blob: 29d747d0932bbf19459e64c0d02e23b2dbf26f75 [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
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700181 addresses = self.vapi.nat44_address_dump()
182 for addr in addresses:
Matus Fabiana6110b62018-06-13 05:39:07 -0700183 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)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700244 :param twice_nat: twice NAT address for external hosts
Matus Fabiana6110b62018-06-13 05:39:07 -0700245 """
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)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700484 :param same_port: Source 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
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700537 :param same_port: Source 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
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700689 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700690 """
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
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700751 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700752 """
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
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001529 cls.pg4._local_ip4 = "172.16.255.1"
1530 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001531 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1532 cls.pg4.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001533 cls.pg5._local_ip4 = "172.17.255.3"
1534 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)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001537 cls.pg6._local_ip4 = "172.16.255.1"
1538 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001539 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()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001551 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(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001553 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
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001565 @classmethod
1566 def tearDownClass(cls):
1567 super(TestNAT44, cls).tearDownClass()
1568
Matus Fabiande886752016-12-07 03:38:19 -08001569 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001570 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001571 self.nat44_add_address(self.nat_addr)
1572 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1573 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1574 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001575
1576 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08001577 tcpn = self.statistics.get_counter(
1578 '/err/nat44-in2out-slowpath/TCP packets')
1579 udpn = self.statistics.get_counter(
1580 '/err/nat44-in2out-slowpath/UDP packets')
1581 icmpn = self.statistics.get_counter(
1582 '/err/nat44-in2out-slowpath/ICMP packets')
1583 totaln = self.statistics.get_counter(
1584 '/err/nat44-in2out-slowpath/good in2out packets processed')
1585
Matus Fabiande886752016-12-07 03:38:19 -08001586 pkts = self.create_stream_in(self.pg0, self.pg1)
1587 self.pg0.add_stream(pkts)
1588 self.pg_enable_capture(self.pg_interfaces)
1589 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001590 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001591 self.verify_capture_out(capture)
1592
Matus Fabiana5e73762018-12-14 01:55:16 -08001593 err = self.statistics.get_counter(
1594 '/err/nat44-in2out-slowpath/TCP packets')
1595 self.assertEqual(err - tcpn, 1)
1596 err = self.statistics.get_counter(
1597 '/err/nat44-in2out-slowpath/UDP packets')
1598 self.assertEqual(err - udpn, 1)
1599 err = self.statistics.get_counter(
1600 '/err/nat44-in2out-slowpath/ICMP packets')
1601 self.assertEqual(err - icmpn, 1)
1602 err = self.statistics.get_counter(
1603 '/err/nat44-in2out-slowpath/good in2out packets processed')
1604 self.assertEqual(err - totaln, 3)
1605
Matus Fabiande886752016-12-07 03:38:19 -08001606 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08001607 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1608 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1609 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1610 totaln = self.statistics.get_counter(
1611 '/err/nat44-out2in/good out2in packets processed')
1612
Matus Fabiande886752016-12-07 03:38:19 -08001613 pkts = self.create_stream_out(self.pg1)
1614 self.pg1.add_stream(pkts)
1615 self.pg_enable_capture(self.pg_interfaces)
1616 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001617 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001618 self.verify_capture_in(capture, self.pg0)
1619
Matus Fabiana5e73762018-12-14 01:55:16 -08001620 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1621 self.assertEqual(err - tcpn, 1)
1622 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1623 self.assertEqual(err - udpn, 1)
1624 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1625 self.assertEqual(err - icmpn, 1)
1626 err = self.statistics.get_counter(
1627 '/err/nat44-out2in/good out2in packets processed')
1628 self.assertEqual(err - totaln, 3)
1629
Matus Fabianfd0d5082018-12-18 01:08:51 -08001630 users = self.statistics.get_counter('/nat44/total-users')
1631 self.assertEqual(users[0][0], 1)
1632 sessions = self.statistics.get_counter('/nat44/total-sessions')
1633 self.assertEqual(sessions[0][0], 3)
1634
Juraj Slobodab33f4132017-02-08 23:54:21 -08001635 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001636 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001637
Matus Fabian2ba92e32017-08-21 07:05:03 -07001638 self.nat44_add_address(self.nat_addr)
1639 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1640 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1641 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001642
1643 # Client side - generate traffic
1644 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1645 self.pg0.add_stream(pkts)
1646 self.pg_enable_capture(self.pg_interfaces)
1647 self.pg_start()
1648
1649 # Client side - verify ICMP type 11 packets
1650 capture = self.pg0.get_capture(len(pkts))
1651 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1652
1653 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001654 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001655
Matus Fabian2ba92e32017-08-21 07:05:03 -07001656 self.nat44_add_address(self.nat_addr)
1657 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1658 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1659 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001660
1661 # Client side - create sessions
1662 pkts = self.create_stream_in(self.pg0, self.pg1)
1663 self.pg0.add_stream(pkts)
1664 self.pg_enable_capture(self.pg_interfaces)
1665 self.pg_start()
1666
1667 # Server side - generate traffic
1668 capture = self.pg1.get_capture(len(pkts))
1669 self.verify_capture_out(capture)
1670 pkts = self.create_stream_out(self.pg1, ttl=1)
1671 self.pg1.add_stream(pkts)
1672 self.pg_enable_capture(self.pg_interfaces)
1673 self.pg_start()
1674
1675 # Server side - verify ICMP type 11 packets
1676 capture = self.pg1.get_capture(len(pkts))
1677 self.verify_capture_out_with_icmp_errors(capture,
1678 src_ip=self.pg1.local_ip4)
1679
1680 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001681 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001682
Matus Fabian2ba92e32017-08-21 07:05:03 -07001683 self.nat44_add_address(self.nat_addr)
1684 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1685 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1686 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001687
1688 # Client side - generate traffic
1689 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1690 self.pg0.add_stream(pkts)
1691 self.pg_enable_capture(self.pg_interfaces)
1692 self.pg_start()
1693
1694 # Server side - simulate ICMP type 11 response
1695 capture = self.pg1.get_capture(len(pkts))
1696 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001697 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001698 ICMP(type=11) / packet[IP] for packet in capture]
1699 self.pg1.add_stream(pkts)
1700 self.pg_enable_capture(self.pg_interfaces)
1701 self.pg_start()
1702
1703 # Client side - verify ICMP type 11 packets
1704 capture = self.pg0.get_capture(len(pkts))
1705 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1706
1707 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001708 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001709
Matus Fabian2ba92e32017-08-21 07:05:03 -07001710 self.nat44_add_address(self.nat_addr)
1711 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1712 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1713 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001714
1715 # Client side - create sessions
1716 pkts = self.create_stream_in(self.pg0, self.pg1)
1717 self.pg0.add_stream(pkts)
1718 self.pg_enable_capture(self.pg_interfaces)
1719 self.pg_start()
1720
1721 # Server side - generate traffic
1722 capture = self.pg1.get_capture(len(pkts))
1723 self.verify_capture_out(capture)
1724 pkts = self.create_stream_out(self.pg1, ttl=2)
1725 self.pg1.add_stream(pkts)
1726 self.pg_enable_capture(self.pg_interfaces)
1727 self.pg_start()
1728
1729 # Client side - simulate ICMP type 11 response
1730 capture = self.pg0.get_capture(len(pkts))
1731 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1732 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1733 ICMP(type=11) / packet[IP] for packet in capture]
1734 self.pg0.add_stream(pkts)
1735 self.pg_enable_capture(self.pg_interfaces)
1736 self.pg_start()
1737
1738 # Server side - verify ICMP type 11 packets
1739 capture = self.pg1.get_capture(len(pkts))
1740 self.verify_capture_out_with_icmp_errors(capture)
1741
Juraj Sloboda665e4822017-02-16 17:17:19 -08001742 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001743 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001744
Matus Fabian2ba92e32017-08-21 07:05:03 -07001745 self.nat44_add_address(self.nat_addr)
1746 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1747 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1748 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001749
1750 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1751 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1752 ICMP(id=self.icmp_id_out, type='echo-request'))
1753 pkts = [p]
1754 self.pg1.add_stream(pkts)
1755 self.pg_enable_capture(self.pg_interfaces)
1756 self.pg_start()
1757 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001758 packet = capture[0]
1759 try:
1760 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1761 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1762 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1763 self.assertEqual(packet[ICMP].type, 0) # echo reply
1764 except:
1765 self.logger.error(ppp("Unexpected or invalid packet "
1766 "(outside network):", packet))
1767 raise
1768
Juraj Slobodad3677682017-04-14 03:24:45 +02001769 def test_ping_internal_host_from_outside(self):
1770 """ Ping internal host from outside network """
1771
Matus Fabian2ba92e32017-08-21 07:05:03 -07001772 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1773 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1774 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1775 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001776
1777 # out2in
1778 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001779 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001780 ICMP(id=self.icmp_id_out, type='echo-request'))
1781 self.pg1.add_stream(pkt)
1782 self.pg_enable_capture(self.pg_interfaces)
1783 self.pg_start()
1784 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001785 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001786 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1787
1788 # in2out
1789 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1790 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1791 ICMP(id=self.icmp_id_in, type='echo-reply'))
1792 self.pg0.add_stream(pkt)
1793 self.pg_enable_capture(self.pg_interfaces)
1794 self.pg_start()
1795 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001796 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001797 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1798
Matus Fabianc79396e2018-07-23 00:05:22 -07001799 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001800 """ NAT44 forwarding test """
1801
1802 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1803 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1804 is_inside=0)
1805 self.vapi.nat44_forwarding_enable_disable(1)
1806
1807 real_ip = self.pg0.remote_ip4n
1808 alias_ip = self.nat_addr_n
1809 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1810 external_ip=alias_ip)
1811
1812 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001813 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001814
1815 pkts = self.create_stream_out(self.pg1)
1816 self.pg1.add_stream(pkts)
1817 self.pg_enable_capture(self.pg_interfaces)
1818 self.pg_start()
1819 capture = self.pg0.get_capture(len(pkts))
1820 self.verify_capture_in(capture, self.pg0)
1821
1822 pkts = self.create_stream_in(self.pg0, self.pg1)
1823 self.pg0.add_stream(pkts)
1824 self.pg_enable_capture(self.pg_interfaces)
1825 self.pg_start()
1826 capture = self.pg1.get_capture(len(pkts))
1827 self.verify_capture_out(capture, same_port=True)
1828
Matus Fabianc79396e2018-07-23 00:05:22 -07001829 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001830
1831 host0 = self.pg0.remote_hosts[0]
1832 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1833 try:
1834 pkts = self.create_stream_out(self.pg1,
1835 dst_ip=self.pg0.remote_ip4,
1836 use_inside_ports=True)
1837 self.pg1.add_stream(pkts)
1838 self.pg_enable_capture(self.pg_interfaces)
1839 self.pg_start()
1840 capture = self.pg0.get_capture(len(pkts))
1841 self.verify_capture_in(capture, self.pg0)
1842
1843 pkts = self.create_stream_in(self.pg0, self.pg1)
1844 self.pg0.add_stream(pkts)
1845 self.pg_enable_capture(self.pg_interfaces)
1846 self.pg_start()
1847 capture = self.pg1.get_capture(len(pkts))
1848 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1849 same_port=True)
1850 finally:
1851 self.pg0.remote_hosts[0] = host0
1852
1853 finally:
1854 self.vapi.nat44_forwarding_enable_disable(0)
1855 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1856 external_ip=alias_ip,
1857 is_add=0)
1858
Matus Fabiande886752016-12-07 03:38:19 -08001859 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001860 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001861
1862 nat_ip = "10.0.0.10"
1863 self.tcp_port_out = 6303
1864 self.udp_port_out = 6304
1865 self.icmp_id_out = 6305
1866
Matus Fabian2ba92e32017-08-21 07:05:03 -07001867 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1868 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1869 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1870 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001871 sm = self.vapi.nat44_static_mapping_dump()
1872 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001873 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
Matus Fabian9dba7812018-01-31 01:13:23 -08001874 self.assertEqual(sm[0].protocol, 0)
1875 self.assertEqual(sm[0].local_port, 0)
1876 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001877
1878 # in2out
1879 pkts = self.create_stream_in(self.pg0, self.pg1)
1880 self.pg0.add_stream(pkts)
1881 self.pg_enable_capture(self.pg_interfaces)
1882 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001883 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001884 self.verify_capture_out(capture, nat_ip, True)
1885
1886 # out2in
1887 pkts = self.create_stream_out(self.pg1, nat_ip)
1888 self.pg1.add_stream(pkts)
1889 self.pg_enable_capture(self.pg_interfaces)
1890 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001891 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001892 self.verify_capture_in(capture, self.pg0)
1893
1894 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001895 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001896
1897 nat_ip = "10.0.0.20"
1898 self.tcp_port_out = 6303
1899 self.udp_port_out = 6304
1900 self.icmp_id_out = 6305
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001901 tag = b"testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001902
Matus Fabian5f224992018-01-25 21:59:16 -08001903 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001904 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1905 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1906 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001907 sm = self.vapi.nat44_static_mapping_dump()
1908 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001909 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001910
1911 # out2in
1912 pkts = self.create_stream_out(self.pg1, nat_ip)
1913 self.pg1.add_stream(pkts)
1914 self.pg_enable_capture(self.pg_interfaces)
1915 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001916 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001917 self.verify_capture_in(capture, self.pg0)
1918
1919 # in2out
1920 pkts = self.create_stream_in(self.pg0, self.pg1)
1921 self.pg0.add_stream(pkts)
1922 self.pg_enable_capture(self.pg_interfaces)
1923 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001924 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001925 self.verify_capture_out(capture, nat_ip, True)
1926
1927 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001928 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001929
1930 self.tcp_port_out = 3606
1931 self.udp_port_out = 3607
1932 self.icmp_id_out = 3608
1933
Matus Fabian2ba92e32017-08-21 07:05:03 -07001934 self.nat44_add_address(self.nat_addr)
1935 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1936 self.tcp_port_in, self.tcp_port_out,
1937 proto=IP_PROTOS.tcp)
1938 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1939 self.udp_port_in, self.udp_port_out,
1940 proto=IP_PROTOS.udp)
1941 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1942 self.icmp_id_in, self.icmp_id_out,
1943 proto=IP_PROTOS.icmp)
1944 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1945 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1946 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001947
1948 # in2out
1949 pkts = self.create_stream_in(self.pg0, self.pg1)
1950 self.pg0.add_stream(pkts)
1951 self.pg_enable_capture(self.pg_interfaces)
1952 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001953 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001954 self.verify_capture_out(capture)
1955
1956 # out2in
1957 pkts = self.create_stream_out(self.pg1)
1958 self.pg1.add_stream(pkts)
1959 self.pg_enable_capture(self.pg_interfaces)
1960 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001961 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001962 self.verify_capture_in(capture, self.pg0)
1963
1964 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001965 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001966
1967 self.tcp_port_out = 30606
1968 self.udp_port_out = 30607
1969 self.icmp_id_out = 30608
1970
Matus Fabian2ba92e32017-08-21 07:05:03 -07001971 self.nat44_add_address(self.nat_addr)
1972 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1973 self.tcp_port_in, self.tcp_port_out,
1974 proto=IP_PROTOS.tcp)
1975 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1976 self.udp_port_in, self.udp_port_out,
1977 proto=IP_PROTOS.udp)
1978 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1979 self.icmp_id_in, self.icmp_id_out,
1980 proto=IP_PROTOS.icmp)
1981 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1982 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1983 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001984
1985 # out2in
1986 pkts = self.create_stream_out(self.pg1)
1987 self.pg1.add_stream(pkts)
1988 self.pg_enable_capture(self.pg_interfaces)
1989 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001990 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001991 self.verify_capture_in(capture, self.pg0)
1992
1993 # in2out
1994 pkts = self.create_stream_in(self.pg0, self.pg1)
1995 self.pg0.add_stream(pkts)
1996 self.pg_enable_capture(self.pg_interfaces)
1997 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001998 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001999 self.verify_capture_out(capture)
2000
2001 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002002 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08002003
2004 nat_ip1 = "10.0.0.30"
2005 nat_ip2 = "10.0.0.40"
2006 self.tcp_port_out = 6303
2007 self.udp_port_out = 6304
2008 self.icmp_id_out = 6305
2009
Matus Fabian2ba92e32017-08-21 07:05:03 -07002010 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2011 vrf_id=10)
2012 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2013 vrf_id=10)
2014 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2015 is_inside=0)
2016 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2017 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08002018
Matus Fabian2ba92e32017-08-21 07:05:03 -07002019 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002020 pkts = self.create_stream_in(self.pg4, self.pg3)
2021 self.pg4.add_stream(pkts)
2022 self.pg_enable_capture(self.pg_interfaces)
2023 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002024 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002025 self.verify_capture_out(capture, nat_ip1, True)
2026
Matus Fabian2ba92e32017-08-21 07:05:03 -07002027 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002028 # are dropped)
2029 pkts = self.create_stream_in(self.pg0, self.pg3)
2030 self.pg0.add_stream(pkts)
2031 self.pg_enable_capture(self.pg_interfaces)
2032 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002033 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002034
Matus Fabianb793d092018-01-31 05:50:21 -08002035 def test_dynamic_to_static(self):
2036 """ Switch from dynamic translation to 1:1NAT """
2037 nat_ip = "10.0.0.10"
2038 self.tcp_port_out = 6303
2039 self.udp_port_out = 6304
2040 self.icmp_id_out = 6305
2041
2042 self.nat44_add_address(self.nat_addr)
2043 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2044 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2045 is_inside=0)
2046
2047 # dynamic
2048 pkts = self.create_stream_in(self.pg0, self.pg1)
2049 self.pg0.add_stream(pkts)
2050 self.pg_enable_capture(self.pg_interfaces)
2051 self.pg_start()
2052 capture = self.pg1.get_capture(len(pkts))
2053 self.verify_capture_out(capture)
2054
2055 # 1:1NAT
2056 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2057 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2058 self.assertEqual(len(sessions), 0)
2059 pkts = self.create_stream_in(self.pg0, self.pg1)
2060 self.pg0.add_stream(pkts)
2061 self.pg_enable_capture(self.pg_interfaces)
2062 self.pg_start()
2063 capture = self.pg1.get_capture(len(pkts))
2064 self.verify_capture_out(capture, nat_ip, True)
2065
Matus Fabianab7a8052017-11-28 04:29:41 -08002066 def test_identity_nat(self):
2067 """ Identity NAT """
2068
2069 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
2070 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2071 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2072 is_inside=0)
2073
2074 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2075 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2076 TCP(sport=12345, dport=56789))
2077 self.pg1.add_stream(p)
2078 self.pg_enable_capture(self.pg_interfaces)
2079 self.pg_start()
2080 capture = self.pg0.get_capture(1)
2081 p = capture[0]
2082 try:
2083 ip = p[IP]
2084 tcp = p[TCP]
2085 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2086 self.assertEqual(ip.src, self.pg1.remote_ip4)
2087 self.assertEqual(tcp.dport, 56789)
2088 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002089 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002090 except:
2091 self.logger.error(ppp("Unexpected or invalid packet:", p))
2092 raise
2093
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002094 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2095 self.assertEqual(len(sessions), 0)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002096 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2097 vrf_id=1)
2098 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2099 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002100
Matus Fabiande886752016-12-07 03:38:19 -08002101 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002102 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002103
Matus Fabian2ba92e32017-08-21 07:05:03 -07002104 self.nat44_add_address(self.nat_addr)
2105 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2106 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2107 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2108 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002109
Matus Fabian2ba92e32017-08-21 07:05:03 -07002110 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002111 pkts = self.create_stream_in(self.pg0, self.pg1)
2112 self.pg0.add_stream(pkts)
2113 self.pg_enable_capture(self.pg_interfaces)
2114 self.pg_start()
2115 capture = self.pg1.get_capture(len(pkts))
2116 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2117
Matus Fabian2ba92e32017-08-21 07:05:03 -07002118 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002119 pkts = self.create_stream_in(self.pg0, self.pg2)
2120 self.pg0.add_stream(pkts)
2121 self.pg_enable_capture(self.pg_interfaces)
2122 self.pg_start()
2123 capture = self.pg2.get_capture(len(pkts))
2124 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2125
Matus Fabiande886752016-12-07 03:38:19 -08002126 # in2out 1st interface
2127 pkts = self.create_stream_in(self.pg0, self.pg3)
2128 self.pg0.add_stream(pkts)
2129 self.pg_enable_capture(self.pg_interfaces)
2130 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002131 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002132 self.verify_capture_out(capture)
2133
2134 # out2in 1st interface
2135 pkts = self.create_stream_out(self.pg3)
2136 self.pg3.add_stream(pkts)
2137 self.pg_enable_capture(self.pg_interfaces)
2138 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002139 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002140 self.verify_capture_in(capture, self.pg0)
2141
2142 # in2out 2nd interface
2143 pkts = self.create_stream_in(self.pg1, self.pg3)
2144 self.pg1.add_stream(pkts)
2145 self.pg_enable_capture(self.pg_interfaces)
2146 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002147 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002148 self.verify_capture_out(capture)
2149
2150 # out2in 2nd interface
2151 pkts = self.create_stream_out(self.pg3)
2152 self.pg3.add_stream(pkts)
2153 self.pg_enable_capture(self.pg_interfaces)
2154 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002155 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002156 self.verify_capture_in(capture, self.pg1)
2157
Matus Fabiande886752016-12-07 03:38:19 -08002158 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002159 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002160
Matus Fabian675a69c2017-01-18 01:46:01 -08002161 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002162 self.nat44_add_address(self.nat_addr)
2163 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2164 is_inside=0)
2165 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2166 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2167 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2168 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2169 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002170
Matus Fabian2ba92e32017-08-21 07:05:03 -07002171 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002172 pkts = self.create_stream_in(self.pg4, self.pg5)
2173 self.pg4.add_stream(pkts)
2174 self.pg_enable_capture(self.pg_interfaces)
2175 self.pg_start()
2176 capture = self.pg5.get_capture(len(pkts))
2177 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2178
Matus Fabian2ba92e32017-08-21 07:05:03 -07002179 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002180 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2181 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2182 TCP(sport=1234, dport=5678))
2183 self.pg4.add_stream(p)
2184 self.pg_enable_capture(self.pg_interfaces)
2185 self.pg_start()
2186 capture = self.pg6.get_capture(1)
2187 p = capture[0]
2188 try:
2189 ip = p[IP]
2190 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002191 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002192 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2193 self.assertNotEqual(tcp.sport, 1234)
2194 self.assertEqual(tcp.dport, 5678)
2195 except:
2196 self.logger.error(ppp("Unexpected or invalid packet:", p))
2197 raise
Matus Fabiande886752016-12-07 03:38:19 -08002198
2199 # in2out 1st interface
2200 pkts = self.create_stream_in(self.pg4, self.pg3)
2201 self.pg4.add_stream(pkts)
2202 self.pg_enable_capture(self.pg_interfaces)
2203 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002204 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002205 self.verify_capture_out(capture)
2206
2207 # out2in 1st interface
2208 pkts = self.create_stream_out(self.pg3)
2209 self.pg3.add_stream(pkts)
2210 self.pg_enable_capture(self.pg_interfaces)
2211 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002212 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002213 self.verify_capture_in(capture, self.pg4)
2214
2215 # in2out 2nd interface
2216 pkts = self.create_stream_in(self.pg5, self.pg3)
2217 self.pg5.add_stream(pkts)
2218 self.pg_enable_capture(self.pg_interfaces)
2219 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002220 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002221 self.verify_capture_out(capture)
2222
2223 # out2in 2nd interface
2224 pkts = self.create_stream_out(self.pg3)
2225 self.pg3.add_stream(pkts)
2226 self.pg_enable_capture(self.pg_interfaces)
2227 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002228 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002229 self.verify_capture_in(capture, self.pg5)
2230
magalik23caa882017-02-08 23:25:45 -08002231 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002232 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002233 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002234 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002235 self.assertEqual(len(sessions), 3)
2236 for session in sessions:
2237 self.assertFalse(session.is_static)
2238 self.assertEqual(session.inside_ip_address[0:4],
2239 self.pg5.remote_ip4n)
2240 self.assertEqual(session.outside_ip_address,
2241 addresses[0].ip_address)
2242 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2243 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2244 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2245 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2246 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2247 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2248 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2249 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2250 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2251
Matus Fabiande886752016-12-07 03:38:19 -08002252 # in2out 3rd interface
2253 pkts = self.create_stream_in(self.pg6, self.pg3)
2254 self.pg6.add_stream(pkts)
2255 self.pg_enable_capture(self.pg_interfaces)
2256 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002257 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002258 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002259
2260 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002261 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002262 self.pg3.add_stream(pkts)
2263 self.pg_enable_capture(self.pg_interfaces)
2264 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002265 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002266 self.verify_capture_in(capture, self.pg6)
2267
magalik23caa882017-02-08 23:25:45 -08002268 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002269 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002270 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002271 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002272 self.assertEqual(len(addresses), 1)
2273 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002274 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2275 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002276 for session in sessions:
2277 self.assertEqual(user.ip_address, session.inside_ip_address)
2278 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2279 self.assertTrue(session.protocol in
2280 [IP_PROTOS.tcp, IP_PROTOS.udp,
2281 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002282 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002283
2284 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002285 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002286 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002287 for session in sessions:
2288 self.assertFalse(session.is_static)
2289 self.assertEqual(session.inside_ip_address[0:4],
2290 self.pg4.remote_ip4n)
2291 self.assertEqual(session.outside_ip_address,
2292 addresses[0].ip_address)
2293
2294 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002295 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002296 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002297 for session in sessions:
2298 self.assertTrue(session.is_static)
2299 self.assertEqual(session.inside_ip_address[0:4],
2300 self.pg6.remote_ip4n)
Matus Fabian34931eb2019-02-26 09:05:23 -08002301 self.assertEqual(session.outside_ip_address,
2302 socket.inet_pton(socket.AF_INET, static_nat_ip))
magalik23caa882017-02-08 23:25:45 -08002303 self.assertTrue(session.inside_port in
2304 [self.tcp_port_in, self.udp_port_in,
2305 self.icmp_id_in])
2306
Matus Fabianf78a70d2016-12-12 04:30:39 -08002307 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002308 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002309
2310 host = self.pg0.remote_hosts[0]
2311 server = self.pg0.remote_hosts[1]
2312 host_in_port = 1234
2313 host_out_port = 0
2314 server_in_port = 5678
2315 server_out_port = 8765
2316
Matus Fabian2ba92e32017-08-21 07:05:03 -07002317 self.nat44_add_address(self.nat_addr)
2318 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2319 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2320 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002321 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002322 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2323 server_in_port, server_out_port,
2324 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002325
2326 # send packet from host to server
2327 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002328 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002329 TCP(sport=host_in_port, dport=server_out_port))
2330 self.pg0.add_stream(p)
2331 self.pg_enable_capture(self.pg_interfaces)
2332 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002333 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002334 p = capture[0]
2335 try:
2336 ip = p[IP]
2337 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002338 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002339 self.assertEqual(ip.dst, server.ip4)
2340 self.assertNotEqual(tcp.sport, host_in_port)
2341 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002342 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002343 host_out_port = tcp.sport
2344 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002345 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002346 raise
2347
2348 # send reply from server to host
2349 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002350 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002351 TCP(sport=server_in_port, dport=host_out_port))
2352 self.pg0.add_stream(p)
2353 self.pg_enable_capture(self.pg_interfaces)
2354 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002355 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002356 p = capture[0]
2357 try:
2358 ip = p[IP]
2359 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002360 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002361 self.assertEqual(ip.dst, host.ip4)
2362 self.assertEqual(tcp.sport, server_out_port)
2363 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002364 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002365 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002366 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002367 raise
2368
Matus Fabian6fa74c62017-06-05 05:55:48 -07002369 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002370 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002371
2372 server1_nat_ip = "10.0.0.10"
2373 server2_nat_ip = "10.0.0.11"
2374 host = self.pg0.remote_hosts[0]
2375 server1 = self.pg0.remote_hosts[1]
2376 server2 = self.pg0.remote_hosts[2]
2377 server_tcp_port = 22
2378 server_udp_port = 20
2379
Matus Fabian2ba92e32017-08-21 07:05:03 -07002380 self.nat44_add_address(self.nat_addr)
2381 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2382 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2383 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002384
2385 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002386 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2387 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002388
2389 # host to server1
2390 pkts = []
2391 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2392 IP(src=host.ip4, dst=server1_nat_ip) /
2393 TCP(sport=self.tcp_port_in, dport=server_tcp_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 UDP(sport=self.udp_port_in, dport=server_udp_port))
2398 pkts.append(p)
2399 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2400 IP(src=host.ip4, dst=server1_nat_ip) /
2401 ICMP(id=self.icmp_id_in, type='echo-request'))
2402 pkts.append(p)
2403 self.pg0.add_stream(pkts)
2404 self.pg_enable_capture(self.pg_interfaces)
2405 self.pg_start()
2406 capture = self.pg0.get_capture(len(pkts))
2407 for packet in capture:
2408 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002409 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002410 self.assertEqual(packet[IP].dst, server1.ip4)
2411 if packet.haslayer(TCP):
2412 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2413 self.assertEqual(packet[TCP].dport, server_tcp_port)
2414 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002415 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002416 elif packet.haslayer(UDP):
2417 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2418 self.assertEqual(packet[UDP].dport, server_udp_port)
2419 self.udp_port_out = packet[UDP].sport
2420 else:
2421 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2422 self.icmp_id_out = packet[ICMP].id
2423 except:
2424 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2425 raise
2426
2427 # server1 to host
2428 pkts = []
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 TCP(sport=server_tcp_port, dport=self.tcp_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 UDP(sport=server_udp_port, dport=self.udp_port_out))
2436 pkts.append(p)
2437 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002438 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002439 ICMP(id=self.icmp_id_out, type='echo-reply'))
2440 pkts.append(p)
2441 self.pg0.add_stream(pkts)
2442 self.pg_enable_capture(self.pg_interfaces)
2443 self.pg_start()
2444 capture = self.pg0.get_capture(len(pkts))
2445 for packet in capture:
2446 try:
2447 self.assertEqual(packet[IP].src, server1_nat_ip)
2448 self.assertEqual(packet[IP].dst, host.ip4)
2449 if packet.haslayer(TCP):
2450 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2451 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002452 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002453 elif packet.haslayer(UDP):
2454 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2455 self.assertEqual(packet[UDP].sport, server_udp_port)
2456 else:
2457 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2458 except:
2459 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2460 raise
2461
2462 # server2 to server1
2463 pkts = []
2464 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2465 IP(src=server2.ip4, dst=server1_nat_ip) /
2466 TCP(sport=self.tcp_port_in, dport=server_tcp_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 UDP(sport=self.udp_port_in, dport=server_udp_port))
2471 pkts.append(p)
2472 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2473 IP(src=server2.ip4, dst=server1_nat_ip) /
2474 ICMP(id=self.icmp_id_in, type='echo-request'))
2475 pkts.append(p)
2476 self.pg0.add_stream(pkts)
2477 self.pg_enable_capture(self.pg_interfaces)
2478 self.pg_start()
2479 capture = self.pg0.get_capture(len(pkts))
2480 for packet in capture:
2481 try:
2482 self.assertEqual(packet[IP].src, server2_nat_ip)
2483 self.assertEqual(packet[IP].dst, server1.ip4)
2484 if packet.haslayer(TCP):
2485 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2486 self.assertEqual(packet[TCP].dport, server_tcp_port)
2487 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002488 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002489 elif packet.haslayer(UDP):
2490 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2491 self.assertEqual(packet[UDP].dport, server_udp_port)
2492 self.udp_port_out = packet[UDP].sport
2493 else:
2494 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2495 self.icmp_id_out = packet[ICMP].id
2496 except:
2497 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2498 raise
2499
2500 # server1 to server2
2501 pkts = []
2502 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2503 IP(src=server1.ip4, dst=server2_nat_ip) /
2504 TCP(sport=server_tcp_port, dport=self.tcp_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 UDP(sport=server_udp_port, dport=self.udp_port_out))
2509 pkts.append(p)
2510 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2511 IP(src=server1.ip4, dst=server2_nat_ip) /
2512 ICMP(id=self.icmp_id_out, type='echo-reply'))
2513 pkts.append(p)
2514 self.pg0.add_stream(pkts)
2515 self.pg_enable_capture(self.pg_interfaces)
2516 self.pg_start()
2517 capture = self.pg0.get_capture(len(pkts))
2518 for packet in capture:
2519 try:
2520 self.assertEqual(packet[IP].src, server1_nat_ip)
2521 self.assertEqual(packet[IP].dst, server2.ip4)
2522 if packet.haslayer(TCP):
2523 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2524 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002525 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002526 elif packet.haslayer(UDP):
2527 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2528 self.assertEqual(packet[UDP].sport, server_udp_port)
2529 else:
2530 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2531 except:
2532 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2533 raise
2534
Matus Fabian9902fcd2016-12-21 23:58:46 -08002535 def test_max_translations_per_user(self):
2536 """ MAX translations per user - recycle the least recently used """
2537
Matus Fabian2ba92e32017-08-21 07:05:03 -07002538 self.nat44_add_address(self.nat_addr)
2539 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2540 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2541 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002542
2543 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002544 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002545
2546 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002547 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002548 pkts = []
2549 for port in range(0, pkts_num):
2550 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2551 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2552 TCP(sport=1025 + port))
2553 pkts.append(p)
2554 self.pg0.add_stream(pkts)
2555 self.pg_enable_capture(self.pg_interfaces)
2556 self.pg_start()
2557
2558 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002559 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002560
Matus Fabian132dc492018-05-09 04:51:03 -07002561 users = self.vapi.nat44_user_dump()
2562 for user in users:
2563 if user.ip_address == self.pg0.remote_ip4n:
2564 self.assertEqual(user.nsessions,
2565 nat44_config.max_translations_per_user)
2566 self.assertEqual(user.nstaticsessions, 0)
2567
2568 tcp_port = 22
2569 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2570 tcp_port, tcp_port,
2571 proto=IP_PROTOS.tcp)
2572 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2573 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2574 TCP(sport=tcp_port))
2575 self.pg0.add_stream(p)
2576 self.pg_enable_capture(self.pg_interfaces)
2577 self.pg_start()
2578 self.pg1.get_capture(1)
2579 users = self.vapi.nat44_user_dump()
2580 for user in users:
2581 if user.ip_address == self.pg0.remote_ip4n:
2582 self.assertEqual(user.nsessions,
2583 nat44_config.max_translations_per_user - 1)
2584 self.assertEqual(user.nstaticsessions, 1)
2585
Matus Fabian8bf68e82017-01-12 04:24:35 -08002586 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002587 """ Acquire NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01002588 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002589
2590 # no address in NAT pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002591 addresses = self.vapi.nat44_address_dump()
2592 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002593
2594 # configure interface address and check NAT address pool
2595 self.pg7.config_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002596 addresses = self.vapi.nat44_address_dump()
2597 self.assertEqual(1, len(addresses))
2598 self.assertEqual(addresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002599
2600 # remove interface address and check NAT address pool
2601 self.pg7.unconfig_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002602 addresses = self.vapi.nat44_address_dump()
2603 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002604
Matus Fabian36532bd2017-01-23 23:42:28 -08002605 def test_interface_addr_static_mapping(self):
2606 """ Static mapping with addresses from interface """
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002607 tag = b"testTAG"
Matus Fabian5f224992018-01-25 21:59:16 -08002608
Ole Troane1ade682019-03-04 23:55:43 +01002609 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002610 self.nat44_add_static_mapping(
2611 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002612 external_sw_if_index=self.pg7.sw_if_index,
2613 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002614
Matus Fabiane22e5462017-02-14 23:33:43 -08002615 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002616 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002617 self.assertEqual(1, len(static_mappings))
2618 self.assertEqual(self.pg7.sw_if_index,
2619 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002620 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002621
2622 # configure interface address and check static mappings
2623 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002624 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002625 self.assertEqual(2, len(static_mappings))
2626 resolved = False
2627 for sm in static_mappings:
2628 if sm.external_sw_if_index == 0xFFFFFFFF:
2629 self.assertEqual(sm.external_ip_address[0:4],
2630 self.pg7.local_ip4n)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002631 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002632 resolved = True
2633 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002634
2635 # remove interface address and check static mappings
2636 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002637 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002638 self.assertEqual(1, len(static_mappings))
2639 self.assertEqual(self.pg7.sw_if_index,
2640 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002641 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002642
2643 # configure interface address again and check static mappings
2644 self.pg7.config_ip4()
2645 static_mappings = self.vapi.nat44_static_mapping_dump()
2646 self.assertEqual(2, len(static_mappings))
2647 resolved = False
2648 for sm in static_mappings:
2649 if sm.external_sw_if_index == 0xFFFFFFFF:
2650 self.assertEqual(sm.external_ip_address[0:4],
2651 self.pg7.local_ip4n)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002652 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002653 resolved = True
2654 self.assertTrue(resolved)
2655
2656 # remove static mapping
2657 self.nat44_add_static_mapping(
2658 '1.2.3.4',
2659 external_sw_if_index=self.pg7.sw_if_index,
2660 tag=tag,
2661 is_add=0)
2662 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002663 self.assertEqual(0, len(static_mappings))
2664
Matus Fabianab7a8052017-11-28 04:29:41 -08002665 def test_interface_addr_identity_nat(self):
2666 """ Identity NAT with addresses from interface """
2667
2668 port = 53053
Ole Troane1ade682019-03-04 23:55:43 +01002669 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002670 self.vapi.nat44_add_del_identity_mapping(
2671 sw_if_index=self.pg7.sw_if_index,
2672 port=port,
2673 protocol=IP_PROTOS.tcp,
2674 addr_only=0)
2675
2676 # identity mappings with external interface
2677 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2678 self.assertEqual(1, len(identity_mappings))
2679 self.assertEqual(self.pg7.sw_if_index,
2680 identity_mappings[0].sw_if_index)
2681
2682 # configure interface address and check identity mappings
2683 self.pg7.config_ip4()
2684 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002685 resolved = False
2686 self.assertEqual(2, len(identity_mappings))
2687 for sm in identity_mappings:
2688 if sm.sw_if_index == 0xFFFFFFFF:
2689 self.assertEqual(identity_mappings[0].ip_address,
2690 self.pg7.local_ip4n)
2691 self.assertEqual(port, identity_mappings[0].port)
2692 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2693 resolved = True
2694 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002695
2696 # remove interface address and check identity mappings
2697 self.pg7.unconfig_ip4()
2698 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002699 self.assertEqual(1, len(identity_mappings))
2700 self.assertEqual(self.pg7.sw_if_index,
2701 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002702
Matus Fabianeea28d72017-01-13 04:15:54 -08002703 def test_ipfix_nat44_sess(self):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002704 """ IPFIX logging NAT44 session created/deleted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002705 self.ipfix_domain_id = 10
2706 self.ipfix_src_port = 20202
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002707 collector_port = 30303
Matus Fabian6631e9c2017-05-24 01:52:20 -07002708 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002709 self.nat44_add_address(self.nat_addr)
2710 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2711 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2712 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002713 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2714 src_address=self.pg3.local_ip4n,
2715 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002716 template_interval=10,
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002717 collector_port=collector_port)
Ole Troane1ade682019-03-04 23:55:43 +01002718 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2719 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002720
2721 pkts = self.create_stream_in(self.pg0, self.pg1)
2722 self.pg0.add_stream(pkts)
2723 self.pg_enable_capture(self.pg_interfaces)
2724 self.pg_start()
2725 capture = self.pg1.get_capture(len(pkts))
2726 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002727 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002728 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002729 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002730 ipfix = IPFIXDecoder()
2731 # first load template
2732 for p in capture:
2733 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002734 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2735 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2736 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002737 self.assertEqual(p[UDP].dport, collector_port)
Matus Fabian6631e9c2017-05-24 01:52:20 -07002738 self.assertEqual(p[IPFIX].observationDomainID,
2739 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002740 if p.haslayer(Template):
2741 ipfix.add_template(p.getlayer(Template))
2742 # verify events in data set
2743 for p in capture:
2744 if p.haslayer(Data):
2745 data = ipfix.decode_data_set(p.getlayer(Set))
2746 self.verify_ipfix_nat44_ses(data)
2747
2748 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002749 """ IPFIX logging NAT addresses exhausted """
2750 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2751 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2752 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002753 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2754 src_address=self.pg3.local_ip4n,
2755 path_mtu=512,
2756 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002757 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2758 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002759
2760 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2761 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2762 TCP(sport=3025))
2763 self.pg0.add_stream(p)
2764 self.pg_enable_capture(self.pg_interfaces)
2765 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002766 self.pg1.assert_nothing_captured()
2767 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002768 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002769 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002770 ipfix = IPFIXDecoder()
2771 # first load template
2772 for p in capture:
2773 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002774 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2775 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2776 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2777 self.assertEqual(p[UDP].dport, 4739)
2778 self.assertEqual(p[IPFIX].observationDomainID,
2779 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002780 if p.haslayer(Template):
2781 ipfix.add_template(p.getlayer(Template))
2782 # verify events in data set
2783 for p in capture:
2784 if p.haslayer(Data):
2785 data = ipfix.decode_data_set(p.getlayer(Set))
2786 self.verify_ipfix_addr_exhausted(data)
2787
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002788 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002789 def test_ipfix_max_sessions(self):
2790 """ IPFIX logging maximum session entries exceeded """
2791 self.nat44_add_address(self.nat_addr)
2792 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2793 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2794 is_inside=0)
2795
2796 nat44_config = self.vapi.nat_show_config()
2797 max_sessions = 10 * nat44_config.translation_buckets
2798
2799 pkts = []
2800 for i in range(0, max_sessions):
2801 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2802 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2803 IP(src=src, dst=self.pg1.remote_ip4) /
2804 TCP(sport=1025))
2805 pkts.append(p)
2806 self.pg0.add_stream(pkts)
2807 self.pg_enable_capture(self.pg_interfaces)
2808 self.pg_start()
2809
2810 self.pg1.get_capture(max_sessions)
2811 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2812 src_address=self.pg3.local_ip4n,
2813 path_mtu=512,
2814 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002815 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2816 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08002817
2818 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2819 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2820 TCP(sport=1025))
2821 self.pg0.add_stream(p)
2822 self.pg_enable_capture(self.pg_interfaces)
2823 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002824 self.pg1.assert_nothing_captured()
2825 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002826 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2827 capture = self.pg3.get_capture(9)
2828 ipfix = IPFIXDecoder()
2829 # first load template
2830 for p in capture:
2831 self.assertTrue(p.haslayer(IPFIX))
2832 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2833 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2834 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2835 self.assertEqual(p[UDP].dport, 4739)
2836 self.assertEqual(p[IPFIX].observationDomainID,
2837 self.ipfix_domain_id)
2838 if p.haslayer(Template):
2839 ipfix.add_template(p.getlayer(Template))
2840 # verify events in data set
2841 for p in capture:
2842 if p.haslayer(Data):
2843 data = ipfix.decode_data_set(p.getlayer(Set))
2844 self.verify_ipfix_max_sessions(data, max_sessions)
2845
Matus Fabianad1f3e12018-11-28 21:26:34 -08002846 def test_syslog_apmap(self):
2847 """ Test syslog address and port mapping creation and deletion """
2848 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01002849 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002850 self.nat44_add_address(self.nat_addr)
2851 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2852 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2853 is_inside=0)
2854
2855 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2856 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2857 TCP(sport=self.tcp_port_in, dport=20))
2858 self.pg0.add_stream(p)
2859 self.pg_enable_capture(self.pg_interfaces)
2860 self.pg_start()
2861 capture = self.pg1.get_capture(1)
2862 self.tcp_port_out = capture[0][TCP].sport
2863 capture = self.pg3.get_capture(1)
2864 self.verify_syslog_apmap(capture[0][Raw].load)
2865
2866 self.pg_enable_capture(self.pg_interfaces)
2867 self.pg_start()
2868 self.nat44_add_address(self.nat_addr, is_add=0)
2869 capture = self.pg3.get_capture(1)
2870 self.verify_syslog_apmap(capture[0][Raw].load, False)
2871
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002872 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002873 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002874 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002875 self.nat44_add_address(self.nat_addr)
2876 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2877 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2878 is_inside=0)
2879 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002880
Matus Fabian2ba92e32017-08-21 07:05:03 -07002881 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002882 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002883 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002884 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2885 self.pg1.add_stream(p)
2886 self.pg_enable_capture(self.pg_interfaces)
2887 self.pg_start()
2888 capture = self.pg1.get_capture(1)
2889 self.assertTrue(capture[0].haslayer(ARP))
2890 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2891
2892 # 1:1 NAT address
2893 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2894 ARP(op=ARP.who_has, pdst=static_addr,
2895 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2896 self.pg1.add_stream(p)
2897 self.pg_enable_capture(self.pg_interfaces)
2898 self.pg_start()
2899 capture = self.pg1.get_capture(1)
2900 self.assertTrue(capture[0].haslayer(ARP))
2901 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2902
Matus Fabian2ba92e32017-08-21 07:05:03 -07002903 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002904 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002905 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002906 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2907 self.pg2.add_stream(p)
2908 self.pg_enable_capture(self.pg_interfaces)
2909 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002910 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002911
2912 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002913 self.nat44_add_address(self.nat_addr, is_add=0)
2914 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2915 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002916
2917 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002918 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002919 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2920 self.pg1.add_stream(p)
2921 self.pg_enable_capture(self.pg_interfaces)
2922 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002923 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002924
2925 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2926 ARP(op=ARP.who_has, pdst=static_addr,
2927 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2928 self.pg1.add_stream(p)
2929 self.pg_enable_capture(self.pg_interfaces)
2930 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002931 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002932
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002933 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002934 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002935
2936 vrf_id1 = 1
2937 vrf_id2 = 2
2938 nat_ip1 = "10.0.0.10"
2939 nat_ip2 = "10.0.0.11"
2940
2941 self.pg0.unconfig_ip4()
2942 self.pg1.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01002943 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
2944 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002945 self.pg0.set_table_ip4(vrf_id1)
2946 self.pg1.set_table_ip4(vrf_id2)
2947 self.pg0.config_ip4()
2948 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002949 self.pg0.resolve_arp()
2950 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002951
Matus Fabian2ba92e32017-08-21 07:05:03 -07002952 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2953 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2954 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2955 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2956 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2957 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002958
Matus Fabian8008d7c2018-07-09 01:34:20 -07002959 try:
2960 # first VRF
2961 pkts = self.create_stream_in(self.pg0, self.pg2)
2962 self.pg0.add_stream(pkts)
2963 self.pg_enable_capture(self.pg_interfaces)
2964 self.pg_start()
2965 capture = self.pg2.get_capture(len(pkts))
2966 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002967
Matus Fabian8008d7c2018-07-09 01:34:20 -07002968 # second VRF
2969 pkts = self.create_stream_in(self.pg1, self.pg2)
2970 self.pg1.add_stream(pkts)
2971 self.pg_enable_capture(self.pg_interfaces)
2972 self.pg_start()
2973 capture = self.pg2.get_capture(len(pkts))
2974 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002975
Matus Fabian8008d7c2018-07-09 01:34:20 -07002976 finally:
2977 self.pg0.unconfig_ip4()
2978 self.pg1.unconfig_ip4()
2979 self.pg0.set_table_ip4(0)
2980 self.pg1.set_table_ip4(0)
2981 self.pg0.config_ip4()
2982 self.pg1.config_ip4()
2983 self.pg0.resolve_arp()
2984 self.pg1.resolve_arp()
Ole Troan9a475372019-03-05 16:58:24 +01002985 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
2986 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
Neale Ranns15002542017-09-10 04:39:11 -07002987
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002988 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002989 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002990
2991 nat_ip1 = "10.0.0.10"
2992 nat_ip2 = "10.0.0.11"
2993
Matus Fabian2ba92e32017-08-21 07:05:03 -07002994 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002995 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002996 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2997 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2998 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2999 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003000
3001 # first VRF
3002 pkts = self.create_stream_in(self.pg0, self.pg2)
3003 self.pg0.add_stream(pkts)
3004 self.pg_enable_capture(self.pg_interfaces)
3005 self.pg_start()
3006 capture = self.pg2.get_capture(len(pkts))
3007 self.verify_capture_out(capture, nat_ip1)
3008
3009 # second VRF
3010 pkts = self.create_stream_in(self.pg1, self.pg2)
3011 self.pg1.add_stream(pkts)
3012 self.pg_enable_capture(self.pg_interfaces)
3013 self.pg_start()
3014 capture = self.pg2.get_capture(len(pkts))
3015 self.verify_capture_out(capture, nat_ip1)
3016
Martin Gálik406eb1d2017-05-04 04:35:04 -07003017 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003018 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003019
Neale Ranns37029302018-08-10 05:30:06 -07003020 self.vapi.ip_neighbor_add_del(
3021 self.pg7.sw_if_index,
3022 self.pg7.remote_mac,
3023 self.pg7.remote_ip4,
3024 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3025 IP_API_NEIGHBOR_FLAG_STATIC))
3026 self.vapi.ip_neighbor_add_del(
3027 self.pg8.sw_if_index,
3028 self.pg8.remote_mac,
3029 self.pg8.remote_ip4,
3030 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3031 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003032
3033 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3034 dst_address_length=32,
3035 next_hop_address=self.pg7.remote_ip4n,
3036 next_hop_sw_if_index=self.pg7.sw_if_index)
3037 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3038 dst_address_length=32,
3039 next_hop_address=self.pg8.remote_ip4n,
3040 next_hop_sw_if_index=self.pg8.sw_if_index)
3041
Matus Fabian2ba92e32017-08-21 07:05:03 -07003042 self.nat44_add_address(self.nat_addr)
3043 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3044 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3045 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003046
3047 # in2out
3048 pkts = self.create_stream_in(self.pg7, self.pg8)
3049 self.pg7.add_stream(pkts)
3050 self.pg_enable_capture(self.pg_interfaces)
3051 self.pg_start()
3052 capture = self.pg8.get_capture(len(pkts))
3053 self.verify_capture_out(capture)
3054
3055 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003056 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003057 self.pg8.add_stream(pkts)
3058 self.pg_enable_capture(self.pg_interfaces)
3059 self.pg_start()
3060 capture = self.pg7.get_capture(len(pkts))
3061 self.verify_capture_in(capture, self.pg7)
3062
3063 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003064 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003065
Neale Ranns37029302018-08-10 05:30:06 -07003066 self.vapi.ip_neighbor_add_del(
3067 self.pg7.sw_if_index,
3068 self.pg7.remote_mac,
3069 self.pg7.remote_ip4,
3070 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3071 IP_API_NEIGHBOR_FLAG_STATIC))
3072 self.vapi.ip_neighbor_add_del(
3073 self.pg8.sw_if_index,
3074 self.pg8.remote_mac,
3075 self.pg8.remote_ip4,
3076 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3077 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003078
3079 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3080 dst_address_length=32,
3081 next_hop_address=self.pg7.remote_ip4n,
3082 next_hop_sw_if_index=self.pg7.sw_if_index)
3083 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3084 dst_address_length=32,
3085 next_hop_address=self.pg8.remote_ip4n,
3086 next_hop_sw_if_index=self.pg8.sw_if_index)
3087
Matus Fabian2ba92e32017-08-21 07:05:03 -07003088 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3089 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3090 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3091 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003092
3093 # out2in
3094 pkts = self.create_stream_out(self.pg8)
3095 self.pg8.add_stream(pkts)
3096 self.pg_enable_capture(self.pg_interfaces)
3097 self.pg_start()
3098 capture = self.pg7.get_capture(len(pkts))
3099 self.verify_capture_in(capture, self.pg7)
3100
3101 # in2out
3102 pkts = self.create_stream_in(self.pg7, self.pg8)
3103 self.pg7.add_stream(pkts)
3104 self.pg_enable_capture(self.pg_interfaces)
3105 self.pg_start()
3106 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003107 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003108
3109 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003110 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003111
3112 self.tcp_port_out = 30606
3113 self.udp_port_out = 30607
3114 self.icmp_id_out = 30608
3115
Neale Ranns37029302018-08-10 05:30:06 -07003116 self.vapi.ip_neighbor_add_del(
3117 self.pg7.sw_if_index,
3118 self.pg7.remote_mac,
3119 self.pg7.remote_ip4,
3120 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3121 IP_API_NEIGHBOR_FLAG_STATIC))
3122 self.vapi.ip_neighbor_add_del(
3123 self.pg8.sw_if_index,
3124 self.pg8.remote_mac,
3125 self.pg8.remote_ip4,
3126 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3127 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003128
3129 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3130 dst_address_length=32,
3131 next_hop_address=self.pg7.remote_ip4n,
3132 next_hop_sw_if_index=self.pg7.sw_if_index)
3133 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3134 dst_address_length=32,
3135 next_hop_address=self.pg8.remote_ip4n,
3136 next_hop_sw_if_index=self.pg8.sw_if_index)
3137
Matus Fabian2ba92e32017-08-21 07:05:03 -07003138 self.nat44_add_address(self.nat_addr)
3139 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3140 self.tcp_port_in, self.tcp_port_out,
3141 proto=IP_PROTOS.tcp)
3142 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3143 self.udp_port_in, self.udp_port_out,
3144 proto=IP_PROTOS.udp)
3145 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3146 self.icmp_id_in, self.icmp_id_out,
3147 proto=IP_PROTOS.icmp)
3148 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3149 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3150 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003151
3152 # out2in
3153 pkts = self.create_stream_out(self.pg8)
3154 self.pg8.add_stream(pkts)
3155 self.pg_enable_capture(self.pg_interfaces)
3156 self.pg_start()
3157 capture = self.pg7.get_capture(len(pkts))
3158 self.verify_capture_in(capture, self.pg7)
3159
3160 # in2out
3161 pkts = self.create_stream_in(self.pg7, self.pg8)
3162 self.pg7.add_stream(pkts)
3163 self.pg_enable_capture(self.pg_interfaces)
3164 self.pg_start()
3165 capture = self.pg8.get_capture(len(pkts))
3166 self.verify_capture_out(capture)
3167
Matus Fabian328dbc82017-06-19 04:28:04 -07003168 def test_static_unknown_proto(self):
3169 """ 1:1 NAT translate packet with unknown protocol """
3170 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003171 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3172 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3173 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3174 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003175
3176 # in2out
3177 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3178 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3179 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003180 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003181 TCP(sport=1234, dport=1234))
3182 self.pg0.add_stream(p)
3183 self.pg_enable_capture(self.pg_interfaces)
3184 self.pg_start()
3185 p = self.pg1.get_capture(1)
3186 packet = p[0]
3187 try:
3188 self.assertEqual(packet[IP].src, nat_ip)
3189 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003190 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003191 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003192 except:
3193 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3194 raise
3195
3196 # out2in
3197 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3198 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3199 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003200 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003201 TCP(sport=1234, dport=1234))
3202 self.pg1.add_stream(p)
3203 self.pg_enable_capture(self.pg_interfaces)
3204 self.pg_start()
3205 p = self.pg0.get_capture(1)
3206 packet = p[0]
3207 try:
3208 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3209 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003210 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003211 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003212 except:
3213 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3214 raise
3215
Matus Fabian7968e6c2017-07-06 05:37:49 -07003216 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003217 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3218
3219 host = self.pg0.remote_hosts[0]
3220 server = self.pg0.remote_hosts[1]
3221
3222 host_nat_ip = "10.0.0.10"
3223 server_nat_ip = "10.0.0.11"
3224
Matus Fabian2ba92e32017-08-21 07:05:03 -07003225 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3226 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3227 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3228 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3229 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003230
3231 # host to server
3232 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3233 IP(src=host.ip4, dst=server_nat_ip) /
3234 GRE() /
3235 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3236 TCP(sport=1234, dport=1234))
3237 self.pg0.add_stream(p)
3238 self.pg_enable_capture(self.pg_interfaces)
3239 self.pg_start()
3240 p = self.pg0.get_capture(1)
3241 packet = p[0]
3242 try:
3243 self.assertEqual(packet[IP].src, host_nat_ip)
3244 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003245 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003246 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003247 except:
3248 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3249 raise
3250
3251 # server to host
3252 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3253 IP(src=server.ip4, dst=host_nat_ip) /
3254 GRE() /
3255 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3256 TCP(sport=1234, dport=1234))
3257 self.pg0.add_stream(p)
3258 self.pg_enable_capture(self.pg_interfaces)
3259 self.pg_start()
3260 p = self.pg0.get_capture(1)
3261 packet = p[0]
3262 try:
3263 self.assertEqual(packet[IP].src, server_nat_ip)
3264 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003265 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003266 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003267 except:
3268 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3269 raise
3270
Matus Fabian93d84c92017-07-19 08:06:01 -07003271 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003272 """ NAT44 interface output feature (in2out postrouting) """
3273 self.nat44_add_address(self.nat_addr)
3274 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003275 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3276 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003277 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003278
3279 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003280 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003281 self.pg0.add_stream(pkts)
3282 self.pg_enable_capture(self.pg_interfaces)
3283 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003284 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003285 self.verify_capture_out(capture)
3286
3287 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003288 pkts = self.create_stream_out(self.pg3)
3289 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003290 self.pg_enable_capture(self.pg_interfaces)
3291 self.pg_start()
3292 capture = self.pg0.get_capture(len(pkts))
3293 self.verify_capture_in(capture, self.pg0)
3294
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003295 # from non-NAT interface to NAT inside interface
3296 pkts = self.create_stream_in(self.pg2, self.pg0)
3297 self.pg2.add_stream(pkts)
3298 self.pg_enable_capture(self.pg_interfaces)
3299 self.pg_start()
3300 capture = self.pg0.get_capture(len(pkts))
3301 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3302
Matus Fabian93d84c92017-07-19 08:06:01 -07003303 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003304 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003305 nat_ip_vrf10 = "10.0.0.10"
3306 nat_ip_vrf20 = "10.0.0.20"
3307
3308 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3309 dst_address_length=32,
3310 next_hop_address=self.pg3.remote_ip4n,
3311 next_hop_sw_if_index=self.pg3.sw_if_index,
3312 table_id=10)
3313 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3314 dst_address_length=32,
3315 next_hop_address=self.pg3.remote_ip4n,
3316 next_hop_sw_if_index=self.pg3.sw_if_index,
3317 table_id=20)
3318
Matus Fabian2ba92e32017-08-21 07:05:03 -07003319 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3320 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3321 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3322 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3323 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3324 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003325
3326 # in2out VRF 10
3327 pkts = self.create_stream_in(self.pg4, self.pg3)
3328 self.pg4.add_stream(pkts)
3329 self.pg_enable_capture(self.pg_interfaces)
3330 self.pg_start()
3331 capture = self.pg3.get_capture(len(pkts))
3332 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3333
3334 # out2in VRF 10
3335 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3336 self.pg3.add_stream(pkts)
3337 self.pg_enable_capture(self.pg_interfaces)
3338 self.pg_start()
3339 capture = self.pg4.get_capture(len(pkts))
3340 self.verify_capture_in(capture, self.pg4)
3341
3342 # in2out VRF 20
3343 pkts = self.create_stream_in(self.pg6, self.pg3)
3344 self.pg6.add_stream(pkts)
3345 self.pg_enable_capture(self.pg_interfaces)
3346 self.pg_start()
3347 capture = self.pg3.get_capture(len(pkts))
3348 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3349
3350 # out2in VRF 20
3351 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3352 self.pg3.add_stream(pkts)
3353 self.pg_enable_capture(self.pg_interfaces)
3354 self.pg_start()
3355 capture = self.pg6.get_capture(len(pkts))
3356 self.verify_capture_in(capture, self.pg6)
3357
Matus Fabian161c59c2017-07-21 03:46:03 -07003358 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003359 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003360 host = self.pg0.remote_hosts[0]
3361 server = self.pg0.remote_hosts[1]
3362 host_in_port = 1234
3363 host_out_port = 0
3364 server_in_port = 5678
3365 server_out_port = 8765
3366
Matus Fabian2ba92e32017-08-21 07:05:03 -07003367 self.nat44_add_address(self.nat_addr)
3368 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3369 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3370 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003371
3372 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003373 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3374 server_in_port, server_out_port,
3375 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003376
3377 # send packet from host to server
3378 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003379 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003380 TCP(sport=host_in_port, dport=server_out_port))
3381 self.pg0.add_stream(p)
3382 self.pg_enable_capture(self.pg_interfaces)
3383 self.pg_start()
3384 capture = self.pg0.get_capture(1)
3385 p = capture[0]
3386 try:
3387 ip = p[IP]
3388 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003389 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003390 self.assertEqual(ip.dst, server.ip4)
3391 self.assertNotEqual(tcp.sport, host_in_port)
3392 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003393 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003394 host_out_port = tcp.sport
3395 except:
3396 self.logger.error(ppp("Unexpected or invalid packet:", p))
3397 raise
3398
3399 # send reply from server to host
3400 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003401 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003402 TCP(sport=server_in_port, dport=host_out_port))
3403 self.pg0.add_stream(p)
3404 self.pg_enable_capture(self.pg_interfaces)
3405 self.pg_start()
3406 capture = self.pg0.get_capture(1)
3407 p = capture[0]
3408 try:
3409 ip = p[IP]
3410 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003411 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003412 self.assertEqual(ip.dst, host.ip4)
3413 self.assertEqual(tcp.sport, server_out_port)
3414 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003415 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003416 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003417 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003418 raise
3419
Matus Fabian36ea2d62017-10-24 04:13:49 -07003420 def test_one_armed_nat44(self):
3421 """ One armed NAT44 """
3422 remote_host = self.pg9.remote_hosts[0]
3423 local_host = self.pg9.remote_hosts[1]
3424 external_port = 0
3425
3426 self.nat44_add_address(self.nat_addr)
3427 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3428 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3429 is_inside=0)
3430
3431 # in2out
3432 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3433 IP(src=local_host.ip4, dst=remote_host.ip4) /
3434 TCP(sport=12345, dport=80))
3435 self.pg9.add_stream(p)
3436 self.pg_enable_capture(self.pg_interfaces)
3437 self.pg_start()
3438 capture = self.pg9.get_capture(1)
3439 p = capture[0]
3440 try:
3441 ip = p[IP]
3442 tcp = p[TCP]
3443 self.assertEqual(ip.src, self.nat_addr)
3444 self.assertEqual(ip.dst, remote_host.ip4)
3445 self.assertNotEqual(tcp.sport, 12345)
3446 external_port = tcp.sport
3447 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003448 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003449 except:
3450 self.logger.error(ppp("Unexpected or invalid packet:", p))
3451 raise
3452
3453 # out2in
3454 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3455 IP(src=remote_host.ip4, dst=self.nat_addr) /
3456 TCP(sport=80, dport=external_port))
3457 self.pg9.add_stream(p)
3458 self.pg_enable_capture(self.pg_interfaces)
3459 self.pg_start()
3460 capture = self.pg9.get_capture(1)
3461 p = capture[0]
3462 try:
3463 ip = p[IP]
3464 tcp = p[TCP]
3465 self.assertEqual(ip.src, remote_host.ip4)
3466 self.assertEqual(ip.dst, local_host.ip4)
3467 self.assertEqual(tcp.sport, 80)
3468 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003469 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003470 except:
3471 self.logger.error(ppp("Unexpected or invalid packet:", p))
3472 raise
3473
Matus Fabiana5e73762018-12-14 01:55:16 -08003474 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3475 self.assertEqual(err, 1)
3476 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3477 self.assertEqual(err, 1)
3478
Matus Fabian5ba86f72017-10-26 03:37:38 -07003479 def test_del_session(self):
3480 """ Delete NAT44 session """
3481 self.nat44_add_address(self.nat_addr)
3482 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3483 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3484 is_inside=0)
3485
3486 pkts = self.create_stream_in(self.pg0, self.pg1)
3487 self.pg0.add_stream(pkts)
3488 self.pg_enable_capture(self.pg_interfaces)
3489 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003490 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003491
3492 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3493 nsessions = len(sessions)
3494
3495 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3496 sessions[0].inside_port,
3497 sessions[0].protocol)
3498 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3499 sessions[1].outside_port,
3500 sessions[1].protocol,
3501 is_in=0)
3502
3503 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3504 self.assertEqual(nsessions - len(sessions), 2)
3505
Matus Fabian68ba8802018-08-08 05:52:47 -07003506 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3507 sessions[0].inside_port,
3508 sessions[0].protocol)
3509
3510 self.verify_no_nat44_user()
3511
Matus Fabianefcd1e92017-08-15 06:59:19 -07003512 def test_set_get_reass(self):
3513 """ NAT44 set/get virtual fragmentation reassembly """
3514 reas_cfg1 = self.vapi.nat_get_reass()
3515
3516 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3517 max_reass=reas_cfg1.ip4_max_reass * 2,
3518 max_frag=reas_cfg1.ip4_max_frag * 2)
3519
3520 reas_cfg2 = self.vapi.nat_get_reass()
3521
3522 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3523 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3524 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3525
3526 self.vapi.nat_set_reass(drop_frag=1)
3527 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3528
3529 def test_frag_in_order(self):
3530 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003531
Matus Fabianefcd1e92017-08-15 06:59:19 -07003532 self.nat44_add_address(self.nat_addr)
3533 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3534 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3535 is_inside=0)
3536
Matus Fabianda41d722018-10-19 04:01:19 -07003537 self.frag_in_order(proto=IP_PROTOS.tcp)
3538 self.frag_in_order(proto=IP_PROTOS.udp)
3539 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003540
Matus Fabian111add72018-11-20 02:19:05 -08003541 def test_frag_forwarding(self):
3542 """ NAT44 forwarding fragment test """
Ole Troane1ade682019-03-04 23:55:43 +01003543 self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
Matus Fabian111add72018-11-20 02:19:05 -08003544 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3545 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3546 is_inside=0)
3547 self.vapi.nat44_forwarding_enable_disable(1)
3548
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003549 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Matus Fabian111add72018-11-20 02:19:05 -08003550 pkts = self.create_stream_frag(self.pg1,
3551 self.pg0.remote_ip4,
3552 4789,
3553 4789,
3554 data,
3555 proto=IP_PROTOS.udp)
3556 self.pg1.add_stream(pkts)
3557 self.pg_enable_capture(self.pg_interfaces)
3558 self.pg_start()
3559 frags = self.pg0.get_capture(len(pkts))
3560 p = self.reass_frags_and_verify(frags,
3561 self.pg1.remote_ip4,
3562 self.pg0.remote_ip4)
3563 self.assertEqual(p[UDP].sport, 4789)
3564 self.assertEqual(p[UDP].dport, 4789)
3565 self.assertEqual(data, p[Raw].load)
3566
Matus Fabianefcd1e92017-08-15 06:59:19 -07003567 def test_reass_hairpinning(self):
3568 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003569
Matus Fabianda41d722018-10-19 04:01:19 -07003570 self.server = self.pg0.remote_hosts[1]
3571 self.host_in_port = random.randint(1025, 65535)
3572 self.server_in_port = random.randint(1025, 65535)
3573 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003574
3575 self.nat44_add_address(self.nat_addr)
3576 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3577 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3578 is_inside=0)
3579 # add static mapping for server
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,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003583 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003584 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3585 self.server_in_port,
3586 self.server_out_port,
3587 proto=IP_PROTOS.udp)
3588 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003589
Matus Fabianda41d722018-10-19 04:01:19 -07003590 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3591 self.reass_hairpinning(proto=IP_PROTOS.udp)
3592 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003593
3594 def test_frag_out_of_order(self):
3595 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003596
Matus Fabianefcd1e92017-08-15 06:59:19 -07003597 self.nat44_add_address(self.nat_addr)
3598 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3599 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3600 is_inside=0)
3601
Matus Fabianda41d722018-10-19 04:01:19 -07003602 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3603 self.frag_out_of_order(proto=IP_PROTOS.udp)
3604 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003605
Matus Fabian27697102017-11-09 01:43:47 -08003606 def test_port_restricted(self):
3607 """ Port restricted NAT44 (MAP-E CE) """
3608 self.nat44_add_address(self.nat_addr)
3609 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3610 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3611 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003612 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3613 psid_offset=6,
3614 psid_length=6,
3615 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003616
3617 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3618 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3619 TCP(sport=4567, dport=22))
3620 self.pg0.add_stream(p)
3621 self.pg_enable_capture(self.pg_interfaces)
3622 self.pg_start()
3623 capture = self.pg1.get_capture(1)
3624 p = capture[0]
3625 try:
3626 ip = p[IP]
3627 tcp = p[TCP]
3628 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3629 self.assertEqual(ip.src, self.nat_addr)
3630 self.assertEqual(tcp.dport, 22)
3631 self.assertNotEqual(tcp.sport, 4567)
3632 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003633 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003634 except:
3635 self.logger.error(ppp("Unexpected or invalid packet:", p))
3636 raise
3637
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003638 def test_port_range(self):
3639 """ External address port range """
3640 self.nat44_add_address(self.nat_addr)
3641 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3642 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3643 is_inside=0)
3644 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3645 start_port=1025,
3646 end_port=1027)
3647
3648 pkts = []
3649 for port in range(0, 5):
3650 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3651 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3652 TCP(sport=1125 + port))
3653 pkts.append(p)
3654 self.pg0.add_stream(pkts)
3655 self.pg_enable_capture(self.pg_interfaces)
3656 self.pg_start()
3657 capture = self.pg1.get_capture(3)
3658 for p in capture:
3659 tcp = p[TCP]
3660 self.assertGreaterEqual(tcp.sport, 1025)
3661 self.assertLessEqual(tcp.sport, 1027)
3662
Matus Fabiana6110b62018-06-13 05:39:07 -07003663 def test_ipfix_max_frags(self):
3664 """ IPFIX logging maximum fragments pending reassembly exceeded """
3665 self.nat44_add_address(self.nat_addr)
3666 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3667 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3668 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003669 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003670 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3671 src_address=self.pg3.local_ip4n,
3672 path_mtu=512,
3673 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01003674 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3675 src_port=self.ipfix_src_port)
Matus Fabiana6110b62018-06-13 05:39:07 -07003676
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003677 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabiana6110b62018-06-13 05:39:07 -07003678 self.tcp_port_in = random.randint(1025, 65535)
3679 pkts = self.create_stream_frag(self.pg0,
3680 self.pg1.remote_ip4,
3681 self.tcp_port_in,
3682 20,
3683 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003684 pkts.reverse()
3685 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003686 self.pg_enable_capture(self.pg_interfaces)
3687 self.pg_start()
3688 self.pg1.assert_nothing_captured()
3689 sleep(1)
3690 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3691 capture = self.pg3.get_capture(9)
3692 ipfix = IPFIXDecoder()
3693 # first load template
3694 for p in capture:
3695 self.assertTrue(p.haslayer(IPFIX))
3696 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3697 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3698 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3699 self.assertEqual(p[UDP].dport, 4739)
3700 self.assertEqual(p[IPFIX].observationDomainID,
3701 self.ipfix_domain_id)
3702 if p.haslayer(Template):
3703 ipfix.add_template(p.getlayer(Template))
3704 # verify events in data set
3705 for p in capture:
3706 if p.haslayer(Data):
3707 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003708 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003709 self.pg0.remote_ip4n)
3710
Matus Fabian8008d7c2018-07-09 01:34:20 -07003711 def test_multiple_outside_vrf(self):
3712 """ Multiple outside VRF """
3713 vrf_id1 = 1
3714 vrf_id2 = 2
3715
3716 self.pg1.unconfig_ip4()
3717 self.pg2.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003718 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3719 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003720 self.pg1.set_table_ip4(vrf_id1)
3721 self.pg2.set_table_ip4(vrf_id2)
3722 self.pg1.config_ip4()
3723 self.pg2.config_ip4()
3724 self.pg1.resolve_arp()
3725 self.pg2.resolve_arp()
3726
3727 self.nat44_add_address(self.nat_addr)
3728 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3729 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3730 is_inside=0)
3731 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3732 is_inside=0)
3733
3734 try:
3735 # first VRF
3736 pkts = self.create_stream_in(self.pg0, self.pg1)
3737 self.pg0.add_stream(pkts)
3738 self.pg_enable_capture(self.pg_interfaces)
3739 self.pg_start()
3740 capture = self.pg1.get_capture(len(pkts))
3741 self.verify_capture_out(capture, self.nat_addr)
3742
3743 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3744 self.pg1.add_stream(pkts)
3745 self.pg_enable_capture(self.pg_interfaces)
3746 self.pg_start()
3747 capture = self.pg0.get_capture(len(pkts))
3748 self.verify_capture_in(capture, self.pg0)
3749
3750 self.tcp_port_in = 60303
3751 self.udp_port_in = 60304
3752 self.icmp_id_in = 60305
3753
3754 # second VRF
3755 pkts = self.create_stream_in(self.pg0, self.pg2)
3756 self.pg0.add_stream(pkts)
3757 self.pg_enable_capture(self.pg_interfaces)
3758 self.pg_start()
3759 capture = self.pg2.get_capture(len(pkts))
3760 self.verify_capture_out(capture, self.nat_addr)
3761
3762 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3763 self.pg2.add_stream(pkts)
3764 self.pg_enable_capture(self.pg_interfaces)
3765 self.pg_start()
3766 capture = self.pg0.get_capture(len(pkts))
3767 self.verify_capture_in(capture, self.pg0)
3768
3769 finally:
3770 self.pg1.unconfig_ip4()
3771 self.pg2.unconfig_ip4()
3772 self.pg1.set_table_ip4(0)
3773 self.pg2.set_table_ip4(0)
3774 self.pg1.config_ip4()
3775 self.pg2.config_ip4()
3776 self.pg1.resolve_arp()
3777 self.pg2.resolve_arp()
3778
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08003779 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07003780 def test_session_timeout(self):
3781 """ NAT44 session timeouts """
3782 self.nat44_add_address(self.nat_addr)
3783 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3784 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3785 is_inside=0)
3786 self.vapi.nat_set_timeouts(udp=5)
3787
3788 max_sessions = 1000
3789 pkts = []
3790 for i in range(0, max_sessions):
3791 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3792 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3793 IP(src=src, dst=self.pg1.remote_ip4) /
3794 UDP(sport=1025, dport=53))
3795 pkts.append(p)
3796 self.pg0.add_stream(pkts)
3797 self.pg_enable_capture(self.pg_interfaces)
3798 self.pg_start()
3799 self.pg1.get_capture(max_sessions)
3800
3801 sleep(6)
3802
3803 pkts = []
3804 for i in range(0, max_sessions):
3805 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3806 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3807 IP(src=src, dst=self.pg1.remote_ip4) /
3808 UDP(sport=1026, dport=53))
3809 pkts.append(p)
3810 self.pg0.add_stream(pkts)
3811 self.pg_enable_capture(self.pg_interfaces)
3812 self.pg_start()
3813 self.pg1.get_capture(max_sessions)
3814
3815 nsessions = 0
3816 users = self.vapi.nat44_user_dump()
3817 for user in users:
3818 nsessions = nsessions + user.nsessions
3819 self.assertLess(nsessions, 2 * max_sessions)
3820
Matus Fabianbb4e0222018-09-13 02:36:25 -07003821 def test_mss_clamping(self):
3822 """ TCP MSS clamping """
3823 self.nat44_add_address(self.nat_addr)
3824 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3825 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3826 is_inside=0)
3827
3828 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3829 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3830 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3831 flags="S", options=[('MSS', 1400)]))
3832
3833 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3834 self.pg0.add_stream(p)
3835 self.pg_enable_capture(self.pg_interfaces)
3836 self.pg_start()
3837 capture = self.pg1.get_capture(1)
3838 # Negotiated MSS value greater than configured - changed
3839 self.verify_mss_value(capture[0], 1000)
3840
3841 self.vapi.nat_set_mss_clamping(enable=0)
3842 self.pg0.add_stream(p)
3843 self.pg_enable_capture(self.pg_interfaces)
3844 self.pg_start()
3845 capture = self.pg1.get_capture(1)
3846 # MSS clamping disabled - negotiated MSS unchanged
3847 self.verify_mss_value(capture[0], 1400)
3848
3849 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3850 self.pg0.add_stream(p)
3851 self.pg_enable_capture(self.pg_interfaces)
3852 self.pg_start()
3853 capture = self.pg1.get_capture(1)
3854 # Negotiated MSS value smaller than configured - unchanged
3855 self.verify_mss_value(capture[0], 1400)
3856
Matus Fabian34931eb2019-02-26 09:05:23 -08003857 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3858 def test_ha_send(self):
3859 """ Send HA session synchronization events (active) """
3860 self.nat44_add_address(self.nat_addr)
3861 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3862 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3863 is_inside=0)
3864 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3865 self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3866 bind_layers(UDP, HANATStateSync, sport=12345)
3867
3868 # create sessions
3869 pkts = self.create_stream_in(self.pg0, self.pg1)
3870 self.pg0.add_stream(pkts)
3871 self.pg_enable_capture(self.pg_interfaces)
3872 self.pg_start()
3873 capture = self.pg1.get_capture(len(pkts))
3874 self.verify_capture_out(capture)
3875 # active send HA events
3876 self.vapi.nat_ha_flush()
3877 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3878 self.assertEqual(stats[0][0], 3)
3879 capture = self.pg3.get_capture(1)
3880 p = capture[0]
3881 self.assert_packet_checksums_valid(p)
3882 try:
3883 ip = p[IP]
3884 udp = p[UDP]
3885 hanat = p[HANATStateSync]
3886 except IndexError:
3887 self.logger.error(ppp("Invalid packet:", p))
3888 raise
3889 else:
3890 self.assertEqual(ip.src, self.pg3.local_ip4)
3891 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3892 self.assertEqual(udp.sport, 12345)
3893 self.assertEqual(udp.dport, 12346)
3894 self.assertEqual(hanat.version, 1)
3895 self.assertEqual(hanat.thread_index, 0)
3896 self.assertEqual(hanat.count, 3)
3897 seq = hanat.sequence_number
3898 for event in hanat.events:
3899 self.assertEqual(event.event_type, 1)
3900 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3901 self.assertEqual(event.out_addr, self.nat_addr)
3902 self.assertEqual(event.fib_index, 0)
3903
3904 # ACK received events
3905 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3906 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3907 UDP(sport=12346, dport=12345) /
3908 HANATStateSync(sequence_number=seq, flags='ACK'))
3909 self.pg3.add_stream(ack)
3910 self.pg_start()
3911 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3912 self.assertEqual(stats[0][0], 1)
3913
3914 # delete one session
3915 self.pg_enable_capture(self.pg_interfaces)
3916 self.vapi.nat44_del_session(self.pg0.remote_ip4n, self.tcp_port_in,
3917 IP_PROTOS.tcp)
3918 self.vapi.nat_ha_flush()
3919 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3920 self.assertEqual(stats[0][0], 1)
3921 capture = self.pg3.get_capture(1)
3922 p = capture[0]
3923 try:
3924 hanat = p[HANATStateSync]
3925 except IndexError:
3926 self.logger.error(ppp("Invalid packet:", p))
3927 raise
3928 else:
3929 self.assertGreater(hanat.sequence_number, seq)
3930
3931 # do not send ACK, active retry send HA event again
3932 self.pg_enable_capture(self.pg_interfaces)
3933 sleep(12)
3934 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3935 self.assertEqual(stats[0][0], 3)
3936 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3937 self.assertEqual(stats[0][0], 1)
3938 capture = self.pg3.get_capture(3)
3939 for packet in capture:
3940 self.assertEqual(packet, p)
3941
3942 # session counters refresh
3943 pkts = self.create_stream_out(self.pg1)
3944 self.pg1.add_stream(pkts)
3945 self.pg_enable_capture(self.pg_interfaces)
3946 self.pg_start()
3947 self.pg0.get_capture(2)
3948 self.vapi.nat_ha_flush()
3949 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3950 self.assertEqual(stats[0][0], 2)
3951 capture = self.pg3.get_capture(1)
3952 p = capture[0]
3953 self.assert_packet_checksums_valid(p)
3954 try:
3955 ip = p[IP]
3956 udp = p[UDP]
3957 hanat = p[HANATStateSync]
3958 except IndexError:
3959 self.logger.error(ppp("Invalid packet:", p))
3960 raise
3961 else:
3962 self.assertEqual(ip.src, self.pg3.local_ip4)
3963 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3964 self.assertEqual(udp.sport, 12345)
3965 self.assertEqual(udp.dport, 12346)
3966 self.assertEqual(hanat.version, 1)
3967 self.assertEqual(hanat.count, 2)
3968 seq = hanat.sequence_number
3969 for event in hanat.events:
3970 self.assertEqual(event.event_type, 3)
3971 self.assertEqual(event.out_addr, self.nat_addr)
3972 self.assertEqual(event.fib_index, 0)
3973 self.assertEqual(event.total_pkts, 2)
3974 self.assertGreater(event.total_bytes, 0)
3975
3976 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3977 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3978 UDP(sport=12346, dport=12345) /
3979 HANATStateSync(sequence_number=seq, flags='ACK'))
3980 self.pg3.add_stream(ack)
3981 self.pg_start()
3982 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3983 self.assertEqual(stats[0][0], 2)
3984
3985 def test_ha_recv(self):
3986 """ Receive HA session synchronization events (passive) """
3987 self.nat44_add_address(self.nat_addr)
3988 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3989 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3990 is_inside=0)
3991 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3992 bind_layers(UDP, HANATStateSync, sport=12345)
3993
3994 self.tcp_port_out = random.randint(1025, 65535)
3995 self.udp_port_out = random.randint(1025, 65535)
3996
3997 # send HA session add events to failover/passive
3998 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3999 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4000 UDP(sport=12346, dport=12345) /
4001 HANATStateSync(sequence_number=1, events=[
4002 Event(event_type='add', protocol='tcp',
4003 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4004 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4005 eh_addr=self.pg1.remote_ip4,
4006 ehn_addr=self.pg1.remote_ip4,
4007 eh_port=self.tcp_external_port,
4008 ehn_port=self.tcp_external_port, fib_index=0),
4009 Event(event_type='add', protocol='udp',
4010 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4011 in_port=self.udp_port_in, out_port=self.udp_port_out,
4012 eh_addr=self.pg1.remote_ip4,
4013 ehn_addr=self.pg1.remote_ip4,
4014 eh_port=self.udp_external_port,
4015 ehn_port=self.udp_external_port, fib_index=0)]))
4016
4017 self.pg3.add_stream(p)
4018 self.pg_enable_capture(self.pg_interfaces)
4019 self.pg_start()
4020 # receive ACK
4021 capture = self.pg3.get_capture(1)
4022 p = capture[0]
4023 try:
4024 hanat = p[HANATStateSync]
4025 except IndexError:
4026 self.logger.error(ppp("Invalid packet:", p))
4027 raise
4028 else:
4029 self.assertEqual(hanat.sequence_number, 1)
4030 self.assertEqual(hanat.flags, 'ACK')
4031 self.assertEqual(hanat.version, 1)
4032 self.assertEqual(hanat.thread_index, 0)
4033 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4034 self.assertEqual(stats[0][0], 1)
4035 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4036 self.assertEqual(stats[0][0], 2)
4037 users = self.statistics.get_counter('/nat44/total-users')
4038 self.assertEqual(users[0][0], 1)
4039 sessions = self.statistics.get_counter('/nat44/total-sessions')
4040 self.assertEqual(sessions[0][0], 2)
4041 users = self.vapi.nat44_user_dump()
4042 self.assertEqual(len(users), 1)
4043 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4044 # there should be 2 sessions created by HA
4045 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4046 users[0].vrf_id)
4047 self.assertEqual(len(sessions), 2)
4048 for session in sessions:
4049 self.assertEqual(session.inside_ip_address, self.pg0.remote_ip4n)
4050 self.assertEqual(session.outside_ip_address, self.nat_addr_n)
4051 self.assertIn(session.inside_port,
4052 [self.tcp_port_in, self.udp_port_in])
4053 self.assertIn(session.outside_port,
4054 [self.tcp_port_out, self.udp_port_out])
4055 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4056
4057 # send HA session delete event to failover/passive
4058 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4059 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4060 UDP(sport=12346, dport=12345) /
4061 HANATStateSync(sequence_number=2, events=[
4062 Event(event_type='del', protocol='udp',
4063 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4064 in_port=self.udp_port_in, out_port=self.udp_port_out,
4065 eh_addr=self.pg1.remote_ip4,
4066 ehn_addr=self.pg1.remote_ip4,
4067 eh_port=self.udp_external_port,
4068 ehn_port=self.udp_external_port, fib_index=0)]))
4069
4070 self.pg3.add_stream(p)
4071 self.pg_enable_capture(self.pg_interfaces)
4072 self.pg_start()
4073 # receive ACK
4074 capture = self.pg3.get_capture(1)
4075 p = capture[0]
4076 try:
4077 hanat = p[HANATStateSync]
4078 except IndexError:
4079 self.logger.error(ppp("Invalid packet:", p))
4080 raise
4081 else:
4082 self.assertEqual(hanat.sequence_number, 2)
4083 self.assertEqual(hanat.flags, 'ACK')
4084 self.assertEqual(hanat.version, 1)
4085 users = self.vapi.nat44_user_dump()
4086 self.assertEqual(len(users), 1)
4087 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4088 # now we should have only 1 session, 1 deleted by HA
4089 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4090 users[0].vrf_id)
4091 self.assertEqual(len(sessions), 1)
4092 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4093 self.assertEqual(stats[0][0], 1)
4094
4095 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4096 self.assertEqual(stats, 2)
4097
4098 # send HA session refresh event to failover/passive
4099 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4100 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4101 UDP(sport=12346, dport=12345) /
4102 HANATStateSync(sequence_number=3, events=[
4103 Event(event_type='refresh', protocol='tcp',
4104 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4105 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4106 eh_addr=self.pg1.remote_ip4,
4107 ehn_addr=self.pg1.remote_ip4,
4108 eh_port=self.tcp_external_port,
4109 ehn_port=self.tcp_external_port, fib_index=0,
4110 total_bytes=1024, total_pkts=2)]))
4111 self.pg3.add_stream(p)
4112 self.pg_enable_capture(self.pg_interfaces)
4113 self.pg_start()
4114 # receive ACK
4115 capture = self.pg3.get_capture(1)
4116 p = capture[0]
4117 try:
4118 hanat = p[HANATStateSync]
4119 except IndexError:
4120 self.logger.error(ppp("Invalid packet:", p))
4121 raise
4122 else:
4123 self.assertEqual(hanat.sequence_number, 3)
4124 self.assertEqual(hanat.flags, 'ACK')
4125 self.assertEqual(hanat.version, 1)
4126 users = self.vapi.nat44_user_dump()
4127 self.assertEqual(len(users), 1)
4128 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4129 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4130 users[0].vrf_id)
4131 self.assertEqual(len(sessions), 1)
4132 session = sessions[0]
4133 self.assertEqual(session.total_bytes, 1024)
4134 self.assertEqual(session.total_pkts, 2)
4135 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4136 self.assertEqual(stats[0][0], 1)
4137
4138 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4139 self.assertEqual(stats, 3)
4140
4141 # send packet to test session created by HA
4142 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4143 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4144 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4145 self.pg1.add_stream(p)
4146 self.pg_enable_capture(self.pg_interfaces)
4147 self.pg_start()
4148 capture = self.pg0.get_capture(1)
4149 p = capture[0]
4150 try:
4151 ip = p[IP]
4152 tcp = p[TCP]
4153 except IndexError:
4154 self.logger.error(ppp("Invalid packet:", p))
4155 raise
4156 else:
4157 self.assertEqual(ip.src, self.pg1.remote_ip4)
4158 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4159 self.assertEqual(tcp.sport, self.tcp_external_port)
4160 self.assertEqual(tcp.dport, self.tcp_port_in)
4161
Matus Fabiana6110b62018-06-13 05:39:07 -07004162 def tearDown(self):
4163 super(TestNAT44, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07004164 self.clear_nat44()
4165 self.vapi.cli("clear logging")
4166
4167 def show_commands_at_teardown(self):
4168 self.logger.info(self.vapi.cli("show nat44 addresses"))
4169 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4170 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4171 self.logger.info(self.vapi.cli("show nat44 interface address"))
4172 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4173 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4174 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4175 self.logger.info(self.vapi.cli("show nat timeouts"))
4176 self.logger.info(
4177 self.vapi.cli("show nat addr-port-assignment-alg"))
4178 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004179
4180
4181class TestNAT44EndpointDependent(MethodHolder):
4182 """ Endpoint-Dependent mapping and filtering test cases """
4183
4184 @classmethod
4185 def setUpConstants(cls):
4186 super(TestNAT44EndpointDependent, cls).setUpConstants()
4187 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4188
4189 @classmethod
4190 def setUpClass(cls):
4191 super(TestNAT44EndpointDependent, cls).setUpClass()
4192 cls.vapi.cli("set log class nat level debug")
4193 try:
4194 cls.tcp_port_in = 6303
4195 cls.tcp_port_out = 6303
4196 cls.udp_port_in = 6304
4197 cls.udp_port_out = 6304
4198 cls.icmp_id_in = 6305
4199 cls.icmp_id_out = 6305
4200 cls.nat_addr = '10.0.0.3'
4201 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4202 cls.ipfix_src_port = 4739
4203 cls.ipfix_domain_id = 1
4204 cls.tcp_external_port = 80
4205
Matus Fabian8008d7c2018-07-09 01:34:20 -07004206 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004207 cls.interfaces = list(cls.pg_interfaces[0:3])
4208
4209 for i in cls.interfaces:
4210 i.admin_up()
4211 i.config_ip4()
4212 i.resolve_arp()
4213
4214 cls.pg0.generate_remote_hosts(3)
4215 cls.pg0.configure_ipv4_neighbors()
4216
4217 cls.pg3.admin_up()
4218
4219 cls.pg4.generate_remote_hosts(2)
4220 cls.pg4.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004221 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01004222 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004223 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4224 address_length=24)
Matus Fabiana6110b62018-06-13 05:39:07 -07004225 cls.pg4.admin_up()
4226 cls.pg4.resolve_arp()
4227 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4228 cls.pg4.resolve_arp()
4229
Matus Fabian8008d7c2018-07-09 01:34:20 -07004230 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004231 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004232
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004233 cls.pg5._local_ip4 = "10.1.1.1"
4234 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4235 cls.pg5.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004236 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4237 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4238 socket.AF_INET, cls.pg5.remote_ip4)
4239 cls.pg5.set_table_ip4(1)
4240 cls.pg5.config_ip4()
4241 cls.pg5.admin_up()
4242 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4243 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004244 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004245 next_hop_sw_if_index=cls.pg5.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004246 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004247
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004248 cls.pg6._local_ip4 = "10.1.2.1"
4249 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4250 cls.pg6.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004251 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4252 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4253 socket.AF_INET, cls.pg6.remote_ip4)
4254 cls.pg6.set_table_ip4(1)
4255 cls.pg6.config_ip4()
4256 cls.pg6.admin_up()
4257 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4258 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004259 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004260 next_hop_sw_if_index=cls.pg6.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004261 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004262
4263 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4264 dst_address_length=16,
Ole Troana5b2eec2019-03-11 19:23:25 +01004265 next_hop_address=zero_ip4n, table_id=0,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004266 next_hop_table_id=1)
4267 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4268 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004269 next_hop_address=zero_ip4n, table_id=1,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004270 next_hop_table_id=0)
4271 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4272 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004273 next_hop_address=cls.pg1.local_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004274 next_hop_sw_if_index=cls.pg1.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004275 table_id=0)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004276
4277 cls.pg5.resolve_arp()
4278 cls.pg6.resolve_arp()
4279
Matus Fabiana6110b62018-06-13 05:39:07 -07004280 except Exception:
4281 super(TestNAT44EndpointDependent, cls).tearDownClass()
4282 raise
4283
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07004284 @classmethod
4285 def tearDownClass(cls):
4286 super(TestNAT44EndpointDependent, cls).tearDownClass()
4287
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004288 def test_frag_in_order(self):
4289 """ NAT44 translate fragments arriving in order """
4290 self.nat44_add_address(self.nat_addr)
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.frag_in_order(proto=IP_PROTOS.tcp)
4295 self.frag_in_order(proto=IP_PROTOS.udp)
4296 self.frag_in_order(proto=IP_PROTOS.icmp)
4297
4298 def test_frag_in_order_dont_translate(self):
4299 """ NAT44 don't translate fragments arriving in order """
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.vapi.nat44_forwarding_enable_disable(enable=True)
4304 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4305
4306 def test_frag_out_of_order(self):
4307 """ NAT44 translate fragments arriving out of order """
4308 self.nat44_add_address(self.nat_addr)
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.frag_out_of_order(proto=IP_PROTOS.tcp)
4313 self.frag_out_of_order(proto=IP_PROTOS.udp)
4314 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4315
4316 def test_frag_out_of_order_dont_translate(self):
4317 """ NAT44 don't translate fragments arriving out of order """
4318 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4319 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4320 is_inside=0)
4321 self.vapi.nat44_forwarding_enable_disable(enable=True)
4322 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4323
4324 def test_frag_in_order_in_plus_out(self):
4325 """ in+out interface fragments in order """
4326 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4327 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4328 is_inside=0)
4329 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4330 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4331 is_inside=0)
4332
4333 self.server = self.pg1.remote_hosts[0]
4334
4335 self.server_in_addr = self.server.ip4
4336 self.server_out_addr = '11.11.11.11'
4337 self.server_in_port = random.randint(1025, 65535)
4338 self.server_out_port = random.randint(1025, 65535)
4339
4340 self.nat44_add_address(self.server_out_addr)
4341
4342 # add static mappings for server
4343 self.nat44_add_static_mapping(self.server_in_addr,
4344 self.server_out_addr,
4345 self.server_in_port,
4346 self.server_out_port,
4347 proto=IP_PROTOS.tcp)
4348 self.nat44_add_static_mapping(self.server_in_addr,
4349 self.server_out_addr,
4350 self.server_in_port,
4351 self.server_out_port,
4352 proto=IP_PROTOS.udp)
4353 self.nat44_add_static_mapping(self.server_in_addr,
4354 self.server_out_addr,
4355 proto=IP_PROTOS.icmp)
4356
4357 self.vapi.nat_set_reass(timeout=10)
4358
4359 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4360 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4361 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4362
4363 def test_frag_out_of_order_in_plus_out(self):
4364 """ in+out interface fragments out of order """
4365 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4366 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4367 is_inside=0)
4368 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4369 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4370 is_inside=0)
4371
4372 self.server = self.pg1.remote_hosts[0]
4373
4374 self.server_in_addr = self.server.ip4
4375 self.server_out_addr = '11.11.11.11'
4376 self.server_in_port = random.randint(1025, 65535)
4377 self.server_out_port = random.randint(1025, 65535)
4378
4379 self.nat44_add_address(self.server_out_addr)
4380
4381 # add static mappings for server
4382 self.nat44_add_static_mapping(self.server_in_addr,
4383 self.server_out_addr,
4384 self.server_in_port,
4385 self.server_out_port,
4386 proto=IP_PROTOS.tcp)
4387 self.nat44_add_static_mapping(self.server_in_addr,
4388 self.server_out_addr,
4389 self.server_in_port,
4390 self.server_out_port,
4391 proto=IP_PROTOS.udp)
4392 self.nat44_add_static_mapping(self.server_in_addr,
4393 self.server_out_addr,
4394 proto=IP_PROTOS.icmp)
4395
4396 self.vapi.nat_set_reass(timeout=10)
4397
4398 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4399 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4400 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4401
4402 def test_reass_hairpinning(self):
4403 """ NAT44 fragments hairpinning """
4404 self.server = self.pg0.remote_hosts[1]
4405 self.host_in_port = random.randint(1025, 65535)
4406 self.server_in_port = random.randint(1025, 65535)
4407 self.server_out_port = random.randint(1025, 65535)
4408
4409 self.nat44_add_address(self.nat_addr)
4410 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4411 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4412 is_inside=0)
4413 # add static mapping for server
4414 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4415 self.server_in_port,
4416 self.server_out_port,
4417 proto=IP_PROTOS.tcp)
4418 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4419 self.server_in_port,
4420 self.server_out_port,
4421 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004422 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004423
4424 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4425 self.reass_hairpinning(proto=IP_PROTOS.udp)
4426 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4427
Matus Fabiana6110b62018-06-13 05:39:07 -07004428 def test_dynamic(self):
4429 """ NAT44 dynamic translation test """
4430
4431 self.nat44_add_address(self.nat_addr)
4432 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4433 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4434 is_inside=0)
4435
Matus Fabian69ce30d2018-08-22 01:27:10 -07004436 nat_config = self.vapi.nat_show_config()
4437 self.assertEqual(1, nat_config.endpoint_dependent)
4438
Matus Fabiana6110b62018-06-13 05:39:07 -07004439 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004440 tcpn = self.statistics.get_counter(
4441 '/err/nat44-ed-in2out-slowpath/TCP packets')
4442 udpn = self.statistics.get_counter(
4443 '/err/nat44-ed-in2out-slowpath/UDP packets')
4444 icmpn = self.statistics.get_counter(
4445 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4446 totaln = self.statistics.get_counter(
4447 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4448
Matus Fabiana6110b62018-06-13 05:39:07 -07004449 pkts = self.create_stream_in(self.pg0, self.pg1)
4450 self.pg0.add_stream(pkts)
4451 self.pg_enable_capture(self.pg_interfaces)
4452 self.pg_start()
4453 capture = self.pg1.get_capture(len(pkts))
4454 self.verify_capture_out(capture)
4455
Matus Fabiana5e73762018-12-14 01:55:16 -08004456 err = self.statistics.get_counter(
4457 '/err/nat44-ed-in2out-slowpath/TCP packets')
4458 self.assertEqual(err - tcpn, 1)
4459 err = self.statistics.get_counter(
4460 '/err/nat44-ed-in2out-slowpath/UDP packets')
4461 self.assertEqual(err - udpn, 1)
4462 err = self.statistics.get_counter(
4463 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4464 self.assertEqual(err - icmpn, 1)
4465 err = self.statistics.get_counter(
4466 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4467 self.assertEqual(err - totaln, 3)
4468
Matus Fabiana6110b62018-06-13 05:39:07 -07004469 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004470 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4471 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4472 icmpn = self.statistics.get_counter(
4473 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4474 totaln = self.statistics.get_counter(
4475 '/err/nat44-ed-out2in/good out2in packets processed')
4476
Matus Fabiana6110b62018-06-13 05:39:07 -07004477 pkts = self.create_stream_out(self.pg1)
4478 self.pg1.add_stream(pkts)
4479 self.pg_enable_capture(self.pg_interfaces)
4480 self.pg_start()
4481 capture = self.pg0.get_capture(len(pkts))
4482 self.verify_capture_in(capture, self.pg0)
4483
Matus Fabiana5e73762018-12-14 01:55:16 -08004484 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4485 self.assertEqual(err - tcpn, 1)
4486 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4487 self.assertEqual(err - udpn, 1)
4488 err = self.statistics.get_counter(
4489 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4490 self.assertEqual(err - icmpn, 1)
4491 err = self.statistics.get_counter(
4492 '/err/nat44-ed-out2in/good out2in packets processed')
4493 self.assertEqual(err - totaln, 2)
4494
Matus Fabianfd0d5082018-12-18 01:08:51 -08004495 users = self.statistics.get_counter('/nat44/total-users')
4496 self.assertEqual(users[0][0], 1)
4497 sessions = self.statistics.get_counter('/nat44/total-sessions')
4498 self.assertEqual(sessions[0][0], 3)
4499
Matus Fabiana6110b62018-06-13 05:39:07 -07004500 def test_forwarding(self):
4501 """ NAT44 forwarding test """
4502
4503 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4504 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4505 is_inside=0)
4506 self.vapi.nat44_forwarding_enable_disable(1)
4507
4508 real_ip = self.pg0.remote_ip4n
4509 alias_ip = self.nat_addr_n
4510 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4511 external_ip=alias_ip)
4512
4513 try:
4514 # in2out - static mapping match
4515
4516 pkts = self.create_stream_out(self.pg1)
4517 self.pg1.add_stream(pkts)
4518 self.pg_enable_capture(self.pg_interfaces)
4519 self.pg_start()
4520 capture = self.pg0.get_capture(len(pkts))
4521 self.verify_capture_in(capture, self.pg0)
4522
4523 pkts = self.create_stream_in(self.pg0, self.pg1)
4524 self.pg0.add_stream(pkts)
4525 self.pg_enable_capture(self.pg_interfaces)
4526 self.pg_start()
4527 capture = self.pg1.get_capture(len(pkts))
4528 self.verify_capture_out(capture, same_port=True)
4529
4530 # in2out - no static mapping match
4531
4532 host0 = self.pg0.remote_hosts[0]
4533 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4534 try:
4535 pkts = self.create_stream_out(self.pg1,
4536 dst_ip=self.pg0.remote_ip4,
4537 use_inside_ports=True)
4538 self.pg1.add_stream(pkts)
4539 self.pg_enable_capture(self.pg_interfaces)
4540 self.pg_start()
4541 capture = self.pg0.get_capture(len(pkts))
4542 self.verify_capture_in(capture, self.pg0)
4543
4544 pkts = self.create_stream_in(self.pg0, self.pg1)
4545 self.pg0.add_stream(pkts)
4546 self.pg_enable_capture(self.pg_interfaces)
4547 self.pg_start()
4548 capture = self.pg1.get_capture(len(pkts))
4549 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4550 same_port=True)
4551 finally:
4552 self.pg0.remote_hosts[0] = host0
4553
4554 user = self.pg0.remote_hosts[1]
4555 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4556 self.assertEqual(len(sessions), 3)
4557 self.assertTrue(sessions[0].ext_host_valid)
4558 self.vapi.nat44_del_session(
4559 sessions[0].inside_ip_address,
4560 sessions[0].inside_port,
4561 sessions[0].protocol,
4562 ext_host_address=sessions[0].ext_host_address,
4563 ext_host_port=sessions[0].ext_host_port)
4564 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4565 self.assertEqual(len(sessions), 2)
4566
4567 finally:
4568 self.vapi.nat44_forwarding_enable_disable(0)
4569 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4570 external_ip=alias_ip,
4571 is_add=0)
4572
4573 def test_static_lb(self):
4574 """ NAT44 local service load balancing """
4575 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4576 external_port = 80
4577 local_port = 8080
4578 server1 = self.pg0.remote_hosts[0]
4579 server2 = self.pg0.remote_hosts[1]
4580
4581 locals = [{'addr': server1.ip4n,
4582 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004583 'probability': 70,
4584 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004585 {'addr': server2.ip4n,
4586 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004587 'probability': 30,
4588 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004589
4590 self.nat44_add_address(self.nat_addr)
4591 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4592 external_port,
4593 IP_PROTOS.tcp,
4594 local_num=len(locals),
4595 locals=locals)
4596 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4597 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4598 is_inside=0)
4599
4600 # from client to service
4601 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4602 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4603 TCP(sport=12345, dport=external_port))
4604 self.pg1.add_stream(p)
4605 self.pg_enable_capture(self.pg_interfaces)
4606 self.pg_start()
4607 capture = self.pg0.get_capture(1)
4608 p = capture[0]
4609 server = None
4610 try:
4611 ip = p[IP]
4612 tcp = p[TCP]
4613 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4614 if ip.dst == server1.ip4:
4615 server = server1
4616 else:
4617 server = server2
4618 self.assertEqual(tcp.dport, local_port)
4619 self.assert_packet_checksums_valid(p)
4620 except:
4621 self.logger.error(ppp("Unexpected or invalid packet:", p))
4622 raise
4623
4624 # from service back to client
4625 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4626 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4627 TCP(sport=local_port, dport=12345))
4628 self.pg0.add_stream(p)
4629 self.pg_enable_capture(self.pg_interfaces)
4630 self.pg_start()
4631 capture = self.pg1.get_capture(1)
4632 p = capture[0]
4633 try:
4634 ip = p[IP]
4635 tcp = p[TCP]
4636 self.assertEqual(ip.src, self.nat_addr)
4637 self.assertEqual(tcp.sport, external_port)
4638 self.assert_packet_checksums_valid(p)
4639 except:
4640 self.logger.error(ppp("Unexpected or invalid packet:", p))
4641 raise
4642
4643 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4644 self.assertEqual(len(sessions), 1)
4645 self.assertTrue(sessions[0].ext_host_valid)
4646 self.vapi.nat44_del_session(
4647 sessions[0].inside_ip_address,
4648 sessions[0].inside_port,
4649 sessions[0].protocol,
4650 ext_host_address=sessions[0].ext_host_address,
4651 ext_host_port=sessions[0].ext_host_port)
4652 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4653 self.assertEqual(len(sessions), 0)
4654
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004655 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004656 def test_static_lb_multi_clients(self):
4657 """ NAT44 local service load balancing - multiple clients"""
4658
4659 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4660 external_port = 80
4661 local_port = 8080
4662 server1 = self.pg0.remote_hosts[0]
4663 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004664 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004665
4666 locals = [{'addr': server1.ip4n,
4667 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004668 'probability': 90,
4669 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004670 {'addr': server2.ip4n,
4671 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004672 'probability': 10,
4673 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004674
4675 self.nat44_add_address(self.nat_addr)
4676 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4677 external_port,
4678 IP_PROTOS.tcp,
4679 local_num=len(locals),
4680 locals=locals)
4681 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4682 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4683 is_inside=0)
4684
4685 server1_n = 0
4686 server2_n = 0
4687 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4688 pkts = []
4689 for client in clients:
4690 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4691 IP(src=client, dst=self.nat_addr) /
4692 TCP(sport=12345, dport=external_port))
4693 pkts.append(p)
4694 self.pg1.add_stream(pkts)
4695 self.pg_enable_capture(self.pg_interfaces)
4696 self.pg_start()
4697 capture = self.pg0.get_capture(len(pkts))
4698 for p in capture:
4699 if p[IP].dst == server1.ip4:
4700 server1_n += 1
4701 else:
4702 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004703 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004704
Matus Fabianb6865082018-12-06 03:11:09 -08004705 # add new back-end
4706 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4707 external_port,
4708 server3.ip4n,
4709 local_port,
4710 IP_PROTOS.tcp,
4711 20)
4712 server1_n = 0
4713 server2_n = 0
4714 server3_n = 0
4715 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4716 pkts = []
4717 for client in clients:
4718 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4719 IP(src=client, dst=self.nat_addr) /
4720 TCP(sport=12346, dport=external_port))
4721 pkts.append(p)
4722 self.assertGreater(len(pkts), 0)
4723 self.pg1.add_stream(pkts)
4724 self.pg_enable_capture(self.pg_interfaces)
4725 self.pg_start()
4726 capture = self.pg0.get_capture(len(pkts))
4727 for p in capture:
4728 if p[IP].dst == server1.ip4:
4729 server1_n += 1
4730 elif p[IP].dst == server2.ip4:
4731 server2_n += 1
4732 else:
4733 server3_n += 1
4734 self.assertGreater(server1_n, 0)
4735 self.assertGreater(server2_n, 0)
4736 self.assertGreater(server3_n, 0)
4737
4738 # remove one back-end
4739 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4740 external_port,
4741 server2.ip4n,
4742 local_port,
4743 IP_PROTOS.tcp,
4744 10,
4745 is_add=0)
4746 server1_n = 0
4747 server2_n = 0
4748 server3_n = 0
4749 self.pg1.add_stream(pkts)
4750 self.pg_enable_capture(self.pg_interfaces)
4751 self.pg_start()
4752 capture = self.pg0.get_capture(len(pkts))
4753 for p in capture:
4754 if p[IP].dst == server1.ip4:
4755 server1_n += 1
4756 elif p[IP].dst == server2.ip4:
4757 server2_n += 1
4758 else:
4759 server3_n += 1
4760 self.assertGreater(server1_n, 0)
4761 self.assertEqual(server2_n, 0)
4762 self.assertGreater(server3_n, 0)
4763
Matus Fabiana6110b62018-06-13 05:39:07 -07004764 def test_static_lb_2(self):
4765 """ NAT44 local service load balancing (asymmetrical rule) """
4766 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4767 external_port = 80
4768 local_port = 8080
4769 server1 = self.pg0.remote_hosts[0]
4770 server2 = self.pg0.remote_hosts[1]
4771
4772 locals = [{'addr': server1.ip4n,
4773 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004774 'probability': 70,
4775 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004776 {'addr': server2.ip4n,
4777 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004778 'probability': 30,
4779 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004780
4781 self.vapi.nat44_forwarding_enable_disable(1)
4782 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4783 external_port,
4784 IP_PROTOS.tcp,
4785 out2in_only=1,
4786 local_num=len(locals),
4787 locals=locals)
4788 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4789 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4790 is_inside=0)
4791
4792 # from client to service
4793 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4794 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4795 TCP(sport=12345, dport=external_port))
4796 self.pg1.add_stream(p)
4797 self.pg_enable_capture(self.pg_interfaces)
4798 self.pg_start()
4799 capture = self.pg0.get_capture(1)
4800 p = capture[0]
4801 server = None
4802 try:
4803 ip = p[IP]
4804 tcp = p[TCP]
4805 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4806 if ip.dst == server1.ip4:
4807 server = server1
4808 else:
4809 server = server2
4810 self.assertEqual(tcp.dport, local_port)
4811 self.assert_packet_checksums_valid(p)
4812 except:
4813 self.logger.error(ppp("Unexpected or invalid packet:", p))
4814 raise
4815
4816 # from service back to client
4817 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4818 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4819 TCP(sport=local_port, dport=12345))
4820 self.pg0.add_stream(p)
4821 self.pg_enable_capture(self.pg_interfaces)
4822 self.pg_start()
4823 capture = self.pg1.get_capture(1)
4824 p = capture[0]
4825 try:
4826 ip = p[IP]
4827 tcp = p[TCP]
4828 self.assertEqual(ip.src, self.nat_addr)
4829 self.assertEqual(tcp.sport, external_port)
4830 self.assert_packet_checksums_valid(p)
4831 except:
4832 self.logger.error(ppp("Unexpected or invalid packet:", p))
4833 raise
4834
4835 # from client to server (no translation)
4836 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4837 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4838 TCP(sport=12346, dport=local_port))
4839 self.pg1.add_stream(p)
4840 self.pg_enable_capture(self.pg_interfaces)
4841 self.pg_start()
4842 capture = self.pg0.get_capture(1)
4843 p = capture[0]
4844 server = None
4845 try:
4846 ip = p[IP]
4847 tcp = p[TCP]
4848 self.assertEqual(ip.dst, server1.ip4)
4849 self.assertEqual(tcp.dport, local_port)
4850 self.assert_packet_checksums_valid(p)
4851 except:
4852 self.logger.error(ppp("Unexpected or invalid packet:", p))
4853 raise
4854
4855 # from service back to client (no translation)
4856 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4857 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4858 TCP(sport=local_port, dport=12346))
4859 self.pg0.add_stream(p)
4860 self.pg_enable_capture(self.pg_interfaces)
4861 self.pg_start()
4862 capture = self.pg1.get_capture(1)
4863 p = capture[0]
4864 try:
4865 ip = p[IP]
4866 tcp = p[TCP]
4867 self.assertEqual(ip.src, server1.ip4)
4868 self.assertEqual(tcp.sport, local_port)
4869 self.assert_packet_checksums_valid(p)
4870 except:
4871 self.logger.error(ppp("Unexpected or invalid packet:", p))
4872 raise
4873
Matus Fabianea5b5be2018-09-03 05:02:23 -07004874 def test_lb_affinity(self):
4875 """ NAT44 local service load balancing affinity """
4876 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4877 external_port = 80
4878 local_port = 8080
4879 server1 = self.pg0.remote_hosts[0]
4880 server2 = self.pg0.remote_hosts[1]
4881
4882 locals = [{'addr': server1.ip4n,
4883 'port': local_port,
4884 'probability': 50,
4885 'vrf_id': 0},
4886 {'addr': server2.ip4n,
4887 'port': local_port,
4888 'probability': 50,
4889 'vrf_id': 0}]
4890
4891 self.nat44_add_address(self.nat_addr)
4892 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4893 external_port,
4894 IP_PROTOS.tcp,
4895 affinity=10800,
4896 local_num=len(locals),
4897 locals=locals)
4898 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4899 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4900 is_inside=0)
4901
4902 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4903 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4904 TCP(sport=1025, dport=external_port))
4905 self.pg1.add_stream(p)
4906 self.pg_enable_capture(self.pg_interfaces)
4907 self.pg_start()
4908 capture = self.pg0.get_capture(1)
4909 backend = capture[0][IP].dst
4910
4911 sessions = self.vapi.nat44_user_session_dump(
4912 socket.inet_pton(socket.AF_INET, backend), 0)
4913 self.assertEqual(len(sessions), 1)
4914 self.assertTrue(sessions[0].ext_host_valid)
4915 self.vapi.nat44_del_session(
4916 sessions[0].inside_ip_address,
4917 sessions[0].inside_port,
4918 sessions[0].protocol,
4919 ext_host_address=sessions[0].ext_host_address,
4920 ext_host_port=sessions[0].ext_host_port)
4921
4922 pkts = []
4923 for port in range(1030, 1100):
4924 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4925 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4926 TCP(sport=port, dport=external_port))
4927 pkts.append(p)
4928 self.pg1.add_stream(pkts)
4929 self.pg_enable_capture(self.pg_interfaces)
4930 self.pg_start()
4931 capture = self.pg0.get_capture(len(pkts))
4932 for p in capture:
4933 self.assertEqual(p[IP].dst, backend)
4934
Matus Fabiana6110b62018-06-13 05:39:07 -07004935 def test_unknown_proto(self):
4936 """ NAT44 translate packet with unknown protocol """
4937 self.nat44_add_address(self.nat_addr)
4938 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4939 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4940 is_inside=0)
4941
4942 # in2out
4943 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4944 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4945 TCP(sport=self.tcp_port_in, dport=20))
4946 self.pg0.add_stream(p)
4947 self.pg_enable_capture(self.pg_interfaces)
4948 self.pg_start()
4949 p = self.pg1.get_capture(1)
4950
4951 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4952 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4953 GRE() /
4954 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4955 TCP(sport=1234, dport=1234))
4956 self.pg0.add_stream(p)
4957 self.pg_enable_capture(self.pg_interfaces)
4958 self.pg_start()
4959 p = self.pg1.get_capture(1)
4960 packet = p[0]
4961 try:
4962 self.assertEqual(packet[IP].src, self.nat_addr)
4963 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004964 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004965 self.assert_packet_checksums_valid(packet)
4966 except:
4967 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4968 raise
4969
4970 # out2in
4971 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4972 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4973 GRE() /
4974 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4975 TCP(sport=1234, dport=1234))
4976 self.pg1.add_stream(p)
4977 self.pg_enable_capture(self.pg_interfaces)
4978 self.pg_start()
4979 p = self.pg0.get_capture(1)
4980 packet = p[0]
4981 try:
4982 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4983 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004984 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004985 self.assert_packet_checksums_valid(packet)
4986 except:
4987 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4988 raise
4989
4990 def test_hairpinning_unknown_proto(self):
4991 """ NAT44 translate packet with unknown protocol - hairpinning """
4992 host = self.pg0.remote_hosts[0]
4993 server = self.pg0.remote_hosts[1]
4994 host_in_port = 1234
4995 server_out_port = 8765
4996 server_nat_ip = "10.0.0.11"
4997
4998 self.nat44_add_address(self.nat_addr)
4999 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5000 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5001 is_inside=0)
5002
5003 # add static mapping for server
5004 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5005
5006 # host to server
5007 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5008 IP(src=host.ip4, dst=server_nat_ip) /
5009 TCP(sport=host_in_port, dport=server_out_port))
5010 self.pg0.add_stream(p)
5011 self.pg_enable_capture(self.pg_interfaces)
5012 self.pg_start()
5013 self.pg0.get_capture(1)
5014
5015 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5016 IP(src=host.ip4, dst=server_nat_ip) /
5017 GRE() /
5018 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5019 TCP(sport=1234, dport=1234))
5020 self.pg0.add_stream(p)
5021 self.pg_enable_capture(self.pg_interfaces)
5022 self.pg_start()
5023 p = self.pg0.get_capture(1)
5024 packet = p[0]
5025 try:
5026 self.assertEqual(packet[IP].src, self.nat_addr)
5027 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005028 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005029 self.assert_packet_checksums_valid(packet)
5030 except:
5031 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5032 raise
5033
5034 # server to host
5035 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5036 IP(src=server.ip4, dst=self.nat_addr) /
5037 GRE() /
5038 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5039 TCP(sport=1234, dport=1234))
5040 self.pg0.add_stream(p)
5041 self.pg_enable_capture(self.pg_interfaces)
5042 self.pg_start()
5043 p = self.pg0.get_capture(1)
5044 packet = p[0]
5045 try:
5046 self.assertEqual(packet[IP].src, server_nat_ip)
5047 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005048 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005049 self.assert_packet_checksums_valid(packet)
5050 except:
5051 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5052 raise
5053
5054 def test_output_feature_and_service(self):
5055 """ NAT44 interface output feature and services """
5056 external_addr = '1.2.3.4'
5057 external_port = 80
5058 local_port = 8080
5059
5060 self.vapi.nat44_forwarding_enable_disable(1)
5061 self.nat44_add_address(self.nat_addr)
5062 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
5063 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5064 local_port, external_port,
5065 proto=IP_PROTOS.tcp, out2in_only=1)
5066 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5067 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5068 is_inside=0)
5069 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5070 is_inside=0)
5071
5072 # from client to service
5073 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5074 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5075 TCP(sport=12345, dport=external_port))
5076 self.pg1.add_stream(p)
5077 self.pg_enable_capture(self.pg_interfaces)
5078 self.pg_start()
5079 capture = self.pg0.get_capture(1)
5080 p = capture[0]
5081 try:
5082 ip = p[IP]
5083 tcp = p[TCP]
5084 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5085 self.assertEqual(tcp.dport, local_port)
5086 self.assert_packet_checksums_valid(p)
5087 except:
5088 self.logger.error(ppp("Unexpected or invalid packet:", p))
5089 raise
5090
5091 # from service back to client
5092 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5093 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5094 TCP(sport=local_port, dport=12345))
5095 self.pg0.add_stream(p)
5096 self.pg_enable_capture(self.pg_interfaces)
5097 self.pg_start()
5098 capture = self.pg1.get_capture(1)
5099 p = capture[0]
5100 try:
5101 ip = p[IP]
5102 tcp = p[TCP]
5103 self.assertEqual(ip.src, external_addr)
5104 self.assertEqual(tcp.sport, external_port)
5105 self.assert_packet_checksums_valid(p)
5106 except:
5107 self.logger.error(ppp("Unexpected or invalid packet:", p))
5108 raise
5109
5110 # from local network host to external network
5111 pkts = self.create_stream_in(self.pg0, self.pg1)
5112 self.pg0.add_stream(pkts)
5113 self.pg_enable_capture(self.pg_interfaces)
5114 self.pg_start()
5115 capture = self.pg1.get_capture(len(pkts))
5116 self.verify_capture_out(capture)
5117 pkts = self.create_stream_in(self.pg0, self.pg1)
5118 self.pg0.add_stream(pkts)
5119 self.pg_enable_capture(self.pg_interfaces)
5120 self.pg_start()
5121 capture = self.pg1.get_capture(len(pkts))
5122 self.verify_capture_out(capture)
5123
5124 # from external network back to local network host
5125 pkts = self.create_stream_out(self.pg1)
5126 self.pg1.add_stream(pkts)
5127 self.pg_enable_capture(self.pg_interfaces)
5128 self.pg_start()
5129 capture = self.pg0.get_capture(len(pkts))
5130 self.verify_capture_in(capture, self.pg0)
5131
5132 def test_output_feature_and_service2(self):
5133 """ NAT44 interface output feature and service host direct access """
5134 self.vapi.nat44_forwarding_enable_disable(1)
5135 self.nat44_add_address(self.nat_addr)
5136 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5137 is_inside=0)
5138
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005139 # session initiated from service host - translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005140 pkts = self.create_stream_in(self.pg0, self.pg1)
5141 self.pg0.add_stream(pkts)
5142 self.pg_enable_capture(self.pg_interfaces)
5143 self.pg_start()
5144 capture = self.pg1.get_capture(len(pkts))
5145 self.verify_capture_out(capture)
5146
5147 pkts = self.create_stream_out(self.pg1)
5148 self.pg1.add_stream(pkts)
5149 self.pg_enable_capture(self.pg_interfaces)
5150 self.pg_start()
5151 capture = self.pg0.get_capture(len(pkts))
5152 self.verify_capture_in(capture, self.pg0)
5153
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005154 # session initiated from remote host - do not translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005155 self.tcp_port_in = 60303
5156 self.udp_port_in = 60304
5157 self.icmp_id_in = 60305
5158 pkts = self.create_stream_out(self.pg1,
5159 self.pg0.remote_ip4,
5160 use_inside_ports=True)
5161 self.pg1.add_stream(pkts)
5162 self.pg_enable_capture(self.pg_interfaces)
5163 self.pg_start()
5164 capture = self.pg0.get_capture(len(pkts))
5165 self.verify_capture_in(capture, self.pg0)
5166
5167 pkts = self.create_stream_in(self.pg0, self.pg1)
5168 self.pg0.add_stream(pkts)
5169 self.pg_enable_capture(self.pg_interfaces)
5170 self.pg_start()
5171 capture = self.pg1.get_capture(len(pkts))
5172 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5173 same_port=True)
5174
5175 def test_output_feature_and_service3(self):
5176 """ NAT44 interface output feature and DST NAT """
5177 external_addr = '1.2.3.4'
5178 external_port = 80
5179 local_port = 8080
5180
5181 self.vapi.nat44_forwarding_enable_disable(1)
5182 self.nat44_add_address(self.nat_addr)
5183 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5184 local_port, external_port,
5185 proto=IP_PROTOS.tcp, out2in_only=1)
5186 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5187 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5188 is_inside=0)
5189 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5190 is_inside=0)
5191
5192 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5193 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5194 TCP(sport=12345, dport=external_port))
5195 self.pg0.add_stream(p)
5196 self.pg_enable_capture(self.pg_interfaces)
5197 self.pg_start()
5198 capture = self.pg1.get_capture(1)
5199 p = capture[0]
5200 try:
5201 ip = p[IP]
5202 tcp = p[TCP]
5203 self.assertEqual(ip.src, self.pg0.remote_ip4)
5204 self.assertEqual(tcp.sport, 12345)
5205 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5206 self.assertEqual(tcp.dport, local_port)
5207 self.assert_packet_checksums_valid(p)
5208 except:
5209 self.logger.error(ppp("Unexpected or invalid packet:", p))
5210 raise
5211
5212 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5213 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5214 TCP(sport=local_port, dport=12345))
5215 self.pg1.add_stream(p)
5216 self.pg_enable_capture(self.pg_interfaces)
5217 self.pg_start()
5218 capture = self.pg0.get_capture(1)
5219 p = capture[0]
5220 try:
5221 ip = p[IP]
5222 tcp = p[TCP]
5223 self.assertEqual(ip.src, external_addr)
5224 self.assertEqual(tcp.sport, external_port)
5225 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5226 self.assertEqual(tcp.dport, 12345)
5227 self.assert_packet_checksums_valid(p)
5228 except:
5229 self.logger.error(ppp("Unexpected or invalid packet:", p))
5230 raise
5231
Matus Fabian182e37e2018-08-14 04:21:26 -07005232 def test_next_src_nat(self):
5233 """ On way back forward packet to nat44-in2out node. """
5234 twice_nat_addr = '10.0.1.3'
5235 external_port = 80
5236 local_port = 8080
5237 post_twice_nat_port = 0
5238
5239 self.vapi.nat44_forwarding_enable_disable(1)
5240 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5241 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5242 local_port, external_port,
5243 proto=IP_PROTOS.tcp, out2in_only=1,
5244 self_twice_nat=1, vrf_id=1)
5245 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5246 is_inside=0)
5247
5248 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5249 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5250 TCP(sport=12345, dport=external_port))
5251 self.pg6.add_stream(p)
5252 self.pg_enable_capture(self.pg_interfaces)
5253 self.pg_start()
5254 capture = self.pg6.get_capture(1)
5255 p = capture[0]
5256 try:
5257 ip = p[IP]
5258 tcp = p[TCP]
5259 self.assertEqual(ip.src, twice_nat_addr)
5260 self.assertNotEqual(tcp.sport, 12345)
5261 post_twice_nat_port = tcp.sport
5262 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5263 self.assertEqual(tcp.dport, local_port)
5264 self.assert_packet_checksums_valid(p)
5265 except:
5266 self.logger.error(ppp("Unexpected or invalid packet:", p))
5267 raise
5268
5269 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5270 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5271 TCP(sport=local_port, dport=post_twice_nat_port))
5272 self.pg6.add_stream(p)
5273 self.pg_enable_capture(self.pg_interfaces)
5274 self.pg_start()
5275 capture = self.pg6.get_capture(1)
5276 p = capture[0]
5277 try:
5278 ip = p[IP]
5279 tcp = p[TCP]
5280 self.assertEqual(ip.src, self.pg1.remote_ip4)
5281 self.assertEqual(tcp.sport, external_port)
5282 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5283 self.assertEqual(tcp.dport, 12345)
5284 self.assert_packet_checksums_valid(p)
5285 except:
5286 self.logger.error(ppp("Unexpected or invalid packet:", p))
5287 raise
5288
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005289 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5290 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005291 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005292
Matus Fabianb932d262017-12-18 05:38:24 -08005293 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005294 if lb:
5295 if not same_pg:
5296 port_in1 = port_in
5297 port_in2 = port_in
5298 else:
Ole Troan9a475372019-03-05 16:58:24 +01005299 port_in1 = port_in + 1
5300 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005301
Matus Fabianb932d262017-12-18 05:38:24 -08005302 port_out = 80
5303 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005304
5305 server1 = self.pg0.remote_hosts[0]
5306 server2 = self.pg0.remote_hosts[1]
5307 if lb and same_pg:
5308 server2 = server1
5309 if not lb:
5310 server = server1
5311
5312 pg0 = self.pg0
5313 if same_pg:
5314 pg1 = self.pg0
5315 else:
5316 pg1 = self.pg1
5317
5318 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5319 client_id == 1)
5320
Matus Fabianb932d262017-12-18 05:38:24 -08005321 self.nat44_add_address(self.nat_addr)
5322 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005323 if not lb:
5324 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5325 port_in, port_out,
5326 proto=IP_PROTOS.tcp,
5327 twice_nat=int(not self_twice_nat),
5328 self_twice_nat=int(self_twice_nat))
5329 else:
5330 locals = [{'addr': server1.ip4n,
5331 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005332 'probability': 50,
5333 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005334 {'addr': server2.ip4n,
5335 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005336 'probability': 50,
5337 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005338 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
5339 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
5340 port_out,
5341 IP_PROTOS.tcp,
5342 twice_nat=int(
5343 not self_twice_nat),
5344 self_twice_nat=int(
5345 self_twice_nat),
5346 local_num=len(locals),
5347 locals=locals)
5348 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
5349 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08005350 is_inside=0)
5351
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005352 if same_pg:
5353 if not lb:
5354 client = server
5355 else:
5356 assert client_id is not None
5357 if client_id == 1:
5358 client = self.pg0.remote_hosts[0]
5359 elif client_id == 2:
5360 client = self.pg0.remote_hosts[1]
5361 else:
5362 client = pg1.remote_hosts[0]
5363 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5364 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005365 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005366 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005367 self.pg_enable_capture(self.pg_interfaces)
5368 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005369 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005370 p = capture[0]
5371 try:
5372 ip = p[IP]
5373 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005374 if lb:
5375 if ip.dst == server1.ip4:
5376 server = server1
5377 port_in = port_in1
5378 else:
5379 server = server2
5380 port_in = port_in2
5381 self.assertEqual(ip.dst, server.ip4)
5382 if lb and same_pg:
5383 self.assertIn(tcp.dport, [port_in1, port_in2])
5384 else:
5385 self.assertEqual(tcp.dport, port_in)
5386 if eh_translate:
5387 self.assertEqual(ip.src, twice_nat_addr)
5388 self.assertNotEqual(tcp.sport, eh_port_out)
5389 else:
5390 self.assertEqual(ip.src, client.ip4)
5391 self.assertEqual(tcp.sport, eh_port_out)
5392 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005393 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005394 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005395 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005396 except:
5397 self.logger.error(ppp("Unexpected or invalid packet:", p))
5398 raise
5399
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005400 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5401 IP(src=server.ip4, dst=eh_addr_in) /
5402 TCP(sport=saved_port_in, dport=eh_port_in))
5403 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005404 self.pg_enable_capture(self.pg_interfaces)
5405 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005406 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005407 p = capture[0]
5408 try:
5409 ip = p[IP]
5410 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005411 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005412 self.assertEqual(ip.src, self.nat_addr)
5413 self.assertEqual(tcp.dport, eh_port_out)
5414 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005415 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005416 except:
5417 self.logger.error(ppp("Unexpected or invalid packet:", p))
5418 raise
5419
Matus Fabian70a26ac2018-05-14 06:20:28 -07005420 if eh_translate:
5421 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5422 self.assertEqual(len(sessions), 1)
5423 self.assertTrue(sessions[0].ext_host_valid)
5424 self.assertTrue(sessions[0].is_twicenat)
5425 self.vapi.nat44_del_session(
5426 sessions[0].inside_ip_address,
5427 sessions[0].inside_port,
5428 sessions[0].protocol,
5429 ext_host_address=sessions[0].ext_host_nat_address,
5430 ext_host_port=sessions[0].ext_host_nat_port)
5431 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5432 self.assertEqual(len(sessions), 0)
5433
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005434 def test_twice_nat(self):
5435 """ Twice NAT44 """
5436 self.twice_nat_common()
5437
5438 def test_self_twice_nat_positive(self):
5439 """ Self Twice NAT44 (positive test) """
5440 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5441
5442 def test_self_twice_nat_negative(self):
5443 """ Self Twice NAT44 (negative test) """
5444 self.twice_nat_common(self_twice_nat=True)
5445
Matus Fabianb932d262017-12-18 05:38:24 -08005446 def test_twice_nat_lb(self):
5447 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005448 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005449
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005450 def test_self_twice_nat_lb_positive(self):
5451 """ Self Twice NAT44 local service load balancing (positive test) """
5452 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5453 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005454
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005455 def test_self_twice_nat_lb_negative(self):
5456 """ Self Twice NAT44 local service load balancing (negative test) """
5457 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5458 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005459
5460 def test_twice_nat_interface_addr(self):
5461 """ Acquire twice NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01005462 self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
5463 twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005464
5465 # no address in NAT pool
5466 adresses = self.vapi.nat44_address_dump()
5467 self.assertEqual(0, len(adresses))
5468
5469 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005470 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005471 adresses = self.vapi.nat44_address_dump()
5472 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07005473 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08005474 self.assertEqual(adresses[0].twice_nat, 1)
5475
5476 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005477 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005478 adresses = self.vapi.nat44_address_dump()
5479 self.assertEqual(0, len(adresses))
5480
Matus Fabian6c01dce2018-11-16 04:41:31 -08005481 def test_tcp_close(self):
5482 """ Close TCP session from inside network - output feature """
5483 self.vapi.nat44_forwarding_enable_disable(1)
5484 self.nat44_add_address(self.pg1.local_ip4)
5485 twice_nat_addr = '10.0.1.3'
5486 service_ip = '192.168.16.150'
5487 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5488 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5489 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5490 is_inside=0)
5491 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5492 is_inside=0)
5493 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5494 service_ip,
5495 80,
5496 80,
5497 proto=IP_PROTOS.tcp,
5498 out2in_only=1,
5499 twice_nat=1)
5500 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5501 start_sessnum = len(sessions)
5502
5503 # SYN packet out->in
5504 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5505 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5506 TCP(sport=33898, dport=80, flags="S"))
5507 self.pg1.add_stream(p)
5508 self.pg_enable_capture(self.pg_interfaces)
5509 self.pg_start()
5510 capture = self.pg0.get_capture(1)
5511 p = capture[0]
5512 tcp_port = p[TCP].sport
5513
5514 # SYN + ACK packet in->out
5515 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5516 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5517 TCP(sport=80, dport=tcp_port, flags="SA"))
5518 self.pg0.add_stream(p)
5519 self.pg_enable_capture(self.pg_interfaces)
5520 self.pg_start()
5521 self.pg1.get_capture(1)
5522
5523 # ACK packet out->in
5524 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5525 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5526 TCP(sport=33898, dport=80, flags="A"))
5527 self.pg1.add_stream(p)
5528 self.pg_enable_capture(self.pg_interfaces)
5529 self.pg_start()
5530 self.pg0.get_capture(1)
5531
5532 # FIN packet in -> out
5533 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5534 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5535 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5536 self.pg0.add_stream(p)
5537 self.pg_enable_capture(self.pg_interfaces)
5538 self.pg_start()
5539 self.pg1.get_capture(1)
5540
5541 # FIN+ACK packet out -> in
5542 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5543 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5544 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5545 self.pg1.add_stream(p)
5546 self.pg_enable_capture(self.pg_interfaces)
5547 self.pg_start()
5548 self.pg0.get_capture(1)
5549
5550 # ACK packet in -> out
5551 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5552 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5553 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5554 self.pg0.add_stream(p)
5555 self.pg_enable_capture(self.pg_interfaces)
5556 self.pg_start()
5557 self.pg1.get_capture(1)
5558
5559 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5560 0)
5561 self.assertEqual(len(sessions) - start_sessnum, 0)
5562
Matus Fabianebdf1902018-05-04 03:57:42 -07005563 def test_tcp_session_close_in(self):
5564 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005565 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005566 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005567 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5568 self.nat_addr,
5569 self.tcp_port_in,
5570 self.tcp_port_out,
5571 proto=IP_PROTOS.tcp,
5572 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005573 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5574 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5575 is_inside=0)
5576
5577 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5578 start_sessnum = len(sessions)
5579
5580 self.initiate_tcp_session(self.pg0, self.pg1)
5581
Matus Fabian229c1aa2018-05-28 04:09:52 -07005582 # FIN packet in -> out
5583 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5584 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5585 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5586 flags="FA", seq=100, ack=300))
5587 self.pg0.add_stream(p)
5588 self.pg_enable_capture(self.pg_interfaces)
5589 self.pg_start()
5590 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005591
Matus Fabian229c1aa2018-05-28 04:09:52 -07005592 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005593
Matus Fabian229c1aa2018-05-28 04:09:52 -07005594 # ACK packet out -> in
5595 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5596 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5597 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5598 flags="A", seq=300, ack=101))
5599 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005600
Matus Fabian229c1aa2018-05-28 04:09:52 -07005601 # FIN packet out -> in
5602 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5603 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5604 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5605 flags="FA", seq=300, ack=101))
5606 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005607
Matus Fabian229c1aa2018-05-28 04:09:52 -07005608 self.pg1.add_stream(pkts)
5609 self.pg_enable_capture(self.pg_interfaces)
5610 self.pg_start()
5611 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005612
Matus Fabian229c1aa2018-05-28 04:09:52 -07005613 # ACK packet in -> out
5614 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5615 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5616 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5617 flags="A", seq=101, ack=301))
5618 self.pg0.add_stream(p)
5619 self.pg_enable_capture(self.pg_interfaces)
5620 self.pg_start()
5621 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005622
Matus Fabian229c1aa2018-05-28 04:09:52 -07005623 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5624 0)
5625 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005626
5627 def test_tcp_session_close_out(self):
5628 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005629 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005630 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005631 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5632 self.nat_addr,
5633 self.tcp_port_in,
5634 self.tcp_port_out,
5635 proto=IP_PROTOS.tcp,
5636 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005637 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5638 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5639 is_inside=0)
5640
5641 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5642 start_sessnum = len(sessions)
5643
5644 self.initiate_tcp_session(self.pg0, self.pg1)
5645
Matus Fabian229c1aa2018-05-28 04:09:52 -07005646 # FIN packet out -> in
5647 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5648 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5649 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5650 flags="FA", seq=100, ack=300))
5651 self.pg1.add_stream(p)
5652 self.pg_enable_capture(self.pg_interfaces)
5653 self.pg_start()
5654 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005655
Matus Fabian229c1aa2018-05-28 04:09:52 -07005656 # FIN+ACK packet in -> out
5657 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5658 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5659 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5660 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005661
Matus Fabian229c1aa2018-05-28 04:09:52 -07005662 self.pg0.add_stream(p)
5663 self.pg_enable_capture(self.pg_interfaces)
5664 self.pg_start()
5665 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005666
Matus Fabian229c1aa2018-05-28 04:09:52 -07005667 # ACK packet out -> in
5668 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5669 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5670 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5671 flags="A", seq=101, ack=301))
5672 self.pg1.add_stream(p)
5673 self.pg_enable_capture(self.pg_interfaces)
5674 self.pg_start()
5675 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005676
Matus Fabian229c1aa2018-05-28 04:09:52 -07005677 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5678 0)
5679 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005680
5681 def test_tcp_session_close_simultaneous(self):
5682 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005683 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005684 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005685 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5686 self.nat_addr,
5687 self.tcp_port_in,
5688 self.tcp_port_out,
5689 proto=IP_PROTOS.tcp,
5690 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005691 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5692 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5693 is_inside=0)
5694
5695 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5696 start_sessnum = len(sessions)
5697
5698 self.initiate_tcp_session(self.pg0, self.pg1)
5699
Matus Fabian229c1aa2018-05-28 04:09:52 -07005700 # FIN packet in -> out
5701 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5702 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5703 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5704 flags="FA", seq=100, ack=300))
5705 self.pg0.add_stream(p)
5706 self.pg_enable_capture(self.pg_interfaces)
5707 self.pg_start()
5708 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005709
Matus Fabian229c1aa2018-05-28 04:09:52 -07005710 # FIN packet out -> in
5711 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5712 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5713 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5714 flags="FA", seq=300, ack=100))
5715 self.pg1.add_stream(p)
5716 self.pg_enable_capture(self.pg_interfaces)
5717 self.pg_start()
5718 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005719
Matus Fabian229c1aa2018-05-28 04:09:52 -07005720 # ACK packet in -> out
5721 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5722 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5723 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5724 flags="A", seq=101, ack=301))
5725 self.pg0.add_stream(p)
5726 self.pg_enable_capture(self.pg_interfaces)
5727 self.pg_start()
5728 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005729
Matus Fabian229c1aa2018-05-28 04:09:52 -07005730 # ACK packet out -> in
5731 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5732 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5733 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5734 flags="A", seq=301, ack=101))
5735 self.pg1.add_stream(p)
5736 self.pg_enable_capture(self.pg_interfaces)
5737 self.pg_start()
5738 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005739
Matus Fabian229c1aa2018-05-28 04:09:52 -07005740 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5741 0)
5742 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005743
Matus Fabiana6110b62018-06-13 05:39:07 -07005744 def test_one_armed_nat44_static(self):
5745 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5746 remote_host = self.pg4.remote_hosts[0]
5747 local_host = self.pg4.remote_hosts[1]
5748 external_port = 80
5749 local_port = 8080
5750 eh_port_in = 0
5751
5752 self.vapi.nat44_forwarding_enable_disable(1)
5753 self.nat44_add_address(self.nat_addr, twice_nat=1)
5754 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5755 local_port, external_port,
5756 proto=IP_PROTOS.tcp, out2in_only=1,
5757 twice_nat=1)
5758 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5759 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5760 is_inside=0)
5761
5762 # from client to service
5763 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5764 IP(src=remote_host.ip4, dst=self.nat_addr) /
5765 TCP(sport=12345, dport=external_port))
5766 self.pg4.add_stream(p)
5767 self.pg_enable_capture(self.pg_interfaces)
5768 self.pg_start()
5769 capture = self.pg4.get_capture(1)
5770 p = capture[0]
5771 try:
5772 ip = p[IP]
5773 tcp = p[TCP]
5774 self.assertEqual(ip.dst, local_host.ip4)
5775 self.assertEqual(ip.src, self.nat_addr)
5776 self.assertEqual(tcp.dport, local_port)
5777 self.assertNotEqual(tcp.sport, 12345)
5778 eh_port_in = tcp.sport
5779 self.assert_packet_checksums_valid(p)
5780 except:
5781 self.logger.error(ppp("Unexpected or invalid packet:", p))
5782 raise
5783
5784 # from service back to client
5785 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5786 IP(src=local_host.ip4, dst=self.nat_addr) /
5787 TCP(sport=local_port, dport=eh_port_in))
5788 self.pg4.add_stream(p)
5789 self.pg_enable_capture(self.pg_interfaces)
5790 self.pg_start()
5791 capture = self.pg4.get_capture(1)
5792 p = capture[0]
5793 try:
5794 ip = p[IP]
5795 tcp = p[TCP]
5796 self.assertEqual(ip.src, self.nat_addr)
5797 self.assertEqual(ip.dst, remote_host.ip4)
5798 self.assertEqual(tcp.sport, external_port)
5799 self.assertEqual(tcp.dport, 12345)
5800 self.assert_packet_checksums_valid(p)
5801 except:
5802 self.logger.error(ppp("Unexpected or invalid packet:", p))
5803 raise
5804
5805 def test_static_with_port_out2(self):
5806 """ 1:1 NAPT asymmetrical rule """
5807
5808 external_port = 80
5809 local_port = 8080
5810
5811 self.vapi.nat44_forwarding_enable_disable(1)
5812 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5813 local_port, external_port,
5814 proto=IP_PROTOS.tcp, out2in_only=1)
5815 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5816 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5817 is_inside=0)
5818
5819 # from client to service
5820 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5821 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5822 TCP(sport=12345, dport=external_port))
5823 self.pg1.add_stream(p)
5824 self.pg_enable_capture(self.pg_interfaces)
5825 self.pg_start()
5826 capture = self.pg0.get_capture(1)
5827 p = capture[0]
5828 try:
5829 ip = p[IP]
5830 tcp = p[TCP]
5831 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5832 self.assertEqual(tcp.dport, local_port)
5833 self.assert_packet_checksums_valid(p)
5834 except:
5835 self.logger.error(ppp("Unexpected or invalid packet:", p))
5836 raise
5837
5838 # ICMP error
5839 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5840 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5841 ICMP(type=11) / capture[0][IP])
5842 self.pg0.add_stream(p)
5843 self.pg_enable_capture(self.pg_interfaces)
5844 self.pg_start()
5845 capture = self.pg1.get_capture(1)
5846 p = capture[0]
5847 try:
5848 self.assertEqual(p[IP].src, self.nat_addr)
5849 inner = p[IPerror]
5850 self.assertEqual(inner.dst, self.nat_addr)
5851 self.assertEqual(inner[TCPerror].dport, external_port)
5852 except:
5853 self.logger.error(ppp("Unexpected or invalid packet:", p))
5854 raise
5855
5856 # from service back to client
5857 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5858 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5859 TCP(sport=local_port, dport=12345))
5860 self.pg0.add_stream(p)
5861 self.pg_enable_capture(self.pg_interfaces)
5862 self.pg_start()
5863 capture = self.pg1.get_capture(1)
5864 p = capture[0]
5865 try:
5866 ip = p[IP]
5867 tcp = p[TCP]
5868 self.assertEqual(ip.src, self.nat_addr)
5869 self.assertEqual(tcp.sport, external_port)
5870 self.assert_packet_checksums_valid(p)
5871 except:
5872 self.logger.error(ppp("Unexpected or invalid packet:", p))
5873 raise
5874
5875 # ICMP error
5876 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5877 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5878 ICMP(type=11) / capture[0][IP])
5879 self.pg1.add_stream(p)
5880 self.pg_enable_capture(self.pg_interfaces)
5881 self.pg_start()
5882 capture = self.pg0.get_capture(1)
5883 p = capture[0]
5884 try:
5885 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5886 inner = p[IPerror]
5887 self.assertEqual(inner.src, self.pg0.remote_ip4)
5888 self.assertEqual(inner[TCPerror].sport, local_port)
5889 except:
5890 self.logger.error(ppp("Unexpected or invalid packet:", p))
5891 raise
5892
5893 # from client to server (no translation)
5894 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5895 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5896 TCP(sport=12346, dport=local_port))
5897 self.pg1.add_stream(p)
5898 self.pg_enable_capture(self.pg_interfaces)
5899 self.pg_start()
5900 capture = self.pg0.get_capture(1)
5901 p = capture[0]
5902 try:
5903 ip = p[IP]
5904 tcp = p[TCP]
5905 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5906 self.assertEqual(tcp.dport, local_port)
5907 self.assert_packet_checksums_valid(p)
5908 except:
5909 self.logger.error(ppp("Unexpected or invalid packet:", p))
5910 raise
5911
5912 # from service back to client (no translation)
5913 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5914 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5915 TCP(sport=local_port, dport=12346))
5916 self.pg0.add_stream(p)
5917 self.pg_enable_capture(self.pg_interfaces)
5918 self.pg_start()
5919 capture = self.pg1.get_capture(1)
5920 p = capture[0]
5921 try:
5922 ip = p[IP]
5923 tcp = p[TCP]
5924 self.assertEqual(ip.src, self.pg0.remote_ip4)
5925 self.assertEqual(tcp.sport, local_port)
5926 self.assert_packet_checksums_valid(p)
5927 except:
5928 self.logger.error(ppp("Unexpected or invalid packet:", p))
5929 raise
5930
Matus Fabian235a47e2018-06-25 16:42:36 -07005931 def test_output_feature(self):
5932 """ NAT44 interface output feature (in2out postrouting) """
5933 self.vapi.nat44_forwarding_enable_disable(1)
5934 self.nat44_add_address(self.nat_addr)
5935 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5936 is_inside=0)
5937 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5938 is_inside=0)
5939
5940 # in2out
5941 pkts = self.create_stream_in(self.pg0, self.pg1)
5942 self.pg0.add_stream(pkts)
5943 self.pg_enable_capture(self.pg_interfaces)
5944 self.pg_start()
5945 capture = self.pg1.get_capture(len(pkts))
5946 self.verify_capture_out(capture)
5947
5948 # out2in
5949 pkts = self.create_stream_out(self.pg1)
5950 self.pg1.add_stream(pkts)
5951 self.pg_enable_capture(self.pg_interfaces)
5952 self.pg_start()
5953 capture = self.pg0.get_capture(len(pkts))
5954 self.verify_capture_in(capture, self.pg0)
5955
Matus Fabian8008d7c2018-07-09 01:34:20 -07005956 def test_multiple_vrf(self):
5957 """ Multiple VRF setup """
5958 external_addr = '1.2.3.4'
5959 external_port = 80
5960 local_port = 8080
5961 port = 0
5962
5963 self.vapi.nat44_forwarding_enable_disable(1)
5964 self.nat44_add_address(self.nat_addr)
5965 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5966 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5967 is_inside=0)
5968 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5969 is_inside=0)
5970 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5971 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5972 is_inside=0)
5973 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5974 is_inside=0)
5975 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5976 local_port, external_port, vrf_id=1,
5977 proto=IP_PROTOS.tcp, out2in_only=1)
5978 self.nat44_add_static_mapping(
Ole Troan9a475372019-03-05 16:58:24 +01005979 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5980 local_port=local_port, vrf_id=0, external_port=external_port,
5981 proto=IP_PROTOS.tcp, out2in_only=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07005982
5983 # from client to service (both VRF1)
5984 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5985 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5986 TCP(sport=12345, dport=external_port))
5987 self.pg6.add_stream(p)
5988 self.pg_enable_capture(self.pg_interfaces)
5989 self.pg_start()
5990 capture = self.pg5.get_capture(1)
5991 p = capture[0]
5992 try:
5993 ip = p[IP]
5994 tcp = p[TCP]
5995 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5996 self.assertEqual(tcp.dport, local_port)
5997 self.assert_packet_checksums_valid(p)
5998 except:
5999 self.logger.error(ppp("Unexpected or invalid packet:", p))
6000 raise
6001
6002 # from service back to client (both VRF1)
6003 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6004 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6005 TCP(sport=local_port, dport=12345))
6006 self.pg5.add_stream(p)
6007 self.pg_enable_capture(self.pg_interfaces)
6008 self.pg_start()
6009 capture = self.pg6.get_capture(1)
6010 p = capture[0]
6011 try:
6012 ip = p[IP]
6013 tcp = p[TCP]
6014 self.assertEqual(ip.src, external_addr)
6015 self.assertEqual(tcp.sport, external_port)
6016 self.assert_packet_checksums_valid(p)
6017 except:
6018 self.logger.error(ppp("Unexpected or invalid packet:", p))
6019 raise
6020
6021 # dynamic NAT from VRF1 to VRF0 (output-feature)
6022 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6023 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6024 TCP(sport=2345, dport=22))
6025 self.pg5.add_stream(p)
6026 self.pg_enable_capture(self.pg_interfaces)
6027 self.pg_start()
6028 capture = self.pg1.get_capture(1)
6029 p = capture[0]
6030 try:
6031 ip = p[IP]
6032 tcp = p[TCP]
6033 self.assertEqual(ip.src, self.nat_addr)
6034 self.assertNotEqual(tcp.sport, 2345)
6035 self.assert_packet_checksums_valid(p)
6036 port = tcp.sport
6037 except:
6038 self.logger.error(ppp("Unexpected or invalid packet:", p))
6039 raise
6040
6041 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6042 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6043 TCP(sport=22, dport=port))
6044 self.pg1.add_stream(p)
6045 self.pg_enable_capture(self.pg_interfaces)
6046 self.pg_start()
6047 capture = self.pg5.get_capture(1)
6048 p = capture[0]
6049 try:
6050 ip = p[IP]
6051 tcp = p[TCP]
6052 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6053 self.assertEqual(tcp.dport, 2345)
6054 self.assert_packet_checksums_valid(p)
6055 except:
6056 self.logger.error(ppp("Unexpected or invalid packet:", p))
6057 raise
6058
6059 # from client VRF1 to service VRF0
6060 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6061 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6062 TCP(sport=12346, dport=external_port))
6063 self.pg6.add_stream(p)
6064 self.pg_enable_capture(self.pg_interfaces)
6065 self.pg_start()
6066 capture = self.pg0.get_capture(1)
6067 p = capture[0]
6068 try:
6069 ip = p[IP]
6070 tcp = p[TCP]
6071 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6072 self.assertEqual(tcp.dport, local_port)
6073 self.assert_packet_checksums_valid(p)
6074 except:
6075 self.logger.error(ppp("Unexpected or invalid packet:", p))
6076 raise
6077
6078 # from service VRF0 back to client VRF1
6079 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6080 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6081 TCP(sport=local_port, dport=12346))
6082 self.pg0.add_stream(p)
6083 self.pg_enable_capture(self.pg_interfaces)
6084 self.pg_start()
6085 capture = self.pg6.get_capture(1)
6086 p = capture[0]
6087 try:
6088 ip = p[IP]
6089 tcp = p[TCP]
6090 self.assertEqual(ip.src, self.pg0.local_ip4)
6091 self.assertEqual(tcp.sport, external_port)
6092 self.assert_packet_checksums_valid(p)
6093 except:
6094 self.logger.error(ppp("Unexpected or invalid packet:", p))
6095 raise
6096
6097 # from client VRF0 to service VRF1
6098 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6099 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6100 TCP(sport=12347, dport=external_port))
6101 self.pg0.add_stream(p)
6102 self.pg_enable_capture(self.pg_interfaces)
6103 self.pg_start()
6104 capture = self.pg5.get_capture(1)
6105 p = capture[0]
6106 try:
6107 ip = p[IP]
6108 tcp = p[TCP]
6109 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6110 self.assertEqual(tcp.dport, local_port)
6111 self.assert_packet_checksums_valid(p)
6112 except:
6113 self.logger.error(ppp("Unexpected or invalid packet:", p))
6114 raise
6115
6116 # from service VRF1 back to client VRF0
6117 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6118 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6119 TCP(sport=local_port, dport=12347))
6120 self.pg5.add_stream(p)
6121 self.pg_enable_capture(self.pg_interfaces)
6122 self.pg_start()
6123 capture = self.pg0.get_capture(1)
6124 p = capture[0]
6125 try:
6126 ip = p[IP]
6127 tcp = p[TCP]
6128 self.assertEqual(ip.src, external_addr)
6129 self.assertEqual(tcp.sport, external_port)
6130 self.assert_packet_checksums_valid(p)
6131 except:
6132 self.logger.error(ppp("Unexpected or invalid packet:", p))
6133 raise
6134
6135 # from client to server (both VRF1, no translation)
6136 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6137 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6138 TCP(sport=12348, dport=local_port))
6139 self.pg6.add_stream(p)
6140 self.pg_enable_capture(self.pg_interfaces)
6141 self.pg_start()
6142 capture = self.pg5.get_capture(1)
6143 p = capture[0]
6144 try:
6145 ip = p[IP]
6146 tcp = p[TCP]
6147 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6148 self.assertEqual(tcp.dport, local_port)
6149 self.assert_packet_checksums_valid(p)
6150 except:
6151 self.logger.error(ppp("Unexpected or invalid packet:", p))
6152 raise
6153
6154 # from server back to client (both VRF1, no translation)
6155 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6156 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6157 TCP(sport=local_port, dport=12348))
6158 self.pg5.add_stream(p)
6159 self.pg_enable_capture(self.pg_interfaces)
6160 self.pg_start()
6161 capture = self.pg6.get_capture(1)
6162 p = capture[0]
6163 try:
6164 ip = p[IP]
6165 tcp = p[TCP]
6166 self.assertEqual(ip.src, self.pg5.remote_ip4)
6167 self.assertEqual(tcp.sport, local_port)
6168 self.assert_packet_checksums_valid(p)
6169 except:
6170 self.logger.error(ppp("Unexpected or invalid packet:", p))
6171 raise
6172
6173 # from client VRF1 to server VRF0 (no translation)
6174 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6175 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6176 TCP(sport=local_port, dport=12349))
6177 self.pg0.add_stream(p)
6178 self.pg_enable_capture(self.pg_interfaces)
6179 self.pg_start()
6180 capture = self.pg6.get_capture(1)
6181 p = capture[0]
6182 try:
6183 ip = p[IP]
6184 tcp = p[TCP]
6185 self.assertEqual(ip.src, self.pg0.remote_ip4)
6186 self.assertEqual(tcp.sport, local_port)
6187 self.assert_packet_checksums_valid(p)
6188 except:
6189 self.logger.error(ppp("Unexpected or invalid packet:", p))
6190 raise
6191
6192 # from server VRF0 back to client VRF1 (no translation)
6193 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6194 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6195 TCP(sport=local_port, dport=12349))
6196 self.pg0.add_stream(p)
6197 self.pg_enable_capture(self.pg_interfaces)
6198 self.pg_start()
6199 capture = self.pg6.get_capture(1)
6200 p = capture[0]
6201 try:
6202 ip = p[IP]
6203 tcp = p[TCP]
6204 self.assertEqual(ip.src, self.pg0.remote_ip4)
6205 self.assertEqual(tcp.sport, local_port)
6206 self.assert_packet_checksums_valid(p)
6207 except:
6208 self.logger.error(ppp("Unexpected or invalid packet:", p))
6209 raise
6210
6211 # from client VRF0 to server VRF1 (no translation)
6212 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6213 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6214 TCP(sport=12344, dport=local_port))
6215 self.pg0.add_stream(p)
6216 self.pg_enable_capture(self.pg_interfaces)
6217 self.pg_start()
6218 capture = self.pg5.get_capture(1)
6219 p = capture[0]
6220 try:
6221 ip = p[IP]
6222 tcp = p[TCP]
6223 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6224 self.assertEqual(tcp.dport, local_port)
6225 self.assert_packet_checksums_valid(p)
6226 except:
6227 self.logger.error(ppp("Unexpected or invalid packet:", p))
6228 raise
6229
6230 # from server VRF1 back to client VRF0 (no translation)
6231 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6232 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6233 TCP(sport=local_port, dport=12344))
6234 self.pg5.add_stream(p)
6235 self.pg_enable_capture(self.pg_interfaces)
6236 self.pg_start()
6237 capture = self.pg0.get_capture(1)
6238 p = capture[0]
6239 try:
6240 ip = p[IP]
6241 tcp = p[TCP]
6242 self.assertEqual(ip.src, self.pg5.remote_ip4)
6243 self.assertEqual(tcp.sport, local_port)
6244 self.assert_packet_checksums_valid(p)
6245 except:
6246 self.logger.error(ppp("Unexpected or invalid packet:", p))
6247 raise
6248
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006249 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006250 def test_session_timeout(self):
6251 """ NAT44 session timeouts """
6252 self.nat44_add_address(self.nat_addr)
6253 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6254 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6255 is_inside=0)
6256 self.vapi.nat_set_timeouts(icmp=5)
6257
6258 max_sessions = 1000
6259 pkts = []
6260 for i in range(0, max_sessions):
6261 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6262 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6263 IP(src=src, dst=self.pg1.remote_ip4) /
6264 ICMP(id=1025, type='echo-request'))
6265 pkts.append(p)
6266 self.pg0.add_stream(pkts)
6267 self.pg_enable_capture(self.pg_interfaces)
6268 self.pg_start()
6269 self.pg1.get_capture(max_sessions)
6270
6271 sleep(10)
6272
6273 pkts = []
6274 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006275 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006276 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6277 IP(src=src, dst=self.pg1.remote_ip4) /
6278 ICMP(id=1026, type='echo-request'))
6279 pkts.append(p)
6280 self.pg0.add_stream(pkts)
6281 self.pg_enable_capture(self.pg_interfaces)
6282 self.pg_start()
6283 self.pg1.get_capture(max_sessions)
6284
6285 nsessions = 0
6286 users = self.vapi.nat44_user_dump()
6287 for user in users:
6288 nsessions = nsessions + user.nsessions
6289 self.assertLess(nsessions, 2 * max_sessions)
6290
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006291 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006292 def test_session_rst_timeout(self):
6293 """ NAT44 session RST timeouts """
6294 self.nat44_add_address(self.nat_addr)
6295 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6296 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6297 is_inside=0)
6298 self.vapi.nat_set_timeouts(tcp_transitory=5)
6299
Matus Fabian15e8e682018-11-21 04:53:10 -08006300 self.initiate_tcp_session(self.pg0, self.pg1)
6301 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6302 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6303 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6304 flags="R"))
6305 self.pg0.add_stream(p)
6306 self.pg_enable_capture(self.pg_interfaces)
6307 self.pg_start()
6308 self.pg1.get_capture(1)
6309
Matus Fabian15e8e682018-11-21 04:53:10 -08006310 sleep(6)
6311
6312 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6313 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6314 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6315 flags="S"))
6316 self.pg0.add_stream(p)
6317 self.pg_enable_capture(self.pg_interfaces)
6318 self.pg_start()
6319 self.pg1.get_capture(1)
6320
6321 nsessions = 0
6322 users = self.vapi.nat44_user_dump()
6323 self.assertEqual(len(users), 1)
6324 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006325 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006326
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006327 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006328 def test_session_limit_per_user(self):
6329 """ Maximum sessions per user limit """
6330 self.nat44_add_address(self.nat_addr)
6331 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6332 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6333 is_inside=0)
6334 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6335 src_address=self.pg2.local_ip4n,
6336 path_mtu=512,
6337 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07006338 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006339
6340 # get maximum number of translations per user
6341 nat44_config = self.vapi.nat_show_config()
6342
6343 pkts = []
6344 for port in range(0, nat44_config.max_translations_per_user):
6345 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6346 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6347 UDP(sport=1025 + port, dport=1025 + port))
6348 pkts.append(p)
6349
6350 self.pg0.add_stream(pkts)
6351 self.pg_enable_capture(self.pg_interfaces)
6352 self.pg_start()
6353 capture = self.pg1.get_capture(len(pkts))
6354
Ole Troane1ade682019-03-04 23:55:43 +01006355 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6356 src_port=self.ipfix_src_port)
Matus Fabian878c6462018-08-23 00:33:35 -07006357
6358 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6359 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6360 UDP(sport=3001, dport=3002))
6361 self.pg0.add_stream(p)
6362 self.pg_enable_capture(self.pg_interfaces)
6363 self.pg_start()
6364 capture = self.pg1.assert_nothing_captured()
6365
6366 # verify IPFIX logging
6367 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6368 sleep(1)
6369 capture = self.pg2.get_capture(10)
6370 ipfix = IPFIXDecoder()
6371 # first load template
6372 for p in capture:
6373 self.assertTrue(p.haslayer(IPFIX))
6374 if p.haslayer(Template):
6375 ipfix.add_template(p.getlayer(Template))
6376 # verify events in data set
6377 for p in capture:
6378 if p.haslayer(Data):
6379 data = ipfix.decode_data_set(p.getlayer(Set))
6380 self.verify_ipfix_max_entries_per_user(
6381 data,
6382 nat44_config.max_translations_per_user,
6383 self.pg0.remote_ip4n)
6384
Matus Fabian8fdc0152018-09-24 04:41:28 -07006385 sleep(6)
6386 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6387 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6388 UDP(sport=3001, dport=3002))
6389 self.pg0.add_stream(p)
6390 self.pg_enable_capture(self.pg_interfaces)
6391 self.pg_start()
6392 self.pg1.get_capture(1)
6393
Matus Fabianad1f3e12018-11-28 21:26:34 -08006394 def test_syslog_sess(self):
6395 """ Test syslog session creation and deletion """
6396 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006397 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006398 self.nat44_add_address(self.nat_addr)
6399 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6400 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6401 is_inside=0)
6402
6403 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6404 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6405 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6406 self.pg0.add_stream(p)
6407 self.pg_enable_capture(self.pg_interfaces)
6408 self.pg_start()
6409 capture = self.pg1.get_capture(1)
6410 self.tcp_port_out = capture[0][TCP].sport
6411 capture = self.pg2.get_capture(1)
6412 self.verify_syslog_sess(capture[0][Raw].load)
6413
6414 self.pg_enable_capture(self.pg_interfaces)
6415 self.pg_start()
6416 self.nat44_add_address(self.nat_addr, is_add=0)
6417 capture = self.pg2.get_capture(1)
6418 self.verify_syslog_sess(capture[0][Raw].load, False)
6419
Matus Fabiande886752016-12-07 03:38:19 -08006420 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006421 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006422 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006423 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006424 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006425
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07006426 def show_commands_at_teardown(self):
6427 self.logger.info(self.vapi.cli("show nat44 addresses"))
6428 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6429 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6430 self.logger.info(self.vapi.cli("show nat44 interface address"))
6431 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6432 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6433 self.logger.info(self.vapi.cli("show nat timeouts"))
6434
Matus Fabianeea28d72017-01-13 04:15:54 -08006435
Juraj Slobodacba69362017-12-19 02:09:32 +01006436class TestNAT44Out2InDPO(MethodHolder):
6437 """ NAT44 Test Cases using out2in DPO """
6438
6439 @classmethod
6440 def setUpConstants(cls):
6441 super(TestNAT44Out2InDPO, cls).setUpConstants()
6442 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6443
6444 @classmethod
6445 def setUpClass(cls):
6446 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006447 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006448
6449 try:
6450 cls.tcp_port_in = 6303
6451 cls.tcp_port_out = 6303
6452 cls.udp_port_in = 6304
6453 cls.udp_port_out = 6304
6454 cls.icmp_id_in = 6305
6455 cls.icmp_id_out = 6305
6456 cls.nat_addr = '10.0.0.3'
6457 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6458 cls.dst_ip4 = '192.168.70.1'
6459
6460 cls.create_pg_interfaces(range(2))
6461
6462 cls.pg0.admin_up()
6463 cls.pg0.config_ip4()
6464 cls.pg0.resolve_arp()
6465
6466 cls.pg1.admin_up()
6467 cls.pg1.config_ip6()
6468 cls.pg1.resolve_ndp()
6469
Ole Troana5b2eec2019-03-11 19:23:25 +01006470 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
Juraj Slobodacba69362017-12-19 02:09:32 +01006471 dst_address_length=0,
6472 next_hop_address=cls.pg1.remote_ip6n,
Ole Troana5b2eec2019-03-11 19:23:25 +01006473 next_hop_sw_if_index=cls.pg1.sw_if_index,
6474 is_ipv6=True)
Juraj Slobodacba69362017-12-19 02:09:32 +01006475
6476 except Exception:
6477 super(TestNAT44Out2InDPO, cls).tearDownClass()
6478 raise
6479
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006480 @classmethod
6481 def tearDownClass(cls):
6482 super(TestNAT44Out2InDPO, cls).tearDownClass()
6483
Juraj Slobodacba69362017-12-19 02:09:32 +01006484 def configure_xlat(self):
6485 self.dst_ip6_pfx = '1:2:3::'
6486 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6487 self.dst_ip6_pfx)
6488 self.dst_ip6_pfx_len = 96
6489 self.src_ip6_pfx = '4:5:6::'
6490 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6491 self.src_ip6_pfx)
6492 self.src_ip6_pfx_len = 96
6493 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6494 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006495 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006496
Ole Troanffba3c32018-11-22 12:53:00 +01006497 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006498 def test_464xlat_ce(self):
6499 """ Test 464XLAT CE with NAT44 """
6500
Matus Fabian69ce30d2018-08-22 01:27:10 -07006501 nat_config = self.vapi.nat_show_config()
6502 self.assertEqual(1, nat_config.out2in_dpo)
6503
Juraj Slobodacba69362017-12-19 02:09:32 +01006504 self.configure_xlat()
6505
6506 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6507 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6508
6509 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6510 self.dst_ip6_pfx_len)
6511 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6512 self.src_ip6_pfx_len)
6513
6514 try:
6515 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6516 self.pg0.add_stream(pkts)
6517 self.pg_enable_capture(self.pg_interfaces)
6518 self.pg_start()
6519 capture = self.pg1.get_capture(len(pkts))
6520 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6521 dst_ip=out_src_ip6)
6522
6523 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6524 out_dst_ip6)
6525 self.pg1.add_stream(pkts)
6526 self.pg_enable_capture(self.pg_interfaces)
6527 self.pg_start()
6528 capture = self.pg0.get_capture(len(pkts))
6529 self.verify_capture_in(capture, self.pg0)
6530 finally:
6531 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6532 is_add=0)
6533 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6534 self.nat_addr_n, is_add=0)
6535
Ole Troanffba3c32018-11-22 12:53:00 +01006536 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006537 def test_464xlat_ce_no_nat(self):
6538 """ Test 464XLAT CE without NAT44 """
6539
6540 self.configure_xlat()
6541
6542 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6543 self.dst_ip6_pfx_len)
6544 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6545 self.src_ip6_pfx_len)
6546
6547 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6548 self.pg0.add_stream(pkts)
6549 self.pg_enable_capture(self.pg_interfaces)
6550 self.pg_start()
6551 capture = self.pg1.get_capture(len(pkts))
6552 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6553 nat_ip=out_dst_ip6, same_port=True)
6554
6555 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6556 self.pg1.add_stream(pkts)
6557 self.pg_enable_capture(self.pg_interfaces)
6558 self.pg_start()
6559 capture = self.pg0.get_capture(len(pkts))
6560 self.verify_capture_in(capture, self.pg0)
6561
6562
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006563class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006564 """ Deterministic NAT Test Cases """
6565
6566 @classmethod
6567 def setUpConstants(cls):
6568 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006569 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006570
6571 @classmethod
6572 def setUpClass(cls):
6573 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006574 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006575
6576 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006577 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006578 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006579 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006580 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006581 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006582 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006583
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006584 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006585 cls.interfaces = list(cls.pg_interfaces)
6586
6587 for i in cls.interfaces:
6588 i.admin_up()
6589 i.config_ip4()
6590 i.resolve_arp()
6591
Martin Gálik977c1cb2017-03-30 23:21:51 -07006592 cls.pg0.generate_remote_hosts(2)
6593 cls.pg0.configure_ipv4_neighbors()
6594
Matus Fabian066f0342017-02-10 03:48:01 -08006595 except Exception:
6596 super(TestDeterministicNAT, cls).tearDownClass()
6597 raise
6598
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006599 @classmethod
6600 def tearDownClass(cls):
6601 super(TestDeterministicNAT, cls).tearDownClass()
6602
Martin Gálik977c1cb2017-03-30 23:21:51 -07006603 def create_stream_in(self, in_if, out_if, ttl=64):
6604 """
6605 Create packet stream for inside network
6606
6607 :param in_if: Inside interface
6608 :param out_if: Outside interface
6609 :param ttl: TTL of generated packets
6610 """
6611 pkts = []
6612 # TCP
6613 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6614 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006615 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006616 pkts.append(p)
6617
6618 # UDP
6619 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6620 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006621 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006622 pkts.append(p)
6623
6624 # ICMP
6625 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6626 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6627 ICMP(id=self.icmp_id_in, type='echo-request'))
6628 pkts.append(p)
6629
6630 return pkts
6631
6632 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6633 """
6634 Create packet stream for outside network
6635
6636 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006637 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006638 :param ttl: TTL of generated packets
6639 """
6640 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006641 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006642 pkts = []
6643 # TCP
6644 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6645 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006646 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006647 pkts.append(p)
6648
6649 # UDP
6650 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6651 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006652 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006653 pkts.append(p)
6654
6655 # ICMP
6656 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6657 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6658 ICMP(id=self.icmp_external_id, type='echo-reply'))
6659 pkts.append(p)
6660
6661 return pkts
6662
Matus Fabian05ca4a32018-09-04 23:45:13 -07006663 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006664 """
6665 Verify captured packets on outside network
6666
6667 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006668 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07006669 :param same_port: Source port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006670 """
6671 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006672 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006673 for packet in capture:
6674 try:
6675 self.assertEqual(packet[IP].src, nat_ip)
6676 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006677 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006678 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006679 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006680 else:
6681 self.icmp_external_id = packet[ICMP].id
6682 except:
6683 self.logger.error(ppp("Unexpected or invalid packet "
6684 "(outside network):", packet))
6685 raise
6686
Matus Fabian066f0342017-02-10 03:48:01 -08006687 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006688 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006689 in_addr = '172.16.255.0'
6690 out_addr = '172.17.255.50'
6691 in_addr_t = '172.16.255.20'
6692 in_addr_n = socket.inet_aton(in_addr)
6693 out_addr_n = socket.inet_aton(out_addr)
6694 in_addr_t_n = socket.inet_aton(in_addr_t)
6695 in_plen = 24
6696 out_plen = 32
6697
Matus Fabian2ba92e32017-08-21 07:05:03 -07006698 nat_config = self.vapi.nat_show_config()
6699 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006700
Matus Fabian2ba92e32017-08-21 07:05:03 -07006701 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006702
Matus Fabian2ba92e32017-08-21 07:05:03 -07006703 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006704 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006705 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006706 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6707
Matus Fabian2ba92e32017-08-21 07:05:03 -07006708 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006709 self.assertEqual(len(deterministic_mappings), 1)
6710 dsm = deterministic_mappings[0]
6711 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6712 self.assertEqual(in_plen, dsm.in_plen)
6713 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6714 self.assertEqual(out_plen, dsm.out_plen)
6715
Matus Fabian2ba92e32017-08-21 07:05:03 -07006716 self.clear_nat_det()
6717 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006718 self.assertEqual(len(deterministic_mappings), 0)
6719
Matus Fabian6a0946f2017-04-12 03:36:13 -07006720 def test_set_timeouts(self):
6721 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006722 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006723
Matus Fabian878c6462018-08-23 00:33:35 -07006724 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6725 timeouts_before.tcp_established + 10,
6726 timeouts_before.tcp_transitory + 10,
6727 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006728
Matus Fabian878c6462018-08-23 00:33:35 -07006729 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006730
6731 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6732 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6733 self.assertNotEqual(timeouts_before.tcp_established,
6734 timeouts_after.tcp_established)
6735 self.assertNotEqual(timeouts_before.tcp_transitory,
6736 timeouts_after.tcp_transitory)
6737
Martin Gálik977c1cb2017-03-30 23:21:51 -07006738 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006739 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006740
6741 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006742
Matus Fabian2ba92e32017-08-21 07:05:03 -07006743 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6744 32,
6745 socket.inet_aton(nat_ip),
6746 32)
6747 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6748 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6749 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006750
6751 # in2out
6752 pkts = self.create_stream_in(self.pg0, self.pg1)
6753 self.pg0.add_stream(pkts)
6754 self.pg_enable_capture(self.pg_interfaces)
6755 self.pg_start()
6756 capture = self.pg1.get_capture(len(pkts))
6757 self.verify_capture_out(capture, nat_ip)
6758
6759 # out2in
6760 pkts = self.create_stream_out(self.pg1, nat_ip)
6761 self.pg1.add_stream(pkts)
6762 self.pg_enable_capture(self.pg_interfaces)
6763 self.pg_start()
6764 capture = self.pg0.get_capture(len(pkts))
6765 self.verify_capture_in(capture, self.pg0)
6766
Martin Gálik9806eae2017-04-25 01:25:08 -07006767 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006768 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006769 self.assertEqual(len(sessions), 3)
6770
6771 # TCP session
6772 s = sessions[0]
6773 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6774 self.assertEqual(s.in_port, self.tcp_port_in)
6775 self.assertEqual(s.out_port, self.tcp_port_out)
6776 self.assertEqual(s.ext_port, self.tcp_external_port)
6777
6778 # UDP session
6779 s = sessions[1]
6780 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6781 self.assertEqual(s.in_port, self.udp_port_in)
6782 self.assertEqual(s.out_port, self.udp_port_out)
6783 self.assertEqual(s.ext_port, self.udp_external_port)
6784
6785 # ICMP session
6786 s = sessions[2]
6787 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6788 self.assertEqual(s.in_port, self.icmp_id_in)
6789 self.assertEqual(s.out_port, self.icmp_external_id)
6790
Martin Gálik977c1cb2017-03-30 23:21:51 -07006791 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006792 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006793
6794 nat_ip = "10.0.0.10"
6795 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006796 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006797
6798 host0 = self.pg0.remote_hosts[0]
6799 host1 = self.pg0.remote_hosts[1]
6800
Matus Fabian2ba92e32017-08-21 07:05:03 -07006801 self.vapi.nat_det_add_del_map(host0.ip4n,
6802 24,
6803 socket.inet_aton(nat_ip),
6804 32)
6805 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6806 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6807 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006808
6809 # host0 to out
6810 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6811 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006812 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006813 self.pg0.add_stream(p)
6814 self.pg_enable_capture(self.pg_interfaces)
6815 self.pg_start()
6816 capture = self.pg1.get_capture(1)
6817 p = capture[0]
6818 try:
6819 ip = p[IP]
6820 tcp = p[TCP]
6821 self.assertEqual(ip.src, nat_ip)
6822 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006823 self.assertEqual(tcp.dport, external_port)
6824 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006825 except:
6826 self.logger.error(ppp("Unexpected or invalid packet:", p))
6827 raise
6828
6829 # host1 to out
6830 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6831 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006832 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006833 self.pg0.add_stream(p)
6834 self.pg_enable_capture(self.pg_interfaces)
6835 self.pg_start()
6836 capture = self.pg1.get_capture(1)
6837 p = capture[0]
6838 try:
6839 ip = p[IP]
6840 tcp = p[TCP]
6841 self.assertEqual(ip.src, nat_ip)
6842 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006843 self.assertEqual(tcp.dport, external_port)
6844 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006845 except:
6846 self.logger.error(ppp("Unexpected or invalid packet:", p))
6847 raise
6848
Matus Fabian2ba92e32017-08-21 07:05:03 -07006849 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006850 self.assertEqual(1, len(dms))
6851 self.assertEqual(2, dms[0].ses_num)
6852
6853 # out to host0
6854 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6855 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006856 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006857 self.pg1.add_stream(p)
6858 self.pg_enable_capture(self.pg_interfaces)
6859 self.pg_start()
6860 capture = self.pg0.get_capture(1)
6861 p = capture[0]
6862 try:
6863 ip = p[IP]
6864 tcp = p[TCP]
6865 self.assertEqual(ip.src, self.pg1.remote_ip4)
6866 self.assertEqual(ip.dst, host0.ip4)
6867 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006868 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006869 except:
6870 self.logger.error(ppp("Unexpected or invalid packet:", p))
6871 raise
6872
6873 # out to host1
6874 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6875 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006876 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006877 self.pg1.add_stream(p)
6878 self.pg_enable_capture(self.pg_interfaces)
6879 self.pg_start()
6880 capture = self.pg0.get_capture(1)
6881 p = capture[0]
6882 try:
6883 ip = p[IP]
6884 tcp = p[TCP]
6885 self.assertEqual(ip.src, self.pg1.remote_ip4)
6886 self.assertEqual(ip.dst, host1.ip4)
6887 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006888 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006889 except:
6890 self.logger.error(ppp("Unexpected or invalid packet", p))
6891 raise
6892
Martin Gálik6bc8c642017-04-19 01:12:27 -07006893 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006894 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6895 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006896 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006897 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006898 dms = self.vapi.nat_det_map_dump()
6899 self.assertEqual(dms[0].ses_num, 1)
6900
6901 self.vapi.nat_det_close_session_in(host0.ip4n,
6902 port_in,
6903 self.pg1.remote_ip4n,
6904 external_port)
6905 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006906 self.assertEqual(dms[0].ses_num, 0)
6907
Martin Gálik977c1cb2017-03-30 23:21:51 -07006908 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006909 """ Deterministic NAT TCP session close from inside network """
6910 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6911 32,
6912 socket.inet_aton(self.nat_addr),
6913 32)
6914 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6915 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6916 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006917
6918 self.initiate_tcp_session(self.pg0, self.pg1)
6919
6920 # close the session from inside
6921 try:
6922 # FIN packet in -> out
6923 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6924 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006925 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006926 flags="F"))
6927 self.pg0.add_stream(p)
6928 self.pg_enable_capture(self.pg_interfaces)
6929 self.pg_start()
6930 self.pg1.get_capture(1)
6931
6932 pkts = []
6933
6934 # ACK packet out -> in
6935 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006936 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006937 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006938 flags="A"))
6939 pkts.append(p)
6940
6941 # FIN packet out -> in
6942 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006943 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006944 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006945 flags="F"))
6946 pkts.append(p)
6947
6948 self.pg1.add_stream(pkts)
6949 self.pg_enable_capture(self.pg_interfaces)
6950 self.pg_start()
6951 self.pg0.get_capture(2)
6952
6953 # ACK packet in -> out
6954 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6955 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006956 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006957 flags="A"))
6958 self.pg0.add_stream(p)
6959 self.pg_enable_capture(self.pg_interfaces)
6960 self.pg_start()
6961 self.pg1.get_capture(1)
6962
Matus Fabian2ba92e32017-08-21 07:05:03 -07006963 # Check if deterministic NAT44 closed the session
6964 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006965 self.assertEqual(0, dms[0].ses_num)
6966 except:
6967 self.logger.error("TCP session termination failed")
6968 raise
6969
6970 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006971 """ Deterministic NAT TCP session close from outside network """
6972 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6973 32,
6974 socket.inet_aton(self.nat_addr),
6975 32)
6976 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6977 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6978 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006979
6980 self.initiate_tcp_session(self.pg0, self.pg1)
6981
6982 # close the session from outside
6983 try:
6984 # FIN packet out -> in
6985 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006986 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006987 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006988 flags="F"))
6989 self.pg1.add_stream(p)
6990 self.pg_enable_capture(self.pg_interfaces)
6991 self.pg_start()
6992 self.pg0.get_capture(1)
6993
6994 pkts = []
6995
6996 # ACK packet in -> out
6997 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6998 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006999 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007000 flags="A"))
7001 pkts.append(p)
7002
7003 # ACK packet in -> out
7004 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7005 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007006 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007007 flags="F"))
7008 pkts.append(p)
7009
7010 self.pg0.add_stream(pkts)
7011 self.pg_enable_capture(self.pg_interfaces)
7012 self.pg_start()
7013 self.pg1.get_capture(2)
7014
7015 # ACK packet out -> in
7016 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007017 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007018 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007019 flags="A"))
7020 self.pg1.add_stream(p)
7021 self.pg_enable_capture(self.pg_interfaces)
7022 self.pg_start()
7023 self.pg0.get_capture(1)
7024
Matus Fabian2ba92e32017-08-21 07:05:03 -07007025 # Check if deterministic NAT44 closed the session
7026 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007027 self.assertEqual(0, dms[0].ses_num)
7028 except:
7029 self.logger.error("TCP session termination failed")
7030 raise
7031
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007032 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007033 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007034 """ Deterministic NAT session timeouts """
7035 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7036 32,
7037 socket.inet_aton(self.nat_addr),
7038 32)
7039 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7040 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7041 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007042
7043 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07007044 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007045 pkts = self.create_stream_in(self.pg0, self.pg1)
7046 self.pg0.add_stream(pkts)
7047 self.pg_enable_capture(self.pg_interfaces)
7048 self.pg_start()
7049 capture = self.pg1.get_capture(len(pkts))
7050 sleep(15)
7051
Matus Fabian2ba92e32017-08-21 07:05:03 -07007052 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007053 self.assertEqual(0, dms[0].ses_num)
7054
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007055 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007056 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007057 """ Deterministic NAT maximum sessions per user limit """
7058 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7059 32,
7060 socket.inet_aton(self.nat_addr),
7061 32)
7062 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7063 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7064 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007065 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7066 src_address=self.pg2.local_ip4n,
7067 path_mtu=512,
7068 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01007069 self.vapi.nat_ipfix_enable_disable()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007070
7071 pkts = []
7072 for port in range(1025, 2025):
7073 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7074 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7075 UDP(sport=port, dport=port))
7076 pkts.append(p)
7077
7078 self.pg0.add_stream(pkts)
7079 self.pg_enable_capture(self.pg_interfaces)
7080 self.pg_start()
7081 capture = self.pg1.get_capture(len(pkts))
7082
7083 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7084 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007085 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007086 self.pg0.add_stream(p)
7087 self.pg_enable_capture(self.pg_interfaces)
7088 self.pg_start()
7089 capture = self.pg1.assert_nothing_captured()
7090
Martin Gálikf7e655d2017-04-27 02:13:26 -07007091 # verify ICMP error packet
7092 capture = self.pg0.get_capture(1)
7093 p = capture[0]
7094 self.assertTrue(p.haslayer(ICMP))
7095 icmp = p[ICMP]
7096 self.assertEqual(icmp.type, 3)
7097 self.assertEqual(icmp.code, 1)
7098 self.assertTrue(icmp.haslayer(IPerror))
7099 inner_ip = icmp[IPerror]
7100 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7101 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7102
Matus Fabian2ba92e32017-08-21 07:05:03 -07007103 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007104
7105 self.assertEqual(1000, dms[0].ses_num)
7106
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007107 # verify IPFIX logging
7108 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007109 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007110 capture = self.pg2.get_capture(2)
7111 ipfix = IPFIXDecoder()
7112 # first load template
7113 for p in capture:
7114 self.assertTrue(p.haslayer(IPFIX))
7115 if p.haslayer(Template):
7116 ipfix.add_template(p.getlayer(Template))
7117 # verify events in data set
7118 for p in capture:
7119 if p.haslayer(Data):
7120 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007121 self.verify_ipfix_max_entries_per_user(data,
7122 1000,
7123 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007124
Matus Fabian2ba92e32017-08-21 07:05:03 -07007125 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007126 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007127 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007128 """
Ole Troane1ade682019-03-04 23:55:43 +01007129 self.vapi.nat_ipfix_enable_disable(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007130 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007131 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007132 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007133 self.vapi.nat_det_add_del_map(dsm.in_addr,
7134 dsm.in_plen,
7135 dsm.out_addr,
7136 dsm.out_plen,
7137 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08007138
Matus Fabian2ba92e32017-08-21 07:05:03 -07007139 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007140 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007141 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7142 intf.is_inside,
7143 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007144
Matus Fabian066f0342017-02-10 03:48:01 -08007145 def tearDown(self):
7146 super(TestDeterministicNAT, self).tearDown()
7147 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007148 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007149
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07007150 def show_commands_at_teardown(self):
7151 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7152 self.logger.info(self.vapi.cli("show nat timeouts"))
7153 self.logger.info(
7154 self.vapi.cli("show nat44 deterministic mappings"))
7155 self.logger.info(
7156 self.vapi.cli("show nat44 deterministic sessions"))
7157
Matus Fabian06596c52017-06-06 04:53:28 -07007158
7159class TestNAT64(MethodHolder):
7160 """ NAT64 Test Cases """
7161
7162 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007163 def setUpConstants(cls):
7164 super(TestNAT64, cls).setUpConstants()
7165 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7166 "nat64 st hash buckets 256", "}"])
7167
7168 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007169 def setUpClass(cls):
7170 super(TestNAT64, cls).setUpClass()
7171
7172 try:
7173 cls.tcp_port_in = 6303
7174 cls.tcp_port_out = 6303
7175 cls.udp_port_in = 6304
7176 cls.udp_port_out = 6304
7177 cls.icmp_id_in = 6305
7178 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007179 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007180 cls.nat_addr = '10.0.0.3'
7181 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007182 cls.vrf1_id = 10
7183 cls.vrf1_nat_addr = '10.0.10.3'
7184 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7185 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08007186 cls.ipfix_src_port = 4739
7187 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007188
Juraj Slobodac746a152018-07-09 02:36:37 +02007189 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007190 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007191 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007192 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7193
Ole Troan9a475372019-03-05 16:58:24 +01007194 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7195 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007196
Matus Fabian029f3d22017-06-15 02:28:50 -07007197 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7198
7199 cls.pg0.generate_remote_hosts(2)
7200
Matus Fabian06596c52017-06-06 04:53:28 -07007201 for i in cls.ip6_interfaces:
7202 i.admin_up()
7203 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007204 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007205
7206 for i in cls.ip4_interfaces:
7207 i.admin_up()
7208 i.config_ip4()
7209 i.resolve_arp()
7210
Matus Fabian36ea2d62017-10-24 04:13:49 -07007211 cls.pg3.admin_up()
7212 cls.pg3.config_ip4()
7213 cls.pg3.resolve_arp()
7214 cls.pg3.config_ip6()
7215 cls.pg3.configure_ipv6_neighbors()
7216
Juraj Slobodac746a152018-07-09 02:36:37 +02007217 cls.pg5.admin_up()
7218 cls.pg5.config_ip6()
7219
Matus Fabian06596c52017-06-06 04:53:28 -07007220 except Exception:
7221 super(TestNAT64, cls).tearDownClass()
7222 raise
7223
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007224 @classmethod
7225 def tearDownClass(cls):
7226 super(TestNAT64, cls).tearDownClass()
7227
Juraj Slobodac746a152018-07-09 02:36:37 +02007228 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7229 """ NAT64 inside interface handles Neighbor Advertisement """
7230
7231 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7232
7233 # Try to send ping
7234 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7235 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7236 ICMPv6EchoRequest())
7237 pkts = [ping]
7238 self.pg5.add_stream(pkts)
7239 self.pg_enable_capture(self.pg_interfaces)
7240 self.pg_start()
7241
7242 # Wait for Neighbor Solicitation
7243 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007244 packet = capture[0]
7245 try:
7246 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007247 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007248 tgt = packet[ICMPv6ND_NS].tgt
7249 except:
7250 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7251 raise
7252
7253 # Send Neighbor Advertisement
7254 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7255 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7256 ICMPv6ND_NA(tgt=tgt) /
7257 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7258 pkts = [p]
7259 self.pg5.add_stream(pkts)
7260 self.pg_enable_capture(self.pg_interfaces)
7261 self.pg_start()
7262
7263 # Try to send ping again
7264 pkts = [ping]
7265 self.pg5.add_stream(pkts)
7266 self.pg_enable_capture(self.pg_interfaces)
7267 self.pg_start()
7268
7269 # Wait for ping reply
7270 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007271 packet = capture[0]
7272 try:
7273 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7274 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007275 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007276 except:
7277 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7278 raise
7279
Matus Fabian06596c52017-06-06 04:53:28 -07007280 def test_pool(self):
7281 """ Add/delete address to NAT64 pool """
7282 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7283
7284 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7285
7286 addresses = self.vapi.nat64_pool_addr_dump()
7287 self.assertEqual(len(addresses), 1)
7288 self.assertEqual(addresses[0].address, nat_addr)
7289
7290 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7291
7292 addresses = self.vapi.nat64_pool_addr_dump()
7293 self.assertEqual(len(addresses), 0)
7294
7295 def test_interface(self):
7296 """ Enable/disable NAT64 feature on the interface """
7297 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7298 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7299
7300 interfaces = self.vapi.nat64_interface_dump()
7301 self.assertEqual(len(interfaces), 2)
7302 pg0_found = False
7303 pg1_found = False
7304 for intf in interfaces:
7305 if intf.sw_if_index == self.pg0.sw_if_index:
7306 self.assertEqual(intf.is_inside, 1)
7307 pg0_found = True
7308 elif intf.sw_if_index == self.pg1.sw_if_index:
7309 self.assertEqual(intf.is_inside, 0)
7310 pg1_found = True
7311 self.assertTrue(pg0_found)
7312 self.assertTrue(pg1_found)
7313
7314 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007315 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007316 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007317 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007318
7319 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7320 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7321
7322 interfaces = self.vapi.nat64_interface_dump()
7323 self.assertEqual(len(interfaces), 0)
7324
7325 def test_static_bib(self):
7326 """ Add/delete static BIB entry """
7327 in_addr = socket.inet_pton(socket.AF_INET6,
7328 '2001:db8:85a3::8a2e:370:7334')
7329 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7330 in_port = 1234
7331 out_port = 5678
7332 proto = IP_PROTOS.tcp
7333
7334 self.vapi.nat64_add_del_static_bib(in_addr,
7335 out_addr,
7336 in_port,
7337 out_port,
7338 proto)
7339 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7340 static_bib_num = 0
7341 for bibe in bib:
7342 if bibe.is_static:
7343 static_bib_num += 1
7344 self.assertEqual(bibe.i_addr, in_addr)
7345 self.assertEqual(bibe.o_addr, out_addr)
7346 self.assertEqual(bibe.i_port, in_port)
7347 self.assertEqual(bibe.o_port, out_port)
7348 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007349 bibs = self.statistics.get_counter('/nat64/total-bibs')
7350 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007351
7352 self.vapi.nat64_add_del_static_bib(in_addr,
7353 out_addr,
7354 in_port,
7355 out_port,
7356 proto,
7357 is_add=0)
7358 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7359 static_bib_num = 0
7360 for bibe in bib:
7361 if bibe.is_static:
7362 static_bib_num += 1
7363 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007364 bibs = self.statistics.get_counter('/nat64/total-bibs')
7365 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007366
7367 def test_set_timeouts(self):
7368 """ Set NAT64 timeouts """
7369 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007370 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007371 self.assertEqual(timeouts.udp, 300)
7372 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007373 self.assertEqual(timeouts.tcp_transitory, 240)
7374 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007375
7376 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07007377 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7378 tcp_established=7450)
7379 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007380 self.assertEqual(timeouts.udp, 200)
7381 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007382 self.assertEqual(timeouts.tcp_transitory, 250)
7383 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007384
7385 def test_dynamic(self):
7386 """ NAT64 dynamic translation test """
7387 self.tcp_port_in = 6303
7388 self.udp_port_in = 6304
7389 self.icmp_id_in = 6305
7390
7391 ses_num_start = self.nat64_get_ses_num()
7392
7393 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7394 self.nat_addr_n)
7395 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7396 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7397
7398 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007399 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7400 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7401 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7402 totaln = self.statistics.get_counter(
7403 '/err/nat64-in2out/good in2out packets processed')
7404
Matus Fabian06596c52017-06-06 04:53:28 -07007405 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7406 self.pg0.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.pg1.get_capture(len(pkts))
7410 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007411 dst_ip=self.pg1.remote_ip4)
7412
Matus Fabiana5e73762018-12-14 01:55:16 -08007413 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7414 self.assertEqual(err - tcpn, 1)
7415 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7416 self.assertEqual(err - udpn, 1)
7417 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7418 self.assertEqual(err - icmpn, 1)
7419 err = self.statistics.get_counter(
7420 '/err/nat64-in2out/good in2out packets processed')
7421 self.assertEqual(err - totaln, 3)
7422
Matus Fabian06596c52017-06-06 04:53:28 -07007423 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007424 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7425 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7426 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7427 totaln = self.statistics.get_counter(
7428 '/err/nat64-out2in/good out2in packets processed')
7429
Matus Fabian06596c52017-06-06 04:53:28 -07007430 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7431 self.pg1.add_stream(pkts)
7432 self.pg_enable_capture(self.pg_interfaces)
7433 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007434 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007435 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7436 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7437
Matus Fabiana5e73762018-12-14 01:55:16 -08007438 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7439 self.assertEqual(err - tcpn, 1)
7440 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7441 self.assertEqual(err - udpn, 1)
7442 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7443 self.assertEqual(err - icmpn, 1)
7444 err = self.statistics.get_counter(
7445 '/err/nat64-out2in/good out2in packets processed')
7446 self.assertEqual(err - totaln, 3)
7447
Matus Fabianfd0d5082018-12-18 01:08:51 -08007448 bibs = self.statistics.get_counter('/nat64/total-bibs')
7449 self.assertEqual(bibs[0][0], 3)
7450 sessions = self.statistics.get_counter('/nat64/total-sessions')
7451 self.assertEqual(sessions[0][0], 3)
7452
Matus Fabian06596c52017-06-06 04:53:28 -07007453 # in2out
7454 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7455 self.pg0.add_stream(pkts)
7456 self.pg_enable_capture(self.pg_interfaces)
7457 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007458 capture = self.pg1.get_capture(len(pkts))
7459 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007460 dst_ip=self.pg1.remote_ip4)
7461
7462 # out2in
7463 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7464 self.pg1.add_stream(pkts)
7465 self.pg_enable_capture(self.pg_interfaces)
7466 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007467 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007468 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7469
7470 ses_num_end = self.nat64_get_ses_num()
7471
7472 self.assertEqual(ses_num_end - ses_num_start, 3)
7473
Matus Fabian029f3d22017-06-15 02:28:50 -07007474 # tenant with specific VRF
7475 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7476 self.vrf1_nat_addr_n,
7477 vrf_id=self.vrf1_id)
7478 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7479
7480 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7481 self.pg2.add_stream(pkts)
7482 self.pg_enable_capture(self.pg_interfaces)
7483 self.pg_start()
7484 capture = self.pg1.get_capture(len(pkts))
7485 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7486 dst_ip=self.pg1.remote_ip4)
7487
7488 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7489 self.pg1.add_stream(pkts)
7490 self.pg_enable_capture(self.pg_interfaces)
7491 self.pg_start()
7492 capture = self.pg2.get_capture(len(pkts))
7493 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7494
Matus Fabian06596c52017-06-06 04:53:28 -07007495 def test_static(self):
7496 """ NAT64 static translation test """
7497 self.tcp_port_in = 60303
7498 self.udp_port_in = 60304
7499 self.icmp_id_in = 60305
7500 self.tcp_port_out = 60303
7501 self.udp_port_out = 60304
7502 self.icmp_id_out = 60305
7503
7504 ses_num_start = self.nat64_get_ses_num()
7505
7506 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7507 self.nat_addr_n)
7508 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7509 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7510
7511 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7512 self.nat_addr_n,
7513 self.tcp_port_in,
7514 self.tcp_port_out,
7515 IP_PROTOS.tcp)
7516 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7517 self.nat_addr_n,
7518 self.udp_port_in,
7519 self.udp_port_out,
7520 IP_PROTOS.udp)
7521 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7522 self.nat_addr_n,
7523 self.icmp_id_in,
7524 self.icmp_id_out,
7525 IP_PROTOS.icmp)
7526
7527 # in2out
7528 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7529 self.pg0.add_stream(pkts)
7530 self.pg_enable_capture(self.pg_interfaces)
7531 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007532 capture = self.pg1.get_capture(len(pkts))
7533 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007534 dst_ip=self.pg1.remote_ip4, same_port=True)
7535
7536 # out2in
7537 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7538 self.pg1.add_stream(pkts)
7539 self.pg_enable_capture(self.pg_interfaces)
7540 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007541 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007542 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7543 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7544
7545 ses_num_end = self.nat64_get_ses_num()
7546
7547 self.assertEqual(ses_num_end - ses_num_start, 3)
7548
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007549 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07007550 def test_session_timeout(self):
7551 """ NAT64 session timeout """
7552 self.icmp_id_in = 1234
7553 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7554 self.nat_addr_n)
7555 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7556 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007557 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07007558
7559 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7560 self.pg0.add_stream(pkts)
7561 self.pg_enable_capture(self.pg_interfaces)
7562 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007563 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007564
7565 ses_num_before_timeout = self.nat64_get_ses_num()
7566
7567 sleep(15)
7568
Matus Fabian8fed4242018-08-14 05:14:55 -07007569 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07007570 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07007571 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07007572
Matus Fabian732036d2017-06-08 05:24:28 -07007573 def test_icmp_error(self):
7574 """ NAT64 ICMP Error message translation """
7575 self.tcp_port_in = 6303
7576 self.udp_port_in = 6304
7577 self.icmp_id_in = 6305
7578
Matus Fabian732036d2017-06-08 05:24:28 -07007579 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7580 self.nat_addr_n)
7581 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7582 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7583
7584 # send some packets to create sessions
7585 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7586 self.pg0.add_stream(pkts)
7587 self.pg_enable_capture(self.pg_interfaces)
7588 self.pg_start()
7589 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07007590 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07007591 nat_ip=self.nat_addr,
7592 dst_ip=self.pg1.remote_ip4)
7593
7594 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7595 self.pg1.add_stream(pkts)
7596 self.pg_enable_capture(self.pg_interfaces)
7597 self.pg_start()
7598 capture_ip6 = self.pg0.get_capture(len(pkts))
7599 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7600 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7601 self.pg0.remote_ip6)
7602
7603 # in2out
7604 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7605 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7606 ICMPv6DestUnreach(code=1) /
7607 packet[IPv6] for packet in capture_ip6]
7608 self.pg0.add_stream(pkts)
7609 self.pg_enable_capture(self.pg_interfaces)
7610 self.pg_start()
7611 capture = self.pg1.get_capture(len(pkts))
7612 for packet in capture:
7613 try:
7614 self.assertEqual(packet[IP].src, self.nat_addr)
7615 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7616 self.assertEqual(packet[ICMP].type, 3)
7617 self.assertEqual(packet[ICMP].code, 13)
7618 inner = packet[IPerror]
7619 self.assertEqual(inner.src, self.pg1.remote_ip4)
7620 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007621 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007622 if inner.haslayer(TCPerror):
7623 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7624 elif inner.haslayer(UDPerror):
7625 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7626 else:
7627 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7628 except:
7629 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7630 raise
7631
7632 # out2in
7633 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7634 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7635 ICMP(type=3, code=13) /
7636 packet[IP] for packet in capture_ip4]
7637 self.pg1.add_stream(pkts)
7638 self.pg_enable_capture(self.pg_interfaces)
7639 self.pg_start()
7640 capture = self.pg0.get_capture(len(pkts))
7641 for packet in capture:
7642 try:
7643 self.assertEqual(packet[IPv6].src, ip.src)
7644 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7645 icmp = packet[ICMPv6DestUnreach]
7646 self.assertEqual(icmp.code, 1)
7647 inner = icmp[IPerror6]
7648 self.assertEqual(inner.src, self.pg0.remote_ip6)
7649 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007650 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007651 if inner.haslayer(TCPerror):
7652 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7653 elif inner.haslayer(UDPerror):
7654 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7655 else:
7656 self.assertEqual(inner[ICMPv6EchoRequest].id,
7657 self.icmp_id_in)
7658 except:
7659 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7660 raise
7661
Matus Fabian029f3d22017-06-15 02:28:50 -07007662 def test_hairpinning(self):
7663 """ NAT64 hairpinning """
7664
7665 client = self.pg0.remote_hosts[0]
7666 server = self.pg0.remote_hosts[1]
7667 server_tcp_in_port = 22
7668 server_tcp_out_port = 4022
7669 server_udp_in_port = 23
7670 server_udp_out_port = 4023
7671 client_tcp_in_port = 1234
7672 client_udp_in_port = 1235
7673 client_tcp_out_port = 0
7674 client_udp_out_port = 0
7675 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7676 nat_addr_ip6 = ip.src
7677
7678 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7679 self.nat_addr_n)
7680 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7681 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7682
7683 self.vapi.nat64_add_del_static_bib(server.ip6n,
7684 self.nat_addr_n,
7685 server_tcp_in_port,
7686 server_tcp_out_port,
7687 IP_PROTOS.tcp)
7688 self.vapi.nat64_add_del_static_bib(server.ip6n,
7689 self.nat_addr_n,
7690 server_udp_in_port,
7691 server_udp_out_port,
7692 IP_PROTOS.udp)
7693
7694 # client to server
7695 pkts = []
7696 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7697 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7698 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7699 pkts.append(p)
7700 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7701 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7702 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7703 pkts.append(p)
7704 self.pg0.add_stream(pkts)
7705 self.pg_enable_capture(self.pg_interfaces)
7706 self.pg_start()
7707 capture = self.pg0.get_capture(len(pkts))
7708 for packet in capture:
7709 try:
7710 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7711 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007712 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007713 if packet.haslayer(TCP):
7714 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7715 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007716 client_tcp_out_port = packet[TCP].sport
7717 else:
7718 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7719 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007720 client_udp_out_port = packet[UDP].sport
7721 except:
7722 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7723 raise
7724
7725 # server to client
7726 pkts = []
7727 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7728 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7729 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7730 pkts.append(p)
7731 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7732 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7733 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7734 pkts.append(p)
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, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007743 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007744 if packet.haslayer(TCP):
7745 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7746 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007747 else:
7748 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7749 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007750 except:
7751 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7752 raise
7753
7754 # ICMP error
7755 pkts = []
7756 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7757 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7758 ICMPv6DestUnreach(code=1) /
7759 packet[IPv6] for packet in capture]
7760 self.pg0.add_stream(pkts)
7761 self.pg_enable_capture(self.pg_interfaces)
7762 self.pg_start()
7763 capture = self.pg0.get_capture(len(pkts))
7764 for packet in capture:
7765 try:
7766 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7767 self.assertEqual(packet[IPv6].dst, server.ip6)
7768 icmp = packet[ICMPv6DestUnreach]
7769 self.assertEqual(icmp.code, 1)
7770 inner = icmp[IPerror6]
7771 self.assertEqual(inner.src, server.ip6)
7772 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007773 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007774 if inner.haslayer(TCPerror):
7775 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7776 self.assertEqual(inner[TCPerror].dport,
7777 client_tcp_out_port)
7778 else:
7779 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7780 self.assertEqual(inner[UDPerror].dport,
7781 client_udp_out_port)
7782 except:
7783 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7784 raise
7785
Matus Fabian428dc912017-06-21 06:15:18 -07007786 def test_prefix(self):
7787 """ NAT64 Network-Specific Prefix """
7788
7789 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7790 self.nat_addr_n)
7791 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7792 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7793 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7794 self.vrf1_nat_addr_n,
7795 vrf_id=self.vrf1_id)
7796 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7797
7798 # Add global prefix
7799 global_pref64 = "2001:db8::"
7800 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7801 global_pref64_len = 32
7802 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7803
7804 prefix = self.vapi.nat64_prefix_dump()
7805 self.assertEqual(len(prefix), 1)
7806 self.assertEqual(prefix[0].prefix, global_pref64_n)
7807 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7808 self.assertEqual(prefix[0].vrf_id, 0)
7809
7810 # Add tenant specific prefix
7811 vrf1_pref64 = "2001:db8:122:300::"
7812 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7813 vrf1_pref64_len = 56
7814 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7815 vrf1_pref64_len,
7816 vrf_id=self.vrf1_id)
7817 prefix = self.vapi.nat64_prefix_dump()
7818 self.assertEqual(len(prefix), 2)
7819
7820 # Global prefix
7821 pkts = self.create_stream_in_ip6(self.pg0,
7822 self.pg1,
7823 pref=global_pref64,
7824 plen=global_pref64_len)
7825 self.pg0.add_stream(pkts)
7826 self.pg_enable_capture(self.pg_interfaces)
7827 self.pg_start()
7828 capture = self.pg1.get_capture(len(pkts))
7829 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7830 dst_ip=self.pg1.remote_ip4)
7831
7832 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7833 self.pg1.add_stream(pkts)
7834 self.pg_enable_capture(self.pg_interfaces)
7835 self.pg_start()
7836 capture = self.pg0.get_capture(len(pkts))
7837 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7838 global_pref64,
7839 global_pref64_len)
7840 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7841
7842 # Tenant specific prefix
7843 pkts = self.create_stream_in_ip6(self.pg2,
7844 self.pg1,
7845 pref=vrf1_pref64,
7846 plen=vrf1_pref64_len)
7847 self.pg2.add_stream(pkts)
7848 self.pg_enable_capture(self.pg_interfaces)
7849 self.pg_start()
7850 capture = self.pg1.get_capture(len(pkts))
7851 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7852 dst_ip=self.pg1.remote_ip4)
7853
7854 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7855 self.pg1.add_stream(pkts)
7856 self.pg_enable_capture(self.pg_interfaces)
7857 self.pg_start()
7858 capture = self.pg2.get_capture(len(pkts))
7859 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7860 vrf1_pref64,
7861 vrf1_pref64_len)
7862 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7863
Matus Fabianf8cd5812017-07-11 03:55:02 -07007864 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007865 """ NAT64 translate packet with unknown protocol """
7866
7867 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7868 self.nat_addr_n)
7869 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7870 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7871 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7872
7873 # in2out
7874 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7875 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7876 TCP(sport=self.tcp_port_in, dport=20))
7877 self.pg0.add_stream(p)
7878 self.pg_enable_capture(self.pg_interfaces)
7879 self.pg_start()
7880 p = self.pg1.get_capture(1)
7881
7882 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007883 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007884 GRE() /
7885 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7886 TCP(sport=1234, dport=1234))
7887 self.pg0.add_stream(p)
7888 self.pg_enable_capture(self.pg_interfaces)
7889 self.pg_start()
7890 p = self.pg1.get_capture(1)
7891 packet = p[0]
7892 try:
7893 self.assertEqual(packet[IP].src, self.nat_addr)
7894 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007895 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02007896 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007897 except:
7898 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7899 raise
7900
7901 # out2in
7902 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7903 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7904 GRE() /
7905 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7906 TCP(sport=1234, dport=1234))
7907 self.pg1.add_stream(p)
7908 self.pg_enable_capture(self.pg_interfaces)
7909 self.pg_start()
7910 p = self.pg0.get_capture(1)
7911 packet = p[0]
7912 try:
7913 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007914 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7915 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007916 except:
7917 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7918 raise
7919
Matus Fabianf8cd5812017-07-11 03:55:02 -07007920 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007921 """ NAT64 translate packet with unknown protocol - hairpinning """
7922
7923 client = self.pg0.remote_hosts[0]
7924 server = self.pg0.remote_hosts[1]
7925 server_tcp_in_port = 22
7926 server_tcp_out_port = 4022
7927 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007928 client_tcp_out_port = 1235
7929 server_nat_ip = "10.0.0.100"
7930 client_nat_ip = "10.0.0.110"
7931 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7932 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7933 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7934 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007935
Matus Fabianf8cd5812017-07-11 03:55:02 -07007936 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7937 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007938 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7939 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7940
7941 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007942 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007943 server_tcp_in_port,
7944 server_tcp_out_port,
7945 IP_PROTOS.tcp)
7946
Matus Fabianf8cd5812017-07-11 03:55:02 -07007947 self.vapi.nat64_add_del_static_bib(server.ip6n,
7948 server_nat_ip_n,
7949 0,
7950 0,
7951 IP_PROTOS.gre)
7952
7953 self.vapi.nat64_add_del_static_bib(client.ip6n,
7954 client_nat_ip_n,
7955 client_tcp_in_port,
7956 client_tcp_out_port,
7957 IP_PROTOS.tcp)
7958
Matus Fabian7968e6c2017-07-06 05:37:49 -07007959 # client to server
7960 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007961 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007962 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7963 self.pg0.add_stream(p)
7964 self.pg_enable_capture(self.pg_interfaces)
7965 self.pg_start()
7966 p = self.pg0.get_capture(1)
7967
7968 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007969 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007970 GRE() /
7971 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7972 TCP(sport=1234, dport=1234))
7973 self.pg0.add_stream(p)
7974 self.pg_enable_capture(self.pg_interfaces)
7975 self.pg_start()
7976 p = self.pg0.get_capture(1)
7977 packet = p[0]
7978 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007979 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007980 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007981 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007982 except:
7983 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7984 raise
7985
7986 # server to client
7987 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007988 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007989 GRE() /
7990 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7991 TCP(sport=1234, dport=1234))
7992 self.pg0.add_stream(p)
7993 self.pg_enable_capture(self.pg_interfaces)
7994 self.pg_start()
7995 p = self.pg0.get_capture(1)
7996 packet = p[0]
7997 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007998 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007999 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008000 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008001 except:
8002 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8003 raise
8004
Matus Fabian36ea2d62017-10-24 04:13:49 -07008005 def test_one_armed_nat64(self):
8006 """ One armed NAT64 """
8007 external_port = 0
8008 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8009 '64:ff9b::',
8010 96)
8011
8012 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8013 self.nat_addr_n)
8014 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
8015 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
8016
8017 # in2out
8018 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8019 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8020 TCP(sport=12345, dport=80))
8021 self.pg3.add_stream(p)
8022 self.pg_enable_capture(self.pg_interfaces)
8023 self.pg_start()
8024 capture = self.pg3.get_capture(1)
8025 p = capture[0]
8026 try:
8027 ip = p[IP]
8028 tcp = p[TCP]
8029 self.assertEqual(ip.src, self.nat_addr)
8030 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8031 self.assertNotEqual(tcp.sport, 12345)
8032 external_port = tcp.sport
8033 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008034 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008035 except:
8036 self.logger.error(ppp("Unexpected or invalid packet:", p))
8037 raise
8038
8039 # out2in
8040 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8041 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8042 TCP(sport=80, dport=external_port))
8043 self.pg3.add_stream(p)
8044 self.pg_enable_capture(self.pg_interfaces)
8045 self.pg_start()
8046 capture = self.pg3.get_capture(1)
8047 p = capture[0]
8048 try:
8049 ip = p[IPv6]
8050 tcp = p[TCP]
8051 self.assertEqual(ip.src, remote_host_ip6)
8052 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8053 self.assertEqual(tcp.sport, 80)
8054 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008055 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008056 except:
8057 self.logger.error(ppp("Unexpected or invalid packet:", p))
8058 raise
8059
Matus Fabianefcd1e92017-08-15 06:59:19 -07008060 def test_frag_in_order(self):
8061 """ NAT64 translate fragments arriving in order """
8062 self.tcp_port_in = random.randint(1025, 65535)
8063
8064 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8065 self.nat_addr_n)
8066 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8067 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8068
8069 reass = self.vapi.nat_reass_dump()
8070 reass_n_start = len(reass)
8071
8072 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008073 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008074 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8075 self.tcp_port_in, 20, data)
8076 self.pg0.add_stream(pkts)
8077 self.pg_enable_capture(self.pg_interfaces)
8078 self.pg_start()
8079 frags = self.pg1.get_capture(len(pkts))
8080 p = self.reass_frags_and_verify(frags,
8081 self.nat_addr,
8082 self.pg1.remote_ip4)
8083 self.assertEqual(p[TCP].dport, 20)
8084 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8085 self.tcp_port_out = p[TCP].sport
8086 self.assertEqual(data, p[Raw].load)
8087
8088 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008089 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008090 pkts = self.create_stream_frag(self.pg1,
8091 self.nat_addr,
8092 20,
8093 self.tcp_port_out,
8094 data)
8095 self.pg1.add_stream(pkts)
8096 self.pg_enable_capture(self.pg_interfaces)
8097 self.pg_start()
8098 frags = self.pg0.get_capture(len(pkts))
8099 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8100 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8101 self.assertEqual(p[TCP].sport, 20)
8102 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8103 self.assertEqual(data, p[Raw].load)
8104
8105 reass = self.vapi.nat_reass_dump()
8106 reass_n_end = len(reass)
8107
8108 self.assertEqual(reass_n_end - reass_n_start, 2)
8109
8110 def test_reass_hairpinning(self):
8111 """ NAT64 fragments hairpinning """
8112 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008113 server = self.pg0.remote_hosts[1]
8114 server_in_port = random.randint(1025, 65535)
8115 server_out_port = random.randint(1025, 65535)
8116 client_in_port = random.randint(1025, 65535)
8117 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8118 nat_addr_ip6 = ip.src
8119
8120 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8121 self.nat_addr_n)
8122 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8123 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8124
8125 # add static BIB entry for server
8126 self.vapi.nat64_add_del_static_bib(server.ip6n,
8127 self.nat_addr_n,
8128 server_in_port,
8129 server_out_port,
8130 IP_PROTOS.tcp)
8131
8132 # send packet from host to server
8133 pkts = self.create_stream_frag_ip6(self.pg0,
8134 self.nat_addr,
8135 client_in_port,
8136 server_out_port,
8137 data)
8138 self.pg0.add_stream(pkts)
8139 self.pg_enable_capture(self.pg_interfaces)
8140 self.pg_start()
8141 frags = self.pg0.get_capture(len(pkts))
8142 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8143 self.assertNotEqual(p[TCP].sport, client_in_port)
8144 self.assertEqual(p[TCP].dport, server_in_port)
8145 self.assertEqual(data, p[Raw].load)
8146
8147 def test_frag_out_of_order(self):
8148 """ NAT64 translate fragments arriving out of order """
8149 self.tcp_port_in = random.randint(1025, 65535)
8150
8151 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8152 self.nat_addr_n)
8153 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8154 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8155
8156 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008157 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008158 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8159 self.tcp_port_in, 20, data)
8160 pkts.reverse()
8161 self.pg0.add_stream(pkts)
8162 self.pg_enable_capture(self.pg_interfaces)
8163 self.pg_start()
8164 frags = self.pg1.get_capture(len(pkts))
8165 p = self.reass_frags_and_verify(frags,
8166 self.nat_addr,
8167 self.pg1.remote_ip4)
8168 self.assertEqual(p[TCP].dport, 20)
8169 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8170 self.tcp_port_out = p[TCP].sport
8171 self.assertEqual(data, p[Raw].load)
8172
8173 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008174 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008175 pkts = self.create_stream_frag(self.pg1,
8176 self.nat_addr,
8177 20,
8178 self.tcp_port_out,
8179 data)
8180 pkts.reverse()
8181 self.pg1.add_stream(pkts)
8182 self.pg_enable_capture(self.pg_interfaces)
8183 self.pg_start()
8184 frags = self.pg0.get_capture(len(pkts))
8185 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8186 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8187 self.assertEqual(p[TCP].sport, 20)
8188 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8189 self.assertEqual(data, p[Raw].load)
8190
Matus Fabian0938dcf2017-11-08 01:59:38 -08008191 def test_interface_addr(self):
8192 """ Acquire NAT64 pool addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01008193 self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008194
8195 # no address in NAT64 pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008196 addresses = self.vapi.nat44_address_dump()
8197 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008198
8199 # configure interface address and check NAT64 address pool
8200 self.pg4.config_ip4()
8201 addresses = self.vapi.nat64_pool_addr_dump()
8202 self.assertEqual(len(addresses), 1)
8203 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8204
8205 # remove interface address and check NAT64 address pool
8206 self.pg4.unconfig_ip4()
8207 addresses = self.vapi.nat64_pool_addr_dump()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008208 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008209
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008210 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008211 def test_ipfix_max_bibs_sessions(self):
8212 """ IPFIX logging maximum session and BIB entries exceeded """
8213 max_bibs = 1280
8214 max_sessions = 2560
8215 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8216 '64:ff9b::',
8217 96)
8218
8219 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8220 self.nat_addr_n)
8221 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8222 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8223
8224 pkts = []
8225 src = ""
8226 for i in range(0, max_bibs):
8227 src = "fd01:aa::%x" % (i)
8228 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8229 IPv6(src=src, dst=remote_host_ip6) /
8230 TCP(sport=12345, dport=80))
8231 pkts.append(p)
8232 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8233 IPv6(src=src, dst=remote_host_ip6) /
8234 TCP(sport=12345, dport=22))
8235 pkts.append(p)
8236 self.pg0.add_stream(pkts)
8237 self.pg_enable_capture(self.pg_interfaces)
8238 self.pg_start()
8239 self.pg1.get_capture(max_sessions)
8240
8241 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8242 src_address=self.pg3.local_ip4n,
8243 path_mtu=512,
8244 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008245 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8246 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008247
8248 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8249 IPv6(src=src, dst=remote_host_ip6) /
8250 TCP(sport=12345, dport=25))
8251 self.pg0.add_stream(p)
8252 self.pg_enable_capture(self.pg_interfaces)
8253 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008254 self.pg1.assert_nothing_captured()
8255 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008256 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8257 capture = self.pg3.get_capture(9)
8258 ipfix = IPFIXDecoder()
8259 # first load template
8260 for p in capture:
8261 self.assertTrue(p.haslayer(IPFIX))
8262 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8263 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8264 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8265 self.assertEqual(p[UDP].dport, 4739)
8266 self.assertEqual(p[IPFIX].observationDomainID,
8267 self.ipfix_domain_id)
8268 if p.haslayer(Template):
8269 ipfix.add_template(p.getlayer(Template))
8270 # verify events in data set
8271 for p in capture:
8272 if p.haslayer(Data):
8273 data = ipfix.decode_data_set(p.getlayer(Set))
8274 self.verify_ipfix_max_sessions(data, max_sessions)
8275
8276 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8277 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8278 TCP(sport=12345, dport=80))
8279 self.pg0.add_stream(p)
8280 self.pg_enable_capture(self.pg_interfaces)
8281 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008282 self.pg1.assert_nothing_captured()
8283 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008284 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8285 capture = self.pg3.get_capture(1)
8286 # verify events in data set
8287 for p in capture:
8288 self.assertTrue(p.haslayer(IPFIX))
8289 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8290 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8291 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8292 self.assertEqual(p[UDP].dport, 4739)
8293 self.assertEqual(p[IPFIX].observationDomainID,
8294 self.ipfix_domain_id)
8295 if p.haslayer(Data):
8296 data = ipfix.decode_data_set(p.getlayer(Set))
8297 self.verify_ipfix_max_bibs(data, max_bibs)
8298
8299 def test_ipfix_max_frags(self):
8300 """ IPFIX logging maximum fragments pending reassembly exceeded """
8301 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8302 self.nat_addr_n)
8303 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8304 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008305 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008306 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8307 src_address=self.pg3.local_ip4n,
8308 path_mtu=512,
8309 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008310 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8311 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008312
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008313 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008314 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8315 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008316 pkts.reverse()
8317 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008318 self.pg_enable_capture(self.pg_interfaces)
8319 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008320 self.pg1.assert_nothing_captured()
8321 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008322 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8323 capture = self.pg3.get_capture(9)
8324 ipfix = IPFIXDecoder()
8325 # first load template
8326 for p in capture:
8327 self.assertTrue(p.haslayer(IPFIX))
8328 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8329 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8330 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8331 self.assertEqual(p[UDP].dport, 4739)
8332 self.assertEqual(p[IPFIX].observationDomainID,
8333 self.ipfix_domain_id)
8334 if p.haslayer(Template):
8335 ipfix.add_template(p.getlayer(Template))
8336 # verify events in data set
8337 for p in capture:
8338 if p.haslayer(Data):
8339 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008340 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008341 self.pg0.remote_ip6n)
8342
8343 def test_ipfix_bib_ses(self):
8344 """ IPFIX logging NAT64 BIB/session create and delete events """
8345 self.tcp_port_in = random.randint(1025, 65535)
8346 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8347 '64:ff9b::',
8348 96)
8349
8350 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8351 self.nat_addr_n)
8352 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8353 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8354 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8355 src_address=self.pg3.local_ip4n,
8356 path_mtu=512,
8357 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008358 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8359 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008360
8361 # Create
8362 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8363 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8364 TCP(sport=self.tcp_port_in, dport=25))
8365 self.pg0.add_stream(p)
8366 self.pg_enable_capture(self.pg_interfaces)
8367 self.pg_start()
8368 p = self.pg1.get_capture(1)
8369 self.tcp_port_out = p[0][TCP].sport
8370 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8371 capture = self.pg3.get_capture(10)
8372 ipfix = IPFIXDecoder()
8373 # first load template
8374 for p in capture:
8375 self.assertTrue(p.haslayer(IPFIX))
8376 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8377 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8378 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8379 self.assertEqual(p[UDP].dport, 4739)
8380 self.assertEqual(p[IPFIX].observationDomainID,
8381 self.ipfix_domain_id)
8382 if p.haslayer(Template):
8383 ipfix.add_template(p.getlayer(Template))
8384 # verify events in data set
8385 for p in capture:
8386 if p.haslayer(Data):
8387 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008388 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008389 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008390 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008391 self.verify_ipfix_nat64_ses(data,
8392 1,
8393 self.pg0.remote_ip6n,
8394 self.pg1.remote_ip4,
8395 25)
8396 else:
8397 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8398
8399 # Delete
8400 self.pg_enable_capture(self.pg_interfaces)
8401 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8402 self.nat_addr_n,
8403 is_add=0)
8404 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8405 capture = self.pg3.get_capture(2)
8406 # verify events in data set
8407 for p in capture:
8408 self.assertTrue(p.haslayer(IPFIX))
8409 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8410 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8411 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8412 self.assertEqual(p[UDP].dport, 4739)
8413 self.assertEqual(p[IPFIX].observationDomainID,
8414 self.ipfix_domain_id)
8415 if p.haslayer(Data):
8416 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008417 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08008418 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008419 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08008420 self.verify_ipfix_nat64_ses(data,
8421 0,
8422 self.pg0.remote_ip6n,
8423 self.pg1.remote_ip4,
8424 25)
8425 else:
8426 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8427
Matus Fabianad1f3e12018-11-28 21:26:34 -08008428 def test_syslog_sess(self):
8429 """ Test syslog session creation and deletion """
8430 self.tcp_port_in = random.randint(1025, 65535)
8431 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8432 '64:ff9b::',
8433 96)
8434
8435 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8436 self.nat_addr_n)
8437 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8438 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8439 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01008440 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008441
8442 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8443 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8444 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8445 self.pg0.add_stream(p)
8446 self.pg_enable_capture(self.pg_interfaces)
8447 self.pg_start()
8448 p = self.pg1.get_capture(1)
8449 self.tcp_port_out = p[0][TCP].sport
8450 capture = self.pg3.get_capture(1)
8451 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8452
8453 self.pg_enable_capture(self.pg_interfaces)
8454 self.pg_start()
8455 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8456 self.nat_addr_n,
8457 is_add=0)
8458 capture = self.pg3.get_capture(1)
8459 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8460
Matus Fabian06596c52017-06-06 04:53:28 -07008461 def nat64_get_ses_num(self):
8462 """
8463 Return number of active NAT64 sessions.
8464 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07008465 st = self.vapi.nat64_st_dump()
8466 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07008467
8468 def clear_nat64(self):
8469 """
8470 Clear NAT64 configuration.
8471 """
Ole Troane1ade682019-03-04 23:55:43 +01008472 self.vapi.nat_ipfix_enable_disable(enable=0,
8473 src_port=self.ipfix_src_port,
8474 domain_id=self.ipfix_domain_id)
Matus Fabiana431ad12018-01-04 04:03:14 -08008475 self.ipfix_src_port = 4739
8476 self.ipfix_domain_id = 1
8477
Matus Fabianad1f3e12018-11-28 21:26:34 -08008478 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8479
Matus Fabian878c6462018-08-23 00:33:35 -07008480 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07008481
8482 interfaces = self.vapi.nat64_interface_dump()
8483 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07008484 if intf.is_inside > 1:
8485 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8486 0,
8487 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07008488 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8489 intf.is_inside,
8490 is_add=0)
8491
Matus Fabiana431ad12018-01-04 04:03:14 -08008492 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07008493 for bibe in bib:
8494 if bibe.is_static:
8495 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8496 bibe.o_addr,
8497 bibe.i_port,
8498 bibe.o_port,
8499 bibe.proto,
8500 bibe.vrf_id,
8501 is_add=0)
8502
8503 adresses = self.vapi.nat64_pool_addr_dump()
8504 for addr in adresses:
8505 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8506 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07008507 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07008508 is_add=0)
8509
Matus Fabian428dc912017-06-21 06:15:18 -07008510 prefixes = self.vapi.nat64_prefix_dump()
8511 for prefix in prefixes:
8512 self.vapi.nat64_add_del_prefix(prefix.prefix,
8513 prefix.prefix_len,
8514 vrf_id=prefix.vrf_id,
8515 is_add=0)
8516
Matus Fabianfd0d5082018-12-18 01:08:51 -08008517 bibs = self.statistics.get_counter('/nat64/total-bibs')
8518 self.assertEqual(bibs[0][0], 0)
8519 sessions = self.statistics.get_counter('/nat64/total-sessions')
8520 self.assertEqual(sessions[0][0], 0)
8521
Matus Fabian06596c52017-06-06 04:53:28 -07008522 def tearDown(self):
8523 super(TestNAT64, self).tearDown()
8524 if not self.vpp_dead:
Matus Fabian06596c52017-06-06 04:53:28 -07008525 self.clear_nat64()
8526
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008527 def show_commands_at_teardown(self):
8528 self.logger.info(self.vapi.cli("show nat64 pool"))
8529 self.logger.info(self.vapi.cli("show nat64 interfaces"))
8530 self.logger.info(self.vapi.cli("show nat64 prefix"))
8531 self.logger.info(self.vapi.cli("show nat64 bib all"))
8532 self.logger.info(self.vapi.cli("show nat64 session table all"))
8533 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
8534
Matus Fabian8ebe6252017-11-06 05:04:53 -08008535
8536class TestDSlite(MethodHolder):
8537 """ DS-Lite Test Cases """
8538
8539 @classmethod
8540 def setUpClass(cls):
8541 super(TestDSlite, cls).setUpClass()
8542
8543 try:
8544 cls.nat_addr = '10.0.0.3'
8545 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8546
Matus Fabianad1f3e12018-11-28 21:26:34 -08008547 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008548 cls.pg0.admin_up()
8549 cls.pg0.config_ip4()
8550 cls.pg0.resolve_arp()
8551 cls.pg1.admin_up()
8552 cls.pg1.config_ip6()
8553 cls.pg1.generate_remote_hosts(2)
8554 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08008555 cls.pg2.admin_up()
8556 cls.pg2.config_ip4()
8557 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08008558
8559 except Exception:
8560 super(TestDSlite, cls).tearDownClass()
8561 raise
8562
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008563 @classmethod
8564 def tearDownClass(cls):
8565 super(TestDSlite, cls).tearDownClass()
8566
Matus Fabianad1f3e12018-11-28 21:26:34 -08008567 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8568 sv6enc, proto):
8569 message = data.decode('utf-8')
8570 try:
8571 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08008572 except ParseError as e:
8573 self.logger.error(e)
8574 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08008575 self.assertEqual(message.severity, SyslogSeverity.info)
8576 self.assertEqual(message.appname, 'NAT')
8577 self.assertEqual(message.msgid, 'APMADD')
8578 sd_params = message.sd.get('napmap')
8579 self.assertTrue(sd_params is not None)
8580 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8581 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8582 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8583 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8584 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8585 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8586 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8587 self.assertTrue(sd_params.get('SSUBIX') is not None)
8588 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008589
Matus Fabian8ebe6252017-11-06 05:04:53 -08008590 def test_dslite(self):
8591 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07008592 nat_config = self.vapi.nat_show_config()
8593 self.assertEqual(0, nat_config.dslite_ce)
8594
Matus Fabian8ebe6252017-11-06 05:04:53 -08008595 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8596 self.nat_addr_n)
8597 aftr_ip4 = '192.0.0.1'
8598 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8599 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8600 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8601 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Ole Troanf159f582019-02-28 20:20:47 +01008602 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008603
8604 # UDP
8605 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8606 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8607 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8608 UDP(sport=20000, dport=10000))
8609 self.pg1.add_stream(p)
8610 self.pg_enable_capture(self.pg_interfaces)
8611 self.pg_start()
8612 capture = self.pg0.get_capture(1)
8613 capture = capture[0]
8614 self.assertFalse(capture.haslayer(IPv6))
8615 self.assertEqual(capture[IP].src, self.nat_addr)
8616 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8617 self.assertNotEqual(capture[UDP].sport, 20000)
8618 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008619 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008620 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008621 capture = self.pg2.get_capture(1)
8622 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8623 20000, self.nat_addr, out_port,
8624 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008625
8626 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8627 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8628 UDP(sport=10000, dport=out_port))
8629 self.pg0.add_stream(p)
8630 self.pg_enable_capture(self.pg_interfaces)
8631 self.pg_start()
8632 capture = self.pg1.get_capture(1)
8633 capture = capture[0]
8634 self.assertEqual(capture[IPv6].src, aftr_ip6)
8635 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8636 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8637 self.assertEqual(capture[IP].dst, '192.168.1.1')
8638 self.assertEqual(capture[UDP].sport, 10000)
8639 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008640 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008641
8642 # TCP
8643 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8644 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8645 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8646 TCP(sport=20001, dport=10001))
8647 self.pg1.add_stream(p)
8648 self.pg_enable_capture(self.pg_interfaces)
8649 self.pg_start()
8650 capture = self.pg0.get_capture(1)
8651 capture = capture[0]
8652 self.assertFalse(capture.haslayer(IPv6))
8653 self.assertEqual(capture[IP].src, self.nat_addr)
8654 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8655 self.assertNotEqual(capture[TCP].sport, 20001)
8656 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008657 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008658 out_port = capture[TCP].sport
8659
8660 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8661 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8662 TCP(sport=10001, dport=out_port))
8663 self.pg0.add_stream(p)
8664 self.pg_enable_capture(self.pg_interfaces)
8665 self.pg_start()
8666 capture = self.pg1.get_capture(1)
8667 capture = capture[0]
8668 self.assertEqual(capture[IPv6].src, aftr_ip6)
8669 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8670 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8671 self.assertEqual(capture[IP].dst, '192.168.1.1')
8672 self.assertEqual(capture[TCP].sport, 10001)
8673 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008674 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008675
8676 # ICMP
8677 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8678 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8679 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8680 ICMP(id=4000, type='echo-request'))
8681 self.pg1.add_stream(p)
8682 self.pg_enable_capture(self.pg_interfaces)
8683 self.pg_start()
8684 capture = self.pg0.get_capture(1)
8685 capture = capture[0]
8686 self.assertFalse(capture.haslayer(IPv6))
8687 self.assertEqual(capture[IP].src, self.nat_addr)
8688 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8689 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008690 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008691 out_id = capture[ICMP].id
8692
8693 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8694 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8695 ICMP(id=out_id, type='echo-reply'))
8696 self.pg0.add_stream(p)
8697 self.pg_enable_capture(self.pg_interfaces)
8698 self.pg_start()
8699 capture = self.pg1.get_capture(1)
8700 capture = capture[0]
8701 self.assertEqual(capture[IPv6].src, aftr_ip6)
8702 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8703 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8704 self.assertEqual(capture[IP].dst, '192.168.1.1')
8705 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008706 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008707
Matus Fabian331acc62017-12-08 03:38:51 -08008708 # ping DS-Lite AFTR tunnel endpoint address
8709 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8710 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8711 ICMPv6EchoRequest())
8712 self.pg1.add_stream(p)
8713 self.pg_enable_capture(self.pg_interfaces)
8714 self.pg_start()
8715 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008716 capture = capture[0]
8717 self.assertEqual(capture[IPv6].src, aftr_ip6)
8718 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8719 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8720
Matus Fabianfd0d5082018-12-18 01:08:51 -08008721 b4s = self.statistics.get_counter('/dslite/total-b4s')
8722 self.assertEqual(b4s[0][0], 2)
8723 sessions = self.statistics.get_counter('/dslite/total-sessions')
8724 self.assertEqual(sessions[0][0], 3)
8725
Matus Fabian8ebe6252017-11-06 05:04:53 -08008726 def tearDown(self):
8727 super(TestDSlite, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008728
8729 def show_commands_at_teardown(self):
8730 self.logger.info(self.vapi.cli("show dslite pool"))
8731 self.logger.info(
8732 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8733 self.logger.info(self.vapi.cli("show dslite sessions"))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008734
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008735
8736class TestDSliteCE(MethodHolder):
8737 """ DS-Lite CE Test Cases """
8738
8739 @classmethod
8740 def setUpConstants(cls):
8741 super(TestDSliteCE, cls).setUpConstants()
8742 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8743
8744 @classmethod
8745 def setUpClass(cls):
8746 super(TestDSliteCE, cls).setUpClass()
8747
8748 try:
8749 cls.create_pg_interfaces(range(2))
8750 cls.pg0.admin_up()
8751 cls.pg0.config_ip4()
8752 cls.pg0.resolve_arp()
8753 cls.pg1.admin_up()
8754 cls.pg1.config_ip6()
8755 cls.pg1.generate_remote_hosts(1)
8756 cls.pg1.configure_ipv6_neighbors()
8757
8758 except Exception:
8759 super(TestDSliteCE, cls).tearDownClass()
8760 raise
8761
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008762 @classmethod
8763 def tearDownClass(cls):
8764 super(TestDSliteCE, cls).tearDownClass()
8765
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008766 def test_dslite_ce(self):
8767 """ Test DS-Lite CE """
8768
Matus Fabian69ce30d2018-08-22 01:27:10 -07008769 nat_config = self.vapi.nat_show_config()
8770 self.assertEqual(1, nat_config.dslite_ce)
8771
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008772 b4_ip4 = '192.0.0.2'
8773 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8774 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8775 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8776 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8777
8778 aftr_ip4 = '192.0.0.1'
8779 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8780 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8781 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8782 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8783
8784 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8785 dst_address_length=128,
8786 next_hop_address=self.pg1.remote_ip6n,
8787 next_hop_sw_if_index=self.pg1.sw_if_index,
8788 is_ipv6=1)
8789
8790 # UDP encapsulation
8791 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8792 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8793 UDP(sport=10000, dport=20000))
8794 self.pg0.add_stream(p)
8795 self.pg_enable_capture(self.pg_interfaces)
8796 self.pg_start()
8797 capture = self.pg1.get_capture(1)
8798 capture = capture[0]
8799 self.assertEqual(capture[IPv6].src, b4_ip6)
8800 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8801 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8802 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8803 self.assertEqual(capture[UDP].sport, 10000)
8804 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008805 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008806
8807 # UDP decapsulation
8808 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8809 IPv6(dst=b4_ip6, src=aftr_ip6) /
8810 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8811 UDP(sport=20000, dport=10000))
8812 self.pg1.add_stream(p)
8813 self.pg_enable_capture(self.pg_interfaces)
8814 self.pg_start()
8815 capture = self.pg0.get_capture(1)
8816 capture = capture[0]
8817 self.assertFalse(capture.haslayer(IPv6))
8818 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8819 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8820 self.assertEqual(capture[UDP].sport, 20000)
8821 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008822 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008823
8824 # ping DS-Lite B4 tunnel endpoint address
8825 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8826 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8827 ICMPv6EchoRequest())
8828 self.pg1.add_stream(p)
8829 self.pg_enable_capture(self.pg_interfaces)
8830 self.pg_start()
8831 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008832 capture = capture[0]
8833 self.assertEqual(capture[IPv6].src, b4_ip6)
8834 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8835 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8836
8837 def tearDown(self):
8838 super(TestDSliteCE, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008839
8840 def show_commands_at_teardown(self):
8841 self.logger.info(
8842 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8843 self.logger.info(
8844 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008845
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008846
8847class TestNAT66(MethodHolder):
8848 """ NAT66 Test Cases """
8849
8850 @classmethod
8851 def setUpClass(cls):
8852 super(TestNAT66, cls).setUpClass()
8853
8854 try:
8855 cls.nat_addr = 'fd01:ff::2'
8856 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8857
8858 cls.create_pg_interfaces(range(2))
8859 cls.interfaces = list(cls.pg_interfaces)
8860
8861 for i in cls.interfaces:
8862 i.admin_up()
8863 i.config_ip6()
8864 i.configure_ipv6_neighbors()
8865
8866 except Exception:
8867 super(TestNAT66, cls).tearDownClass()
8868 raise
8869
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008870 @classmethod
8871 def tearDownClass(cls):
8872 super(TestNAT66, cls).tearDownClass()
8873
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008874 def test_static(self):
8875 """ 1:1 NAT66 test """
8876 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8877 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8878 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8879 self.nat_addr_n)
8880
8881 # in2out
8882 pkts = []
8883 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8884 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8885 TCP())
8886 pkts.append(p)
8887 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8888 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8889 UDP())
8890 pkts.append(p)
8891 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8892 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8893 ICMPv6EchoRequest())
8894 pkts.append(p)
8895 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8896 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8897 GRE() / IP() / TCP())
8898 pkts.append(p)
8899 self.pg0.add_stream(pkts)
8900 self.pg_enable_capture(self.pg_interfaces)
8901 self.pg_start()
8902 capture = self.pg1.get_capture(len(pkts))
8903 for packet in capture:
8904 try:
8905 self.assertEqual(packet[IPv6].src, self.nat_addr)
8906 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008907 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008908 except:
8909 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8910 raise
8911
8912 # out2in
8913 pkts = []
8914 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8915 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8916 TCP())
8917 pkts.append(p)
8918 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8919 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8920 UDP())
8921 pkts.append(p)
8922 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8923 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8924 ICMPv6EchoReply())
8925 pkts.append(p)
8926 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8927 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8928 GRE() / IP() / TCP())
8929 pkts.append(p)
8930 self.pg1.add_stream(pkts)
8931 self.pg_enable_capture(self.pg_interfaces)
8932 self.pg_start()
8933 capture = self.pg0.get_capture(len(pkts))
8934 for packet in capture:
8935 try:
8936 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8937 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008938 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008939 except:
8940 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8941 raise
8942
8943 sm = self.vapi.nat66_static_mapping_dump()
8944 self.assertEqual(len(sm), 1)
8945 self.assertEqual(sm[0].total_pkts, 8)
8946
Juraj Sloboda9341e342018-04-13 12:00:46 +02008947 def test_check_no_translate(self):
8948 """ NAT66 translate only when egress interface is outside interface """
8949 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8950 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8951 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8952 self.nat_addr_n)
8953
8954 # in2out
8955 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8956 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8957 UDP())
8958 self.pg0.add_stream([p])
8959 self.pg_enable_capture(self.pg_interfaces)
8960 self.pg_start()
8961 capture = self.pg1.get_capture(1)
8962 packet = capture[0]
8963 try:
8964 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8965 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8966 except:
8967 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8968 raise
8969
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008970 def clear_nat66(self):
8971 """
8972 Clear NAT66 configuration.
8973 """
8974 interfaces = self.vapi.nat66_interface_dump()
8975 for intf in interfaces:
8976 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8977 intf.is_inside,
8978 is_add=0)
8979
8980 static_mappings = self.vapi.nat66_static_mapping_dump()
8981 for sm in static_mappings:
8982 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8983 sm.external_ip_address,
8984 sm.vrf_id,
8985 is_add=0)
8986
8987 def tearDown(self):
8988 super(TestNAT66, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008989 self.clear_nat66()
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008990
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008991 def show_commands_at_teardown(self):
8992 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8993 self.logger.info(self.vapi.cli("show nat66 static mappings"))
Klement Sekerad81ae412018-05-16 10:52:54 +02008994
Matus Fabiande886752016-12-07 03:38:19 -08008995if __name__ == '__main__':
8996 unittest.main(testRunner=VppTestRunner)