blob: 5cd0ad9d8abd746d30954711d07f1928f081b6f7 [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()
4164 if not self.vpp_dead:
4165 self.logger.info(self.vapi.cli("show nat44 addresses"))
4166 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4167 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4168 self.logger.info(self.vapi.cli("show nat44 interface address"))
4169 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4170 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4171 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07004172 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07004173 self.logger.info(
4174 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabian34931eb2019-02-26 09:05:23 -08004175 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004176 self.clear_nat44()
4177 self.vapi.cli("clear logging")
4178
4179
4180class TestNAT44EndpointDependent(MethodHolder):
4181 """ Endpoint-Dependent mapping and filtering test cases """
4182
4183 @classmethod
4184 def setUpConstants(cls):
4185 super(TestNAT44EndpointDependent, cls).setUpConstants()
4186 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4187
4188 @classmethod
4189 def setUpClass(cls):
4190 super(TestNAT44EndpointDependent, cls).setUpClass()
4191 cls.vapi.cli("set log class nat level debug")
4192 try:
4193 cls.tcp_port_in = 6303
4194 cls.tcp_port_out = 6303
4195 cls.udp_port_in = 6304
4196 cls.udp_port_out = 6304
4197 cls.icmp_id_in = 6305
4198 cls.icmp_id_out = 6305
4199 cls.nat_addr = '10.0.0.3'
4200 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4201 cls.ipfix_src_port = 4739
4202 cls.ipfix_domain_id = 1
4203 cls.tcp_external_port = 80
4204
Matus Fabian8008d7c2018-07-09 01:34:20 -07004205 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004206 cls.interfaces = list(cls.pg_interfaces[0:3])
4207
4208 for i in cls.interfaces:
4209 i.admin_up()
4210 i.config_ip4()
4211 i.resolve_arp()
4212
4213 cls.pg0.generate_remote_hosts(3)
4214 cls.pg0.configure_ipv4_neighbors()
4215
4216 cls.pg3.admin_up()
4217
4218 cls.pg4.generate_remote_hosts(2)
4219 cls.pg4.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004220 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01004221 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004222 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4223 address_length=24)
Matus Fabiana6110b62018-06-13 05:39:07 -07004224 cls.pg4.admin_up()
4225 cls.pg4.resolve_arp()
4226 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4227 cls.pg4.resolve_arp()
4228
Matus Fabian8008d7c2018-07-09 01:34:20 -07004229 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004230 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004231
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004232 cls.pg5._local_ip4 = "10.1.1.1"
4233 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4234 cls.pg5.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004235 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4236 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4237 socket.AF_INET, cls.pg5.remote_ip4)
4238 cls.pg5.set_table_ip4(1)
4239 cls.pg5.config_ip4()
4240 cls.pg5.admin_up()
4241 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4242 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004243 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004244 next_hop_sw_if_index=cls.pg5.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004245 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004246
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004247 cls.pg6._local_ip4 = "10.1.2.1"
4248 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4249 cls.pg6.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004250 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4251 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4252 socket.AF_INET, cls.pg6.remote_ip4)
4253 cls.pg6.set_table_ip4(1)
4254 cls.pg6.config_ip4()
4255 cls.pg6.admin_up()
4256 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4257 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004258 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004259 next_hop_sw_if_index=cls.pg6.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004260 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004261
4262 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4263 dst_address_length=16,
Ole Troana5b2eec2019-03-11 19:23:25 +01004264 next_hop_address=zero_ip4n, table_id=0,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004265 next_hop_table_id=1)
4266 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4267 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004268 next_hop_address=zero_ip4n, table_id=1,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004269 next_hop_table_id=0)
4270 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4271 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004272 next_hop_address=cls.pg1.local_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004273 next_hop_sw_if_index=cls.pg1.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004274 table_id=0)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004275
4276 cls.pg5.resolve_arp()
4277 cls.pg6.resolve_arp()
4278
Matus Fabiana6110b62018-06-13 05:39:07 -07004279 except Exception:
4280 super(TestNAT44EndpointDependent, cls).tearDownClass()
4281 raise
4282
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07004283 @classmethod
4284 def tearDownClass(cls):
4285 super(TestNAT44EndpointDependent, cls).tearDownClass()
4286
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004287 def test_frag_in_order(self):
4288 """ NAT44 translate fragments arriving in order """
4289 self.nat44_add_address(self.nat_addr)
4290 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4291 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4292 is_inside=0)
4293 self.frag_in_order(proto=IP_PROTOS.tcp)
4294 self.frag_in_order(proto=IP_PROTOS.udp)
4295 self.frag_in_order(proto=IP_PROTOS.icmp)
4296
4297 def test_frag_in_order_dont_translate(self):
4298 """ NAT44 don't translate fragments arriving in order """
4299 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4300 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4301 is_inside=0)
4302 self.vapi.nat44_forwarding_enable_disable(enable=True)
4303 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4304
4305 def test_frag_out_of_order(self):
4306 """ NAT44 translate fragments arriving out of order """
4307 self.nat44_add_address(self.nat_addr)
4308 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4309 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4310 is_inside=0)
4311 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4312 self.frag_out_of_order(proto=IP_PROTOS.udp)
4313 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4314
4315 def test_frag_out_of_order_dont_translate(self):
4316 """ NAT44 don't translate fragments arriving out of order """
4317 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4318 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4319 is_inside=0)
4320 self.vapi.nat44_forwarding_enable_disable(enable=True)
4321 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4322
4323 def test_frag_in_order_in_plus_out(self):
4324 """ in+out interface fragments in order """
4325 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4326 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4327 is_inside=0)
4328 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4329 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4330 is_inside=0)
4331
4332 self.server = self.pg1.remote_hosts[0]
4333
4334 self.server_in_addr = self.server.ip4
4335 self.server_out_addr = '11.11.11.11'
4336 self.server_in_port = random.randint(1025, 65535)
4337 self.server_out_port = random.randint(1025, 65535)
4338
4339 self.nat44_add_address(self.server_out_addr)
4340
4341 # add static mappings for server
4342 self.nat44_add_static_mapping(self.server_in_addr,
4343 self.server_out_addr,
4344 self.server_in_port,
4345 self.server_out_port,
4346 proto=IP_PROTOS.tcp)
4347 self.nat44_add_static_mapping(self.server_in_addr,
4348 self.server_out_addr,
4349 self.server_in_port,
4350 self.server_out_port,
4351 proto=IP_PROTOS.udp)
4352 self.nat44_add_static_mapping(self.server_in_addr,
4353 self.server_out_addr,
4354 proto=IP_PROTOS.icmp)
4355
4356 self.vapi.nat_set_reass(timeout=10)
4357
4358 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4359 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4360 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4361
4362 def test_frag_out_of_order_in_plus_out(self):
4363 """ in+out interface fragments out of order """
4364 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4365 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4366 is_inside=0)
4367 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4368 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4369 is_inside=0)
4370
4371 self.server = self.pg1.remote_hosts[0]
4372
4373 self.server_in_addr = self.server.ip4
4374 self.server_out_addr = '11.11.11.11'
4375 self.server_in_port = random.randint(1025, 65535)
4376 self.server_out_port = random.randint(1025, 65535)
4377
4378 self.nat44_add_address(self.server_out_addr)
4379
4380 # add static mappings for server
4381 self.nat44_add_static_mapping(self.server_in_addr,
4382 self.server_out_addr,
4383 self.server_in_port,
4384 self.server_out_port,
4385 proto=IP_PROTOS.tcp)
4386 self.nat44_add_static_mapping(self.server_in_addr,
4387 self.server_out_addr,
4388 self.server_in_port,
4389 self.server_out_port,
4390 proto=IP_PROTOS.udp)
4391 self.nat44_add_static_mapping(self.server_in_addr,
4392 self.server_out_addr,
4393 proto=IP_PROTOS.icmp)
4394
4395 self.vapi.nat_set_reass(timeout=10)
4396
4397 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4398 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4399 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4400
4401 def test_reass_hairpinning(self):
4402 """ NAT44 fragments hairpinning """
4403 self.server = self.pg0.remote_hosts[1]
4404 self.host_in_port = random.randint(1025, 65535)
4405 self.server_in_port = random.randint(1025, 65535)
4406 self.server_out_port = random.randint(1025, 65535)
4407
4408 self.nat44_add_address(self.nat_addr)
4409 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4410 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4411 is_inside=0)
4412 # add static mapping for server
4413 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4414 self.server_in_port,
4415 self.server_out_port,
4416 proto=IP_PROTOS.tcp)
4417 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4418 self.server_in_port,
4419 self.server_out_port,
4420 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004421 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004422
4423 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4424 self.reass_hairpinning(proto=IP_PROTOS.udp)
4425 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4426
Matus Fabiana6110b62018-06-13 05:39:07 -07004427 def test_dynamic(self):
4428 """ NAT44 dynamic translation test """
4429
4430 self.nat44_add_address(self.nat_addr)
4431 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4432 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4433 is_inside=0)
4434
Matus Fabian69ce30d2018-08-22 01:27:10 -07004435 nat_config = self.vapi.nat_show_config()
4436 self.assertEqual(1, nat_config.endpoint_dependent)
4437
Matus Fabiana6110b62018-06-13 05:39:07 -07004438 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004439 tcpn = self.statistics.get_counter(
4440 '/err/nat44-ed-in2out-slowpath/TCP packets')
4441 udpn = self.statistics.get_counter(
4442 '/err/nat44-ed-in2out-slowpath/UDP packets')
4443 icmpn = self.statistics.get_counter(
4444 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4445 totaln = self.statistics.get_counter(
4446 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4447
Matus Fabiana6110b62018-06-13 05:39:07 -07004448 pkts = self.create_stream_in(self.pg0, self.pg1)
4449 self.pg0.add_stream(pkts)
4450 self.pg_enable_capture(self.pg_interfaces)
4451 self.pg_start()
4452 capture = self.pg1.get_capture(len(pkts))
4453 self.verify_capture_out(capture)
4454
Matus Fabiana5e73762018-12-14 01:55:16 -08004455 err = self.statistics.get_counter(
4456 '/err/nat44-ed-in2out-slowpath/TCP packets')
4457 self.assertEqual(err - tcpn, 1)
4458 err = self.statistics.get_counter(
4459 '/err/nat44-ed-in2out-slowpath/UDP packets')
4460 self.assertEqual(err - udpn, 1)
4461 err = self.statistics.get_counter(
4462 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4463 self.assertEqual(err - icmpn, 1)
4464 err = self.statistics.get_counter(
4465 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4466 self.assertEqual(err - totaln, 3)
4467
Matus Fabiana6110b62018-06-13 05:39:07 -07004468 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004469 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4470 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4471 icmpn = self.statistics.get_counter(
4472 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4473 totaln = self.statistics.get_counter(
4474 '/err/nat44-ed-out2in/good out2in packets processed')
4475
Matus Fabiana6110b62018-06-13 05:39:07 -07004476 pkts = self.create_stream_out(self.pg1)
4477 self.pg1.add_stream(pkts)
4478 self.pg_enable_capture(self.pg_interfaces)
4479 self.pg_start()
4480 capture = self.pg0.get_capture(len(pkts))
4481 self.verify_capture_in(capture, self.pg0)
4482
Matus Fabiana5e73762018-12-14 01:55:16 -08004483 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4484 self.assertEqual(err - tcpn, 1)
4485 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4486 self.assertEqual(err - udpn, 1)
4487 err = self.statistics.get_counter(
4488 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4489 self.assertEqual(err - icmpn, 1)
4490 err = self.statistics.get_counter(
4491 '/err/nat44-ed-out2in/good out2in packets processed')
4492 self.assertEqual(err - totaln, 2)
4493
Matus Fabianfd0d5082018-12-18 01:08:51 -08004494 users = self.statistics.get_counter('/nat44/total-users')
4495 self.assertEqual(users[0][0], 1)
4496 sessions = self.statistics.get_counter('/nat44/total-sessions')
4497 self.assertEqual(sessions[0][0], 3)
4498
Matus Fabiana6110b62018-06-13 05:39:07 -07004499 def test_forwarding(self):
4500 """ NAT44 forwarding test """
4501
4502 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4503 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4504 is_inside=0)
4505 self.vapi.nat44_forwarding_enable_disable(1)
4506
4507 real_ip = self.pg0.remote_ip4n
4508 alias_ip = self.nat_addr_n
4509 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4510 external_ip=alias_ip)
4511
4512 try:
4513 # in2out - static mapping match
4514
4515 pkts = self.create_stream_out(self.pg1)
4516 self.pg1.add_stream(pkts)
4517 self.pg_enable_capture(self.pg_interfaces)
4518 self.pg_start()
4519 capture = self.pg0.get_capture(len(pkts))
4520 self.verify_capture_in(capture, self.pg0)
4521
4522 pkts = self.create_stream_in(self.pg0, self.pg1)
4523 self.pg0.add_stream(pkts)
4524 self.pg_enable_capture(self.pg_interfaces)
4525 self.pg_start()
4526 capture = self.pg1.get_capture(len(pkts))
4527 self.verify_capture_out(capture, same_port=True)
4528
4529 # in2out - no static mapping match
4530
4531 host0 = self.pg0.remote_hosts[0]
4532 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4533 try:
4534 pkts = self.create_stream_out(self.pg1,
4535 dst_ip=self.pg0.remote_ip4,
4536 use_inside_ports=True)
4537 self.pg1.add_stream(pkts)
4538 self.pg_enable_capture(self.pg_interfaces)
4539 self.pg_start()
4540 capture = self.pg0.get_capture(len(pkts))
4541 self.verify_capture_in(capture, self.pg0)
4542
4543 pkts = self.create_stream_in(self.pg0, self.pg1)
4544 self.pg0.add_stream(pkts)
4545 self.pg_enable_capture(self.pg_interfaces)
4546 self.pg_start()
4547 capture = self.pg1.get_capture(len(pkts))
4548 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4549 same_port=True)
4550 finally:
4551 self.pg0.remote_hosts[0] = host0
4552
4553 user = self.pg0.remote_hosts[1]
4554 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4555 self.assertEqual(len(sessions), 3)
4556 self.assertTrue(sessions[0].ext_host_valid)
4557 self.vapi.nat44_del_session(
4558 sessions[0].inside_ip_address,
4559 sessions[0].inside_port,
4560 sessions[0].protocol,
4561 ext_host_address=sessions[0].ext_host_address,
4562 ext_host_port=sessions[0].ext_host_port)
4563 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4564 self.assertEqual(len(sessions), 2)
4565
4566 finally:
4567 self.vapi.nat44_forwarding_enable_disable(0)
4568 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4569 external_ip=alias_ip,
4570 is_add=0)
4571
4572 def test_static_lb(self):
4573 """ NAT44 local service load balancing """
4574 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4575 external_port = 80
4576 local_port = 8080
4577 server1 = self.pg0.remote_hosts[0]
4578 server2 = self.pg0.remote_hosts[1]
4579
4580 locals = [{'addr': server1.ip4n,
4581 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004582 'probability': 70,
4583 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004584 {'addr': server2.ip4n,
4585 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004586 'probability': 30,
4587 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004588
4589 self.nat44_add_address(self.nat_addr)
4590 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4591 external_port,
4592 IP_PROTOS.tcp,
4593 local_num=len(locals),
4594 locals=locals)
4595 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4596 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4597 is_inside=0)
4598
4599 # from client to service
4600 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4601 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4602 TCP(sport=12345, dport=external_port))
4603 self.pg1.add_stream(p)
4604 self.pg_enable_capture(self.pg_interfaces)
4605 self.pg_start()
4606 capture = self.pg0.get_capture(1)
4607 p = capture[0]
4608 server = None
4609 try:
4610 ip = p[IP]
4611 tcp = p[TCP]
4612 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4613 if ip.dst == server1.ip4:
4614 server = server1
4615 else:
4616 server = server2
4617 self.assertEqual(tcp.dport, local_port)
4618 self.assert_packet_checksums_valid(p)
4619 except:
4620 self.logger.error(ppp("Unexpected or invalid packet:", p))
4621 raise
4622
4623 # from service back to client
4624 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4625 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4626 TCP(sport=local_port, dport=12345))
4627 self.pg0.add_stream(p)
4628 self.pg_enable_capture(self.pg_interfaces)
4629 self.pg_start()
4630 capture = self.pg1.get_capture(1)
4631 p = capture[0]
4632 try:
4633 ip = p[IP]
4634 tcp = p[TCP]
4635 self.assertEqual(ip.src, self.nat_addr)
4636 self.assertEqual(tcp.sport, external_port)
4637 self.assert_packet_checksums_valid(p)
4638 except:
4639 self.logger.error(ppp("Unexpected or invalid packet:", p))
4640 raise
4641
4642 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4643 self.assertEqual(len(sessions), 1)
4644 self.assertTrue(sessions[0].ext_host_valid)
4645 self.vapi.nat44_del_session(
4646 sessions[0].inside_ip_address,
4647 sessions[0].inside_port,
4648 sessions[0].protocol,
4649 ext_host_address=sessions[0].ext_host_address,
4650 ext_host_port=sessions[0].ext_host_port)
4651 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4652 self.assertEqual(len(sessions), 0)
4653
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004654 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004655 def test_static_lb_multi_clients(self):
4656 """ NAT44 local service load balancing - multiple clients"""
4657
4658 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4659 external_port = 80
4660 local_port = 8080
4661 server1 = self.pg0.remote_hosts[0]
4662 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004663 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004664
4665 locals = [{'addr': server1.ip4n,
4666 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004667 'probability': 90,
4668 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004669 {'addr': server2.ip4n,
4670 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004671 'probability': 10,
4672 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004673
4674 self.nat44_add_address(self.nat_addr)
4675 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4676 external_port,
4677 IP_PROTOS.tcp,
4678 local_num=len(locals),
4679 locals=locals)
4680 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4681 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4682 is_inside=0)
4683
4684 server1_n = 0
4685 server2_n = 0
4686 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4687 pkts = []
4688 for client in clients:
4689 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4690 IP(src=client, dst=self.nat_addr) /
4691 TCP(sport=12345, dport=external_port))
4692 pkts.append(p)
4693 self.pg1.add_stream(pkts)
4694 self.pg_enable_capture(self.pg_interfaces)
4695 self.pg_start()
4696 capture = self.pg0.get_capture(len(pkts))
4697 for p in capture:
4698 if p[IP].dst == server1.ip4:
4699 server1_n += 1
4700 else:
4701 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004702 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004703
Matus Fabianb6865082018-12-06 03:11:09 -08004704 # add new back-end
4705 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4706 external_port,
4707 server3.ip4n,
4708 local_port,
4709 IP_PROTOS.tcp,
4710 20)
4711 server1_n = 0
4712 server2_n = 0
4713 server3_n = 0
4714 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4715 pkts = []
4716 for client in clients:
4717 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4718 IP(src=client, dst=self.nat_addr) /
4719 TCP(sport=12346, dport=external_port))
4720 pkts.append(p)
4721 self.assertGreater(len(pkts), 0)
4722 self.pg1.add_stream(pkts)
4723 self.pg_enable_capture(self.pg_interfaces)
4724 self.pg_start()
4725 capture = self.pg0.get_capture(len(pkts))
4726 for p in capture:
4727 if p[IP].dst == server1.ip4:
4728 server1_n += 1
4729 elif p[IP].dst == server2.ip4:
4730 server2_n += 1
4731 else:
4732 server3_n += 1
4733 self.assertGreater(server1_n, 0)
4734 self.assertGreater(server2_n, 0)
4735 self.assertGreater(server3_n, 0)
4736
4737 # remove one back-end
4738 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4739 external_port,
4740 server2.ip4n,
4741 local_port,
4742 IP_PROTOS.tcp,
4743 10,
4744 is_add=0)
4745 server1_n = 0
4746 server2_n = 0
4747 server3_n = 0
4748 self.pg1.add_stream(pkts)
4749 self.pg_enable_capture(self.pg_interfaces)
4750 self.pg_start()
4751 capture = self.pg0.get_capture(len(pkts))
4752 for p in capture:
4753 if p[IP].dst == server1.ip4:
4754 server1_n += 1
4755 elif p[IP].dst == server2.ip4:
4756 server2_n += 1
4757 else:
4758 server3_n += 1
4759 self.assertGreater(server1_n, 0)
4760 self.assertEqual(server2_n, 0)
4761 self.assertGreater(server3_n, 0)
4762
Matus Fabiana6110b62018-06-13 05:39:07 -07004763 def test_static_lb_2(self):
4764 """ NAT44 local service load balancing (asymmetrical rule) """
4765 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4766 external_port = 80
4767 local_port = 8080
4768 server1 = self.pg0.remote_hosts[0]
4769 server2 = self.pg0.remote_hosts[1]
4770
4771 locals = [{'addr': server1.ip4n,
4772 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004773 'probability': 70,
4774 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004775 {'addr': server2.ip4n,
4776 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004777 'probability': 30,
4778 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004779
4780 self.vapi.nat44_forwarding_enable_disable(1)
4781 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4782 external_port,
4783 IP_PROTOS.tcp,
4784 out2in_only=1,
4785 local_num=len(locals),
4786 locals=locals)
4787 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4788 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4789 is_inside=0)
4790
4791 # from client to service
4792 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4793 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4794 TCP(sport=12345, dport=external_port))
4795 self.pg1.add_stream(p)
4796 self.pg_enable_capture(self.pg_interfaces)
4797 self.pg_start()
4798 capture = self.pg0.get_capture(1)
4799 p = capture[0]
4800 server = None
4801 try:
4802 ip = p[IP]
4803 tcp = p[TCP]
4804 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4805 if ip.dst == server1.ip4:
4806 server = server1
4807 else:
4808 server = server2
4809 self.assertEqual(tcp.dport, local_port)
4810 self.assert_packet_checksums_valid(p)
4811 except:
4812 self.logger.error(ppp("Unexpected or invalid packet:", p))
4813 raise
4814
4815 # from service back to client
4816 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4817 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4818 TCP(sport=local_port, dport=12345))
4819 self.pg0.add_stream(p)
4820 self.pg_enable_capture(self.pg_interfaces)
4821 self.pg_start()
4822 capture = self.pg1.get_capture(1)
4823 p = capture[0]
4824 try:
4825 ip = p[IP]
4826 tcp = p[TCP]
4827 self.assertEqual(ip.src, self.nat_addr)
4828 self.assertEqual(tcp.sport, external_port)
4829 self.assert_packet_checksums_valid(p)
4830 except:
4831 self.logger.error(ppp("Unexpected or invalid packet:", p))
4832 raise
4833
4834 # from client to server (no translation)
4835 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4836 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4837 TCP(sport=12346, dport=local_port))
4838 self.pg1.add_stream(p)
4839 self.pg_enable_capture(self.pg_interfaces)
4840 self.pg_start()
4841 capture = self.pg0.get_capture(1)
4842 p = capture[0]
4843 server = None
4844 try:
4845 ip = p[IP]
4846 tcp = p[TCP]
4847 self.assertEqual(ip.dst, server1.ip4)
4848 self.assertEqual(tcp.dport, local_port)
4849 self.assert_packet_checksums_valid(p)
4850 except:
4851 self.logger.error(ppp("Unexpected or invalid packet:", p))
4852 raise
4853
4854 # from service back to client (no translation)
4855 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4856 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4857 TCP(sport=local_port, dport=12346))
4858 self.pg0.add_stream(p)
4859 self.pg_enable_capture(self.pg_interfaces)
4860 self.pg_start()
4861 capture = self.pg1.get_capture(1)
4862 p = capture[0]
4863 try:
4864 ip = p[IP]
4865 tcp = p[TCP]
4866 self.assertEqual(ip.src, server1.ip4)
4867 self.assertEqual(tcp.sport, local_port)
4868 self.assert_packet_checksums_valid(p)
4869 except:
4870 self.logger.error(ppp("Unexpected or invalid packet:", p))
4871 raise
4872
Matus Fabianea5b5be2018-09-03 05:02:23 -07004873 def test_lb_affinity(self):
4874 """ NAT44 local service load balancing affinity """
4875 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4876 external_port = 80
4877 local_port = 8080
4878 server1 = self.pg0.remote_hosts[0]
4879 server2 = self.pg0.remote_hosts[1]
4880
4881 locals = [{'addr': server1.ip4n,
4882 'port': local_port,
4883 'probability': 50,
4884 'vrf_id': 0},
4885 {'addr': server2.ip4n,
4886 'port': local_port,
4887 'probability': 50,
4888 'vrf_id': 0}]
4889
4890 self.nat44_add_address(self.nat_addr)
4891 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4892 external_port,
4893 IP_PROTOS.tcp,
4894 affinity=10800,
4895 local_num=len(locals),
4896 locals=locals)
4897 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4898 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4899 is_inside=0)
4900
4901 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4902 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4903 TCP(sport=1025, dport=external_port))
4904 self.pg1.add_stream(p)
4905 self.pg_enable_capture(self.pg_interfaces)
4906 self.pg_start()
4907 capture = self.pg0.get_capture(1)
4908 backend = capture[0][IP].dst
4909
4910 sessions = self.vapi.nat44_user_session_dump(
4911 socket.inet_pton(socket.AF_INET, backend), 0)
4912 self.assertEqual(len(sessions), 1)
4913 self.assertTrue(sessions[0].ext_host_valid)
4914 self.vapi.nat44_del_session(
4915 sessions[0].inside_ip_address,
4916 sessions[0].inside_port,
4917 sessions[0].protocol,
4918 ext_host_address=sessions[0].ext_host_address,
4919 ext_host_port=sessions[0].ext_host_port)
4920
4921 pkts = []
4922 for port in range(1030, 1100):
4923 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4924 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4925 TCP(sport=port, dport=external_port))
4926 pkts.append(p)
4927 self.pg1.add_stream(pkts)
4928 self.pg_enable_capture(self.pg_interfaces)
4929 self.pg_start()
4930 capture = self.pg0.get_capture(len(pkts))
4931 for p in capture:
4932 self.assertEqual(p[IP].dst, backend)
4933
Matus Fabiana6110b62018-06-13 05:39:07 -07004934 def test_unknown_proto(self):
4935 """ NAT44 translate packet with unknown protocol """
4936 self.nat44_add_address(self.nat_addr)
4937 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4938 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4939 is_inside=0)
4940
4941 # in2out
4942 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4943 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4944 TCP(sport=self.tcp_port_in, dport=20))
4945 self.pg0.add_stream(p)
4946 self.pg_enable_capture(self.pg_interfaces)
4947 self.pg_start()
4948 p = self.pg1.get_capture(1)
4949
4950 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4951 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4952 GRE() /
4953 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4954 TCP(sport=1234, dport=1234))
4955 self.pg0.add_stream(p)
4956 self.pg_enable_capture(self.pg_interfaces)
4957 self.pg_start()
4958 p = self.pg1.get_capture(1)
4959 packet = p[0]
4960 try:
4961 self.assertEqual(packet[IP].src, self.nat_addr)
4962 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004963 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004964 self.assert_packet_checksums_valid(packet)
4965 except:
4966 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4967 raise
4968
4969 # out2in
4970 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4971 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4972 GRE() /
4973 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4974 TCP(sport=1234, dport=1234))
4975 self.pg1.add_stream(p)
4976 self.pg_enable_capture(self.pg_interfaces)
4977 self.pg_start()
4978 p = self.pg0.get_capture(1)
4979 packet = p[0]
4980 try:
4981 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4982 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004983 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004984 self.assert_packet_checksums_valid(packet)
4985 except:
4986 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4987 raise
4988
4989 def test_hairpinning_unknown_proto(self):
4990 """ NAT44 translate packet with unknown protocol - hairpinning """
4991 host = self.pg0.remote_hosts[0]
4992 server = self.pg0.remote_hosts[1]
4993 host_in_port = 1234
4994 server_out_port = 8765
4995 server_nat_ip = "10.0.0.11"
4996
4997 self.nat44_add_address(self.nat_addr)
4998 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4999 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5000 is_inside=0)
5001
5002 # add static mapping for server
5003 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5004
5005 # host to server
5006 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5007 IP(src=host.ip4, dst=server_nat_ip) /
5008 TCP(sport=host_in_port, dport=server_out_port))
5009 self.pg0.add_stream(p)
5010 self.pg_enable_capture(self.pg_interfaces)
5011 self.pg_start()
5012 self.pg0.get_capture(1)
5013
5014 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5015 IP(src=host.ip4, dst=server_nat_ip) /
5016 GRE() /
5017 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5018 TCP(sport=1234, dport=1234))
5019 self.pg0.add_stream(p)
5020 self.pg_enable_capture(self.pg_interfaces)
5021 self.pg_start()
5022 p = self.pg0.get_capture(1)
5023 packet = p[0]
5024 try:
5025 self.assertEqual(packet[IP].src, self.nat_addr)
5026 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005027 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005028 self.assert_packet_checksums_valid(packet)
5029 except:
5030 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5031 raise
5032
5033 # server to host
5034 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5035 IP(src=server.ip4, dst=self.nat_addr) /
5036 GRE() /
5037 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5038 TCP(sport=1234, dport=1234))
5039 self.pg0.add_stream(p)
5040 self.pg_enable_capture(self.pg_interfaces)
5041 self.pg_start()
5042 p = self.pg0.get_capture(1)
5043 packet = p[0]
5044 try:
5045 self.assertEqual(packet[IP].src, server_nat_ip)
5046 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005047 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005048 self.assert_packet_checksums_valid(packet)
5049 except:
5050 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5051 raise
5052
5053 def test_output_feature_and_service(self):
5054 """ NAT44 interface output feature and services """
5055 external_addr = '1.2.3.4'
5056 external_port = 80
5057 local_port = 8080
5058
5059 self.vapi.nat44_forwarding_enable_disable(1)
5060 self.nat44_add_address(self.nat_addr)
5061 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
5062 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5063 local_port, external_port,
5064 proto=IP_PROTOS.tcp, out2in_only=1)
5065 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5066 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5067 is_inside=0)
5068 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5069 is_inside=0)
5070
5071 # from client to service
5072 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5073 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5074 TCP(sport=12345, dport=external_port))
5075 self.pg1.add_stream(p)
5076 self.pg_enable_capture(self.pg_interfaces)
5077 self.pg_start()
5078 capture = self.pg0.get_capture(1)
5079 p = capture[0]
5080 try:
5081 ip = p[IP]
5082 tcp = p[TCP]
5083 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5084 self.assertEqual(tcp.dport, local_port)
5085 self.assert_packet_checksums_valid(p)
5086 except:
5087 self.logger.error(ppp("Unexpected or invalid packet:", p))
5088 raise
5089
5090 # from service back to client
5091 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5092 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5093 TCP(sport=local_port, dport=12345))
5094 self.pg0.add_stream(p)
5095 self.pg_enable_capture(self.pg_interfaces)
5096 self.pg_start()
5097 capture = self.pg1.get_capture(1)
5098 p = capture[0]
5099 try:
5100 ip = p[IP]
5101 tcp = p[TCP]
5102 self.assertEqual(ip.src, external_addr)
5103 self.assertEqual(tcp.sport, external_port)
5104 self.assert_packet_checksums_valid(p)
5105 except:
5106 self.logger.error(ppp("Unexpected or invalid packet:", p))
5107 raise
5108
5109 # from local network host to external network
5110 pkts = self.create_stream_in(self.pg0, self.pg1)
5111 self.pg0.add_stream(pkts)
5112 self.pg_enable_capture(self.pg_interfaces)
5113 self.pg_start()
5114 capture = self.pg1.get_capture(len(pkts))
5115 self.verify_capture_out(capture)
5116 pkts = self.create_stream_in(self.pg0, self.pg1)
5117 self.pg0.add_stream(pkts)
5118 self.pg_enable_capture(self.pg_interfaces)
5119 self.pg_start()
5120 capture = self.pg1.get_capture(len(pkts))
5121 self.verify_capture_out(capture)
5122
5123 # from external network back to local network host
5124 pkts = self.create_stream_out(self.pg1)
5125 self.pg1.add_stream(pkts)
5126 self.pg_enable_capture(self.pg_interfaces)
5127 self.pg_start()
5128 capture = self.pg0.get_capture(len(pkts))
5129 self.verify_capture_in(capture, self.pg0)
5130
5131 def test_output_feature_and_service2(self):
5132 """ NAT44 interface output feature and service host direct access """
5133 self.vapi.nat44_forwarding_enable_disable(1)
5134 self.nat44_add_address(self.nat_addr)
5135 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5136 is_inside=0)
5137
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005138 # session initiated from service host - translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005139 pkts = self.create_stream_in(self.pg0, self.pg1)
5140 self.pg0.add_stream(pkts)
5141 self.pg_enable_capture(self.pg_interfaces)
5142 self.pg_start()
5143 capture = self.pg1.get_capture(len(pkts))
5144 self.verify_capture_out(capture)
5145
5146 pkts = self.create_stream_out(self.pg1)
5147 self.pg1.add_stream(pkts)
5148 self.pg_enable_capture(self.pg_interfaces)
5149 self.pg_start()
5150 capture = self.pg0.get_capture(len(pkts))
5151 self.verify_capture_in(capture, self.pg0)
5152
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005153 # session initiated from remote host - do not translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005154 self.tcp_port_in = 60303
5155 self.udp_port_in = 60304
5156 self.icmp_id_in = 60305
5157 pkts = self.create_stream_out(self.pg1,
5158 self.pg0.remote_ip4,
5159 use_inside_ports=True)
5160 self.pg1.add_stream(pkts)
5161 self.pg_enable_capture(self.pg_interfaces)
5162 self.pg_start()
5163 capture = self.pg0.get_capture(len(pkts))
5164 self.verify_capture_in(capture, self.pg0)
5165
5166 pkts = self.create_stream_in(self.pg0, self.pg1)
5167 self.pg0.add_stream(pkts)
5168 self.pg_enable_capture(self.pg_interfaces)
5169 self.pg_start()
5170 capture = self.pg1.get_capture(len(pkts))
5171 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5172 same_port=True)
5173
5174 def test_output_feature_and_service3(self):
5175 """ NAT44 interface output feature and DST NAT """
5176 external_addr = '1.2.3.4'
5177 external_port = 80
5178 local_port = 8080
5179
5180 self.vapi.nat44_forwarding_enable_disable(1)
5181 self.nat44_add_address(self.nat_addr)
5182 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5183 local_port, external_port,
5184 proto=IP_PROTOS.tcp, out2in_only=1)
5185 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5186 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5187 is_inside=0)
5188 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5189 is_inside=0)
5190
5191 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5192 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5193 TCP(sport=12345, dport=external_port))
5194 self.pg0.add_stream(p)
5195 self.pg_enable_capture(self.pg_interfaces)
5196 self.pg_start()
5197 capture = self.pg1.get_capture(1)
5198 p = capture[0]
5199 try:
5200 ip = p[IP]
5201 tcp = p[TCP]
5202 self.assertEqual(ip.src, self.pg0.remote_ip4)
5203 self.assertEqual(tcp.sport, 12345)
5204 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5205 self.assertEqual(tcp.dport, local_port)
5206 self.assert_packet_checksums_valid(p)
5207 except:
5208 self.logger.error(ppp("Unexpected or invalid packet:", p))
5209 raise
5210
5211 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5212 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5213 TCP(sport=local_port, dport=12345))
5214 self.pg1.add_stream(p)
5215 self.pg_enable_capture(self.pg_interfaces)
5216 self.pg_start()
5217 capture = self.pg0.get_capture(1)
5218 p = capture[0]
5219 try:
5220 ip = p[IP]
5221 tcp = p[TCP]
5222 self.assertEqual(ip.src, external_addr)
5223 self.assertEqual(tcp.sport, external_port)
5224 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5225 self.assertEqual(tcp.dport, 12345)
5226 self.assert_packet_checksums_valid(p)
5227 except:
5228 self.logger.error(ppp("Unexpected or invalid packet:", p))
5229 raise
5230
Matus Fabian182e37e2018-08-14 04:21:26 -07005231 def test_next_src_nat(self):
5232 """ On way back forward packet to nat44-in2out node. """
5233 twice_nat_addr = '10.0.1.3'
5234 external_port = 80
5235 local_port = 8080
5236 post_twice_nat_port = 0
5237
5238 self.vapi.nat44_forwarding_enable_disable(1)
5239 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5240 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5241 local_port, external_port,
5242 proto=IP_PROTOS.tcp, out2in_only=1,
5243 self_twice_nat=1, vrf_id=1)
5244 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5245 is_inside=0)
5246
5247 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5248 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5249 TCP(sport=12345, dport=external_port))
5250 self.pg6.add_stream(p)
5251 self.pg_enable_capture(self.pg_interfaces)
5252 self.pg_start()
5253 capture = self.pg6.get_capture(1)
5254 p = capture[0]
5255 try:
5256 ip = p[IP]
5257 tcp = p[TCP]
5258 self.assertEqual(ip.src, twice_nat_addr)
5259 self.assertNotEqual(tcp.sport, 12345)
5260 post_twice_nat_port = tcp.sport
5261 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5262 self.assertEqual(tcp.dport, local_port)
5263 self.assert_packet_checksums_valid(p)
5264 except:
5265 self.logger.error(ppp("Unexpected or invalid packet:", p))
5266 raise
5267
5268 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5269 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5270 TCP(sport=local_port, dport=post_twice_nat_port))
5271 self.pg6.add_stream(p)
5272 self.pg_enable_capture(self.pg_interfaces)
5273 self.pg_start()
5274 capture = self.pg6.get_capture(1)
5275 p = capture[0]
5276 try:
5277 ip = p[IP]
5278 tcp = p[TCP]
5279 self.assertEqual(ip.src, self.pg1.remote_ip4)
5280 self.assertEqual(tcp.sport, external_port)
5281 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5282 self.assertEqual(tcp.dport, 12345)
5283 self.assert_packet_checksums_valid(p)
5284 except:
5285 self.logger.error(ppp("Unexpected or invalid packet:", p))
5286 raise
5287
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005288 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5289 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005290 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005291
Matus Fabianb932d262017-12-18 05:38:24 -08005292 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005293 if lb:
5294 if not same_pg:
5295 port_in1 = port_in
5296 port_in2 = port_in
5297 else:
Ole Troan9a475372019-03-05 16:58:24 +01005298 port_in1 = port_in + 1
5299 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005300
Matus Fabianb932d262017-12-18 05:38:24 -08005301 port_out = 80
5302 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005303
5304 server1 = self.pg0.remote_hosts[0]
5305 server2 = self.pg0.remote_hosts[1]
5306 if lb and same_pg:
5307 server2 = server1
5308 if not lb:
5309 server = server1
5310
5311 pg0 = self.pg0
5312 if same_pg:
5313 pg1 = self.pg0
5314 else:
5315 pg1 = self.pg1
5316
5317 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5318 client_id == 1)
5319
Matus Fabianb932d262017-12-18 05:38:24 -08005320 self.nat44_add_address(self.nat_addr)
5321 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005322 if not lb:
5323 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5324 port_in, port_out,
5325 proto=IP_PROTOS.tcp,
5326 twice_nat=int(not self_twice_nat),
5327 self_twice_nat=int(self_twice_nat))
5328 else:
5329 locals = [{'addr': server1.ip4n,
5330 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005331 'probability': 50,
5332 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005333 {'addr': server2.ip4n,
5334 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005335 'probability': 50,
5336 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005337 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
5338 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
5339 port_out,
5340 IP_PROTOS.tcp,
5341 twice_nat=int(
5342 not self_twice_nat),
5343 self_twice_nat=int(
5344 self_twice_nat),
5345 local_num=len(locals),
5346 locals=locals)
5347 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
5348 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08005349 is_inside=0)
5350
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005351 if same_pg:
5352 if not lb:
5353 client = server
5354 else:
5355 assert client_id is not None
5356 if client_id == 1:
5357 client = self.pg0.remote_hosts[0]
5358 elif client_id == 2:
5359 client = self.pg0.remote_hosts[1]
5360 else:
5361 client = pg1.remote_hosts[0]
5362 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5363 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005364 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005365 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005366 self.pg_enable_capture(self.pg_interfaces)
5367 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005368 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005369 p = capture[0]
5370 try:
5371 ip = p[IP]
5372 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005373 if lb:
5374 if ip.dst == server1.ip4:
5375 server = server1
5376 port_in = port_in1
5377 else:
5378 server = server2
5379 port_in = port_in2
5380 self.assertEqual(ip.dst, server.ip4)
5381 if lb and same_pg:
5382 self.assertIn(tcp.dport, [port_in1, port_in2])
5383 else:
5384 self.assertEqual(tcp.dport, port_in)
5385 if eh_translate:
5386 self.assertEqual(ip.src, twice_nat_addr)
5387 self.assertNotEqual(tcp.sport, eh_port_out)
5388 else:
5389 self.assertEqual(ip.src, client.ip4)
5390 self.assertEqual(tcp.sport, eh_port_out)
5391 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005392 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005393 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005394 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005395 except:
5396 self.logger.error(ppp("Unexpected or invalid packet:", p))
5397 raise
5398
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005399 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5400 IP(src=server.ip4, dst=eh_addr_in) /
5401 TCP(sport=saved_port_in, dport=eh_port_in))
5402 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005403 self.pg_enable_capture(self.pg_interfaces)
5404 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005405 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005406 p = capture[0]
5407 try:
5408 ip = p[IP]
5409 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005410 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005411 self.assertEqual(ip.src, self.nat_addr)
5412 self.assertEqual(tcp.dport, eh_port_out)
5413 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005414 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005415 except:
5416 self.logger.error(ppp("Unexpected or invalid packet:", p))
5417 raise
5418
Matus Fabian70a26ac2018-05-14 06:20:28 -07005419 if eh_translate:
5420 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5421 self.assertEqual(len(sessions), 1)
5422 self.assertTrue(sessions[0].ext_host_valid)
5423 self.assertTrue(sessions[0].is_twicenat)
5424 self.vapi.nat44_del_session(
5425 sessions[0].inside_ip_address,
5426 sessions[0].inside_port,
5427 sessions[0].protocol,
5428 ext_host_address=sessions[0].ext_host_nat_address,
5429 ext_host_port=sessions[0].ext_host_nat_port)
5430 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5431 self.assertEqual(len(sessions), 0)
5432
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005433 def test_twice_nat(self):
5434 """ Twice NAT44 """
5435 self.twice_nat_common()
5436
5437 def test_self_twice_nat_positive(self):
5438 """ Self Twice NAT44 (positive test) """
5439 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5440
5441 def test_self_twice_nat_negative(self):
5442 """ Self Twice NAT44 (negative test) """
5443 self.twice_nat_common(self_twice_nat=True)
5444
Matus Fabianb932d262017-12-18 05:38:24 -08005445 def test_twice_nat_lb(self):
5446 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005447 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005448
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005449 def test_self_twice_nat_lb_positive(self):
5450 """ Self Twice NAT44 local service load balancing (positive test) """
5451 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5452 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005453
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005454 def test_self_twice_nat_lb_negative(self):
5455 """ Self Twice NAT44 local service load balancing (negative test) """
5456 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5457 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005458
5459 def test_twice_nat_interface_addr(self):
5460 """ Acquire twice NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01005461 self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
5462 twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005463
5464 # no address in NAT pool
5465 adresses = self.vapi.nat44_address_dump()
5466 self.assertEqual(0, len(adresses))
5467
5468 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005469 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005470 adresses = self.vapi.nat44_address_dump()
5471 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07005472 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08005473 self.assertEqual(adresses[0].twice_nat, 1)
5474
5475 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005476 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005477 adresses = self.vapi.nat44_address_dump()
5478 self.assertEqual(0, len(adresses))
5479
Matus Fabian6c01dce2018-11-16 04:41:31 -08005480 def test_tcp_close(self):
5481 """ Close TCP session from inside network - output feature """
5482 self.vapi.nat44_forwarding_enable_disable(1)
5483 self.nat44_add_address(self.pg1.local_ip4)
5484 twice_nat_addr = '10.0.1.3'
5485 service_ip = '192.168.16.150'
5486 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5487 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5488 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5489 is_inside=0)
5490 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5491 is_inside=0)
5492 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5493 service_ip,
5494 80,
5495 80,
5496 proto=IP_PROTOS.tcp,
5497 out2in_only=1,
5498 twice_nat=1)
5499 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5500 start_sessnum = len(sessions)
5501
5502 # SYN packet out->in
5503 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5504 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5505 TCP(sport=33898, dport=80, flags="S"))
5506 self.pg1.add_stream(p)
5507 self.pg_enable_capture(self.pg_interfaces)
5508 self.pg_start()
5509 capture = self.pg0.get_capture(1)
5510 p = capture[0]
5511 tcp_port = p[TCP].sport
5512
5513 # SYN + ACK packet in->out
5514 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5515 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5516 TCP(sport=80, dport=tcp_port, flags="SA"))
5517 self.pg0.add_stream(p)
5518 self.pg_enable_capture(self.pg_interfaces)
5519 self.pg_start()
5520 self.pg1.get_capture(1)
5521
5522 # ACK packet out->in
5523 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5524 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5525 TCP(sport=33898, dport=80, flags="A"))
5526 self.pg1.add_stream(p)
5527 self.pg_enable_capture(self.pg_interfaces)
5528 self.pg_start()
5529 self.pg0.get_capture(1)
5530
5531 # FIN packet in -> out
5532 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5533 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5534 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5535 self.pg0.add_stream(p)
5536 self.pg_enable_capture(self.pg_interfaces)
5537 self.pg_start()
5538 self.pg1.get_capture(1)
5539
5540 # FIN+ACK packet out -> in
5541 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5542 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5543 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5544 self.pg1.add_stream(p)
5545 self.pg_enable_capture(self.pg_interfaces)
5546 self.pg_start()
5547 self.pg0.get_capture(1)
5548
5549 # ACK packet in -> out
5550 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5551 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5552 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5553 self.pg0.add_stream(p)
5554 self.pg_enable_capture(self.pg_interfaces)
5555 self.pg_start()
5556 self.pg1.get_capture(1)
5557
5558 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5559 0)
5560 self.assertEqual(len(sessions) - start_sessnum, 0)
5561
Matus Fabianebdf1902018-05-04 03:57:42 -07005562 def test_tcp_session_close_in(self):
5563 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005564 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005565 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005566 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5567 self.nat_addr,
5568 self.tcp_port_in,
5569 self.tcp_port_out,
5570 proto=IP_PROTOS.tcp,
5571 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005572 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5573 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5574 is_inside=0)
5575
5576 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5577 start_sessnum = len(sessions)
5578
5579 self.initiate_tcp_session(self.pg0, self.pg1)
5580
Matus Fabian229c1aa2018-05-28 04:09:52 -07005581 # FIN packet in -> out
5582 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5583 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5584 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5585 flags="FA", seq=100, ack=300))
5586 self.pg0.add_stream(p)
5587 self.pg_enable_capture(self.pg_interfaces)
5588 self.pg_start()
5589 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005590
Matus Fabian229c1aa2018-05-28 04:09:52 -07005591 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005592
Matus Fabian229c1aa2018-05-28 04:09:52 -07005593 # ACK packet out -> in
5594 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5595 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5596 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5597 flags="A", seq=300, ack=101))
5598 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005599
Matus Fabian229c1aa2018-05-28 04:09:52 -07005600 # FIN packet out -> in
5601 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5602 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5603 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5604 flags="FA", seq=300, ack=101))
5605 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005606
Matus Fabian229c1aa2018-05-28 04:09:52 -07005607 self.pg1.add_stream(pkts)
5608 self.pg_enable_capture(self.pg_interfaces)
5609 self.pg_start()
5610 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005611
Matus Fabian229c1aa2018-05-28 04:09:52 -07005612 # ACK packet in -> out
5613 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5614 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5615 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5616 flags="A", seq=101, ack=301))
5617 self.pg0.add_stream(p)
5618 self.pg_enable_capture(self.pg_interfaces)
5619 self.pg_start()
5620 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005621
Matus Fabian229c1aa2018-05-28 04:09:52 -07005622 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5623 0)
5624 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005625
5626 def test_tcp_session_close_out(self):
5627 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005628 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005629 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005630 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5631 self.nat_addr,
5632 self.tcp_port_in,
5633 self.tcp_port_out,
5634 proto=IP_PROTOS.tcp,
5635 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005636 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5637 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5638 is_inside=0)
5639
5640 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5641 start_sessnum = len(sessions)
5642
5643 self.initiate_tcp_session(self.pg0, self.pg1)
5644
Matus Fabian229c1aa2018-05-28 04:09:52 -07005645 # FIN packet out -> in
5646 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5647 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5648 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5649 flags="FA", seq=100, ack=300))
5650 self.pg1.add_stream(p)
5651 self.pg_enable_capture(self.pg_interfaces)
5652 self.pg_start()
5653 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005654
Matus Fabian229c1aa2018-05-28 04:09:52 -07005655 # FIN+ACK packet in -> out
5656 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5657 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5658 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5659 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005660
Matus Fabian229c1aa2018-05-28 04:09:52 -07005661 self.pg0.add_stream(p)
5662 self.pg_enable_capture(self.pg_interfaces)
5663 self.pg_start()
5664 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005665
Matus Fabian229c1aa2018-05-28 04:09:52 -07005666 # ACK packet out -> in
5667 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5668 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5669 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5670 flags="A", seq=101, ack=301))
5671 self.pg1.add_stream(p)
5672 self.pg_enable_capture(self.pg_interfaces)
5673 self.pg_start()
5674 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005675
Matus Fabian229c1aa2018-05-28 04:09:52 -07005676 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5677 0)
5678 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005679
5680 def test_tcp_session_close_simultaneous(self):
5681 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005682 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005683 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005684 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5685 self.nat_addr,
5686 self.tcp_port_in,
5687 self.tcp_port_out,
5688 proto=IP_PROTOS.tcp,
5689 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005690 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5691 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5692 is_inside=0)
5693
5694 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5695 start_sessnum = len(sessions)
5696
5697 self.initiate_tcp_session(self.pg0, self.pg1)
5698
Matus Fabian229c1aa2018-05-28 04:09:52 -07005699 # FIN packet in -> out
5700 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5701 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5702 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5703 flags="FA", seq=100, ack=300))
5704 self.pg0.add_stream(p)
5705 self.pg_enable_capture(self.pg_interfaces)
5706 self.pg_start()
5707 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005708
Matus Fabian229c1aa2018-05-28 04:09:52 -07005709 # FIN packet out -> in
5710 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5711 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5712 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5713 flags="FA", seq=300, ack=100))
5714 self.pg1.add_stream(p)
5715 self.pg_enable_capture(self.pg_interfaces)
5716 self.pg_start()
5717 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005718
Matus Fabian229c1aa2018-05-28 04:09:52 -07005719 # ACK packet in -> out
5720 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5721 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5722 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5723 flags="A", seq=101, ack=301))
5724 self.pg0.add_stream(p)
5725 self.pg_enable_capture(self.pg_interfaces)
5726 self.pg_start()
5727 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005728
Matus Fabian229c1aa2018-05-28 04:09:52 -07005729 # ACK packet out -> in
5730 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5731 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5732 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5733 flags="A", seq=301, ack=101))
5734 self.pg1.add_stream(p)
5735 self.pg_enable_capture(self.pg_interfaces)
5736 self.pg_start()
5737 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005738
Matus Fabian229c1aa2018-05-28 04:09:52 -07005739 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5740 0)
5741 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005742
Matus Fabiana6110b62018-06-13 05:39:07 -07005743 def test_one_armed_nat44_static(self):
5744 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5745 remote_host = self.pg4.remote_hosts[0]
5746 local_host = self.pg4.remote_hosts[1]
5747 external_port = 80
5748 local_port = 8080
5749 eh_port_in = 0
5750
5751 self.vapi.nat44_forwarding_enable_disable(1)
5752 self.nat44_add_address(self.nat_addr, twice_nat=1)
5753 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5754 local_port, external_port,
5755 proto=IP_PROTOS.tcp, out2in_only=1,
5756 twice_nat=1)
5757 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5758 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5759 is_inside=0)
5760
5761 # from client to service
5762 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5763 IP(src=remote_host.ip4, dst=self.nat_addr) /
5764 TCP(sport=12345, dport=external_port))
5765 self.pg4.add_stream(p)
5766 self.pg_enable_capture(self.pg_interfaces)
5767 self.pg_start()
5768 capture = self.pg4.get_capture(1)
5769 p = capture[0]
5770 try:
5771 ip = p[IP]
5772 tcp = p[TCP]
5773 self.assertEqual(ip.dst, local_host.ip4)
5774 self.assertEqual(ip.src, self.nat_addr)
5775 self.assertEqual(tcp.dport, local_port)
5776 self.assertNotEqual(tcp.sport, 12345)
5777 eh_port_in = tcp.sport
5778 self.assert_packet_checksums_valid(p)
5779 except:
5780 self.logger.error(ppp("Unexpected or invalid packet:", p))
5781 raise
5782
5783 # from service back to client
5784 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5785 IP(src=local_host.ip4, dst=self.nat_addr) /
5786 TCP(sport=local_port, dport=eh_port_in))
5787 self.pg4.add_stream(p)
5788 self.pg_enable_capture(self.pg_interfaces)
5789 self.pg_start()
5790 capture = self.pg4.get_capture(1)
5791 p = capture[0]
5792 try:
5793 ip = p[IP]
5794 tcp = p[TCP]
5795 self.assertEqual(ip.src, self.nat_addr)
5796 self.assertEqual(ip.dst, remote_host.ip4)
5797 self.assertEqual(tcp.sport, external_port)
5798 self.assertEqual(tcp.dport, 12345)
5799 self.assert_packet_checksums_valid(p)
5800 except:
5801 self.logger.error(ppp("Unexpected or invalid packet:", p))
5802 raise
5803
5804 def test_static_with_port_out2(self):
5805 """ 1:1 NAPT asymmetrical rule """
5806
5807 external_port = 80
5808 local_port = 8080
5809
5810 self.vapi.nat44_forwarding_enable_disable(1)
5811 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5812 local_port, external_port,
5813 proto=IP_PROTOS.tcp, out2in_only=1)
5814 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5815 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5816 is_inside=0)
5817
5818 # from client to service
5819 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5820 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5821 TCP(sport=12345, dport=external_port))
5822 self.pg1.add_stream(p)
5823 self.pg_enable_capture(self.pg_interfaces)
5824 self.pg_start()
5825 capture = self.pg0.get_capture(1)
5826 p = capture[0]
5827 try:
5828 ip = p[IP]
5829 tcp = p[TCP]
5830 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5831 self.assertEqual(tcp.dport, local_port)
5832 self.assert_packet_checksums_valid(p)
5833 except:
5834 self.logger.error(ppp("Unexpected or invalid packet:", p))
5835 raise
5836
5837 # ICMP error
5838 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5839 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5840 ICMP(type=11) / capture[0][IP])
5841 self.pg0.add_stream(p)
5842 self.pg_enable_capture(self.pg_interfaces)
5843 self.pg_start()
5844 capture = self.pg1.get_capture(1)
5845 p = capture[0]
5846 try:
5847 self.assertEqual(p[IP].src, self.nat_addr)
5848 inner = p[IPerror]
5849 self.assertEqual(inner.dst, self.nat_addr)
5850 self.assertEqual(inner[TCPerror].dport, external_port)
5851 except:
5852 self.logger.error(ppp("Unexpected or invalid packet:", p))
5853 raise
5854
5855 # from service back to client
5856 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5857 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5858 TCP(sport=local_port, dport=12345))
5859 self.pg0.add_stream(p)
5860 self.pg_enable_capture(self.pg_interfaces)
5861 self.pg_start()
5862 capture = self.pg1.get_capture(1)
5863 p = capture[0]
5864 try:
5865 ip = p[IP]
5866 tcp = p[TCP]
5867 self.assertEqual(ip.src, self.nat_addr)
5868 self.assertEqual(tcp.sport, external_port)
5869 self.assert_packet_checksums_valid(p)
5870 except:
5871 self.logger.error(ppp("Unexpected or invalid packet:", p))
5872 raise
5873
5874 # ICMP error
5875 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5876 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5877 ICMP(type=11) / capture[0][IP])
5878 self.pg1.add_stream(p)
5879 self.pg_enable_capture(self.pg_interfaces)
5880 self.pg_start()
5881 capture = self.pg0.get_capture(1)
5882 p = capture[0]
5883 try:
5884 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5885 inner = p[IPerror]
5886 self.assertEqual(inner.src, self.pg0.remote_ip4)
5887 self.assertEqual(inner[TCPerror].sport, local_port)
5888 except:
5889 self.logger.error(ppp("Unexpected or invalid packet:", p))
5890 raise
5891
5892 # from client to server (no translation)
5893 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5894 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5895 TCP(sport=12346, dport=local_port))
5896 self.pg1.add_stream(p)
5897 self.pg_enable_capture(self.pg_interfaces)
5898 self.pg_start()
5899 capture = self.pg0.get_capture(1)
5900 p = capture[0]
5901 try:
5902 ip = p[IP]
5903 tcp = p[TCP]
5904 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5905 self.assertEqual(tcp.dport, local_port)
5906 self.assert_packet_checksums_valid(p)
5907 except:
5908 self.logger.error(ppp("Unexpected or invalid packet:", p))
5909 raise
5910
5911 # from service back to client (no translation)
5912 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5913 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5914 TCP(sport=local_port, dport=12346))
5915 self.pg0.add_stream(p)
5916 self.pg_enable_capture(self.pg_interfaces)
5917 self.pg_start()
5918 capture = self.pg1.get_capture(1)
5919 p = capture[0]
5920 try:
5921 ip = p[IP]
5922 tcp = p[TCP]
5923 self.assertEqual(ip.src, self.pg0.remote_ip4)
5924 self.assertEqual(tcp.sport, local_port)
5925 self.assert_packet_checksums_valid(p)
5926 except:
5927 self.logger.error(ppp("Unexpected or invalid packet:", p))
5928 raise
5929
Matus Fabian235a47e2018-06-25 16:42:36 -07005930 def test_output_feature(self):
5931 """ NAT44 interface output feature (in2out postrouting) """
5932 self.vapi.nat44_forwarding_enable_disable(1)
5933 self.nat44_add_address(self.nat_addr)
5934 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5935 is_inside=0)
5936 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5937 is_inside=0)
5938
5939 # in2out
5940 pkts = self.create_stream_in(self.pg0, self.pg1)
5941 self.pg0.add_stream(pkts)
5942 self.pg_enable_capture(self.pg_interfaces)
5943 self.pg_start()
5944 capture = self.pg1.get_capture(len(pkts))
5945 self.verify_capture_out(capture)
5946
5947 # out2in
5948 pkts = self.create_stream_out(self.pg1)
5949 self.pg1.add_stream(pkts)
5950 self.pg_enable_capture(self.pg_interfaces)
5951 self.pg_start()
5952 capture = self.pg0.get_capture(len(pkts))
5953 self.verify_capture_in(capture, self.pg0)
5954
Matus Fabian8008d7c2018-07-09 01:34:20 -07005955 def test_multiple_vrf(self):
5956 """ Multiple VRF setup """
5957 external_addr = '1.2.3.4'
5958 external_port = 80
5959 local_port = 8080
5960 port = 0
5961
5962 self.vapi.nat44_forwarding_enable_disable(1)
5963 self.nat44_add_address(self.nat_addr)
5964 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5965 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5966 is_inside=0)
5967 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5968 is_inside=0)
5969 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5970 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5971 is_inside=0)
5972 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5973 is_inside=0)
5974 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5975 local_port, external_port, vrf_id=1,
5976 proto=IP_PROTOS.tcp, out2in_only=1)
5977 self.nat44_add_static_mapping(
Ole Troan9a475372019-03-05 16:58:24 +01005978 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5979 local_port=local_port, vrf_id=0, external_port=external_port,
5980 proto=IP_PROTOS.tcp, out2in_only=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07005981
5982 # from client to service (both VRF1)
5983 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5984 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5985 TCP(sport=12345, dport=external_port))
5986 self.pg6.add_stream(p)
5987 self.pg_enable_capture(self.pg_interfaces)
5988 self.pg_start()
5989 capture = self.pg5.get_capture(1)
5990 p = capture[0]
5991 try:
5992 ip = p[IP]
5993 tcp = p[TCP]
5994 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5995 self.assertEqual(tcp.dport, local_port)
5996 self.assert_packet_checksums_valid(p)
5997 except:
5998 self.logger.error(ppp("Unexpected or invalid packet:", p))
5999 raise
6000
6001 # from service back to client (both VRF1)
6002 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6003 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6004 TCP(sport=local_port, dport=12345))
6005 self.pg5.add_stream(p)
6006 self.pg_enable_capture(self.pg_interfaces)
6007 self.pg_start()
6008 capture = self.pg6.get_capture(1)
6009 p = capture[0]
6010 try:
6011 ip = p[IP]
6012 tcp = p[TCP]
6013 self.assertEqual(ip.src, external_addr)
6014 self.assertEqual(tcp.sport, external_port)
6015 self.assert_packet_checksums_valid(p)
6016 except:
6017 self.logger.error(ppp("Unexpected or invalid packet:", p))
6018 raise
6019
6020 # dynamic NAT from VRF1 to VRF0 (output-feature)
6021 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6022 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6023 TCP(sport=2345, dport=22))
6024 self.pg5.add_stream(p)
6025 self.pg_enable_capture(self.pg_interfaces)
6026 self.pg_start()
6027 capture = self.pg1.get_capture(1)
6028 p = capture[0]
6029 try:
6030 ip = p[IP]
6031 tcp = p[TCP]
6032 self.assertEqual(ip.src, self.nat_addr)
6033 self.assertNotEqual(tcp.sport, 2345)
6034 self.assert_packet_checksums_valid(p)
6035 port = tcp.sport
6036 except:
6037 self.logger.error(ppp("Unexpected or invalid packet:", p))
6038 raise
6039
6040 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6041 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6042 TCP(sport=22, dport=port))
6043 self.pg1.add_stream(p)
6044 self.pg_enable_capture(self.pg_interfaces)
6045 self.pg_start()
6046 capture = self.pg5.get_capture(1)
6047 p = capture[0]
6048 try:
6049 ip = p[IP]
6050 tcp = p[TCP]
6051 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6052 self.assertEqual(tcp.dport, 2345)
6053 self.assert_packet_checksums_valid(p)
6054 except:
6055 self.logger.error(ppp("Unexpected or invalid packet:", p))
6056 raise
6057
6058 # from client VRF1 to service VRF0
6059 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6060 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6061 TCP(sport=12346, dport=external_port))
6062 self.pg6.add_stream(p)
6063 self.pg_enable_capture(self.pg_interfaces)
6064 self.pg_start()
6065 capture = self.pg0.get_capture(1)
6066 p = capture[0]
6067 try:
6068 ip = p[IP]
6069 tcp = p[TCP]
6070 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6071 self.assertEqual(tcp.dport, local_port)
6072 self.assert_packet_checksums_valid(p)
6073 except:
6074 self.logger.error(ppp("Unexpected or invalid packet:", p))
6075 raise
6076
6077 # from service VRF0 back to client VRF1
6078 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6079 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6080 TCP(sport=local_port, dport=12346))
6081 self.pg0.add_stream(p)
6082 self.pg_enable_capture(self.pg_interfaces)
6083 self.pg_start()
6084 capture = self.pg6.get_capture(1)
6085 p = capture[0]
6086 try:
6087 ip = p[IP]
6088 tcp = p[TCP]
6089 self.assertEqual(ip.src, self.pg0.local_ip4)
6090 self.assertEqual(tcp.sport, external_port)
6091 self.assert_packet_checksums_valid(p)
6092 except:
6093 self.logger.error(ppp("Unexpected or invalid packet:", p))
6094 raise
6095
6096 # from client VRF0 to service VRF1
6097 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6098 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6099 TCP(sport=12347, dport=external_port))
6100 self.pg0.add_stream(p)
6101 self.pg_enable_capture(self.pg_interfaces)
6102 self.pg_start()
6103 capture = self.pg5.get_capture(1)
6104 p = capture[0]
6105 try:
6106 ip = p[IP]
6107 tcp = p[TCP]
6108 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6109 self.assertEqual(tcp.dport, local_port)
6110 self.assert_packet_checksums_valid(p)
6111 except:
6112 self.logger.error(ppp("Unexpected or invalid packet:", p))
6113 raise
6114
6115 # from service VRF1 back to client VRF0
6116 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6117 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6118 TCP(sport=local_port, dport=12347))
6119 self.pg5.add_stream(p)
6120 self.pg_enable_capture(self.pg_interfaces)
6121 self.pg_start()
6122 capture = self.pg0.get_capture(1)
6123 p = capture[0]
6124 try:
6125 ip = p[IP]
6126 tcp = p[TCP]
6127 self.assertEqual(ip.src, external_addr)
6128 self.assertEqual(tcp.sport, external_port)
6129 self.assert_packet_checksums_valid(p)
6130 except:
6131 self.logger.error(ppp("Unexpected or invalid packet:", p))
6132 raise
6133
6134 # from client to server (both VRF1, no translation)
6135 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6136 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6137 TCP(sport=12348, dport=local_port))
6138 self.pg6.add_stream(p)
6139 self.pg_enable_capture(self.pg_interfaces)
6140 self.pg_start()
6141 capture = self.pg5.get_capture(1)
6142 p = capture[0]
6143 try:
6144 ip = p[IP]
6145 tcp = p[TCP]
6146 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6147 self.assertEqual(tcp.dport, local_port)
6148 self.assert_packet_checksums_valid(p)
6149 except:
6150 self.logger.error(ppp("Unexpected or invalid packet:", p))
6151 raise
6152
6153 # from server back to client (both VRF1, no translation)
6154 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6155 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6156 TCP(sport=local_port, dport=12348))
6157 self.pg5.add_stream(p)
6158 self.pg_enable_capture(self.pg_interfaces)
6159 self.pg_start()
6160 capture = self.pg6.get_capture(1)
6161 p = capture[0]
6162 try:
6163 ip = p[IP]
6164 tcp = p[TCP]
6165 self.assertEqual(ip.src, self.pg5.remote_ip4)
6166 self.assertEqual(tcp.sport, local_port)
6167 self.assert_packet_checksums_valid(p)
6168 except:
6169 self.logger.error(ppp("Unexpected or invalid packet:", p))
6170 raise
6171
6172 # from client VRF1 to server VRF0 (no translation)
6173 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6174 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6175 TCP(sport=local_port, dport=12349))
6176 self.pg0.add_stream(p)
6177 self.pg_enable_capture(self.pg_interfaces)
6178 self.pg_start()
6179 capture = self.pg6.get_capture(1)
6180 p = capture[0]
6181 try:
6182 ip = p[IP]
6183 tcp = p[TCP]
6184 self.assertEqual(ip.src, self.pg0.remote_ip4)
6185 self.assertEqual(tcp.sport, local_port)
6186 self.assert_packet_checksums_valid(p)
6187 except:
6188 self.logger.error(ppp("Unexpected or invalid packet:", p))
6189 raise
6190
6191 # from server VRF0 back to client VRF1 (no translation)
6192 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6193 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6194 TCP(sport=local_port, dport=12349))
6195 self.pg0.add_stream(p)
6196 self.pg_enable_capture(self.pg_interfaces)
6197 self.pg_start()
6198 capture = self.pg6.get_capture(1)
6199 p = capture[0]
6200 try:
6201 ip = p[IP]
6202 tcp = p[TCP]
6203 self.assertEqual(ip.src, self.pg0.remote_ip4)
6204 self.assertEqual(tcp.sport, local_port)
6205 self.assert_packet_checksums_valid(p)
6206 except:
6207 self.logger.error(ppp("Unexpected or invalid packet:", p))
6208 raise
6209
6210 # from client VRF0 to server VRF1 (no translation)
6211 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6212 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6213 TCP(sport=12344, dport=local_port))
6214 self.pg0.add_stream(p)
6215 self.pg_enable_capture(self.pg_interfaces)
6216 self.pg_start()
6217 capture = self.pg5.get_capture(1)
6218 p = capture[0]
6219 try:
6220 ip = p[IP]
6221 tcp = p[TCP]
6222 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6223 self.assertEqual(tcp.dport, local_port)
6224 self.assert_packet_checksums_valid(p)
6225 except:
6226 self.logger.error(ppp("Unexpected or invalid packet:", p))
6227 raise
6228
6229 # from server VRF1 back to client VRF0 (no translation)
6230 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6231 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6232 TCP(sport=local_port, dport=12344))
6233 self.pg5.add_stream(p)
6234 self.pg_enable_capture(self.pg_interfaces)
6235 self.pg_start()
6236 capture = self.pg0.get_capture(1)
6237 p = capture[0]
6238 try:
6239 ip = p[IP]
6240 tcp = p[TCP]
6241 self.assertEqual(ip.src, self.pg5.remote_ip4)
6242 self.assertEqual(tcp.sport, local_port)
6243 self.assert_packet_checksums_valid(p)
6244 except:
6245 self.logger.error(ppp("Unexpected or invalid packet:", p))
6246 raise
6247
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006248 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006249 def test_session_timeout(self):
6250 """ NAT44 session timeouts """
6251 self.nat44_add_address(self.nat_addr)
6252 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6253 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6254 is_inside=0)
6255 self.vapi.nat_set_timeouts(icmp=5)
6256
6257 max_sessions = 1000
6258 pkts = []
6259 for i in range(0, max_sessions):
6260 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6261 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6262 IP(src=src, dst=self.pg1.remote_ip4) /
6263 ICMP(id=1025, type='echo-request'))
6264 pkts.append(p)
6265 self.pg0.add_stream(pkts)
6266 self.pg_enable_capture(self.pg_interfaces)
6267 self.pg_start()
6268 self.pg1.get_capture(max_sessions)
6269
6270 sleep(10)
6271
6272 pkts = []
6273 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006274 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006275 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6276 IP(src=src, dst=self.pg1.remote_ip4) /
6277 ICMP(id=1026, type='echo-request'))
6278 pkts.append(p)
6279 self.pg0.add_stream(pkts)
6280 self.pg_enable_capture(self.pg_interfaces)
6281 self.pg_start()
6282 self.pg1.get_capture(max_sessions)
6283
6284 nsessions = 0
6285 users = self.vapi.nat44_user_dump()
6286 for user in users:
6287 nsessions = nsessions + user.nsessions
6288 self.assertLess(nsessions, 2 * max_sessions)
6289
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006290 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006291 def test_session_rst_timeout(self):
6292 """ NAT44 session RST timeouts """
6293 self.nat44_add_address(self.nat_addr)
6294 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6295 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6296 is_inside=0)
6297 self.vapi.nat_set_timeouts(tcp_transitory=5)
6298
Matus Fabian15e8e682018-11-21 04:53:10 -08006299 self.initiate_tcp_session(self.pg0, self.pg1)
6300 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6301 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6302 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6303 flags="R"))
6304 self.pg0.add_stream(p)
6305 self.pg_enable_capture(self.pg_interfaces)
6306 self.pg_start()
6307 self.pg1.get_capture(1)
6308
Matus Fabian15e8e682018-11-21 04:53:10 -08006309 sleep(6)
6310
6311 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6312 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6313 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6314 flags="S"))
6315 self.pg0.add_stream(p)
6316 self.pg_enable_capture(self.pg_interfaces)
6317 self.pg_start()
6318 self.pg1.get_capture(1)
6319
6320 nsessions = 0
6321 users = self.vapi.nat44_user_dump()
6322 self.assertEqual(len(users), 1)
6323 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006324 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006325
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006326 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006327 def test_session_limit_per_user(self):
6328 """ Maximum sessions per user limit """
6329 self.nat44_add_address(self.nat_addr)
6330 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6331 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6332 is_inside=0)
6333 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6334 src_address=self.pg2.local_ip4n,
6335 path_mtu=512,
6336 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07006337 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006338
6339 # get maximum number of translations per user
6340 nat44_config = self.vapi.nat_show_config()
6341
6342 pkts = []
6343 for port in range(0, nat44_config.max_translations_per_user):
6344 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6345 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6346 UDP(sport=1025 + port, dport=1025 + port))
6347 pkts.append(p)
6348
6349 self.pg0.add_stream(pkts)
6350 self.pg_enable_capture(self.pg_interfaces)
6351 self.pg_start()
6352 capture = self.pg1.get_capture(len(pkts))
6353
Ole Troane1ade682019-03-04 23:55:43 +01006354 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6355 src_port=self.ipfix_src_port)
Matus Fabian878c6462018-08-23 00:33:35 -07006356
6357 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6358 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6359 UDP(sport=3001, dport=3002))
6360 self.pg0.add_stream(p)
6361 self.pg_enable_capture(self.pg_interfaces)
6362 self.pg_start()
6363 capture = self.pg1.assert_nothing_captured()
6364
6365 # verify IPFIX logging
6366 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6367 sleep(1)
6368 capture = self.pg2.get_capture(10)
6369 ipfix = IPFIXDecoder()
6370 # first load template
6371 for p in capture:
6372 self.assertTrue(p.haslayer(IPFIX))
6373 if p.haslayer(Template):
6374 ipfix.add_template(p.getlayer(Template))
6375 # verify events in data set
6376 for p in capture:
6377 if p.haslayer(Data):
6378 data = ipfix.decode_data_set(p.getlayer(Set))
6379 self.verify_ipfix_max_entries_per_user(
6380 data,
6381 nat44_config.max_translations_per_user,
6382 self.pg0.remote_ip4n)
6383
Matus Fabian8fdc0152018-09-24 04:41:28 -07006384 sleep(6)
6385 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6386 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6387 UDP(sport=3001, dport=3002))
6388 self.pg0.add_stream(p)
6389 self.pg_enable_capture(self.pg_interfaces)
6390 self.pg_start()
6391 self.pg1.get_capture(1)
6392
Matus Fabianad1f3e12018-11-28 21:26:34 -08006393 def test_syslog_sess(self):
6394 """ Test syslog session creation and deletion """
6395 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006396 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006397 self.nat44_add_address(self.nat_addr)
6398 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6399 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6400 is_inside=0)
6401
6402 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6403 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6404 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6405 self.pg0.add_stream(p)
6406 self.pg_enable_capture(self.pg_interfaces)
6407 self.pg_start()
6408 capture = self.pg1.get_capture(1)
6409 self.tcp_port_out = capture[0][TCP].sport
6410 capture = self.pg2.get_capture(1)
6411 self.verify_syslog_sess(capture[0][Raw].load)
6412
6413 self.pg_enable_capture(self.pg_interfaces)
6414 self.pg_start()
6415 self.nat44_add_address(self.nat_addr, is_add=0)
6416 capture = self.pg2.get_capture(1)
6417 self.verify_syslog_sess(capture[0][Raw].load, False)
6418
Matus Fabiande886752016-12-07 03:38:19 -08006419 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006420 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006421 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006422 self.logger.info(self.vapi.cli("show nat44 addresses"))
6423 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6424 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6425 self.logger.info(self.vapi.cli("show nat44 interface address"))
6426 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07006427 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07006428 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006429 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006430 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006431
Matus Fabianeea28d72017-01-13 04:15:54 -08006432
Juraj Slobodacba69362017-12-19 02:09:32 +01006433class TestNAT44Out2InDPO(MethodHolder):
6434 """ NAT44 Test Cases using out2in DPO """
6435
6436 @classmethod
6437 def setUpConstants(cls):
6438 super(TestNAT44Out2InDPO, cls).setUpConstants()
6439 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6440
6441 @classmethod
6442 def setUpClass(cls):
6443 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006444 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006445
6446 try:
6447 cls.tcp_port_in = 6303
6448 cls.tcp_port_out = 6303
6449 cls.udp_port_in = 6304
6450 cls.udp_port_out = 6304
6451 cls.icmp_id_in = 6305
6452 cls.icmp_id_out = 6305
6453 cls.nat_addr = '10.0.0.3'
6454 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6455 cls.dst_ip4 = '192.168.70.1'
6456
6457 cls.create_pg_interfaces(range(2))
6458
6459 cls.pg0.admin_up()
6460 cls.pg0.config_ip4()
6461 cls.pg0.resolve_arp()
6462
6463 cls.pg1.admin_up()
6464 cls.pg1.config_ip6()
6465 cls.pg1.resolve_ndp()
6466
Ole Troana5b2eec2019-03-11 19:23:25 +01006467 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
Juraj Slobodacba69362017-12-19 02:09:32 +01006468 dst_address_length=0,
6469 next_hop_address=cls.pg1.remote_ip6n,
Ole Troana5b2eec2019-03-11 19:23:25 +01006470 next_hop_sw_if_index=cls.pg1.sw_if_index,
6471 is_ipv6=True)
Juraj Slobodacba69362017-12-19 02:09:32 +01006472
6473 except Exception:
6474 super(TestNAT44Out2InDPO, cls).tearDownClass()
6475 raise
6476
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006477 @classmethod
6478 def tearDownClass(cls):
6479 super(TestNAT44Out2InDPO, cls).tearDownClass()
6480
Juraj Slobodacba69362017-12-19 02:09:32 +01006481 def configure_xlat(self):
6482 self.dst_ip6_pfx = '1:2:3::'
6483 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6484 self.dst_ip6_pfx)
6485 self.dst_ip6_pfx_len = 96
6486 self.src_ip6_pfx = '4:5:6::'
6487 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6488 self.src_ip6_pfx)
6489 self.src_ip6_pfx_len = 96
6490 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6491 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006492 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006493
Ole Troanffba3c32018-11-22 12:53:00 +01006494 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006495 def test_464xlat_ce(self):
6496 """ Test 464XLAT CE with NAT44 """
6497
Matus Fabian69ce30d2018-08-22 01:27:10 -07006498 nat_config = self.vapi.nat_show_config()
6499 self.assertEqual(1, nat_config.out2in_dpo)
6500
Juraj Slobodacba69362017-12-19 02:09:32 +01006501 self.configure_xlat()
6502
6503 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6504 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6505
6506 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6507 self.dst_ip6_pfx_len)
6508 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6509 self.src_ip6_pfx_len)
6510
6511 try:
6512 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6513 self.pg0.add_stream(pkts)
6514 self.pg_enable_capture(self.pg_interfaces)
6515 self.pg_start()
6516 capture = self.pg1.get_capture(len(pkts))
6517 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6518 dst_ip=out_src_ip6)
6519
6520 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6521 out_dst_ip6)
6522 self.pg1.add_stream(pkts)
6523 self.pg_enable_capture(self.pg_interfaces)
6524 self.pg_start()
6525 capture = self.pg0.get_capture(len(pkts))
6526 self.verify_capture_in(capture, self.pg0)
6527 finally:
6528 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6529 is_add=0)
6530 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6531 self.nat_addr_n, is_add=0)
6532
Ole Troanffba3c32018-11-22 12:53:00 +01006533 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006534 def test_464xlat_ce_no_nat(self):
6535 """ Test 464XLAT CE without NAT44 """
6536
6537 self.configure_xlat()
6538
6539 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6540 self.dst_ip6_pfx_len)
6541 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6542 self.src_ip6_pfx_len)
6543
6544 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6545 self.pg0.add_stream(pkts)
6546 self.pg_enable_capture(self.pg_interfaces)
6547 self.pg_start()
6548 capture = self.pg1.get_capture(len(pkts))
6549 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6550 nat_ip=out_dst_ip6, same_port=True)
6551
6552 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6553 self.pg1.add_stream(pkts)
6554 self.pg_enable_capture(self.pg_interfaces)
6555 self.pg_start()
6556 capture = self.pg0.get_capture(len(pkts))
6557 self.verify_capture_in(capture, self.pg0)
6558
6559
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006560class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006561 """ Deterministic NAT Test Cases """
6562
6563 @classmethod
6564 def setUpConstants(cls):
6565 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006566 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006567
6568 @classmethod
6569 def setUpClass(cls):
6570 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006571 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006572
6573 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006574 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006575 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006576 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006577 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006578 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006579 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006580
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006581 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006582 cls.interfaces = list(cls.pg_interfaces)
6583
6584 for i in cls.interfaces:
6585 i.admin_up()
6586 i.config_ip4()
6587 i.resolve_arp()
6588
Martin Gálik977c1cb2017-03-30 23:21:51 -07006589 cls.pg0.generate_remote_hosts(2)
6590 cls.pg0.configure_ipv4_neighbors()
6591
Matus Fabian066f0342017-02-10 03:48:01 -08006592 except Exception:
6593 super(TestDeterministicNAT, cls).tearDownClass()
6594 raise
6595
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006596 @classmethod
6597 def tearDownClass(cls):
6598 super(TestDeterministicNAT, cls).tearDownClass()
6599
Martin Gálik977c1cb2017-03-30 23:21:51 -07006600 def create_stream_in(self, in_if, out_if, ttl=64):
6601 """
6602 Create packet stream for inside network
6603
6604 :param in_if: Inside interface
6605 :param out_if: Outside interface
6606 :param ttl: TTL of generated packets
6607 """
6608 pkts = []
6609 # TCP
6610 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6611 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006612 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006613 pkts.append(p)
6614
6615 # UDP
6616 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6617 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006618 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006619 pkts.append(p)
6620
6621 # ICMP
6622 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6623 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6624 ICMP(id=self.icmp_id_in, type='echo-request'))
6625 pkts.append(p)
6626
6627 return pkts
6628
6629 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6630 """
6631 Create packet stream for outside network
6632
6633 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006634 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006635 :param ttl: TTL of generated packets
6636 """
6637 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006638 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006639 pkts = []
6640 # TCP
6641 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6642 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006643 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006644 pkts.append(p)
6645
6646 # UDP
6647 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6648 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006649 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006650 pkts.append(p)
6651
6652 # ICMP
6653 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6654 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6655 ICMP(id=self.icmp_external_id, type='echo-reply'))
6656 pkts.append(p)
6657
6658 return pkts
6659
Matus Fabian05ca4a32018-09-04 23:45:13 -07006660 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006661 """
6662 Verify captured packets on outside network
6663
6664 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006665 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07006666 :param same_port: Source port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006667 """
6668 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006669 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006670 for packet in capture:
6671 try:
6672 self.assertEqual(packet[IP].src, nat_ip)
6673 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006674 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006675 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006676 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006677 else:
6678 self.icmp_external_id = packet[ICMP].id
6679 except:
6680 self.logger.error(ppp("Unexpected or invalid packet "
6681 "(outside network):", packet))
6682 raise
6683
Matus Fabian066f0342017-02-10 03:48:01 -08006684 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006685 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006686 in_addr = '172.16.255.0'
6687 out_addr = '172.17.255.50'
6688 in_addr_t = '172.16.255.20'
6689 in_addr_n = socket.inet_aton(in_addr)
6690 out_addr_n = socket.inet_aton(out_addr)
6691 in_addr_t_n = socket.inet_aton(in_addr_t)
6692 in_plen = 24
6693 out_plen = 32
6694
Matus Fabian2ba92e32017-08-21 07:05:03 -07006695 nat_config = self.vapi.nat_show_config()
6696 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006697
Matus Fabian2ba92e32017-08-21 07:05:03 -07006698 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006699
Matus Fabian2ba92e32017-08-21 07:05:03 -07006700 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006701 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006702 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006703 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6704
Matus Fabian2ba92e32017-08-21 07:05:03 -07006705 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006706 self.assertEqual(len(deterministic_mappings), 1)
6707 dsm = deterministic_mappings[0]
6708 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6709 self.assertEqual(in_plen, dsm.in_plen)
6710 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6711 self.assertEqual(out_plen, dsm.out_plen)
6712
Matus Fabian2ba92e32017-08-21 07:05:03 -07006713 self.clear_nat_det()
6714 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006715 self.assertEqual(len(deterministic_mappings), 0)
6716
Matus Fabian6a0946f2017-04-12 03:36:13 -07006717 def test_set_timeouts(self):
6718 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006719 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006720
Matus Fabian878c6462018-08-23 00:33:35 -07006721 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6722 timeouts_before.tcp_established + 10,
6723 timeouts_before.tcp_transitory + 10,
6724 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006725
Matus Fabian878c6462018-08-23 00:33:35 -07006726 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006727
6728 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6729 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6730 self.assertNotEqual(timeouts_before.tcp_established,
6731 timeouts_after.tcp_established)
6732 self.assertNotEqual(timeouts_before.tcp_transitory,
6733 timeouts_after.tcp_transitory)
6734
Martin Gálik977c1cb2017-03-30 23:21:51 -07006735 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006736 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006737
6738 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006739
Matus Fabian2ba92e32017-08-21 07:05:03 -07006740 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6741 32,
6742 socket.inet_aton(nat_ip),
6743 32)
6744 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6745 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6746 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006747
6748 # in2out
6749 pkts = self.create_stream_in(self.pg0, self.pg1)
6750 self.pg0.add_stream(pkts)
6751 self.pg_enable_capture(self.pg_interfaces)
6752 self.pg_start()
6753 capture = self.pg1.get_capture(len(pkts))
6754 self.verify_capture_out(capture, nat_ip)
6755
6756 # out2in
6757 pkts = self.create_stream_out(self.pg1, nat_ip)
6758 self.pg1.add_stream(pkts)
6759 self.pg_enable_capture(self.pg_interfaces)
6760 self.pg_start()
6761 capture = self.pg0.get_capture(len(pkts))
6762 self.verify_capture_in(capture, self.pg0)
6763
Martin Gálik9806eae2017-04-25 01:25:08 -07006764 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006765 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006766 self.assertEqual(len(sessions), 3)
6767
6768 # TCP session
6769 s = sessions[0]
6770 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6771 self.assertEqual(s.in_port, self.tcp_port_in)
6772 self.assertEqual(s.out_port, self.tcp_port_out)
6773 self.assertEqual(s.ext_port, self.tcp_external_port)
6774
6775 # UDP session
6776 s = sessions[1]
6777 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6778 self.assertEqual(s.in_port, self.udp_port_in)
6779 self.assertEqual(s.out_port, self.udp_port_out)
6780 self.assertEqual(s.ext_port, self.udp_external_port)
6781
6782 # ICMP session
6783 s = sessions[2]
6784 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6785 self.assertEqual(s.in_port, self.icmp_id_in)
6786 self.assertEqual(s.out_port, self.icmp_external_id)
6787
Martin Gálik977c1cb2017-03-30 23:21:51 -07006788 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006789 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006790
6791 nat_ip = "10.0.0.10"
6792 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006793 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006794
6795 host0 = self.pg0.remote_hosts[0]
6796 host1 = self.pg0.remote_hosts[1]
6797
Matus Fabian2ba92e32017-08-21 07:05:03 -07006798 self.vapi.nat_det_add_del_map(host0.ip4n,
6799 24,
6800 socket.inet_aton(nat_ip),
6801 32)
6802 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6803 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6804 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006805
6806 # host0 to out
6807 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6808 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006809 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006810 self.pg0.add_stream(p)
6811 self.pg_enable_capture(self.pg_interfaces)
6812 self.pg_start()
6813 capture = self.pg1.get_capture(1)
6814 p = capture[0]
6815 try:
6816 ip = p[IP]
6817 tcp = p[TCP]
6818 self.assertEqual(ip.src, nat_ip)
6819 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006820 self.assertEqual(tcp.dport, external_port)
6821 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006822 except:
6823 self.logger.error(ppp("Unexpected or invalid packet:", p))
6824 raise
6825
6826 # host1 to out
6827 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6828 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006829 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006830 self.pg0.add_stream(p)
6831 self.pg_enable_capture(self.pg_interfaces)
6832 self.pg_start()
6833 capture = self.pg1.get_capture(1)
6834 p = capture[0]
6835 try:
6836 ip = p[IP]
6837 tcp = p[TCP]
6838 self.assertEqual(ip.src, nat_ip)
6839 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006840 self.assertEqual(tcp.dport, external_port)
6841 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006842 except:
6843 self.logger.error(ppp("Unexpected or invalid packet:", p))
6844 raise
6845
Matus Fabian2ba92e32017-08-21 07:05:03 -07006846 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006847 self.assertEqual(1, len(dms))
6848 self.assertEqual(2, dms[0].ses_num)
6849
6850 # out to host0
6851 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6852 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006853 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006854 self.pg1.add_stream(p)
6855 self.pg_enable_capture(self.pg_interfaces)
6856 self.pg_start()
6857 capture = self.pg0.get_capture(1)
6858 p = capture[0]
6859 try:
6860 ip = p[IP]
6861 tcp = p[TCP]
6862 self.assertEqual(ip.src, self.pg1.remote_ip4)
6863 self.assertEqual(ip.dst, host0.ip4)
6864 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006865 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006866 except:
6867 self.logger.error(ppp("Unexpected or invalid packet:", p))
6868 raise
6869
6870 # out to host1
6871 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6872 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006873 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006874 self.pg1.add_stream(p)
6875 self.pg_enable_capture(self.pg_interfaces)
6876 self.pg_start()
6877 capture = self.pg0.get_capture(1)
6878 p = capture[0]
6879 try:
6880 ip = p[IP]
6881 tcp = p[TCP]
6882 self.assertEqual(ip.src, self.pg1.remote_ip4)
6883 self.assertEqual(ip.dst, host1.ip4)
6884 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006885 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006886 except:
6887 self.logger.error(ppp("Unexpected or invalid packet", p))
6888 raise
6889
Martin Gálik6bc8c642017-04-19 01:12:27 -07006890 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006891 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6892 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006893 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006894 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006895 dms = self.vapi.nat_det_map_dump()
6896 self.assertEqual(dms[0].ses_num, 1)
6897
6898 self.vapi.nat_det_close_session_in(host0.ip4n,
6899 port_in,
6900 self.pg1.remote_ip4n,
6901 external_port)
6902 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006903 self.assertEqual(dms[0].ses_num, 0)
6904
Martin Gálik977c1cb2017-03-30 23:21:51 -07006905 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006906 """ Deterministic NAT TCP session close from inside network """
6907 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6908 32,
6909 socket.inet_aton(self.nat_addr),
6910 32)
6911 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6912 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6913 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006914
6915 self.initiate_tcp_session(self.pg0, self.pg1)
6916
6917 # close the session from inside
6918 try:
6919 # FIN packet in -> out
6920 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6921 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006922 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006923 flags="F"))
6924 self.pg0.add_stream(p)
6925 self.pg_enable_capture(self.pg_interfaces)
6926 self.pg_start()
6927 self.pg1.get_capture(1)
6928
6929 pkts = []
6930
6931 # ACK packet out -> in
6932 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006933 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006934 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006935 flags="A"))
6936 pkts.append(p)
6937
6938 # FIN packet out -> in
6939 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006940 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006941 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006942 flags="F"))
6943 pkts.append(p)
6944
6945 self.pg1.add_stream(pkts)
6946 self.pg_enable_capture(self.pg_interfaces)
6947 self.pg_start()
6948 self.pg0.get_capture(2)
6949
6950 # ACK packet in -> out
6951 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6952 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006953 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006954 flags="A"))
6955 self.pg0.add_stream(p)
6956 self.pg_enable_capture(self.pg_interfaces)
6957 self.pg_start()
6958 self.pg1.get_capture(1)
6959
Matus Fabian2ba92e32017-08-21 07:05:03 -07006960 # Check if deterministic NAT44 closed the session
6961 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006962 self.assertEqual(0, dms[0].ses_num)
6963 except:
6964 self.logger.error("TCP session termination failed")
6965 raise
6966
6967 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006968 """ Deterministic NAT TCP session close from outside network """
6969 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6970 32,
6971 socket.inet_aton(self.nat_addr),
6972 32)
6973 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6974 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6975 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006976
6977 self.initiate_tcp_session(self.pg0, self.pg1)
6978
6979 # close the session from outside
6980 try:
6981 # FIN packet out -> in
6982 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006983 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006984 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006985 flags="F"))
6986 self.pg1.add_stream(p)
6987 self.pg_enable_capture(self.pg_interfaces)
6988 self.pg_start()
6989 self.pg0.get_capture(1)
6990
6991 pkts = []
6992
6993 # ACK packet in -> out
6994 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6995 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006996 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006997 flags="A"))
6998 pkts.append(p)
6999
7000 # ACK packet in -> out
7001 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7002 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007003 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007004 flags="F"))
7005 pkts.append(p)
7006
7007 self.pg0.add_stream(pkts)
7008 self.pg_enable_capture(self.pg_interfaces)
7009 self.pg_start()
7010 self.pg1.get_capture(2)
7011
7012 # ACK packet out -> in
7013 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007014 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007015 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007016 flags="A"))
7017 self.pg1.add_stream(p)
7018 self.pg_enable_capture(self.pg_interfaces)
7019 self.pg_start()
7020 self.pg0.get_capture(1)
7021
Matus Fabian2ba92e32017-08-21 07:05:03 -07007022 # Check if deterministic NAT44 closed the session
7023 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007024 self.assertEqual(0, dms[0].ses_num)
7025 except:
7026 self.logger.error("TCP session termination failed")
7027 raise
7028
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007029 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007030 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007031 """ Deterministic NAT session timeouts """
7032 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7033 32,
7034 socket.inet_aton(self.nat_addr),
7035 32)
7036 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7037 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7038 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007039
7040 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07007041 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007042 pkts = self.create_stream_in(self.pg0, self.pg1)
7043 self.pg0.add_stream(pkts)
7044 self.pg_enable_capture(self.pg_interfaces)
7045 self.pg_start()
7046 capture = self.pg1.get_capture(len(pkts))
7047 sleep(15)
7048
Matus Fabian2ba92e32017-08-21 07:05:03 -07007049 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007050 self.assertEqual(0, dms[0].ses_num)
7051
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007052 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007053 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007054 """ Deterministic NAT maximum sessions per user limit """
7055 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7056 32,
7057 socket.inet_aton(self.nat_addr),
7058 32)
7059 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7060 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7061 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007062 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7063 src_address=self.pg2.local_ip4n,
7064 path_mtu=512,
7065 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01007066 self.vapi.nat_ipfix_enable_disable()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007067
7068 pkts = []
7069 for port in range(1025, 2025):
7070 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7071 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7072 UDP(sport=port, dport=port))
7073 pkts.append(p)
7074
7075 self.pg0.add_stream(pkts)
7076 self.pg_enable_capture(self.pg_interfaces)
7077 self.pg_start()
7078 capture = self.pg1.get_capture(len(pkts))
7079
7080 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7081 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007082 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007083 self.pg0.add_stream(p)
7084 self.pg_enable_capture(self.pg_interfaces)
7085 self.pg_start()
7086 capture = self.pg1.assert_nothing_captured()
7087
Martin Gálikf7e655d2017-04-27 02:13:26 -07007088 # verify ICMP error packet
7089 capture = self.pg0.get_capture(1)
7090 p = capture[0]
7091 self.assertTrue(p.haslayer(ICMP))
7092 icmp = p[ICMP]
7093 self.assertEqual(icmp.type, 3)
7094 self.assertEqual(icmp.code, 1)
7095 self.assertTrue(icmp.haslayer(IPerror))
7096 inner_ip = icmp[IPerror]
7097 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7098 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7099
Matus Fabian2ba92e32017-08-21 07:05:03 -07007100 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007101
7102 self.assertEqual(1000, dms[0].ses_num)
7103
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007104 # verify IPFIX logging
7105 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007106 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007107 capture = self.pg2.get_capture(2)
7108 ipfix = IPFIXDecoder()
7109 # first load template
7110 for p in capture:
7111 self.assertTrue(p.haslayer(IPFIX))
7112 if p.haslayer(Template):
7113 ipfix.add_template(p.getlayer(Template))
7114 # verify events in data set
7115 for p in capture:
7116 if p.haslayer(Data):
7117 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007118 self.verify_ipfix_max_entries_per_user(data,
7119 1000,
7120 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007121
Matus Fabian2ba92e32017-08-21 07:05:03 -07007122 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007123 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007124 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007125 """
Ole Troane1ade682019-03-04 23:55:43 +01007126 self.vapi.nat_ipfix_enable_disable(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007127 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007128 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007129 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007130 self.vapi.nat_det_add_del_map(dsm.in_addr,
7131 dsm.in_plen,
7132 dsm.out_addr,
7133 dsm.out_plen,
7134 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08007135
Matus Fabian2ba92e32017-08-21 07:05:03 -07007136 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007137 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007138 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7139 intf.is_inside,
7140 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007141
Matus Fabian066f0342017-02-10 03:48:01 -08007142 def tearDown(self):
7143 super(TestDeterministicNAT, self).tearDown()
7144 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08007145 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07007146 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08007147 self.logger.info(
7148 self.vapi.cli("show nat44 deterministic mappings"))
7149 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08007150 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07007151 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007152
Matus Fabian06596c52017-06-06 04:53:28 -07007153
7154class TestNAT64(MethodHolder):
7155 """ NAT64 Test Cases """
7156
7157 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007158 def setUpConstants(cls):
7159 super(TestNAT64, cls).setUpConstants()
7160 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7161 "nat64 st hash buckets 256", "}"])
7162
7163 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007164 def setUpClass(cls):
7165 super(TestNAT64, cls).setUpClass()
7166
7167 try:
7168 cls.tcp_port_in = 6303
7169 cls.tcp_port_out = 6303
7170 cls.udp_port_in = 6304
7171 cls.udp_port_out = 6304
7172 cls.icmp_id_in = 6305
7173 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007174 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007175 cls.nat_addr = '10.0.0.3'
7176 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007177 cls.vrf1_id = 10
7178 cls.vrf1_nat_addr = '10.0.10.3'
7179 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7180 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08007181 cls.ipfix_src_port = 4739
7182 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007183
Juraj Slobodac746a152018-07-09 02:36:37 +02007184 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007185 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007186 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007187 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7188
Ole Troan9a475372019-03-05 16:58:24 +01007189 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7190 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007191
Matus Fabian029f3d22017-06-15 02:28:50 -07007192 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7193
7194 cls.pg0.generate_remote_hosts(2)
7195
Matus Fabian06596c52017-06-06 04:53:28 -07007196 for i in cls.ip6_interfaces:
7197 i.admin_up()
7198 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007199 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007200
7201 for i in cls.ip4_interfaces:
7202 i.admin_up()
7203 i.config_ip4()
7204 i.resolve_arp()
7205
Matus Fabian36ea2d62017-10-24 04:13:49 -07007206 cls.pg3.admin_up()
7207 cls.pg3.config_ip4()
7208 cls.pg3.resolve_arp()
7209 cls.pg3.config_ip6()
7210 cls.pg3.configure_ipv6_neighbors()
7211
Juraj Slobodac746a152018-07-09 02:36:37 +02007212 cls.pg5.admin_up()
7213 cls.pg5.config_ip6()
7214
Matus Fabian06596c52017-06-06 04:53:28 -07007215 except Exception:
7216 super(TestNAT64, cls).tearDownClass()
7217 raise
7218
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007219 @classmethod
7220 def tearDownClass(cls):
7221 super(TestNAT64, cls).tearDownClass()
7222
Juraj Slobodac746a152018-07-09 02:36:37 +02007223 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7224 """ NAT64 inside interface handles Neighbor Advertisement """
7225
7226 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7227
7228 # Try to send ping
7229 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7230 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7231 ICMPv6EchoRequest())
7232 pkts = [ping]
7233 self.pg5.add_stream(pkts)
7234 self.pg_enable_capture(self.pg_interfaces)
7235 self.pg_start()
7236
7237 # Wait for Neighbor Solicitation
7238 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007239 packet = capture[0]
7240 try:
7241 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007242 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007243 tgt = packet[ICMPv6ND_NS].tgt
7244 except:
7245 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7246 raise
7247
7248 # Send Neighbor Advertisement
7249 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7250 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7251 ICMPv6ND_NA(tgt=tgt) /
7252 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7253 pkts = [p]
7254 self.pg5.add_stream(pkts)
7255 self.pg_enable_capture(self.pg_interfaces)
7256 self.pg_start()
7257
7258 # Try to send ping again
7259 pkts = [ping]
7260 self.pg5.add_stream(pkts)
7261 self.pg_enable_capture(self.pg_interfaces)
7262 self.pg_start()
7263
7264 # Wait for ping reply
7265 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007266 packet = capture[0]
7267 try:
7268 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7269 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007270 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007271 except:
7272 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7273 raise
7274
Matus Fabian06596c52017-06-06 04:53:28 -07007275 def test_pool(self):
7276 """ Add/delete address to NAT64 pool """
7277 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7278
7279 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7280
7281 addresses = self.vapi.nat64_pool_addr_dump()
7282 self.assertEqual(len(addresses), 1)
7283 self.assertEqual(addresses[0].address, nat_addr)
7284
7285 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7286
7287 addresses = self.vapi.nat64_pool_addr_dump()
7288 self.assertEqual(len(addresses), 0)
7289
7290 def test_interface(self):
7291 """ Enable/disable NAT64 feature on the interface """
7292 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7293 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7294
7295 interfaces = self.vapi.nat64_interface_dump()
7296 self.assertEqual(len(interfaces), 2)
7297 pg0_found = False
7298 pg1_found = False
7299 for intf in interfaces:
7300 if intf.sw_if_index == self.pg0.sw_if_index:
7301 self.assertEqual(intf.is_inside, 1)
7302 pg0_found = True
7303 elif intf.sw_if_index == self.pg1.sw_if_index:
7304 self.assertEqual(intf.is_inside, 0)
7305 pg1_found = True
7306 self.assertTrue(pg0_found)
7307 self.assertTrue(pg1_found)
7308
7309 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007310 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007311 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007312 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007313
7314 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7315 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7316
7317 interfaces = self.vapi.nat64_interface_dump()
7318 self.assertEqual(len(interfaces), 0)
7319
7320 def test_static_bib(self):
7321 """ Add/delete static BIB entry """
7322 in_addr = socket.inet_pton(socket.AF_INET6,
7323 '2001:db8:85a3::8a2e:370:7334')
7324 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7325 in_port = 1234
7326 out_port = 5678
7327 proto = IP_PROTOS.tcp
7328
7329 self.vapi.nat64_add_del_static_bib(in_addr,
7330 out_addr,
7331 in_port,
7332 out_port,
7333 proto)
7334 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7335 static_bib_num = 0
7336 for bibe in bib:
7337 if bibe.is_static:
7338 static_bib_num += 1
7339 self.assertEqual(bibe.i_addr, in_addr)
7340 self.assertEqual(bibe.o_addr, out_addr)
7341 self.assertEqual(bibe.i_port, in_port)
7342 self.assertEqual(bibe.o_port, out_port)
7343 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007344 bibs = self.statistics.get_counter('/nat64/total-bibs')
7345 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007346
7347 self.vapi.nat64_add_del_static_bib(in_addr,
7348 out_addr,
7349 in_port,
7350 out_port,
7351 proto,
7352 is_add=0)
7353 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7354 static_bib_num = 0
7355 for bibe in bib:
7356 if bibe.is_static:
7357 static_bib_num += 1
7358 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007359 bibs = self.statistics.get_counter('/nat64/total-bibs')
7360 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007361
7362 def test_set_timeouts(self):
7363 """ Set NAT64 timeouts """
7364 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007365 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007366 self.assertEqual(timeouts.udp, 300)
7367 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007368 self.assertEqual(timeouts.tcp_transitory, 240)
7369 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007370
7371 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07007372 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7373 tcp_established=7450)
7374 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007375 self.assertEqual(timeouts.udp, 200)
7376 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007377 self.assertEqual(timeouts.tcp_transitory, 250)
7378 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007379
7380 def test_dynamic(self):
7381 """ NAT64 dynamic translation test """
7382 self.tcp_port_in = 6303
7383 self.udp_port_in = 6304
7384 self.icmp_id_in = 6305
7385
7386 ses_num_start = self.nat64_get_ses_num()
7387
7388 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7389 self.nat_addr_n)
7390 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7391 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7392
7393 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007394 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7395 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7396 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7397 totaln = self.statistics.get_counter(
7398 '/err/nat64-in2out/good in2out packets processed')
7399
Matus Fabian06596c52017-06-06 04:53:28 -07007400 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7401 self.pg0.add_stream(pkts)
7402 self.pg_enable_capture(self.pg_interfaces)
7403 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007404 capture = self.pg1.get_capture(len(pkts))
7405 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007406 dst_ip=self.pg1.remote_ip4)
7407
Matus Fabiana5e73762018-12-14 01:55:16 -08007408 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7409 self.assertEqual(err - tcpn, 1)
7410 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7411 self.assertEqual(err - udpn, 1)
7412 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7413 self.assertEqual(err - icmpn, 1)
7414 err = self.statistics.get_counter(
7415 '/err/nat64-in2out/good in2out packets processed')
7416 self.assertEqual(err - totaln, 3)
7417
Matus Fabian06596c52017-06-06 04:53:28 -07007418 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007419 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7420 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7421 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7422 totaln = self.statistics.get_counter(
7423 '/err/nat64-out2in/good out2in packets processed')
7424
Matus Fabian06596c52017-06-06 04:53:28 -07007425 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7426 self.pg1.add_stream(pkts)
7427 self.pg_enable_capture(self.pg_interfaces)
7428 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007429 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007430 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7431 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7432
Matus Fabiana5e73762018-12-14 01:55:16 -08007433 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7434 self.assertEqual(err - tcpn, 1)
7435 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7436 self.assertEqual(err - udpn, 1)
7437 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7438 self.assertEqual(err - icmpn, 1)
7439 err = self.statistics.get_counter(
7440 '/err/nat64-out2in/good out2in packets processed')
7441 self.assertEqual(err - totaln, 3)
7442
Matus Fabianfd0d5082018-12-18 01:08:51 -08007443 bibs = self.statistics.get_counter('/nat64/total-bibs')
7444 self.assertEqual(bibs[0][0], 3)
7445 sessions = self.statistics.get_counter('/nat64/total-sessions')
7446 self.assertEqual(sessions[0][0], 3)
7447
Matus Fabian06596c52017-06-06 04:53:28 -07007448 # in2out
7449 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7450 self.pg0.add_stream(pkts)
7451 self.pg_enable_capture(self.pg_interfaces)
7452 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007453 capture = self.pg1.get_capture(len(pkts))
7454 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007455 dst_ip=self.pg1.remote_ip4)
7456
7457 # out2in
7458 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7459 self.pg1.add_stream(pkts)
7460 self.pg_enable_capture(self.pg_interfaces)
7461 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007462 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007463 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7464
7465 ses_num_end = self.nat64_get_ses_num()
7466
7467 self.assertEqual(ses_num_end - ses_num_start, 3)
7468
Matus Fabian029f3d22017-06-15 02:28:50 -07007469 # tenant with specific VRF
7470 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7471 self.vrf1_nat_addr_n,
7472 vrf_id=self.vrf1_id)
7473 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7474
7475 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7476 self.pg2.add_stream(pkts)
7477 self.pg_enable_capture(self.pg_interfaces)
7478 self.pg_start()
7479 capture = self.pg1.get_capture(len(pkts))
7480 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7481 dst_ip=self.pg1.remote_ip4)
7482
7483 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7484 self.pg1.add_stream(pkts)
7485 self.pg_enable_capture(self.pg_interfaces)
7486 self.pg_start()
7487 capture = self.pg2.get_capture(len(pkts))
7488 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7489
Matus Fabian06596c52017-06-06 04:53:28 -07007490 def test_static(self):
7491 """ NAT64 static translation test """
7492 self.tcp_port_in = 60303
7493 self.udp_port_in = 60304
7494 self.icmp_id_in = 60305
7495 self.tcp_port_out = 60303
7496 self.udp_port_out = 60304
7497 self.icmp_id_out = 60305
7498
7499 ses_num_start = self.nat64_get_ses_num()
7500
7501 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7502 self.nat_addr_n)
7503 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7504 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7505
7506 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7507 self.nat_addr_n,
7508 self.tcp_port_in,
7509 self.tcp_port_out,
7510 IP_PROTOS.tcp)
7511 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7512 self.nat_addr_n,
7513 self.udp_port_in,
7514 self.udp_port_out,
7515 IP_PROTOS.udp)
7516 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7517 self.nat_addr_n,
7518 self.icmp_id_in,
7519 self.icmp_id_out,
7520 IP_PROTOS.icmp)
7521
7522 # in2out
7523 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7524 self.pg0.add_stream(pkts)
7525 self.pg_enable_capture(self.pg_interfaces)
7526 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007527 capture = self.pg1.get_capture(len(pkts))
7528 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007529 dst_ip=self.pg1.remote_ip4, same_port=True)
7530
7531 # out2in
7532 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7533 self.pg1.add_stream(pkts)
7534 self.pg_enable_capture(self.pg_interfaces)
7535 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007536 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007537 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7538 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7539
7540 ses_num_end = self.nat64_get_ses_num()
7541
7542 self.assertEqual(ses_num_end - ses_num_start, 3)
7543
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007544 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07007545 def test_session_timeout(self):
7546 """ NAT64 session timeout """
7547 self.icmp_id_in = 1234
7548 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7549 self.nat_addr_n)
7550 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7551 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007552 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07007553
7554 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7555 self.pg0.add_stream(pkts)
7556 self.pg_enable_capture(self.pg_interfaces)
7557 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007558 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007559
7560 ses_num_before_timeout = self.nat64_get_ses_num()
7561
7562 sleep(15)
7563
Matus Fabian8fed4242018-08-14 05:14:55 -07007564 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07007565 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07007566 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07007567
Matus Fabian732036d2017-06-08 05:24:28 -07007568 def test_icmp_error(self):
7569 """ NAT64 ICMP Error message translation """
7570 self.tcp_port_in = 6303
7571 self.udp_port_in = 6304
7572 self.icmp_id_in = 6305
7573
Matus Fabian732036d2017-06-08 05:24:28 -07007574 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7575 self.nat_addr_n)
7576 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7577 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7578
7579 # send some packets to create sessions
7580 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7581 self.pg0.add_stream(pkts)
7582 self.pg_enable_capture(self.pg_interfaces)
7583 self.pg_start()
7584 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07007585 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07007586 nat_ip=self.nat_addr,
7587 dst_ip=self.pg1.remote_ip4)
7588
7589 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7590 self.pg1.add_stream(pkts)
7591 self.pg_enable_capture(self.pg_interfaces)
7592 self.pg_start()
7593 capture_ip6 = self.pg0.get_capture(len(pkts))
7594 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7595 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7596 self.pg0.remote_ip6)
7597
7598 # in2out
7599 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7600 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7601 ICMPv6DestUnreach(code=1) /
7602 packet[IPv6] for packet in capture_ip6]
7603 self.pg0.add_stream(pkts)
7604 self.pg_enable_capture(self.pg_interfaces)
7605 self.pg_start()
7606 capture = self.pg1.get_capture(len(pkts))
7607 for packet in capture:
7608 try:
7609 self.assertEqual(packet[IP].src, self.nat_addr)
7610 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7611 self.assertEqual(packet[ICMP].type, 3)
7612 self.assertEqual(packet[ICMP].code, 13)
7613 inner = packet[IPerror]
7614 self.assertEqual(inner.src, self.pg1.remote_ip4)
7615 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007616 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007617 if inner.haslayer(TCPerror):
7618 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7619 elif inner.haslayer(UDPerror):
7620 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7621 else:
7622 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7623 except:
7624 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7625 raise
7626
7627 # out2in
7628 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7629 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7630 ICMP(type=3, code=13) /
7631 packet[IP] for packet in capture_ip4]
7632 self.pg1.add_stream(pkts)
7633 self.pg_enable_capture(self.pg_interfaces)
7634 self.pg_start()
7635 capture = self.pg0.get_capture(len(pkts))
7636 for packet in capture:
7637 try:
7638 self.assertEqual(packet[IPv6].src, ip.src)
7639 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7640 icmp = packet[ICMPv6DestUnreach]
7641 self.assertEqual(icmp.code, 1)
7642 inner = icmp[IPerror6]
7643 self.assertEqual(inner.src, self.pg0.remote_ip6)
7644 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007645 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007646 if inner.haslayer(TCPerror):
7647 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7648 elif inner.haslayer(UDPerror):
7649 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7650 else:
7651 self.assertEqual(inner[ICMPv6EchoRequest].id,
7652 self.icmp_id_in)
7653 except:
7654 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7655 raise
7656
Matus Fabian029f3d22017-06-15 02:28:50 -07007657 def test_hairpinning(self):
7658 """ NAT64 hairpinning """
7659
7660 client = self.pg0.remote_hosts[0]
7661 server = self.pg0.remote_hosts[1]
7662 server_tcp_in_port = 22
7663 server_tcp_out_port = 4022
7664 server_udp_in_port = 23
7665 server_udp_out_port = 4023
7666 client_tcp_in_port = 1234
7667 client_udp_in_port = 1235
7668 client_tcp_out_port = 0
7669 client_udp_out_port = 0
7670 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7671 nat_addr_ip6 = ip.src
7672
7673 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7674 self.nat_addr_n)
7675 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7676 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7677
7678 self.vapi.nat64_add_del_static_bib(server.ip6n,
7679 self.nat_addr_n,
7680 server_tcp_in_port,
7681 server_tcp_out_port,
7682 IP_PROTOS.tcp)
7683 self.vapi.nat64_add_del_static_bib(server.ip6n,
7684 self.nat_addr_n,
7685 server_udp_in_port,
7686 server_udp_out_port,
7687 IP_PROTOS.udp)
7688
7689 # client to server
7690 pkts = []
7691 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7692 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7693 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7694 pkts.append(p)
7695 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7696 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7697 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7698 pkts.append(p)
7699 self.pg0.add_stream(pkts)
7700 self.pg_enable_capture(self.pg_interfaces)
7701 self.pg_start()
7702 capture = self.pg0.get_capture(len(pkts))
7703 for packet in capture:
7704 try:
7705 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7706 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007707 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007708 if packet.haslayer(TCP):
7709 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7710 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007711 client_tcp_out_port = packet[TCP].sport
7712 else:
7713 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7714 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007715 client_udp_out_port = packet[UDP].sport
7716 except:
7717 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7718 raise
7719
7720 # server to client
7721 pkts = []
7722 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7723 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7724 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7725 pkts.append(p)
7726 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7727 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7728 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7729 pkts.append(p)
7730 self.pg0.add_stream(pkts)
7731 self.pg_enable_capture(self.pg_interfaces)
7732 self.pg_start()
7733 capture = self.pg0.get_capture(len(pkts))
7734 for packet in capture:
7735 try:
7736 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7737 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007738 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007739 if packet.haslayer(TCP):
7740 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7741 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007742 else:
7743 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7744 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007745 except:
7746 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7747 raise
7748
7749 # ICMP error
7750 pkts = []
7751 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7752 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7753 ICMPv6DestUnreach(code=1) /
7754 packet[IPv6] for packet in capture]
7755 self.pg0.add_stream(pkts)
7756 self.pg_enable_capture(self.pg_interfaces)
7757 self.pg_start()
7758 capture = self.pg0.get_capture(len(pkts))
7759 for packet in capture:
7760 try:
7761 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7762 self.assertEqual(packet[IPv6].dst, server.ip6)
7763 icmp = packet[ICMPv6DestUnreach]
7764 self.assertEqual(icmp.code, 1)
7765 inner = icmp[IPerror6]
7766 self.assertEqual(inner.src, server.ip6)
7767 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007768 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007769 if inner.haslayer(TCPerror):
7770 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7771 self.assertEqual(inner[TCPerror].dport,
7772 client_tcp_out_port)
7773 else:
7774 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7775 self.assertEqual(inner[UDPerror].dport,
7776 client_udp_out_port)
7777 except:
7778 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7779 raise
7780
Matus Fabian428dc912017-06-21 06:15:18 -07007781 def test_prefix(self):
7782 """ NAT64 Network-Specific Prefix """
7783
7784 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7785 self.nat_addr_n)
7786 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7787 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7788 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7789 self.vrf1_nat_addr_n,
7790 vrf_id=self.vrf1_id)
7791 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7792
7793 # Add global prefix
7794 global_pref64 = "2001:db8::"
7795 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7796 global_pref64_len = 32
7797 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7798
7799 prefix = self.vapi.nat64_prefix_dump()
7800 self.assertEqual(len(prefix), 1)
7801 self.assertEqual(prefix[0].prefix, global_pref64_n)
7802 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7803 self.assertEqual(prefix[0].vrf_id, 0)
7804
7805 # Add tenant specific prefix
7806 vrf1_pref64 = "2001:db8:122:300::"
7807 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7808 vrf1_pref64_len = 56
7809 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7810 vrf1_pref64_len,
7811 vrf_id=self.vrf1_id)
7812 prefix = self.vapi.nat64_prefix_dump()
7813 self.assertEqual(len(prefix), 2)
7814
7815 # Global prefix
7816 pkts = self.create_stream_in_ip6(self.pg0,
7817 self.pg1,
7818 pref=global_pref64,
7819 plen=global_pref64_len)
7820 self.pg0.add_stream(pkts)
7821 self.pg_enable_capture(self.pg_interfaces)
7822 self.pg_start()
7823 capture = self.pg1.get_capture(len(pkts))
7824 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7825 dst_ip=self.pg1.remote_ip4)
7826
7827 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7828 self.pg1.add_stream(pkts)
7829 self.pg_enable_capture(self.pg_interfaces)
7830 self.pg_start()
7831 capture = self.pg0.get_capture(len(pkts))
7832 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7833 global_pref64,
7834 global_pref64_len)
7835 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7836
7837 # Tenant specific prefix
7838 pkts = self.create_stream_in_ip6(self.pg2,
7839 self.pg1,
7840 pref=vrf1_pref64,
7841 plen=vrf1_pref64_len)
7842 self.pg2.add_stream(pkts)
7843 self.pg_enable_capture(self.pg_interfaces)
7844 self.pg_start()
7845 capture = self.pg1.get_capture(len(pkts))
7846 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7847 dst_ip=self.pg1.remote_ip4)
7848
7849 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7850 self.pg1.add_stream(pkts)
7851 self.pg_enable_capture(self.pg_interfaces)
7852 self.pg_start()
7853 capture = self.pg2.get_capture(len(pkts))
7854 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7855 vrf1_pref64,
7856 vrf1_pref64_len)
7857 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7858
Matus Fabianf8cd5812017-07-11 03:55:02 -07007859 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007860 """ NAT64 translate packet with unknown protocol """
7861
7862 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7863 self.nat_addr_n)
7864 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7865 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7866 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7867
7868 # in2out
7869 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7870 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7871 TCP(sport=self.tcp_port_in, dport=20))
7872 self.pg0.add_stream(p)
7873 self.pg_enable_capture(self.pg_interfaces)
7874 self.pg_start()
7875 p = self.pg1.get_capture(1)
7876
7877 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007878 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007879 GRE() /
7880 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7881 TCP(sport=1234, dport=1234))
7882 self.pg0.add_stream(p)
7883 self.pg_enable_capture(self.pg_interfaces)
7884 self.pg_start()
7885 p = self.pg1.get_capture(1)
7886 packet = p[0]
7887 try:
7888 self.assertEqual(packet[IP].src, self.nat_addr)
7889 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007890 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02007891 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007892 except:
7893 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7894 raise
7895
7896 # out2in
7897 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7898 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7899 GRE() /
7900 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7901 TCP(sport=1234, dport=1234))
7902 self.pg1.add_stream(p)
7903 self.pg_enable_capture(self.pg_interfaces)
7904 self.pg_start()
7905 p = self.pg0.get_capture(1)
7906 packet = p[0]
7907 try:
7908 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007909 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7910 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007911 except:
7912 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7913 raise
7914
Matus Fabianf8cd5812017-07-11 03:55:02 -07007915 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007916 """ NAT64 translate packet with unknown protocol - hairpinning """
7917
7918 client = self.pg0.remote_hosts[0]
7919 server = self.pg0.remote_hosts[1]
7920 server_tcp_in_port = 22
7921 server_tcp_out_port = 4022
7922 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007923 client_tcp_out_port = 1235
7924 server_nat_ip = "10.0.0.100"
7925 client_nat_ip = "10.0.0.110"
7926 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7927 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7928 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7929 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007930
Matus Fabianf8cd5812017-07-11 03:55:02 -07007931 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7932 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007933 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7934 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7935
7936 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007937 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007938 server_tcp_in_port,
7939 server_tcp_out_port,
7940 IP_PROTOS.tcp)
7941
Matus Fabianf8cd5812017-07-11 03:55:02 -07007942 self.vapi.nat64_add_del_static_bib(server.ip6n,
7943 server_nat_ip_n,
7944 0,
7945 0,
7946 IP_PROTOS.gre)
7947
7948 self.vapi.nat64_add_del_static_bib(client.ip6n,
7949 client_nat_ip_n,
7950 client_tcp_in_port,
7951 client_tcp_out_port,
7952 IP_PROTOS.tcp)
7953
Matus Fabian7968e6c2017-07-06 05:37:49 -07007954 # client to server
7955 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007956 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007957 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7958 self.pg0.add_stream(p)
7959 self.pg_enable_capture(self.pg_interfaces)
7960 self.pg_start()
7961 p = self.pg0.get_capture(1)
7962
7963 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007964 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007965 GRE() /
7966 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7967 TCP(sport=1234, dport=1234))
7968 self.pg0.add_stream(p)
7969 self.pg_enable_capture(self.pg_interfaces)
7970 self.pg_start()
7971 p = self.pg0.get_capture(1)
7972 packet = p[0]
7973 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007974 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007975 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007976 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007977 except:
7978 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7979 raise
7980
7981 # server to client
7982 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007983 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007984 GRE() /
7985 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7986 TCP(sport=1234, dport=1234))
7987 self.pg0.add_stream(p)
7988 self.pg_enable_capture(self.pg_interfaces)
7989 self.pg_start()
7990 p = self.pg0.get_capture(1)
7991 packet = p[0]
7992 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007993 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007994 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007995 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007996 except:
7997 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7998 raise
7999
Matus Fabian36ea2d62017-10-24 04:13:49 -07008000 def test_one_armed_nat64(self):
8001 """ One armed NAT64 """
8002 external_port = 0
8003 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8004 '64:ff9b::',
8005 96)
8006
8007 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8008 self.nat_addr_n)
8009 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
8010 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
8011
8012 # in2out
8013 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8014 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8015 TCP(sport=12345, dport=80))
8016 self.pg3.add_stream(p)
8017 self.pg_enable_capture(self.pg_interfaces)
8018 self.pg_start()
8019 capture = self.pg3.get_capture(1)
8020 p = capture[0]
8021 try:
8022 ip = p[IP]
8023 tcp = p[TCP]
8024 self.assertEqual(ip.src, self.nat_addr)
8025 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8026 self.assertNotEqual(tcp.sport, 12345)
8027 external_port = tcp.sport
8028 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008029 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008030 except:
8031 self.logger.error(ppp("Unexpected or invalid packet:", p))
8032 raise
8033
8034 # out2in
8035 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8036 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8037 TCP(sport=80, dport=external_port))
8038 self.pg3.add_stream(p)
8039 self.pg_enable_capture(self.pg_interfaces)
8040 self.pg_start()
8041 capture = self.pg3.get_capture(1)
8042 p = capture[0]
8043 try:
8044 ip = p[IPv6]
8045 tcp = p[TCP]
8046 self.assertEqual(ip.src, remote_host_ip6)
8047 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8048 self.assertEqual(tcp.sport, 80)
8049 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008050 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008051 except:
8052 self.logger.error(ppp("Unexpected or invalid packet:", p))
8053 raise
8054
Matus Fabianefcd1e92017-08-15 06:59:19 -07008055 def test_frag_in_order(self):
8056 """ NAT64 translate fragments arriving in order """
8057 self.tcp_port_in = random.randint(1025, 65535)
8058
8059 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8060 self.nat_addr_n)
8061 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8062 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8063
8064 reass = self.vapi.nat_reass_dump()
8065 reass_n_start = len(reass)
8066
8067 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008068 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008069 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8070 self.tcp_port_in, 20, data)
8071 self.pg0.add_stream(pkts)
8072 self.pg_enable_capture(self.pg_interfaces)
8073 self.pg_start()
8074 frags = self.pg1.get_capture(len(pkts))
8075 p = self.reass_frags_and_verify(frags,
8076 self.nat_addr,
8077 self.pg1.remote_ip4)
8078 self.assertEqual(p[TCP].dport, 20)
8079 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8080 self.tcp_port_out = p[TCP].sport
8081 self.assertEqual(data, p[Raw].load)
8082
8083 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008084 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008085 pkts = self.create_stream_frag(self.pg1,
8086 self.nat_addr,
8087 20,
8088 self.tcp_port_out,
8089 data)
8090 self.pg1.add_stream(pkts)
8091 self.pg_enable_capture(self.pg_interfaces)
8092 self.pg_start()
8093 frags = self.pg0.get_capture(len(pkts))
8094 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8095 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8096 self.assertEqual(p[TCP].sport, 20)
8097 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8098 self.assertEqual(data, p[Raw].load)
8099
8100 reass = self.vapi.nat_reass_dump()
8101 reass_n_end = len(reass)
8102
8103 self.assertEqual(reass_n_end - reass_n_start, 2)
8104
8105 def test_reass_hairpinning(self):
8106 """ NAT64 fragments hairpinning """
8107 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008108 server = self.pg0.remote_hosts[1]
8109 server_in_port = random.randint(1025, 65535)
8110 server_out_port = random.randint(1025, 65535)
8111 client_in_port = random.randint(1025, 65535)
8112 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8113 nat_addr_ip6 = ip.src
8114
8115 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8116 self.nat_addr_n)
8117 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8118 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8119
8120 # add static BIB entry for server
8121 self.vapi.nat64_add_del_static_bib(server.ip6n,
8122 self.nat_addr_n,
8123 server_in_port,
8124 server_out_port,
8125 IP_PROTOS.tcp)
8126
8127 # send packet from host to server
8128 pkts = self.create_stream_frag_ip6(self.pg0,
8129 self.nat_addr,
8130 client_in_port,
8131 server_out_port,
8132 data)
8133 self.pg0.add_stream(pkts)
8134 self.pg_enable_capture(self.pg_interfaces)
8135 self.pg_start()
8136 frags = self.pg0.get_capture(len(pkts))
8137 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8138 self.assertNotEqual(p[TCP].sport, client_in_port)
8139 self.assertEqual(p[TCP].dport, server_in_port)
8140 self.assertEqual(data, p[Raw].load)
8141
8142 def test_frag_out_of_order(self):
8143 """ NAT64 translate fragments arriving out of order """
8144 self.tcp_port_in = random.randint(1025, 65535)
8145
8146 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8147 self.nat_addr_n)
8148 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8149 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8150
8151 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008152 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008153 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8154 self.tcp_port_in, 20, data)
8155 pkts.reverse()
8156 self.pg0.add_stream(pkts)
8157 self.pg_enable_capture(self.pg_interfaces)
8158 self.pg_start()
8159 frags = self.pg1.get_capture(len(pkts))
8160 p = self.reass_frags_and_verify(frags,
8161 self.nat_addr,
8162 self.pg1.remote_ip4)
8163 self.assertEqual(p[TCP].dport, 20)
8164 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8165 self.tcp_port_out = p[TCP].sport
8166 self.assertEqual(data, p[Raw].load)
8167
8168 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008169 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008170 pkts = self.create_stream_frag(self.pg1,
8171 self.nat_addr,
8172 20,
8173 self.tcp_port_out,
8174 data)
8175 pkts.reverse()
8176 self.pg1.add_stream(pkts)
8177 self.pg_enable_capture(self.pg_interfaces)
8178 self.pg_start()
8179 frags = self.pg0.get_capture(len(pkts))
8180 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8181 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8182 self.assertEqual(p[TCP].sport, 20)
8183 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8184 self.assertEqual(data, p[Raw].load)
8185
Matus Fabian0938dcf2017-11-08 01:59:38 -08008186 def test_interface_addr(self):
8187 """ Acquire NAT64 pool addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01008188 self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008189
8190 # no address in NAT64 pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008191 addresses = self.vapi.nat44_address_dump()
8192 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008193
8194 # configure interface address and check NAT64 address pool
8195 self.pg4.config_ip4()
8196 addresses = self.vapi.nat64_pool_addr_dump()
8197 self.assertEqual(len(addresses), 1)
8198 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8199
8200 # remove interface address and check NAT64 address pool
8201 self.pg4.unconfig_ip4()
8202 addresses = self.vapi.nat64_pool_addr_dump()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008203 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008204
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008205 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008206 def test_ipfix_max_bibs_sessions(self):
8207 """ IPFIX logging maximum session and BIB entries exceeded """
8208 max_bibs = 1280
8209 max_sessions = 2560
8210 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8211 '64:ff9b::',
8212 96)
8213
8214 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8215 self.nat_addr_n)
8216 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8217 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8218
8219 pkts = []
8220 src = ""
8221 for i in range(0, max_bibs):
8222 src = "fd01:aa::%x" % (i)
8223 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8224 IPv6(src=src, dst=remote_host_ip6) /
8225 TCP(sport=12345, dport=80))
8226 pkts.append(p)
8227 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8228 IPv6(src=src, dst=remote_host_ip6) /
8229 TCP(sport=12345, dport=22))
8230 pkts.append(p)
8231 self.pg0.add_stream(pkts)
8232 self.pg_enable_capture(self.pg_interfaces)
8233 self.pg_start()
8234 self.pg1.get_capture(max_sessions)
8235
8236 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8237 src_address=self.pg3.local_ip4n,
8238 path_mtu=512,
8239 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008240 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8241 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008242
8243 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8244 IPv6(src=src, dst=remote_host_ip6) /
8245 TCP(sport=12345, dport=25))
8246 self.pg0.add_stream(p)
8247 self.pg_enable_capture(self.pg_interfaces)
8248 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008249 self.pg1.assert_nothing_captured()
8250 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008251 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8252 capture = self.pg3.get_capture(9)
8253 ipfix = IPFIXDecoder()
8254 # first load template
8255 for p in capture:
8256 self.assertTrue(p.haslayer(IPFIX))
8257 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8258 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8259 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8260 self.assertEqual(p[UDP].dport, 4739)
8261 self.assertEqual(p[IPFIX].observationDomainID,
8262 self.ipfix_domain_id)
8263 if p.haslayer(Template):
8264 ipfix.add_template(p.getlayer(Template))
8265 # verify events in data set
8266 for p in capture:
8267 if p.haslayer(Data):
8268 data = ipfix.decode_data_set(p.getlayer(Set))
8269 self.verify_ipfix_max_sessions(data, max_sessions)
8270
8271 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8272 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8273 TCP(sport=12345, dport=80))
8274 self.pg0.add_stream(p)
8275 self.pg_enable_capture(self.pg_interfaces)
8276 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008277 self.pg1.assert_nothing_captured()
8278 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008279 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8280 capture = self.pg3.get_capture(1)
8281 # verify events in data set
8282 for p in capture:
8283 self.assertTrue(p.haslayer(IPFIX))
8284 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8285 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8286 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8287 self.assertEqual(p[UDP].dport, 4739)
8288 self.assertEqual(p[IPFIX].observationDomainID,
8289 self.ipfix_domain_id)
8290 if p.haslayer(Data):
8291 data = ipfix.decode_data_set(p.getlayer(Set))
8292 self.verify_ipfix_max_bibs(data, max_bibs)
8293
8294 def test_ipfix_max_frags(self):
8295 """ IPFIX logging maximum fragments pending reassembly exceeded """
8296 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8297 self.nat_addr_n)
8298 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8299 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008300 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008301 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8302 src_address=self.pg3.local_ip4n,
8303 path_mtu=512,
8304 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008305 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8306 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008307
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008308 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008309 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8310 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008311 pkts.reverse()
8312 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008313 self.pg_enable_capture(self.pg_interfaces)
8314 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008315 self.pg1.assert_nothing_captured()
8316 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008317 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8318 capture = self.pg3.get_capture(9)
8319 ipfix = IPFIXDecoder()
8320 # first load template
8321 for p in capture:
8322 self.assertTrue(p.haslayer(IPFIX))
8323 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8324 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8325 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8326 self.assertEqual(p[UDP].dport, 4739)
8327 self.assertEqual(p[IPFIX].observationDomainID,
8328 self.ipfix_domain_id)
8329 if p.haslayer(Template):
8330 ipfix.add_template(p.getlayer(Template))
8331 # verify events in data set
8332 for p in capture:
8333 if p.haslayer(Data):
8334 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008335 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008336 self.pg0.remote_ip6n)
8337
8338 def test_ipfix_bib_ses(self):
8339 """ IPFIX logging NAT64 BIB/session create and delete events """
8340 self.tcp_port_in = random.randint(1025, 65535)
8341 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8342 '64:ff9b::',
8343 96)
8344
8345 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8346 self.nat_addr_n)
8347 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8348 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8349 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8350 src_address=self.pg3.local_ip4n,
8351 path_mtu=512,
8352 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008353 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8354 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008355
8356 # Create
8357 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8358 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8359 TCP(sport=self.tcp_port_in, dport=25))
8360 self.pg0.add_stream(p)
8361 self.pg_enable_capture(self.pg_interfaces)
8362 self.pg_start()
8363 p = self.pg1.get_capture(1)
8364 self.tcp_port_out = p[0][TCP].sport
8365 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8366 capture = self.pg3.get_capture(10)
8367 ipfix = IPFIXDecoder()
8368 # first load template
8369 for p in capture:
8370 self.assertTrue(p.haslayer(IPFIX))
8371 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8372 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8373 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8374 self.assertEqual(p[UDP].dport, 4739)
8375 self.assertEqual(p[IPFIX].observationDomainID,
8376 self.ipfix_domain_id)
8377 if p.haslayer(Template):
8378 ipfix.add_template(p.getlayer(Template))
8379 # verify events in data set
8380 for p in capture:
8381 if p.haslayer(Data):
8382 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008383 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008384 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008385 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008386 self.verify_ipfix_nat64_ses(data,
8387 1,
8388 self.pg0.remote_ip6n,
8389 self.pg1.remote_ip4,
8390 25)
8391 else:
8392 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8393
8394 # Delete
8395 self.pg_enable_capture(self.pg_interfaces)
8396 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8397 self.nat_addr_n,
8398 is_add=0)
8399 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8400 capture = self.pg3.get_capture(2)
8401 # verify events in data set
8402 for p in capture:
8403 self.assertTrue(p.haslayer(IPFIX))
8404 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8405 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8406 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8407 self.assertEqual(p[UDP].dport, 4739)
8408 self.assertEqual(p[IPFIX].observationDomainID,
8409 self.ipfix_domain_id)
8410 if p.haslayer(Data):
8411 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008412 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08008413 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008414 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08008415 self.verify_ipfix_nat64_ses(data,
8416 0,
8417 self.pg0.remote_ip6n,
8418 self.pg1.remote_ip4,
8419 25)
8420 else:
8421 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8422
Matus Fabianad1f3e12018-11-28 21:26:34 -08008423 def test_syslog_sess(self):
8424 """ Test syslog session creation and deletion """
8425 self.tcp_port_in = random.randint(1025, 65535)
8426 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8427 '64:ff9b::',
8428 96)
8429
8430 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8431 self.nat_addr_n)
8432 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8433 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8434 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01008435 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008436
8437 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8438 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8439 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8440 self.pg0.add_stream(p)
8441 self.pg_enable_capture(self.pg_interfaces)
8442 self.pg_start()
8443 p = self.pg1.get_capture(1)
8444 self.tcp_port_out = p[0][TCP].sport
8445 capture = self.pg3.get_capture(1)
8446 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8447
8448 self.pg_enable_capture(self.pg_interfaces)
8449 self.pg_start()
8450 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8451 self.nat_addr_n,
8452 is_add=0)
8453 capture = self.pg3.get_capture(1)
8454 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8455
Matus Fabian06596c52017-06-06 04:53:28 -07008456 def nat64_get_ses_num(self):
8457 """
8458 Return number of active NAT64 sessions.
8459 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07008460 st = self.vapi.nat64_st_dump()
8461 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07008462
8463 def clear_nat64(self):
8464 """
8465 Clear NAT64 configuration.
8466 """
Ole Troane1ade682019-03-04 23:55:43 +01008467 self.vapi.nat_ipfix_enable_disable(enable=0,
8468 src_port=self.ipfix_src_port,
8469 domain_id=self.ipfix_domain_id)
Matus Fabiana431ad12018-01-04 04:03:14 -08008470 self.ipfix_src_port = 4739
8471 self.ipfix_domain_id = 1
8472
Matus Fabianad1f3e12018-11-28 21:26:34 -08008473 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8474
Matus Fabian878c6462018-08-23 00:33:35 -07008475 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07008476
8477 interfaces = self.vapi.nat64_interface_dump()
8478 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07008479 if intf.is_inside > 1:
8480 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8481 0,
8482 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07008483 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8484 intf.is_inside,
8485 is_add=0)
8486
Matus Fabiana431ad12018-01-04 04:03:14 -08008487 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07008488 for bibe in bib:
8489 if bibe.is_static:
8490 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8491 bibe.o_addr,
8492 bibe.i_port,
8493 bibe.o_port,
8494 bibe.proto,
8495 bibe.vrf_id,
8496 is_add=0)
8497
8498 adresses = self.vapi.nat64_pool_addr_dump()
8499 for addr in adresses:
8500 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8501 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07008502 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07008503 is_add=0)
8504
Matus Fabian428dc912017-06-21 06:15:18 -07008505 prefixes = self.vapi.nat64_prefix_dump()
8506 for prefix in prefixes:
8507 self.vapi.nat64_add_del_prefix(prefix.prefix,
8508 prefix.prefix_len,
8509 vrf_id=prefix.vrf_id,
8510 is_add=0)
8511
Matus Fabianfd0d5082018-12-18 01:08:51 -08008512 bibs = self.statistics.get_counter('/nat64/total-bibs')
8513 self.assertEqual(bibs[0][0], 0)
8514 sessions = self.statistics.get_counter('/nat64/total-sessions')
8515 self.assertEqual(sessions[0][0], 0)
8516
Matus Fabian06596c52017-06-06 04:53:28 -07008517 def tearDown(self):
8518 super(TestNAT64, self).tearDown()
8519 if not self.vpp_dead:
8520 self.logger.info(self.vapi.cli("show nat64 pool"))
8521 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07008522 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07008523 self.logger.info(self.vapi.cli("show nat64 bib all"))
8524 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07008525 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07008526 self.clear_nat64()
8527
Matus Fabian8ebe6252017-11-06 05:04:53 -08008528
8529class TestDSlite(MethodHolder):
8530 """ DS-Lite Test Cases """
8531
8532 @classmethod
8533 def setUpClass(cls):
8534 super(TestDSlite, cls).setUpClass()
8535
8536 try:
8537 cls.nat_addr = '10.0.0.3'
8538 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8539
Matus Fabianad1f3e12018-11-28 21:26:34 -08008540 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008541 cls.pg0.admin_up()
8542 cls.pg0.config_ip4()
8543 cls.pg0.resolve_arp()
8544 cls.pg1.admin_up()
8545 cls.pg1.config_ip6()
8546 cls.pg1.generate_remote_hosts(2)
8547 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08008548 cls.pg2.admin_up()
8549 cls.pg2.config_ip4()
8550 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08008551
8552 except Exception:
8553 super(TestDSlite, cls).tearDownClass()
8554 raise
8555
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008556 @classmethod
8557 def tearDownClass(cls):
8558 super(TestDSlite, cls).tearDownClass()
8559
Matus Fabianad1f3e12018-11-28 21:26:34 -08008560 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8561 sv6enc, proto):
8562 message = data.decode('utf-8')
8563 try:
8564 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08008565 except ParseError as e:
8566 self.logger.error(e)
8567 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08008568 self.assertEqual(message.severity, SyslogSeverity.info)
8569 self.assertEqual(message.appname, 'NAT')
8570 self.assertEqual(message.msgid, 'APMADD')
8571 sd_params = message.sd.get('napmap')
8572 self.assertTrue(sd_params is not None)
8573 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8574 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8575 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8576 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8577 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8578 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8579 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8580 self.assertTrue(sd_params.get('SSUBIX') is not None)
8581 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008582
Matus Fabian8ebe6252017-11-06 05:04:53 -08008583 def test_dslite(self):
8584 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07008585 nat_config = self.vapi.nat_show_config()
8586 self.assertEqual(0, nat_config.dslite_ce)
8587
Matus Fabian8ebe6252017-11-06 05:04:53 -08008588 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8589 self.nat_addr_n)
8590 aftr_ip4 = '192.0.0.1'
8591 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8592 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8593 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8594 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Ole Troanf159f582019-02-28 20:20:47 +01008595 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008596
8597 # UDP
8598 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8599 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8600 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8601 UDP(sport=20000, dport=10000))
8602 self.pg1.add_stream(p)
8603 self.pg_enable_capture(self.pg_interfaces)
8604 self.pg_start()
8605 capture = self.pg0.get_capture(1)
8606 capture = capture[0]
8607 self.assertFalse(capture.haslayer(IPv6))
8608 self.assertEqual(capture[IP].src, self.nat_addr)
8609 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8610 self.assertNotEqual(capture[UDP].sport, 20000)
8611 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008612 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008613 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008614 capture = self.pg2.get_capture(1)
8615 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8616 20000, self.nat_addr, out_port,
8617 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008618
8619 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8620 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8621 UDP(sport=10000, dport=out_port))
8622 self.pg0.add_stream(p)
8623 self.pg_enable_capture(self.pg_interfaces)
8624 self.pg_start()
8625 capture = self.pg1.get_capture(1)
8626 capture = capture[0]
8627 self.assertEqual(capture[IPv6].src, aftr_ip6)
8628 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8629 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8630 self.assertEqual(capture[IP].dst, '192.168.1.1')
8631 self.assertEqual(capture[UDP].sport, 10000)
8632 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008633 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008634
8635 # TCP
8636 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8637 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8638 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8639 TCP(sport=20001, dport=10001))
8640 self.pg1.add_stream(p)
8641 self.pg_enable_capture(self.pg_interfaces)
8642 self.pg_start()
8643 capture = self.pg0.get_capture(1)
8644 capture = capture[0]
8645 self.assertFalse(capture.haslayer(IPv6))
8646 self.assertEqual(capture[IP].src, self.nat_addr)
8647 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8648 self.assertNotEqual(capture[TCP].sport, 20001)
8649 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008650 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008651 out_port = capture[TCP].sport
8652
8653 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8654 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8655 TCP(sport=10001, dport=out_port))
8656 self.pg0.add_stream(p)
8657 self.pg_enable_capture(self.pg_interfaces)
8658 self.pg_start()
8659 capture = self.pg1.get_capture(1)
8660 capture = capture[0]
8661 self.assertEqual(capture[IPv6].src, aftr_ip6)
8662 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8663 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8664 self.assertEqual(capture[IP].dst, '192.168.1.1')
8665 self.assertEqual(capture[TCP].sport, 10001)
8666 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008667 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008668
8669 # ICMP
8670 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8671 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8672 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8673 ICMP(id=4000, type='echo-request'))
8674 self.pg1.add_stream(p)
8675 self.pg_enable_capture(self.pg_interfaces)
8676 self.pg_start()
8677 capture = self.pg0.get_capture(1)
8678 capture = capture[0]
8679 self.assertFalse(capture.haslayer(IPv6))
8680 self.assertEqual(capture[IP].src, self.nat_addr)
8681 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8682 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008683 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008684 out_id = capture[ICMP].id
8685
8686 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8687 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8688 ICMP(id=out_id, type='echo-reply'))
8689 self.pg0.add_stream(p)
8690 self.pg_enable_capture(self.pg_interfaces)
8691 self.pg_start()
8692 capture = self.pg1.get_capture(1)
8693 capture = capture[0]
8694 self.assertEqual(capture[IPv6].src, aftr_ip6)
8695 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8696 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8697 self.assertEqual(capture[IP].dst, '192.168.1.1')
8698 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008699 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008700
Matus Fabian331acc62017-12-08 03:38:51 -08008701 # ping DS-Lite AFTR tunnel endpoint address
8702 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8703 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8704 ICMPv6EchoRequest())
8705 self.pg1.add_stream(p)
8706 self.pg_enable_capture(self.pg_interfaces)
8707 self.pg_start()
8708 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008709 capture = capture[0]
8710 self.assertEqual(capture[IPv6].src, aftr_ip6)
8711 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8712 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8713
Matus Fabianfd0d5082018-12-18 01:08:51 -08008714 b4s = self.statistics.get_counter('/dslite/total-b4s')
8715 self.assertEqual(b4s[0][0], 2)
8716 sessions = self.statistics.get_counter('/dslite/total-sessions')
8717 self.assertEqual(sessions[0][0], 3)
8718
Matus Fabian8ebe6252017-11-06 05:04:53 -08008719 def tearDown(self):
8720 super(TestDSlite, self).tearDown()
8721 if not self.vpp_dead:
8722 self.logger.info(self.vapi.cli("show dslite pool"))
8723 self.logger.info(
8724 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8725 self.logger.info(self.vapi.cli("show dslite sessions"))
8726
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008727
8728class TestDSliteCE(MethodHolder):
8729 """ DS-Lite CE Test Cases """
8730
8731 @classmethod
8732 def setUpConstants(cls):
8733 super(TestDSliteCE, cls).setUpConstants()
8734 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8735
8736 @classmethod
8737 def setUpClass(cls):
8738 super(TestDSliteCE, cls).setUpClass()
8739
8740 try:
8741 cls.create_pg_interfaces(range(2))
8742 cls.pg0.admin_up()
8743 cls.pg0.config_ip4()
8744 cls.pg0.resolve_arp()
8745 cls.pg1.admin_up()
8746 cls.pg1.config_ip6()
8747 cls.pg1.generate_remote_hosts(1)
8748 cls.pg1.configure_ipv6_neighbors()
8749
8750 except Exception:
8751 super(TestDSliteCE, cls).tearDownClass()
8752 raise
8753
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008754 @classmethod
8755 def tearDownClass(cls):
8756 super(TestDSliteCE, cls).tearDownClass()
8757
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008758 def test_dslite_ce(self):
8759 """ Test DS-Lite CE """
8760
Matus Fabian69ce30d2018-08-22 01:27:10 -07008761 nat_config = self.vapi.nat_show_config()
8762 self.assertEqual(1, nat_config.dslite_ce)
8763
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008764 b4_ip4 = '192.0.0.2'
8765 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8766 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8767 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8768 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8769
8770 aftr_ip4 = '192.0.0.1'
8771 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8772 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8773 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8774 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8775
8776 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8777 dst_address_length=128,
8778 next_hop_address=self.pg1.remote_ip6n,
8779 next_hop_sw_if_index=self.pg1.sw_if_index,
8780 is_ipv6=1)
8781
8782 # UDP encapsulation
8783 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8784 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8785 UDP(sport=10000, dport=20000))
8786 self.pg0.add_stream(p)
8787 self.pg_enable_capture(self.pg_interfaces)
8788 self.pg_start()
8789 capture = self.pg1.get_capture(1)
8790 capture = capture[0]
8791 self.assertEqual(capture[IPv6].src, b4_ip6)
8792 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8793 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8794 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8795 self.assertEqual(capture[UDP].sport, 10000)
8796 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008797 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008798
8799 # UDP decapsulation
8800 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8801 IPv6(dst=b4_ip6, src=aftr_ip6) /
8802 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8803 UDP(sport=20000, dport=10000))
8804 self.pg1.add_stream(p)
8805 self.pg_enable_capture(self.pg_interfaces)
8806 self.pg_start()
8807 capture = self.pg0.get_capture(1)
8808 capture = capture[0]
8809 self.assertFalse(capture.haslayer(IPv6))
8810 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8811 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8812 self.assertEqual(capture[UDP].sport, 20000)
8813 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008814 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008815
8816 # ping DS-Lite B4 tunnel endpoint address
8817 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8818 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8819 ICMPv6EchoRequest())
8820 self.pg1.add_stream(p)
8821 self.pg_enable_capture(self.pg_interfaces)
8822 self.pg_start()
8823 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008824 capture = capture[0]
8825 self.assertEqual(capture[IPv6].src, b4_ip6)
8826 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8827 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8828
8829 def tearDown(self):
8830 super(TestDSliteCE, self).tearDown()
8831 if not self.vpp_dead:
8832 self.logger.info(
8833 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8834 self.logger.info(
8835 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8836
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008837
8838class TestNAT66(MethodHolder):
8839 """ NAT66 Test Cases """
8840
8841 @classmethod
8842 def setUpClass(cls):
8843 super(TestNAT66, cls).setUpClass()
8844
8845 try:
8846 cls.nat_addr = 'fd01:ff::2'
8847 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8848
8849 cls.create_pg_interfaces(range(2))
8850 cls.interfaces = list(cls.pg_interfaces)
8851
8852 for i in cls.interfaces:
8853 i.admin_up()
8854 i.config_ip6()
8855 i.configure_ipv6_neighbors()
8856
8857 except Exception:
8858 super(TestNAT66, cls).tearDownClass()
8859 raise
8860
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008861 @classmethod
8862 def tearDownClass(cls):
8863 super(TestNAT66, cls).tearDownClass()
8864
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008865 def test_static(self):
8866 """ 1:1 NAT66 test """
8867 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8868 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8869 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8870 self.nat_addr_n)
8871
8872 # in2out
8873 pkts = []
8874 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8875 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8876 TCP())
8877 pkts.append(p)
8878 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8879 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8880 UDP())
8881 pkts.append(p)
8882 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8883 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8884 ICMPv6EchoRequest())
8885 pkts.append(p)
8886 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8887 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8888 GRE() / IP() / TCP())
8889 pkts.append(p)
8890 self.pg0.add_stream(pkts)
8891 self.pg_enable_capture(self.pg_interfaces)
8892 self.pg_start()
8893 capture = self.pg1.get_capture(len(pkts))
8894 for packet in capture:
8895 try:
8896 self.assertEqual(packet[IPv6].src, self.nat_addr)
8897 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008898 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008899 except:
8900 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8901 raise
8902
8903 # out2in
8904 pkts = []
8905 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8906 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8907 TCP())
8908 pkts.append(p)
8909 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8910 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8911 UDP())
8912 pkts.append(p)
8913 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8914 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8915 ICMPv6EchoReply())
8916 pkts.append(p)
8917 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8918 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8919 GRE() / IP() / TCP())
8920 pkts.append(p)
8921 self.pg1.add_stream(pkts)
8922 self.pg_enable_capture(self.pg_interfaces)
8923 self.pg_start()
8924 capture = self.pg0.get_capture(len(pkts))
8925 for packet in capture:
8926 try:
8927 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8928 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008929 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008930 except:
8931 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8932 raise
8933
8934 sm = self.vapi.nat66_static_mapping_dump()
8935 self.assertEqual(len(sm), 1)
8936 self.assertEqual(sm[0].total_pkts, 8)
8937
Juraj Sloboda9341e342018-04-13 12:00:46 +02008938 def test_check_no_translate(self):
8939 """ NAT66 translate only when egress interface is outside interface """
8940 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8941 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8942 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8943 self.nat_addr_n)
8944
8945 # in2out
8946 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8947 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8948 UDP())
8949 self.pg0.add_stream([p])
8950 self.pg_enable_capture(self.pg_interfaces)
8951 self.pg_start()
8952 capture = self.pg1.get_capture(1)
8953 packet = capture[0]
8954 try:
8955 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8956 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8957 except:
8958 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8959 raise
8960
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008961 def clear_nat66(self):
8962 """
8963 Clear NAT66 configuration.
8964 """
8965 interfaces = self.vapi.nat66_interface_dump()
8966 for intf in interfaces:
8967 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8968 intf.is_inside,
8969 is_add=0)
8970
8971 static_mappings = self.vapi.nat66_static_mapping_dump()
8972 for sm in static_mappings:
8973 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8974 sm.external_ip_address,
8975 sm.vrf_id,
8976 is_add=0)
8977
8978 def tearDown(self):
8979 super(TestNAT66, self).tearDown()
8980 if not self.vpp_dead:
8981 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8982 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8983 self.clear_nat66()
8984
Klement Sekerad81ae412018-05-16 10:52:54 +02008985
Matus Fabiande886752016-12-07 03:38:19 -08008986if __name__ == '__main__':
8987 unittest.main(testRunner=VppTestRunner)