blob: 166044db4355dc9fd34c89285d91ea9417f4b337 [file] [log] [blame]
Filip Varga18f1e412020-12-03 15:27:40 +01001#!/usr/bin/env python3
2
3import ipaddress
4import random
5import socket
6import struct
7import unittest
8from io import BytesIO
Filip Varga18f1e412020-12-03 15:27:40 +01009
10import scapy.compat
Dave Wallace8800f732023-08-31 00:47:44 -040011from framework import VppTestCase, VppLoInterface
12from asfframework import VppTestRunner, tag_fixme_debian11, is_distro_debian11
Filip Varga18f1e412020-12-03 15:27:40 +010013from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020014from scapy.all import (
15 bind_layers,
16 Packet,
17 ByteEnumField,
18 ShortField,
19 IPField,
20 IntField,
21 LongField,
22 XByteField,
23 FlagsField,
24 FieldLenField,
25 PacketListField,
26)
Filip Varga18f1e412020-12-03 15:27:40 +010027from scapy.data import IP_PROTOS
28from scapy.layers.inet import IP, TCP, UDP, ICMP
29from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
30from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
31from scapy.layers.l2 import Ether, ARP, GRE
32from scapy.packet import Raw
33from syslog_rfc5424_parser import SyslogMessage, ParseError
34from syslog_rfc5424_parser.constants import SyslogSeverity
35from util import ppp
36from vpp_ip_route import VppIpRoute, VppRoutePath
37from vpp_neighbor import VppNeighbor
38from vpp_papi import VppEnum
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000039from config import config
Filip Varga18f1e412020-12-03 15:27:40 +010040
41
42# NAT HA protocol event data
43class Event(Packet):
44 name = "Event"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020045 fields_desc = [
46 ByteEnumField("event_type", None, {1: "add", 2: "del", 3: "refresh"}),
47 ByteEnumField("protocol", None, {0: "other", 1: "udp", 2: "tcp", 3: "icmp"}),
48 ShortField("flags", 0),
49 IPField("in_addr", None),
50 IPField("out_addr", None),
51 ShortField("in_port", None),
52 ShortField("out_port", None),
53 IPField("eh_addr", None),
54 IPField("ehn_addr", None),
55 ShortField("eh_port", None),
56 ShortField("ehn_port", None),
57 IntField("fib_index", None),
58 IntField("total_pkts", 0),
59 LongField("total_bytes", 0),
60 ]
Filip Varga18f1e412020-12-03 15:27:40 +010061
62 def extract_padding(self, s):
63 return "", s
64
65
66# NAT HA protocol header
67class HANATStateSync(Packet):
68 name = "HA NAT state sync"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020069 fields_desc = [
70 XByteField("version", 1),
71 FlagsField("flags", 0, 8, ["ACK"]),
72 FieldLenField("count", None, count_of="events"),
73 IntField("sequence_number", 1),
74 IntField("thread_index", 0),
75 PacketListField("events", [], Event, count_from=lambda pkt: pkt.count),
76 ]
Filip Varga18f1e412020-12-03 15:27:40 +010077
78
79class MethodHolder(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020080 """NAT create capture and verify method holder"""
Filip Varga18f1e412020-12-03 15:27:40 +010081
82 @property
83 def config_flags(self):
Filip Varga0eaf4e62021-02-17 14:34:54 +010084 return VppEnum.vl_api_nat44_ei_config_flags_t
Filip Varga18f1e412020-12-03 15:27:40 +010085
86 @property
87 def SYSLOG_SEVERITY(self):
88 return VppEnum.vl_api_syslog_severity_t
89
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020090 def nat44_add_static_mapping(
91 self,
92 local_ip,
93 external_ip="0.0.0.0",
94 local_port=0,
95 external_port=0,
96 vrf_id=0,
97 is_add=1,
98 external_sw_if_index=0xFFFFFFFF,
99 proto=0,
100 tag="",
101 flags=0,
102 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100103 """
104 Add/delete NAT44EI static mapping
105
106 :param local_ip: Local IP address
107 :param external_ip: External IP address
108 :param local_port: Local port number (Optional)
109 :param external_port: External port number (Optional)
110 :param vrf_id: VRF ID (Default 0)
111 :param is_add: 1 if add, 0 if delete (Default add)
112 :param external_sw_if_index: External interface instead of IP address
113 :param proto: IP protocol (Mandatory if port specified)
114 :param tag: Opaque string tag
115 :param flags: NAT configuration flags
116 """
117
118 if not (local_port and external_port):
Filip Varga0eaf4e62021-02-17 14:34:54 +0100119 flags |= self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
Filip Varga18f1e412020-12-03 15:27:40 +0100120
Filip Varga0eaf4e62021-02-17 14:34:54 +0100121 self.vapi.nat44_ei_add_del_static_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +0100122 is_add=is_add,
123 local_ip_address=local_ip,
124 external_ip_address=external_ip,
125 external_sw_if_index=external_sw_if_index,
126 local_port=local_port,
127 external_port=external_port,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200128 vrf_id=vrf_id,
129 protocol=proto,
Filip Varga18f1e412020-12-03 15:27:40 +0100130 flags=flags,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200131 tag=tag,
132 )
Filip Varga18f1e412020-12-03 15:27:40 +0100133
Filip Varga0eaf4e62021-02-17 14:34:54 +0100134 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF):
Filip Varga18f1e412020-12-03 15:27:40 +0100135 """
136 Add/delete NAT44EI address
137
138 :param ip: IP address
139 :param is_add: 1 if add, 0 if delete (Default add)
Filip Varga18f1e412020-12-03 15:27:40 +0100140 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200141 self.vapi.nat44_ei_add_del_address_range(
142 first_ip_address=ip, last_ip_address=ip, vrf_id=vrf_id, is_add=is_add
143 )
Filip Varga18f1e412020-12-03 15:27:40 +0100144
145 def create_routes_and_neigbors(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200146 r1 = VppIpRoute(
147 self,
148 self.pg7.remote_ip4,
149 32,
150 [VppRoutePath(self.pg7.remote_ip4, self.pg7.sw_if_index)],
151 )
152 r2 = VppIpRoute(
153 self,
154 self.pg8.remote_ip4,
155 32,
156 [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)],
157 )
Filip Varga18f1e412020-12-03 15:27:40 +0100158 r1.add_vpp_config()
159 r2.add_vpp_config()
160
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200161 n1 = VppNeighbor(
162 self,
163 self.pg7.sw_if_index,
164 self.pg7.remote_mac,
165 self.pg7.remote_ip4,
166 is_static=1,
167 )
168 n2 = VppNeighbor(
169 self,
170 self.pg8.sw_if_index,
171 self.pg8.remote_mac,
172 self.pg8.remote_ip4,
173 is_static=1,
174 )
Filip Varga18f1e412020-12-03 15:27:40 +0100175 n1.add_vpp_config()
176 n2.add_vpp_config()
177
178 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
179 """
180 Create packet stream for inside network
181
182 :param in_if: Inside interface
183 :param out_if: Outside interface
184 :param dst_ip: Destination address
185 :param ttl: TTL of generated packets
186 """
187 if dst_ip is None:
188 dst_ip = out_if.remote_ip4
189
190 pkts = []
191 # TCP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200192 p = (
193 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
194 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
195 / TCP(sport=self.tcp_port_in, dport=20)
196 )
Filip Varga18f1e412020-12-03 15:27:40 +0100197 pkts.extend([p, p])
198
199 # UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200200 p = (
201 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
202 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
203 / UDP(sport=self.udp_port_in, dport=20)
204 )
Filip Varga18f1e412020-12-03 15:27:40 +0100205 pkts.append(p)
206
207 # ICMP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200208 p = (
209 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
210 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
211 / ICMP(id=self.icmp_id_in, type="echo-request")
212 )
Filip Varga18f1e412020-12-03 15:27:40 +0100213 pkts.append(p)
214
215 return pkts
216
217 def compose_ip6(self, ip4, pref, plen):
218 """
219 Compose IPv4-embedded IPv6 addresses
220
221 :param ip4: IPv4 address
222 :param pref: IPv6 prefix
223 :param plen: IPv6 prefix length
224 :returns: IPv4-embedded IPv6 addresses
225 """
226 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
227 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
228 if plen == 32:
229 pref_n[4] = ip4_n[0]
230 pref_n[5] = ip4_n[1]
231 pref_n[6] = ip4_n[2]
232 pref_n[7] = ip4_n[3]
233 elif plen == 40:
234 pref_n[5] = ip4_n[0]
235 pref_n[6] = ip4_n[1]
236 pref_n[7] = ip4_n[2]
237 pref_n[9] = ip4_n[3]
238 elif plen == 48:
239 pref_n[6] = ip4_n[0]
240 pref_n[7] = ip4_n[1]
241 pref_n[9] = ip4_n[2]
242 pref_n[10] = ip4_n[3]
243 elif plen == 56:
244 pref_n[7] = ip4_n[0]
245 pref_n[9] = ip4_n[1]
246 pref_n[10] = ip4_n[2]
247 pref_n[11] = ip4_n[3]
248 elif plen == 64:
249 pref_n[9] = ip4_n[0]
250 pref_n[10] = ip4_n[1]
251 pref_n[11] = ip4_n[2]
252 pref_n[12] = ip4_n[3]
253 elif plen == 96:
254 pref_n[12] = ip4_n[0]
255 pref_n[13] = ip4_n[1]
256 pref_n[14] = ip4_n[2]
257 pref_n[15] = ip4_n[3]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200258 packed_pref_n = b"".join([scapy.compat.chb(x) for x in pref_n])
Filip Varga18f1e412020-12-03 15:27:40 +0100259 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
260
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200261 def create_stream_out(self, out_if, dst_ip=None, ttl=64, use_inside_ports=False):
Filip Varga18f1e412020-12-03 15:27:40 +0100262 """
263 Create packet stream for outside network
264
265 :param out_if: Outside interface
266 :param dst_ip: Destination IP address (Default use global NAT address)
267 :param ttl: TTL of generated packets
268 :param use_inside_ports: Use inside NAT ports as destination ports
269 instead of outside ports
270 """
271 if dst_ip is None:
272 dst_ip = self.nat_addr
273 if not use_inside_ports:
274 tcp_port = self.tcp_port_out
275 udp_port = self.udp_port_out
276 icmp_id = self.icmp_id_out
277 else:
278 tcp_port = self.tcp_port_in
279 udp_port = self.udp_port_in
280 icmp_id = self.icmp_id_in
281 pkts = []
282 # TCP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200283 p = (
284 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
285 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
286 / TCP(dport=tcp_port, sport=20)
287 )
Filip Varga18f1e412020-12-03 15:27:40 +0100288 pkts.extend([p, p])
289
290 # UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200291 p = (
292 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
293 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
294 / UDP(dport=udp_port, sport=20)
295 )
Filip Varga18f1e412020-12-03 15:27:40 +0100296 pkts.append(p)
297
298 # ICMP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200299 p = (
300 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
301 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
302 / ICMP(id=icmp_id, type="echo-reply")
303 )
Filip Varga18f1e412020-12-03 15:27:40 +0100304 pkts.append(p)
305
306 return pkts
307
308 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
309 """
310 Create packet stream for outside network
311
312 :param out_if: Outside interface
313 :param dst_ip: Destination IP address (Default use global NAT address)
314 :param hl: HL of generated packets
315 """
316 pkts = []
317 # TCP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200318 p = (
319 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
320 / IPv6(src=src_ip, dst=dst_ip, hlim=hl)
321 / TCP(dport=self.tcp_port_out, sport=20)
322 )
Filip Varga18f1e412020-12-03 15:27:40 +0100323 pkts.append(p)
324
325 # UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 p = (
327 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
328 / IPv6(src=src_ip, dst=dst_ip, hlim=hl)
329 / UDP(dport=self.udp_port_out, sport=20)
330 )
Filip Varga18f1e412020-12-03 15:27:40 +0100331 pkts.append(p)
332
333 # ICMP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200334 p = (
335 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
336 / IPv6(src=src_ip, dst=dst_ip, hlim=hl)
337 / ICMPv6EchoReply(id=self.icmp_id_out)
338 )
Filip Varga18f1e412020-12-03 15:27:40 +0100339 pkts.append(p)
340
341 return pkts
342
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 def verify_capture_out(
344 self,
345 capture,
346 nat_ip=None,
347 same_port=False,
348 dst_ip=None,
349 is_ip6=False,
350 ignore_port=False,
351 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100352 """
353 Verify captured packets on outside network
354
355 :param capture: Captured packets
356 :param nat_ip: Translated IP address (Default use global NAT address)
357 :param same_port: Source port number is not translated (Default False)
358 :param dst_ip: Destination IP address (Default do not verify)
359 :param is_ip6: If L3 protocol is IPv6 (Default False)
360 """
361 if is_ip6:
362 IP46 = IPv6
363 ICMP46 = ICMPv6EchoRequest
364 else:
365 IP46 = IP
366 ICMP46 = ICMP
367 if nat_ip is None:
368 nat_ip = self.nat_addr
369 for packet in capture:
370 try:
371 if not is_ip6:
372 self.assert_packet_checksums_valid(packet)
373 self.assertEqual(packet[IP46].src, nat_ip)
374 if dst_ip is not None:
375 self.assertEqual(packet[IP46].dst, dst_ip)
376 if packet.haslayer(TCP):
377 if not ignore_port:
378 if same_port:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200379 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100380 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200381 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100382 self.tcp_port_out = packet[TCP].sport
383 self.assert_packet_checksums_valid(packet)
384 elif packet.haslayer(UDP):
385 if not ignore_port:
386 if same_port:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200387 self.assertEqual(packet[UDP].sport, self.udp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100388 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200389 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100390 self.udp_port_out = packet[UDP].sport
391 else:
392 if not ignore_port:
393 if same_port:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200394 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100395 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200396 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100397 self.icmp_id_out = packet[ICMP46].id
398 self.assert_packet_checksums_valid(packet)
399 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200400 self.logger.error(
401 ppp("Unexpected or invalid packet (outside network):", packet)
402 )
Filip Varga18f1e412020-12-03 15:27:40 +0100403 raise
404
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200405 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False, dst_ip=None):
Filip Varga18f1e412020-12-03 15:27:40 +0100406 """
407 Verify captured packets on outside network
408
409 :param capture: Captured packets
410 :param nat_ip: Translated IP address
411 :param same_port: Source port number is not translated (Default False)
412 :param dst_ip: Destination IP address (Default do not verify)
413 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200414 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip, True)
Filip Varga18f1e412020-12-03 15:27:40 +0100415
416 def verify_capture_in(self, capture, in_if):
417 """
418 Verify captured packets on inside network
419
420 :param capture: Captured packets
421 :param in_if: Inside interface
422 """
423 for packet in capture:
424 try:
425 self.assert_packet_checksums_valid(packet)
426 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
427 if packet.haslayer(TCP):
428 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
429 elif packet.haslayer(UDP):
430 self.assertEqual(packet[UDP].dport, self.udp_port_in)
431 else:
432 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
433 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200434 self.logger.error(
435 ppp("Unexpected or invalid packet (inside network):", packet)
436 )
Filip Varga18f1e412020-12-03 15:27:40 +0100437 raise
438
439 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
440 """
441 Verify captured packet that don't have to be translated
442
443 :param capture: Captured packets
444 :param ingress_if: Ingress interface
445 :param egress_if: Egress interface
446 """
447 for packet in capture:
448 try:
449 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
450 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
451 if packet.haslayer(TCP):
452 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
453 elif packet.haslayer(UDP):
454 self.assertEqual(packet[UDP].sport, self.udp_port_in)
455 else:
456 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
457 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200458 self.logger.error(
459 ppp("Unexpected or invalid packet (inside network):", packet)
460 )
Filip Varga18f1e412020-12-03 15:27:40 +0100461 raise
462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200463 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None, icmp_type=11):
Filip Varga18f1e412020-12-03 15:27:40 +0100464 """
465 Verify captured packets with ICMP errors on outside network
466
467 :param capture: Captured packets
468 :param src_ip: Translated IP address or IP address of VPP
469 (Default use global NAT address)
470 :param icmp_type: Type of error ICMP packet
471 we are expecting (Default 11)
472 """
473 if src_ip is None:
474 src_ip = self.nat_addr
475 for packet in capture:
476 try:
477 self.assertEqual(packet[IP].src, src_ip)
478 self.assertEqual(packet.haslayer(ICMP), 1)
479 icmp = packet[ICMP]
480 self.assertEqual(icmp.type, icmp_type)
481 self.assertTrue(icmp.haslayer(IPerror))
482 inner_ip = icmp[IPerror]
483 if inner_ip.haslayer(TCPerror):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200484 self.assertEqual(inner_ip[TCPerror].dport, self.tcp_port_out)
Filip Varga18f1e412020-12-03 15:27:40 +0100485 elif inner_ip.haslayer(UDPerror):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200486 self.assertEqual(inner_ip[UDPerror].dport, self.udp_port_out)
Filip Varga18f1e412020-12-03 15:27:40 +0100487 else:
488 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
489 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 self.logger.error(
491 ppp("Unexpected or invalid packet (outside network):", packet)
492 )
Filip Varga18f1e412020-12-03 15:27:40 +0100493 raise
494
495 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
496 """
497 Verify captured packets with ICMP errors on inside network
498
499 :param capture: Captured packets
500 :param in_if: Inside interface
501 :param icmp_type: Type of error ICMP packet
502 we are expecting (Default 11)
503 """
504 for packet in capture:
505 try:
506 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
507 self.assertEqual(packet.haslayer(ICMP), 1)
508 icmp = packet[ICMP]
509 self.assertEqual(icmp.type, icmp_type)
510 self.assertTrue(icmp.haslayer(IPerror))
511 inner_ip = icmp[IPerror]
512 if inner_ip.haslayer(TCPerror):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200513 self.assertEqual(inner_ip[TCPerror].sport, self.tcp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100514 elif inner_ip.haslayer(UDPerror):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200515 self.assertEqual(inner_ip[UDPerror].sport, self.udp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100516 else:
517 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
518 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200519 self.logger.error(
520 ppp("Unexpected or invalid packet (inside network):", packet)
521 )
Filip Varga18f1e412020-12-03 15:27:40 +0100522 raise
523
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200524 def create_stream_frag(
525 self, src_if, dst, sport, dport, data, proto=IP_PROTOS.tcp, echo_reply=False
526 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100527 """
528 Create fragmented packet stream
529
530 :param src_if: Source interface
531 :param dst: Destination IPv4 address
532 :param sport: Source port
533 :param dport: Destination port
534 :param data: Payload data
535 :param proto: protocol (TCP, UDP, ICMP)
536 :param echo_reply: use echo_reply if protocol is ICMP
537 :returns: Fragments
538 """
539 if proto == IP_PROTOS.tcp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200540 p = (
541 IP(src=src_if.remote_ip4, dst=dst)
542 / TCP(sport=sport, dport=dport)
543 / Raw(data)
544 )
Filip Varga18f1e412020-12-03 15:27:40 +0100545 p = p.__class__(scapy.compat.raw(p))
546 chksum = p[TCP].chksum
547 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
548 elif proto == IP_PROTOS.udp:
549 proto_header = UDP(sport=sport, dport=dport)
550 elif proto == IP_PROTOS.icmp:
551 if not echo_reply:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200552 proto_header = ICMP(id=sport, type="echo-request")
Filip Varga18f1e412020-12-03 15:27:40 +0100553 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200554 proto_header = ICMP(id=sport, type="echo-reply")
Filip Varga18f1e412020-12-03 15:27:40 +0100555 else:
556 raise Exception("Unsupported protocol")
557 id = random.randint(0, 65535)
558 pkts = []
559 if proto == IP_PROTOS.tcp:
560 raw = Raw(data[0:4])
561 else:
562 raw = Raw(data[0:16])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200563 p = (
564 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
565 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id)
566 / proto_header
567 / raw
568 )
Filip Varga18f1e412020-12-03 15:27:40 +0100569 pkts.append(p)
570 if proto == IP_PROTOS.tcp:
571 raw = Raw(data[4:20])
572 else:
573 raw = Raw(data[16:32])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200574 p = (
575 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
576 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id, proto=proto)
577 / raw
578 )
Filip Varga18f1e412020-12-03 15:27:40 +0100579 pkts.append(p)
580 if proto == IP_PROTOS.tcp:
581 raw = Raw(data[20:])
582 else:
583 raw = Raw(data[32:])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200584 p = (
585 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
586 / IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto, id=id)
587 / raw
588 )
Filip Varga18f1e412020-12-03 15:27:40 +0100589 pkts.append(p)
590 return pkts
591
592 def reass_frags_and_verify(self, frags, src, dst):
593 """
594 Reassemble and verify fragmented packet
595
596 :param frags: Captured fragments
597 :param src: Source IPv4 address to verify
598 :param dst: Destination IPv4 address to verify
599
600 :returns: Reassembled IPv4 packet
601 """
602 buffer = BytesIO()
603 for p in frags:
604 self.assertEqual(p[IP].src, src)
605 self.assertEqual(p[IP].dst, dst)
606 self.assert_ip_checksum_valid(p)
607 buffer.seek(p[IP].frag * 8)
608 buffer.write(bytes(p[IP].payload))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst, proto=frags[0][IP].proto)
Filip Varga18f1e412020-12-03 15:27:40 +0100610 if ip.proto == IP_PROTOS.tcp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200611 p = ip / TCP(buffer.getvalue())
Filip Varga18f1e412020-12-03 15:27:40 +0100612 self.logger.debug(ppp("Reassembled:", p))
613 self.assert_tcp_checksum_valid(p)
614 elif ip.proto == IP_PROTOS.udp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200615 p = ip / UDP(buffer.getvalue()[:8]) / Raw(buffer.getvalue()[8:])
Filip Varga18f1e412020-12-03 15:27:40 +0100616 elif ip.proto == IP_PROTOS.icmp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200617 p = ip / ICMP(buffer.getvalue())
Filip Varga18f1e412020-12-03 15:27:40 +0100618 return p
619
620 def verify_ipfix_nat44_ses(self, data):
621 """
622 Verify IPFIX NAT44EI session create/delete event
623
624 :param data: Decoded IPFIX data records
625 """
626 nat44_ses_create_num = 0
627 nat44_ses_delete_num = 0
628 self.assertEqual(6, len(data))
629 for record in data:
630 # natEvent
631 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
632 if scapy.compat.orb(record[230]) == 4:
633 nat44_ses_create_num += 1
634 else:
635 nat44_ses_delete_num += 1
636 # sourceIPv4Address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200637 self.assertEqual(self.pg0.remote_ip4, str(ipaddress.IPv4Address(record[8])))
Filip Varga18f1e412020-12-03 15:27:40 +0100638 # postNATSourceIPv4Address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200639 self.assertEqual(
640 socket.inet_pton(socket.AF_INET, self.nat_addr), record[225]
641 )
Filip Varga18f1e412020-12-03 15:27:40 +0100642 # ingressVRFID
643 self.assertEqual(struct.pack("!I", 0), record[234])
644 # protocolIdentifier/sourceTransportPort
645 # /postNAPTSourceTransportPort
646 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
647 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200648 self.assertEqual(struct.pack("!H", self.icmp_id_out), record[227])
Filip Varga18f1e412020-12-03 15:27:40 +0100649 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200650 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
651 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
Filip Varga18f1e412020-12-03 15:27:40 +0100652 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200653 self.assertEqual(struct.pack("!H", self.udp_port_in), record[7])
654 self.assertEqual(struct.pack("!H", self.udp_port_out), record[227])
Filip Varga18f1e412020-12-03 15:27:40 +0100655 else:
Klement Sekeraff334db2021-05-26 13:02:35 +0200656 self.fail(f"Invalid protocol {scapy.compat.orb(record[4])}")
Filip Varga18f1e412020-12-03 15:27:40 +0100657 self.assertEqual(3, nat44_ses_create_num)
658 self.assertEqual(3, nat44_ses_delete_num)
659
660 def verify_ipfix_addr_exhausted(self, data):
661 self.assertEqual(1, len(data))
662 record = data[0]
663 # natEvent
664 self.assertEqual(scapy.compat.orb(record[230]), 3)
665 # natPoolID
666 self.assertEqual(struct.pack("!I", 0), record[283])
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +0500667 return len(data)
Filip Varga18f1e412020-12-03 15:27:40 +0100668
669 def verify_ipfix_max_sessions(self, data, limit):
670 self.assertEqual(1, len(data))
671 record = data[0]
672 # natEvent
673 self.assertEqual(scapy.compat.orb(record[230]), 13)
674 # natQuotaExceededEvent
Matthew Smithe3f078f2020-11-04 11:18:10 -0600675 self.assertEqual(struct.pack("!I", 1), record[466])
Filip Varga18f1e412020-12-03 15:27:40 +0100676 # maxSessionEntries
Matthew Smithe3f078f2020-11-04 11:18:10 -0600677 self.assertEqual(struct.pack("!I", limit), record[471])
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +0500678 return len(data)
Filip Varga18f1e412020-12-03 15:27:40 +0100679
680 def verify_no_nat44_user(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200681 """Verify that there is no NAT44EI user"""
Filip Varga0eaf4e62021-02-17 14:34:54 +0100682 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +0100683 self.assertEqual(len(users), 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200684 users = self.statistics["/nat44-ei/total-users"]
Filip Varga18f1e412020-12-03 15:27:40 +0100685 self.assertEqual(users[0][0], 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200686 sessions = self.statistics["/nat44-ei/total-sessions"]
Filip Varga18f1e412020-12-03 15:27:40 +0100687 self.assertEqual(sessions[0][0], 0)
688
689 def verify_syslog_apmap(self, data, is_add=True):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200690 message = data.decode("utf-8")
Filip Varga18f1e412020-12-03 15:27:40 +0100691 try:
692 message = SyslogMessage.parse(message)
693 except ParseError as e:
694 self.logger.error(e)
695 raise
696 else:
697 self.assertEqual(message.severity, SyslogSeverity.info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200698 self.assertEqual(message.appname, "NAT")
699 self.assertEqual(message.msgid, "APMADD" if is_add else "APMDEL")
700 sd_params = message.sd.get("napmap")
Filip Varga18f1e412020-12-03 15:27:40 +0100701 self.assertTrue(sd_params is not None)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200702 self.assertEqual(sd_params.get("IATYP"), "IPv4")
703 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip4)
704 self.assertEqual(sd_params.get("ISPORT"), "%d" % self.tcp_port_in)
705 self.assertEqual(sd_params.get("XATYP"), "IPv4")
706 self.assertEqual(sd_params.get("XSADDR"), self.nat_addr)
707 self.assertEqual(sd_params.get("XSPORT"), "%d" % self.tcp_port_out)
708 self.assertEqual(sd_params.get("PROTO"), "%d" % IP_PROTOS.tcp)
709 self.assertTrue(sd_params.get("SSUBIX") is not None)
710 self.assertEqual(sd_params.get("SVLAN"), "0")
Filip Varga18f1e412020-12-03 15:27:40 +0100711
712 def verify_mss_value(self, pkt, mss):
713 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
714 raise TypeError("Not a TCP/IP packet")
715
716 for option in pkt[TCP].options:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200717 if option[0] == "MSS":
Filip Varga18f1e412020-12-03 15:27:40 +0100718 self.assertEqual(option[1], mss)
719 self.assert_tcp_checksum_valid(pkt)
720
721 @staticmethod
722 def proto2layer(proto):
723 if proto == IP_PROTOS.tcp:
724 return TCP
725 elif proto == IP_PROTOS.udp:
726 return UDP
727 elif proto == IP_PROTOS.icmp:
728 return ICMP
729 else:
730 raise Exception("Unsupported protocol")
731
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200732 def frag_in_order(
733 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
734 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100735 layer = self.proto2layer(proto)
736
737 if proto == IP_PROTOS.tcp:
738 data = b"A" * 4 + b"B" * 16 + b"C" * 3
739 else:
740 data = b"A" * 16 + b"B" * 16 + b"C" * 3
741 self.port_in = random.randint(1025, 65535)
742
743 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200744 pkts = self.create_stream_frag(
745 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
746 )
Filip Varga18f1e412020-12-03 15:27:40 +0100747 self.pg0.add_stream(pkts)
748 self.pg_enable_capture(self.pg_interfaces)
749 self.pg_start()
750 frags = self.pg1.get_capture(len(pkts))
751 if not dont_translate:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200752 p = self.reass_frags_and_verify(frags, self.nat_addr, self.pg1.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +0100753 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200754 p = self.reass_frags_and_verify(
755 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
756 )
Filip Varga18f1e412020-12-03 15:27:40 +0100757 if proto != IP_PROTOS.icmp:
758 if not dont_translate:
759 self.assertEqual(p[layer].dport, 20)
760 if not ignore_port:
761 self.assertNotEqual(p[layer].sport, self.port_in)
762 else:
763 self.assertEqual(p[layer].sport, self.port_in)
764 else:
765 if not ignore_port:
766 if not dont_translate:
767 self.assertNotEqual(p[layer].id, self.port_in)
768 else:
769 self.assertEqual(p[layer].id, self.port_in)
770 self.assertEqual(data, p[Raw].load)
771
772 # out2in
773 if not dont_translate:
774 dst_addr = self.nat_addr
775 else:
776 dst_addr = self.pg0.remote_ip4
777 if proto != IP_PROTOS.icmp:
778 sport = 20
779 dport = p[layer].sport
780 else:
781 sport = p[layer].id
782 dport = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200783 pkts = self.create_stream_frag(
784 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
785 )
Filip Varga18f1e412020-12-03 15:27:40 +0100786 self.pg1.add_stream(pkts)
787 self.pg_enable_capture(self.pg_interfaces)
788 self.pg_start()
789 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200790 p = self.reass_frags_and_verify(frags, self.pg1.remote_ip4, self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +0100791 if proto != IP_PROTOS.icmp:
792 self.assertEqual(p[layer].sport, 20)
793 self.assertEqual(p[layer].dport, self.port_in)
794 else:
795 self.assertEqual(p[layer].id, self.port_in)
796 self.assertEqual(data, p[Raw].load)
797
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200798 def reass_hairpinning(
799 self,
800 server_addr,
801 server_in_port,
802 server_out_port,
803 host_in_port,
804 proto=IP_PROTOS.tcp,
805 ignore_port=False,
806 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100807 layer = self.proto2layer(proto)
808
809 if proto == IP_PROTOS.tcp:
810 data = b"A" * 4 + b"B" * 16 + b"C" * 3
811 else:
812 data = b"A" * 16 + b"B" * 16 + b"C" * 3
813
814 # send packet from host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200815 pkts = self.create_stream_frag(
816 self.pg0, self.nat_addr, host_in_port, server_out_port, data, proto
817 )
Filip Varga18f1e412020-12-03 15:27:40 +0100818 self.pg0.add_stream(pkts)
819 self.pg_enable_capture(self.pg_interfaces)
820 self.pg_start()
821 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200822 p = self.reass_frags_and_verify(frags, self.nat_addr, server_addr)
Filip Varga18f1e412020-12-03 15:27:40 +0100823 if proto != IP_PROTOS.icmp:
824 if not ignore_port:
825 self.assertNotEqual(p[layer].sport, host_in_port)
826 self.assertEqual(p[layer].dport, server_in_port)
827 else:
828 if not ignore_port:
829 self.assertNotEqual(p[layer].id, host_in_port)
830 self.assertEqual(data, p[Raw].load)
831
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200832 def frag_out_of_order(
833 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
834 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100835 layer = self.proto2layer(proto)
836
837 if proto == IP_PROTOS.tcp:
838 data = b"A" * 4 + b"B" * 16 + b"C" * 3
839 else:
840 data = b"A" * 16 + b"B" * 16 + b"C" * 3
841 self.port_in = random.randint(1025, 65535)
842
843 for i in range(2):
844 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200845 pkts = self.create_stream_frag(
846 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
847 )
Filip Varga18f1e412020-12-03 15:27:40 +0100848 pkts.reverse()
849 self.pg0.add_stream(pkts)
850 self.pg_enable_capture(self.pg_interfaces)
851 self.pg_start()
852 frags = self.pg1.get_capture(len(pkts))
853 if not dont_translate:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200854 p = self.reass_frags_and_verify(
855 frags, self.nat_addr, self.pg1.remote_ip4
856 )
Filip Varga18f1e412020-12-03 15:27:40 +0100857 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200858 p = self.reass_frags_and_verify(
859 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
860 )
Filip Varga18f1e412020-12-03 15:27:40 +0100861 if proto != IP_PROTOS.icmp:
862 if not dont_translate:
863 self.assertEqual(p[layer].dport, 20)
864 if not ignore_port:
865 self.assertNotEqual(p[layer].sport, self.port_in)
866 else:
867 self.assertEqual(p[layer].sport, self.port_in)
868 else:
869 if not ignore_port:
870 if not dont_translate:
871 self.assertNotEqual(p[layer].id, self.port_in)
872 else:
873 self.assertEqual(p[layer].id, self.port_in)
874 self.assertEqual(data, p[Raw].load)
875
876 # out2in
877 if not dont_translate:
878 dst_addr = self.nat_addr
879 else:
880 dst_addr = self.pg0.remote_ip4
881 if proto != IP_PROTOS.icmp:
882 sport = 20
883 dport = p[layer].sport
884 else:
885 sport = p[layer].id
886 dport = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200887 pkts = self.create_stream_frag(
888 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
889 )
Filip Varga18f1e412020-12-03 15:27:40 +0100890 pkts.reverse()
891 self.pg1.add_stream(pkts)
892 self.pg_enable_capture(self.pg_interfaces)
893 self.pg_start()
894 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200895 p = self.reass_frags_and_verify(
896 frags, self.pg1.remote_ip4, self.pg0.remote_ip4
897 )
Filip Varga18f1e412020-12-03 15:27:40 +0100898 if proto != IP_PROTOS.icmp:
899 self.assertEqual(p[layer].sport, 20)
900 self.assertEqual(p[layer].dport, self.port_in)
901 else:
902 self.assertEqual(p[layer].id, self.port_in)
903 self.assertEqual(data, p[Raw].load)
904
905
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100906def get_nat44_ei_in2out_worker_index(ip, vpp_worker_count):
907 if 0 == vpp_worker_count:
908 return 0
909 numeric = socket.inet_aton(ip)
910 numeric = struct.unpack("!L", numeric)[0]
911 numeric = socket.htonl(numeric)
912 h = numeric + (numeric >> 8) + (numeric >> 16) + (numeric >> 24)
913 return 1 + h % vpp_worker_count
914
915
Dave Wallace670724c2022-09-20 21:52:18 -0400916@tag_fixme_debian11
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000917@unittest.skipIf("nat" in config.excluded_plugins, "Exclude NAT plugin tests")
Filip Varga18f1e412020-12-03 15:27:40 +0100918class TestNAT44EI(MethodHolder):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200919 """NAT44EI Test Cases"""
Filip Varga18f1e412020-12-03 15:27:40 +0100920
921 max_translations = 10240
922 max_users = 10240
923
924 @classmethod
925 def setUpClass(cls):
926 super(TestNAT44EI, cls).setUpClass()
Dave Wallace670724c2022-09-20 21:52:18 -0400927 if is_distro_debian11 == True and not hasattr(cls, "vpp"):
928 return
Filip Varga0eaf4e62021-02-17 14:34:54 +0100929 cls.vapi.cli("set log class nat44-ei level debug")
Filip Varga18f1e412020-12-03 15:27:40 +0100930
931 cls.tcp_port_in = 6303
932 cls.tcp_port_out = 6303
933 cls.udp_port_in = 6304
934 cls.udp_port_out = 6304
935 cls.icmp_id_in = 6305
936 cls.icmp_id_out = 6305
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200937 cls.nat_addr = "10.0.0.3"
Filip Varga18f1e412020-12-03 15:27:40 +0100938 cls.ipfix_src_port = 4739
939 cls.ipfix_domain_id = 1
940 cls.tcp_external_port = 80
941 cls.udp_external_port = 69
942
943 cls.create_pg_interfaces(range(10))
944 cls.interfaces = list(cls.pg_interfaces[0:4])
945
946 for i in cls.interfaces:
947 i.admin_up()
948 i.config_ip4()
949 i.resolve_arp()
950
951 cls.pg0.generate_remote_hosts(3)
952 cls.pg0.configure_ipv4_neighbors()
953
954 cls.pg1.generate_remote_hosts(1)
955 cls.pg1.configure_ipv4_neighbors()
956
957 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Benoît Ganneff570d32024-04-16 09:36:05 +0200958 cls.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": 10})
959 cls.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": 20})
Filip Varga18f1e412020-12-03 15:27:40 +0100960
961 cls.pg4._local_ip4 = "172.16.255.1"
962 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
963 cls.pg4.set_table_ip4(10)
964 cls.pg5._local_ip4 = "172.17.255.3"
965 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
966 cls.pg5.set_table_ip4(10)
967 cls.pg6._local_ip4 = "172.16.255.1"
968 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
969 cls.pg6.set_table_ip4(20)
970 for i in cls.overlapping_interfaces:
971 i.config_ip4()
972 i.admin_up()
973 i.resolve_arp()
974
975 cls.pg7.admin_up()
976 cls.pg8.admin_up()
977
978 cls.pg9.generate_remote_hosts(2)
979 cls.pg9.config_ip4()
980 cls.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200981 sw_if_index=cls.pg9.sw_if_index, prefix="10.0.0.1/24"
982 )
Filip Varga18f1e412020-12-03 15:27:40 +0100983
984 cls.pg9.admin_up()
985 cls.pg9.resolve_arp()
986 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
987 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
988 cls.pg9.resolve_arp()
989
Filip Varga0eaf4e62021-02-17 14:34:54 +0100990 def plugin_enable(self):
991 self.vapi.nat44_ei_plugin_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200992 sessions=self.max_translations, users=self.max_users, enable=1
993 )
Filip Varga18f1e412020-12-03 15:27:40 +0100994
Filip Varga0eaf4e62021-02-17 14:34:54 +0100995 def setUp(self):
996 super(TestNAT44EI, self).setUp()
997 self.plugin_enable()
998
Filip Varga18f1e412020-12-03 15:27:40 +0100999 def tearDown(self):
1000 super(TestNAT44EI, self).tearDown()
1001 if not self.vpp_dead:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001002 self.vapi.nat44_ei_ipfix_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001003 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port, enable=0
1004 )
Filip Varga18f1e412020-12-03 15:27:40 +01001005 self.ipfix_src_port = 4739
1006 self.ipfix_domain_id = 1
1007
Filip Varga0eaf4e62021-02-17 14:34:54 +01001008 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +01001009 self.vapi.cli("clear logging")
1010
1011 def test_clear_sessions(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001012 """NAT44EI session clearing test"""
Filip Varga18f1e412020-12-03 15:27:40 +01001013
1014 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001015 flags = self.config_flags.NAT44_EI_IF_INSIDE
1016 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001017 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1018 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001019 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001020 sw_if_index=self.pg1.sw_if_index, is_add=1
1021 )
Filip Varga18f1e412020-12-03 15:27:40 +01001022
Filip Varga18f1e412020-12-03 15:27:40 +01001023 pkts = self.create_stream_in(self.pg0, self.pg1)
1024 self.pg0.add_stream(pkts)
1025 self.pg_enable_capture(self.pg_interfaces)
1026 self.pg_start()
1027 capture = self.pg1.get_capture(len(pkts))
1028 self.verify_capture_out(capture)
1029
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001030 sessions = self.statistics["/nat44-ei/total-sessions"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001031 self.assertGreater(sessions[:, 0].sum(), 0, "Session count invalid")
Filip Varga18f1e412020-12-03 15:27:40 +01001032 self.logger.info("sessions before clearing: %s" % sessions[0][0])
1033
Filip Varga0eaf4e62021-02-17 14:34:54 +01001034 self.vapi.cli("clear nat44 ei sessions")
Filip Varga18f1e412020-12-03 15:27:40 +01001035
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 sessions = self.statistics["/nat44-ei/total-sessions"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001037 self.assertEqual(sessions[:, 0].sum(), 0, "Session count invalid")
Filip Varga18f1e412020-12-03 15:27:40 +01001038 self.logger.info("sessions after clearing: %s" % sessions[0][0])
1039
1040 def test_dynamic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001041 """NAT44EI dynamic translation test"""
Filip Varga18f1e412020-12-03 15:27:40 +01001042 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001043 flags = self.config_flags.NAT44_EI_IF_INSIDE
1044 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001045 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1046 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001047 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001048 sw_if_index=self.pg1.sw_if_index, is_add=1
1049 )
Filip Varga18f1e412020-12-03 15:27:40 +01001050
1051 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001052 tcpn = self.statistics["/nat44-ei/in2out/slowpath/tcp"]
1053 udpn = self.statistics["/nat44-ei/in2out/slowpath/udp"]
1054 icmpn = self.statistics["/nat44-ei/in2out/slowpath/icmp"]
1055 drops = self.statistics["/nat44-ei/in2out/slowpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01001056
1057 pkts = self.create_stream_in(self.pg0, self.pg1)
1058 self.pg0.add_stream(pkts)
1059 self.pg_enable_capture(self.pg_interfaces)
1060 self.pg_start()
1061 capture = self.pg1.get_capture(len(pkts))
1062 self.verify_capture_out(capture)
1063
1064 if_idx = self.pg0.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001065 cnt = self.statistics["/nat44-ei/in2out/slowpath/tcp"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001066 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001067 cnt = self.statistics["/nat44-ei/in2out/slowpath/udp"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001068 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 cnt = self.statistics["/nat44-ei/in2out/slowpath/icmp"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001070 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001071 cnt = self.statistics["/nat44-ei/in2out/slowpath/drops"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001072 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001073
1074 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001075 tcpn = self.statistics["/nat44-ei/out2in/slowpath/tcp"]
1076 udpn = self.statistics["/nat44-ei/out2in/slowpath/udp"]
1077 icmpn = self.statistics["/nat44-ei/out2in/slowpath/icmp"]
1078 drops = self.statistics["/nat44-ei/out2in/slowpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01001079
1080 pkts = self.create_stream_out(self.pg1)
1081 self.pg1.add_stream(pkts)
1082 self.pg_enable_capture(self.pg_interfaces)
1083 self.pg_start()
1084 capture = self.pg0.get_capture(len(pkts))
1085 self.verify_capture_in(capture, self.pg0)
1086
1087 if_idx = self.pg1.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001088 cnt = self.statistics["/nat44-ei/out2in/slowpath/tcp"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001089 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001090 cnt = self.statistics["/nat44-ei/out2in/slowpath/udp"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001091 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001092 cnt = self.statistics["/nat44-ei/out2in/slowpath/icmp"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001093 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001094 cnt = self.statistics["/nat44-ei/out2in/slowpath/drops"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001095 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001096
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001097 users = self.statistics["/nat44-ei/total-users"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001098 self.assertEqual(users[:, 0].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001099 sessions = self.statistics["/nat44-ei/total-sessions"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001100 self.assertEqual(sessions[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01001101
1102 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001103 """NAT44EI handling of client packets with TTL=1"""
Filip Varga18f1e412020-12-03 15:27:40 +01001104
1105 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001106 flags = self.config_flags.NAT44_EI_IF_INSIDE
1107 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001108 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1109 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001110 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001111 sw_if_index=self.pg1.sw_if_index, is_add=1
1112 )
Filip Varga18f1e412020-12-03 15:27:40 +01001113
1114 # Client side - generate traffic
1115 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001116 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01001117
1118 # Client side - verify ICMP type 11 packets
Filip Varga18f1e412020-12-03 15:27:40 +01001119 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1120
1121 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001122 """NAT44EI handling of server packets with TTL=1"""
Filip Varga18f1e412020-12-03 15:27:40 +01001123
1124 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001125 flags = self.config_flags.NAT44_EI_IF_INSIDE
1126 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001127 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1128 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001129 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001130 sw_if_index=self.pg1.sw_if_index, is_add=1
1131 )
Filip Varga18f1e412020-12-03 15:27:40 +01001132
1133 # Client side - create sessions
1134 pkts = self.create_stream_in(self.pg0, self.pg1)
1135 self.pg0.add_stream(pkts)
1136 self.pg_enable_capture(self.pg_interfaces)
1137 self.pg_start()
1138
1139 # Server side - generate traffic
1140 capture = self.pg1.get_capture(len(pkts))
1141 self.verify_capture_out(capture)
1142 pkts = self.create_stream_out(self.pg1, ttl=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001143 capture = self.send_and_expect_some(self.pg1, pkts, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01001144
1145 # Server side - verify ICMP type 11 packets
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001146 self.verify_capture_out_with_icmp_errors(capture, src_ip=self.pg1.local_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01001147
1148 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001149 """NAT44EI handling of error responses to client packets with TTL=2"""
Filip Varga18f1e412020-12-03 15:27:40 +01001150
1151 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001152 flags = self.config_flags.NAT44_EI_IF_INSIDE
1153 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001154 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1155 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001156 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001157 sw_if_index=self.pg1.sw_if_index, is_add=1
1158 )
Filip Varga18f1e412020-12-03 15:27:40 +01001159
1160 # Client side - generate traffic
1161 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1162 self.pg0.add_stream(pkts)
1163 self.pg_enable_capture(self.pg_interfaces)
1164 self.pg_start()
1165
1166 # Server side - simulate ICMP type 11 response
1167 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001168 pkts = [
1169 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1170 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1171 / ICMP(type=11)
1172 / packet[IP]
1173 for packet in capture
1174 ]
Filip Varga18f1e412020-12-03 15:27:40 +01001175 self.pg1.add_stream(pkts)
1176 self.pg_enable_capture(self.pg_interfaces)
1177 self.pg_start()
1178
1179 # Client side - verify ICMP type 11 packets
1180 capture = self.pg0.get_capture(len(pkts))
1181 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1182
1183 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001184 """NAT44EI handling of error responses to server packets with TTL=2"""
Filip Varga18f1e412020-12-03 15:27:40 +01001185
1186 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001187 flags = self.config_flags.NAT44_EI_IF_INSIDE
1188 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001189 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1190 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001191 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001192 sw_if_index=self.pg1.sw_if_index, is_add=1
1193 )
Filip Varga18f1e412020-12-03 15:27:40 +01001194
1195 # Client side - create sessions
1196 pkts = self.create_stream_in(self.pg0, self.pg1)
1197 self.pg0.add_stream(pkts)
1198 self.pg_enable_capture(self.pg_interfaces)
1199 self.pg_start()
1200
1201 # Server side - generate traffic
1202 capture = self.pg1.get_capture(len(pkts))
1203 self.verify_capture_out(capture)
1204 pkts = self.create_stream_out(self.pg1, ttl=2)
1205 self.pg1.add_stream(pkts)
1206 self.pg_enable_capture(self.pg_interfaces)
1207 self.pg_start()
1208
1209 # Client side - simulate ICMP type 11 response
1210 capture = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001211 pkts = [
1212 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1213 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1214 / ICMP(type=11)
1215 / packet[IP]
1216 for packet in capture
1217 ]
Filip Varga18f1e412020-12-03 15:27:40 +01001218 self.pg0.add_stream(pkts)
1219 self.pg_enable_capture(self.pg_interfaces)
1220 self.pg_start()
1221
1222 # Server side - verify ICMP type 11 packets
1223 capture = self.pg1.get_capture(len(pkts))
1224 self.verify_capture_out_with_icmp_errors(capture)
1225
1226 def test_ping_out_interface_from_outside(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001227 """NAT44EI ping out interface from outside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01001228
1229 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001230 flags = self.config_flags.NAT44_EI_IF_INSIDE
1231 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001232 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1233 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001234 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001235 sw_if_index=self.pg1.sw_if_index, is_add=1
1236 )
Filip Varga18f1e412020-12-03 15:27:40 +01001237
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001238 p = (
1239 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1240 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1241 / ICMP(id=self.icmp_id_out, type="echo-request")
1242 )
Filip Varga18f1e412020-12-03 15:27:40 +01001243 pkts = [p]
1244 self.pg1.add_stream(pkts)
1245 self.pg_enable_capture(self.pg_interfaces)
1246 self.pg_start()
1247 capture = self.pg1.get_capture(len(pkts))
1248 packet = capture[0]
1249 try:
1250 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1251 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1252 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1253 self.assertEqual(packet[ICMP].type, 0) # echo reply
1254 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001255 self.logger.error(
1256 ppp("Unexpected or invalid packet (outside network):", packet)
1257 )
Filip Varga18f1e412020-12-03 15:27:40 +01001258 raise
1259
1260 def test_ping_internal_host_from_outside(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001261 """NAT44EI ping internal host from outside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01001262
1263 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001264 flags = self.config_flags.NAT44_EI_IF_INSIDE
1265 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001266 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1267 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001268 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001269 sw_if_index=self.pg1.sw_if_index, is_add=1
1270 )
Filip Varga18f1e412020-12-03 15:27:40 +01001271
1272 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001273 pkt = (
1274 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1275 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64)
1276 / ICMP(id=self.icmp_id_out, type="echo-request")
1277 )
Filip Varga18f1e412020-12-03 15:27:40 +01001278 self.pg1.add_stream(pkt)
1279 self.pg_enable_capture(self.pg_interfaces)
1280 self.pg_start()
1281 capture = self.pg0.get_capture(1)
1282 self.verify_capture_in(capture, self.pg0)
1283 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1284
1285 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001286 pkt = (
1287 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1288 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
1289 / ICMP(id=self.icmp_id_in, type="echo-reply")
1290 )
Filip Varga18f1e412020-12-03 15:27:40 +01001291 self.pg0.add_stream(pkt)
1292 self.pg_enable_capture(self.pg_interfaces)
1293 self.pg_start()
1294 capture = self.pg1.get_capture(1)
1295 self.verify_capture_out(capture, same_port=True)
1296 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1297
1298 def test_forwarding(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001299 """NAT44EI forwarding test"""
Filip Varga18f1e412020-12-03 15:27:40 +01001300
Filip Varga0eaf4e62021-02-17 14:34:54 +01001301 flags = self.config_flags.NAT44_EI_IF_INSIDE
1302 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001303 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1304 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001305 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001306 sw_if_index=self.pg1.sw_if_index, is_add=1
1307 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001308 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01001309
1310 real_ip = self.pg0.remote_ip4
1311 alias_ip = self.nat_addr
Filip Varga0eaf4e62021-02-17 14:34:54 +01001312 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1313 self.vapi.nat44_ei_add_del_static_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001314 is_add=1,
1315 local_ip_address=real_ip,
Filip Varga0eaf4e62021-02-17 14:34:54 +01001316 external_ip_address=alias_ip,
1317 external_sw_if_index=0xFFFFFFFF,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001318 flags=flags,
1319 )
Filip Varga18f1e412020-12-03 15:27:40 +01001320
1321 try:
1322 # static mapping match
1323
1324 pkts = self.create_stream_out(self.pg1)
1325 self.pg1.add_stream(pkts)
1326 self.pg_enable_capture(self.pg_interfaces)
1327 self.pg_start()
1328 capture = self.pg0.get_capture(len(pkts))
1329 self.verify_capture_in(capture, self.pg0)
1330
1331 pkts = self.create_stream_in(self.pg0, self.pg1)
1332 self.pg0.add_stream(pkts)
1333 self.pg_enable_capture(self.pg_interfaces)
1334 self.pg_start()
1335 capture = self.pg1.get_capture(len(pkts))
1336 self.verify_capture_out(capture, same_port=True)
1337
1338 # no static mapping match
1339
1340 host0 = self.pg0.remote_hosts[0]
1341 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1342 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001343 pkts = self.create_stream_out(
1344 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1345 )
Filip Varga18f1e412020-12-03 15:27:40 +01001346 self.pg1.add_stream(pkts)
1347 self.pg_enable_capture(self.pg_interfaces)
1348 self.pg_start()
1349 capture = self.pg0.get_capture(len(pkts))
1350 self.verify_capture_in(capture, self.pg0)
1351
1352 pkts = self.create_stream_in(self.pg0, self.pg1)
1353 self.pg0.add_stream(pkts)
1354 self.pg_enable_capture(self.pg_interfaces)
1355 self.pg_start()
1356 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001357 self.verify_capture_out(
1358 capture, nat_ip=self.pg0.remote_ip4, same_port=True
1359 )
Filip Varga18f1e412020-12-03 15:27:40 +01001360 finally:
1361 self.pg0.remote_hosts[0] = host0
1362
1363 finally:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001364 self.vapi.nat44_ei_forwarding_enable_disable(enable=0)
1365 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1366 self.vapi.nat44_ei_add_del_static_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +01001367 is_add=0,
1368 local_ip_address=real_ip,
1369 external_ip_address=alias_ip,
1370 external_sw_if_index=0xFFFFFFFF,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001371 flags=flags,
1372 )
Filip Varga18f1e412020-12-03 15:27:40 +01001373
1374 def test_static_in(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001375 """NAT44EI 1:1 NAT initialized from inside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01001376
1377 nat_ip = "10.0.0.10"
1378 self.tcp_port_out = 6303
1379 self.udp_port_out = 6304
1380 self.icmp_id_out = 6305
1381
1382 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001383 flags = self.config_flags.NAT44_EI_IF_INSIDE
1384 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001385 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1386 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001387 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001388 sw_if_index=self.pg1.sw_if_index, is_add=1
1389 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001390 sm = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001391 self.assertEqual(len(sm), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001392 self.assertEqual(sm[0].tag, "")
Filip Varga18f1e412020-12-03 15:27:40 +01001393 self.assertEqual(sm[0].protocol, 0)
1394 self.assertEqual(sm[0].local_port, 0)
1395 self.assertEqual(sm[0].external_port, 0)
1396
1397 # in2out
1398 pkts = self.create_stream_in(self.pg0, self.pg1)
1399 self.pg0.add_stream(pkts)
1400 self.pg_enable_capture(self.pg_interfaces)
1401 self.pg_start()
1402 capture = self.pg1.get_capture(len(pkts))
1403 self.verify_capture_out(capture, nat_ip, True)
1404
1405 # out2in
1406 pkts = self.create_stream_out(self.pg1, nat_ip)
1407 self.pg1.add_stream(pkts)
1408 self.pg_enable_capture(self.pg_interfaces)
1409 self.pg_start()
1410 capture = self.pg0.get_capture(len(pkts))
1411 self.verify_capture_in(capture, self.pg0)
1412
1413 def test_static_out(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001414 """NAT44EI 1:1 NAT initialized from outside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01001415
1416 nat_ip = "10.0.0.20"
1417 self.tcp_port_out = 6303
1418 self.udp_port_out = 6304
1419 self.icmp_id_out = 6305
1420 tag = "testTAG"
1421
1422 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001423 flags = self.config_flags.NAT44_EI_IF_INSIDE
1424 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001425 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1426 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001427 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001428 sw_if_index=self.pg1.sw_if_index, is_add=1
1429 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001430 sm = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001431 self.assertEqual(len(sm), 1)
1432 self.assertEqual(sm[0].tag, tag)
1433
1434 # out2in
1435 pkts = self.create_stream_out(self.pg1, nat_ip)
1436 self.pg1.add_stream(pkts)
1437 self.pg_enable_capture(self.pg_interfaces)
1438 self.pg_start()
1439 capture = self.pg0.get_capture(len(pkts))
1440 self.verify_capture_in(capture, self.pg0)
1441
1442 # in2out
1443 pkts = self.create_stream_in(self.pg0, self.pg1)
1444 self.pg0.add_stream(pkts)
1445 self.pg_enable_capture(self.pg_interfaces)
1446 self.pg_start()
1447 capture = self.pg1.get_capture(len(pkts))
1448 self.verify_capture_out(capture, nat_ip, True)
1449
1450 def test_static_with_port_in(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001451 """NAT44EI 1:1 NAPT initialized from inside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01001452
1453 self.tcp_port_out = 3606
1454 self.udp_port_out = 3607
1455 self.icmp_id_out = 3608
1456
1457 self.nat44_add_address(self.nat_addr)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001458 self.nat44_add_static_mapping(
1459 self.pg0.remote_ip4,
1460 self.nat_addr,
1461 self.tcp_port_in,
1462 self.tcp_port_out,
1463 proto=IP_PROTOS.tcp,
1464 )
1465 self.nat44_add_static_mapping(
1466 self.pg0.remote_ip4,
1467 self.nat_addr,
1468 self.udp_port_in,
1469 self.udp_port_out,
1470 proto=IP_PROTOS.udp,
1471 )
1472 self.nat44_add_static_mapping(
1473 self.pg0.remote_ip4,
1474 self.nat_addr,
1475 self.icmp_id_in,
1476 self.icmp_id_out,
1477 proto=IP_PROTOS.icmp,
1478 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001479 flags = self.config_flags.NAT44_EI_IF_INSIDE
1480 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001481 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1482 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001483 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001484 sw_if_index=self.pg1.sw_if_index, is_add=1
1485 )
Filip Varga18f1e412020-12-03 15:27:40 +01001486
1487 # in2out
1488 pkts = self.create_stream_in(self.pg0, self.pg1)
1489 self.pg0.add_stream(pkts)
1490 self.pg_enable_capture(self.pg_interfaces)
1491 self.pg_start()
1492 capture = self.pg1.get_capture(len(pkts))
1493 self.verify_capture_out(capture)
1494
1495 # out2in
1496 pkts = self.create_stream_out(self.pg1)
1497 self.pg1.add_stream(pkts)
1498 self.pg_enable_capture(self.pg_interfaces)
1499 self.pg_start()
1500 capture = self.pg0.get_capture(len(pkts))
1501 self.verify_capture_in(capture, self.pg0)
1502
1503 def test_static_with_port_out(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001504 """NAT44EI 1:1 NAPT initialized from outside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01001505
1506 self.tcp_port_out = 30606
1507 self.udp_port_out = 30607
1508 self.icmp_id_out = 30608
1509
1510 self.nat44_add_address(self.nat_addr)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001511 self.nat44_add_static_mapping(
1512 self.pg0.remote_ip4,
1513 self.nat_addr,
1514 self.tcp_port_in,
1515 self.tcp_port_out,
1516 proto=IP_PROTOS.tcp,
1517 )
1518 self.nat44_add_static_mapping(
1519 self.pg0.remote_ip4,
1520 self.nat_addr,
1521 self.udp_port_in,
1522 self.udp_port_out,
1523 proto=IP_PROTOS.udp,
1524 )
1525 self.nat44_add_static_mapping(
1526 self.pg0.remote_ip4,
1527 self.nat_addr,
1528 self.icmp_id_in,
1529 self.icmp_id_out,
1530 proto=IP_PROTOS.icmp,
1531 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001532 flags = self.config_flags.NAT44_EI_IF_INSIDE
1533 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001534 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1535 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001536 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001537 sw_if_index=self.pg1.sw_if_index, is_add=1
1538 )
Filip Varga18f1e412020-12-03 15:27:40 +01001539
1540 # out2in
1541 pkts = self.create_stream_out(self.pg1)
1542 self.pg1.add_stream(pkts)
1543 self.pg_enable_capture(self.pg_interfaces)
1544 self.pg_start()
1545 capture = self.pg0.get_capture(len(pkts))
1546 self.verify_capture_in(capture, self.pg0)
1547
1548 # in2out
1549 pkts = self.create_stream_in(self.pg0, self.pg1)
1550 self.pg0.add_stream(pkts)
1551 self.pg_enable_capture(self.pg_interfaces)
1552 self.pg_start()
1553 capture = self.pg1.get_capture(len(pkts))
1554 self.verify_capture_out(capture)
1555
1556 def test_static_vrf_aware(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001557 """NAT44EI 1:1 NAT VRF awareness"""
Filip Varga18f1e412020-12-03 15:27:40 +01001558
1559 nat_ip1 = "10.0.0.30"
1560 nat_ip2 = "10.0.0.40"
1561 self.tcp_port_out = 6303
1562 self.udp_port_out = 6304
1563 self.icmp_id_out = 6305
1564
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001565 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1, vrf_id=10)
1566 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2, vrf_id=10)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001567 flags = self.config_flags.NAT44_EI_IF_INSIDE
1568 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001569 sw_if_index=self.pg3.sw_if_index, is_add=1
1570 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001571 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001572 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1573 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001574 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001575 sw_if_index=self.pg4.sw_if_index, flags=flags, is_add=1
1576 )
Filip Varga18f1e412020-12-03 15:27:40 +01001577
1578 # inside interface VRF match NAT44EI static mapping VRF
1579 pkts = self.create_stream_in(self.pg4, self.pg3)
1580 self.pg4.add_stream(pkts)
1581 self.pg_enable_capture(self.pg_interfaces)
1582 self.pg_start()
1583 capture = self.pg3.get_capture(len(pkts))
1584 self.verify_capture_out(capture, nat_ip1, True)
1585
1586 # inside interface VRF don't match NAT44EI static mapping VRF (packets
1587 # are dropped)
1588 pkts = self.create_stream_in(self.pg0, self.pg3)
1589 self.pg0.add_stream(pkts)
1590 self.pg_enable_capture(self.pg_interfaces)
1591 self.pg_start()
1592 self.pg3.assert_nothing_captured()
1593
1594 def test_dynamic_to_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001595 """NAT44EI Switch from dynamic translation to 1:1NAT"""
Filip Varga18f1e412020-12-03 15:27:40 +01001596 nat_ip = "10.0.0.10"
1597 self.tcp_port_out = 6303
1598 self.udp_port_out = 6304
1599 self.icmp_id_out = 6305
1600
1601 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001602 flags = self.config_flags.NAT44_EI_IF_INSIDE
1603 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001604 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1605 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001606 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001607 sw_if_index=self.pg1.sw_if_index, is_add=1
1608 )
Filip Varga18f1e412020-12-03 15:27:40 +01001609
1610 # dynamic
1611 pkts = self.create_stream_in(self.pg0, self.pg1)
1612 self.pg0.add_stream(pkts)
1613 self.pg_enable_capture(self.pg_interfaces)
1614 self.pg_start()
1615 capture = self.pg1.get_capture(len(pkts))
1616 self.verify_capture_out(capture)
1617
1618 # 1:1NAT
1619 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001620 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001621 self.assertEqual(len(sessions), 0)
1622 pkts = self.create_stream_in(self.pg0, self.pg1)
1623 self.pg0.add_stream(pkts)
1624 self.pg_enable_capture(self.pg_interfaces)
1625 self.pg_start()
1626 capture = self.pg1.get_capture(len(pkts))
1627 self.verify_capture_out(capture, nat_ip, True)
1628
1629 def test_identity_nat(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001630 """NAT44EI Identity NAT"""
Filip Varga0eaf4e62021-02-17 14:34:54 +01001631 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1632 self.vapi.nat44_ei_add_del_identity_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001633 ip_address=self.pg0.remote_ip4,
1634 sw_if_index=0xFFFFFFFF,
1635 flags=flags,
1636 is_add=1,
1637 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001638 flags = self.config_flags.NAT44_EI_IF_INSIDE
1639 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001640 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1641 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001642 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001643 sw_if_index=self.pg1.sw_if_index, is_add=1
1644 )
Filip Varga18f1e412020-12-03 15:27:40 +01001645
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001646 p = (
1647 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1648 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
1649 / TCP(sport=12345, dport=56789)
1650 )
Filip Varga18f1e412020-12-03 15:27:40 +01001651 self.pg1.add_stream(p)
1652 self.pg_enable_capture(self.pg_interfaces)
1653 self.pg_start()
1654 capture = self.pg0.get_capture(1)
1655 p = capture[0]
1656 try:
1657 ip = p[IP]
1658 tcp = p[TCP]
1659 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1660 self.assertEqual(ip.src, self.pg1.remote_ip4)
1661 self.assertEqual(tcp.dport, 56789)
1662 self.assertEqual(tcp.sport, 12345)
1663 self.assert_packet_checksums_valid(p)
1664 except:
1665 self.logger.error(ppp("Unexpected or invalid packet:", p))
1666 raise
1667
Filip Varga0eaf4e62021-02-17 14:34:54 +01001668 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001669 self.assertEqual(len(sessions), 0)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001670 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1671 self.vapi.nat44_ei_add_del_identity_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001672 ip_address=self.pg0.remote_ip4,
1673 sw_if_index=0xFFFFFFFF,
1674 flags=flags,
1675 vrf_id=1,
1676 is_add=1,
1677 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001678 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001679 self.assertEqual(len(identity_mappings), 2)
1680
1681 def test_multiple_inside_interfaces(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001682 """NAT44EI multiple non-overlapping address space inside interfaces"""
Filip Varga18f1e412020-12-03 15:27:40 +01001683
1684 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001685 flags = self.config_flags.NAT44_EI_IF_INSIDE
1686 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001687 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1688 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001689 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001690 sw_if_index=self.pg1.sw_if_index, flags=flags, is_add=1
1691 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001692 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001693 sw_if_index=self.pg3.sw_if_index, is_add=1
1694 )
Filip Varga18f1e412020-12-03 15:27:40 +01001695
1696 # between two NAT44EI inside interfaces (no translation)
1697 pkts = self.create_stream_in(self.pg0, self.pg1)
1698 self.pg0.add_stream(pkts)
1699 self.pg_enable_capture(self.pg_interfaces)
1700 self.pg_start()
1701 capture = self.pg1.get_capture(len(pkts))
1702 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1703
1704 # from inside to interface without translation
1705 pkts = self.create_stream_in(self.pg0, self.pg2)
1706 self.pg0.add_stream(pkts)
1707 self.pg_enable_capture(self.pg_interfaces)
1708 self.pg_start()
1709 capture = self.pg2.get_capture(len(pkts))
1710 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1711
1712 # in2out 1st interface
1713 pkts = self.create_stream_in(self.pg0, self.pg3)
1714 self.pg0.add_stream(pkts)
1715 self.pg_enable_capture(self.pg_interfaces)
1716 self.pg_start()
1717 capture = self.pg3.get_capture(len(pkts))
1718 self.verify_capture_out(capture)
1719
1720 # out2in 1st interface
1721 pkts = self.create_stream_out(self.pg3)
1722 self.pg3.add_stream(pkts)
1723 self.pg_enable_capture(self.pg_interfaces)
1724 self.pg_start()
1725 capture = self.pg0.get_capture(len(pkts))
1726 self.verify_capture_in(capture, self.pg0)
1727
1728 # in2out 2nd interface
1729 pkts = self.create_stream_in(self.pg1, self.pg3)
1730 self.pg1.add_stream(pkts)
1731 self.pg_enable_capture(self.pg_interfaces)
1732 self.pg_start()
1733 capture = self.pg3.get_capture(len(pkts))
1734 self.verify_capture_out(capture)
1735
1736 # out2in 2nd interface
1737 pkts = self.create_stream_out(self.pg3)
1738 self.pg3.add_stream(pkts)
1739 self.pg_enable_capture(self.pg_interfaces)
1740 self.pg_start()
1741 capture = self.pg1.get_capture(len(pkts))
1742 self.verify_capture_in(capture, self.pg1)
1743
1744 def test_inside_overlapping_interfaces(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001745 """NAT44EI multiple inside interfaces with overlapping address space"""
Filip Varga18f1e412020-12-03 15:27:40 +01001746
1747 static_nat_ip = "10.0.0.10"
1748 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001749 flags = self.config_flags.NAT44_EI_IF_INSIDE
1750 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001751 sw_if_index=self.pg3.sw_if_index, is_add=1
1752 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001753 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001754 sw_if_index=self.pg4.sw_if_index, flags=flags, is_add=1
1755 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001756 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001757 sw_if_index=self.pg5.sw_if_index, flags=flags, is_add=1
1758 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001759 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001760 sw_if_index=self.pg6.sw_if_index, flags=flags, is_add=1
1761 )
1762 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip, vrf_id=20)
Filip Varga18f1e412020-12-03 15:27:40 +01001763
1764 # between NAT44EI inside interfaces with same VRF (no translation)
1765 pkts = self.create_stream_in(self.pg4, self.pg5)
1766 self.pg4.add_stream(pkts)
1767 self.pg_enable_capture(self.pg_interfaces)
1768 self.pg_start()
1769 capture = self.pg5.get_capture(len(pkts))
1770 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1771
1772 # between NAT44EI inside interfaces with different VRF (hairpinning)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001773 p = (
1774 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
1775 / IP(src=self.pg4.remote_ip4, dst=static_nat_ip)
1776 / TCP(sport=1234, dport=5678)
1777 )
Filip Varga18f1e412020-12-03 15:27:40 +01001778 self.pg4.add_stream(p)
1779 self.pg_enable_capture(self.pg_interfaces)
1780 self.pg_start()
1781 capture = self.pg6.get_capture(1)
1782 p = capture[0]
1783 try:
1784 ip = p[IP]
1785 tcp = p[TCP]
1786 self.assertEqual(ip.src, self.nat_addr)
1787 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1788 self.assertNotEqual(tcp.sport, 1234)
1789 self.assertEqual(tcp.dport, 5678)
1790 except:
1791 self.logger.error(ppp("Unexpected or invalid packet:", p))
1792 raise
1793
1794 # in2out 1st interface
1795 pkts = self.create_stream_in(self.pg4, self.pg3)
1796 self.pg4.add_stream(pkts)
1797 self.pg_enable_capture(self.pg_interfaces)
1798 self.pg_start()
1799 capture = self.pg3.get_capture(len(pkts))
1800 self.verify_capture_out(capture)
1801
1802 # out2in 1st interface
1803 pkts = self.create_stream_out(self.pg3)
1804 self.pg3.add_stream(pkts)
1805 self.pg_enable_capture(self.pg_interfaces)
1806 self.pg_start()
1807 capture = self.pg4.get_capture(len(pkts))
1808 self.verify_capture_in(capture, self.pg4)
1809
1810 # in2out 2nd interface
1811 pkts = self.create_stream_in(self.pg5, self.pg3)
1812 self.pg5.add_stream(pkts)
1813 self.pg_enable_capture(self.pg_interfaces)
1814 self.pg_start()
1815 capture = self.pg3.get_capture(len(pkts))
1816 self.verify_capture_out(capture)
1817
1818 # out2in 2nd interface
1819 pkts = self.create_stream_out(self.pg3)
1820 self.pg3.add_stream(pkts)
1821 self.pg_enable_capture(self.pg_interfaces)
1822 self.pg_start()
1823 capture = self.pg5.get_capture(len(pkts))
1824 self.verify_capture_in(capture, self.pg5)
1825
1826 # pg5 session dump
Filip Varga0eaf4e62021-02-17 14:34:54 +01001827 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001828 self.assertEqual(len(addresses), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001829 sessions = self.vapi.nat44_ei_user_session_dump(self.pg5.remote_ip4, 10)
Filip Varga18f1e412020-12-03 15:27:40 +01001830 self.assertEqual(len(sessions), 3)
1831 for session in sessions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001832 self.assertFalse(session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1833 self.assertEqual(str(session.inside_ip_address), self.pg5.remote_ip4)
1834 self.assertEqual(session.outside_ip_address, addresses[0].ip_address)
Filip Varga18f1e412020-12-03 15:27:40 +01001835 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1836 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1837 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1838 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1839 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1840 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1841 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1842 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1843 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1844
1845 # in2out 3rd interface
1846 pkts = self.create_stream_in(self.pg6, self.pg3)
1847 self.pg6.add_stream(pkts)
1848 self.pg_enable_capture(self.pg_interfaces)
1849 self.pg_start()
1850 capture = self.pg3.get_capture(len(pkts))
1851 self.verify_capture_out(capture, static_nat_ip, True)
1852
1853 # out2in 3rd interface
1854 pkts = self.create_stream_out(self.pg3, static_nat_ip)
1855 self.pg3.add_stream(pkts)
1856 self.pg_enable_capture(self.pg_interfaces)
1857 self.pg_start()
1858 capture = self.pg6.get_capture(len(pkts))
1859 self.verify_capture_in(capture, self.pg6)
1860
1861 # general user and session dump verifications
Filip Varga0eaf4e62021-02-17 14:34:54 +01001862 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001863 self.assertGreaterEqual(len(users), 3)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001864 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001865 self.assertEqual(len(addresses), 1)
1866 for user in users:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001867 sessions = self.vapi.nat44_ei_user_session_dump(
1868 user.ip_address, user.vrf_id
1869 )
Filip Varga18f1e412020-12-03 15:27:40 +01001870 for session in sessions:
1871 self.assertEqual(user.ip_address, session.inside_ip_address)
1872 self.assertTrue(session.total_bytes > session.total_pkts > 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001873 self.assertTrue(
1874 session.protocol in [IP_PROTOS.tcp, IP_PROTOS.udp, IP_PROTOS.icmp]
1875 )
Filip Varga18f1e412020-12-03 15:27:40 +01001876
1877 # pg4 session dump
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001878 sessions = self.vapi.nat44_ei_user_session_dump(self.pg4.remote_ip4, 10)
Filip Varga18f1e412020-12-03 15:27:40 +01001879 self.assertGreaterEqual(len(sessions), 4)
1880 for session in sessions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001881 self.assertFalse(session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1882 self.assertEqual(str(session.inside_ip_address), self.pg4.remote_ip4)
1883 self.assertEqual(session.outside_ip_address, addresses[0].ip_address)
Filip Varga18f1e412020-12-03 15:27:40 +01001884
1885 # pg6 session dump
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001886 sessions = self.vapi.nat44_ei_user_session_dump(self.pg6.remote_ip4, 20)
Filip Varga18f1e412020-12-03 15:27:40 +01001887 self.assertGreaterEqual(len(sessions), 3)
1888 for session in sessions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001889 self.assertTrue(session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1890 self.assertEqual(str(session.inside_ip_address), self.pg6.remote_ip4)
1891 self.assertEqual(str(session.outside_ip_address), static_nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001892 self.assertTrue(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001893 session.inside_port
1894 in [self.tcp_port_in, self.udp_port_in, self.icmp_id_in]
1895 )
Filip Varga18f1e412020-12-03 15:27:40 +01001896
1897 def test_hairpinning(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001898 """NAT44EI hairpinning - 1:1 NAPT"""
Filip Varga18f1e412020-12-03 15:27:40 +01001899
1900 host = self.pg0.remote_hosts[0]
1901 server = self.pg0.remote_hosts[1]
1902 host_in_port = 1234
1903 host_out_port = 0
1904 server_in_port = 5678
1905 server_out_port = 8765
1906
1907 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001908 flags = self.config_flags.NAT44_EI_IF_INSIDE
1909 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001910 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1911 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01001912 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001913 sw_if_index=self.pg1.sw_if_index, is_add=1
1914 )
Filip Varga18f1e412020-12-03 15:27:40 +01001915
1916 # add static mapping for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001917 self.nat44_add_static_mapping(
1918 server.ip4,
1919 self.nat_addr,
1920 server_in_port,
1921 server_out_port,
1922 proto=IP_PROTOS.tcp,
1923 )
Filip Varga18f1e412020-12-03 15:27:40 +01001924
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001925 cnt = self.statistics["/nat44-ei/hairpinning"]
Filip Varga18f1e412020-12-03 15:27:40 +01001926 # send packet from host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001927 p = (
1928 Ether(src=host.mac, dst=self.pg0.local_mac)
1929 / IP(src=host.ip4, dst=self.nat_addr)
1930 / TCP(sport=host_in_port, dport=server_out_port)
1931 )
Filip Varga18f1e412020-12-03 15:27:40 +01001932 self.pg0.add_stream(p)
1933 self.pg_enable_capture(self.pg_interfaces)
1934 self.pg_start()
1935 capture = self.pg0.get_capture(1)
1936 p = capture[0]
1937 try:
1938 ip = p[IP]
1939 tcp = p[TCP]
1940 self.assertEqual(ip.src, self.nat_addr)
1941 self.assertEqual(ip.dst, server.ip4)
1942 self.assertNotEqual(tcp.sport, host_in_port)
1943 self.assertEqual(tcp.dport, server_in_port)
1944 self.assert_packet_checksums_valid(p)
1945 host_out_port = tcp.sport
1946 except:
1947 self.logger.error(ppp("Unexpected or invalid packet:", p))
1948 raise
1949
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001950 after = self.statistics["/nat44-ei/hairpinning"]
Filip Varga18f1e412020-12-03 15:27:40 +01001951 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001952 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01001953
1954 # send reply from server to host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001955 p = (
1956 Ether(src=server.mac, dst=self.pg0.local_mac)
1957 / IP(src=server.ip4, dst=self.nat_addr)
1958 / TCP(sport=server_in_port, dport=host_out_port)
1959 )
Filip Varga18f1e412020-12-03 15:27:40 +01001960 self.pg0.add_stream(p)
1961 self.pg_enable_capture(self.pg_interfaces)
1962 self.pg_start()
1963 capture = self.pg0.get_capture(1)
1964 p = capture[0]
1965 try:
1966 ip = p[IP]
1967 tcp = p[TCP]
1968 self.assertEqual(ip.src, self.nat_addr)
1969 self.assertEqual(ip.dst, host.ip4)
1970 self.assertEqual(tcp.sport, server_out_port)
1971 self.assertEqual(tcp.dport, host_in_port)
1972 self.assert_packet_checksums_valid(p)
1973 except:
1974 self.logger.error(ppp("Unexpected or invalid packet:", p))
1975 raise
1976
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001977 after = self.statistics["/nat44-ei/hairpinning"]
Filip Varga18f1e412020-12-03 15:27:40 +01001978 if_idx = self.pg0.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001979 self.assertEqual(
1980 after[:, if_idx].sum() - cnt[:, if_idx].sum(),
1981 2 + (1 if self.vpp_worker_count > 0 else 0),
1982 )
Filip Varga18f1e412020-12-03 15:27:40 +01001983
1984 def test_hairpinning2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001985 """NAT44EI hairpinning - 1:1 NAT"""
Filip Varga18f1e412020-12-03 15:27:40 +01001986
1987 server1_nat_ip = "10.0.0.10"
1988 server2_nat_ip = "10.0.0.11"
1989 host = self.pg0.remote_hosts[0]
1990 server1 = self.pg0.remote_hosts[1]
1991 server2 = self.pg0.remote_hosts[2]
1992 server_tcp_port = 22
1993 server_udp_port = 20
1994
1995 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001996 flags = self.config_flags.NAT44_EI_IF_INSIDE
1997 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001998 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1999 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002000 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002001 sw_if_index=self.pg1.sw_if_index, is_add=1
2002 )
Filip Varga18f1e412020-12-03 15:27:40 +01002003
2004 # add static mapping for servers
2005 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2006 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2007
2008 # host to server1
2009 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002010 p = (
2011 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2012 / IP(src=host.ip4, dst=server1_nat_ip)
2013 / TCP(sport=self.tcp_port_in, dport=server_tcp_port)
2014 )
Filip Varga18f1e412020-12-03 15:27:40 +01002015 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002016 p = (
2017 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2018 / IP(src=host.ip4, dst=server1_nat_ip)
2019 / UDP(sport=self.udp_port_in, dport=server_udp_port)
2020 )
Filip Varga18f1e412020-12-03 15:27:40 +01002021 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002022 p = (
2023 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2024 / IP(src=host.ip4, dst=server1_nat_ip)
2025 / ICMP(id=self.icmp_id_in, type="echo-request")
2026 )
Filip Varga18f1e412020-12-03 15:27:40 +01002027 pkts.append(p)
2028 self.pg0.add_stream(pkts)
2029 self.pg_enable_capture(self.pg_interfaces)
2030 self.pg_start()
2031 capture = self.pg0.get_capture(len(pkts))
2032 for packet in capture:
2033 try:
2034 self.assertEqual(packet[IP].src, self.nat_addr)
2035 self.assertEqual(packet[IP].dst, server1.ip4)
2036 if packet.haslayer(TCP):
2037 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2038 self.assertEqual(packet[TCP].dport, server_tcp_port)
2039 self.tcp_port_out = packet[TCP].sport
2040 self.assert_packet_checksums_valid(packet)
2041 elif packet.haslayer(UDP):
2042 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2043 self.assertEqual(packet[UDP].dport, server_udp_port)
2044 self.udp_port_out = packet[UDP].sport
2045 else:
2046 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2047 self.icmp_id_out = packet[ICMP].id
2048 except:
2049 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2050 raise
2051
2052 # server1 to host
2053 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002054 p = (
2055 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2056 / IP(src=server1.ip4, dst=self.nat_addr)
2057 / TCP(sport=server_tcp_port, dport=self.tcp_port_out)
2058 )
Filip Varga18f1e412020-12-03 15:27:40 +01002059 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002060 p = (
2061 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2062 / IP(src=server1.ip4, dst=self.nat_addr)
2063 / UDP(sport=server_udp_port, dport=self.udp_port_out)
2064 )
Filip Varga18f1e412020-12-03 15:27:40 +01002065 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002066 p = (
2067 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2068 / IP(src=server1.ip4, dst=self.nat_addr)
2069 / ICMP(id=self.icmp_id_out, type="echo-reply")
2070 )
Filip Varga18f1e412020-12-03 15:27:40 +01002071 pkts.append(p)
2072 self.pg0.add_stream(pkts)
2073 self.pg_enable_capture(self.pg_interfaces)
2074 self.pg_start()
2075 capture = self.pg0.get_capture(len(pkts))
2076 for packet in capture:
2077 try:
2078 self.assertEqual(packet[IP].src, server1_nat_ip)
2079 self.assertEqual(packet[IP].dst, host.ip4)
2080 if packet.haslayer(TCP):
2081 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2082 self.assertEqual(packet[TCP].sport, server_tcp_port)
2083 self.assert_packet_checksums_valid(packet)
2084 elif packet.haslayer(UDP):
2085 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2086 self.assertEqual(packet[UDP].sport, server_udp_port)
2087 else:
2088 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2089 except:
2090 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2091 raise
2092
2093 # server2 to server1
2094 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002095 p = (
2096 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2097 / IP(src=server2.ip4, dst=server1_nat_ip)
2098 / TCP(sport=self.tcp_port_in, dport=server_tcp_port)
2099 )
Filip Varga18f1e412020-12-03 15:27:40 +01002100 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002101 p = (
2102 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2103 / IP(src=server2.ip4, dst=server1_nat_ip)
2104 / UDP(sport=self.udp_port_in, dport=server_udp_port)
2105 )
Filip Varga18f1e412020-12-03 15:27:40 +01002106 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002107 p = (
2108 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2109 / IP(src=server2.ip4, dst=server1_nat_ip)
2110 / ICMP(id=self.icmp_id_in, type="echo-request")
2111 )
Filip Varga18f1e412020-12-03 15:27:40 +01002112 pkts.append(p)
2113 self.pg0.add_stream(pkts)
2114 self.pg_enable_capture(self.pg_interfaces)
2115 self.pg_start()
2116 capture = self.pg0.get_capture(len(pkts))
2117 for packet in capture:
2118 try:
2119 self.assertEqual(packet[IP].src, server2_nat_ip)
2120 self.assertEqual(packet[IP].dst, server1.ip4)
2121 if packet.haslayer(TCP):
2122 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2123 self.assertEqual(packet[TCP].dport, server_tcp_port)
2124 self.tcp_port_out = packet[TCP].sport
2125 self.assert_packet_checksums_valid(packet)
2126 elif packet.haslayer(UDP):
2127 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2128 self.assertEqual(packet[UDP].dport, server_udp_port)
2129 self.udp_port_out = packet[UDP].sport
2130 else:
2131 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2132 self.icmp_id_out = packet[ICMP].id
2133 except:
2134 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2135 raise
2136
2137 # server1 to server2
2138 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002139 p = (
2140 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2141 / IP(src=server1.ip4, dst=server2_nat_ip)
2142 / TCP(sport=server_tcp_port, dport=self.tcp_port_out)
2143 )
Filip Varga18f1e412020-12-03 15:27:40 +01002144 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002145 p = (
2146 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2147 / IP(src=server1.ip4, dst=server2_nat_ip)
2148 / UDP(sport=server_udp_port, dport=self.udp_port_out)
2149 )
Filip Varga18f1e412020-12-03 15:27:40 +01002150 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002151 p = (
2152 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2153 / IP(src=server1.ip4, dst=server2_nat_ip)
2154 / ICMP(id=self.icmp_id_out, type="echo-reply")
2155 )
Filip Varga18f1e412020-12-03 15:27:40 +01002156 pkts.append(p)
2157 self.pg0.add_stream(pkts)
2158 self.pg_enable_capture(self.pg_interfaces)
2159 self.pg_start()
2160 capture = self.pg0.get_capture(len(pkts))
2161 for packet in capture:
2162 try:
2163 self.assertEqual(packet[IP].src, server1_nat_ip)
2164 self.assertEqual(packet[IP].dst, server2.ip4)
2165 if packet.haslayer(TCP):
2166 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2167 self.assertEqual(packet[TCP].sport, server_tcp_port)
2168 self.assert_packet_checksums_valid(packet)
2169 elif packet.haslayer(UDP):
2170 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2171 self.assertEqual(packet[UDP].sport, server_udp_port)
2172 else:
2173 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2174 except:
2175 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2176 raise
2177
2178 def test_hairpinning_avoid_inf_loop(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002179 """NAT44EI hairpinning - 1:1 NAPT avoid infinite loop"""
Filip Varga18f1e412020-12-03 15:27:40 +01002180
2181 host = self.pg0.remote_hosts[0]
2182 server = self.pg0.remote_hosts[1]
2183 host_in_port = 1234
2184 host_out_port = 0
2185 server_in_port = 5678
2186 server_out_port = 8765
2187
2188 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002189 flags = self.config_flags.NAT44_EI_IF_INSIDE
2190 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002191 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2192 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002193 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002194 sw_if_index=self.pg1.sw_if_index, is_add=1
2195 )
Filip Varga18f1e412020-12-03 15:27:40 +01002196
2197 # add static mapping for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002198 self.nat44_add_static_mapping(
2199 server.ip4,
2200 self.nat_addr,
2201 server_in_port,
2202 server_out_port,
2203 proto=IP_PROTOS.tcp,
2204 )
Filip Varga18f1e412020-12-03 15:27:40 +01002205
2206 # add another static mapping that maps pg0.local_ip4 address to itself
2207 self.nat44_add_static_mapping(self.pg0.local_ip4, self.pg0.local_ip4)
2208
2209 # send packet from host to VPP (the packet should get dropped)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002210 p = (
2211 Ether(src=host.mac, dst=self.pg0.local_mac)
2212 / IP(src=host.ip4, dst=self.pg0.local_ip4)
2213 / TCP(sport=host_in_port, dport=server_out_port)
2214 )
Filip Varga18f1e412020-12-03 15:27:40 +01002215 self.pg0.add_stream(p)
2216 self.pg_enable_capture(self.pg_interfaces)
2217 self.pg_start()
2218 # Here VPP used to crash due to an infinite loop
2219
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002220 cnt = self.statistics["/nat44-ei/hairpinning"]
Filip Varga18f1e412020-12-03 15:27:40 +01002221 # send packet from host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002222 p = (
2223 Ether(src=host.mac, dst=self.pg0.local_mac)
2224 / IP(src=host.ip4, dst=self.nat_addr)
2225 / TCP(sport=host_in_port, dport=server_out_port)
2226 )
Filip Varga18f1e412020-12-03 15:27:40 +01002227 self.pg0.add_stream(p)
2228 self.pg_enable_capture(self.pg_interfaces)
2229 self.pg_start()
2230 capture = self.pg0.get_capture(1)
2231 p = capture[0]
2232 try:
2233 ip = p[IP]
2234 tcp = p[TCP]
2235 self.assertEqual(ip.src, self.nat_addr)
2236 self.assertEqual(ip.dst, server.ip4)
2237 self.assertNotEqual(tcp.sport, host_in_port)
2238 self.assertEqual(tcp.dport, server_in_port)
2239 self.assert_packet_checksums_valid(p)
2240 host_out_port = tcp.sport
2241 except:
2242 self.logger.error(ppp("Unexpected or invalid packet:", p))
2243 raise
2244
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002245 after = self.statistics["/nat44-ei/hairpinning"]
Filip Varga18f1e412020-12-03 15:27:40 +01002246 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002247 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01002248
2249 # send reply from server to host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002250 p = (
2251 Ether(src=server.mac, dst=self.pg0.local_mac)
2252 / IP(src=server.ip4, dst=self.nat_addr)
2253 / TCP(sport=server_in_port, dport=host_out_port)
2254 )
Filip Varga18f1e412020-12-03 15:27:40 +01002255 self.pg0.add_stream(p)
2256 self.pg_enable_capture(self.pg_interfaces)
2257 self.pg_start()
2258 capture = self.pg0.get_capture(1)
2259 p = capture[0]
2260 try:
2261 ip = p[IP]
2262 tcp = p[TCP]
2263 self.assertEqual(ip.src, self.nat_addr)
2264 self.assertEqual(ip.dst, host.ip4)
2265 self.assertEqual(tcp.sport, server_out_port)
2266 self.assertEqual(tcp.dport, host_in_port)
2267 self.assert_packet_checksums_valid(p)
2268 except:
2269 self.logger.error(ppp("Unexpected or invalid packet:", p))
2270 raise
2271
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002272 after = self.statistics["/nat44-ei/hairpinning"]
Filip Varga18f1e412020-12-03 15:27:40 +01002273 if_idx = self.pg0.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002274 self.assertEqual(
2275 after[:, if_idx].sum() - cnt[:, if_idx].sum(),
2276 2 + (1 if self.vpp_worker_count > 0 else 0),
2277 )
Filip Varga18f1e412020-12-03 15:27:40 +01002278
2279 def test_interface_addr(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002280 """NAT44EI acquire addresses from interface"""
Filip Varga0eaf4e62021-02-17 14:34:54 +01002281 self.vapi.nat44_ei_add_del_interface_addr(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002282 is_add=1, sw_if_index=self.pg7.sw_if_index
2283 )
Filip Varga18f1e412020-12-03 15:27:40 +01002284
2285 # no address in NAT pool
Filip Varga0eaf4e62021-02-17 14:34:54 +01002286 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002287 self.assertEqual(0, len(addresses))
2288
2289 # configure interface address and check NAT address pool
2290 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002291 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002292 self.assertEqual(1, len(addresses))
2293 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2294
2295 # remove interface address and check NAT address pool
2296 self.pg7.unconfig_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002297 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002298 self.assertEqual(0, len(addresses))
2299
2300 def test_interface_addr_static_mapping(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002301 """NAT44EI Static mapping with addresses from interface"""
Filip Varga18f1e412020-12-03 15:27:40 +01002302 tag = "testTAG"
2303
Filip Varga0eaf4e62021-02-17 14:34:54 +01002304 self.vapi.nat44_ei_add_del_interface_addr(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002305 is_add=1, sw_if_index=self.pg7.sw_if_index
2306 )
Filip Varga18f1e412020-12-03 15:27:40 +01002307 self.nat44_add_static_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002308 "1.2.3.4", external_sw_if_index=self.pg7.sw_if_index, tag=tag
2309 )
Filip Varga18f1e412020-12-03 15:27:40 +01002310
2311 # static mappings with external interface
Filip Varga0eaf4e62021-02-17 14:34:54 +01002312 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002313 self.assertEqual(1, len(static_mappings))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002314 self.assertEqual(self.pg7.sw_if_index, static_mappings[0].external_sw_if_index)
Filip Varga18f1e412020-12-03 15:27:40 +01002315 self.assertEqual(static_mappings[0].tag, tag)
2316
2317 # configure interface address and check static mappings
2318 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002319 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002320 self.assertEqual(2, len(static_mappings))
2321 resolved = False
2322 for sm in static_mappings:
2323 if sm.external_sw_if_index == 0xFFFFFFFF:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002324 self.assertEqual(str(sm.external_ip_address), self.pg7.local_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01002325 self.assertEqual(sm.tag, tag)
2326 resolved = True
2327 self.assertTrue(resolved)
2328
2329 # remove interface address and check static mappings
2330 self.pg7.unconfig_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002331 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002332 self.assertEqual(1, len(static_mappings))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002333 self.assertEqual(self.pg7.sw_if_index, static_mappings[0].external_sw_if_index)
Filip Varga18f1e412020-12-03 15:27:40 +01002334 self.assertEqual(static_mappings[0].tag, tag)
2335
2336 # configure interface address again and check static mappings
2337 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002338 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002339 self.assertEqual(2, len(static_mappings))
2340 resolved = False
2341 for sm in static_mappings:
2342 if sm.external_sw_if_index == 0xFFFFFFFF:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002343 self.assertEqual(str(sm.external_ip_address), self.pg7.local_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01002344 self.assertEqual(sm.tag, tag)
2345 resolved = True
2346 self.assertTrue(resolved)
2347
2348 # remove static mapping
2349 self.nat44_add_static_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002350 "1.2.3.4", external_sw_if_index=self.pg7.sw_if_index, tag=tag, is_add=0
2351 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002352 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002353 self.assertEqual(0, len(static_mappings))
2354
2355 def test_interface_addr_identity_nat(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002356 """NAT44EI Identity NAT with addresses from interface"""
Filip Varga18f1e412020-12-03 15:27:40 +01002357
2358 port = 53053
Filip Varga0eaf4e62021-02-17 14:34:54 +01002359 self.vapi.nat44_ei_add_del_interface_addr(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002360 is_add=1, sw_if_index=self.pg7.sw_if_index
2361 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002362 self.vapi.nat44_ei_add_del_identity_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002363 ip_address=b"0",
Filip Varga18f1e412020-12-03 15:27:40 +01002364 sw_if_index=self.pg7.sw_if_index,
2365 port=port,
2366 protocol=IP_PROTOS.tcp,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002367 is_add=1,
2368 )
Filip Varga18f1e412020-12-03 15:27:40 +01002369
2370 # identity mappings with external interface
Filip Varga0eaf4e62021-02-17 14:34:54 +01002371 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002372 self.assertEqual(1, len(identity_mappings))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002373 self.assertEqual(self.pg7.sw_if_index, identity_mappings[0].sw_if_index)
Filip Varga18f1e412020-12-03 15:27:40 +01002374
2375 # configure interface address and check identity mappings
2376 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002377 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002378 resolved = False
2379 self.assertEqual(2, len(identity_mappings))
2380 for sm in identity_mappings:
2381 if sm.sw_if_index == 0xFFFFFFFF:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002382 self.assertEqual(
2383 str(identity_mappings[0].ip_address), self.pg7.local_ip4
2384 )
Filip Varga18f1e412020-12-03 15:27:40 +01002385 self.assertEqual(port, identity_mappings[0].port)
2386 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2387 resolved = True
2388 self.assertTrue(resolved)
2389
2390 # remove interface address and check identity mappings
2391 self.pg7.unconfig_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002392 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002393 self.assertEqual(1, len(identity_mappings))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002394 self.assertEqual(self.pg7.sw_if_index, identity_mappings[0].sw_if_index)
Filip Varga18f1e412020-12-03 15:27:40 +01002395
2396 def test_ipfix_nat44_sess(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002397 """NAT44EI IPFIX logging NAT44EI session created/deleted"""
Filip Varga18f1e412020-12-03 15:27:40 +01002398 self.ipfix_domain_id = 10
2399 self.ipfix_src_port = 20202
2400 collector_port = 30303
2401 bind_layers(UDP, IPFIX, dport=30303)
2402 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002403 flags = self.config_flags.NAT44_EI_IF_INSIDE
2404 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002405 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2406 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002407 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002408 sw_if_index=self.pg1.sw_if_index, is_add=1
2409 )
2410 self.vapi.set_ipfix_exporter(
2411 collector_address=self.pg3.remote_ip4,
2412 src_address=self.pg3.local_ip4,
2413 path_mtu=512,
2414 template_interval=10,
2415 collector_port=collector_port,
2416 )
2417 self.vapi.nat44_ei_ipfix_enable_disable(
2418 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port, enable=1
2419 )
Filip Varga18f1e412020-12-03 15:27:40 +01002420
2421 pkts = self.create_stream_in(self.pg0, self.pg1)
2422 self.pg0.add_stream(pkts)
2423 self.pg_enable_capture(self.pg_interfaces)
2424 self.pg_start()
2425 capture = self.pg1.get_capture(len(pkts))
2426 self.verify_capture_out(capture)
2427 self.nat44_add_address(self.nat_addr, is_add=0)
2428 self.vapi.ipfix_flush()
2429 capture = self.pg3.get_capture(7)
2430 ipfix = IPFIXDecoder()
2431 # first load template
2432 for p in capture:
2433 self.assertTrue(p.haslayer(IPFIX))
2434 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2435 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2436 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2437 self.assertEqual(p[UDP].dport, collector_port)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002438 self.assertEqual(p[IPFIX].observationDomainID, self.ipfix_domain_id)
Filip Varga18f1e412020-12-03 15:27:40 +01002439 if p.haslayer(Template):
2440 ipfix.add_template(p.getlayer(Template))
2441 # verify events in data set
2442 for p in capture:
2443 if p.haslayer(Data):
2444 data = ipfix.decode_data_set(p.getlayer(Set))
2445 self.verify_ipfix_nat44_ses(data)
2446
2447 def test_ipfix_addr_exhausted(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002448 """NAT44EI IPFIX logging NAT addresses exhausted"""
Filip Varga0eaf4e62021-02-17 14:34:54 +01002449 flags = self.config_flags.NAT44_EI_IF_INSIDE
2450 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002451 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2452 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002453 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002454 sw_if_index=self.pg1.sw_if_index, is_add=1
2455 )
2456 self.vapi.set_ipfix_exporter(
2457 collector_address=self.pg3.remote_ip4,
2458 src_address=self.pg3.local_ip4,
2459 path_mtu=512,
2460 template_interval=10,
2461 )
2462 self.vapi.nat44_ei_ipfix_enable_disable(
2463 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port, enable=1
2464 )
Filip Varga18f1e412020-12-03 15:27:40 +01002465
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002466 p = (
2467 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2468 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2469 / TCP(sport=3025)
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +05002470 ) * 3
Filip Varga18f1e412020-12-03 15:27:40 +01002471 self.pg0.add_stream(p)
2472 self.pg_enable_capture(self.pg_interfaces)
2473 self.pg_start()
2474 self.pg1.assert_nothing_captured()
Filip Varga18f1e412020-12-03 15:27:40 +01002475 self.vapi.ipfix_flush()
2476 capture = self.pg3.get_capture(7)
2477 ipfix = IPFIXDecoder()
2478 # first load template
2479 for p in capture:
2480 self.assertTrue(p.haslayer(IPFIX))
2481 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2482 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2483 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2484 self.assertEqual(p[UDP].dport, 4739)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002485 self.assertEqual(p[IPFIX].observationDomainID, self.ipfix_domain_id)
Filip Varga18f1e412020-12-03 15:27:40 +01002486 if p.haslayer(Template):
2487 ipfix.add_template(p.getlayer(Template))
2488 # verify events in data set
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +05002489 event_count = 0
Filip Varga18f1e412020-12-03 15:27:40 +01002490 for p in capture:
2491 if p.haslayer(Data):
2492 data = ipfix.decode_data_set(p.getlayer(Set))
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +05002493 event_count += self.verify_ipfix_addr_exhausted(data)
2494 self.assertEqual(event_count, 1)
Filip Varga18f1e412020-12-03 15:27:40 +01002495
2496 def test_ipfix_max_sessions(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002497 """NAT44EI IPFIX logging maximum session entries exceeded"""
Filip Varga18f1e412020-12-03 15:27:40 +01002498 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002499 flags = self.config_flags.NAT44_EI_IF_INSIDE
2500 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002501 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2502 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002503 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002504 sw_if_index=self.pg1.sw_if_index, is_add=1
2505 )
Filip Varga18f1e412020-12-03 15:27:40 +01002506
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002507 max_sessions_per_thread = self.max_translations
2508 max_sessions = max(1, self.vpp_worker_count) * max_sessions_per_thread
Filip Varga18f1e412020-12-03 15:27:40 +01002509
2510 pkts = []
2511 for i in range(0, max_sessions):
2512 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002513 p = (
2514 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2515 / IP(src=src, dst=self.pg1.remote_ip4)
2516 / TCP(sport=1025)
2517 )
Filip Varga18f1e412020-12-03 15:27:40 +01002518 pkts.append(p)
2519 self.pg0.add_stream(pkts)
2520 self.pg_enable_capture(self.pg_interfaces)
2521 self.pg_start()
2522
2523 self.pg1.get_capture(max_sessions)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002524 self.vapi.set_ipfix_exporter(
2525 collector_address=self.pg3.remote_ip4,
2526 src_address=self.pg3.local_ip4,
2527 path_mtu=512,
2528 template_interval=10,
2529 )
2530 self.vapi.nat44_ei_ipfix_enable_disable(
2531 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port, enable=1
2532 )
Filip Varga18f1e412020-12-03 15:27:40 +01002533
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002534 p = (
2535 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2536 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2537 / TCP(sport=1025)
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +05002538 ) * 3
Filip Varga18f1e412020-12-03 15:27:40 +01002539 self.pg0.add_stream(p)
2540 self.pg_enable_capture(self.pg_interfaces)
2541 self.pg_start()
2542 self.pg1.assert_nothing_captured()
Filip Varga18f1e412020-12-03 15:27:40 +01002543 self.vapi.ipfix_flush()
2544 capture = self.pg3.get_capture(7)
2545 ipfix = IPFIXDecoder()
2546 # first load template
2547 for p in capture:
2548 self.assertTrue(p.haslayer(IPFIX))
2549 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2550 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2551 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2552 self.assertEqual(p[UDP].dport, 4739)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002553 self.assertEqual(p[IPFIX].observationDomainID, self.ipfix_domain_id)
Filip Varga18f1e412020-12-03 15:27:40 +01002554 if p.haslayer(Template):
2555 ipfix.add_template(p.getlayer(Template))
2556 # verify events in data set
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +05002557 event_count = 0
Filip Varga18f1e412020-12-03 15:27:40 +01002558 for p in capture:
2559 if p.haslayer(Data):
2560 data = ipfix.decode_data_set(p.getlayer(Set))
Vladislav Grishenkoda34f4a2023-09-14 22:14:38 +05002561 event_count += self.verify_ipfix_max_sessions(
2562 data, max_sessions_per_thread
2563 )
2564 self.assertEqual(event_count, 1)
Filip Varga18f1e412020-12-03 15:27:40 +01002565
2566 def test_syslog_apmap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002567 """NAT44EI syslog address and port mapping creation and deletion"""
2568 self.vapi.syslog_set_filter(self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
Filip Varga18f1e412020-12-03 15:27:40 +01002569 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2570 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002571 flags = self.config_flags.NAT44_EI_IF_INSIDE
2572 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002573 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2574 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002575 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002576 sw_if_index=self.pg1.sw_if_index, is_add=1
2577 )
Filip Varga18f1e412020-12-03 15:27:40 +01002578
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002579 p = (
2580 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2581 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2582 / TCP(sport=self.tcp_port_in, dport=20)
2583 )
Filip Varga18f1e412020-12-03 15:27:40 +01002584 self.pg0.add_stream(p)
2585 self.pg_enable_capture(self.pg_interfaces)
2586 self.pg_start()
2587 capture = self.pg1.get_capture(1)
2588 self.tcp_port_out = capture[0][TCP].sport
2589 capture = self.pg3.get_capture(1)
2590 self.verify_syslog_apmap(capture[0][Raw].load)
2591
2592 self.pg_enable_capture(self.pg_interfaces)
2593 self.pg_start()
2594 self.nat44_add_address(self.nat_addr, is_add=0)
2595 capture = self.pg3.get_capture(1)
2596 self.verify_syslog_apmap(capture[0][Raw].load, False)
2597
2598 def test_pool_addr_fib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002599 """NAT44EI add pool addresses to FIB"""
2600 static_addr = "10.0.0.10"
Filip Varga18f1e412020-12-03 15:27:40 +01002601 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002602 flags = self.config_flags.NAT44_EI_IF_INSIDE
2603 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002604 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2605 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002606 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002607 sw_if_index=self.pg1.sw_if_index, is_add=1
2608 )
Filip Varga18f1e412020-12-03 15:27:40 +01002609 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2610
2611 # NAT44EI address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002612 p = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
2613 op=ARP.who_has,
2614 pdst=self.nat_addr,
2615 psrc=self.pg1.remote_ip4,
2616 hwsrc=self.pg1.remote_mac,
2617 )
Filip Varga18f1e412020-12-03 15:27:40 +01002618 self.pg1.add_stream(p)
2619 self.pg_enable_capture(self.pg_interfaces)
2620 self.pg_start()
2621 capture = self.pg1.get_capture(1)
2622 self.assertTrue(capture[0].haslayer(ARP))
2623 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2624
2625 # 1:1 NAT address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002626 p = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
2627 op=ARP.who_has,
2628 pdst=static_addr,
2629 psrc=self.pg1.remote_ip4,
2630 hwsrc=self.pg1.remote_mac,
2631 )
Filip Varga18f1e412020-12-03 15:27:40 +01002632 self.pg1.add_stream(p)
2633 self.pg_enable_capture(self.pg_interfaces)
2634 self.pg_start()
2635 capture = self.pg1.get_capture(1)
2636 self.assertTrue(capture[0].haslayer(ARP))
2637 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2638
2639 # send ARP to non-NAT44EI interface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002640 p = Ether(src=self.pg2.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
2641 op=ARP.who_has,
2642 pdst=self.nat_addr,
2643 psrc=self.pg2.remote_ip4,
2644 hwsrc=self.pg2.remote_mac,
2645 )
Filip Varga18f1e412020-12-03 15:27:40 +01002646 self.pg2.add_stream(p)
2647 self.pg_enable_capture(self.pg_interfaces)
2648 self.pg_start()
2649 self.pg1.assert_nothing_captured()
2650
2651 # remove addresses and verify
2652 self.nat44_add_address(self.nat_addr, is_add=0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002653 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr, is_add=0)
Filip Varga18f1e412020-12-03 15:27:40 +01002654
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002655 p = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
2656 op=ARP.who_has,
2657 pdst=self.nat_addr,
2658 psrc=self.pg1.remote_ip4,
2659 hwsrc=self.pg1.remote_mac,
2660 )
Filip Varga18f1e412020-12-03 15:27:40 +01002661 self.pg1.add_stream(p)
2662 self.pg_enable_capture(self.pg_interfaces)
2663 self.pg_start()
2664 self.pg1.assert_nothing_captured()
2665
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002666 p = Ether(src=self.pg1.remote_mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
2667 op=ARP.who_has,
2668 pdst=static_addr,
2669 psrc=self.pg1.remote_ip4,
2670 hwsrc=self.pg1.remote_mac,
2671 )
Filip Varga18f1e412020-12-03 15:27:40 +01002672 self.pg1.add_stream(p)
2673 self.pg_enable_capture(self.pg_interfaces)
2674 self.pg_start()
2675 self.pg1.assert_nothing_captured()
2676
2677 def test_vrf_mode(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002678 """NAT44EI tenant VRF aware address pool mode"""
Filip Varga18f1e412020-12-03 15:27:40 +01002679
2680 vrf_id1 = 1
2681 vrf_id2 = 2
2682 nat_ip1 = "10.0.0.10"
2683 nat_ip2 = "10.0.0.11"
2684
2685 self.pg0.unconfig_ip4()
2686 self.pg1.unconfig_ip4()
Benoît Ganneff570d32024-04-16 09:36:05 +02002687 self.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": vrf_id1})
2688 self.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": vrf_id2})
Filip Varga18f1e412020-12-03 15:27:40 +01002689 self.pg0.set_table_ip4(vrf_id1)
2690 self.pg1.set_table_ip4(vrf_id2)
2691 self.pg0.config_ip4()
2692 self.pg1.config_ip4()
2693 self.pg0.resolve_arp()
2694 self.pg1.resolve_arp()
2695
2696 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2697 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002698 flags = self.config_flags.NAT44_EI_IF_INSIDE
2699 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002700 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2701 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002702 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002703 sw_if_index=self.pg1.sw_if_index, flags=flags, is_add=1
2704 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002705 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002706 sw_if_index=self.pg2.sw_if_index, is_add=1
2707 )
Filip Varga18f1e412020-12-03 15:27:40 +01002708
2709 try:
2710 # first VRF
2711 pkts = self.create_stream_in(self.pg0, self.pg2)
2712 self.pg0.add_stream(pkts)
2713 self.pg_enable_capture(self.pg_interfaces)
2714 self.pg_start()
2715 capture = self.pg2.get_capture(len(pkts))
2716 self.verify_capture_out(capture, nat_ip1)
2717
2718 # second VRF
2719 pkts = self.create_stream_in(self.pg1, self.pg2)
2720 self.pg1.add_stream(pkts)
2721 self.pg_enable_capture(self.pg_interfaces)
2722 self.pg_start()
2723 capture = self.pg2.get_capture(len(pkts))
2724 self.verify_capture_out(capture, nat_ip2)
2725
2726 finally:
2727 self.pg0.unconfig_ip4()
2728 self.pg1.unconfig_ip4()
2729 self.pg0.set_table_ip4(0)
2730 self.pg1.set_table_ip4(0)
2731 self.pg0.config_ip4()
2732 self.pg1.config_ip4()
2733 self.pg0.resolve_arp()
2734 self.pg1.resolve_arp()
Benoît Ganneff570d32024-04-16 09:36:05 +02002735 self.vapi.ip_table_add_del_v2(is_add=0, table={"table_id": vrf_id1})
2736 self.vapi.ip_table_add_del_v2(is_add=0, table={"table_id": vrf_id2})
Filip Varga18f1e412020-12-03 15:27:40 +01002737
2738 def test_vrf_feature_independent(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002739 """NAT44EI tenant VRF independent address pool mode"""
Filip Varga18f1e412020-12-03 15:27:40 +01002740
2741 nat_ip1 = "10.0.0.10"
2742 nat_ip2 = "10.0.0.11"
2743
2744 self.nat44_add_address(nat_ip1)
2745 self.nat44_add_address(nat_ip2, vrf_id=99)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002746 flags = self.config_flags.NAT44_EI_IF_INSIDE
2747 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002748 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2749 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002750 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002751 sw_if_index=self.pg1.sw_if_index, flags=flags, is_add=1
2752 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002753 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002754 sw_if_index=self.pg2.sw_if_index, is_add=1
2755 )
Filip Varga18f1e412020-12-03 15:27:40 +01002756
2757 # first VRF
2758 pkts = self.create_stream_in(self.pg0, self.pg2)
2759 self.pg0.add_stream(pkts)
2760 self.pg_enable_capture(self.pg_interfaces)
2761 self.pg_start()
2762 capture = self.pg2.get_capture(len(pkts))
2763 self.verify_capture_out(capture, nat_ip1)
2764
2765 # second VRF
2766 pkts = self.create_stream_in(self.pg1, self.pg2)
2767 self.pg1.add_stream(pkts)
2768 self.pg_enable_capture(self.pg_interfaces)
2769 self.pg_start()
2770 capture = self.pg2.get_capture(len(pkts))
2771 self.verify_capture_out(capture, nat_ip1)
2772
2773 def test_dynamic_ipless_interfaces(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002774 """NAT44EI interfaces without configured IP address"""
Filip Varga18f1e412020-12-03 15:27:40 +01002775 self.create_routes_and_neigbors()
2776 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002777 flags = self.config_flags.NAT44_EI_IF_INSIDE
2778 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002779 sw_if_index=self.pg7.sw_if_index, flags=flags, is_add=1
2780 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002781 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002782 sw_if_index=self.pg8.sw_if_index, is_add=1
2783 )
Filip Varga18f1e412020-12-03 15:27:40 +01002784
2785 # in2out
2786 pkts = self.create_stream_in(self.pg7, self.pg8)
2787 self.pg7.add_stream(pkts)
2788 self.pg_enable_capture(self.pg_interfaces)
2789 self.pg_start()
2790 capture = self.pg8.get_capture(len(pkts))
2791 self.verify_capture_out(capture)
2792
2793 # out2in
2794 pkts = self.create_stream_out(self.pg8, self.nat_addr)
2795 self.pg8.add_stream(pkts)
2796 self.pg_enable_capture(self.pg_interfaces)
2797 self.pg_start()
2798 capture = self.pg7.get_capture(len(pkts))
2799 self.verify_capture_in(capture, self.pg7)
2800
2801 def test_static_ipless_interfaces(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002802 """NAT44EI interfaces without configured IP address - 1:1 NAT"""
Filip Varga18f1e412020-12-03 15:27:40 +01002803
2804 self.create_routes_and_neigbors()
2805 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002806 flags = self.config_flags.NAT44_EI_IF_INSIDE
2807 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002808 sw_if_index=self.pg7.sw_if_index, flags=flags, is_add=1
2809 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002810 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002811 sw_if_index=self.pg8.sw_if_index, is_add=1
2812 )
Filip Varga18f1e412020-12-03 15:27:40 +01002813
2814 # out2in
2815 pkts = self.create_stream_out(self.pg8)
2816 self.pg8.add_stream(pkts)
2817 self.pg_enable_capture(self.pg_interfaces)
2818 self.pg_start()
2819 capture = self.pg7.get_capture(len(pkts))
2820 self.verify_capture_in(capture, self.pg7)
2821
2822 # in2out
2823 pkts = self.create_stream_in(self.pg7, self.pg8)
2824 self.pg7.add_stream(pkts)
2825 self.pg_enable_capture(self.pg_interfaces)
2826 self.pg_start()
2827 capture = self.pg8.get_capture(len(pkts))
2828 self.verify_capture_out(capture, self.nat_addr, True)
2829
2830 def test_static_with_port_ipless_interfaces(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002831 """NAT44EI interfaces without configured IP address - 1:1 NAPT"""
Filip Varga18f1e412020-12-03 15:27:40 +01002832
2833 self.tcp_port_out = 30606
2834 self.udp_port_out = 30607
2835 self.icmp_id_out = 30608
2836
2837 self.create_routes_and_neigbors()
2838 self.nat44_add_address(self.nat_addr)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002839 self.nat44_add_static_mapping(
2840 self.pg7.remote_ip4,
2841 self.nat_addr,
2842 self.tcp_port_in,
2843 self.tcp_port_out,
2844 proto=IP_PROTOS.tcp,
2845 )
2846 self.nat44_add_static_mapping(
2847 self.pg7.remote_ip4,
2848 self.nat_addr,
2849 self.udp_port_in,
2850 self.udp_port_out,
2851 proto=IP_PROTOS.udp,
2852 )
2853 self.nat44_add_static_mapping(
2854 self.pg7.remote_ip4,
2855 self.nat_addr,
2856 self.icmp_id_in,
2857 self.icmp_id_out,
2858 proto=IP_PROTOS.icmp,
2859 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002860 flags = self.config_flags.NAT44_EI_IF_INSIDE
2861 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002862 sw_if_index=self.pg7.sw_if_index, flags=flags, is_add=1
2863 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002864 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002865 sw_if_index=self.pg8.sw_if_index, is_add=1
2866 )
Filip Varga18f1e412020-12-03 15:27:40 +01002867
2868 # out2in
2869 pkts = self.create_stream_out(self.pg8)
2870 self.pg8.add_stream(pkts)
2871 self.pg_enable_capture(self.pg_interfaces)
2872 self.pg_start()
2873 capture = self.pg7.get_capture(len(pkts))
2874 self.verify_capture_in(capture, self.pg7)
2875
2876 # in2out
2877 pkts = self.create_stream_in(self.pg7, self.pg8)
2878 self.pg7.add_stream(pkts)
2879 self.pg_enable_capture(self.pg_interfaces)
2880 self.pg_start()
2881 capture = self.pg8.get_capture(len(pkts))
2882 self.verify_capture_out(capture)
2883
2884 def test_static_unknown_proto(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002885 """NAT44EI 1:1 translate packet with unknown protocol"""
Filip Varga18f1e412020-12-03 15:27:40 +01002886 nat_ip = "10.0.0.10"
2887 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002888 flags = self.config_flags.NAT44_EI_IF_INSIDE
2889 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002890 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2891 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002892 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002893 sw_if_index=self.pg1.sw_if_index, is_add=1
2894 )
Filip Varga18f1e412020-12-03 15:27:40 +01002895
2896 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002897 p = (
2898 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2899 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2900 / GRE()
2901 / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4)
2902 / TCP(sport=1234, dport=1234)
2903 )
Filip Varga18f1e412020-12-03 15:27:40 +01002904 self.pg0.add_stream(p)
2905 self.pg_enable_capture(self.pg_interfaces)
2906 self.pg_start()
2907 p = self.pg1.get_capture(1)
2908 packet = p[0]
2909 try:
2910 self.assertEqual(packet[IP].src, nat_ip)
2911 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2912 self.assertEqual(packet.haslayer(GRE), 1)
2913 self.assert_packet_checksums_valid(packet)
2914 except:
2915 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2916 raise
2917
2918 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002919 p = (
2920 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2921 / IP(src=self.pg1.remote_ip4, dst=nat_ip)
2922 / GRE()
2923 / IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4)
2924 / TCP(sport=1234, dport=1234)
2925 )
Filip Varga18f1e412020-12-03 15:27:40 +01002926 self.pg1.add_stream(p)
2927 self.pg_enable_capture(self.pg_interfaces)
2928 self.pg_start()
2929 p = self.pg0.get_capture(1)
2930 packet = p[0]
2931 try:
2932 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2933 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2934 self.assertEqual(packet.haslayer(GRE), 1)
2935 self.assert_packet_checksums_valid(packet)
2936 except:
2937 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2938 raise
2939
2940 def test_hairpinning_static_unknown_proto(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002941 """NAT44EI 1:1 translate packet with unknown protocol - hairpinning"""
Filip Varga18f1e412020-12-03 15:27:40 +01002942
2943 host = self.pg0.remote_hosts[0]
2944 server = self.pg0.remote_hosts[1]
2945
2946 host_nat_ip = "10.0.0.10"
2947 server_nat_ip = "10.0.0.11"
2948
2949 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2950 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002951 flags = self.config_flags.NAT44_EI_IF_INSIDE
2952 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002953 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
2954 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01002955 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002956 sw_if_index=self.pg1.sw_if_index, is_add=1
2957 )
Filip Varga18f1e412020-12-03 15:27:40 +01002958
2959 # host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002960 p = (
2961 Ether(dst=self.pg0.local_mac, src=host.mac)
2962 / IP(src=host.ip4, dst=server_nat_ip)
2963 / GRE()
2964 / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4)
2965 / TCP(sport=1234, dport=1234)
2966 )
Filip Varga18f1e412020-12-03 15:27:40 +01002967 self.pg0.add_stream(p)
2968 self.pg_enable_capture(self.pg_interfaces)
2969 self.pg_start()
2970 p = self.pg0.get_capture(1)
2971 packet = p[0]
2972 try:
2973 self.assertEqual(packet[IP].src, host_nat_ip)
2974 self.assertEqual(packet[IP].dst, server.ip4)
2975 self.assertEqual(packet.haslayer(GRE), 1)
2976 self.assert_packet_checksums_valid(packet)
2977 except:
2978 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2979 raise
2980
2981 # server to host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002982 p = (
2983 Ether(dst=self.pg0.local_mac, src=server.mac)
2984 / IP(src=server.ip4, dst=host_nat_ip)
2985 / GRE()
2986 / IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4)
2987 / TCP(sport=1234, dport=1234)
2988 )
Filip Varga18f1e412020-12-03 15:27:40 +01002989 self.pg0.add_stream(p)
2990 self.pg_enable_capture(self.pg_interfaces)
2991 self.pg_start()
2992 p = self.pg0.get_capture(1)
2993 packet = p[0]
2994 try:
2995 self.assertEqual(packet[IP].src, server_nat_ip)
2996 self.assertEqual(packet[IP].dst, host.ip4)
2997 self.assertEqual(packet.haslayer(GRE), 1)
2998 self.assert_packet_checksums_valid(packet)
2999 except:
3000 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3001 raise
3002
3003 def test_output_feature(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003004 """NAT44EI output feature (in2out postrouting)"""
Filip Varga18f1e412020-12-03 15:27:40 +01003005 self.nat44_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02003006 self.vapi.nat44_ei_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003007 sw_if_index=self.pg3.sw_if_index, is_add=1
3008 )
Filip Varga18f1e412020-12-03 15:27:40 +01003009
3010 # in2out
3011 pkts = self.create_stream_in(self.pg0, self.pg3)
3012 self.pg0.add_stream(pkts)
3013 self.pg_enable_capture(self.pg_interfaces)
3014 self.pg_start()
3015 capture = self.pg3.get_capture(len(pkts))
3016 self.verify_capture_out(capture)
3017
3018 # out2in
3019 pkts = self.create_stream_out(self.pg3)
3020 self.pg3.add_stream(pkts)
3021 self.pg_enable_capture(self.pg_interfaces)
3022 self.pg_start()
3023 capture = self.pg0.get_capture(len(pkts))
3024 self.verify_capture_in(capture, self.pg0)
3025
3026 # from non-NAT interface to NAT inside interface
3027 pkts = self.create_stream_in(self.pg2, self.pg0)
3028 self.pg2.add_stream(pkts)
3029 self.pg_enable_capture(self.pg_interfaces)
3030 self.pg_start()
3031 capture = self.pg0.get_capture(len(pkts))
3032 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3033
3034 def test_output_feature_vrf_aware(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003035 """NAT44EI output feature VRF aware (in2out postrouting)"""
Filip Varga18f1e412020-12-03 15:27:40 +01003036 nat_ip_vrf10 = "10.0.0.10"
3037 nat_ip_vrf20 = "10.0.0.20"
3038
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003039 r1 = VppIpRoute(
3040 self,
3041 self.pg3.remote_ip4,
3042 32,
3043 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
3044 table_id=10,
3045 )
3046 r2 = VppIpRoute(
3047 self,
3048 self.pg3.remote_ip4,
3049 32,
3050 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
3051 table_id=20,
3052 )
Filip Varga18f1e412020-12-03 15:27:40 +01003053 r1.add_vpp_config()
3054 r2.add_vpp_config()
3055
3056 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3057 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
Filip Varga9c25eb12021-10-21 13:00:27 +02003058 self.vapi.nat44_ei_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003059 sw_if_index=self.pg3.sw_if_index, is_add=1
3060 )
Filip Varga18f1e412020-12-03 15:27:40 +01003061
3062 # in2out VRF 10
3063 pkts = self.create_stream_in(self.pg4, self.pg3)
3064 self.pg4.add_stream(pkts)
3065 self.pg_enable_capture(self.pg_interfaces)
3066 self.pg_start()
3067 capture = self.pg3.get_capture(len(pkts))
3068 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3069
3070 # out2in VRF 10
3071 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3072 self.pg3.add_stream(pkts)
3073 self.pg_enable_capture(self.pg_interfaces)
3074 self.pg_start()
3075 capture = self.pg4.get_capture(len(pkts))
3076 self.verify_capture_in(capture, self.pg4)
3077
3078 # in2out VRF 20
3079 pkts = self.create_stream_in(self.pg6, self.pg3)
3080 self.pg6.add_stream(pkts)
3081 self.pg_enable_capture(self.pg_interfaces)
3082 self.pg_start()
3083 capture = self.pg3.get_capture(len(pkts))
3084 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3085
3086 # out2in VRF 20
3087 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3088 self.pg3.add_stream(pkts)
3089 self.pg_enable_capture(self.pg_interfaces)
3090 self.pg_start()
3091 capture = self.pg6.get_capture(len(pkts))
3092 self.verify_capture_in(capture, self.pg6)
3093
3094 def test_output_feature_hairpinning(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003095 """NAT44EI output feature hairpinning (in2out postrouting)"""
Filip Varga18f1e412020-12-03 15:27:40 +01003096 host = self.pg0.remote_hosts[0]
3097 server = self.pg0.remote_hosts[1]
3098 host_in_port = 1234
3099 host_out_port = 0
3100 server_in_port = 5678
3101 server_out_port = 8765
3102
3103 self.nat44_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02003104 self.vapi.nat44_ei_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003105 sw_if_index=self.pg0.sw_if_index, is_add=1
3106 )
Filip Varga9c25eb12021-10-21 13:00:27 +02003107 self.vapi.nat44_ei_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003108 sw_if_index=self.pg1.sw_if_index, is_add=1
3109 )
Filip Varga18f1e412020-12-03 15:27:40 +01003110
3111 # add static mapping for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003112 self.nat44_add_static_mapping(
3113 server.ip4,
3114 self.nat_addr,
3115 server_in_port,
3116 server_out_port,
3117 proto=IP_PROTOS.tcp,
3118 )
Filip Varga18f1e412020-12-03 15:27:40 +01003119
3120 # send packet from host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003121 p = (
3122 Ether(src=host.mac, dst=self.pg0.local_mac)
3123 / IP(src=host.ip4, dst=self.nat_addr)
3124 / TCP(sport=host_in_port, dport=server_out_port)
3125 )
Filip Varga18f1e412020-12-03 15:27:40 +01003126 self.pg0.add_stream(p)
3127 self.pg_enable_capture(self.pg_interfaces)
3128 self.pg_start()
3129 capture = self.pg0.get_capture(1)
3130 p = capture[0]
3131 try:
3132 ip = p[IP]
3133 tcp = p[TCP]
3134 self.assertEqual(ip.src, self.nat_addr)
3135 self.assertEqual(ip.dst, server.ip4)
3136 self.assertNotEqual(tcp.sport, host_in_port)
3137 self.assertEqual(tcp.dport, server_in_port)
3138 self.assert_packet_checksums_valid(p)
3139 host_out_port = tcp.sport
3140 except:
3141 self.logger.error(ppp("Unexpected or invalid packet:", p))
3142 raise
3143
3144 # send reply from server to host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003145 p = (
3146 Ether(src=server.mac, dst=self.pg0.local_mac)
3147 / IP(src=server.ip4, dst=self.nat_addr)
3148 / TCP(sport=server_in_port, dport=host_out_port)
3149 )
Filip Varga18f1e412020-12-03 15:27:40 +01003150 self.pg0.add_stream(p)
3151 self.pg_enable_capture(self.pg_interfaces)
3152 self.pg_start()
3153 capture = self.pg0.get_capture(1)
3154 p = capture[0]
3155 try:
3156 ip = p[IP]
3157 tcp = p[TCP]
3158 self.assertEqual(ip.src, self.nat_addr)
3159 self.assertEqual(ip.dst, host.ip4)
3160 self.assertEqual(tcp.sport, server_out_port)
3161 self.assertEqual(tcp.dport, host_in_port)
3162 self.assert_packet_checksums_valid(p)
3163 except:
3164 self.logger.error(ppp("Unexpected or invalid packet:", p))
3165 raise
3166
3167 def test_one_armed_nat44(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003168 """NAT44EI One armed NAT"""
Filip Varga18f1e412020-12-03 15:27:40 +01003169 remote_host = self.pg9.remote_hosts[0]
3170 local_host = self.pg9.remote_hosts[1]
3171 external_port = 0
3172
3173 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003174 flags = self.config_flags.NAT44_EI_IF_INSIDE
3175 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003176 sw_if_index=self.pg9.sw_if_index, is_add=1
3177 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003178 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003179 sw_if_index=self.pg9.sw_if_index, flags=flags, is_add=1
3180 )
Filip Varga18f1e412020-12-03 15:27:40 +01003181
3182 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003183 p = (
3184 Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac)
3185 / IP(src=local_host.ip4, dst=remote_host.ip4)
3186 / TCP(sport=12345, dport=80)
3187 )
Filip Varga18f1e412020-12-03 15:27:40 +01003188 self.pg9.add_stream(p)
3189 self.pg_enable_capture(self.pg_interfaces)
3190 self.pg_start()
3191 capture = self.pg9.get_capture(1)
3192 p = capture[0]
3193 try:
3194 ip = p[IP]
3195 tcp = p[TCP]
3196 self.assertEqual(ip.src, self.nat_addr)
3197 self.assertEqual(ip.dst, remote_host.ip4)
3198 self.assertNotEqual(tcp.sport, 12345)
3199 external_port = tcp.sport
3200 self.assertEqual(tcp.dport, 80)
3201 self.assert_packet_checksums_valid(p)
3202 except:
3203 self.logger.error(ppp("Unexpected or invalid packet:", p))
3204 raise
3205
3206 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003207 p = (
3208 Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac)
3209 / IP(src=remote_host.ip4, dst=self.nat_addr)
3210 / TCP(sport=80, dport=external_port)
3211 )
Filip Varga18f1e412020-12-03 15:27:40 +01003212 self.pg9.add_stream(p)
3213 self.pg_enable_capture(self.pg_interfaces)
3214 self.pg_start()
3215 capture = self.pg9.get_capture(1)
3216 p = capture[0]
3217 try:
3218 ip = p[IP]
3219 tcp = p[TCP]
3220 self.assertEqual(ip.src, remote_host.ip4)
3221 self.assertEqual(ip.dst, local_host.ip4)
3222 self.assertEqual(tcp.sport, 80)
3223 self.assertEqual(tcp.dport, 12345)
3224 self.assert_packet_checksums_valid(p)
3225 except:
3226 self.logger.error(ppp("Unexpected or invalid packet:", p))
3227 raise
3228
Klement Sekerac294c502021-03-24 17:20:40 +01003229 if self.vpp_worker_count > 1:
3230 node = "nat44-ei-handoff-classify"
3231 else:
3232 node = "nat44-ei-classify"
3233
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003234 err = self.statistics.get_err_counter("/err/%s/next in2out" % node)
Filip Varga18f1e412020-12-03 15:27:40 +01003235 self.assertEqual(err, 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003236 err = self.statistics.get_err_counter("/err/%s/next out2in" % node)
Filip Varga18f1e412020-12-03 15:27:40 +01003237 self.assertEqual(err, 1)
3238
3239 def test_del_session(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003240 """NAT44EI delete session"""
Filip Varga18f1e412020-12-03 15:27:40 +01003241 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003242 flags = self.config_flags.NAT44_EI_IF_INSIDE
3243 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003244 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3245 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003246 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003247 sw_if_index=self.pg1.sw_if_index, is_add=1
3248 )
Filip Varga18f1e412020-12-03 15:27:40 +01003249
3250 pkts = self.create_stream_in(self.pg0, self.pg1)
3251 self.pg0.add_stream(pkts)
3252 self.pg_enable_capture(self.pg_interfaces)
3253 self.pg_start()
3254 self.pg1.get_capture(len(pkts))
3255
Filip Varga0eaf4e62021-02-17 14:34:54 +01003256 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003257 nsessions = len(sessions)
3258
Filip Varga0eaf4e62021-02-17 14:34:54 +01003259 self.vapi.nat44_ei_del_session(
3260 address=sessions[0].inside_ip_address,
3261 port=sessions[0].inside_port,
3262 protocol=sessions[0].protocol,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003263 flags=self.config_flags.NAT44_EI_IF_INSIDE,
3264 )
Filip Varga18f1e412020-12-03 15:27:40 +01003265
Filip Varga0eaf4e62021-02-17 14:34:54 +01003266 self.vapi.nat44_ei_del_session(
3267 address=sessions[1].outside_ip_address,
3268 port=sessions[1].outside_port,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003269 protocol=sessions[1].protocol,
3270 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003271
3272 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003273 self.assertEqual(nsessions - len(sessions), 2)
3274
Filip Varga0eaf4e62021-02-17 14:34:54 +01003275 self.vapi.nat44_ei_del_session(
3276 address=sessions[0].inside_ip_address,
3277 port=sessions[0].inside_port,
3278 protocol=sessions[0].protocol,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003279 flags=self.config_flags.NAT44_EI_IF_INSIDE,
3280 )
Filip Varga18f1e412020-12-03 15:27:40 +01003281
3282 self.verify_no_nat44_user()
3283
3284 def test_frag_in_order(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003285 """NAT44EI translate fragments arriving in order"""
Filip Varga18f1e412020-12-03 15:27:40 +01003286
3287 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003288 flags = self.config_flags.NAT44_EI_IF_INSIDE
3289 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003290 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3291 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003292 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003293 sw_if_index=self.pg1.sw_if_index, is_add=1
3294 )
Filip Varga18f1e412020-12-03 15:27:40 +01003295
3296 self.frag_in_order(proto=IP_PROTOS.tcp)
3297 self.frag_in_order(proto=IP_PROTOS.udp)
3298 self.frag_in_order(proto=IP_PROTOS.icmp)
3299
3300 def test_frag_forwarding(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003301 """NAT44EI forwarding fragment test"""
Filip Varga0eaf4e62021-02-17 14:34:54 +01003302 self.vapi.nat44_ei_add_del_interface_addr(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003303 is_add=1, sw_if_index=self.pg1.sw_if_index
3304 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003305 flags = self.config_flags.NAT44_EI_IF_INSIDE
3306 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003307 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3308 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003309 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003310 sw_if_index=self.pg1.sw_if_index, is_add=1
3311 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003312 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003313
3314 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003315 pkts = self.create_stream_frag(
3316 self.pg1, self.pg0.remote_ip4, 4789, 4789, data, proto=IP_PROTOS.udp
3317 )
Filip Varga18f1e412020-12-03 15:27:40 +01003318 self.pg1.add_stream(pkts)
3319 self.pg_enable_capture(self.pg_interfaces)
3320 self.pg_start()
3321 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003322 p = self.reass_frags_and_verify(frags, self.pg1.remote_ip4, self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01003323 self.assertEqual(p[UDP].sport, 4789)
3324 self.assertEqual(p[UDP].dport, 4789)
3325 self.assertEqual(data, p[Raw].load)
3326
3327 def test_reass_hairpinning(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003328 """NAT44EI fragments hairpinning"""
Filip Varga18f1e412020-12-03 15:27:40 +01003329
3330 server_addr = self.pg0.remote_hosts[1].ip4
3331 host_in_port = random.randint(1025, 65535)
3332 server_in_port = random.randint(1025, 65535)
3333 server_out_port = random.randint(1025, 65535)
3334
3335 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003336 flags = self.config_flags.NAT44_EI_IF_INSIDE
3337 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003338 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3339 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003340 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003341 sw_if_index=self.pg1.sw_if_index, is_add=1
3342 )
Filip Varga18f1e412020-12-03 15:27:40 +01003343 # add static mapping for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003344 self.nat44_add_static_mapping(
3345 server_addr,
3346 self.nat_addr,
3347 server_in_port,
3348 server_out_port,
3349 proto=IP_PROTOS.tcp,
3350 )
3351 self.nat44_add_static_mapping(
3352 server_addr,
3353 self.nat_addr,
3354 server_in_port,
3355 server_out_port,
3356 proto=IP_PROTOS.udp,
3357 )
Filip Varga18f1e412020-12-03 15:27:40 +01003358 self.nat44_add_static_mapping(server_addr, self.nat_addr)
3359
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003360 self.reass_hairpinning(
3361 server_addr,
3362 server_in_port,
3363 server_out_port,
3364 host_in_port,
3365 proto=IP_PROTOS.tcp,
3366 )
3367 self.reass_hairpinning(
3368 server_addr,
3369 server_in_port,
3370 server_out_port,
3371 host_in_port,
3372 proto=IP_PROTOS.udp,
3373 )
3374 self.reass_hairpinning(
3375 server_addr,
3376 server_in_port,
3377 server_out_port,
3378 host_in_port,
3379 proto=IP_PROTOS.icmp,
3380 )
Filip Varga18f1e412020-12-03 15:27:40 +01003381
3382 def test_frag_out_of_order(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003383 """NAT44EI translate fragments arriving out of order"""
Filip Varga18f1e412020-12-03 15:27:40 +01003384
3385 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003386 flags = self.config_flags.NAT44_EI_IF_INSIDE
3387 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003388 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3389 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003390 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003391 sw_if_index=self.pg1.sw_if_index, is_add=1
3392 )
Filip Varga18f1e412020-12-03 15:27:40 +01003393
3394 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3395 self.frag_out_of_order(proto=IP_PROTOS.udp)
3396 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3397
3398 def test_port_restricted(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003399 """NAT44EI Port restricted NAT44EI (MAP-E CE)"""
Filip Varga18f1e412020-12-03 15:27:40 +01003400 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003401 flags = self.config_flags.NAT44_EI_IF_INSIDE
3402 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003403 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3404 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003405 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003406 sw_if_index=self.pg1.sw_if_index, is_add=1
3407 )
3408 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(
3409 alg=1, psid_offset=6, psid_length=6, psid=10
3410 )
Filip Varga18f1e412020-12-03 15:27:40 +01003411
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003412 p = (
3413 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3414 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3415 / TCP(sport=4567, dport=22)
3416 )
Filip Varga18f1e412020-12-03 15:27:40 +01003417 self.pg0.add_stream(p)
3418 self.pg_enable_capture(self.pg_interfaces)
3419 self.pg_start()
3420 capture = self.pg1.get_capture(1)
3421 p = capture[0]
3422 try:
3423 ip = p[IP]
3424 tcp = p[TCP]
3425 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3426 self.assertEqual(ip.src, self.nat_addr)
3427 self.assertEqual(tcp.dport, 22)
3428 self.assertNotEqual(tcp.sport, 4567)
3429 self.assertEqual((tcp.sport >> 6) & 63, 10)
3430 self.assert_packet_checksums_valid(p)
3431 except:
3432 self.logger.error(ppp("Unexpected or invalid packet:", p))
3433 raise
3434
3435 def test_port_range(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003436 """NAT44EI External address port range"""
Filip Varga18f1e412020-12-03 15:27:40 +01003437 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003438 flags = self.config_flags.NAT44_EI_IF_INSIDE
3439 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003440 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3441 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003442 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003443 sw_if_index=self.pg1.sw_if_index, is_add=1
3444 )
3445 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(
3446 alg=2, start_port=1025, end_port=1027
3447 )
Filip Varga18f1e412020-12-03 15:27:40 +01003448
3449 pkts = []
3450 for port in range(0, 5):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003451 p = (
3452 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3453 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3454 / TCP(sport=1125 + port)
3455 )
Filip Varga18f1e412020-12-03 15:27:40 +01003456 pkts.append(p)
3457 self.pg0.add_stream(pkts)
3458 self.pg_enable_capture(self.pg_interfaces)
3459 self.pg_start()
3460 capture = self.pg1.get_capture(3)
3461 for p in capture:
3462 tcp = p[TCP]
3463 self.assertGreaterEqual(tcp.sport, 1025)
3464 self.assertLessEqual(tcp.sport, 1027)
3465
3466 def test_multiple_outside_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003467 """NAT44EI Multiple outside VRF"""
Filip Varga18f1e412020-12-03 15:27:40 +01003468 vrf_id1 = 1
3469 vrf_id2 = 2
3470
3471 self.pg1.unconfig_ip4()
3472 self.pg2.unconfig_ip4()
Benoît Ganneff570d32024-04-16 09:36:05 +02003473 self.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": vrf_id1})
3474 self.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": vrf_id2})
Filip Varga18f1e412020-12-03 15:27:40 +01003475 self.pg1.set_table_ip4(vrf_id1)
3476 self.pg2.set_table_ip4(vrf_id2)
3477 self.pg1.config_ip4()
3478 self.pg2.config_ip4()
3479 self.pg1.resolve_arp()
3480 self.pg2.resolve_arp()
3481
3482 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003483 flags = self.config_flags.NAT44_EI_IF_INSIDE
3484 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003485 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3486 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003487 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003488 sw_if_index=self.pg1.sw_if_index, is_add=1
3489 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003490 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003491 sw_if_index=self.pg2.sw_if_index, is_add=1
3492 )
Filip Varga18f1e412020-12-03 15:27:40 +01003493
3494 try:
3495 # first VRF
3496 pkts = self.create_stream_in(self.pg0, self.pg1)
3497 self.pg0.add_stream(pkts)
3498 self.pg_enable_capture(self.pg_interfaces)
3499 self.pg_start()
3500 capture = self.pg1.get_capture(len(pkts))
3501 self.verify_capture_out(capture, self.nat_addr)
3502
3503 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3504 self.pg1.add_stream(pkts)
3505 self.pg_enable_capture(self.pg_interfaces)
3506 self.pg_start()
3507 capture = self.pg0.get_capture(len(pkts))
3508 self.verify_capture_in(capture, self.pg0)
3509
3510 self.tcp_port_in = 60303
3511 self.udp_port_in = 60304
3512 self.icmp_id_in = 60305
3513
3514 # second VRF
3515 pkts = self.create_stream_in(self.pg0, self.pg2)
3516 self.pg0.add_stream(pkts)
3517 self.pg_enable_capture(self.pg_interfaces)
3518 self.pg_start()
3519 capture = self.pg2.get_capture(len(pkts))
3520 self.verify_capture_out(capture, self.nat_addr)
3521
3522 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3523 self.pg2.add_stream(pkts)
3524 self.pg_enable_capture(self.pg_interfaces)
3525 self.pg_start()
3526 capture = self.pg0.get_capture(len(pkts))
3527 self.verify_capture_in(capture, self.pg0)
3528
3529 finally:
3530 self.nat44_add_address(self.nat_addr, is_add=0)
3531 self.pg1.unconfig_ip4()
3532 self.pg2.unconfig_ip4()
3533 self.pg1.set_table_ip4(0)
3534 self.pg2.set_table_ip4(0)
3535 self.pg1.config_ip4()
3536 self.pg2.config_ip4()
3537 self.pg1.resolve_arp()
3538 self.pg2.resolve_arp()
3539
3540 def test_mss_clamping(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003541 """NAT44EI TCP MSS clamping"""
Filip Varga18f1e412020-12-03 15:27:40 +01003542 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003543 flags = self.config_flags.NAT44_EI_IF_INSIDE
3544 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003545 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3546 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003547 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003548 sw_if_index=self.pg1.sw_if_index, is_add=1
3549 )
Filip Varga18f1e412020-12-03 15:27:40 +01003550
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003551 p = (
3552 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3553 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3554 / TCP(
3555 sport=self.tcp_port_in,
3556 dport=self.tcp_external_port,
3557 flags="S",
3558 options=[("MSS", 1400)],
3559 )
3560 )
Filip Varga18f1e412020-12-03 15:27:40 +01003561
Filip Varga0eaf4e62021-02-17 14:34:54 +01003562 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1000)
Filip Varga18f1e412020-12-03 15:27:40 +01003563 self.pg0.add_stream(p)
3564 self.pg_enable_capture(self.pg_interfaces)
3565 self.pg_start()
3566 capture = self.pg1.get_capture(1)
3567 # Negotiated MSS value greater than configured - changed
3568 self.verify_mss_value(capture[0], 1000)
3569
Filip Varga0eaf4e62021-02-17 14:34:54 +01003570 self.vapi.nat44_ei_set_mss_clamping(enable=0, mss_value=1500)
Filip Varga18f1e412020-12-03 15:27:40 +01003571 self.pg0.add_stream(p)
3572 self.pg_enable_capture(self.pg_interfaces)
3573 self.pg_start()
3574 capture = self.pg1.get_capture(1)
3575 # MSS clamping disabled - negotiated MSS unchanged
3576 self.verify_mss_value(capture[0], 1400)
3577
Filip Varga0eaf4e62021-02-17 14:34:54 +01003578 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1500)
Filip Varga18f1e412020-12-03 15:27:40 +01003579 self.pg0.add_stream(p)
3580 self.pg_enable_capture(self.pg_interfaces)
3581 self.pg_start()
3582 capture = self.pg1.get_capture(1)
3583 # Negotiated MSS value smaller than configured - unchanged
3584 self.verify_mss_value(capture[0], 1400)
3585
3586 def test_ha_send(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003587 """NAT44EI Send HA session synchronization events (active)"""
Filip Varga0eaf4e62021-02-17 14:34:54 +01003588 flags = self.config_flags.NAT44_EI_IF_INSIDE
3589 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003590 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3591 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003592 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003593 sw_if_index=self.pg1.sw_if_index, is_add=1
3594 )
Filip Varga18f1e412020-12-03 15:27:40 +01003595 self.nat44_add_address(self.nat_addr)
3596
Filip Varga0eaf4e62021-02-17 14:34:54 +01003597 self.vapi.nat44_ei_ha_set_listener(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003598 ip_address=self.pg3.local_ip4, port=12345, path_mtu=512
3599 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003600 self.vapi.nat44_ei_ha_set_failover(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003601 ip_address=self.pg3.remote_ip4, port=12346, session_refresh_interval=10
3602 )
Filip Varga18f1e412020-12-03 15:27:40 +01003603 bind_layers(UDP, HANATStateSync, sport=12345)
3604
3605 # create sessions
3606 pkts = self.create_stream_in(self.pg0, self.pg1)
3607 self.pg0.add_stream(pkts)
3608 self.pg_enable_capture(self.pg_interfaces)
3609 self.pg_start()
3610 capture = self.pg1.get_capture(len(pkts))
3611 self.verify_capture_out(capture)
3612 # active send HA events
Filip Varga0eaf4e62021-02-17 14:34:54 +01003613 self.vapi.nat44_ei_ha_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003614 stats = self.statistics["/nat44-ei/ha/add-event-send"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003615 self.assertEqual(stats[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01003616 capture = self.pg3.get_capture(1)
3617 p = capture[0]
3618 self.assert_packet_checksums_valid(p)
3619 try:
3620 ip = p[IP]
3621 udp = p[UDP]
3622 hanat = p[HANATStateSync]
3623 except IndexError:
3624 self.logger.error(ppp("Invalid packet:", p))
3625 raise
3626 else:
3627 self.assertEqual(ip.src, self.pg3.local_ip4)
3628 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3629 self.assertEqual(udp.sport, 12345)
3630 self.assertEqual(udp.dport, 12346)
3631 self.assertEqual(hanat.version, 1)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003632 # self.assertEqual(hanat.thread_index, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003633 self.assertEqual(hanat.count, 3)
3634 seq = hanat.sequence_number
3635 for event in hanat.events:
3636 self.assertEqual(event.event_type, 1)
3637 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3638 self.assertEqual(event.out_addr, self.nat_addr)
3639 self.assertEqual(event.fib_index, 0)
3640
3641 # ACK received events
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003642 ack = (
3643 Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac)
3644 / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4)
3645 / UDP(sport=12346, dport=12345)
3646 / HANATStateSync(
3647 sequence_number=seq, flags="ACK", thread_index=hanat.thread_index
3648 )
3649 )
Filip Varga18f1e412020-12-03 15:27:40 +01003650 self.pg3.add_stream(ack)
3651 self.pg_start()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003652 stats = self.statistics["/nat44-ei/ha/ack-recv"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003653 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003654
3655 # delete one session
3656 self.pg_enable_capture(self.pg_interfaces)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003657 self.vapi.nat44_ei_del_session(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003658 address=self.pg0.remote_ip4,
3659 port=self.tcp_port_in,
3660 protocol=IP_PROTOS.tcp,
3661 flags=self.config_flags.NAT44_EI_IF_INSIDE,
3662 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003663 self.vapi.nat44_ei_ha_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003664 stats = self.statistics["/nat44-ei/ha/del-event-send"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003665 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003666 capture = self.pg3.get_capture(1)
3667 p = capture[0]
3668 try:
3669 hanat = p[HANATStateSync]
3670 except IndexError:
3671 self.logger.error(ppp("Invalid packet:", p))
3672 raise
3673 else:
3674 self.assertGreater(hanat.sequence_number, seq)
3675
3676 # do not send ACK, active retry send HA event again
3677 self.pg_enable_capture(self.pg_interfaces)
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003678 self.virtual_sleep(12)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003679 stats = self.statistics["/nat44-ei/ha/retry-count"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003680 self.assertEqual(stats[:, 0].sum(), 3)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003681 stats = self.statistics["/nat44-ei/ha/missed-count"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003682 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003683 capture = self.pg3.get_capture(3)
3684 for packet in capture:
3685 self.assertEqual(packet, p)
3686
3687 # session counters refresh
3688 pkts = self.create_stream_out(self.pg1)
3689 self.pg1.add_stream(pkts)
3690 self.pg_enable_capture(self.pg_interfaces)
3691 self.pg_start()
3692 self.pg0.get_capture(2)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003693 self.vapi.nat44_ei_ha_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003694 stats = self.statistics["/nat44-ei/ha/refresh-event-send"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003695 self.assertEqual(stats[:, 0].sum(), 2)
Filip Varga18f1e412020-12-03 15:27:40 +01003696 capture = self.pg3.get_capture(1)
3697 p = capture[0]
3698 self.assert_packet_checksums_valid(p)
3699 try:
3700 ip = p[IP]
3701 udp = p[UDP]
3702 hanat = p[HANATStateSync]
3703 except IndexError:
3704 self.logger.error(ppp("Invalid packet:", p))
3705 raise
3706 else:
3707 self.assertEqual(ip.src, self.pg3.local_ip4)
3708 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3709 self.assertEqual(udp.sport, 12345)
3710 self.assertEqual(udp.dport, 12346)
3711 self.assertEqual(hanat.version, 1)
3712 self.assertEqual(hanat.count, 2)
3713 seq = hanat.sequence_number
3714 for event in hanat.events:
3715 self.assertEqual(event.event_type, 3)
3716 self.assertEqual(event.out_addr, self.nat_addr)
3717 self.assertEqual(event.fib_index, 0)
3718 self.assertEqual(event.total_pkts, 2)
3719 self.assertGreater(event.total_bytes, 0)
3720
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003721 stats = self.statistics["/nat44-ei/ha/ack-recv"]
3722 ack = (
3723 Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac)
3724 / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4)
3725 / UDP(sport=12346, dport=12345)
3726 / HANATStateSync(
3727 sequence_number=seq, flags="ACK", thread_index=hanat.thread_index
3728 )
3729 )
Filip Varga18f1e412020-12-03 15:27:40 +01003730 self.pg3.add_stream(ack)
3731 self.pg_start()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003732 stats = self.statistics["/nat44-ei/ha/ack-recv"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003733 self.assertEqual(stats[:, 0].sum(), 2)
Filip Varga18f1e412020-12-03 15:27:40 +01003734
3735 def test_ha_recv(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003736 """NAT44EI Receive HA session synchronization events (passive)"""
Filip Varga18f1e412020-12-03 15:27:40 +01003737 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003738 flags = self.config_flags.NAT44_EI_IF_INSIDE
3739 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003740 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3741 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01003742 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003743 sw_if_index=self.pg1.sw_if_index, is_add=1
3744 )
3745 self.vapi.nat44_ei_ha_set_listener(
3746 ip_address=self.pg3.local_ip4, port=12345, path_mtu=512
3747 )
Filip Varga18f1e412020-12-03 15:27:40 +01003748 bind_layers(UDP, HANATStateSync, sport=12345)
3749
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003750 # this is a bit tricky - HA dictates thread index due to how it's
3751 # designed, but once we use HA to create a session, we also want
3752 # to pass a packet through said session. so the session must end
3753 # up on the correct thread from both directions - in2out (based on
3754 # IP address) and out2in (based on outside port)
3755
3756 # first choose a thread index which is correct for IP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003757 thread_index = get_nat44_ei_in2out_worker_index(
3758 self.pg0.remote_ip4, self.vpp_worker_count
3759 )
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003760
3761 # now pick a port which is correct for given thread
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003762 port_per_thread = int((0xFFFF - 1024) / max(1, self.vpp_worker_count))
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003763 self.tcp_port_out = 1024 + random.randint(1, port_per_thread)
3764 self.udp_port_out = 1024 + random.randint(1, port_per_thread)
3765 if self.vpp_worker_count > 0:
3766 self.tcp_port_out += port_per_thread * (thread_index - 1)
3767 self.udp_port_out += port_per_thread * (thread_index - 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003768
3769 # send HA session add events to failover/passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003770 p = (
3771 Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac)
3772 / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4)
3773 / UDP(sport=12346, dport=12345)
3774 / HANATStateSync(
3775 sequence_number=1,
3776 events=[
3777 Event(
3778 event_type="add",
3779 protocol="tcp",
3780 in_addr=self.pg0.remote_ip4,
3781 out_addr=self.nat_addr,
3782 in_port=self.tcp_port_in,
3783 out_port=self.tcp_port_out,
3784 eh_addr=self.pg1.remote_ip4,
3785 ehn_addr=self.pg1.remote_ip4,
3786 eh_port=self.tcp_external_port,
3787 ehn_port=self.tcp_external_port,
3788 fib_index=0,
3789 ),
3790 Event(
3791 event_type="add",
3792 protocol="udp",
3793 in_addr=self.pg0.remote_ip4,
3794 out_addr=self.nat_addr,
3795 in_port=self.udp_port_in,
3796 out_port=self.udp_port_out,
3797 eh_addr=self.pg1.remote_ip4,
3798 ehn_addr=self.pg1.remote_ip4,
3799 eh_port=self.udp_external_port,
3800 ehn_port=self.udp_external_port,
3801 fib_index=0,
3802 ),
3803 ],
3804 thread_index=thread_index,
3805 )
3806 )
Filip Varga18f1e412020-12-03 15:27:40 +01003807
3808 self.pg3.add_stream(p)
3809 self.pg_enable_capture(self.pg_interfaces)
3810 self.pg_start()
3811 # receive ACK
3812 capture = self.pg3.get_capture(1)
3813 p = capture[0]
3814 try:
3815 hanat = p[HANATStateSync]
3816 except IndexError:
3817 self.logger.error(ppp("Invalid packet:", p))
3818 raise
3819 else:
3820 self.assertEqual(hanat.sequence_number, 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003821 self.assertEqual(hanat.flags, "ACK")
Filip Varga18f1e412020-12-03 15:27:40 +01003822 self.assertEqual(hanat.version, 1)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003823 self.assertEqual(hanat.thread_index, thread_index)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003824 stats = self.statistics["/nat44-ei/ha/ack-send"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003825 self.assertEqual(stats[:, 0].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003826 stats = self.statistics["/nat44-ei/ha/add-event-recv"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003827 self.assertEqual(stats[:, 0].sum(), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003828 users = self.statistics["/nat44-ei/total-users"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003829 self.assertEqual(users[:, 0].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003830 sessions = self.statistics["/nat44-ei/total-sessions"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003831 self.assertEqual(sessions[:, 0].sum(), 2)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003832 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01003833 self.assertEqual(len(users), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003834 self.assertEqual(str(users[0].ip_address), self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01003835 # there should be 2 sessions created by HA
Filip Varga0eaf4e62021-02-17 14:34:54 +01003836 sessions = self.vapi.nat44_ei_user_session_dump(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003837 users[0].ip_address, users[0].vrf_id
3838 )
Filip Varga18f1e412020-12-03 15:27:40 +01003839 self.assertEqual(len(sessions), 2)
3840 for session in sessions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003841 self.assertEqual(str(session.inside_ip_address), self.pg0.remote_ip4)
3842 self.assertEqual(str(session.outside_ip_address), self.nat_addr)
3843 self.assertIn(session.inside_port, [self.tcp_port_in, self.udp_port_in])
3844 self.assertIn(session.outside_port, [self.tcp_port_out, self.udp_port_out])
Filip Varga18f1e412020-12-03 15:27:40 +01003845 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3846
3847 # send HA session delete event to failover/passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003848 p = (
3849 Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac)
3850 / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4)
3851 / UDP(sport=12346, dport=12345)
3852 / HANATStateSync(
3853 sequence_number=2,
3854 events=[
3855 Event(
3856 event_type="del",
3857 protocol="udp",
3858 in_addr=self.pg0.remote_ip4,
3859 out_addr=self.nat_addr,
3860 in_port=self.udp_port_in,
3861 out_port=self.udp_port_out,
3862 eh_addr=self.pg1.remote_ip4,
3863 ehn_addr=self.pg1.remote_ip4,
3864 eh_port=self.udp_external_port,
3865 ehn_port=self.udp_external_port,
3866 fib_index=0,
3867 )
3868 ],
3869 thread_index=thread_index,
3870 )
3871 )
Filip Varga18f1e412020-12-03 15:27:40 +01003872
3873 self.pg3.add_stream(p)
3874 self.pg_enable_capture(self.pg_interfaces)
3875 self.pg_start()
3876 # receive ACK
3877 capture = self.pg3.get_capture(1)
3878 p = capture[0]
3879 try:
3880 hanat = p[HANATStateSync]
3881 except IndexError:
3882 self.logger.error(ppp("Invalid packet:", p))
3883 raise
3884 else:
3885 self.assertEqual(hanat.sequence_number, 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003886 self.assertEqual(hanat.flags, "ACK")
Filip Varga18f1e412020-12-03 15:27:40 +01003887 self.assertEqual(hanat.version, 1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003888 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01003889 self.assertEqual(len(users), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003890 self.assertEqual(str(users[0].ip_address), self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01003891 # now we should have only 1 session, 1 deleted by HA
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003892 sessions = self.vapi.nat44_ei_user_session_dump(
3893 users[0].ip_address, users[0].vrf_id
3894 )
Filip Varga18f1e412020-12-03 15:27:40 +01003895 self.assertEqual(len(sessions), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003896 stats = self.statistics["/nat44-ei/ha/del-event-recv"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003897 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003898
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003899 stats = self.statistics.get_err_counter("/err/nat44-ei-ha/pkts-processed")
Filip Varga18f1e412020-12-03 15:27:40 +01003900 self.assertEqual(stats, 2)
3901
3902 # send HA session refresh event to failover/passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003903 p = (
3904 Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac)
3905 / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4)
3906 / UDP(sport=12346, dport=12345)
3907 / HANATStateSync(
3908 sequence_number=3,
3909 events=[
3910 Event(
3911 event_type="refresh",
3912 protocol="tcp",
3913 in_addr=self.pg0.remote_ip4,
3914 out_addr=self.nat_addr,
3915 in_port=self.tcp_port_in,
3916 out_port=self.tcp_port_out,
3917 eh_addr=self.pg1.remote_ip4,
3918 ehn_addr=self.pg1.remote_ip4,
3919 eh_port=self.tcp_external_port,
3920 ehn_port=self.tcp_external_port,
3921 fib_index=0,
3922 total_bytes=1024,
3923 total_pkts=2,
3924 )
3925 ],
3926 thread_index=thread_index,
3927 )
3928 )
Filip Varga18f1e412020-12-03 15:27:40 +01003929 self.pg3.add_stream(p)
3930 self.pg_enable_capture(self.pg_interfaces)
3931 self.pg_start()
3932 # receive ACK
3933 capture = self.pg3.get_capture(1)
3934 p = capture[0]
3935 try:
3936 hanat = p[HANATStateSync]
3937 except IndexError:
3938 self.logger.error(ppp("Invalid packet:", p))
3939 raise
3940 else:
3941 self.assertEqual(hanat.sequence_number, 3)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003942 self.assertEqual(hanat.flags, "ACK")
Filip Varga18f1e412020-12-03 15:27:40 +01003943 self.assertEqual(hanat.version, 1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003944 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01003945 self.assertEqual(len(users), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003946 self.assertEqual(str(users[0].ip_address), self.pg0.remote_ip4)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003947 sessions = self.vapi.nat44_ei_user_session_dump(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003948 users[0].ip_address, users[0].vrf_id
3949 )
Filip Varga18f1e412020-12-03 15:27:40 +01003950 self.assertEqual(len(sessions), 1)
3951 session = sessions[0]
3952 self.assertEqual(session.total_bytes, 1024)
3953 self.assertEqual(session.total_pkts, 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003954 stats = self.statistics["/nat44-ei/ha/refresh-event-recv"]
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003955 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003956
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003957 stats = self.statistics.get_err_counter("/err/nat44-ei-ha/pkts-processed")
Filip Varga18f1e412020-12-03 15:27:40 +01003958 self.assertEqual(stats, 3)
3959
3960 # send packet to test session created by HA
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003961 p = (
3962 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3963 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3964 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out)
3965 )
Filip Varga18f1e412020-12-03 15:27:40 +01003966 self.pg1.add_stream(p)
3967 self.pg_enable_capture(self.pg_interfaces)
3968 self.pg_start()
3969 capture = self.pg0.get_capture(1)
3970 p = capture[0]
3971 try:
3972 ip = p[IP]
3973 tcp = p[TCP]
3974 except IndexError:
3975 self.logger.error(ppp("Invalid packet:", p))
3976 raise
3977 else:
3978 self.assertEqual(ip.src, self.pg1.remote_ip4)
3979 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3980 self.assertEqual(tcp.sport, self.tcp_external_port)
3981 self.assertEqual(tcp.dport, self.tcp_port_in)
3982
Filip Varga0eaf4e62021-02-17 14:34:54 +01003983 def reconfigure_frame_queue_nelts(self, frame_queue_nelts):
3984 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3985 self.vapi.nat44_ei_set_fq_options(frame_queue_nelts=frame_queue_nelts)
3986 # keep plugin configuration persistent
3987 self.plugin_enable()
3988 return self.vapi.nat44_ei_show_fq_options().frame_queue_nelts
3989
3990 def test_set_frame_queue_nelts(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003991 """NAT44EI API test - worker handoff frame queue elements"""
Filip Varga0eaf4e62021-02-17 14:34:54 +01003992 self.assertEqual(self.reconfigure_frame_queue_nelts(512), 512)
3993
Filip Varga18f1e412020-12-03 15:27:40 +01003994 def show_commands_at_teardown(self):
Filip Varga0eaf4e62021-02-17 14:34:54 +01003995 self.logger.info(self.vapi.cli("show nat44 ei timeouts"))
3996 self.logger.info(self.vapi.cli("show nat44 ei addresses"))
3997 self.logger.info(self.vapi.cli("show nat44 ei interfaces"))
3998 self.logger.info(self.vapi.cli("show nat44 ei static mappings"))
3999 self.logger.info(self.vapi.cli("show nat44 ei interface address"))
4000 self.logger.info(self.vapi.cli("show nat44 ei sessions detail"))
4001 self.logger.info(self.vapi.cli("show nat44 ei hash tables detail"))
4002 self.logger.info(self.vapi.cli("show nat44 ei ha"))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004003 self.logger.info(self.vapi.cli("show nat44 ei addr-port-assignment-alg"))
Filip Varga18f1e412020-12-03 15:27:40 +01004004
Klement Sekeradc243ee2021-02-25 16:47:23 +01004005 def test_outside_address_distribution(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004006 """Outside address distribution based on source address"""
Klement Sekeradc243ee2021-02-25 16:47:23 +01004007
4008 x = 100
4009 nat_addresses = []
4010
4011 for i in range(1, x):
4012 a = "10.0.0.%d" % i
4013 nat_addresses.append(a)
4014
4015 flags = self.config_flags.NAT44_EI_IF_INSIDE
4016 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004017 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
4018 )
Klement Sekeradc243ee2021-02-25 16:47:23 +01004019 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004020 sw_if_index=self.pg1.sw_if_index, is_add=1
4021 )
Klement Sekeradc243ee2021-02-25 16:47:23 +01004022
4023 self.vapi.nat44_ei_add_del_address_range(
4024 first_ip_address=nat_addresses[0],
4025 last_ip_address=nat_addresses[-1],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004026 vrf_id=0xFFFFFFFF,
4027 is_add=1,
4028 )
Klement Sekeradc243ee2021-02-25 16:47:23 +01004029
4030 self.pg0.generate_remote_hosts(x)
4031
4032 pkts = []
4033 for i in range(x):
Klement Sekerab2da6d62021-03-24 17:25:14 +01004034 info = self.create_packet_info(self.pg0, self.pg1)
4035 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004036 p = (
4037 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4038 / IP(src=self.pg0.remote_hosts[i].ip4, dst=self.pg1.remote_ip4)
4039 / UDP(sport=7000 + i, dport=8000 + i)
4040 / Raw(payload)
4041 )
Klement Sekerab2da6d62021-03-24 17:25:14 +01004042 info.data = p
Klement Sekeradc243ee2021-02-25 16:47:23 +01004043 pkts.append(p)
4044
4045 self.pg0.add_stream(pkts)
4046 self.pg_enable_capture(self.pg_interfaces)
4047 self.pg_start()
4048 recvd = self.pg1.get_capture(len(pkts))
Klement Sekerab2da6d62021-03-24 17:25:14 +01004049 for p_recvd in recvd:
4050 payload_info = self.payload_to_info(p_recvd[Raw])
4051 packet_index = payload_info.index
4052 info = self._packet_infos[packet_index]
4053 self.assertTrue(info is not None)
4054 self.assertEqual(packet_index, info.index)
4055 p_sent = info.data
Klement Sekeradc243ee2021-02-25 16:47:23 +01004056 packed = socket.inet_aton(p_sent[IP].src)
4057 numeric = struct.unpack("!L", packed)[0]
4058 numeric = socket.htonl(numeric)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004059 a = nat_addresses[(numeric - 1) % len(nat_addresses)]
Klement Sekerab2da6d62021-03-24 17:25:14 +01004060 self.assertEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004061 a,
4062 p_recvd[IP].src,
Klement Sekerab2da6d62021-03-24 17:25:14 +01004063 "Invalid packet (src IP %s translated to %s, but expected %s)"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004064 % (p_sent[IP].src, p_recvd[IP].src, a),
4065 )
Klement Sekeradc243ee2021-02-25 16:47:23 +01004066
Matthew Smith01930f52021-05-13 11:11:33 -05004067 def test_default_user_sessions(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004068 """NAT44EI default per-user session limit is used and reported"""
Matthew Smith01930f52021-05-13 11:11:33 -05004069 nat44_ei_config = self.vapi.nat44_ei_show_running_config()
4070 # a nonzero default should be reported for user_sessions
4071 self.assertNotEqual(nat44_ei_config.user_sessions, 0)
4072
Vladislav Grishenko3abb32c2022-12-04 15:02:03 +05004073 def test_delete_interface(self):
4074 """NAT44EI delete nat interface"""
4075
4076 self.nat44_add_address(self.nat_addr)
4077
4078 interfaces = self.create_loopback_interfaces(4)
4079
4080 self.vapi.nat44_ei_interface_add_del_feature(
4081 sw_if_index=interfaces[0].sw_if_index, is_add=1
4082 )
4083 flags = self.config_flags.NAT44_EI_IF_INSIDE
4084 self.vapi.nat44_ei_interface_add_del_feature(
4085 sw_if_index=interfaces[1].sw_if_index, flags=flags, is_add=1
4086 )
4087 flags |= self.config_flags.NAT44_EI_IF_OUTSIDE
4088 self.vapi.nat44_ei_interface_add_del_feature(
4089 sw_if_index=interfaces[2].sw_if_index, flags=flags, is_add=1
4090 )
4091 self.vapi.nat44_ei_add_del_output_interface(
4092 sw_if_index=interfaces[3].sw_if_index, is_add=1
4093 )
4094
4095 nat_sw_if_indices = [
4096 i.sw_if_index
4097 for i in self.vapi.nat44_ei_interface_dump()
4098 + list(self.vapi.vpp.details_iter(self.vapi.nat44_ei_output_interface_get))
4099 ]
4100 self.assertEqual(len(nat_sw_if_indices), len(interfaces))
4101
4102 loopbacks = []
4103 for i in interfaces:
4104 # delete nat-enabled interface
4105 self.assertIn(i.sw_if_index, nat_sw_if_indices)
4106 i.remove_vpp_config()
4107
4108 # create interface with the same index
4109 lo = VppLoInterface(self)
4110 loopbacks.append(lo)
4111 self.assertEqual(lo.sw_if_index, i.sw_if_index)
4112
4113 # check interface is not nat-enabled
4114 nat_sw_if_indices = [
4115 i.sw_if_index
4116 for i in self.vapi.nat44_ei_interface_dump()
4117 + list(
4118 self.vapi.vpp.details_iter(self.vapi.nat44_ei_output_interface_get)
4119 )
4120 ]
4121 self.assertNotIn(lo.sw_if_index, nat_sw_if_indices)
4122
4123 for i in loopbacks:
4124 i.remove_vpp_config()
4125
Filip Varga18f1e412020-12-03 15:27:40 +01004126
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00004127@unittest.skipIf("nat" in config.excluded_plugins, "Exclude NAT plugin tests")
Filip Varga18f1e412020-12-03 15:27:40 +01004128class TestNAT44Out2InDPO(MethodHolder):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004129 """NAT44EI Test Cases using out2in DPO"""
Filip Varga18f1e412020-12-03 15:27:40 +01004130
4131 @classmethod
4132 def setUpClass(cls):
4133 super(TestNAT44Out2InDPO, cls).setUpClass()
Filip Varga0eaf4e62021-02-17 14:34:54 +01004134 cls.vapi.cli("set log class nat44-ei level debug")
Filip Varga18f1e412020-12-03 15:27:40 +01004135
4136 cls.tcp_port_in = 6303
4137 cls.tcp_port_out = 6303
4138 cls.udp_port_in = 6304
4139 cls.udp_port_out = 6304
4140 cls.icmp_id_in = 6305
4141 cls.icmp_id_out = 6305
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004142 cls.nat_addr = "10.0.0.3"
4143 cls.dst_ip4 = "192.168.70.1"
Filip Varga18f1e412020-12-03 15:27:40 +01004144
4145 cls.create_pg_interfaces(range(2))
4146
4147 cls.pg0.admin_up()
4148 cls.pg0.config_ip4()
4149 cls.pg0.resolve_arp()
4150
4151 cls.pg1.admin_up()
4152 cls.pg1.config_ip6()
4153 cls.pg1.resolve_ndp()
4154
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004155 r1 = VppIpRoute(
4156 cls,
4157 "::",
4158 0,
4159 [VppRoutePath(cls.pg1.remote_ip6, cls.pg1.sw_if_index)],
4160 register=False,
4161 )
Filip Varga18f1e412020-12-03 15:27:40 +01004162 r1.add_vpp_config()
4163
4164 def setUp(self):
4165 super(TestNAT44Out2InDPO, self).setUp()
Filip Varga0eaf4e62021-02-17 14:34:54 +01004166 flags = self.config_flags.NAT44_EI_OUT2IN_DPO
4167 self.vapi.nat44_ei_plugin_enable_disable(enable=1, flags=flags)
Filip Varga18f1e412020-12-03 15:27:40 +01004168
4169 def tearDown(self):
4170 super(TestNAT44Out2InDPO, self).tearDown()
4171 if not self.vpp_dead:
Filip Varga0eaf4e62021-02-17 14:34:54 +01004172 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +01004173 self.vapi.cli("clear logging")
4174
4175 def configure_xlat(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004176 self.dst_ip6_pfx = "1:2:3::"
4177 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6, self.dst_ip6_pfx)
Filip Varga18f1e412020-12-03 15:27:40 +01004178 self.dst_ip6_pfx_len = 96
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004179 self.src_ip6_pfx = "4:5:6::"
4180 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6, self.src_ip6_pfx)
Filip Varga18f1e412020-12-03 15:27:40 +01004181 self.src_ip6_pfx_len = 96
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004182 self.vapi.map_add_domain(
4183 self.dst_ip6_pfx_n,
4184 self.dst_ip6_pfx_len,
4185 self.src_ip6_pfx_n,
4186 self.src_ip6_pfx_len,
4187 "\x00\x00\x00\x00",
4188 0,
4189 )
Filip Varga18f1e412020-12-03 15:27:40 +01004190
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004191 @unittest.skip("Temporary disabled")
Filip Varga18f1e412020-12-03 15:27:40 +01004192 def test_464xlat_ce(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004193 """Test 464XLAT CE with NAT44EI"""
Filip Varga18f1e412020-12-03 15:27:40 +01004194
Filip Varga18f1e412020-12-03 15:27:40 +01004195 self.configure_xlat()
4196
Filip Varga0eaf4e62021-02-17 14:34:54 +01004197 flags = self.config_flags.NAT44_EI_IF_INSIDE
4198 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004199 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
4200 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01004201 self.vapi.nat44_ei_add_del_address_range(
4202 first_ip_address=self.nat_addr_n,
4203 last_ip_address=self.nat_addr_n,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004204 vrf_id=0xFFFFFFFF,
4205 is_add=1,
4206 )
Filip Varga18f1e412020-12-03 15:27:40 +01004207
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004208 out_src_ip6 = self.compose_ip6(
4209 self.dst_ip4, self.dst_ip6_pfx, self.dst_ip6_pfx_len
4210 )
4211 out_dst_ip6 = self.compose_ip6(
4212 self.nat_addr, self.src_ip6_pfx, self.src_ip6_pfx_len
4213 )
Filip Varga18f1e412020-12-03 15:27:40 +01004214
4215 try:
4216 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4217 self.pg0.add_stream(pkts)
4218 self.pg_enable_capture(self.pg_interfaces)
4219 self.pg_start()
4220 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004221 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6, dst_ip=out_src_ip6)
Filip Varga18f1e412020-12-03 15:27:40 +01004222
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004223 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
Filip Varga18f1e412020-12-03 15:27:40 +01004224 self.pg1.add_stream(pkts)
4225 self.pg_enable_capture(self.pg_interfaces)
4226 self.pg_start()
4227 capture = self.pg0.get_capture(len(pkts))
4228 self.verify_capture_in(capture, self.pg0)
4229 finally:
Filip Varga0eaf4e62021-02-17 14:34:54 +01004230 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004231 sw_if_index=self.pg0.sw_if_index, flags=flags
4232 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01004233 self.vapi.nat44_ei_add_del_address_range(
Filip Varga18f1e412020-12-03 15:27:40 +01004234 first_ip_address=self.nat_addr_n,
4235 last_ip_address=self.nat_addr_n,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004236 vrf_id=0xFFFFFFFF,
4237 )
Filip Varga18f1e412020-12-03 15:27:40 +01004238
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004239 @unittest.skip("Temporary disabled")
Filip Varga18f1e412020-12-03 15:27:40 +01004240 def test_464xlat_ce_no_nat(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004241 """Test 464XLAT CE without NAT44EI"""
Filip Varga18f1e412020-12-03 15:27:40 +01004242
4243 self.configure_xlat()
4244
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004245 out_src_ip6 = self.compose_ip6(
4246 self.dst_ip4, self.dst_ip6_pfx, self.dst_ip6_pfx_len
4247 )
4248 out_dst_ip6 = self.compose_ip6(
4249 self.pg0.remote_ip4, self.src_ip6_pfx, self.src_ip6_pfx_len
4250 )
Filip Varga18f1e412020-12-03 15:27:40 +01004251
4252 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4253 self.pg0.add_stream(pkts)
4254 self.pg_enable_capture(self.pg_interfaces)
4255 self.pg_start()
4256 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004257 self.verify_capture_out_ip6(
4258 capture, dst_ip=out_src_ip6, nat_ip=out_dst_ip6, same_port=True
4259 )
Filip Varga18f1e412020-12-03 15:27:40 +01004260
4261 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4262 self.pg1.add_stream(pkts)
4263 self.pg_enable_capture(self.pg_interfaces)
4264 self.pg_start()
4265 capture = self.pg0.get_capture(len(pkts))
4266 self.verify_capture_in(capture, self.pg0)
4267
4268
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00004269@unittest.skipIf("nat" in config.excluded_plugins, "Exclude NAT plugin tests")
Klement Sekera98d82ca2021-02-02 13:25:40 +01004270class TestNAT44EIMW(MethodHolder):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004271 """NAT44EI Test Cases (multiple workers)"""
4272
Klement Sekera8d815022021-03-15 16:58:10 +01004273 vpp_worker_count = 2
Klement Sekera98d82ca2021-02-02 13:25:40 +01004274 max_translations = 10240
4275 max_users = 10240
4276
4277 @classmethod
4278 def setUpClass(cls):
4279 super(TestNAT44EIMW, cls).setUpClass()
4280 cls.vapi.cli("set log class nat level debug")
4281
4282 cls.tcp_port_in = 6303
4283 cls.tcp_port_out = 6303
4284 cls.udp_port_in = 6304
4285 cls.udp_port_out = 6304
4286 cls.icmp_id_in = 6305
4287 cls.icmp_id_out = 6305
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004288 cls.nat_addr = "10.0.0.3"
Klement Sekera98d82ca2021-02-02 13:25:40 +01004289 cls.ipfix_src_port = 4739
4290 cls.ipfix_domain_id = 1
4291 cls.tcp_external_port = 80
4292 cls.udp_external_port = 69
4293
4294 cls.create_pg_interfaces(range(10))
4295 cls.interfaces = list(cls.pg_interfaces[0:4])
4296
4297 for i in cls.interfaces:
4298 i.admin_up()
4299 i.config_ip4()
4300 i.resolve_arp()
4301
4302 cls.pg0.generate_remote_hosts(3)
4303 cls.pg0.configure_ipv4_neighbors()
4304
4305 cls.pg1.generate_remote_hosts(1)
4306 cls.pg1.configure_ipv4_neighbors()
4307
4308 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Benoît Ganneff570d32024-04-16 09:36:05 +02004309 cls.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": 10})
4310 cls.vapi.ip_table_add_del_v2(is_add=1, table={"table_id": 20})
Klement Sekera98d82ca2021-02-02 13:25:40 +01004311
4312 cls.pg4._local_ip4 = "172.16.255.1"
4313 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
4314 cls.pg4.set_table_ip4(10)
4315 cls.pg5._local_ip4 = "172.17.255.3"
4316 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
4317 cls.pg5.set_table_ip4(10)
4318 cls.pg6._local_ip4 = "172.16.255.1"
4319 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
4320 cls.pg6.set_table_ip4(20)
4321 for i in cls.overlapping_interfaces:
4322 i.config_ip4()
4323 i.admin_up()
4324 i.resolve_arp()
4325
4326 cls.pg7.admin_up()
4327 cls.pg8.admin_up()
4328
4329 cls.pg9.generate_remote_hosts(2)
4330 cls.pg9.config_ip4()
4331 cls.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004332 sw_if_index=cls.pg9.sw_if_index, prefix="10.0.0.1/24"
4333 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004334
4335 cls.pg9.admin_up()
4336 cls.pg9.resolve_arp()
4337 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
4338 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
4339 cls.pg9.resolve_arp()
4340
4341 def setUp(self):
4342 super(TestNAT44EIMW, self).setUp()
Filip Varga0eaf4e62021-02-17 14:34:54 +01004343 self.vapi.nat44_ei_plugin_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004344 sessions=self.max_translations, users=self.max_users, enable=1
4345 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004346
4347 def tearDown(self):
4348 super(TestNAT44EIMW, self).tearDown()
4349 if not self.vpp_dead:
Filip Varga0eaf4e62021-02-17 14:34:54 +01004350 self.vapi.nat44_ei_ipfix_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004351 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port, enable=0
4352 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004353 self.ipfix_src_port = 4739
4354 self.ipfix_domain_id = 1
4355
Filip Varga0eaf4e62021-02-17 14:34:54 +01004356 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
Klement Sekera98d82ca2021-02-02 13:25:40 +01004357 self.vapi.cli("clear logging")
4358
4359 def test_hairpinning(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004360 """NAT44EI hairpinning - 1:1 NAPT"""
Klement Sekera98d82ca2021-02-02 13:25:40 +01004361
4362 host = self.pg0.remote_hosts[0]
4363 server = self.pg0.remote_hosts[1]
4364 host_in_port = 1234
4365 host_out_port = 0
4366 server_in_port = 5678
4367 server_out_port = 8765
4368 worker_1 = 1
4369 worker_2 = 2
4370
4371 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01004372 flags = self.config_flags.NAT44_EI_IF_INSIDE
4373 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004374 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
4375 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01004376 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004377 sw_if_index=self.pg1.sw_if_index, is_add=1
4378 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004379
4380 # add static mapping for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004381 self.nat44_add_static_mapping(
4382 server.ip4,
4383 self.nat_addr,
4384 server_in_port,
4385 server_out_port,
4386 proto=IP_PROTOS.tcp,
4387 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004388
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004389 cnt = self.statistics["/nat44-ei/hairpinning"]
Klement Sekera98d82ca2021-02-02 13:25:40 +01004390 # send packet from host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004391 p = (
4392 Ether(src=host.mac, dst=self.pg0.local_mac)
4393 / IP(src=host.ip4, dst=self.nat_addr)
4394 / TCP(sport=host_in_port, dport=server_out_port)
4395 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004396 self.pg0.add_stream(p)
4397 self.pg_enable_capture(self.pg_interfaces)
4398 self.pg_start()
4399 capture = self.pg0.get_capture(1)
4400 p = capture[0]
4401 try:
4402 ip = p[IP]
4403 tcp = p[TCP]
4404 self.assertEqual(ip.src, self.nat_addr)
4405 self.assertEqual(ip.dst, server.ip4)
4406 self.assertNotEqual(tcp.sport, host_in_port)
4407 self.assertEqual(tcp.dport, server_in_port)
4408 self.assert_packet_checksums_valid(p)
4409 host_out_port = tcp.sport
4410 except:
4411 self.logger.error(ppp("Unexpected or invalid packet:", p))
4412 raise
4413
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004414 after = self.statistics["/nat44-ei/hairpinning"]
Klement Sekera98d82ca2021-02-02 13:25:40 +01004415
4416 if_idx = self.pg0.sw_if_index
4417 self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1)
4418
4419 # send reply from server to host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004420 p = (
4421 Ether(src=server.mac, dst=self.pg0.local_mac)
4422 / IP(src=server.ip4, dst=self.nat_addr)
4423 / TCP(sport=server_in_port, dport=host_out_port)
4424 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004425 self.pg0.add_stream(p)
4426 self.pg_enable_capture(self.pg_interfaces)
4427 self.pg_start()
4428 capture = self.pg0.get_capture(1)
4429 p = capture[0]
4430 try:
4431 ip = p[IP]
4432 tcp = p[TCP]
4433 self.assertEqual(ip.src, self.nat_addr)
4434 self.assertEqual(ip.dst, host.ip4)
4435 self.assertEqual(tcp.sport, server_out_port)
4436 self.assertEqual(tcp.dport, host_in_port)
4437 self.assert_packet_checksums_valid(p)
4438 except:
4439 self.logger.error(ppp("Unexpected or invalid packet:", p))
4440 raise
4441
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004442 after = self.statistics["/nat44-ei/hairpinning"]
Klement Sekera98d82ca2021-02-02 13:25:40 +01004443 if_idx = self.pg0.sw_if_index
4444 self.assertEqual(after[worker_1][if_idx] - cnt[worker_1][if_idx], 1)
4445 self.assertEqual(after[worker_2][if_idx] - cnt[worker_2][if_idx], 2)
4446
4447 def test_hairpinning2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004448 """NAT44EI hairpinning - 1:1 NAT"""
Klement Sekera98d82ca2021-02-02 13:25:40 +01004449
4450 server1_nat_ip = "10.0.0.10"
4451 server2_nat_ip = "10.0.0.11"
4452 host = self.pg0.remote_hosts[0]
4453 server1 = self.pg0.remote_hosts[1]
4454 server2 = self.pg0.remote_hosts[2]
4455 server_tcp_port = 22
4456 server_udp_port = 20
4457
4458 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01004459 flags = self.config_flags.NAT44_EI_IF_INSIDE
4460 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004461 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
4462 )
Filip Varga0eaf4e62021-02-17 14:34:54 +01004463 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004464 sw_if_index=self.pg1.sw_if_index, is_add=1
4465 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004466
4467 # add static mapping for servers
4468 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
4469 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
4470
4471 # host to server1
4472 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004473 p = (
4474 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4475 / IP(src=host.ip4, dst=server1_nat_ip)
4476 / TCP(sport=self.tcp_port_in, dport=server_tcp_port)
4477 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004478 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004479 p = (
4480 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4481 / IP(src=host.ip4, dst=server1_nat_ip)
4482 / UDP(sport=self.udp_port_in, dport=server_udp_port)
4483 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004484 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004485 p = (
4486 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4487 / IP(src=host.ip4, dst=server1_nat_ip)
4488 / ICMP(id=self.icmp_id_in, type="echo-request")
4489 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004490 pkts.append(p)
4491 self.pg0.add_stream(pkts)
4492 self.pg_enable_capture(self.pg_interfaces)
4493 self.pg_start()
4494 capture = self.pg0.get_capture(len(pkts))
4495 for packet in capture:
4496 try:
4497 self.assertEqual(packet[IP].src, self.nat_addr)
4498 self.assertEqual(packet[IP].dst, server1.ip4)
4499 if packet.haslayer(TCP):
4500 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
4501 self.assertEqual(packet[TCP].dport, server_tcp_port)
4502 self.tcp_port_out = packet[TCP].sport
4503 self.assert_packet_checksums_valid(packet)
4504 elif packet.haslayer(UDP):
4505 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
4506 self.assertEqual(packet[UDP].dport, server_udp_port)
4507 self.udp_port_out = packet[UDP].sport
4508 else:
4509 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
4510 self.icmp_id_out = packet[ICMP].id
4511 except:
4512 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4513 raise
4514
4515 # server1 to host
4516 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004517 p = (
4518 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4519 / IP(src=server1.ip4, dst=self.nat_addr)
4520 / TCP(sport=server_tcp_port, dport=self.tcp_port_out)
4521 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004522 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004523 p = (
4524 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4525 / IP(src=server1.ip4, dst=self.nat_addr)
4526 / UDP(sport=server_udp_port, dport=self.udp_port_out)
4527 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004528 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004529 p = (
4530 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4531 / IP(src=server1.ip4, dst=self.nat_addr)
4532 / ICMP(id=self.icmp_id_out, type="echo-reply")
4533 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004534 pkts.append(p)
4535 self.pg0.add_stream(pkts)
4536 self.pg_enable_capture(self.pg_interfaces)
4537 self.pg_start()
4538 capture = self.pg0.get_capture(len(pkts))
4539 for packet in capture:
4540 try:
4541 self.assertEqual(packet[IP].src, server1_nat_ip)
4542 self.assertEqual(packet[IP].dst, host.ip4)
4543 if packet.haslayer(TCP):
4544 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4545 self.assertEqual(packet[TCP].sport, server_tcp_port)
4546 self.assert_packet_checksums_valid(packet)
4547 elif packet.haslayer(UDP):
4548 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4549 self.assertEqual(packet[UDP].sport, server_udp_port)
4550 else:
4551 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4552 except:
4553 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4554 raise
4555
4556 # server2 to server1
4557 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004558 p = (
4559 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4560 / IP(src=server2.ip4, dst=server1_nat_ip)
4561 / TCP(sport=self.tcp_port_in, dport=server_tcp_port)
4562 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004563 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004564 p = (
4565 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4566 / IP(src=server2.ip4, dst=server1_nat_ip)
4567 / UDP(sport=self.udp_port_in, dport=server_udp_port)
4568 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004569 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004570 p = (
4571 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4572 / IP(src=server2.ip4, dst=server1_nat_ip)
4573 / ICMP(id=self.icmp_id_in, type="echo-request")
4574 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004575 pkts.append(p)
4576 self.pg0.add_stream(pkts)
4577 self.pg_enable_capture(self.pg_interfaces)
4578 self.pg_start()
4579 capture = self.pg0.get_capture(len(pkts))
4580 for packet in capture:
4581 try:
4582 self.assertEqual(packet[IP].src, server2_nat_ip)
4583 self.assertEqual(packet[IP].dst, server1.ip4)
4584 if packet.haslayer(TCP):
4585 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
4586 self.assertEqual(packet[TCP].dport, server_tcp_port)
4587 self.tcp_port_out = packet[TCP].sport
4588 self.assert_packet_checksums_valid(packet)
4589 elif packet.haslayer(UDP):
4590 self.assertEqual(packet[UDP].sport, self.udp_port_in)
4591 self.assertEqual(packet[UDP].dport, server_udp_port)
4592 self.udp_port_out = packet[UDP].sport
4593 else:
4594 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4595 self.icmp_id_out = packet[ICMP].id
4596 except:
4597 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4598 raise
4599
4600 # server1 to server2
4601 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004602 p = (
4603 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4604 / IP(src=server1.ip4, dst=server2_nat_ip)
4605 / TCP(sport=server_tcp_port, dport=self.tcp_port_out)
4606 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004607 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004608 p = (
4609 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4610 / IP(src=server1.ip4, dst=server2_nat_ip)
4611 / UDP(sport=server_udp_port, dport=self.udp_port_out)
4612 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004613 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004614 p = (
4615 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
4616 / IP(src=server1.ip4, dst=server2_nat_ip)
4617 / ICMP(id=self.icmp_id_out, type="echo-reply")
4618 )
Klement Sekera98d82ca2021-02-02 13:25:40 +01004619 pkts.append(p)
4620 self.pg0.add_stream(pkts)
4621 self.pg_enable_capture(self.pg_interfaces)
4622 self.pg_start()
4623 capture = self.pg0.get_capture(len(pkts))
4624 for packet in capture:
4625 try:
4626 self.assertEqual(packet[IP].src, server1_nat_ip)
4627 self.assertEqual(packet[IP].dst, server2.ip4)
4628 if packet.haslayer(TCP):
4629 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4630 self.assertEqual(packet[TCP].sport, server_tcp_port)
4631 self.assert_packet_checksums_valid(packet)
4632 elif packet.haslayer(UDP):
4633 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4634 self.assertEqual(packet[UDP].sport, server_udp_port)
4635 else:
4636 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4637 except:
4638 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4639 raise
4640
Filip Varga0eaf4e62021-02-17 14:34:54 +01004641
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004642if __name__ == "__main__":
Filip Varga18f1e412020-12-03 15:27:40 +01004643 unittest.main(testRunner=VppTestRunner)