blob: aafd345f43f5859148de2f8e63c63cbb41061b2d [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
11from framework import VppTestCase, VppTestRunner
12from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
13from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
14 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
15 PacketListField
16from scapy.data import IP_PROTOS
17from scapy.layers.inet import IP, TCP, UDP, ICMP
18from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
19from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
20from scapy.layers.l2 import Ether, ARP, GRE
21from scapy.packet import Raw
22from syslog_rfc5424_parser import SyslogMessage, ParseError
23from syslog_rfc5424_parser.constants import SyslogSeverity
24from util import ppp
25from vpp_ip_route import VppIpRoute, VppRoutePath
26from vpp_neighbor import VppNeighbor
27from vpp_papi import VppEnum
28
29
30# NAT HA protocol event data
31class Event(Packet):
32 name = "Event"
33 fields_desc = [ByteEnumField("event_type", None,
34 {1: "add", 2: "del", 3: "refresh"}),
35 ByteEnumField("protocol", None,
36 {0: "other", 1: "udp", 2: "tcp", 3: "icmp"}),
37 ShortField("flags", 0),
38 IPField("in_addr", None),
39 IPField("out_addr", None),
40 ShortField("in_port", None),
41 ShortField("out_port", None),
42 IPField("eh_addr", None),
43 IPField("ehn_addr", None),
44 ShortField("eh_port", None),
45 ShortField("ehn_port", None),
46 IntField("fib_index", None),
47 IntField("total_pkts", 0),
48 LongField("total_bytes", 0)]
49
50 def extract_padding(self, s):
51 return "", s
52
53
54# NAT HA protocol header
55class HANATStateSync(Packet):
56 name = "HA NAT state sync"
57 fields_desc = [XByteField("version", 1),
58 FlagsField("flags", 0, 8, ['ACK']),
59 FieldLenField("count", None, count_of="events"),
60 IntField("sequence_number", 1),
61 IntField("thread_index", 0),
62 PacketListField("events", [], Event,
63 count_from=lambda pkt: pkt.count)]
64
65
66class MethodHolder(VppTestCase):
67 """ NAT create capture and verify method holder """
68
69 @property
70 def config_flags(self):
Filip Varga0eaf4e62021-02-17 14:34:54 +010071 return VppEnum.vl_api_nat44_ei_config_flags_t
Filip Varga18f1e412020-12-03 15:27:40 +010072
73 @property
74 def SYSLOG_SEVERITY(self):
75 return VppEnum.vl_api_syslog_severity_t
76
77 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
78 local_port=0, external_port=0, vrf_id=0,
79 is_add=1, external_sw_if_index=0xFFFFFFFF,
80 proto=0, tag="", flags=0):
81 """
82 Add/delete NAT44EI static mapping
83
84 :param local_ip: Local IP address
85 :param external_ip: External IP address
86 :param local_port: Local port number (Optional)
87 :param external_port: External port number (Optional)
88 :param vrf_id: VRF ID (Default 0)
89 :param is_add: 1 if add, 0 if delete (Default add)
90 :param external_sw_if_index: External interface instead of IP address
91 :param proto: IP protocol (Mandatory if port specified)
92 :param tag: Opaque string tag
93 :param flags: NAT configuration flags
94 """
95
96 if not (local_port and external_port):
Filip Varga0eaf4e62021-02-17 14:34:54 +010097 flags |= self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
Filip Varga18f1e412020-12-03 15:27:40 +010098
Filip Varga0eaf4e62021-02-17 14:34:54 +010099 self.vapi.nat44_ei_add_del_static_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +0100100 is_add=is_add,
101 local_ip_address=local_ip,
102 external_ip_address=external_ip,
103 external_sw_if_index=external_sw_if_index,
104 local_port=local_port,
105 external_port=external_port,
106 vrf_id=vrf_id, protocol=proto,
107 flags=flags,
108 tag=tag)
109
Filip Varga0eaf4e62021-02-17 14:34:54 +0100110 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF):
Filip Varga18f1e412020-12-03 15:27:40 +0100111 """
112 Add/delete NAT44EI address
113
114 :param ip: IP address
115 :param is_add: 1 if add, 0 if delete (Default add)
Filip Varga18f1e412020-12-03 15:27:40 +0100116 """
Filip Varga0eaf4e62021-02-17 14:34:54 +0100117 self.vapi.nat44_ei_add_del_address_range(first_ip_address=ip,
118 last_ip_address=ip,
119 vrf_id=vrf_id,
120 is_add=is_add)
Filip Varga18f1e412020-12-03 15:27:40 +0100121
122 def create_routes_and_neigbors(self):
123 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
124 [VppRoutePath(self.pg7.remote_ip4,
125 self.pg7.sw_if_index)])
126 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
127 [VppRoutePath(self.pg8.remote_ip4,
128 self.pg8.sw_if_index)])
129 r1.add_vpp_config()
130 r2.add_vpp_config()
131
132 n1 = VppNeighbor(self,
133 self.pg7.sw_if_index,
134 self.pg7.remote_mac,
135 self.pg7.remote_ip4,
136 is_static=1)
137 n2 = VppNeighbor(self,
138 self.pg8.sw_if_index,
139 self.pg8.remote_mac,
140 self.pg8.remote_ip4,
141 is_static=1)
142 n1.add_vpp_config()
143 n2.add_vpp_config()
144
145 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
146 """
147 Create packet stream for inside network
148
149 :param in_if: Inside interface
150 :param out_if: Outside interface
151 :param dst_ip: Destination address
152 :param ttl: TTL of generated packets
153 """
154 if dst_ip is None:
155 dst_ip = out_if.remote_ip4
156
157 pkts = []
158 # TCP
159 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
160 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
161 TCP(sport=self.tcp_port_in, dport=20))
162 pkts.extend([p, p])
163
164 # UDP
165 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
166 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
167 UDP(sport=self.udp_port_in, dport=20))
168 pkts.append(p)
169
170 # ICMP
171 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
172 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
173 ICMP(id=self.icmp_id_in, type='echo-request'))
174 pkts.append(p)
175
176 return pkts
177
178 def compose_ip6(self, ip4, pref, plen):
179 """
180 Compose IPv4-embedded IPv6 addresses
181
182 :param ip4: IPv4 address
183 :param pref: IPv6 prefix
184 :param plen: IPv6 prefix length
185 :returns: IPv4-embedded IPv6 addresses
186 """
187 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
188 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
189 if plen == 32:
190 pref_n[4] = ip4_n[0]
191 pref_n[5] = ip4_n[1]
192 pref_n[6] = ip4_n[2]
193 pref_n[7] = ip4_n[3]
194 elif plen == 40:
195 pref_n[5] = ip4_n[0]
196 pref_n[6] = ip4_n[1]
197 pref_n[7] = ip4_n[2]
198 pref_n[9] = ip4_n[3]
199 elif plen == 48:
200 pref_n[6] = ip4_n[0]
201 pref_n[7] = ip4_n[1]
202 pref_n[9] = ip4_n[2]
203 pref_n[10] = ip4_n[3]
204 elif plen == 56:
205 pref_n[7] = ip4_n[0]
206 pref_n[9] = ip4_n[1]
207 pref_n[10] = ip4_n[2]
208 pref_n[11] = ip4_n[3]
209 elif plen == 64:
210 pref_n[9] = ip4_n[0]
211 pref_n[10] = ip4_n[1]
212 pref_n[11] = ip4_n[2]
213 pref_n[12] = ip4_n[3]
214 elif plen == 96:
215 pref_n[12] = ip4_n[0]
216 pref_n[13] = ip4_n[1]
217 pref_n[14] = ip4_n[2]
218 pref_n[15] = ip4_n[3]
219 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
220 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
221
222 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
223 use_inside_ports=False):
224 """
225 Create packet stream for outside network
226
227 :param out_if: Outside interface
228 :param dst_ip: Destination IP address (Default use global NAT address)
229 :param ttl: TTL of generated packets
230 :param use_inside_ports: Use inside NAT ports as destination ports
231 instead of outside ports
232 """
233 if dst_ip is None:
234 dst_ip = self.nat_addr
235 if not use_inside_ports:
236 tcp_port = self.tcp_port_out
237 udp_port = self.udp_port_out
238 icmp_id = self.icmp_id_out
239 else:
240 tcp_port = self.tcp_port_in
241 udp_port = self.udp_port_in
242 icmp_id = self.icmp_id_in
243 pkts = []
244 # TCP
245 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
246 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
247 TCP(dport=tcp_port, sport=20))
248 pkts.extend([p, p])
249
250 # UDP
251 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
252 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
253 UDP(dport=udp_port, sport=20))
254 pkts.append(p)
255
256 # ICMP
257 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
258 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
259 ICMP(id=icmp_id, type='echo-reply'))
260 pkts.append(p)
261
262 return pkts
263
264 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
265 """
266 Create packet stream for outside network
267
268 :param out_if: Outside interface
269 :param dst_ip: Destination IP address (Default use global NAT address)
270 :param hl: HL of generated packets
271 """
272 pkts = []
273 # TCP
274 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
275 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
276 TCP(dport=self.tcp_port_out, sport=20))
277 pkts.append(p)
278
279 # UDP
280 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
281 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
282 UDP(dport=self.udp_port_out, sport=20))
283 pkts.append(p)
284
285 # ICMP
286 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
287 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
288 ICMPv6EchoReply(id=self.icmp_id_out))
289 pkts.append(p)
290
291 return pkts
292
293 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
294 dst_ip=None, is_ip6=False, ignore_port=False):
295 """
296 Verify captured packets on outside network
297
298 :param capture: Captured packets
299 :param nat_ip: Translated IP address (Default use global NAT address)
300 :param same_port: Source port number is not translated (Default False)
301 :param dst_ip: Destination IP address (Default do not verify)
302 :param is_ip6: If L3 protocol is IPv6 (Default False)
303 """
304 if is_ip6:
305 IP46 = IPv6
306 ICMP46 = ICMPv6EchoRequest
307 else:
308 IP46 = IP
309 ICMP46 = ICMP
310 if nat_ip is None:
311 nat_ip = self.nat_addr
312 for packet in capture:
313 try:
314 if not is_ip6:
315 self.assert_packet_checksums_valid(packet)
316 self.assertEqual(packet[IP46].src, nat_ip)
317 if dst_ip is not None:
318 self.assertEqual(packet[IP46].dst, dst_ip)
319 if packet.haslayer(TCP):
320 if not ignore_port:
321 if same_port:
322 self.assertEqual(
323 packet[TCP].sport, self.tcp_port_in)
324 else:
325 self.assertNotEqual(
326 packet[TCP].sport, self.tcp_port_in)
327 self.tcp_port_out = packet[TCP].sport
328 self.assert_packet_checksums_valid(packet)
329 elif packet.haslayer(UDP):
330 if not ignore_port:
331 if same_port:
332 self.assertEqual(
333 packet[UDP].sport, self.udp_port_in)
334 else:
335 self.assertNotEqual(
336 packet[UDP].sport, self.udp_port_in)
337 self.udp_port_out = packet[UDP].sport
338 else:
339 if not ignore_port:
340 if same_port:
341 self.assertEqual(
342 packet[ICMP46].id, self.icmp_id_in)
343 else:
344 self.assertNotEqual(
345 packet[ICMP46].id, self.icmp_id_in)
346 self.icmp_id_out = packet[ICMP46].id
347 self.assert_packet_checksums_valid(packet)
348 except:
349 self.logger.error(ppp("Unexpected or invalid packet "
350 "(outside network):", packet))
351 raise
352
353 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
354 dst_ip=None):
355 """
356 Verify captured packets on outside network
357
358 :param capture: Captured packets
359 :param nat_ip: Translated IP address
360 :param same_port: Source port number is not translated (Default False)
361 :param dst_ip: Destination IP address (Default do not verify)
362 """
363 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
364 True)
365
366 def verify_capture_in(self, capture, in_if):
367 """
368 Verify captured packets on inside network
369
370 :param capture: Captured packets
371 :param in_if: Inside interface
372 """
373 for packet in capture:
374 try:
375 self.assert_packet_checksums_valid(packet)
376 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
377 if packet.haslayer(TCP):
378 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
379 elif packet.haslayer(UDP):
380 self.assertEqual(packet[UDP].dport, self.udp_port_in)
381 else:
382 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
383 except:
384 self.logger.error(ppp("Unexpected or invalid packet "
385 "(inside network):", packet))
386 raise
387
388 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
389 """
390 Verify captured packet that don't have to be translated
391
392 :param capture: Captured packets
393 :param ingress_if: Ingress interface
394 :param egress_if: Egress interface
395 """
396 for packet in capture:
397 try:
398 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
399 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
400 if packet.haslayer(TCP):
401 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
402 elif packet.haslayer(UDP):
403 self.assertEqual(packet[UDP].sport, self.udp_port_in)
404 else:
405 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
406 except:
407 self.logger.error(ppp("Unexpected or invalid packet "
408 "(inside network):", packet))
409 raise
410
411 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
412 icmp_type=11):
413 """
414 Verify captured packets with ICMP errors on outside network
415
416 :param capture: Captured packets
417 :param src_ip: Translated IP address or IP address of VPP
418 (Default use global NAT address)
419 :param icmp_type: Type of error ICMP packet
420 we are expecting (Default 11)
421 """
422 if src_ip is None:
423 src_ip = self.nat_addr
424 for packet in capture:
425 try:
426 self.assertEqual(packet[IP].src, src_ip)
427 self.assertEqual(packet.haslayer(ICMP), 1)
428 icmp = packet[ICMP]
429 self.assertEqual(icmp.type, icmp_type)
430 self.assertTrue(icmp.haslayer(IPerror))
431 inner_ip = icmp[IPerror]
432 if inner_ip.haslayer(TCPerror):
433 self.assertEqual(inner_ip[TCPerror].dport,
434 self.tcp_port_out)
435 elif inner_ip.haslayer(UDPerror):
436 self.assertEqual(inner_ip[UDPerror].dport,
437 self.udp_port_out)
438 else:
439 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
440 except:
441 self.logger.error(ppp("Unexpected or invalid packet "
442 "(outside network):", packet))
443 raise
444
445 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
446 """
447 Verify captured packets with ICMP errors on inside network
448
449 :param capture: Captured packets
450 :param in_if: Inside interface
451 :param icmp_type: Type of error ICMP packet
452 we are expecting (Default 11)
453 """
454 for packet in capture:
455 try:
456 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
457 self.assertEqual(packet.haslayer(ICMP), 1)
458 icmp = packet[ICMP]
459 self.assertEqual(icmp.type, icmp_type)
460 self.assertTrue(icmp.haslayer(IPerror))
461 inner_ip = icmp[IPerror]
462 if inner_ip.haslayer(TCPerror):
463 self.assertEqual(inner_ip[TCPerror].sport,
464 self.tcp_port_in)
465 elif inner_ip.haslayer(UDPerror):
466 self.assertEqual(inner_ip[UDPerror].sport,
467 self.udp_port_in)
468 else:
469 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
470 except:
471 self.logger.error(ppp("Unexpected or invalid packet "
472 "(inside network):", packet))
473 raise
474
475 def create_stream_frag(self, src_if, dst, sport, dport, data,
476 proto=IP_PROTOS.tcp, echo_reply=False):
477 """
478 Create fragmented packet stream
479
480 :param src_if: Source interface
481 :param dst: Destination IPv4 address
482 :param sport: Source port
483 :param dport: Destination port
484 :param data: Payload data
485 :param proto: protocol (TCP, UDP, ICMP)
486 :param echo_reply: use echo_reply if protocol is ICMP
487 :returns: Fragments
488 """
489 if proto == IP_PROTOS.tcp:
490 p = (IP(src=src_if.remote_ip4, dst=dst) /
491 TCP(sport=sport, dport=dport) /
492 Raw(data))
493 p = p.__class__(scapy.compat.raw(p))
494 chksum = p[TCP].chksum
495 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
496 elif proto == IP_PROTOS.udp:
497 proto_header = UDP(sport=sport, dport=dport)
498 elif proto == IP_PROTOS.icmp:
499 if not echo_reply:
500 proto_header = ICMP(id=sport, type='echo-request')
501 else:
502 proto_header = ICMP(id=sport, type='echo-reply')
503 else:
504 raise Exception("Unsupported protocol")
505 id = random.randint(0, 65535)
506 pkts = []
507 if proto == IP_PROTOS.tcp:
508 raw = Raw(data[0:4])
509 else:
510 raw = Raw(data[0:16])
511 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
512 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
513 proto_header /
514 raw)
515 pkts.append(p)
516 if proto == IP_PROTOS.tcp:
517 raw = Raw(data[4:20])
518 else:
519 raw = Raw(data[16:32])
520 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
521 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
522 proto=proto) /
523 raw)
524 pkts.append(p)
525 if proto == IP_PROTOS.tcp:
526 raw = Raw(data[20:])
527 else:
528 raw = Raw(data[32:])
529 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
530 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
531 id=id) /
532 raw)
533 pkts.append(p)
534 return pkts
535
536 def reass_frags_and_verify(self, frags, src, dst):
537 """
538 Reassemble and verify fragmented packet
539
540 :param frags: Captured fragments
541 :param src: Source IPv4 address to verify
542 :param dst: Destination IPv4 address to verify
543
544 :returns: Reassembled IPv4 packet
545 """
546 buffer = BytesIO()
547 for p in frags:
548 self.assertEqual(p[IP].src, src)
549 self.assertEqual(p[IP].dst, dst)
550 self.assert_ip_checksum_valid(p)
551 buffer.seek(p[IP].frag * 8)
552 buffer.write(bytes(p[IP].payload))
553 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
554 proto=frags[0][IP].proto)
555 if ip.proto == IP_PROTOS.tcp:
556 p = (ip / TCP(buffer.getvalue()))
557 self.logger.debug(ppp("Reassembled:", p))
558 self.assert_tcp_checksum_valid(p)
559 elif ip.proto == IP_PROTOS.udp:
560 p = (ip / UDP(buffer.getvalue()[:8]) /
561 Raw(buffer.getvalue()[8:]))
562 elif ip.proto == IP_PROTOS.icmp:
563 p = (ip / ICMP(buffer.getvalue()))
564 return p
565
566 def verify_ipfix_nat44_ses(self, data):
567 """
568 Verify IPFIX NAT44EI session create/delete event
569
570 :param data: Decoded IPFIX data records
571 """
572 nat44_ses_create_num = 0
573 nat44_ses_delete_num = 0
574 self.assertEqual(6, len(data))
575 for record in data:
576 # natEvent
577 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
578 if scapy.compat.orb(record[230]) == 4:
579 nat44_ses_create_num += 1
580 else:
581 nat44_ses_delete_num += 1
582 # sourceIPv4Address
583 self.assertEqual(self.pg0.remote_ip4,
584 str(ipaddress.IPv4Address(record[8])))
585 # postNATSourceIPv4Address
586 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
587 record[225])
588 # ingressVRFID
589 self.assertEqual(struct.pack("!I", 0), record[234])
590 # protocolIdentifier/sourceTransportPort
591 # /postNAPTSourceTransportPort
592 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
593 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
594 self.assertEqual(struct.pack("!H", self.icmp_id_out),
595 record[227])
596 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
597 self.assertEqual(struct.pack("!H", self.tcp_port_in),
598 record[7])
599 self.assertEqual(struct.pack("!H", self.tcp_port_out),
600 record[227])
601 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
602 self.assertEqual(struct.pack("!H", self.udp_port_in),
603 record[7])
604 self.assertEqual(struct.pack("!H", self.udp_port_out),
605 record[227])
606 else:
Klement Sekeraff334db2021-05-26 13:02:35 +0200607 self.fail(f"Invalid protocol {scapy.compat.orb(record[4])}")
Filip Varga18f1e412020-12-03 15:27:40 +0100608 self.assertEqual(3, nat44_ses_create_num)
609 self.assertEqual(3, nat44_ses_delete_num)
610
611 def verify_ipfix_addr_exhausted(self, data):
612 self.assertEqual(1, len(data))
613 record = data[0]
614 # natEvent
615 self.assertEqual(scapy.compat.orb(record[230]), 3)
616 # natPoolID
617 self.assertEqual(struct.pack("!I", 0), record[283])
618
619 def verify_ipfix_max_sessions(self, data, limit):
620 self.assertEqual(1, len(data))
621 record = data[0]
622 # natEvent
623 self.assertEqual(scapy.compat.orb(record[230]), 13)
624 # natQuotaExceededEvent
Matthew Smithe3f078f2020-11-04 11:18:10 -0600625 self.assertEqual(struct.pack("!I", 1), record[466])
Filip Varga18f1e412020-12-03 15:27:40 +0100626 # maxSessionEntries
Matthew Smithe3f078f2020-11-04 11:18:10 -0600627 self.assertEqual(struct.pack("!I", limit), record[471])
Filip Varga18f1e412020-12-03 15:27:40 +0100628
629 def verify_no_nat44_user(self):
630 """ Verify that there is no NAT44EI user """
Filip Varga0eaf4e62021-02-17 14:34:54 +0100631 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +0100632 self.assertEqual(len(users), 0)
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100633 users = self.statistics['/nat44-ei/total-users']
Filip Varga18f1e412020-12-03 15:27:40 +0100634 self.assertEqual(users[0][0], 0)
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100635 sessions = self.statistics['/nat44-ei/total-sessions']
Filip Varga18f1e412020-12-03 15:27:40 +0100636 self.assertEqual(sessions[0][0], 0)
637
638 def verify_syslog_apmap(self, data, is_add=True):
639 message = data.decode('utf-8')
640 try:
641 message = SyslogMessage.parse(message)
642 except ParseError as e:
643 self.logger.error(e)
644 raise
645 else:
646 self.assertEqual(message.severity, SyslogSeverity.info)
647 self.assertEqual(message.appname, 'NAT')
648 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
649 sd_params = message.sd.get('napmap')
650 self.assertTrue(sd_params is not None)
651 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
652 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
653 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
654 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
655 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
656 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
657 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
658 self.assertTrue(sd_params.get('SSUBIX') is not None)
659 self.assertEqual(sd_params.get('SVLAN'), '0')
660
661 def verify_mss_value(self, pkt, mss):
662 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
663 raise TypeError("Not a TCP/IP packet")
664
665 for option in pkt[TCP].options:
666 if option[0] == 'MSS':
667 self.assertEqual(option[1], mss)
668 self.assert_tcp_checksum_valid(pkt)
669
670 @staticmethod
671 def proto2layer(proto):
672 if proto == IP_PROTOS.tcp:
673 return TCP
674 elif proto == IP_PROTOS.udp:
675 return UDP
676 elif proto == IP_PROTOS.icmp:
677 return ICMP
678 else:
679 raise Exception("Unsupported protocol")
680
681 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
682 ignore_port=False):
683 layer = self.proto2layer(proto)
684
685 if proto == IP_PROTOS.tcp:
686 data = b"A" * 4 + b"B" * 16 + b"C" * 3
687 else:
688 data = b"A" * 16 + b"B" * 16 + b"C" * 3
689 self.port_in = random.randint(1025, 65535)
690
691 # in2out
692 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
693 self.port_in, 20, data, proto)
694 self.pg0.add_stream(pkts)
695 self.pg_enable_capture(self.pg_interfaces)
696 self.pg_start()
697 frags = self.pg1.get_capture(len(pkts))
698 if not dont_translate:
699 p = self.reass_frags_and_verify(frags,
700 self.nat_addr,
701 self.pg1.remote_ip4)
702 else:
703 p = self.reass_frags_and_verify(frags,
704 self.pg0.remote_ip4,
705 self.pg1.remote_ip4)
706 if proto != IP_PROTOS.icmp:
707 if not dont_translate:
708 self.assertEqual(p[layer].dport, 20)
709 if not ignore_port:
710 self.assertNotEqual(p[layer].sport, self.port_in)
711 else:
712 self.assertEqual(p[layer].sport, self.port_in)
713 else:
714 if not ignore_port:
715 if not dont_translate:
716 self.assertNotEqual(p[layer].id, self.port_in)
717 else:
718 self.assertEqual(p[layer].id, self.port_in)
719 self.assertEqual(data, p[Raw].load)
720
721 # out2in
722 if not dont_translate:
723 dst_addr = self.nat_addr
724 else:
725 dst_addr = self.pg0.remote_ip4
726 if proto != IP_PROTOS.icmp:
727 sport = 20
728 dport = p[layer].sport
729 else:
730 sport = p[layer].id
731 dport = 0
732 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
733 proto, echo_reply=True)
734 self.pg1.add_stream(pkts)
735 self.pg_enable_capture(self.pg_interfaces)
736 self.pg_start()
737 frags = self.pg0.get_capture(len(pkts))
738 p = self.reass_frags_and_verify(frags,
739 self.pg1.remote_ip4,
740 self.pg0.remote_ip4)
741 if proto != IP_PROTOS.icmp:
742 self.assertEqual(p[layer].sport, 20)
743 self.assertEqual(p[layer].dport, self.port_in)
744 else:
745 self.assertEqual(p[layer].id, self.port_in)
746 self.assertEqual(data, p[Raw].load)
747
748 def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
749 host_in_port, proto=IP_PROTOS.tcp,
750 ignore_port=False):
751
752 layer = self.proto2layer(proto)
753
754 if proto == IP_PROTOS.tcp:
755 data = b"A" * 4 + b"B" * 16 + b"C" * 3
756 else:
757 data = b"A" * 16 + b"B" * 16 + b"C" * 3
758
759 # send packet from host to server
760 pkts = self.create_stream_frag(self.pg0,
761 self.nat_addr,
762 host_in_port,
763 server_out_port,
764 data,
765 proto)
766 self.pg0.add_stream(pkts)
767 self.pg_enable_capture(self.pg_interfaces)
768 self.pg_start()
769 frags = self.pg0.get_capture(len(pkts))
770 p = self.reass_frags_and_verify(frags,
771 self.nat_addr,
772 server_addr)
773 if proto != IP_PROTOS.icmp:
774 if not ignore_port:
775 self.assertNotEqual(p[layer].sport, host_in_port)
776 self.assertEqual(p[layer].dport, server_in_port)
777 else:
778 if not ignore_port:
779 self.assertNotEqual(p[layer].id, host_in_port)
780 self.assertEqual(data, p[Raw].load)
781
782 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
783 ignore_port=False):
784 layer = self.proto2layer(proto)
785
786 if proto == IP_PROTOS.tcp:
787 data = b"A" * 4 + b"B" * 16 + b"C" * 3
788 else:
789 data = b"A" * 16 + b"B" * 16 + b"C" * 3
790 self.port_in = random.randint(1025, 65535)
791
792 for i in range(2):
793 # in2out
794 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
795 self.port_in, 20, data, proto)
796 pkts.reverse()
797 self.pg0.add_stream(pkts)
798 self.pg_enable_capture(self.pg_interfaces)
799 self.pg_start()
800 frags = self.pg1.get_capture(len(pkts))
801 if not dont_translate:
802 p = self.reass_frags_and_verify(frags,
803 self.nat_addr,
804 self.pg1.remote_ip4)
805 else:
806 p = self.reass_frags_and_verify(frags,
807 self.pg0.remote_ip4,
808 self.pg1.remote_ip4)
809 if proto != IP_PROTOS.icmp:
810 if not dont_translate:
811 self.assertEqual(p[layer].dport, 20)
812 if not ignore_port:
813 self.assertNotEqual(p[layer].sport, self.port_in)
814 else:
815 self.assertEqual(p[layer].sport, self.port_in)
816 else:
817 if not ignore_port:
818 if not dont_translate:
819 self.assertNotEqual(p[layer].id, self.port_in)
820 else:
821 self.assertEqual(p[layer].id, self.port_in)
822 self.assertEqual(data, p[Raw].load)
823
824 # out2in
825 if not dont_translate:
826 dst_addr = self.nat_addr
827 else:
828 dst_addr = self.pg0.remote_ip4
829 if proto != IP_PROTOS.icmp:
830 sport = 20
831 dport = p[layer].sport
832 else:
833 sport = p[layer].id
834 dport = 0
835 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
836 data, proto, echo_reply=True)
837 pkts.reverse()
838 self.pg1.add_stream(pkts)
839 self.pg_enable_capture(self.pg_interfaces)
840 self.pg_start()
841 frags = self.pg0.get_capture(len(pkts))
842 p = self.reass_frags_and_verify(frags,
843 self.pg1.remote_ip4,
844 self.pg0.remote_ip4)
845 if proto != IP_PROTOS.icmp:
846 self.assertEqual(p[layer].sport, 20)
847 self.assertEqual(p[layer].dport, self.port_in)
848 else:
849 self.assertEqual(p[layer].id, self.port_in)
850 self.assertEqual(data, p[Raw].load)
851
852
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100853def get_nat44_ei_in2out_worker_index(ip, vpp_worker_count):
854 if 0 == vpp_worker_count:
855 return 0
856 numeric = socket.inet_aton(ip)
857 numeric = struct.unpack("!L", numeric)[0]
858 numeric = socket.htonl(numeric)
859 h = numeric + (numeric >> 8) + (numeric >> 16) + (numeric >> 24)
860 return 1 + h % vpp_worker_count
861
862
Filip Varga18f1e412020-12-03 15:27:40 +0100863class TestNAT44EI(MethodHolder):
864 """ NAT44EI Test Cases """
865
866 max_translations = 10240
867 max_users = 10240
868
869 @classmethod
870 def setUpClass(cls):
871 super(TestNAT44EI, cls).setUpClass()
Filip Varga0eaf4e62021-02-17 14:34:54 +0100872 cls.vapi.cli("set log class nat44-ei level debug")
Filip Varga18f1e412020-12-03 15:27:40 +0100873
874 cls.tcp_port_in = 6303
875 cls.tcp_port_out = 6303
876 cls.udp_port_in = 6304
877 cls.udp_port_out = 6304
878 cls.icmp_id_in = 6305
879 cls.icmp_id_out = 6305
880 cls.nat_addr = '10.0.0.3'
881 cls.ipfix_src_port = 4739
882 cls.ipfix_domain_id = 1
883 cls.tcp_external_port = 80
884 cls.udp_external_port = 69
885
886 cls.create_pg_interfaces(range(10))
887 cls.interfaces = list(cls.pg_interfaces[0:4])
888
889 for i in cls.interfaces:
890 i.admin_up()
891 i.config_ip4()
892 i.resolve_arp()
893
894 cls.pg0.generate_remote_hosts(3)
895 cls.pg0.configure_ipv4_neighbors()
896
897 cls.pg1.generate_remote_hosts(1)
898 cls.pg1.configure_ipv4_neighbors()
899
900 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
901 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
902 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
903
904 cls.pg4._local_ip4 = "172.16.255.1"
905 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
906 cls.pg4.set_table_ip4(10)
907 cls.pg5._local_ip4 = "172.17.255.3"
908 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
909 cls.pg5.set_table_ip4(10)
910 cls.pg6._local_ip4 = "172.16.255.1"
911 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
912 cls.pg6.set_table_ip4(20)
913 for i in cls.overlapping_interfaces:
914 i.config_ip4()
915 i.admin_up()
916 i.resolve_arp()
917
918 cls.pg7.admin_up()
919 cls.pg8.admin_up()
920
921 cls.pg9.generate_remote_hosts(2)
922 cls.pg9.config_ip4()
923 cls.vapi.sw_interface_add_del_address(
924 sw_if_index=cls.pg9.sw_if_index,
925 prefix="10.0.0.1/24")
926
927 cls.pg9.admin_up()
928 cls.pg9.resolve_arp()
929 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
930 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
931 cls.pg9.resolve_arp()
932
Filip Varga0eaf4e62021-02-17 14:34:54 +0100933 def plugin_enable(self):
934 self.vapi.nat44_ei_plugin_enable_disable(
Filip Varga18f1e412020-12-03 15:27:40 +0100935 sessions=self.max_translations,
936 users=self.max_users, enable=1)
937
Filip Varga0eaf4e62021-02-17 14:34:54 +0100938 def setUp(self):
939 super(TestNAT44EI, self).setUp()
940 self.plugin_enable()
941
Filip Varga18f1e412020-12-03 15:27:40 +0100942 def tearDown(self):
943 super(TestNAT44EI, self).tearDown()
944 if not self.vpp_dead:
Filip Varga0eaf4e62021-02-17 14:34:54 +0100945 self.vapi.nat44_ei_ipfix_enable_disable(
946 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port,
947 enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +0100948 self.ipfix_src_port = 4739
949 self.ipfix_domain_id = 1
950
Filip Varga0eaf4e62021-02-17 14:34:54 +0100951 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +0100952 self.vapi.cli("clear logging")
953
954 def test_clear_sessions(self):
955 """ NAT44EI session clearing test """
956
957 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +0100958 flags = self.config_flags.NAT44_EI_IF_INSIDE
959 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +0100960 sw_if_index=self.pg0.sw_if_index,
961 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +0100962 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +0100963 sw_if_index=self.pg1.sw_if_index,
964 is_add=1)
965
Filip Varga18f1e412020-12-03 15:27:40 +0100966 pkts = self.create_stream_in(self.pg0, self.pg1)
967 self.pg0.add_stream(pkts)
968 self.pg_enable_capture(self.pg_interfaces)
969 self.pg_start()
970 capture = self.pg1.get_capture(len(pkts))
971 self.verify_capture_out(capture)
972
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100973 sessions = self.statistics['/nat44-ei/total-sessions']
974 self.assertGreater(sessions[:, 0].sum(), 0, "Session count invalid")
Filip Varga18f1e412020-12-03 15:27:40 +0100975 self.logger.info("sessions before clearing: %s" % sessions[0][0])
976
Filip Varga0eaf4e62021-02-17 14:34:54 +0100977 self.vapi.cli("clear nat44 ei sessions")
Filip Varga18f1e412020-12-03 15:27:40 +0100978
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100979 sessions = self.statistics['/nat44-ei/total-sessions']
980 self.assertEqual(sessions[:, 0].sum(), 0, "Session count invalid")
Filip Varga18f1e412020-12-03 15:27:40 +0100981 self.logger.info("sessions after clearing: %s" % sessions[0][0])
982
983 def test_dynamic(self):
984 """ NAT44EI dynamic translation test """
985 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +0100986 flags = self.config_flags.NAT44_EI_IF_INSIDE
987 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +0100988 sw_if_index=self.pg0.sw_if_index,
989 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +0100990 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +0100991 sw_if_index=self.pg1.sw_if_index,
992 is_add=1)
993
994 # in2out
Klement Sekeraeafb5db2021-03-15 16:34:01 +0100995 tcpn = self.statistics['/nat44-ei/in2out/slowpath/tcp']
996 udpn = self.statistics['/nat44-ei/in2out/slowpath/udp']
997 icmpn = self.statistics['/nat44-ei/in2out/slowpath/icmp']
998 drops = self.statistics['/nat44-ei/in2out/slowpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +0100999
1000 pkts = self.create_stream_in(self.pg0, self.pg1)
1001 self.pg0.add_stream(pkts)
1002 self.pg_enable_capture(self.pg_interfaces)
1003 self.pg_start()
1004 capture = self.pg1.get_capture(len(pkts))
1005 self.verify_capture_out(capture)
1006
1007 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001008 cnt = self.statistics['/nat44-ei/in2out/slowpath/tcp']
1009 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
1010 cnt = self.statistics['/nat44-ei/in2out/slowpath/udp']
1011 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
1012 cnt = self.statistics['/nat44-ei/in2out/slowpath/icmp']
1013 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
1014 cnt = self.statistics['/nat44-ei/in2out/slowpath/drops']
1015 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001016
1017 # out2in
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001018 tcpn = self.statistics['/nat44-ei/out2in/slowpath/tcp']
1019 udpn = self.statistics['/nat44-ei/out2in/slowpath/udp']
1020 icmpn = self.statistics['/nat44-ei/out2in/slowpath/icmp']
1021 drops = self.statistics['/nat44-ei/out2in/slowpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01001022
1023 pkts = self.create_stream_out(self.pg1)
1024 self.pg1.add_stream(pkts)
1025 self.pg_enable_capture(self.pg_interfaces)
1026 self.pg_start()
1027 capture = self.pg0.get_capture(len(pkts))
1028 self.verify_capture_in(capture, self.pg0)
1029
1030 if_idx = self.pg1.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001031 cnt = self.statistics['/nat44-ei/out2in/slowpath/tcp']
1032 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
1033 cnt = self.statistics['/nat44-ei/out2in/slowpath/udp']
1034 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
1035 cnt = self.statistics['/nat44-ei/out2in/slowpath/icmp']
1036 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
1037 cnt = self.statistics['/nat44-ei/out2in/slowpath/drops']
1038 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001039
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001040 users = self.statistics['/nat44-ei/total-users']
1041 self.assertEqual(users[:, 0].sum(), 1)
1042 sessions = self.statistics['/nat44-ei/total-sessions']
1043 self.assertEqual(sessions[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01001044
1045 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1046 """ NAT44EI handling of client packets with TTL=1 """
1047
1048 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001049 flags = self.config_flags.NAT44_EI_IF_INSIDE
1050 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001051 sw_if_index=self.pg0.sw_if_index,
1052 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001053 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001054 sw_if_index=self.pg1.sw_if_index,
1055 is_add=1)
1056
1057 # Client side - generate traffic
1058 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001059 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01001060
1061 # Client side - verify ICMP type 11 packets
Filip Varga18f1e412020-12-03 15:27:40 +01001062 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1063
1064 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1065 """ NAT44EI handling of server packets with TTL=1 """
1066
1067 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001068 flags = self.config_flags.NAT44_EI_IF_INSIDE
1069 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001070 sw_if_index=self.pg0.sw_if_index,
1071 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001072 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001073 sw_if_index=self.pg1.sw_if_index,
1074 is_add=1)
1075
1076 # Client side - create sessions
1077 pkts = self.create_stream_in(self.pg0, self.pg1)
1078 self.pg0.add_stream(pkts)
1079 self.pg_enable_capture(self.pg_interfaces)
1080 self.pg_start()
1081
1082 # Server side - generate traffic
1083 capture = self.pg1.get_capture(len(pkts))
1084 self.verify_capture_out(capture)
1085 pkts = self.create_stream_out(self.pg1, ttl=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001086 capture = self.send_and_expect_some(self.pg1, pkts, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01001087
1088 # Server side - verify ICMP type 11 packets
Filip Varga18f1e412020-12-03 15:27:40 +01001089 self.verify_capture_out_with_icmp_errors(capture,
1090 src_ip=self.pg1.local_ip4)
1091
1092 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1093 """ NAT44EI handling of error responses to client packets with TTL=2
1094 """
1095
1096 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001097 flags = self.config_flags.NAT44_EI_IF_INSIDE
1098 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001099 sw_if_index=self.pg0.sw_if_index,
1100 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001101 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001102 sw_if_index=self.pg1.sw_if_index,
1103 is_add=1)
1104
1105 # Client side - generate traffic
1106 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1107 self.pg0.add_stream(pkts)
1108 self.pg_enable_capture(self.pg_interfaces)
1109 self.pg_start()
1110
1111 # Server side - simulate ICMP type 11 response
1112 capture = self.pg1.get_capture(len(pkts))
1113 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1114 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1115 ICMP(type=11) / packet[IP] for packet in capture]
1116 self.pg1.add_stream(pkts)
1117 self.pg_enable_capture(self.pg_interfaces)
1118 self.pg_start()
1119
1120 # Client side - verify ICMP type 11 packets
1121 capture = self.pg0.get_capture(len(pkts))
1122 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1123
1124 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1125 """ NAT44EI handling of error responses to server packets with TTL=2
1126 """
1127
1128 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001129 flags = self.config_flags.NAT44_EI_IF_INSIDE
1130 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001131 sw_if_index=self.pg0.sw_if_index,
1132 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001133 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001134 sw_if_index=self.pg1.sw_if_index,
1135 is_add=1)
1136
1137 # Client side - create sessions
1138 pkts = self.create_stream_in(self.pg0, self.pg1)
1139 self.pg0.add_stream(pkts)
1140 self.pg_enable_capture(self.pg_interfaces)
1141 self.pg_start()
1142
1143 # Server side - generate traffic
1144 capture = self.pg1.get_capture(len(pkts))
1145 self.verify_capture_out(capture)
1146 pkts = self.create_stream_out(self.pg1, ttl=2)
1147 self.pg1.add_stream(pkts)
1148 self.pg_enable_capture(self.pg_interfaces)
1149 self.pg_start()
1150
1151 # Client side - simulate ICMP type 11 response
1152 capture = self.pg0.get_capture(len(pkts))
1153 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1154 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1155 ICMP(type=11) / packet[IP] for packet in capture]
1156 self.pg0.add_stream(pkts)
1157 self.pg_enable_capture(self.pg_interfaces)
1158 self.pg_start()
1159
1160 # Server side - verify ICMP type 11 packets
1161 capture = self.pg1.get_capture(len(pkts))
1162 self.verify_capture_out_with_icmp_errors(capture)
1163
1164 def test_ping_out_interface_from_outside(self):
1165 """ NAT44EI ping out interface from outside network """
1166
1167 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001168 flags = self.config_flags.NAT44_EI_IF_INSIDE
1169 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001170 sw_if_index=self.pg0.sw_if_index,
1171 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001172 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001173 sw_if_index=self.pg1.sw_if_index,
1174 is_add=1)
1175
1176 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1177 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1178 ICMP(id=self.icmp_id_out, type='echo-request'))
1179 pkts = [p]
1180 self.pg1.add_stream(pkts)
1181 self.pg_enable_capture(self.pg_interfaces)
1182 self.pg_start()
1183 capture = self.pg1.get_capture(len(pkts))
1184 packet = capture[0]
1185 try:
1186 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1187 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1188 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1189 self.assertEqual(packet[ICMP].type, 0) # echo reply
1190 except:
1191 self.logger.error(ppp("Unexpected or invalid packet "
1192 "(outside network):", packet))
1193 raise
1194
1195 def test_ping_internal_host_from_outside(self):
1196 """ NAT44EI ping internal host from outside network """
1197
1198 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001199 flags = self.config_flags.NAT44_EI_IF_INSIDE
1200 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001201 sw_if_index=self.pg0.sw_if_index,
1202 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001203 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001204 sw_if_index=self.pg1.sw_if_index,
1205 is_add=1)
1206
1207 # out2in
1208 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1209 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1210 ICMP(id=self.icmp_id_out, type='echo-request'))
1211 self.pg1.add_stream(pkt)
1212 self.pg_enable_capture(self.pg_interfaces)
1213 self.pg_start()
1214 capture = self.pg0.get_capture(1)
1215 self.verify_capture_in(capture, self.pg0)
1216 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1217
1218 # in2out
1219 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1220 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1221 ICMP(id=self.icmp_id_in, type='echo-reply'))
1222 self.pg0.add_stream(pkt)
1223 self.pg_enable_capture(self.pg_interfaces)
1224 self.pg_start()
1225 capture = self.pg1.get_capture(1)
1226 self.verify_capture_out(capture, same_port=True)
1227 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1228
1229 def test_forwarding(self):
1230 """ NAT44EI forwarding test """
1231
Filip Varga0eaf4e62021-02-17 14:34:54 +01001232 flags = self.config_flags.NAT44_EI_IF_INSIDE
1233 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001234 sw_if_index=self.pg0.sw_if_index,
1235 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001236 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001237 sw_if_index=self.pg1.sw_if_index,
1238 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001239 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01001240
1241 real_ip = self.pg0.remote_ip4
1242 alias_ip = self.nat_addr
Filip Varga0eaf4e62021-02-17 14:34:54 +01001243 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1244 self.vapi.nat44_ei_add_del_static_mapping(
1245 is_add=1, local_ip_address=real_ip,
1246 external_ip_address=alias_ip,
1247 external_sw_if_index=0xFFFFFFFF,
1248 flags=flags)
Filip Varga18f1e412020-12-03 15:27:40 +01001249
1250 try:
1251 # static mapping match
1252
1253 pkts = self.create_stream_out(self.pg1)
1254 self.pg1.add_stream(pkts)
1255 self.pg_enable_capture(self.pg_interfaces)
1256 self.pg_start()
1257 capture = self.pg0.get_capture(len(pkts))
1258 self.verify_capture_in(capture, self.pg0)
1259
1260 pkts = self.create_stream_in(self.pg0, self.pg1)
1261 self.pg0.add_stream(pkts)
1262 self.pg_enable_capture(self.pg_interfaces)
1263 self.pg_start()
1264 capture = self.pg1.get_capture(len(pkts))
1265 self.verify_capture_out(capture, same_port=True)
1266
1267 # no static mapping match
1268
1269 host0 = self.pg0.remote_hosts[0]
1270 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1271 try:
1272 pkts = self.create_stream_out(self.pg1,
1273 dst_ip=self.pg0.remote_ip4,
1274 use_inside_ports=True)
1275 self.pg1.add_stream(pkts)
1276 self.pg_enable_capture(self.pg_interfaces)
1277 self.pg_start()
1278 capture = self.pg0.get_capture(len(pkts))
1279 self.verify_capture_in(capture, self.pg0)
1280
1281 pkts = self.create_stream_in(self.pg0, self.pg1)
1282 self.pg0.add_stream(pkts)
1283 self.pg_enable_capture(self.pg_interfaces)
1284 self.pg_start()
1285 capture = self.pg1.get_capture(len(pkts))
1286 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1287 same_port=True)
1288 finally:
1289 self.pg0.remote_hosts[0] = host0
1290
1291 finally:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001292 self.vapi.nat44_ei_forwarding_enable_disable(enable=0)
1293 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1294 self.vapi.nat44_ei_add_del_static_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +01001295 is_add=0,
1296 local_ip_address=real_ip,
1297 external_ip_address=alias_ip,
1298 external_sw_if_index=0xFFFFFFFF,
1299 flags=flags)
1300
1301 def test_static_in(self):
1302 """ NAT44EI 1:1 NAT initialized from inside network """
1303
1304 nat_ip = "10.0.0.10"
1305 self.tcp_port_out = 6303
1306 self.udp_port_out = 6304
1307 self.icmp_id_out = 6305
1308
1309 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001310 flags = self.config_flags.NAT44_EI_IF_INSIDE
1311 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001312 sw_if_index=self.pg0.sw_if_index,
1313 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001314 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001315 sw_if_index=self.pg1.sw_if_index,
1316 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001317 sm = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001318 self.assertEqual(len(sm), 1)
1319 self.assertEqual(sm[0].tag, '')
1320 self.assertEqual(sm[0].protocol, 0)
1321 self.assertEqual(sm[0].local_port, 0)
1322 self.assertEqual(sm[0].external_port, 0)
1323
1324 # in2out
1325 pkts = self.create_stream_in(self.pg0, self.pg1)
1326 self.pg0.add_stream(pkts)
1327 self.pg_enable_capture(self.pg_interfaces)
1328 self.pg_start()
1329 capture = self.pg1.get_capture(len(pkts))
1330 self.verify_capture_out(capture, nat_ip, True)
1331
1332 # out2in
1333 pkts = self.create_stream_out(self.pg1, nat_ip)
1334 self.pg1.add_stream(pkts)
1335 self.pg_enable_capture(self.pg_interfaces)
1336 self.pg_start()
1337 capture = self.pg0.get_capture(len(pkts))
1338 self.verify_capture_in(capture, self.pg0)
1339
1340 def test_static_out(self):
1341 """ NAT44EI 1:1 NAT initialized from outside network """
1342
1343 nat_ip = "10.0.0.20"
1344 self.tcp_port_out = 6303
1345 self.udp_port_out = 6304
1346 self.icmp_id_out = 6305
1347 tag = "testTAG"
1348
1349 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001350 flags = self.config_flags.NAT44_EI_IF_INSIDE
1351 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001352 sw_if_index=self.pg0.sw_if_index,
1353 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001354 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001355 sw_if_index=self.pg1.sw_if_index,
1356 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001357 sm = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001358 self.assertEqual(len(sm), 1)
1359 self.assertEqual(sm[0].tag, tag)
1360
1361 # out2in
1362 pkts = self.create_stream_out(self.pg1, nat_ip)
1363 self.pg1.add_stream(pkts)
1364 self.pg_enable_capture(self.pg_interfaces)
1365 self.pg_start()
1366 capture = self.pg0.get_capture(len(pkts))
1367 self.verify_capture_in(capture, self.pg0)
1368
1369 # in2out
1370 pkts = self.create_stream_in(self.pg0, self.pg1)
1371 self.pg0.add_stream(pkts)
1372 self.pg_enable_capture(self.pg_interfaces)
1373 self.pg_start()
1374 capture = self.pg1.get_capture(len(pkts))
1375 self.verify_capture_out(capture, nat_ip, True)
1376
1377 def test_static_with_port_in(self):
1378 """ NAT44EI 1:1 NAPT initialized from inside network """
1379
1380 self.tcp_port_out = 3606
1381 self.udp_port_out = 3607
1382 self.icmp_id_out = 3608
1383
1384 self.nat44_add_address(self.nat_addr)
1385 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1386 self.tcp_port_in, self.tcp_port_out,
1387 proto=IP_PROTOS.tcp)
1388 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1389 self.udp_port_in, self.udp_port_out,
1390 proto=IP_PROTOS.udp)
1391 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1392 self.icmp_id_in, self.icmp_id_out,
1393 proto=IP_PROTOS.icmp)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001394 flags = self.config_flags.NAT44_EI_IF_INSIDE
1395 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001396 sw_if_index=self.pg0.sw_if_index,
1397 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001398 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001399 sw_if_index=self.pg1.sw_if_index,
1400 is_add=1)
1401
1402 # in2out
1403 pkts = self.create_stream_in(self.pg0, self.pg1)
1404 self.pg0.add_stream(pkts)
1405 self.pg_enable_capture(self.pg_interfaces)
1406 self.pg_start()
1407 capture = self.pg1.get_capture(len(pkts))
1408 self.verify_capture_out(capture)
1409
1410 # out2in
1411 pkts = self.create_stream_out(self.pg1)
1412 self.pg1.add_stream(pkts)
1413 self.pg_enable_capture(self.pg_interfaces)
1414 self.pg_start()
1415 capture = self.pg0.get_capture(len(pkts))
1416 self.verify_capture_in(capture, self.pg0)
1417
1418 def test_static_with_port_out(self):
1419 """ NAT44EI 1:1 NAPT initialized from outside network """
1420
1421 self.tcp_port_out = 30606
1422 self.udp_port_out = 30607
1423 self.icmp_id_out = 30608
1424
1425 self.nat44_add_address(self.nat_addr)
1426 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1427 self.tcp_port_in, self.tcp_port_out,
1428 proto=IP_PROTOS.tcp)
1429 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1430 self.udp_port_in, self.udp_port_out,
1431 proto=IP_PROTOS.udp)
1432 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1433 self.icmp_id_in, self.icmp_id_out,
1434 proto=IP_PROTOS.icmp)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001435 flags = self.config_flags.NAT44_EI_IF_INSIDE
1436 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001437 sw_if_index=self.pg0.sw_if_index,
1438 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001439 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001440 sw_if_index=self.pg1.sw_if_index,
1441 is_add=1)
1442
1443 # out2in
1444 pkts = self.create_stream_out(self.pg1)
1445 self.pg1.add_stream(pkts)
1446 self.pg_enable_capture(self.pg_interfaces)
1447 self.pg_start()
1448 capture = self.pg0.get_capture(len(pkts))
1449 self.verify_capture_in(capture, self.pg0)
1450
1451 # in2out
1452 pkts = self.create_stream_in(self.pg0, self.pg1)
1453 self.pg0.add_stream(pkts)
1454 self.pg_enable_capture(self.pg_interfaces)
1455 self.pg_start()
1456 capture = self.pg1.get_capture(len(pkts))
1457 self.verify_capture_out(capture)
1458
1459 def test_static_vrf_aware(self):
1460 """ NAT44EI 1:1 NAT VRF awareness """
1461
1462 nat_ip1 = "10.0.0.30"
1463 nat_ip2 = "10.0.0.40"
1464 self.tcp_port_out = 6303
1465 self.udp_port_out = 6304
1466 self.icmp_id_out = 6305
1467
1468 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1469 vrf_id=10)
1470 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1471 vrf_id=10)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001472 flags = self.config_flags.NAT44_EI_IF_INSIDE
1473 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001474 sw_if_index=self.pg3.sw_if_index,
1475 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001476 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001477 sw_if_index=self.pg0.sw_if_index,
1478 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001479 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001480 sw_if_index=self.pg4.sw_if_index,
1481 flags=flags, is_add=1)
1482
1483 # inside interface VRF match NAT44EI static mapping VRF
1484 pkts = self.create_stream_in(self.pg4, self.pg3)
1485 self.pg4.add_stream(pkts)
1486 self.pg_enable_capture(self.pg_interfaces)
1487 self.pg_start()
1488 capture = self.pg3.get_capture(len(pkts))
1489 self.verify_capture_out(capture, nat_ip1, True)
1490
1491 # inside interface VRF don't match NAT44EI static mapping VRF (packets
1492 # are dropped)
1493 pkts = self.create_stream_in(self.pg0, self.pg3)
1494 self.pg0.add_stream(pkts)
1495 self.pg_enable_capture(self.pg_interfaces)
1496 self.pg_start()
1497 self.pg3.assert_nothing_captured()
1498
1499 def test_dynamic_to_static(self):
1500 """ NAT44EI Switch from dynamic translation to 1:1NAT """
1501 nat_ip = "10.0.0.10"
1502 self.tcp_port_out = 6303
1503 self.udp_port_out = 6304
1504 self.icmp_id_out = 6305
1505
1506 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001507 flags = self.config_flags.NAT44_EI_IF_INSIDE
1508 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001509 sw_if_index=self.pg0.sw_if_index,
1510 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001511 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001512 sw_if_index=self.pg1.sw_if_index,
1513 is_add=1)
1514
1515 # dynamic
1516 pkts = self.create_stream_in(self.pg0, self.pg1)
1517 self.pg0.add_stream(pkts)
1518 self.pg_enable_capture(self.pg_interfaces)
1519 self.pg_start()
1520 capture = self.pg1.get_capture(len(pkts))
1521 self.verify_capture_out(capture)
1522
1523 # 1:1NAT
1524 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001525 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001526 self.assertEqual(len(sessions), 0)
1527 pkts = self.create_stream_in(self.pg0, self.pg1)
1528 self.pg0.add_stream(pkts)
1529 self.pg_enable_capture(self.pg_interfaces)
1530 self.pg_start()
1531 capture = self.pg1.get_capture(len(pkts))
1532 self.verify_capture_out(capture, nat_ip, True)
1533
1534 def test_identity_nat(self):
1535 """ NAT44EI Identity NAT """
Filip Varga0eaf4e62021-02-17 14:34:54 +01001536 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1537 self.vapi.nat44_ei_add_del_identity_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +01001538 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1539 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001540 flags = self.config_flags.NAT44_EI_IF_INSIDE
1541 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001542 sw_if_index=self.pg0.sw_if_index,
1543 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001544 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001545 sw_if_index=self.pg1.sw_if_index,
1546 is_add=1)
1547
1548 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1549 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1550 TCP(sport=12345, dport=56789))
1551 self.pg1.add_stream(p)
1552 self.pg_enable_capture(self.pg_interfaces)
1553 self.pg_start()
1554 capture = self.pg0.get_capture(1)
1555 p = capture[0]
1556 try:
1557 ip = p[IP]
1558 tcp = p[TCP]
1559 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1560 self.assertEqual(ip.src, self.pg1.remote_ip4)
1561 self.assertEqual(tcp.dport, 56789)
1562 self.assertEqual(tcp.sport, 12345)
1563 self.assert_packet_checksums_valid(p)
1564 except:
1565 self.logger.error(ppp("Unexpected or invalid packet:", p))
1566 raise
1567
Filip Varga0eaf4e62021-02-17 14:34:54 +01001568 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01001569 self.assertEqual(len(sessions), 0)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001570 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1571 self.vapi.nat44_ei_add_del_identity_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +01001572 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1573 flags=flags, vrf_id=1, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001574 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001575 self.assertEqual(len(identity_mappings), 2)
1576
1577 def test_multiple_inside_interfaces(self):
1578 """ NAT44EI multiple non-overlapping address space inside interfaces
1579 """
1580
1581 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001582 flags = self.config_flags.NAT44_EI_IF_INSIDE
1583 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001584 sw_if_index=self.pg0.sw_if_index,
1585 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001586 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001587 sw_if_index=self.pg1.sw_if_index,
1588 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001589 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001590 sw_if_index=self.pg3.sw_if_index,
1591 is_add=1)
1592
1593 # between two NAT44EI inside interfaces (no translation)
1594 pkts = self.create_stream_in(self.pg0, self.pg1)
1595 self.pg0.add_stream(pkts)
1596 self.pg_enable_capture(self.pg_interfaces)
1597 self.pg_start()
1598 capture = self.pg1.get_capture(len(pkts))
1599 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1600
1601 # from inside to interface without translation
1602 pkts = self.create_stream_in(self.pg0, self.pg2)
1603 self.pg0.add_stream(pkts)
1604 self.pg_enable_capture(self.pg_interfaces)
1605 self.pg_start()
1606 capture = self.pg2.get_capture(len(pkts))
1607 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1608
1609 # in2out 1st interface
1610 pkts = self.create_stream_in(self.pg0, self.pg3)
1611 self.pg0.add_stream(pkts)
1612 self.pg_enable_capture(self.pg_interfaces)
1613 self.pg_start()
1614 capture = self.pg3.get_capture(len(pkts))
1615 self.verify_capture_out(capture)
1616
1617 # out2in 1st interface
1618 pkts = self.create_stream_out(self.pg3)
1619 self.pg3.add_stream(pkts)
1620 self.pg_enable_capture(self.pg_interfaces)
1621 self.pg_start()
1622 capture = self.pg0.get_capture(len(pkts))
1623 self.verify_capture_in(capture, self.pg0)
1624
1625 # in2out 2nd interface
1626 pkts = self.create_stream_in(self.pg1, self.pg3)
1627 self.pg1.add_stream(pkts)
1628 self.pg_enable_capture(self.pg_interfaces)
1629 self.pg_start()
1630 capture = self.pg3.get_capture(len(pkts))
1631 self.verify_capture_out(capture)
1632
1633 # out2in 2nd interface
1634 pkts = self.create_stream_out(self.pg3)
1635 self.pg3.add_stream(pkts)
1636 self.pg_enable_capture(self.pg_interfaces)
1637 self.pg_start()
1638 capture = self.pg1.get_capture(len(pkts))
1639 self.verify_capture_in(capture, self.pg1)
1640
1641 def test_inside_overlapping_interfaces(self):
1642 """ NAT44EI multiple inside interfaces with overlapping address space
1643 """
1644
1645 static_nat_ip = "10.0.0.10"
1646 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001647 flags = self.config_flags.NAT44_EI_IF_INSIDE
1648 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001649 sw_if_index=self.pg3.sw_if_index,
1650 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001651 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001652 sw_if_index=self.pg4.sw_if_index,
1653 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001654 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001655 sw_if_index=self.pg5.sw_if_index,
1656 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001657 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001658 sw_if_index=self.pg6.sw_if_index,
1659 flags=flags, is_add=1)
1660 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1661 vrf_id=20)
1662
1663 # between NAT44EI inside interfaces with same VRF (no translation)
1664 pkts = self.create_stream_in(self.pg4, self.pg5)
1665 self.pg4.add_stream(pkts)
1666 self.pg_enable_capture(self.pg_interfaces)
1667 self.pg_start()
1668 capture = self.pg5.get_capture(len(pkts))
1669 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1670
1671 # between NAT44EI inside interfaces with different VRF (hairpinning)
1672 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1673 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1674 TCP(sport=1234, dport=5678))
1675 self.pg4.add_stream(p)
1676 self.pg_enable_capture(self.pg_interfaces)
1677 self.pg_start()
1678 capture = self.pg6.get_capture(1)
1679 p = capture[0]
1680 try:
1681 ip = p[IP]
1682 tcp = p[TCP]
1683 self.assertEqual(ip.src, self.nat_addr)
1684 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1685 self.assertNotEqual(tcp.sport, 1234)
1686 self.assertEqual(tcp.dport, 5678)
1687 except:
1688 self.logger.error(ppp("Unexpected or invalid packet:", p))
1689 raise
1690
1691 # in2out 1st interface
1692 pkts = self.create_stream_in(self.pg4, self.pg3)
1693 self.pg4.add_stream(pkts)
1694 self.pg_enable_capture(self.pg_interfaces)
1695 self.pg_start()
1696 capture = self.pg3.get_capture(len(pkts))
1697 self.verify_capture_out(capture)
1698
1699 # out2in 1st interface
1700 pkts = self.create_stream_out(self.pg3)
1701 self.pg3.add_stream(pkts)
1702 self.pg_enable_capture(self.pg_interfaces)
1703 self.pg_start()
1704 capture = self.pg4.get_capture(len(pkts))
1705 self.verify_capture_in(capture, self.pg4)
1706
1707 # in2out 2nd interface
1708 pkts = self.create_stream_in(self.pg5, self.pg3)
1709 self.pg5.add_stream(pkts)
1710 self.pg_enable_capture(self.pg_interfaces)
1711 self.pg_start()
1712 capture = self.pg3.get_capture(len(pkts))
1713 self.verify_capture_out(capture)
1714
1715 # out2in 2nd interface
1716 pkts = self.create_stream_out(self.pg3)
1717 self.pg3.add_stream(pkts)
1718 self.pg_enable_capture(self.pg_interfaces)
1719 self.pg_start()
1720 capture = self.pg5.get_capture(len(pkts))
1721 self.verify_capture_in(capture, self.pg5)
1722
1723 # pg5 session dump
Filip Varga0eaf4e62021-02-17 14:34:54 +01001724 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001725 self.assertEqual(len(addresses), 1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001726 sessions = self.vapi.nat44_ei_user_session_dump(
1727 self.pg5.remote_ip4, 10)
Filip Varga18f1e412020-12-03 15:27:40 +01001728 self.assertEqual(len(sessions), 3)
1729 for session in sessions:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001730 self.assertFalse(session.flags &
1731 self.config_flags.NAT44_EI_STATIC_MAPPING)
Filip Varga18f1e412020-12-03 15:27:40 +01001732 self.assertEqual(str(session.inside_ip_address),
1733 self.pg5.remote_ip4)
1734 self.assertEqual(session.outside_ip_address,
1735 addresses[0].ip_address)
1736 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1737 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1738 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1739 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1740 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1741 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1742 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1743 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1744 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1745
1746 # in2out 3rd interface
1747 pkts = self.create_stream_in(self.pg6, self.pg3)
1748 self.pg6.add_stream(pkts)
1749 self.pg_enable_capture(self.pg_interfaces)
1750 self.pg_start()
1751 capture = self.pg3.get_capture(len(pkts))
1752 self.verify_capture_out(capture, static_nat_ip, True)
1753
1754 # out2in 3rd interface
1755 pkts = self.create_stream_out(self.pg3, static_nat_ip)
1756 self.pg3.add_stream(pkts)
1757 self.pg_enable_capture(self.pg_interfaces)
1758 self.pg_start()
1759 capture = self.pg6.get_capture(len(pkts))
1760 self.verify_capture_in(capture, self.pg6)
1761
1762 # general user and session dump verifications
Filip Varga0eaf4e62021-02-17 14:34:54 +01001763 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001764 self.assertGreaterEqual(len(users), 3)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001765 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01001766 self.assertEqual(len(addresses), 1)
1767 for user in users:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001768 sessions = self.vapi.nat44_ei_user_session_dump(user.ip_address,
1769 user.vrf_id)
Filip Varga18f1e412020-12-03 15:27:40 +01001770 for session in sessions:
1771 self.assertEqual(user.ip_address, session.inside_ip_address)
1772 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1773 self.assertTrue(session.protocol in
1774 [IP_PROTOS.tcp, IP_PROTOS.udp,
1775 IP_PROTOS.icmp])
Filip Varga18f1e412020-12-03 15:27:40 +01001776
1777 # pg4 session dump
Filip Varga0eaf4e62021-02-17 14:34:54 +01001778 sessions = self.vapi.nat44_ei_user_session_dump(
1779 self.pg4.remote_ip4, 10)
Filip Varga18f1e412020-12-03 15:27:40 +01001780 self.assertGreaterEqual(len(sessions), 4)
1781 for session in sessions:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001782 self.assertFalse(
1783 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
Filip Varga18f1e412020-12-03 15:27:40 +01001784 self.assertEqual(str(session.inside_ip_address),
1785 self.pg4.remote_ip4)
1786 self.assertEqual(session.outside_ip_address,
1787 addresses[0].ip_address)
1788
1789 # pg6 session dump
Filip Varga0eaf4e62021-02-17 14:34:54 +01001790 sessions = self.vapi.nat44_ei_user_session_dump(
1791 self.pg6.remote_ip4, 20)
Filip Varga18f1e412020-12-03 15:27:40 +01001792 self.assertGreaterEqual(len(sessions), 3)
1793 for session in sessions:
Filip Varga0eaf4e62021-02-17 14:34:54 +01001794 self.assertTrue(
1795 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
Filip Varga18f1e412020-12-03 15:27:40 +01001796 self.assertEqual(str(session.inside_ip_address),
1797 self.pg6.remote_ip4)
1798 self.assertEqual(str(session.outside_ip_address),
1799 static_nat_ip)
1800 self.assertTrue(session.inside_port in
1801 [self.tcp_port_in, self.udp_port_in,
1802 self.icmp_id_in])
1803
1804 def test_hairpinning(self):
1805 """ NAT44EI hairpinning - 1:1 NAPT """
1806
1807 host = self.pg0.remote_hosts[0]
1808 server = self.pg0.remote_hosts[1]
1809 host_in_port = 1234
1810 host_out_port = 0
1811 server_in_port = 5678
1812 server_out_port = 8765
1813
1814 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001815 flags = self.config_flags.NAT44_EI_IF_INSIDE
1816 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001817 sw_if_index=self.pg0.sw_if_index,
1818 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001819 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001820 sw_if_index=self.pg1.sw_if_index,
1821 is_add=1)
1822
1823 # add static mapping for server
1824 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1825 server_in_port, server_out_port,
1826 proto=IP_PROTOS.tcp)
1827
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001828 cnt = self.statistics['/nat44-ei/hairpinning']
Filip Varga18f1e412020-12-03 15:27:40 +01001829 # send packet from host to server
1830 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
1831 IP(src=host.ip4, dst=self.nat_addr) /
1832 TCP(sport=host_in_port, dport=server_out_port))
1833 self.pg0.add_stream(p)
1834 self.pg_enable_capture(self.pg_interfaces)
1835 self.pg_start()
1836 capture = self.pg0.get_capture(1)
1837 p = capture[0]
1838 try:
1839 ip = p[IP]
1840 tcp = p[TCP]
1841 self.assertEqual(ip.src, self.nat_addr)
1842 self.assertEqual(ip.dst, server.ip4)
1843 self.assertNotEqual(tcp.sport, host_in_port)
1844 self.assertEqual(tcp.dport, server_in_port)
1845 self.assert_packet_checksums_valid(p)
1846 host_out_port = tcp.sport
1847 except:
1848 self.logger.error(ppp("Unexpected or invalid packet:", p))
1849 raise
1850
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001851 after = self.statistics['/nat44-ei/hairpinning']
Filip Varga18f1e412020-12-03 15:27:40 +01001852 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001853 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01001854
1855 # send reply from server to host
1856 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1857 IP(src=server.ip4, dst=self.nat_addr) /
1858 TCP(sport=server_in_port, dport=host_out_port))
1859 self.pg0.add_stream(p)
1860 self.pg_enable_capture(self.pg_interfaces)
1861 self.pg_start()
1862 capture = self.pg0.get_capture(1)
1863 p = capture[0]
1864 try:
1865 ip = p[IP]
1866 tcp = p[TCP]
1867 self.assertEqual(ip.src, self.nat_addr)
1868 self.assertEqual(ip.dst, host.ip4)
1869 self.assertEqual(tcp.sport, server_out_port)
1870 self.assertEqual(tcp.dport, host_in_port)
1871 self.assert_packet_checksums_valid(p)
1872 except:
1873 self.logger.error(ppp("Unexpected or invalid packet:", p))
1874 raise
1875
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001876 after = self.statistics['/nat44-ei/hairpinning']
Filip Varga18f1e412020-12-03 15:27:40 +01001877 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01001878 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(),
1879 2+(1 if self.vpp_worker_count > 0 else 0))
Filip Varga18f1e412020-12-03 15:27:40 +01001880
1881 def test_hairpinning2(self):
1882 """ NAT44EI hairpinning - 1:1 NAT"""
1883
1884 server1_nat_ip = "10.0.0.10"
1885 server2_nat_ip = "10.0.0.11"
1886 host = self.pg0.remote_hosts[0]
1887 server1 = self.pg0.remote_hosts[1]
1888 server2 = self.pg0.remote_hosts[2]
1889 server_tcp_port = 22
1890 server_udp_port = 20
1891
1892 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001893 flags = self.config_flags.NAT44_EI_IF_INSIDE
1894 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001895 sw_if_index=self.pg0.sw_if_index,
1896 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01001897 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001898 sw_if_index=self.pg1.sw_if_index,
1899 is_add=1)
1900
1901 # add static mapping for servers
1902 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1903 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
1904
1905 # host to server1
1906 pkts = []
1907 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1908 IP(src=host.ip4, dst=server1_nat_ip) /
1909 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1910 pkts.append(p)
1911 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1912 IP(src=host.ip4, dst=server1_nat_ip) /
1913 UDP(sport=self.udp_port_in, dport=server_udp_port))
1914 pkts.append(p)
1915 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1916 IP(src=host.ip4, dst=server1_nat_ip) /
1917 ICMP(id=self.icmp_id_in, type='echo-request'))
1918 pkts.append(p)
1919 self.pg0.add_stream(pkts)
1920 self.pg_enable_capture(self.pg_interfaces)
1921 self.pg_start()
1922 capture = self.pg0.get_capture(len(pkts))
1923 for packet in capture:
1924 try:
1925 self.assertEqual(packet[IP].src, self.nat_addr)
1926 self.assertEqual(packet[IP].dst, server1.ip4)
1927 if packet.haslayer(TCP):
1928 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1929 self.assertEqual(packet[TCP].dport, server_tcp_port)
1930 self.tcp_port_out = packet[TCP].sport
1931 self.assert_packet_checksums_valid(packet)
1932 elif packet.haslayer(UDP):
1933 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1934 self.assertEqual(packet[UDP].dport, server_udp_port)
1935 self.udp_port_out = packet[UDP].sport
1936 else:
1937 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1938 self.icmp_id_out = packet[ICMP].id
1939 except:
1940 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1941 raise
1942
1943 # server1 to host
1944 pkts = []
1945 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1946 IP(src=server1.ip4, dst=self.nat_addr) /
1947 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1948 pkts.append(p)
1949 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1950 IP(src=server1.ip4, dst=self.nat_addr) /
1951 UDP(sport=server_udp_port, dport=self.udp_port_out))
1952 pkts.append(p)
1953 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1954 IP(src=server1.ip4, dst=self.nat_addr) /
1955 ICMP(id=self.icmp_id_out, type='echo-reply'))
1956 pkts.append(p)
1957 self.pg0.add_stream(pkts)
1958 self.pg_enable_capture(self.pg_interfaces)
1959 self.pg_start()
1960 capture = self.pg0.get_capture(len(pkts))
1961 for packet in capture:
1962 try:
1963 self.assertEqual(packet[IP].src, server1_nat_ip)
1964 self.assertEqual(packet[IP].dst, host.ip4)
1965 if packet.haslayer(TCP):
1966 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1967 self.assertEqual(packet[TCP].sport, server_tcp_port)
1968 self.assert_packet_checksums_valid(packet)
1969 elif packet.haslayer(UDP):
1970 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1971 self.assertEqual(packet[UDP].sport, server_udp_port)
1972 else:
1973 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1974 except:
1975 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1976 raise
1977
1978 # server2 to server1
1979 pkts = []
1980 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1981 IP(src=server2.ip4, dst=server1_nat_ip) /
1982 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1983 pkts.append(p)
1984 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1985 IP(src=server2.ip4, dst=server1_nat_ip) /
1986 UDP(sport=self.udp_port_in, dport=server_udp_port))
1987 pkts.append(p)
1988 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1989 IP(src=server2.ip4, dst=server1_nat_ip) /
1990 ICMP(id=self.icmp_id_in, type='echo-request'))
1991 pkts.append(p)
1992 self.pg0.add_stream(pkts)
1993 self.pg_enable_capture(self.pg_interfaces)
1994 self.pg_start()
1995 capture = self.pg0.get_capture(len(pkts))
1996 for packet in capture:
1997 try:
1998 self.assertEqual(packet[IP].src, server2_nat_ip)
1999 self.assertEqual(packet[IP].dst, server1.ip4)
2000 if packet.haslayer(TCP):
2001 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2002 self.assertEqual(packet[TCP].dport, server_tcp_port)
2003 self.tcp_port_out = packet[TCP].sport
2004 self.assert_packet_checksums_valid(packet)
2005 elif packet.haslayer(UDP):
2006 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2007 self.assertEqual(packet[UDP].dport, server_udp_port)
2008 self.udp_port_out = packet[UDP].sport
2009 else:
2010 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2011 self.icmp_id_out = packet[ICMP].id
2012 except:
2013 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2014 raise
2015
2016 # server1 to server2
2017 pkts = []
2018 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2019 IP(src=server1.ip4, dst=server2_nat_ip) /
2020 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2021 pkts.append(p)
2022 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2023 IP(src=server1.ip4, dst=server2_nat_ip) /
2024 UDP(sport=server_udp_port, dport=self.udp_port_out))
2025 pkts.append(p)
2026 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2027 IP(src=server1.ip4, dst=server2_nat_ip) /
2028 ICMP(id=self.icmp_id_out, type='echo-reply'))
2029 pkts.append(p)
2030 self.pg0.add_stream(pkts)
2031 self.pg_enable_capture(self.pg_interfaces)
2032 self.pg_start()
2033 capture = self.pg0.get_capture(len(pkts))
2034 for packet in capture:
2035 try:
2036 self.assertEqual(packet[IP].src, server1_nat_ip)
2037 self.assertEqual(packet[IP].dst, server2.ip4)
2038 if packet.haslayer(TCP):
2039 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2040 self.assertEqual(packet[TCP].sport, server_tcp_port)
2041 self.assert_packet_checksums_valid(packet)
2042 elif packet.haslayer(UDP):
2043 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2044 self.assertEqual(packet[UDP].sport, server_udp_port)
2045 else:
2046 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2047 except:
2048 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2049 raise
2050
2051 def test_hairpinning_avoid_inf_loop(self):
Filip Varga0eaf4e62021-02-17 14:34:54 +01002052 """ NAT44EI hairpinning - 1:1 NAPT avoid infinite loop """
Filip Varga18f1e412020-12-03 15:27:40 +01002053
2054 host = self.pg0.remote_hosts[0]
2055 server = self.pg0.remote_hosts[1]
2056 host_in_port = 1234
2057 host_out_port = 0
2058 server_in_port = 5678
2059 server_out_port = 8765
2060
2061 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002062 flags = self.config_flags.NAT44_EI_IF_INSIDE
2063 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002064 sw_if_index=self.pg0.sw_if_index,
2065 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002066 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002067 sw_if_index=self.pg1.sw_if_index,
2068 is_add=1)
2069
2070 # add static mapping for server
2071 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2072 server_in_port, server_out_port,
2073 proto=IP_PROTOS.tcp)
2074
2075 # add another static mapping that maps pg0.local_ip4 address to itself
2076 self.nat44_add_static_mapping(self.pg0.local_ip4, self.pg0.local_ip4)
2077
2078 # send packet from host to VPP (the packet should get dropped)
2079 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2080 IP(src=host.ip4, dst=self.pg0.local_ip4) /
2081 TCP(sport=host_in_port, dport=server_out_port))
2082 self.pg0.add_stream(p)
2083 self.pg_enable_capture(self.pg_interfaces)
2084 self.pg_start()
2085 # Here VPP used to crash due to an infinite loop
2086
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002087 cnt = self.statistics['/nat44-ei/hairpinning']
Filip Varga18f1e412020-12-03 15:27:40 +01002088 # send packet from host to server
2089 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2090 IP(src=host.ip4, dst=self.nat_addr) /
2091 TCP(sport=host_in_port, dport=server_out_port))
2092 self.pg0.add_stream(p)
2093 self.pg_enable_capture(self.pg_interfaces)
2094 self.pg_start()
2095 capture = self.pg0.get_capture(1)
2096 p = capture[0]
2097 try:
2098 ip = p[IP]
2099 tcp = p[TCP]
2100 self.assertEqual(ip.src, self.nat_addr)
2101 self.assertEqual(ip.dst, server.ip4)
2102 self.assertNotEqual(tcp.sport, host_in_port)
2103 self.assertEqual(tcp.dport, server_in_port)
2104 self.assert_packet_checksums_valid(p)
2105 host_out_port = tcp.sport
2106 except:
2107 self.logger.error(ppp("Unexpected or invalid packet:", p))
2108 raise
2109
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002110 after = self.statistics['/nat44-ei/hairpinning']
Filip Varga18f1e412020-12-03 15:27:40 +01002111 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002112 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01002113
2114 # send reply from server to host
2115 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2116 IP(src=server.ip4, dst=self.nat_addr) /
2117 TCP(sport=server_in_port, dport=host_out_port))
2118 self.pg0.add_stream(p)
2119 self.pg_enable_capture(self.pg_interfaces)
2120 self.pg_start()
2121 capture = self.pg0.get_capture(1)
2122 p = capture[0]
2123 try:
2124 ip = p[IP]
2125 tcp = p[TCP]
2126 self.assertEqual(ip.src, self.nat_addr)
2127 self.assertEqual(ip.dst, host.ip4)
2128 self.assertEqual(tcp.sport, server_out_port)
2129 self.assertEqual(tcp.dport, host_in_port)
2130 self.assert_packet_checksums_valid(p)
2131 except:
2132 self.logger.error(ppp("Unexpected or invalid packet:", p))
2133 raise
2134
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002135 after = self.statistics['/nat44-ei/hairpinning']
Filip Varga18f1e412020-12-03 15:27:40 +01002136 if_idx = self.pg0.sw_if_index
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002137 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(),
2138 2+(1 if self.vpp_worker_count > 0 else 0))
Filip Varga18f1e412020-12-03 15:27:40 +01002139
2140 def test_interface_addr(self):
2141 """ NAT44EI acquire addresses from interface """
Filip Varga0eaf4e62021-02-17 14:34:54 +01002142 self.vapi.nat44_ei_add_del_interface_addr(
Filip Varga18f1e412020-12-03 15:27:40 +01002143 is_add=1,
2144 sw_if_index=self.pg7.sw_if_index)
2145
2146 # no address in NAT pool
Filip Varga0eaf4e62021-02-17 14:34:54 +01002147 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002148 self.assertEqual(0, len(addresses))
2149
2150 # configure interface address and check NAT address pool
2151 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002152 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002153 self.assertEqual(1, len(addresses))
2154 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2155
2156 # remove interface address and check NAT address pool
2157 self.pg7.unconfig_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002158 addresses = self.vapi.nat44_ei_address_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002159 self.assertEqual(0, len(addresses))
2160
2161 def test_interface_addr_static_mapping(self):
2162 """ NAT44EI Static mapping with addresses from interface """
2163 tag = "testTAG"
2164
Filip Varga0eaf4e62021-02-17 14:34:54 +01002165 self.vapi.nat44_ei_add_del_interface_addr(
Filip Varga18f1e412020-12-03 15:27:40 +01002166 is_add=1,
2167 sw_if_index=self.pg7.sw_if_index)
2168 self.nat44_add_static_mapping(
2169 '1.2.3.4',
2170 external_sw_if_index=self.pg7.sw_if_index,
2171 tag=tag)
2172
2173 # static mappings with external interface
Filip Varga0eaf4e62021-02-17 14:34:54 +01002174 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002175 self.assertEqual(1, len(static_mappings))
2176 self.assertEqual(self.pg7.sw_if_index,
2177 static_mappings[0].external_sw_if_index)
2178 self.assertEqual(static_mappings[0].tag, tag)
2179
2180 # configure interface address and check static mappings
2181 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002182 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002183 self.assertEqual(2, len(static_mappings))
2184 resolved = False
2185 for sm in static_mappings:
2186 if sm.external_sw_if_index == 0xFFFFFFFF:
2187 self.assertEqual(str(sm.external_ip_address),
2188 self.pg7.local_ip4)
2189 self.assertEqual(sm.tag, tag)
2190 resolved = True
2191 self.assertTrue(resolved)
2192
2193 # remove interface address and check static mappings
2194 self.pg7.unconfig_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002195 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002196 self.assertEqual(1, len(static_mappings))
2197 self.assertEqual(self.pg7.sw_if_index,
2198 static_mappings[0].external_sw_if_index)
2199 self.assertEqual(static_mappings[0].tag, tag)
2200
2201 # configure interface address again and check static mappings
2202 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002203 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002204 self.assertEqual(2, len(static_mappings))
2205 resolved = False
2206 for sm in static_mappings:
2207 if sm.external_sw_if_index == 0xFFFFFFFF:
2208 self.assertEqual(str(sm.external_ip_address),
2209 self.pg7.local_ip4)
2210 self.assertEqual(sm.tag, tag)
2211 resolved = True
2212 self.assertTrue(resolved)
2213
2214 # remove static mapping
2215 self.nat44_add_static_mapping(
2216 '1.2.3.4',
2217 external_sw_if_index=self.pg7.sw_if_index,
2218 tag=tag,
2219 is_add=0)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002220 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002221 self.assertEqual(0, len(static_mappings))
2222
2223 def test_interface_addr_identity_nat(self):
2224 """ NAT44EI Identity NAT with addresses from interface """
2225
2226 port = 53053
Filip Varga0eaf4e62021-02-17 14:34:54 +01002227 self.vapi.nat44_ei_add_del_interface_addr(
Filip Varga18f1e412020-12-03 15:27:40 +01002228 is_add=1,
2229 sw_if_index=self.pg7.sw_if_index)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002230 self.vapi.nat44_ei_add_del_identity_mapping(
Filip Varga18f1e412020-12-03 15:27:40 +01002231 ip_address=b'0',
2232 sw_if_index=self.pg7.sw_if_index,
2233 port=port,
2234 protocol=IP_PROTOS.tcp,
2235 is_add=1)
2236
2237 # identity mappings with external interface
Filip Varga0eaf4e62021-02-17 14:34:54 +01002238 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002239 self.assertEqual(1, len(identity_mappings))
2240 self.assertEqual(self.pg7.sw_if_index,
2241 identity_mappings[0].sw_if_index)
2242
2243 # configure interface address and check identity mappings
2244 self.pg7.config_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002245 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002246 resolved = False
2247 self.assertEqual(2, len(identity_mappings))
2248 for sm in identity_mappings:
2249 if sm.sw_if_index == 0xFFFFFFFF:
2250 self.assertEqual(str(identity_mappings[0].ip_address),
2251 self.pg7.local_ip4)
2252 self.assertEqual(port, identity_mappings[0].port)
2253 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2254 resolved = True
2255 self.assertTrue(resolved)
2256
2257 # remove interface address and check identity mappings
2258 self.pg7.unconfig_ip4()
Filip Varga0eaf4e62021-02-17 14:34:54 +01002259 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01002260 self.assertEqual(1, len(identity_mappings))
2261 self.assertEqual(self.pg7.sw_if_index,
2262 identity_mappings[0].sw_if_index)
2263
2264 def test_ipfix_nat44_sess(self):
2265 """ NAT44EI IPFIX logging NAT44EI session created/deleted """
2266 self.ipfix_domain_id = 10
2267 self.ipfix_src_port = 20202
2268 collector_port = 30303
2269 bind_layers(UDP, IPFIX, dport=30303)
2270 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002271 flags = self.config_flags.NAT44_EI_IF_INSIDE
2272 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002273 sw_if_index=self.pg0.sw_if_index,
2274 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002275 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002276 sw_if_index=self.pg1.sw_if_index,
2277 is_add=1)
2278 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2279 src_address=self.pg3.local_ip4,
2280 path_mtu=512,
2281 template_interval=10,
2282 collector_port=collector_port)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002283 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2284 src_port=self.ipfix_src_port,
2285 enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01002286
2287 pkts = self.create_stream_in(self.pg0, self.pg1)
2288 self.pg0.add_stream(pkts)
2289 self.pg_enable_capture(self.pg_interfaces)
2290 self.pg_start()
2291 capture = self.pg1.get_capture(len(pkts))
2292 self.verify_capture_out(capture)
2293 self.nat44_add_address(self.nat_addr, is_add=0)
2294 self.vapi.ipfix_flush()
2295 capture = self.pg3.get_capture(7)
2296 ipfix = IPFIXDecoder()
2297 # first load template
2298 for p in capture:
2299 self.assertTrue(p.haslayer(IPFIX))
2300 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2301 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2302 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2303 self.assertEqual(p[UDP].dport, collector_port)
2304 self.assertEqual(p[IPFIX].observationDomainID,
2305 self.ipfix_domain_id)
2306 if p.haslayer(Template):
2307 ipfix.add_template(p.getlayer(Template))
2308 # verify events in data set
2309 for p in capture:
2310 if p.haslayer(Data):
2311 data = ipfix.decode_data_set(p.getlayer(Set))
2312 self.verify_ipfix_nat44_ses(data)
2313
2314 def test_ipfix_addr_exhausted(self):
2315 """ NAT44EI IPFIX logging NAT addresses exhausted """
Filip Varga0eaf4e62021-02-17 14:34:54 +01002316 flags = self.config_flags.NAT44_EI_IF_INSIDE
2317 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002318 sw_if_index=self.pg0.sw_if_index,
2319 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002320 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002321 sw_if_index=self.pg1.sw_if_index,
2322 is_add=1)
2323 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2324 src_address=self.pg3.local_ip4,
2325 path_mtu=512,
2326 template_interval=10)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002327 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2328 src_port=self.ipfix_src_port,
2329 enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01002330
2331 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2332 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2333 TCP(sport=3025))
2334 self.pg0.add_stream(p)
2335 self.pg_enable_capture(self.pg_interfaces)
2336 self.pg_start()
2337 self.pg1.assert_nothing_captured()
Filip Varga18f1e412020-12-03 15:27:40 +01002338 self.vapi.ipfix_flush()
2339 capture = self.pg3.get_capture(7)
2340 ipfix = IPFIXDecoder()
2341 # first load template
2342 for p in capture:
2343 self.assertTrue(p.haslayer(IPFIX))
2344 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2345 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2346 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2347 self.assertEqual(p[UDP].dport, 4739)
2348 self.assertEqual(p[IPFIX].observationDomainID,
2349 self.ipfix_domain_id)
2350 if p.haslayer(Template):
2351 ipfix.add_template(p.getlayer(Template))
2352 # verify events in data set
2353 for p in capture:
2354 if p.haslayer(Data):
2355 data = ipfix.decode_data_set(p.getlayer(Set))
2356 self.verify_ipfix_addr_exhausted(data)
2357
2358 def test_ipfix_max_sessions(self):
2359 """ NAT44EI IPFIX logging maximum session entries exceeded """
2360 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002361 flags = self.config_flags.NAT44_EI_IF_INSIDE
2362 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002363 sw_if_index=self.pg0.sw_if_index,
2364 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002365 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002366 sw_if_index=self.pg1.sw_if_index,
2367 is_add=1)
2368
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002369 max_sessions_per_thread = self.max_translations
2370 max_sessions = max(1, self.vpp_worker_count) * max_sessions_per_thread
Filip Varga18f1e412020-12-03 15:27:40 +01002371
2372 pkts = []
2373 for i in range(0, max_sessions):
2374 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2375 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2376 IP(src=src, dst=self.pg1.remote_ip4) /
2377 TCP(sport=1025))
2378 pkts.append(p)
2379 self.pg0.add_stream(pkts)
2380 self.pg_enable_capture(self.pg_interfaces)
2381 self.pg_start()
2382
2383 self.pg1.get_capture(max_sessions)
2384 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2385 src_address=self.pg3.local_ip4,
2386 path_mtu=512,
2387 template_interval=10)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002388 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2389 src_port=self.ipfix_src_port,
2390 enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01002391
2392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2393 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2394 TCP(sport=1025))
2395 self.pg0.add_stream(p)
2396 self.pg_enable_capture(self.pg_interfaces)
2397 self.pg_start()
2398 self.pg1.assert_nothing_captured()
Filip Varga18f1e412020-12-03 15:27:40 +01002399 self.vapi.ipfix_flush()
2400 capture = self.pg3.get_capture(7)
2401 ipfix = IPFIXDecoder()
2402 # first load template
2403 for p in capture:
2404 self.assertTrue(p.haslayer(IPFIX))
2405 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2406 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2407 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2408 self.assertEqual(p[UDP].dport, 4739)
2409 self.assertEqual(p[IPFIX].observationDomainID,
2410 self.ipfix_domain_id)
2411 if p.haslayer(Template):
2412 ipfix.add_template(p.getlayer(Template))
2413 # verify events in data set
2414 for p in capture:
2415 if p.haslayer(Data):
2416 data = ipfix.decode_data_set(p.getlayer(Set))
Klement Sekeraeafb5db2021-03-15 16:34:01 +01002417 self.verify_ipfix_max_sessions(data, max_sessions_per_thread)
Filip Varga18f1e412020-12-03 15:27:40 +01002418
2419 def test_syslog_apmap(self):
2420 """ NAT44EI syslog address and port mapping creation and deletion """
2421 self.vapi.syslog_set_filter(
2422 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2423 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2424 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002425 flags = self.config_flags.NAT44_EI_IF_INSIDE
2426 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002427 sw_if_index=self.pg0.sw_if_index,
2428 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002429 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002430 sw_if_index=self.pg1.sw_if_index,
2431 is_add=1)
2432
2433 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2434 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2435 TCP(sport=self.tcp_port_in, dport=20))
2436 self.pg0.add_stream(p)
2437 self.pg_enable_capture(self.pg_interfaces)
2438 self.pg_start()
2439 capture = self.pg1.get_capture(1)
2440 self.tcp_port_out = capture[0][TCP].sport
2441 capture = self.pg3.get_capture(1)
2442 self.verify_syslog_apmap(capture[0][Raw].load)
2443
2444 self.pg_enable_capture(self.pg_interfaces)
2445 self.pg_start()
2446 self.nat44_add_address(self.nat_addr, is_add=0)
2447 capture = self.pg3.get_capture(1)
2448 self.verify_syslog_apmap(capture[0][Raw].load, False)
2449
2450 def test_pool_addr_fib(self):
2451 """ NAT44EI add pool addresses to FIB """
2452 static_addr = '10.0.0.10'
2453 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002454 flags = self.config_flags.NAT44_EI_IF_INSIDE
2455 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002456 sw_if_index=self.pg0.sw_if_index,
2457 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002458 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002459 sw_if_index=self.pg1.sw_if_index,
2460 is_add=1)
2461 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2462
2463 # NAT44EI address
2464 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2465 ARP(op=ARP.who_has, pdst=self.nat_addr,
2466 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2467 self.pg1.add_stream(p)
2468 self.pg_enable_capture(self.pg_interfaces)
2469 self.pg_start()
2470 capture = self.pg1.get_capture(1)
2471 self.assertTrue(capture[0].haslayer(ARP))
2472 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2473
2474 # 1:1 NAT address
2475 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2476 ARP(op=ARP.who_has, pdst=static_addr,
2477 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2478 self.pg1.add_stream(p)
2479 self.pg_enable_capture(self.pg_interfaces)
2480 self.pg_start()
2481 capture = self.pg1.get_capture(1)
2482 self.assertTrue(capture[0].haslayer(ARP))
2483 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2484
2485 # send ARP to non-NAT44EI interface
2486 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2487 ARP(op=ARP.who_has, pdst=self.nat_addr,
2488 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2489 self.pg2.add_stream(p)
2490 self.pg_enable_capture(self.pg_interfaces)
2491 self.pg_start()
2492 self.pg1.assert_nothing_captured()
2493
2494 # remove addresses and verify
2495 self.nat44_add_address(self.nat_addr, is_add=0)
2496 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2497 is_add=0)
2498
2499 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2500 ARP(op=ARP.who_has, pdst=self.nat_addr,
2501 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2502 self.pg1.add_stream(p)
2503 self.pg_enable_capture(self.pg_interfaces)
2504 self.pg_start()
2505 self.pg1.assert_nothing_captured()
2506
2507 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2508 ARP(op=ARP.who_has, pdst=static_addr,
2509 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2510 self.pg1.add_stream(p)
2511 self.pg_enable_capture(self.pg_interfaces)
2512 self.pg_start()
2513 self.pg1.assert_nothing_captured()
2514
2515 def test_vrf_mode(self):
2516 """ NAT44EI tenant VRF aware address pool mode """
2517
2518 vrf_id1 = 1
2519 vrf_id2 = 2
2520 nat_ip1 = "10.0.0.10"
2521 nat_ip2 = "10.0.0.11"
2522
2523 self.pg0.unconfig_ip4()
2524 self.pg1.unconfig_ip4()
2525 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2526 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2527 self.pg0.set_table_ip4(vrf_id1)
2528 self.pg1.set_table_ip4(vrf_id2)
2529 self.pg0.config_ip4()
2530 self.pg1.config_ip4()
2531 self.pg0.resolve_arp()
2532 self.pg1.resolve_arp()
2533
2534 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2535 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002536 flags = self.config_flags.NAT44_EI_IF_INSIDE
2537 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002538 sw_if_index=self.pg0.sw_if_index,
2539 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002540 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002541 sw_if_index=self.pg1.sw_if_index,
2542 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002543 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002544 sw_if_index=self.pg2.sw_if_index,
2545 is_add=1)
2546
2547 try:
2548 # first VRF
2549 pkts = self.create_stream_in(self.pg0, self.pg2)
2550 self.pg0.add_stream(pkts)
2551 self.pg_enable_capture(self.pg_interfaces)
2552 self.pg_start()
2553 capture = self.pg2.get_capture(len(pkts))
2554 self.verify_capture_out(capture, nat_ip1)
2555
2556 # second VRF
2557 pkts = self.create_stream_in(self.pg1, self.pg2)
2558 self.pg1.add_stream(pkts)
2559 self.pg_enable_capture(self.pg_interfaces)
2560 self.pg_start()
2561 capture = self.pg2.get_capture(len(pkts))
2562 self.verify_capture_out(capture, nat_ip2)
2563
2564 finally:
2565 self.pg0.unconfig_ip4()
2566 self.pg1.unconfig_ip4()
2567 self.pg0.set_table_ip4(0)
2568 self.pg1.set_table_ip4(0)
2569 self.pg0.config_ip4()
2570 self.pg1.config_ip4()
2571 self.pg0.resolve_arp()
2572 self.pg1.resolve_arp()
2573 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2574 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2575
2576 def test_vrf_feature_independent(self):
2577 """ NAT44EI tenant VRF independent address pool mode """
2578
2579 nat_ip1 = "10.0.0.10"
2580 nat_ip2 = "10.0.0.11"
2581
2582 self.nat44_add_address(nat_ip1)
2583 self.nat44_add_address(nat_ip2, vrf_id=99)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002584 flags = self.config_flags.NAT44_EI_IF_INSIDE
2585 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002586 sw_if_index=self.pg0.sw_if_index,
2587 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002588 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002589 sw_if_index=self.pg1.sw_if_index,
2590 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002591 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002592 sw_if_index=self.pg2.sw_if_index,
2593 is_add=1)
2594
2595 # first VRF
2596 pkts = self.create_stream_in(self.pg0, self.pg2)
2597 self.pg0.add_stream(pkts)
2598 self.pg_enable_capture(self.pg_interfaces)
2599 self.pg_start()
2600 capture = self.pg2.get_capture(len(pkts))
2601 self.verify_capture_out(capture, nat_ip1)
2602
2603 # second VRF
2604 pkts = self.create_stream_in(self.pg1, self.pg2)
2605 self.pg1.add_stream(pkts)
2606 self.pg_enable_capture(self.pg_interfaces)
2607 self.pg_start()
2608 capture = self.pg2.get_capture(len(pkts))
2609 self.verify_capture_out(capture, nat_ip1)
2610
2611 def test_dynamic_ipless_interfaces(self):
2612 """ NAT44EI interfaces without configured IP address """
2613 self.create_routes_and_neigbors()
2614 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002615 flags = self.config_flags.NAT44_EI_IF_INSIDE
2616 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002617 sw_if_index=self.pg7.sw_if_index,
2618 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002619 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002620 sw_if_index=self.pg8.sw_if_index,
2621 is_add=1)
2622
2623 # in2out
2624 pkts = self.create_stream_in(self.pg7, self.pg8)
2625 self.pg7.add_stream(pkts)
2626 self.pg_enable_capture(self.pg_interfaces)
2627 self.pg_start()
2628 capture = self.pg8.get_capture(len(pkts))
2629 self.verify_capture_out(capture)
2630
2631 # out2in
2632 pkts = self.create_stream_out(self.pg8, self.nat_addr)
2633 self.pg8.add_stream(pkts)
2634 self.pg_enable_capture(self.pg_interfaces)
2635 self.pg_start()
2636 capture = self.pg7.get_capture(len(pkts))
2637 self.verify_capture_in(capture, self.pg7)
2638
2639 def test_static_ipless_interfaces(self):
2640 """ NAT44EI interfaces without configured IP address - 1:1 NAT """
2641
2642 self.create_routes_and_neigbors()
2643 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002644 flags = self.config_flags.NAT44_EI_IF_INSIDE
2645 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002646 sw_if_index=self.pg7.sw_if_index,
2647 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002648 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002649 sw_if_index=self.pg8.sw_if_index,
2650 is_add=1)
2651
2652 # out2in
2653 pkts = self.create_stream_out(self.pg8)
2654 self.pg8.add_stream(pkts)
2655 self.pg_enable_capture(self.pg_interfaces)
2656 self.pg_start()
2657 capture = self.pg7.get_capture(len(pkts))
2658 self.verify_capture_in(capture, self.pg7)
2659
2660 # in2out
2661 pkts = self.create_stream_in(self.pg7, self.pg8)
2662 self.pg7.add_stream(pkts)
2663 self.pg_enable_capture(self.pg_interfaces)
2664 self.pg_start()
2665 capture = self.pg8.get_capture(len(pkts))
2666 self.verify_capture_out(capture, self.nat_addr, True)
2667
2668 def test_static_with_port_ipless_interfaces(self):
2669 """ NAT44EI interfaces without configured IP address - 1:1 NAPT """
2670
2671 self.tcp_port_out = 30606
2672 self.udp_port_out = 30607
2673 self.icmp_id_out = 30608
2674
2675 self.create_routes_and_neigbors()
2676 self.nat44_add_address(self.nat_addr)
2677 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2678 self.tcp_port_in, self.tcp_port_out,
2679 proto=IP_PROTOS.tcp)
2680 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2681 self.udp_port_in, self.udp_port_out,
2682 proto=IP_PROTOS.udp)
2683 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2684 self.icmp_id_in, self.icmp_id_out,
2685 proto=IP_PROTOS.icmp)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002686 flags = self.config_flags.NAT44_EI_IF_INSIDE
2687 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002688 sw_if_index=self.pg7.sw_if_index,
2689 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002690 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002691 sw_if_index=self.pg8.sw_if_index,
2692 is_add=1)
2693
2694 # out2in
2695 pkts = self.create_stream_out(self.pg8)
2696 self.pg8.add_stream(pkts)
2697 self.pg_enable_capture(self.pg_interfaces)
2698 self.pg_start()
2699 capture = self.pg7.get_capture(len(pkts))
2700 self.verify_capture_in(capture, self.pg7)
2701
2702 # in2out
2703 pkts = self.create_stream_in(self.pg7, self.pg8)
2704 self.pg7.add_stream(pkts)
2705 self.pg_enable_capture(self.pg_interfaces)
2706 self.pg_start()
2707 capture = self.pg8.get_capture(len(pkts))
2708 self.verify_capture_out(capture)
2709
2710 def test_static_unknown_proto(self):
2711 """ NAT44EI 1:1 translate packet with unknown protocol """
2712 nat_ip = "10.0.0.10"
2713 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002714 flags = self.config_flags.NAT44_EI_IF_INSIDE
2715 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002716 sw_if_index=self.pg0.sw_if_index,
2717 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002718 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002719 sw_if_index=self.pg1.sw_if_index,
2720 is_add=1)
2721
2722 # in2out
2723 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2724 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2725 GRE() /
2726 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2727 TCP(sport=1234, dport=1234))
2728 self.pg0.add_stream(p)
2729 self.pg_enable_capture(self.pg_interfaces)
2730 self.pg_start()
2731 p = self.pg1.get_capture(1)
2732 packet = p[0]
2733 try:
2734 self.assertEqual(packet[IP].src, nat_ip)
2735 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2736 self.assertEqual(packet.haslayer(GRE), 1)
2737 self.assert_packet_checksums_valid(packet)
2738 except:
2739 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2740 raise
2741
2742 # out2in
2743 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2744 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2745 GRE() /
2746 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2747 TCP(sport=1234, dport=1234))
2748 self.pg1.add_stream(p)
2749 self.pg_enable_capture(self.pg_interfaces)
2750 self.pg_start()
2751 p = self.pg0.get_capture(1)
2752 packet = p[0]
2753 try:
2754 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2755 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2756 self.assertEqual(packet.haslayer(GRE), 1)
2757 self.assert_packet_checksums_valid(packet)
2758 except:
2759 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2760 raise
2761
2762 def test_hairpinning_static_unknown_proto(self):
2763 """ NAT44EI 1:1 translate packet with unknown protocol - hairpinning
2764 """
2765
2766 host = self.pg0.remote_hosts[0]
2767 server = self.pg0.remote_hosts[1]
2768
2769 host_nat_ip = "10.0.0.10"
2770 server_nat_ip = "10.0.0.11"
2771
2772 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2773 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002774 flags = self.config_flags.NAT44_EI_IF_INSIDE
2775 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002776 sw_if_index=self.pg0.sw_if_index,
2777 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002778 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002779 sw_if_index=self.pg1.sw_if_index,
2780 is_add=1)
2781
2782 # host to server
2783 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2784 IP(src=host.ip4, dst=server_nat_ip) /
2785 GRE() /
2786 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2787 TCP(sport=1234, dport=1234))
2788 self.pg0.add_stream(p)
2789 self.pg_enable_capture(self.pg_interfaces)
2790 self.pg_start()
2791 p = self.pg0.get_capture(1)
2792 packet = p[0]
2793 try:
2794 self.assertEqual(packet[IP].src, host_nat_ip)
2795 self.assertEqual(packet[IP].dst, server.ip4)
2796 self.assertEqual(packet.haslayer(GRE), 1)
2797 self.assert_packet_checksums_valid(packet)
2798 except:
2799 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2800 raise
2801
2802 # server to host
2803 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2804 IP(src=server.ip4, dst=host_nat_ip) /
2805 GRE() /
2806 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2807 TCP(sport=1234, dport=1234))
2808 self.pg0.add_stream(p)
2809 self.pg_enable_capture(self.pg_interfaces)
2810 self.pg_start()
2811 p = self.pg0.get_capture(1)
2812 packet = p[0]
2813 try:
2814 self.assertEqual(packet[IP].src, server_nat_ip)
2815 self.assertEqual(packet[IP].dst, host.ip4)
2816 self.assertEqual(packet.haslayer(GRE), 1)
2817 self.assert_packet_checksums_valid(packet)
2818 except:
2819 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2820 raise
2821
2822 def test_output_feature(self):
2823 """ NAT44EI output feature (in2out postrouting) """
2824 self.nat44_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02002825 self.vapi.nat44_ei_add_del_output_interface(
2826 sw_if_index=self.pg3.sw_if_index, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01002827
2828 # in2out
2829 pkts = self.create_stream_in(self.pg0, self.pg3)
2830 self.pg0.add_stream(pkts)
2831 self.pg_enable_capture(self.pg_interfaces)
2832 self.pg_start()
2833 capture = self.pg3.get_capture(len(pkts))
2834 self.verify_capture_out(capture)
2835
2836 # out2in
2837 pkts = self.create_stream_out(self.pg3)
2838 self.pg3.add_stream(pkts)
2839 self.pg_enable_capture(self.pg_interfaces)
2840 self.pg_start()
2841 capture = self.pg0.get_capture(len(pkts))
2842 self.verify_capture_in(capture, self.pg0)
2843
2844 # from non-NAT interface to NAT inside interface
2845 pkts = self.create_stream_in(self.pg2, self.pg0)
2846 self.pg2.add_stream(pkts)
2847 self.pg_enable_capture(self.pg_interfaces)
2848 self.pg_start()
2849 capture = self.pg0.get_capture(len(pkts))
2850 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2851
2852 def test_output_feature_vrf_aware(self):
2853 """ NAT44EI output feature VRF aware (in2out postrouting) """
2854 nat_ip_vrf10 = "10.0.0.10"
2855 nat_ip_vrf20 = "10.0.0.20"
2856
2857 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2858 [VppRoutePath(self.pg3.remote_ip4,
2859 self.pg3.sw_if_index)],
2860 table_id=10)
2861 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2862 [VppRoutePath(self.pg3.remote_ip4,
2863 self.pg3.sw_if_index)],
2864 table_id=20)
2865 r1.add_vpp_config()
2866 r2.add_vpp_config()
2867
2868 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2869 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
Filip Varga9c25eb12021-10-21 13:00:27 +02002870 self.vapi.nat44_ei_add_del_output_interface(
2871 sw_if_index=self.pg3.sw_if_index, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01002872
2873 # in2out VRF 10
2874 pkts = self.create_stream_in(self.pg4, self.pg3)
2875 self.pg4.add_stream(pkts)
2876 self.pg_enable_capture(self.pg_interfaces)
2877 self.pg_start()
2878 capture = self.pg3.get_capture(len(pkts))
2879 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2880
2881 # out2in VRF 10
2882 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2883 self.pg3.add_stream(pkts)
2884 self.pg_enable_capture(self.pg_interfaces)
2885 self.pg_start()
2886 capture = self.pg4.get_capture(len(pkts))
2887 self.verify_capture_in(capture, self.pg4)
2888
2889 # in2out VRF 20
2890 pkts = self.create_stream_in(self.pg6, self.pg3)
2891 self.pg6.add_stream(pkts)
2892 self.pg_enable_capture(self.pg_interfaces)
2893 self.pg_start()
2894 capture = self.pg3.get_capture(len(pkts))
2895 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2896
2897 # out2in VRF 20
2898 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2899 self.pg3.add_stream(pkts)
2900 self.pg_enable_capture(self.pg_interfaces)
2901 self.pg_start()
2902 capture = self.pg6.get_capture(len(pkts))
2903 self.verify_capture_in(capture, self.pg6)
2904
2905 def test_output_feature_hairpinning(self):
2906 """ NAT44EI output feature hairpinning (in2out postrouting) """
2907 host = self.pg0.remote_hosts[0]
2908 server = self.pg0.remote_hosts[1]
2909 host_in_port = 1234
2910 host_out_port = 0
2911 server_in_port = 5678
2912 server_out_port = 8765
2913
2914 self.nat44_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02002915 self.vapi.nat44_ei_add_del_output_interface(
2916 sw_if_index=self.pg0.sw_if_index, is_add=1)
2917 self.vapi.nat44_ei_add_del_output_interface(
2918 sw_if_index=self.pg1.sw_if_index, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01002919
2920 # add static mapping for server
2921 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2922 server_in_port, server_out_port,
2923 proto=IP_PROTOS.tcp)
2924
2925 # send packet from host to server
2926 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2927 IP(src=host.ip4, dst=self.nat_addr) /
2928 TCP(sport=host_in_port, dport=server_out_port))
2929 self.pg0.add_stream(p)
2930 self.pg_enable_capture(self.pg_interfaces)
2931 self.pg_start()
2932 capture = self.pg0.get_capture(1)
2933 p = capture[0]
2934 try:
2935 ip = p[IP]
2936 tcp = p[TCP]
2937 self.assertEqual(ip.src, self.nat_addr)
2938 self.assertEqual(ip.dst, server.ip4)
2939 self.assertNotEqual(tcp.sport, host_in_port)
2940 self.assertEqual(tcp.dport, server_in_port)
2941 self.assert_packet_checksums_valid(p)
2942 host_out_port = tcp.sport
2943 except:
2944 self.logger.error(ppp("Unexpected or invalid packet:", p))
2945 raise
2946
2947 # send reply from server to host
2948 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2949 IP(src=server.ip4, dst=self.nat_addr) /
2950 TCP(sport=server_in_port, dport=host_out_port))
2951 self.pg0.add_stream(p)
2952 self.pg_enable_capture(self.pg_interfaces)
2953 self.pg_start()
2954 capture = self.pg0.get_capture(1)
2955 p = capture[0]
2956 try:
2957 ip = p[IP]
2958 tcp = p[TCP]
2959 self.assertEqual(ip.src, self.nat_addr)
2960 self.assertEqual(ip.dst, host.ip4)
2961 self.assertEqual(tcp.sport, server_out_port)
2962 self.assertEqual(tcp.dport, host_in_port)
2963 self.assert_packet_checksums_valid(p)
2964 except:
2965 self.logger.error(ppp("Unexpected or invalid packet:", p))
2966 raise
2967
2968 def test_one_armed_nat44(self):
2969 """ NAT44EI One armed NAT """
2970 remote_host = self.pg9.remote_hosts[0]
2971 local_host = self.pg9.remote_hosts[1]
2972 external_port = 0
2973
2974 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002975 flags = self.config_flags.NAT44_EI_IF_INSIDE
2976 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002977 sw_if_index=self.pg9.sw_if_index,
2978 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01002979 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01002980 sw_if_index=self.pg9.sw_if_index,
2981 flags=flags, is_add=1)
2982
2983 # in2out
2984 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2985 IP(src=local_host.ip4, dst=remote_host.ip4) /
2986 TCP(sport=12345, dport=80))
2987 self.pg9.add_stream(p)
2988 self.pg_enable_capture(self.pg_interfaces)
2989 self.pg_start()
2990 capture = self.pg9.get_capture(1)
2991 p = capture[0]
2992 try:
2993 ip = p[IP]
2994 tcp = p[TCP]
2995 self.assertEqual(ip.src, self.nat_addr)
2996 self.assertEqual(ip.dst, remote_host.ip4)
2997 self.assertNotEqual(tcp.sport, 12345)
2998 external_port = tcp.sport
2999 self.assertEqual(tcp.dport, 80)
3000 self.assert_packet_checksums_valid(p)
3001 except:
3002 self.logger.error(ppp("Unexpected or invalid packet:", p))
3003 raise
3004
3005 # out2in
3006 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3007 IP(src=remote_host.ip4, dst=self.nat_addr) /
3008 TCP(sport=80, dport=external_port))
3009 self.pg9.add_stream(p)
3010 self.pg_enable_capture(self.pg_interfaces)
3011 self.pg_start()
3012 capture = self.pg9.get_capture(1)
3013 p = capture[0]
3014 try:
3015 ip = p[IP]
3016 tcp = p[TCP]
3017 self.assertEqual(ip.src, remote_host.ip4)
3018 self.assertEqual(ip.dst, local_host.ip4)
3019 self.assertEqual(tcp.sport, 80)
3020 self.assertEqual(tcp.dport, 12345)
3021 self.assert_packet_checksums_valid(p)
3022 except:
3023 self.logger.error(ppp("Unexpected or invalid packet:", p))
3024 raise
3025
Klement Sekerac294c502021-03-24 17:20:40 +01003026 if self.vpp_worker_count > 1:
3027 node = "nat44-ei-handoff-classify"
3028 else:
3029 node = "nat44-ei-classify"
3030
3031 err = self.statistics.get_err_counter('/err/%s/next in2out' % node)
Filip Varga18f1e412020-12-03 15:27:40 +01003032 self.assertEqual(err, 1)
Klement Sekerac294c502021-03-24 17:20:40 +01003033 err = self.statistics.get_err_counter('/err/%s/next out2in' % node)
Filip Varga18f1e412020-12-03 15:27:40 +01003034 self.assertEqual(err, 1)
3035
3036 def test_del_session(self):
3037 """ NAT44EI delete session """
3038 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003039 flags = self.config_flags.NAT44_EI_IF_INSIDE
3040 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003041 sw_if_index=self.pg0.sw_if_index,
3042 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003043 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003044 sw_if_index=self.pg1.sw_if_index,
3045 is_add=1)
3046
3047 pkts = self.create_stream_in(self.pg0, self.pg1)
3048 self.pg0.add_stream(pkts)
3049 self.pg_enable_capture(self.pg_interfaces)
3050 self.pg_start()
3051 self.pg1.get_capture(len(pkts))
3052
Filip Varga0eaf4e62021-02-17 14:34:54 +01003053 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003054 nsessions = len(sessions)
3055
Filip Varga0eaf4e62021-02-17 14:34:54 +01003056 self.vapi.nat44_ei_del_session(
3057 address=sessions[0].inside_ip_address,
3058 port=sessions[0].inside_port,
3059 protocol=sessions[0].protocol,
3060 flags=self.config_flags.NAT44_EI_IF_INSIDE)
Filip Varga18f1e412020-12-03 15:27:40 +01003061
Filip Varga0eaf4e62021-02-17 14:34:54 +01003062 self.vapi.nat44_ei_del_session(
3063 address=sessions[1].outside_ip_address,
3064 port=sessions[1].outside_port,
3065 protocol=sessions[1].protocol)
3066
3067 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003068 self.assertEqual(nsessions - len(sessions), 2)
3069
Filip Varga0eaf4e62021-02-17 14:34:54 +01003070 self.vapi.nat44_ei_del_session(
3071 address=sessions[0].inside_ip_address,
3072 port=sessions[0].inside_port,
3073 protocol=sessions[0].protocol,
3074 flags=self.config_flags.NAT44_EI_IF_INSIDE)
Filip Varga18f1e412020-12-03 15:27:40 +01003075
3076 self.verify_no_nat44_user()
3077
3078 def test_frag_in_order(self):
3079 """ NAT44EI translate fragments arriving in order """
3080
3081 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003082 flags = self.config_flags.NAT44_EI_IF_INSIDE
3083 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003084 sw_if_index=self.pg0.sw_if_index,
3085 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003086 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003087 sw_if_index=self.pg1.sw_if_index,
3088 is_add=1)
3089
3090 self.frag_in_order(proto=IP_PROTOS.tcp)
3091 self.frag_in_order(proto=IP_PROTOS.udp)
3092 self.frag_in_order(proto=IP_PROTOS.icmp)
3093
3094 def test_frag_forwarding(self):
3095 """ NAT44EI forwarding fragment test """
Filip Varga0eaf4e62021-02-17 14:34:54 +01003096 self.vapi.nat44_ei_add_del_interface_addr(
Filip Varga18f1e412020-12-03 15:27:40 +01003097 is_add=1,
3098 sw_if_index=self.pg1.sw_if_index)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003099 flags = self.config_flags.NAT44_EI_IF_INSIDE
3100 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003101 sw_if_index=self.pg0.sw_if_index,
3102 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003103 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003104 sw_if_index=self.pg1.sw_if_index,
3105 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003106 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003107
3108 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3109 pkts = self.create_stream_frag(self.pg1,
3110 self.pg0.remote_ip4,
3111 4789,
3112 4789,
3113 data,
3114 proto=IP_PROTOS.udp)
3115 self.pg1.add_stream(pkts)
3116 self.pg_enable_capture(self.pg_interfaces)
3117 self.pg_start()
3118 frags = self.pg0.get_capture(len(pkts))
3119 p = self.reass_frags_and_verify(frags,
3120 self.pg1.remote_ip4,
3121 self.pg0.remote_ip4)
3122 self.assertEqual(p[UDP].sport, 4789)
3123 self.assertEqual(p[UDP].dport, 4789)
3124 self.assertEqual(data, p[Raw].load)
3125
3126 def test_reass_hairpinning(self):
3127 """ NAT44EI fragments hairpinning """
3128
3129 server_addr = self.pg0.remote_hosts[1].ip4
3130 host_in_port = random.randint(1025, 65535)
3131 server_in_port = random.randint(1025, 65535)
3132 server_out_port = random.randint(1025, 65535)
3133
3134 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003135 flags = self.config_flags.NAT44_EI_IF_INSIDE
3136 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003137 sw_if_index=self.pg0.sw_if_index,
3138 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003139 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003140 sw_if_index=self.pg1.sw_if_index,
3141 is_add=1)
3142 # add static mapping for server
3143 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3144 server_in_port,
3145 server_out_port,
3146 proto=IP_PROTOS.tcp)
3147 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3148 server_in_port,
3149 server_out_port,
3150 proto=IP_PROTOS.udp)
3151 self.nat44_add_static_mapping(server_addr, self.nat_addr)
3152
3153 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3154 host_in_port, proto=IP_PROTOS.tcp)
3155 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3156 host_in_port, proto=IP_PROTOS.udp)
3157 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3158 host_in_port, proto=IP_PROTOS.icmp)
3159
3160 def test_frag_out_of_order(self):
3161 """ NAT44EI translate fragments arriving out of order """
3162
3163 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003164 flags = self.config_flags.NAT44_EI_IF_INSIDE
3165 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003166 sw_if_index=self.pg0.sw_if_index,
3167 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003168 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003169 sw_if_index=self.pg1.sw_if_index,
3170 is_add=1)
3171
3172 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3173 self.frag_out_of_order(proto=IP_PROTOS.udp)
3174 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3175
3176 def test_port_restricted(self):
3177 """ NAT44EI Port restricted NAT44EI (MAP-E CE) """
3178 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003179 flags = self.config_flags.NAT44_EI_IF_INSIDE
3180 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003181 sw_if_index=self.pg0.sw_if_index,
3182 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003183 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003184 sw_if_index=self.pg1.sw_if_index,
3185 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003186 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=1,
3187 psid_offset=6,
3188 psid_length=6,
3189 psid=10)
Filip Varga18f1e412020-12-03 15:27:40 +01003190
3191 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3192 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3193 TCP(sport=4567, dport=22))
3194 self.pg0.add_stream(p)
3195 self.pg_enable_capture(self.pg_interfaces)
3196 self.pg_start()
3197 capture = self.pg1.get_capture(1)
3198 p = capture[0]
3199 try:
3200 ip = p[IP]
3201 tcp = p[TCP]
3202 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3203 self.assertEqual(ip.src, self.nat_addr)
3204 self.assertEqual(tcp.dport, 22)
3205 self.assertNotEqual(tcp.sport, 4567)
3206 self.assertEqual((tcp.sport >> 6) & 63, 10)
3207 self.assert_packet_checksums_valid(p)
3208 except:
3209 self.logger.error(ppp("Unexpected or invalid packet:", p))
3210 raise
3211
3212 def test_port_range(self):
3213 """ NAT44EI External address port range """
3214 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003215 flags = self.config_flags.NAT44_EI_IF_INSIDE
3216 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003217 sw_if_index=self.pg0.sw_if_index,
3218 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003219 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003220 sw_if_index=self.pg1.sw_if_index,
3221 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003222 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=2,
3223 start_port=1025,
3224 end_port=1027)
Filip Varga18f1e412020-12-03 15:27:40 +01003225
3226 pkts = []
3227 for port in range(0, 5):
3228 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3229 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3230 TCP(sport=1125 + port))
3231 pkts.append(p)
3232 self.pg0.add_stream(pkts)
3233 self.pg_enable_capture(self.pg_interfaces)
3234 self.pg_start()
3235 capture = self.pg1.get_capture(3)
3236 for p in capture:
3237 tcp = p[TCP]
3238 self.assertGreaterEqual(tcp.sport, 1025)
3239 self.assertLessEqual(tcp.sport, 1027)
3240
3241 def test_multiple_outside_vrf(self):
3242 """ NAT44EI Multiple outside VRF """
3243 vrf_id1 = 1
3244 vrf_id2 = 2
3245
3246 self.pg1.unconfig_ip4()
3247 self.pg2.unconfig_ip4()
3248 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3249 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3250 self.pg1.set_table_ip4(vrf_id1)
3251 self.pg2.set_table_ip4(vrf_id2)
3252 self.pg1.config_ip4()
3253 self.pg2.config_ip4()
3254 self.pg1.resolve_arp()
3255 self.pg2.resolve_arp()
3256
3257 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003258 flags = self.config_flags.NAT44_EI_IF_INSIDE
3259 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003260 sw_if_index=self.pg0.sw_if_index,
3261 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003262 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003263 sw_if_index=self.pg1.sw_if_index,
3264 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003265 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003266 sw_if_index=self.pg2.sw_if_index,
3267 is_add=1)
3268
3269 try:
3270 # first VRF
3271 pkts = self.create_stream_in(self.pg0, self.pg1)
3272 self.pg0.add_stream(pkts)
3273 self.pg_enable_capture(self.pg_interfaces)
3274 self.pg_start()
3275 capture = self.pg1.get_capture(len(pkts))
3276 self.verify_capture_out(capture, self.nat_addr)
3277
3278 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3279 self.pg1.add_stream(pkts)
3280 self.pg_enable_capture(self.pg_interfaces)
3281 self.pg_start()
3282 capture = self.pg0.get_capture(len(pkts))
3283 self.verify_capture_in(capture, self.pg0)
3284
3285 self.tcp_port_in = 60303
3286 self.udp_port_in = 60304
3287 self.icmp_id_in = 60305
3288
3289 # second VRF
3290 pkts = self.create_stream_in(self.pg0, self.pg2)
3291 self.pg0.add_stream(pkts)
3292 self.pg_enable_capture(self.pg_interfaces)
3293 self.pg_start()
3294 capture = self.pg2.get_capture(len(pkts))
3295 self.verify_capture_out(capture, self.nat_addr)
3296
3297 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3298 self.pg2.add_stream(pkts)
3299 self.pg_enable_capture(self.pg_interfaces)
3300 self.pg_start()
3301 capture = self.pg0.get_capture(len(pkts))
3302 self.verify_capture_in(capture, self.pg0)
3303
3304 finally:
3305 self.nat44_add_address(self.nat_addr, is_add=0)
3306 self.pg1.unconfig_ip4()
3307 self.pg2.unconfig_ip4()
3308 self.pg1.set_table_ip4(0)
3309 self.pg2.set_table_ip4(0)
3310 self.pg1.config_ip4()
3311 self.pg2.config_ip4()
3312 self.pg1.resolve_arp()
3313 self.pg2.resolve_arp()
3314
3315 def test_mss_clamping(self):
3316 """ NAT44EI TCP MSS clamping """
3317 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003318 flags = self.config_flags.NAT44_EI_IF_INSIDE
3319 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003320 sw_if_index=self.pg0.sw_if_index,
3321 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003322 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003323 sw_if_index=self.pg1.sw_if_index,
3324 is_add=1)
3325
3326 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3327 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3328 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3329 flags="S", options=[('MSS', 1400)]))
3330
Filip Varga0eaf4e62021-02-17 14:34:54 +01003331 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1000)
Filip Varga18f1e412020-12-03 15:27:40 +01003332 self.pg0.add_stream(p)
3333 self.pg_enable_capture(self.pg_interfaces)
3334 self.pg_start()
3335 capture = self.pg1.get_capture(1)
3336 # Negotiated MSS value greater than configured - changed
3337 self.verify_mss_value(capture[0], 1000)
3338
Filip Varga0eaf4e62021-02-17 14:34:54 +01003339 self.vapi.nat44_ei_set_mss_clamping(enable=0, mss_value=1500)
Filip Varga18f1e412020-12-03 15:27:40 +01003340 self.pg0.add_stream(p)
3341 self.pg_enable_capture(self.pg_interfaces)
3342 self.pg_start()
3343 capture = self.pg1.get_capture(1)
3344 # MSS clamping disabled - negotiated MSS unchanged
3345 self.verify_mss_value(capture[0], 1400)
3346
Filip Varga0eaf4e62021-02-17 14:34:54 +01003347 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1500)
Filip Varga18f1e412020-12-03 15:27:40 +01003348 self.pg0.add_stream(p)
3349 self.pg_enable_capture(self.pg_interfaces)
3350 self.pg_start()
3351 capture = self.pg1.get_capture(1)
3352 # Negotiated MSS value smaller than configured - unchanged
3353 self.verify_mss_value(capture[0], 1400)
3354
3355 def test_ha_send(self):
3356 """ NAT44EI Send HA session synchronization events (active) """
Filip Varga0eaf4e62021-02-17 14:34:54 +01003357 flags = self.config_flags.NAT44_EI_IF_INSIDE
3358 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003359 sw_if_index=self.pg0.sw_if_index,
3360 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003361 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003362 sw_if_index=self.pg1.sw_if_index,
3363 is_add=1)
3364 self.nat44_add_address(self.nat_addr)
3365
Filip Varga0eaf4e62021-02-17 14:34:54 +01003366 self.vapi.nat44_ei_ha_set_listener(
3367 ip_address=self.pg3.local_ip4, port=12345, path_mtu=512)
3368 self.vapi.nat44_ei_ha_set_failover(
3369 ip_address=self.pg3.remote_ip4, port=12346,
3370 session_refresh_interval=10)
Filip Varga18f1e412020-12-03 15:27:40 +01003371 bind_layers(UDP, HANATStateSync, sport=12345)
3372
3373 # create sessions
3374 pkts = self.create_stream_in(self.pg0, self.pg1)
3375 self.pg0.add_stream(pkts)
3376 self.pg_enable_capture(self.pg_interfaces)
3377 self.pg_start()
3378 capture = self.pg1.get_capture(len(pkts))
3379 self.verify_capture_out(capture)
3380 # active send HA events
Filip Varga0eaf4e62021-02-17 14:34:54 +01003381 self.vapi.nat44_ei_ha_flush()
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003382 stats = self.statistics['/nat44-ei/ha/add-event-send']
3383 self.assertEqual(stats[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01003384 capture = self.pg3.get_capture(1)
3385 p = capture[0]
3386 self.assert_packet_checksums_valid(p)
3387 try:
3388 ip = p[IP]
3389 udp = p[UDP]
3390 hanat = p[HANATStateSync]
3391 except IndexError:
3392 self.logger.error(ppp("Invalid packet:", p))
3393 raise
3394 else:
3395 self.assertEqual(ip.src, self.pg3.local_ip4)
3396 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3397 self.assertEqual(udp.sport, 12345)
3398 self.assertEqual(udp.dport, 12346)
3399 self.assertEqual(hanat.version, 1)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003400 # self.assertEqual(hanat.thread_index, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003401 self.assertEqual(hanat.count, 3)
3402 seq = hanat.sequence_number
3403 for event in hanat.events:
3404 self.assertEqual(event.event_type, 1)
3405 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3406 self.assertEqual(event.out_addr, self.nat_addr)
3407 self.assertEqual(event.fib_index, 0)
3408
3409 # ACK received events
3410 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3411 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3412 UDP(sport=12346, dport=12345) /
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003413 HANATStateSync(sequence_number=seq, flags='ACK',
3414 thread_index=hanat.thread_index))
Filip Varga18f1e412020-12-03 15:27:40 +01003415 self.pg3.add_stream(ack)
3416 self.pg_start()
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003417 stats = self.statistics['/nat44-ei/ha/ack-recv']
3418 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003419
3420 # delete one session
3421 self.pg_enable_capture(self.pg_interfaces)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003422 self.vapi.nat44_ei_del_session(
3423 address=self.pg0.remote_ip4, port=self.tcp_port_in,
3424 protocol=IP_PROTOS.tcp, flags=self.config_flags.NAT44_EI_IF_INSIDE)
3425 self.vapi.nat44_ei_ha_flush()
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003426 stats = self.statistics['/nat44-ei/ha/del-event-send']
3427 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003428 capture = self.pg3.get_capture(1)
3429 p = capture[0]
3430 try:
3431 hanat = p[HANATStateSync]
3432 except IndexError:
3433 self.logger.error(ppp("Invalid packet:", p))
3434 raise
3435 else:
3436 self.assertGreater(hanat.sequence_number, seq)
3437
3438 # do not send ACK, active retry send HA event again
3439 self.pg_enable_capture(self.pg_interfaces)
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003440 self.virtual_sleep(12)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003441 stats = self.statistics['/nat44-ei/ha/retry-count']
3442 self.assertEqual(stats[:, 0].sum(), 3)
3443 stats = self.statistics['/nat44-ei/ha/missed-count']
3444 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003445 capture = self.pg3.get_capture(3)
3446 for packet in capture:
3447 self.assertEqual(packet, p)
3448
3449 # session counters refresh
3450 pkts = self.create_stream_out(self.pg1)
3451 self.pg1.add_stream(pkts)
3452 self.pg_enable_capture(self.pg_interfaces)
3453 self.pg_start()
3454 self.pg0.get_capture(2)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003455 self.vapi.nat44_ei_ha_flush()
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003456 stats = self.statistics['/nat44-ei/ha/refresh-event-send']
3457 self.assertEqual(stats[:, 0].sum(), 2)
Filip Varga18f1e412020-12-03 15:27:40 +01003458 capture = self.pg3.get_capture(1)
3459 p = capture[0]
3460 self.assert_packet_checksums_valid(p)
3461 try:
3462 ip = p[IP]
3463 udp = p[UDP]
3464 hanat = p[HANATStateSync]
3465 except IndexError:
3466 self.logger.error(ppp("Invalid packet:", p))
3467 raise
3468 else:
3469 self.assertEqual(ip.src, self.pg3.local_ip4)
3470 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3471 self.assertEqual(udp.sport, 12345)
3472 self.assertEqual(udp.dport, 12346)
3473 self.assertEqual(hanat.version, 1)
3474 self.assertEqual(hanat.count, 2)
3475 seq = hanat.sequence_number
3476 for event in hanat.events:
3477 self.assertEqual(event.event_type, 3)
3478 self.assertEqual(event.out_addr, self.nat_addr)
3479 self.assertEqual(event.fib_index, 0)
3480 self.assertEqual(event.total_pkts, 2)
3481 self.assertGreater(event.total_bytes, 0)
3482
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003483 stats = self.statistics['/nat44-ei/ha/ack-recv']
Filip Varga18f1e412020-12-03 15:27:40 +01003484 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3485 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3486 UDP(sport=12346, dport=12345) /
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003487 HANATStateSync(sequence_number=seq, flags='ACK',
3488 thread_index=hanat.thread_index))
Filip Varga18f1e412020-12-03 15:27:40 +01003489 self.pg3.add_stream(ack)
3490 self.pg_start()
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003491 stats = self.statistics['/nat44-ei/ha/ack-recv']
3492 self.assertEqual(stats[:, 0].sum(), 2)
Filip Varga18f1e412020-12-03 15:27:40 +01003493
3494 def test_ha_recv(self):
3495 """ NAT44EI Receive HA session synchronization events (passive) """
3496 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003497 flags = self.config_flags.NAT44_EI_IF_INSIDE
3498 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003499 sw_if_index=self.pg0.sw_if_index,
3500 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003501 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003502 sw_if_index=self.pg1.sw_if_index,
3503 is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003504 self.vapi.nat44_ei_ha_set_listener(ip_address=self.pg3.local_ip4,
3505 port=12345, path_mtu=512)
Filip Varga18f1e412020-12-03 15:27:40 +01003506 bind_layers(UDP, HANATStateSync, sport=12345)
3507
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003508 # this is a bit tricky - HA dictates thread index due to how it's
3509 # designed, but once we use HA to create a session, we also want
3510 # to pass a packet through said session. so the session must end
3511 # up on the correct thread from both directions - in2out (based on
3512 # IP address) and out2in (based on outside port)
3513
3514 # first choose a thread index which is correct for IP
3515 thread_index = get_nat44_ei_in2out_worker_index(self.pg0.remote_ip4,
3516 self.vpp_worker_count)
3517
3518 # now pick a port which is correct for given thread
3519 port_per_thread = int((0xffff-1024) / max(1, self.vpp_worker_count))
3520 self.tcp_port_out = 1024 + random.randint(1, port_per_thread)
3521 self.udp_port_out = 1024 + random.randint(1, port_per_thread)
3522 if self.vpp_worker_count > 0:
3523 self.tcp_port_out += port_per_thread * (thread_index - 1)
3524 self.udp_port_out += port_per_thread * (thread_index - 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003525
3526 # send HA session add events to failover/passive
3527 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3528 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3529 UDP(sport=12346, dport=12345) /
3530 HANATStateSync(sequence_number=1, events=[
3531 Event(event_type='add', protocol='tcp',
3532 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3533 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3534 eh_addr=self.pg1.remote_ip4,
3535 ehn_addr=self.pg1.remote_ip4,
3536 eh_port=self.tcp_external_port,
3537 ehn_port=self.tcp_external_port, fib_index=0),
3538 Event(event_type='add', protocol='udp',
3539 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3540 in_port=self.udp_port_in, out_port=self.udp_port_out,
3541 eh_addr=self.pg1.remote_ip4,
3542 ehn_addr=self.pg1.remote_ip4,
3543 eh_port=self.udp_external_port,
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003544 ehn_port=self.udp_external_port, fib_index=0)],
3545 thread_index=thread_index))
Filip Varga18f1e412020-12-03 15:27:40 +01003546
3547 self.pg3.add_stream(p)
3548 self.pg_enable_capture(self.pg_interfaces)
3549 self.pg_start()
3550 # receive ACK
3551 capture = self.pg3.get_capture(1)
3552 p = capture[0]
3553 try:
3554 hanat = p[HANATStateSync]
3555 except IndexError:
3556 self.logger.error(ppp("Invalid packet:", p))
3557 raise
3558 else:
3559 self.assertEqual(hanat.sequence_number, 1)
3560 self.assertEqual(hanat.flags, 'ACK')
3561 self.assertEqual(hanat.version, 1)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003562 self.assertEqual(hanat.thread_index, thread_index)
3563 stats = self.statistics['/nat44-ei/ha/ack-send']
3564 self.assertEqual(stats[:, 0].sum(), 1)
3565 stats = self.statistics['/nat44-ei/ha/add-event-recv']
3566 self.assertEqual(stats[:, 0].sum(), 2)
3567 users = self.statistics['/nat44-ei/total-users']
3568 self.assertEqual(users[:, 0].sum(), 1)
3569 sessions = self.statistics['/nat44-ei/total-sessions']
3570 self.assertEqual(sessions[:, 0].sum(), 2)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003571 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01003572 self.assertEqual(len(users), 1)
3573 self.assertEqual(str(users[0].ip_address),
3574 self.pg0.remote_ip4)
3575 # there should be 2 sessions created by HA
Filip Varga0eaf4e62021-02-17 14:34:54 +01003576 sessions = self.vapi.nat44_ei_user_session_dump(
3577 users[0].ip_address, users[0].vrf_id)
Filip Varga18f1e412020-12-03 15:27:40 +01003578 self.assertEqual(len(sessions), 2)
3579 for session in sessions:
3580 self.assertEqual(str(session.inside_ip_address),
3581 self.pg0.remote_ip4)
3582 self.assertEqual(str(session.outside_ip_address),
3583 self.nat_addr)
3584 self.assertIn(session.inside_port,
3585 [self.tcp_port_in, self.udp_port_in])
3586 self.assertIn(session.outside_port,
3587 [self.tcp_port_out, self.udp_port_out])
3588 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3589
3590 # send HA session delete event to failover/passive
3591 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3592 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3593 UDP(sport=12346, dport=12345) /
3594 HANATStateSync(sequence_number=2, events=[
3595 Event(event_type='del', protocol='udp',
3596 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3597 in_port=self.udp_port_in, out_port=self.udp_port_out,
3598 eh_addr=self.pg1.remote_ip4,
3599 ehn_addr=self.pg1.remote_ip4,
3600 eh_port=self.udp_external_port,
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003601 ehn_port=self.udp_external_port, fib_index=0)],
3602 thread_index=thread_index))
Filip Varga18f1e412020-12-03 15:27:40 +01003603
3604 self.pg3.add_stream(p)
3605 self.pg_enable_capture(self.pg_interfaces)
3606 self.pg_start()
3607 # receive ACK
3608 capture = self.pg3.get_capture(1)
3609 p = capture[0]
3610 try:
3611 hanat = p[HANATStateSync]
3612 except IndexError:
3613 self.logger.error(ppp("Invalid packet:", p))
3614 raise
3615 else:
3616 self.assertEqual(hanat.sequence_number, 2)
3617 self.assertEqual(hanat.flags, 'ACK')
3618 self.assertEqual(hanat.version, 1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003619 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01003620 self.assertEqual(len(users), 1)
3621 self.assertEqual(str(users[0].ip_address),
3622 self.pg0.remote_ip4)
3623 # now we should have only 1 session, 1 deleted by HA
Filip Varga0eaf4e62021-02-17 14:34:54 +01003624 sessions = self.vapi.nat44_ei_user_session_dump(users[0].ip_address,
3625 users[0].vrf_id)
Filip Varga18f1e412020-12-03 15:27:40 +01003626 self.assertEqual(len(sessions), 1)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003627 stats = self.statistics['/nat44-ei/ha/del-event-recv']
3628 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003629
Filip Varga0eaf4e62021-02-17 14:34:54 +01003630 stats = self.statistics.get_err_counter(
3631 '/err/nat44-ei-ha/pkts-processed')
Filip Varga18f1e412020-12-03 15:27:40 +01003632 self.assertEqual(stats, 2)
3633
3634 # send HA session refresh event to failover/passive
3635 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3636 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3637 UDP(sport=12346, dport=12345) /
3638 HANATStateSync(sequence_number=3, events=[
3639 Event(event_type='refresh', protocol='tcp',
3640 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3641 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3642 eh_addr=self.pg1.remote_ip4,
3643 ehn_addr=self.pg1.remote_ip4,
3644 eh_port=self.tcp_external_port,
3645 ehn_port=self.tcp_external_port, fib_index=0,
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003646 total_bytes=1024, total_pkts=2)],
3647 thread_index=thread_index))
Filip Varga18f1e412020-12-03 15:27:40 +01003648 self.pg3.add_stream(p)
3649 self.pg_enable_capture(self.pg_interfaces)
3650 self.pg_start()
3651 # receive ACK
3652 capture = self.pg3.get_capture(1)
3653 p = capture[0]
3654 try:
3655 hanat = p[HANATStateSync]
3656 except IndexError:
3657 self.logger.error(ppp("Invalid packet:", p))
3658 raise
3659 else:
3660 self.assertEqual(hanat.sequence_number, 3)
3661 self.assertEqual(hanat.flags, 'ACK')
3662 self.assertEqual(hanat.version, 1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003663 users = self.vapi.nat44_ei_user_dump()
Filip Varga18f1e412020-12-03 15:27:40 +01003664 self.assertEqual(len(users), 1)
3665 self.assertEqual(str(users[0].ip_address),
3666 self.pg0.remote_ip4)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003667 sessions = self.vapi.nat44_ei_user_session_dump(
3668 users[0].ip_address, users[0].vrf_id)
Filip Varga18f1e412020-12-03 15:27:40 +01003669 self.assertEqual(len(sessions), 1)
3670 session = sessions[0]
3671 self.assertEqual(session.total_bytes, 1024)
3672 self.assertEqual(session.total_pkts, 2)
Klement Sekeraeafb5db2021-03-15 16:34:01 +01003673 stats = self.statistics['/nat44-ei/ha/refresh-event-recv']
3674 self.assertEqual(stats[:, 0].sum(), 1)
Filip Varga18f1e412020-12-03 15:27:40 +01003675
Filip Varga0eaf4e62021-02-17 14:34:54 +01003676 stats = self.statistics.get_err_counter(
3677 '/err/nat44-ei-ha/pkts-processed')
Filip Varga18f1e412020-12-03 15:27:40 +01003678 self.assertEqual(stats, 3)
3679
3680 # send packet to test session created by HA
3681 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3682 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3683 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3684 self.pg1.add_stream(p)
3685 self.pg_enable_capture(self.pg_interfaces)
3686 self.pg_start()
3687 capture = self.pg0.get_capture(1)
3688 p = capture[0]
3689 try:
3690 ip = p[IP]
3691 tcp = p[TCP]
3692 except IndexError:
3693 self.logger.error(ppp("Invalid packet:", p))
3694 raise
3695 else:
3696 self.assertEqual(ip.src, self.pg1.remote_ip4)
3697 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3698 self.assertEqual(tcp.sport, self.tcp_external_port)
3699 self.assertEqual(tcp.dport, self.tcp_port_in)
3700
Filip Varga0eaf4e62021-02-17 14:34:54 +01003701 def reconfigure_frame_queue_nelts(self, frame_queue_nelts):
3702 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3703 self.vapi.nat44_ei_set_fq_options(frame_queue_nelts=frame_queue_nelts)
3704 # keep plugin configuration persistent
3705 self.plugin_enable()
3706 return self.vapi.nat44_ei_show_fq_options().frame_queue_nelts
3707
3708 def test_set_frame_queue_nelts(self):
Filip Varga53cee152022-01-18 13:17:07 -08003709 """ NAT44EI API test - worker handoff frame queue elements """
Filip Varga0eaf4e62021-02-17 14:34:54 +01003710 self.assertEqual(self.reconfigure_frame_queue_nelts(512), 512)
3711
Filip Varga18f1e412020-12-03 15:27:40 +01003712 def show_commands_at_teardown(self):
Filip Varga0eaf4e62021-02-17 14:34:54 +01003713 self.logger.info(self.vapi.cli("show nat44 ei timeouts"))
3714 self.logger.info(self.vapi.cli("show nat44 ei addresses"))
3715 self.logger.info(self.vapi.cli("show nat44 ei interfaces"))
3716 self.logger.info(self.vapi.cli("show nat44 ei static mappings"))
3717 self.logger.info(self.vapi.cli("show nat44 ei interface address"))
3718 self.logger.info(self.vapi.cli("show nat44 ei sessions detail"))
3719 self.logger.info(self.vapi.cli("show nat44 ei hash tables detail"))
3720 self.logger.info(self.vapi.cli("show nat44 ei ha"))
Filip Varga18f1e412020-12-03 15:27:40 +01003721 self.logger.info(
Filip Varga0eaf4e62021-02-17 14:34:54 +01003722 self.vapi.cli("show nat44 ei addr-port-assignment-alg"))
Filip Varga18f1e412020-12-03 15:27:40 +01003723
Klement Sekeradc243ee2021-02-25 16:47:23 +01003724 def test_outside_address_distribution(self):
3725 """ Outside address distribution based on source address """
3726
3727 x = 100
3728 nat_addresses = []
3729
3730 for i in range(1, x):
3731 a = "10.0.0.%d" % i
3732 nat_addresses.append(a)
3733
3734 flags = self.config_flags.NAT44_EI_IF_INSIDE
3735 self.vapi.nat44_ei_interface_add_del_feature(
3736 sw_if_index=self.pg0.sw_if_index,
3737 flags=flags, is_add=1)
3738 self.vapi.nat44_ei_interface_add_del_feature(
3739 sw_if_index=self.pg1.sw_if_index,
3740 is_add=1)
3741
3742 self.vapi.nat44_ei_add_del_address_range(
3743 first_ip_address=nat_addresses[0],
3744 last_ip_address=nat_addresses[-1],
3745 vrf_id=0xFFFFFFFF, is_add=1)
3746
3747 self.pg0.generate_remote_hosts(x)
3748
3749 pkts = []
3750 for i in range(x):
Klement Sekerab2da6d62021-03-24 17:25:14 +01003751 info = self.create_packet_info(self.pg0, self.pg1)
3752 payload = self.info_to_payload(info)
Klement Sekeradc243ee2021-02-25 16:47:23 +01003753 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3754 IP(src=self.pg0.remote_hosts[i].ip4,
3755 dst=self.pg1.remote_ip4) /
Klement Sekerab2da6d62021-03-24 17:25:14 +01003756 UDP(sport=7000+i, dport=8000+i) /
3757 Raw(payload))
3758 info.data = p
Klement Sekeradc243ee2021-02-25 16:47:23 +01003759 pkts.append(p)
3760
3761 self.pg0.add_stream(pkts)
3762 self.pg_enable_capture(self.pg_interfaces)
3763 self.pg_start()
3764 recvd = self.pg1.get_capture(len(pkts))
Klement Sekerab2da6d62021-03-24 17:25:14 +01003765 for p_recvd in recvd:
3766 payload_info = self.payload_to_info(p_recvd[Raw])
3767 packet_index = payload_info.index
3768 info = self._packet_infos[packet_index]
3769 self.assertTrue(info is not None)
3770 self.assertEqual(packet_index, info.index)
3771 p_sent = info.data
Klement Sekeradc243ee2021-02-25 16:47:23 +01003772 packed = socket.inet_aton(p_sent[IP].src)
3773 numeric = struct.unpack("!L", packed)[0]
3774 numeric = socket.htonl(numeric)
3775 a = nat_addresses[(numeric-1) % len(nat_addresses)]
Klement Sekerab2da6d62021-03-24 17:25:14 +01003776 self.assertEqual(
3777 a, p_recvd[IP].src,
3778 "Invalid packet (src IP %s translated to %s, but expected %s)"
3779 % (p_sent[IP].src, p_recvd[IP].src, a))
Klement Sekeradc243ee2021-02-25 16:47:23 +01003780
Matthew Smith01930f52021-05-13 11:11:33 -05003781 def test_default_user_sessions(self):
3782 """ NAT44EI default per-user session limit is used and reported """
3783 nat44_ei_config = self.vapi.nat44_ei_show_running_config()
3784 # a nonzero default should be reported for user_sessions
3785 self.assertNotEqual(nat44_ei_config.user_sessions, 0)
3786
Filip Varga18f1e412020-12-03 15:27:40 +01003787
3788class TestNAT44Out2InDPO(MethodHolder):
3789 """ NAT44EI Test Cases using out2in DPO """
3790
3791 @classmethod
3792 def setUpClass(cls):
3793 super(TestNAT44Out2InDPO, cls).setUpClass()
Filip Varga0eaf4e62021-02-17 14:34:54 +01003794 cls.vapi.cli("set log class nat44-ei level debug")
Filip Varga18f1e412020-12-03 15:27:40 +01003795
3796 cls.tcp_port_in = 6303
3797 cls.tcp_port_out = 6303
3798 cls.udp_port_in = 6304
3799 cls.udp_port_out = 6304
3800 cls.icmp_id_in = 6305
3801 cls.icmp_id_out = 6305
3802 cls.nat_addr = '10.0.0.3'
3803 cls.dst_ip4 = '192.168.70.1'
3804
3805 cls.create_pg_interfaces(range(2))
3806
3807 cls.pg0.admin_up()
3808 cls.pg0.config_ip4()
3809 cls.pg0.resolve_arp()
3810
3811 cls.pg1.admin_up()
3812 cls.pg1.config_ip6()
3813 cls.pg1.resolve_ndp()
3814
3815 r1 = VppIpRoute(cls, "::", 0,
3816 [VppRoutePath(cls.pg1.remote_ip6,
3817 cls.pg1.sw_if_index)],
3818 register=False)
3819 r1.add_vpp_config()
3820
3821 def setUp(self):
3822 super(TestNAT44Out2InDPO, self).setUp()
Filip Varga0eaf4e62021-02-17 14:34:54 +01003823 flags = self.config_flags.NAT44_EI_OUT2IN_DPO
3824 self.vapi.nat44_ei_plugin_enable_disable(enable=1, flags=flags)
Filip Varga18f1e412020-12-03 15:27:40 +01003825
3826 def tearDown(self):
3827 super(TestNAT44Out2InDPO, self).tearDown()
3828 if not self.vpp_dead:
Filip Varga0eaf4e62021-02-17 14:34:54 +01003829 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +01003830 self.vapi.cli("clear logging")
3831
3832 def configure_xlat(self):
3833 self.dst_ip6_pfx = '1:2:3::'
3834 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3835 self.dst_ip6_pfx)
3836 self.dst_ip6_pfx_len = 96
3837 self.src_ip6_pfx = '4:5:6::'
3838 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3839 self.src_ip6_pfx)
3840 self.src_ip6_pfx_len = 96
3841 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
3842 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
3843 '\x00\x00\x00\x00', 0)
3844
3845 @unittest.skip('Temporary disabled')
3846 def test_464xlat_ce(self):
3847 """ Test 464XLAT CE with NAT44EI """
3848
Filip Varga18f1e412020-12-03 15:27:40 +01003849 self.configure_xlat()
3850
Filip Varga0eaf4e62021-02-17 14:34:54 +01003851 flags = self.config_flags.NAT44_EI_IF_INSIDE
3852 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003853 sw_if_index=self.pg0.sw_if_index,
3854 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003855 self.vapi.nat44_ei_add_del_address_range(
3856 first_ip_address=self.nat_addr_n,
3857 last_ip_address=self.nat_addr_n,
3858 vrf_id=0xFFFFFFFF, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003859
3860 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3861 self.dst_ip6_pfx_len)
3862 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
3863 self.src_ip6_pfx_len)
3864
3865 try:
3866 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3867 self.pg0.add_stream(pkts)
3868 self.pg_enable_capture(self.pg_interfaces)
3869 self.pg_start()
3870 capture = self.pg1.get_capture(len(pkts))
3871 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
3872 dst_ip=out_src_ip6)
3873
3874 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
3875 out_dst_ip6)
3876 self.pg1.add_stream(pkts)
3877 self.pg_enable_capture(self.pg_interfaces)
3878 self.pg_start()
3879 capture = self.pg0.get_capture(len(pkts))
3880 self.verify_capture_in(capture, self.pg0)
3881 finally:
Filip Varga0eaf4e62021-02-17 14:34:54 +01003882 self.vapi.nat44_ei_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01003883 sw_if_index=self.pg0.sw_if_index,
3884 flags=flags)
Filip Varga0eaf4e62021-02-17 14:34:54 +01003885 self.vapi.nat44_ei_add_del_address_range(
Filip Varga18f1e412020-12-03 15:27:40 +01003886 first_ip_address=self.nat_addr_n,
3887 last_ip_address=self.nat_addr_n,
3888 vrf_id=0xFFFFFFFF)
3889
3890 @unittest.skip('Temporary disabled')
3891 def test_464xlat_ce_no_nat(self):
3892 """ Test 464XLAT CE without NAT44EI """
3893
3894 self.configure_xlat()
3895
3896 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3897 self.dst_ip6_pfx_len)
3898 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
3899 self.src_ip6_pfx_len)
3900
3901 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3902 self.pg0.add_stream(pkts)
3903 self.pg_enable_capture(self.pg_interfaces)
3904 self.pg_start()
3905 capture = self.pg1.get_capture(len(pkts))
3906 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
3907 nat_ip=out_dst_ip6, same_port=True)
3908
3909 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
3910 self.pg1.add_stream(pkts)
3911 self.pg_enable_capture(self.pg_interfaces)
3912 self.pg_start()
3913 capture = self.pg0.get_capture(len(pkts))
3914 self.verify_capture_in(capture, self.pg0)
3915
3916
Klement Sekera98d82ca2021-02-02 13:25:40 +01003917class TestNAT44EIMW(MethodHolder):
3918 """ NAT44EI Test Cases (multiple workers) """
Klement Sekera8d815022021-03-15 16:58:10 +01003919 vpp_worker_count = 2
Klement Sekera98d82ca2021-02-02 13:25:40 +01003920 max_translations = 10240
3921 max_users = 10240
3922
3923 @classmethod
3924 def setUpClass(cls):
3925 super(TestNAT44EIMW, cls).setUpClass()
3926 cls.vapi.cli("set log class nat level debug")
3927
3928 cls.tcp_port_in = 6303
3929 cls.tcp_port_out = 6303
3930 cls.udp_port_in = 6304
3931 cls.udp_port_out = 6304
3932 cls.icmp_id_in = 6305
3933 cls.icmp_id_out = 6305
3934 cls.nat_addr = '10.0.0.3'
3935 cls.ipfix_src_port = 4739
3936 cls.ipfix_domain_id = 1
3937 cls.tcp_external_port = 80
3938 cls.udp_external_port = 69
3939
3940 cls.create_pg_interfaces(range(10))
3941 cls.interfaces = list(cls.pg_interfaces[0:4])
3942
3943 for i in cls.interfaces:
3944 i.admin_up()
3945 i.config_ip4()
3946 i.resolve_arp()
3947
3948 cls.pg0.generate_remote_hosts(3)
3949 cls.pg0.configure_ipv4_neighbors()
3950
3951 cls.pg1.generate_remote_hosts(1)
3952 cls.pg1.configure_ipv4_neighbors()
3953
3954 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
3955 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
3956 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
3957
3958 cls.pg4._local_ip4 = "172.16.255.1"
3959 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
3960 cls.pg4.set_table_ip4(10)
3961 cls.pg5._local_ip4 = "172.17.255.3"
3962 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
3963 cls.pg5.set_table_ip4(10)
3964 cls.pg6._local_ip4 = "172.16.255.1"
3965 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
3966 cls.pg6.set_table_ip4(20)
3967 for i in cls.overlapping_interfaces:
3968 i.config_ip4()
3969 i.admin_up()
3970 i.resolve_arp()
3971
3972 cls.pg7.admin_up()
3973 cls.pg8.admin_up()
3974
3975 cls.pg9.generate_remote_hosts(2)
3976 cls.pg9.config_ip4()
3977 cls.vapi.sw_interface_add_del_address(
3978 sw_if_index=cls.pg9.sw_if_index,
3979 prefix="10.0.0.1/24")
3980
3981 cls.pg9.admin_up()
3982 cls.pg9.resolve_arp()
3983 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
3984 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
3985 cls.pg9.resolve_arp()
3986
3987 def setUp(self):
3988 super(TestNAT44EIMW, self).setUp()
Filip Varga0eaf4e62021-02-17 14:34:54 +01003989 self.vapi.nat44_ei_plugin_enable_disable(
Klement Sekera98d82ca2021-02-02 13:25:40 +01003990 sessions=self.max_translations,
3991 users=self.max_users, enable=1)
3992
3993 def tearDown(self):
3994 super(TestNAT44EIMW, self).tearDown()
3995 if not self.vpp_dead:
Filip Varga0eaf4e62021-02-17 14:34:54 +01003996 self.vapi.nat44_ei_ipfix_enable_disable(
3997 domain_id=self.ipfix_domain_id,
3998 src_port=self.ipfix_src_port,
3999 enable=0)
Klement Sekera98d82ca2021-02-02 13:25:40 +01004000 self.ipfix_src_port = 4739
4001 self.ipfix_domain_id = 1
4002
Filip Varga0eaf4e62021-02-17 14:34:54 +01004003 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
Klement Sekera98d82ca2021-02-02 13:25:40 +01004004 self.vapi.cli("clear logging")
4005
4006 def test_hairpinning(self):
4007 """ NAT44EI hairpinning - 1:1 NAPT """
4008
4009 host = self.pg0.remote_hosts[0]
4010 server = self.pg0.remote_hosts[1]
4011 host_in_port = 1234
4012 host_out_port = 0
4013 server_in_port = 5678
4014 server_out_port = 8765
4015 worker_1 = 1
4016 worker_2 = 2
4017
4018 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01004019 flags = self.config_flags.NAT44_EI_IF_INSIDE
4020 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekera98d82ca2021-02-02 13:25:40 +01004021 sw_if_index=self.pg0.sw_if_index,
4022 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01004023 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekera98d82ca2021-02-02 13:25:40 +01004024 sw_if_index=self.pg1.sw_if_index,
4025 is_add=1)
4026
4027 # add static mapping for server
4028 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
4029 server_in_port, server_out_port,
4030 proto=IP_PROTOS.tcp)
4031
Klement Sekeraeafb5db2021-03-15 16:34:01 +01004032 cnt = self.statistics['/nat44-ei/hairpinning']
Klement Sekera98d82ca2021-02-02 13:25:40 +01004033 # send packet from host to server
4034 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4035 IP(src=host.ip4, dst=self.nat_addr) /
4036 TCP(sport=host_in_port, dport=server_out_port))
4037 self.pg0.add_stream(p)
4038 self.pg_enable_capture(self.pg_interfaces)
4039 self.pg_start()
4040 capture = self.pg0.get_capture(1)
4041 p = capture[0]
4042 try:
4043 ip = p[IP]
4044 tcp = p[TCP]
4045 self.assertEqual(ip.src, self.nat_addr)
4046 self.assertEqual(ip.dst, server.ip4)
4047 self.assertNotEqual(tcp.sport, host_in_port)
4048 self.assertEqual(tcp.dport, server_in_port)
4049 self.assert_packet_checksums_valid(p)
4050 host_out_port = tcp.sport
4051 except:
4052 self.logger.error(ppp("Unexpected or invalid packet:", p))
4053 raise
4054
Klement Sekeraeafb5db2021-03-15 16:34:01 +01004055 after = self.statistics['/nat44-ei/hairpinning']
Klement Sekera98d82ca2021-02-02 13:25:40 +01004056
4057 if_idx = self.pg0.sw_if_index
4058 self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1)
4059
4060 # send reply from server to host
4061 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4062 IP(src=server.ip4, dst=self.nat_addr) /
4063 TCP(sport=server_in_port, dport=host_out_port))
4064 self.pg0.add_stream(p)
4065 self.pg_enable_capture(self.pg_interfaces)
4066 self.pg_start()
4067 capture = self.pg0.get_capture(1)
4068 p = capture[0]
4069 try:
4070 ip = p[IP]
4071 tcp = p[TCP]
4072 self.assertEqual(ip.src, self.nat_addr)
4073 self.assertEqual(ip.dst, host.ip4)
4074 self.assertEqual(tcp.sport, server_out_port)
4075 self.assertEqual(tcp.dport, host_in_port)
4076 self.assert_packet_checksums_valid(p)
4077 except:
4078 self.logger.error(ppp("Unexpected or invalid packet:", p))
4079 raise
4080
Klement Sekeraeafb5db2021-03-15 16:34:01 +01004081 after = self.statistics['/nat44-ei/hairpinning']
Klement Sekera98d82ca2021-02-02 13:25:40 +01004082 if_idx = self.pg0.sw_if_index
4083 self.assertEqual(after[worker_1][if_idx] - cnt[worker_1][if_idx], 1)
4084 self.assertEqual(after[worker_2][if_idx] - cnt[worker_2][if_idx], 2)
4085
4086 def test_hairpinning2(self):
4087 """ NAT44EI hairpinning - 1:1 NAT"""
4088
4089 server1_nat_ip = "10.0.0.10"
4090 server2_nat_ip = "10.0.0.11"
4091 host = self.pg0.remote_hosts[0]
4092 server1 = self.pg0.remote_hosts[1]
4093 server2 = self.pg0.remote_hosts[2]
4094 server_tcp_port = 22
4095 server_udp_port = 20
4096
4097 self.nat44_add_address(self.nat_addr)
Filip Varga0eaf4e62021-02-17 14:34:54 +01004098 flags = self.config_flags.NAT44_EI_IF_INSIDE
4099 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekera98d82ca2021-02-02 13:25:40 +01004100 sw_if_index=self.pg0.sw_if_index,
4101 flags=flags, is_add=1)
Filip Varga0eaf4e62021-02-17 14:34:54 +01004102 self.vapi.nat44_ei_interface_add_del_feature(
Klement Sekera98d82ca2021-02-02 13:25:40 +01004103 sw_if_index=self.pg1.sw_if_index,
4104 is_add=1)
4105
4106 # add static mapping for servers
4107 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
4108 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
4109
4110 # host to server1
4111 pkts = []
4112 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4113 IP(src=host.ip4, dst=server1_nat_ip) /
4114 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4115 pkts.append(p)
4116 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4117 IP(src=host.ip4, dst=server1_nat_ip) /
4118 UDP(sport=self.udp_port_in, dport=server_udp_port))
4119 pkts.append(p)
4120 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4121 IP(src=host.ip4, dst=server1_nat_ip) /
4122 ICMP(id=self.icmp_id_in, type='echo-request'))
4123 pkts.append(p)
4124 self.pg0.add_stream(pkts)
4125 self.pg_enable_capture(self.pg_interfaces)
4126 self.pg_start()
4127 capture = self.pg0.get_capture(len(pkts))
4128 for packet in capture:
4129 try:
4130 self.assertEqual(packet[IP].src, self.nat_addr)
4131 self.assertEqual(packet[IP].dst, server1.ip4)
4132 if packet.haslayer(TCP):
4133 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
4134 self.assertEqual(packet[TCP].dport, server_tcp_port)
4135 self.tcp_port_out = packet[TCP].sport
4136 self.assert_packet_checksums_valid(packet)
4137 elif packet.haslayer(UDP):
4138 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
4139 self.assertEqual(packet[UDP].dport, server_udp_port)
4140 self.udp_port_out = packet[UDP].sport
4141 else:
4142 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
4143 self.icmp_id_out = packet[ICMP].id
4144 except:
4145 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4146 raise
4147
4148 # server1 to host
4149 pkts = []
4150 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4151 IP(src=server1.ip4, dst=self.nat_addr) /
4152 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4153 pkts.append(p)
4154 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4155 IP(src=server1.ip4, dst=self.nat_addr) /
4156 UDP(sport=server_udp_port, dport=self.udp_port_out))
4157 pkts.append(p)
4158 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4159 IP(src=server1.ip4, dst=self.nat_addr) /
4160 ICMP(id=self.icmp_id_out, type='echo-reply'))
4161 pkts.append(p)
4162 self.pg0.add_stream(pkts)
4163 self.pg_enable_capture(self.pg_interfaces)
4164 self.pg_start()
4165 capture = self.pg0.get_capture(len(pkts))
4166 for packet in capture:
4167 try:
4168 self.assertEqual(packet[IP].src, server1_nat_ip)
4169 self.assertEqual(packet[IP].dst, host.ip4)
4170 if packet.haslayer(TCP):
4171 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4172 self.assertEqual(packet[TCP].sport, server_tcp_port)
4173 self.assert_packet_checksums_valid(packet)
4174 elif packet.haslayer(UDP):
4175 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4176 self.assertEqual(packet[UDP].sport, server_udp_port)
4177 else:
4178 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4179 except:
4180 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4181 raise
4182
4183 # server2 to server1
4184 pkts = []
4185 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4186 IP(src=server2.ip4, dst=server1_nat_ip) /
4187 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4188 pkts.append(p)
4189 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4190 IP(src=server2.ip4, dst=server1_nat_ip) /
4191 UDP(sport=self.udp_port_in, dport=server_udp_port))
4192 pkts.append(p)
4193 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4194 IP(src=server2.ip4, dst=server1_nat_ip) /
4195 ICMP(id=self.icmp_id_in, type='echo-request'))
4196 pkts.append(p)
4197 self.pg0.add_stream(pkts)
4198 self.pg_enable_capture(self.pg_interfaces)
4199 self.pg_start()
4200 capture = self.pg0.get_capture(len(pkts))
4201 for packet in capture:
4202 try:
4203 self.assertEqual(packet[IP].src, server2_nat_ip)
4204 self.assertEqual(packet[IP].dst, server1.ip4)
4205 if packet.haslayer(TCP):
4206 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
4207 self.assertEqual(packet[TCP].dport, server_tcp_port)
4208 self.tcp_port_out = packet[TCP].sport
4209 self.assert_packet_checksums_valid(packet)
4210 elif packet.haslayer(UDP):
4211 self.assertEqual(packet[UDP].sport, self.udp_port_in)
4212 self.assertEqual(packet[UDP].dport, server_udp_port)
4213 self.udp_port_out = packet[UDP].sport
4214 else:
4215 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4216 self.icmp_id_out = packet[ICMP].id
4217 except:
4218 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4219 raise
4220
4221 # server1 to server2
4222 pkts = []
4223 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4224 IP(src=server1.ip4, dst=server2_nat_ip) /
4225 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4226 pkts.append(p)
4227 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4228 IP(src=server1.ip4, dst=server2_nat_ip) /
4229 UDP(sport=server_udp_port, dport=self.udp_port_out))
4230 pkts.append(p)
4231 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4232 IP(src=server1.ip4, dst=server2_nat_ip) /
4233 ICMP(id=self.icmp_id_out, type='echo-reply'))
4234 pkts.append(p)
4235 self.pg0.add_stream(pkts)
4236 self.pg_enable_capture(self.pg_interfaces)
4237 self.pg_start()
4238 capture = self.pg0.get_capture(len(pkts))
4239 for packet in capture:
4240 try:
4241 self.assertEqual(packet[IP].src, server1_nat_ip)
4242 self.assertEqual(packet[IP].dst, server2.ip4)
4243 if packet.haslayer(TCP):
4244 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4245 self.assertEqual(packet[TCP].sport, server_tcp_port)
4246 self.assert_packet_checksums_valid(packet)
4247 elif packet.haslayer(UDP):
4248 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4249 self.assertEqual(packet[UDP].sport, server_udp_port)
4250 else:
4251 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4252 except:
4253 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4254 raise
4255
Filip Varga0eaf4e62021-02-17 14:34:54 +01004256
Filip Varga18f1e412020-12-03 15:27:40 +01004257if __name__ == '__main__':
4258 unittest.main(testRunner=VppTestRunner)