11 from framework import VppTestCase, VppTestRunner
12 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
13 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
14 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
16 from scapy.data import IP_PROTOS
17 from scapy.layers.inet import IP, TCP, UDP, ICMP
18 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
19 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
20 from scapy.layers.l2 import Ether, ARP, GRE
21 from scapy.packet import Raw
22 from syslog_rfc5424_parser import SyslogMessage, ParseError
23 from syslog_rfc5424_parser.constants import SyslogSeverity
25 from vpp_ip_route import VppIpRoute, VppRoutePath
26 from vpp_neighbor import VppNeighbor
27 from vpp_papi import VppEnum
30 # NAT HA protocol event data
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)]
50 def extract_padding(self, s):
54 # NAT HA protocol header
55 class 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)]
66 class MethodHolder(VppTestCase):
67 """ NAT create capture and verify method holder """
70 def config_flags(self):
71 return VppEnum.vl_api_nat44_ei_config_flags_t
74 def SYSLOG_SEVERITY(self):
75 return VppEnum.vl_api_syslog_severity_t
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):
82 Add/delete NAT44EI static mapping
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
96 if not (local_port and external_port):
97 flags |= self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
99 self.vapi.nat44_ei_add_del_static_mapping(
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,
110 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF):
112 Add/delete NAT44EI address
114 :param ip: IP address
115 :param is_add: 1 if add, 0 if delete (Default add)
117 self.vapi.nat44_ei_add_del_address_range(first_ip_address=ip,
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)])
132 n1 = VppNeighbor(self,
133 self.pg7.sw_if_index,
137 n2 = VppNeighbor(self,
138 self.pg8.sw_if_index,
145 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
147 Create packet stream for inside network
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
155 dst_ip = out_if.remote_ip4
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))
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))
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'))
178 def compose_ip6(self, ip4, pref, plen):
180 Compose IPv4-embedded IPv6 addresses
182 :param ip4: IPv4 address
183 :param pref: IPv6 prefix
184 :param plen: IPv6 prefix length
185 :returns: IPv4-embedded IPv6 addresses
187 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
188 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
203 pref_n[10] = ip4_n[3]
207 pref_n[10] = ip4_n[2]
208 pref_n[11] = ip4_n[3]
211 pref_n[10] = ip4_n[1]
212 pref_n[11] = ip4_n[2]
213 pref_n[12] = ip4_n[3]
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)
222 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
223 use_inside_ports=False):
225 Create packet stream for outside network
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
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
240 tcp_port = self.tcp_port_in
241 udp_port = self.udp_port_in
242 icmp_id = self.icmp_id_in
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))
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))
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'))
264 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
266 Create packet stream for outside network
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
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))
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))
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))
293 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
294 dst_ip=None, is_ip6=False, ignore_port=False):
296 Verify captured packets on outside network
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)
306 ICMP46 = ICMPv6EchoRequest
311 nat_ip = self.nat_addr
312 for packet in capture:
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):
323 packet[TCP].sport, self.tcp_port_in)
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):
333 packet[UDP].sport, self.udp_port_in)
336 packet[UDP].sport, self.udp_port_in)
337 self.udp_port_out = packet[UDP].sport
342 packet[ICMP46].id, self.icmp_id_in)
345 packet[ICMP46].id, self.icmp_id_in)
346 self.icmp_id_out = packet[ICMP46].id
347 self.assert_packet_checksums_valid(packet)
349 self.logger.error(ppp("Unexpected or invalid packet "
350 "(outside network):", packet))
353 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
356 Verify captured packets on outside network
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)
363 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
366 def verify_capture_in(self, capture, in_if):
368 Verify captured packets on inside network
370 :param capture: Captured packets
371 :param in_if: Inside interface
373 for packet in capture:
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)
382 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
384 self.logger.error(ppp("Unexpected or invalid packet "
385 "(inside network):", packet))
388 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
390 Verify captured packet that don't have to be translated
392 :param capture: Captured packets
393 :param ingress_if: Ingress interface
394 :param egress_if: Egress interface
396 for packet in capture:
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)
405 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
407 self.logger.error(ppp("Unexpected or invalid packet "
408 "(inside network):", packet))
411 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
414 Verify captured packets with ICMP errors on outside network
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)
423 src_ip = self.nat_addr
424 for packet in capture:
426 self.assertEqual(packet[IP].src, src_ip)
427 self.assertEqual(packet.haslayer(ICMP), 1)
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,
435 elif inner_ip.haslayer(UDPerror):
436 self.assertEqual(inner_ip[UDPerror].dport,
439 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
441 self.logger.error(ppp("Unexpected or invalid packet "
442 "(outside network):", packet))
445 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
447 Verify captured packets with ICMP errors on inside network
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)
454 for packet in capture:
456 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
457 self.assertEqual(packet.haslayer(ICMP), 1)
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,
465 elif inner_ip.haslayer(UDPerror):
466 self.assertEqual(inner_ip[UDPerror].sport,
469 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
471 self.logger.error(ppp("Unexpected or invalid packet "
472 "(inside network):", packet))
475 def create_stream_frag(self, src_if, dst, sport, dport, data,
476 proto=IP_PROTOS.tcp, echo_reply=False):
478 Create fragmented packet stream
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
489 if proto == IP_PROTOS.tcp:
490 p = (IP(src=src_if.remote_ip4, dst=dst) /
491 TCP(sport=sport, dport=dport) /
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:
500 proto_header = ICMP(id=sport, type='echo-request')
502 proto_header = ICMP(id=sport, type='echo-reply')
504 raise Exception("Unsupported protocol")
505 id = random.randint(0, 65535)
507 if proto == IP_PROTOS.tcp:
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) /
516 if proto == IP_PROTOS.tcp:
517 raw = Raw(data[4:20])
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,
525 if proto == IP_PROTOS.tcp:
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,
536 def reass_frags_and_verify(self, frags, src, dst):
538 Reassemble and verify fragmented packet
540 :param frags: Captured fragments
541 :param src: Source IPv4 address to verify
542 :param dst: Destination IPv4 address to verify
544 :returns: Reassembled IPv4 packet
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()))
566 def verify_ipfix_nat44_ses(self, data):
568 Verify IPFIX NAT44EI session create/delete event
570 :param data: Decoded IPFIX data records
572 nat44_ses_create_num = 0
573 nat44_ses_delete_num = 0
574 self.assertEqual(6, len(data))
577 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
578 if scapy.compat.orb(record[230]) == 4:
579 nat44_ses_create_num += 1
581 nat44_ses_delete_num += 1
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),
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),
596 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
597 self.assertEqual(struct.pack("!H", self.tcp_port_in),
599 self.assertEqual(struct.pack("!H", self.tcp_port_out),
601 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
602 self.assertEqual(struct.pack("!H", self.udp_port_in),
604 self.assertEqual(struct.pack("!H", self.udp_port_out),
607 self.fail(f"Invalid protocol {scapy.compat.orb(record[4])}")
608 self.assertEqual(3, nat44_ses_create_num)
609 self.assertEqual(3, nat44_ses_delete_num)
611 def verify_ipfix_addr_exhausted(self, data):
612 self.assertEqual(1, len(data))
615 self.assertEqual(scapy.compat.orb(record[230]), 3)
617 self.assertEqual(struct.pack("!I", 0), record[283])
619 def verify_ipfix_max_sessions(self, data, limit):
620 self.assertEqual(1, len(data))
623 self.assertEqual(scapy.compat.orb(record[230]), 13)
624 # natQuotaExceededEvent
625 self.assertEqual(struct.pack("!I", 1), record[466])
627 self.assertEqual(struct.pack("!I", limit), record[471])
629 def verify_no_nat44_user(self):
630 """ Verify that there is no NAT44EI user """
631 users = self.vapi.nat44_ei_user_dump()
632 self.assertEqual(len(users), 0)
633 users = self.statistics['/nat44-ei/total-users']
634 self.assertEqual(users[0][0], 0)
635 sessions = self.statistics['/nat44-ei/total-sessions']
636 self.assertEqual(sessions[0][0], 0)
638 def verify_syslog_apmap(self, data, is_add=True):
639 message = data.decode('utf-8')
641 message = SyslogMessage.parse(message)
642 except ParseError as e:
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')
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")
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)
671 def proto2layer(proto):
672 if proto == IP_PROTOS.tcp:
674 elif proto == IP_PROTOS.udp:
676 elif proto == IP_PROTOS.icmp:
679 raise Exception("Unsupported protocol")
681 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
683 layer = self.proto2layer(proto)
685 if proto == IP_PROTOS.tcp:
686 data = b"A" * 4 + b"B" * 16 + b"C" * 3
688 data = b"A" * 16 + b"B" * 16 + b"C" * 3
689 self.port_in = random.randint(1025, 65535)
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)
697 frags = self.pg1.get_capture(len(pkts))
698 if not dont_translate:
699 p = self.reass_frags_and_verify(frags,
703 p = self.reass_frags_and_verify(frags,
706 if proto != IP_PROTOS.icmp:
707 if not dont_translate:
708 self.assertEqual(p[layer].dport, 20)
710 self.assertNotEqual(p[layer].sport, self.port_in)
712 self.assertEqual(p[layer].sport, self.port_in)
715 if not dont_translate:
716 self.assertNotEqual(p[layer].id, self.port_in)
718 self.assertEqual(p[layer].id, self.port_in)
719 self.assertEqual(data, p[Raw].load)
722 if not dont_translate:
723 dst_addr = self.nat_addr
725 dst_addr = self.pg0.remote_ip4
726 if proto != IP_PROTOS.icmp:
728 dport = p[layer].sport
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)
737 frags = self.pg0.get_capture(len(pkts))
738 p = self.reass_frags_and_verify(frags,
741 if proto != IP_PROTOS.icmp:
742 self.assertEqual(p[layer].sport, 20)
743 self.assertEqual(p[layer].dport, self.port_in)
745 self.assertEqual(p[layer].id, self.port_in)
746 self.assertEqual(data, p[Raw].load)
748 def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
749 host_in_port, proto=IP_PROTOS.tcp,
752 layer = self.proto2layer(proto)
754 if proto == IP_PROTOS.tcp:
755 data = b"A" * 4 + b"B" * 16 + b"C" * 3
757 data = b"A" * 16 + b"B" * 16 + b"C" * 3
759 # send packet from host to server
760 pkts = self.create_stream_frag(self.pg0,
766 self.pg0.add_stream(pkts)
767 self.pg_enable_capture(self.pg_interfaces)
769 frags = self.pg0.get_capture(len(pkts))
770 p = self.reass_frags_and_verify(frags,
773 if proto != IP_PROTOS.icmp:
775 self.assertNotEqual(p[layer].sport, host_in_port)
776 self.assertEqual(p[layer].dport, server_in_port)
779 self.assertNotEqual(p[layer].id, host_in_port)
780 self.assertEqual(data, p[Raw].load)
782 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
784 layer = self.proto2layer(proto)
786 if proto == IP_PROTOS.tcp:
787 data = b"A" * 4 + b"B" * 16 + b"C" * 3
789 data = b"A" * 16 + b"B" * 16 + b"C" * 3
790 self.port_in = random.randint(1025, 65535)
794 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
795 self.port_in, 20, data, proto)
797 self.pg0.add_stream(pkts)
798 self.pg_enable_capture(self.pg_interfaces)
800 frags = self.pg1.get_capture(len(pkts))
801 if not dont_translate:
802 p = self.reass_frags_and_verify(frags,
806 p = self.reass_frags_and_verify(frags,
809 if proto != IP_PROTOS.icmp:
810 if not dont_translate:
811 self.assertEqual(p[layer].dport, 20)
813 self.assertNotEqual(p[layer].sport, self.port_in)
815 self.assertEqual(p[layer].sport, self.port_in)
818 if not dont_translate:
819 self.assertNotEqual(p[layer].id, self.port_in)
821 self.assertEqual(p[layer].id, self.port_in)
822 self.assertEqual(data, p[Raw].load)
825 if not dont_translate:
826 dst_addr = self.nat_addr
828 dst_addr = self.pg0.remote_ip4
829 if proto != IP_PROTOS.icmp:
831 dport = p[layer].sport
835 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
836 data, proto, echo_reply=True)
838 self.pg1.add_stream(pkts)
839 self.pg_enable_capture(self.pg_interfaces)
841 frags = self.pg0.get_capture(len(pkts))
842 p = self.reass_frags_and_verify(frags,
845 if proto != IP_PROTOS.icmp:
846 self.assertEqual(p[layer].sport, 20)
847 self.assertEqual(p[layer].dport, self.port_in)
849 self.assertEqual(p[layer].id, self.port_in)
850 self.assertEqual(data, p[Raw].load)
853 def get_nat44_ei_in2out_worker_index(ip, vpp_worker_count):
854 if 0 == vpp_worker_count:
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
863 class TestNAT44EI(MethodHolder):
864 """ NAT44EI Test Cases """
866 max_translations = 10240
871 super(TestNAT44EI, cls).setUpClass()
872 cls.vapi.cli("set log class nat44-ei level debug")
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
886 cls.create_pg_interfaces(range(10))
887 cls.interfaces = list(cls.pg_interfaces[0:4])
889 for i in cls.interfaces:
894 cls.pg0.generate_remote_hosts(3)
895 cls.pg0.configure_ipv4_neighbors()
897 cls.pg1.generate_remote_hosts(1)
898 cls.pg1.configure_ipv4_neighbors()
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})
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:
921 cls.pg9.generate_remote_hosts(2)
923 cls.vapi.sw_interface_add_del_address(
924 sw_if_index=cls.pg9.sw_if_index,
925 prefix="10.0.0.1/24")
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()
933 def plugin_enable(self):
934 self.vapi.nat44_ei_plugin_enable_disable(
935 sessions=self.max_translations,
936 users=self.max_users, enable=1)
939 super(TestNAT44EI, self).setUp()
943 super(TestNAT44EI, self).tearDown()
944 if not self.vpp_dead:
945 self.vapi.nat44_ei_ipfix_enable_disable(
946 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port,
948 self.ipfix_src_port = 4739
949 self.ipfix_domain_id = 1
951 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
952 self.vapi.cli("clear logging")
954 def test_clear_sessions(self):
955 """ NAT44EI session clearing test """
957 self.nat44_add_address(self.nat_addr)
958 flags = self.config_flags.NAT44_EI_IF_INSIDE
959 self.vapi.nat44_ei_interface_add_del_feature(
960 sw_if_index=self.pg0.sw_if_index,
961 flags=flags, is_add=1)
962 self.vapi.nat44_ei_interface_add_del_feature(
963 sw_if_index=self.pg1.sw_if_index,
966 pkts = self.create_stream_in(self.pg0, self.pg1)
967 self.pg0.add_stream(pkts)
968 self.pg_enable_capture(self.pg_interfaces)
970 capture = self.pg1.get_capture(len(pkts))
971 self.verify_capture_out(capture)
973 sessions = self.statistics['/nat44-ei/total-sessions']
974 self.assertGreater(sessions[:, 0].sum(), 0, "Session count invalid")
975 self.logger.info("sessions before clearing: %s" % sessions[0][0])
977 self.vapi.cli("clear nat44 ei sessions")
979 sessions = self.statistics['/nat44-ei/total-sessions']
980 self.assertEqual(sessions[:, 0].sum(), 0, "Session count invalid")
981 self.logger.info("sessions after clearing: %s" % sessions[0][0])
983 def test_dynamic(self):
984 """ NAT44EI dynamic translation test """
985 self.nat44_add_address(self.nat_addr)
986 flags = self.config_flags.NAT44_EI_IF_INSIDE
987 self.vapi.nat44_ei_interface_add_del_feature(
988 sw_if_index=self.pg0.sw_if_index,
989 flags=flags, is_add=1)
990 self.vapi.nat44_ei_interface_add_del_feature(
991 sw_if_index=self.pg1.sw_if_index,
995 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']
1000 pkts = self.create_stream_in(self.pg0, self.pg1)
1001 self.pg0.add_stream(pkts)
1002 self.pg_enable_capture(self.pg_interfaces)
1004 capture = self.pg1.get_capture(len(pkts))
1005 self.verify_capture_out(capture)
1007 if_idx = self.pg0.sw_if_index
1008 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)
1018 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']
1023 pkts = self.create_stream_out(self.pg1)
1024 self.pg1.add_stream(pkts)
1025 self.pg_enable_capture(self.pg_interfaces)
1027 capture = self.pg0.get_capture(len(pkts))
1028 self.verify_capture_in(capture, self.pg0)
1030 if_idx = self.pg1.sw_if_index
1031 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)
1040 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)
1045 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1046 """ NAT44EI handling of client packets with TTL=1 """
1048 self.nat44_add_address(self.nat_addr)
1049 flags = self.config_flags.NAT44_EI_IF_INSIDE
1050 self.vapi.nat44_ei_interface_add_del_feature(
1051 sw_if_index=self.pg0.sw_if_index,
1052 flags=flags, is_add=1)
1053 self.vapi.nat44_ei_interface_add_del_feature(
1054 sw_if_index=self.pg1.sw_if_index,
1057 # Client side - generate traffic
1058 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1059 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
1061 # Client side - verify ICMP type 11 packets
1062 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1064 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1065 """ NAT44EI handling of server packets with TTL=1 """
1067 self.nat44_add_address(self.nat_addr)
1068 flags = self.config_flags.NAT44_EI_IF_INSIDE
1069 self.vapi.nat44_ei_interface_add_del_feature(
1070 sw_if_index=self.pg0.sw_if_index,
1071 flags=flags, is_add=1)
1072 self.vapi.nat44_ei_interface_add_del_feature(
1073 sw_if_index=self.pg1.sw_if_index,
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)
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)
1086 capture = self.send_and_expect_some(self.pg1, pkts, self.pg1)
1088 # Server side - verify ICMP type 11 packets
1089 self.verify_capture_out_with_icmp_errors(capture,
1090 src_ip=self.pg1.local_ip4)
1092 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1093 """ NAT44EI handling of error responses to client packets with TTL=2
1096 self.nat44_add_address(self.nat_addr)
1097 flags = self.config_flags.NAT44_EI_IF_INSIDE
1098 self.vapi.nat44_ei_interface_add_del_feature(
1099 sw_if_index=self.pg0.sw_if_index,
1100 flags=flags, is_add=1)
1101 self.vapi.nat44_ei_interface_add_del_feature(
1102 sw_if_index=self.pg1.sw_if_index,
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)
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)
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)
1124 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1125 """ NAT44EI handling of error responses to server packets with TTL=2
1128 self.nat44_add_address(self.nat_addr)
1129 flags = self.config_flags.NAT44_EI_IF_INSIDE
1130 self.vapi.nat44_ei_interface_add_del_feature(
1131 sw_if_index=self.pg0.sw_if_index,
1132 flags=flags, is_add=1)
1133 self.vapi.nat44_ei_interface_add_del_feature(
1134 sw_if_index=self.pg1.sw_if_index,
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)
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)
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)
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)
1164 def test_ping_out_interface_from_outside(self):
1165 """ NAT44EI ping out interface from outside network """
1167 self.nat44_add_address(self.nat_addr)
1168 flags = self.config_flags.NAT44_EI_IF_INSIDE
1169 self.vapi.nat44_ei_interface_add_del_feature(
1170 sw_if_index=self.pg0.sw_if_index,
1171 flags=flags, is_add=1)
1172 self.vapi.nat44_ei_interface_add_del_feature(
1173 sw_if_index=self.pg1.sw_if_index,
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'))
1180 self.pg1.add_stream(pkts)
1181 self.pg_enable_capture(self.pg_interfaces)
1183 capture = self.pg1.get_capture(len(pkts))
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
1191 self.logger.error(ppp("Unexpected or invalid packet "
1192 "(outside network):", packet))
1195 def test_ping_internal_host_from_outside(self):
1196 """ NAT44EI ping internal host from outside network """
1198 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1199 flags = self.config_flags.NAT44_EI_IF_INSIDE
1200 self.vapi.nat44_ei_interface_add_del_feature(
1201 sw_if_index=self.pg0.sw_if_index,
1202 flags=flags, is_add=1)
1203 self.vapi.nat44_ei_interface_add_del_feature(
1204 sw_if_index=self.pg1.sw_if_index,
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)
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)
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)
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)
1229 def test_forwarding(self):
1230 """ NAT44EI forwarding test """
1232 flags = self.config_flags.NAT44_EI_IF_INSIDE
1233 self.vapi.nat44_ei_interface_add_del_feature(
1234 sw_if_index=self.pg0.sw_if_index,
1235 flags=flags, is_add=1)
1236 self.vapi.nat44_ei_interface_add_del_feature(
1237 sw_if_index=self.pg1.sw_if_index,
1239 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
1241 real_ip = self.pg0.remote_ip4
1242 alias_ip = self.nat_addr
1243 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,
1251 # static mapping match
1253 pkts = self.create_stream_out(self.pg1)
1254 self.pg1.add_stream(pkts)
1255 self.pg_enable_capture(self.pg_interfaces)
1257 capture = self.pg0.get_capture(len(pkts))
1258 self.verify_capture_in(capture, self.pg0)
1260 pkts = self.create_stream_in(self.pg0, self.pg1)
1261 self.pg0.add_stream(pkts)
1262 self.pg_enable_capture(self.pg_interfaces)
1264 capture = self.pg1.get_capture(len(pkts))
1265 self.verify_capture_out(capture, same_port=True)
1267 # no static mapping match
1269 host0 = self.pg0.remote_hosts[0]
1270 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
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)
1278 capture = self.pg0.get_capture(len(pkts))
1279 self.verify_capture_in(capture, self.pg0)
1281 pkts = self.create_stream_in(self.pg0, self.pg1)
1282 self.pg0.add_stream(pkts)
1283 self.pg_enable_capture(self.pg_interfaces)
1285 capture = self.pg1.get_capture(len(pkts))
1286 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1289 self.pg0.remote_hosts[0] = host0
1292 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(
1296 local_ip_address=real_ip,
1297 external_ip_address=alias_ip,
1298 external_sw_if_index=0xFFFFFFFF,
1301 def test_static_in(self):
1302 """ NAT44EI 1:1 NAT initialized from inside network """
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
1309 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1310 flags = self.config_flags.NAT44_EI_IF_INSIDE
1311 self.vapi.nat44_ei_interface_add_del_feature(
1312 sw_if_index=self.pg0.sw_if_index,
1313 flags=flags, is_add=1)
1314 self.vapi.nat44_ei_interface_add_del_feature(
1315 sw_if_index=self.pg1.sw_if_index,
1317 sm = self.vapi.nat44_ei_static_mapping_dump()
1318 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)
1325 pkts = self.create_stream_in(self.pg0, self.pg1)
1326 self.pg0.add_stream(pkts)
1327 self.pg_enable_capture(self.pg_interfaces)
1329 capture = self.pg1.get_capture(len(pkts))
1330 self.verify_capture_out(capture, nat_ip, True)
1333 pkts = self.create_stream_out(self.pg1, nat_ip)
1334 self.pg1.add_stream(pkts)
1335 self.pg_enable_capture(self.pg_interfaces)
1337 capture = self.pg0.get_capture(len(pkts))
1338 self.verify_capture_in(capture, self.pg0)
1340 def test_static_out(self):
1341 """ NAT44EI 1:1 NAT initialized from outside network """
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
1349 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1350 flags = self.config_flags.NAT44_EI_IF_INSIDE
1351 self.vapi.nat44_ei_interface_add_del_feature(
1352 sw_if_index=self.pg0.sw_if_index,
1353 flags=flags, is_add=1)
1354 self.vapi.nat44_ei_interface_add_del_feature(
1355 sw_if_index=self.pg1.sw_if_index,
1357 sm = self.vapi.nat44_ei_static_mapping_dump()
1358 self.assertEqual(len(sm), 1)
1359 self.assertEqual(sm[0].tag, tag)
1362 pkts = self.create_stream_out(self.pg1, nat_ip)
1363 self.pg1.add_stream(pkts)
1364 self.pg_enable_capture(self.pg_interfaces)
1366 capture = self.pg0.get_capture(len(pkts))
1367 self.verify_capture_in(capture, self.pg0)
1370 pkts = self.create_stream_in(self.pg0, self.pg1)
1371 self.pg0.add_stream(pkts)
1372 self.pg_enable_capture(self.pg_interfaces)
1374 capture = self.pg1.get_capture(len(pkts))
1375 self.verify_capture_out(capture, nat_ip, True)
1377 def test_static_with_port_in(self):
1378 """ NAT44EI 1:1 NAPT initialized from inside network """
1380 self.tcp_port_out = 3606
1381 self.udp_port_out = 3607
1382 self.icmp_id_out = 3608
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)
1394 flags = self.config_flags.NAT44_EI_IF_INSIDE
1395 self.vapi.nat44_ei_interface_add_del_feature(
1396 sw_if_index=self.pg0.sw_if_index,
1397 flags=flags, is_add=1)
1398 self.vapi.nat44_ei_interface_add_del_feature(
1399 sw_if_index=self.pg1.sw_if_index,
1403 pkts = self.create_stream_in(self.pg0, self.pg1)
1404 self.pg0.add_stream(pkts)
1405 self.pg_enable_capture(self.pg_interfaces)
1407 capture = self.pg1.get_capture(len(pkts))
1408 self.verify_capture_out(capture)
1411 pkts = self.create_stream_out(self.pg1)
1412 self.pg1.add_stream(pkts)
1413 self.pg_enable_capture(self.pg_interfaces)
1415 capture = self.pg0.get_capture(len(pkts))
1416 self.verify_capture_in(capture, self.pg0)
1418 def test_static_with_port_out(self):
1419 """ NAT44EI 1:1 NAPT initialized from outside network """
1421 self.tcp_port_out = 30606
1422 self.udp_port_out = 30607
1423 self.icmp_id_out = 30608
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)
1435 flags = self.config_flags.NAT44_EI_IF_INSIDE
1436 self.vapi.nat44_ei_interface_add_del_feature(
1437 sw_if_index=self.pg0.sw_if_index,
1438 flags=flags, is_add=1)
1439 self.vapi.nat44_ei_interface_add_del_feature(
1440 sw_if_index=self.pg1.sw_if_index,
1444 pkts = self.create_stream_out(self.pg1)
1445 self.pg1.add_stream(pkts)
1446 self.pg_enable_capture(self.pg_interfaces)
1448 capture = self.pg0.get_capture(len(pkts))
1449 self.verify_capture_in(capture, self.pg0)
1452 pkts = self.create_stream_in(self.pg0, self.pg1)
1453 self.pg0.add_stream(pkts)
1454 self.pg_enable_capture(self.pg_interfaces)
1456 capture = self.pg1.get_capture(len(pkts))
1457 self.verify_capture_out(capture)
1459 def test_static_vrf_aware(self):
1460 """ NAT44EI 1:1 NAT VRF awareness """
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
1468 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1470 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1472 flags = self.config_flags.NAT44_EI_IF_INSIDE
1473 self.vapi.nat44_ei_interface_add_del_feature(
1474 sw_if_index=self.pg3.sw_if_index,
1476 self.vapi.nat44_ei_interface_add_del_feature(
1477 sw_if_index=self.pg0.sw_if_index,
1478 flags=flags, is_add=1)
1479 self.vapi.nat44_ei_interface_add_del_feature(
1480 sw_if_index=self.pg4.sw_if_index,
1481 flags=flags, is_add=1)
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)
1488 capture = self.pg3.get_capture(len(pkts))
1489 self.verify_capture_out(capture, nat_ip1, True)
1491 # inside interface VRF don't match NAT44EI static mapping VRF (packets
1493 pkts = self.create_stream_in(self.pg0, self.pg3)
1494 self.pg0.add_stream(pkts)
1495 self.pg_enable_capture(self.pg_interfaces)
1497 self.pg3.assert_nothing_captured()
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
1506 self.nat44_add_address(self.nat_addr)
1507 flags = self.config_flags.NAT44_EI_IF_INSIDE
1508 self.vapi.nat44_ei_interface_add_del_feature(
1509 sw_if_index=self.pg0.sw_if_index,
1510 flags=flags, is_add=1)
1511 self.vapi.nat44_ei_interface_add_del_feature(
1512 sw_if_index=self.pg1.sw_if_index,
1516 pkts = self.create_stream_in(self.pg0, self.pg1)
1517 self.pg0.add_stream(pkts)
1518 self.pg_enable_capture(self.pg_interfaces)
1520 capture = self.pg1.get_capture(len(pkts))
1521 self.verify_capture_out(capture)
1524 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1525 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
1526 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)
1531 capture = self.pg1.get_capture(len(pkts))
1532 self.verify_capture_out(capture, nat_ip, True)
1534 def test_identity_nat(self):
1535 """ NAT44EI Identity NAT """
1536 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1537 self.vapi.nat44_ei_add_del_identity_mapping(
1538 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1539 flags=flags, is_add=1)
1540 flags = self.config_flags.NAT44_EI_IF_INSIDE
1541 self.vapi.nat44_ei_interface_add_del_feature(
1542 sw_if_index=self.pg0.sw_if_index,
1543 flags=flags, is_add=1)
1544 self.vapi.nat44_ei_interface_add_del_feature(
1545 sw_if_index=self.pg1.sw_if_index,
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)
1554 capture = self.pg0.get_capture(1)
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)
1565 self.logger.error(ppp("Unexpected or invalid packet:", p))
1568 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
1569 self.assertEqual(len(sessions), 0)
1570 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1571 self.vapi.nat44_ei_add_del_identity_mapping(
1572 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1573 flags=flags, vrf_id=1, is_add=1)
1574 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
1575 self.assertEqual(len(identity_mappings), 2)
1577 def test_multiple_inside_interfaces(self):
1578 """ NAT44EI multiple non-overlapping address space inside interfaces
1581 self.nat44_add_address(self.nat_addr)
1582 flags = self.config_flags.NAT44_EI_IF_INSIDE
1583 self.vapi.nat44_ei_interface_add_del_feature(
1584 sw_if_index=self.pg0.sw_if_index,
1585 flags=flags, is_add=1)
1586 self.vapi.nat44_ei_interface_add_del_feature(
1587 sw_if_index=self.pg1.sw_if_index,
1588 flags=flags, is_add=1)
1589 self.vapi.nat44_ei_interface_add_del_feature(
1590 sw_if_index=self.pg3.sw_if_index,
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)
1598 capture = self.pg1.get_capture(len(pkts))
1599 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
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)
1606 capture = self.pg2.get_capture(len(pkts))
1607 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
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)
1614 capture = self.pg3.get_capture(len(pkts))
1615 self.verify_capture_out(capture)
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)
1622 capture = self.pg0.get_capture(len(pkts))
1623 self.verify_capture_in(capture, self.pg0)
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)
1630 capture = self.pg3.get_capture(len(pkts))
1631 self.verify_capture_out(capture)
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)
1638 capture = self.pg1.get_capture(len(pkts))
1639 self.verify_capture_in(capture, self.pg1)
1641 def test_inside_overlapping_interfaces(self):
1642 """ NAT44EI multiple inside interfaces with overlapping address space
1645 static_nat_ip = "10.0.0.10"
1646 self.nat44_add_address(self.nat_addr)
1647 flags = self.config_flags.NAT44_EI_IF_INSIDE
1648 self.vapi.nat44_ei_interface_add_del_feature(
1649 sw_if_index=self.pg3.sw_if_index,
1651 self.vapi.nat44_ei_interface_add_del_feature(
1652 sw_if_index=self.pg4.sw_if_index,
1653 flags=flags, is_add=1)
1654 self.vapi.nat44_ei_interface_add_del_feature(
1655 sw_if_index=self.pg5.sw_if_index,
1656 flags=flags, is_add=1)
1657 self.vapi.nat44_ei_interface_add_del_feature(
1658 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,
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)
1668 capture = self.pg5.get_capture(len(pkts))
1669 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
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)
1678 capture = self.pg6.get_capture(1)
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)
1688 self.logger.error(ppp("Unexpected or invalid packet:", p))
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)
1696 capture = self.pg3.get_capture(len(pkts))
1697 self.verify_capture_out(capture)
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)
1704 capture = self.pg4.get_capture(len(pkts))
1705 self.verify_capture_in(capture, self.pg4)
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)
1712 capture = self.pg3.get_capture(len(pkts))
1713 self.verify_capture_out(capture)
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)
1720 capture = self.pg5.get_capture(len(pkts))
1721 self.verify_capture_in(capture, self.pg5)
1724 addresses = self.vapi.nat44_ei_address_dump()
1725 self.assertEqual(len(addresses), 1)
1726 sessions = self.vapi.nat44_ei_user_session_dump(
1727 self.pg5.remote_ip4, 10)
1728 self.assertEqual(len(sessions), 3)
1729 for session in sessions:
1730 self.assertFalse(session.flags &
1731 self.config_flags.NAT44_EI_STATIC_MAPPING)
1732 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)
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)
1751 capture = self.pg3.get_capture(len(pkts))
1752 self.verify_capture_out(capture, static_nat_ip, True)
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)
1759 capture = self.pg6.get_capture(len(pkts))
1760 self.verify_capture_in(capture, self.pg6)
1762 # general user and session dump verifications
1763 users = self.vapi.nat44_ei_user_dump()
1764 self.assertGreaterEqual(len(users), 3)
1765 addresses = self.vapi.nat44_ei_address_dump()
1766 self.assertEqual(len(addresses), 1)
1768 sessions = self.vapi.nat44_ei_user_session_dump(user.ip_address,
1770 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,
1778 sessions = self.vapi.nat44_ei_user_session_dump(
1779 self.pg4.remote_ip4, 10)
1780 self.assertGreaterEqual(len(sessions), 4)
1781 for session in sessions:
1783 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1784 self.assertEqual(str(session.inside_ip_address),
1785 self.pg4.remote_ip4)
1786 self.assertEqual(session.outside_ip_address,
1787 addresses[0].ip_address)
1790 sessions = self.vapi.nat44_ei_user_session_dump(
1791 self.pg6.remote_ip4, 20)
1792 self.assertGreaterEqual(len(sessions), 3)
1793 for session in sessions:
1795 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1796 self.assertEqual(str(session.inside_ip_address),
1797 self.pg6.remote_ip4)
1798 self.assertEqual(str(session.outside_ip_address),
1800 self.assertTrue(session.inside_port in
1801 [self.tcp_port_in, self.udp_port_in,
1804 def test_hairpinning(self):
1805 """ NAT44EI hairpinning - 1:1 NAPT """
1807 host = self.pg0.remote_hosts[0]
1808 server = self.pg0.remote_hosts[1]
1811 server_in_port = 5678
1812 server_out_port = 8765
1814 self.nat44_add_address(self.nat_addr)
1815 flags = self.config_flags.NAT44_EI_IF_INSIDE
1816 self.vapi.nat44_ei_interface_add_del_feature(
1817 sw_if_index=self.pg0.sw_if_index,
1818 flags=flags, is_add=1)
1819 self.vapi.nat44_ei_interface_add_del_feature(
1820 sw_if_index=self.pg1.sw_if_index,
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)
1828 cnt = self.statistics['/nat44-ei/hairpinning']
1829 # 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)
1836 capture = self.pg0.get_capture(1)
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
1848 self.logger.error(ppp("Unexpected or invalid packet:", p))
1851 after = self.statistics['/nat44-ei/hairpinning']
1852 if_idx = self.pg0.sw_if_index
1853 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
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)
1862 capture = self.pg0.get_capture(1)
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)
1873 self.logger.error(ppp("Unexpected or invalid packet:", p))
1876 after = self.statistics['/nat44-ei/hairpinning']
1877 if_idx = self.pg0.sw_if_index
1878 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(),
1879 2+(1 if self.vpp_worker_count > 0 else 0))
1881 def test_hairpinning2(self):
1882 """ NAT44EI hairpinning - 1:1 NAT"""
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
1892 self.nat44_add_address(self.nat_addr)
1893 flags = self.config_flags.NAT44_EI_IF_INSIDE
1894 self.vapi.nat44_ei_interface_add_del_feature(
1895 sw_if_index=self.pg0.sw_if_index,
1896 flags=flags, is_add=1)
1897 self.vapi.nat44_ei_interface_add_del_feature(
1898 sw_if_index=self.pg1.sw_if_index,
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)
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))
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))
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'))
1919 self.pg0.add_stream(pkts)
1920 self.pg_enable_capture(self.pg_interfaces)
1922 capture = self.pg0.get_capture(len(pkts))
1923 for packet in capture:
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
1937 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1938 self.icmp_id_out = packet[ICMP].id
1940 self.logger.error(ppp("Unexpected or invalid packet:", packet))
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))
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))
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'))
1957 self.pg0.add_stream(pkts)
1958 self.pg_enable_capture(self.pg_interfaces)
1960 capture = self.pg0.get_capture(len(pkts))
1961 for packet in capture:
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)
1973 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1975 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1978 # server2 to server1
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))
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))
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'))
1992 self.pg0.add_stream(pkts)
1993 self.pg_enable_capture(self.pg_interfaces)
1995 capture = self.pg0.get_capture(len(pkts))
1996 for packet in capture:
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
2010 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2011 self.icmp_id_out = packet[ICMP].id
2013 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2016 # server1 to server2
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))
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))
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'))
2030 self.pg0.add_stream(pkts)
2031 self.pg_enable_capture(self.pg_interfaces)
2033 capture = self.pg0.get_capture(len(pkts))
2034 for packet in capture:
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)
2046 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2048 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2051 def test_hairpinning_avoid_inf_loop(self):
2052 """ NAT44EI hairpinning - 1:1 NAPT avoid infinite loop """
2054 host = self.pg0.remote_hosts[0]
2055 server = self.pg0.remote_hosts[1]
2058 server_in_port = 5678
2059 server_out_port = 8765
2061 self.nat44_add_address(self.nat_addr)
2062 flags = self.config_flags.NAT44_EI_IF_INSIDE
2063 self.vapi.nat44_ei_interface_add_del_feature(
2064 sw_if_index=self.pg0.sw_if_index,
2065 flags=flags, is_add=1)
2066 self.vapi.nat44_ei_interface_add_del_feature(
2067 sw_if_index=self.pg1.sw_if_index,
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)
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)
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)
2085 # Here VPP used to crash due to an infinite loop
2087 cnt = self.statistics['/nat44-ei/hairpinning']
2088 # 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)
2095 capture = self.pg0.get_capture(1)
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
2107 self.logger.error(ppp("Unexpected or invalid packet:", p))
2110 after = self.statistics['/nat44-ei/hairpinning']
2111 if_idx = self.pg0.sw_if_index
2112 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
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)
2121 capture = self.pg0.get_capture(1)
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)
2132 self.logger.error(ppp("Unexpected or invalid packet:", p))
2135 after = self.statistics['/nat44-ei/hairpinning']
2136 if_idx = self.pg0.sw_if_index
2137 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(),
2138 2+(1 if self.vpp_worker_count > 0 else 0))
2140 def test_interface_addr(self):
2141 """ NAT44EI acquire addresses from interface """
2142 self.vapi.nat44_ei_add_del_interface_addr(
2144 sw_if_index=self.pg7.sw_if_index)
2146 # no address in NAT pool
2147 addresses = self.vapi.nat44_ei_address_dump()
2148 self.assertEqual(0, len(addresses))
2150 # configure interface address and check NAT address pool
2151 self.pg7.config_ip4()
2152 addresses = self.vapi.nat44_ei_address_dump()
2153 self.assertEqual(1, len(addresses))
2154 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2156 # remove interface address and check NAT address pool
2157 self.pg7.unconfig_ip4()
2158 addresses = self.vapi.nat44_ei_address_dump()
2159 self.assertEqual(0, len(addresses))
2161 def test_interface_addr_static_mapping(self):
2162 """ NAT44EI Static mapping with addresses from interface """
2165 self.vapi.nat44_ei_add_del_interface_addr(
2167 sw_if_index=self.pg7.sw_if_index)
2168 self.nat44_add_static_mapping(
2170 external_sw_if_index=self.pg7.sw_if_index,
2173 # static mappings with external interface
2174 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2175 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)
2180 # configure interface address and check static mappings
2181 self.pg7.config_ip4()
2182 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2183 self.assertEqual(2, len(static_mappings))
2185 for sm in static_mappings:
2186 if sm.external_sw_if_index == 0xFFFFFFFF:
2187 self.assertEqual(str(sm.external_ip_address),
2189 self.assertEqual(sm.tag, tag)
2191 self.assertTrue(resolved)
2193 # remove interface address and check static mappings
2194 self.pg7.unconfig_ip4()
2195 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2196 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)
2201 # configure interface address again and check static mappings
2202 self.pg7.config_ip4()
2203 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2204 self.assertEqual(2, len(static_mappings))
2206 for sm in static_mappings:
2207 if sm.external_sw_if_index == 0xFFFFFFFF:
2208 self.assertEqual(str(sm.external_ip_address),
2210 self.assertEqual(sm.tag, tag)
2212 self.assertTrue(resolved)
2214 # remove static mapping
2215 self.nat44_add_static_mapping(
2217 external_sw_if_index=self.pg7.sw_if_index,
2220 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2221 self.assertEqual(0, len(static_mappings))
2223 def test_interface_addr_identity_nat(self):
2224 """ NAT44EI Identity NAT with addresses from interface """
2227 self.vapi.nat44_ei_add_del_interface_addr(
2229 sw_if_index=self.pg7.sw_if_index)
2230 self.vapi.nat44_ei_add_del_identity_mapping(
2232 sw_if_index=self.pg7.sw_if_index,
2234 protocol=IP_PROTOS.tcp,
2237 # identity mappings with external interface
2238 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2239 self.assertEqual(1, len(identity_mappings))
2240 self.assertEqual(self.pg7.sw_if_index,
2241 identity_mappings[0].sw_if_index)
2243 # configure interface address and check identity mappings
2244 self.pg7.config_ip4()
2245 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
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),
2252 self.assertEqual(port, identity_mappings[0].port)
2253 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2255 self.assertTrue(resolved)
2257 # remove interface address and check identity mappings
2258 self.pg7.unconfig_ip4()
2259 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2260 self.assertEqual(1, len(identity_mappings))
2261 self.assertEqual(self.pg7.sw_if_index,
2262 identity_mappings[0].sw_if_index)
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)
2271 flags = self.config_flags.NAT44_EI_IF_INSIDE
2272 self.vapi.nat44_ei_interface_add_del_feature(
2273 sw_if_index=self.pg0.sw_if_index,
2274 flags=flags, is_add=1)
2275 self.vapi.nat44_ei_interface_add_del_feature(
2276 sw_if_index=self.pg1.sw_if_index,
2278 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2279 src_address=self.pg3.local_ip4,
2281 template_interval=10,
2282 collector_port=collector_port)
2283 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2284 src_port=self.ipfix_src_port,
2287 pkts = self.create_stream_in(self.pg0, self.pg1)
2288 self.pg0.add_stream(pkts)
2289 self.pg_enable_capture(self.pg_interfaces)
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
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
2310 if p.haslayer(Data):
2311 data = ipfix.decode_data_set(p.getlayer(Set))
2312 self.verify_ipfix_nat44_ses(data)
2314 def test_ipfix_addr_exhausted(self):
2315 """ NAT44EI IPFIX logging NAT addresses exhausted """
2316 flags = self.config_flags.NAT44_EI_IF_INSIDE
2317 self.vapi.nat44_ei_interface_add_del_feature(
2318 sw_if_index=self.pg0.sw_if_index,
2319 flags=flags, is_add=1)
2320 self.vapi.nat44_ei_interface_add_del_feature(
2321 sw_if_index=self.pg1.sw_if_index,
2323 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2324 src_address=self.pg3.local_ip4,
2326 template_interval=10)
2327 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2328 src_port=self.ipfix_src_port,
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) /
2334 self.pg0.add_stream(p)
2335 self.pg_enable_capture(self.pg_interfaces)
2337 self.pg1.assert_nothing_captured()
2338 self.vapi.ipfix_flush()
2339 capture = self.pg3.get_capture(7)
2340 ipfix = IPFIXDecoder()
2341 # first load template
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
2354 if p.haslayer(Data):
2355 data = ipfix.decode_data_set(p.getlayer(Set))
2356 self.verify_ipfix_addr_exhausted(data)
2358 def test_ipfix_max_sessions(self):
2359 """ NAT44EI IPFIX logging maximum session entries exceeded """
2360 self.nat44_add_address(self.nat_addr)
2361 flags = self.config_flags.NAT44_EI_IF_INSIDE
2362 self.vapi.nat44_ei_interface_add_del_feature(
2363 sw_if_index=self.pg0.sw_if_index,
2364 flags=flags, is_add=1)
2365 self.vapi.nat44_ei_interface_add_del_feature(
2366 sw_if_index=self.pg1.sw_if_index,
2369 max_sessions_per_thread = self.max_translations
2370 max_sessions = max(1, self.vpp_worker_count) * max_sessions_per_thread
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) /
2379 self.pg0.add_stream(pkts)
2380 self.pg_enable_capture(self.pg_interfaces)
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,
2387 template_interval=10)
2388 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2389 src_port=self.ipfix_src_port,
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) /
2395 self.pg0.add_stream(p)
2396 self.pg_enable_capture(self.pg_interfaces)
2398 self.pg1.assert_nothing_captured()
2399 self.vapi.ipfix_flush()
2400 capture = self.pg3.get_capture(7)
2401 ipfix = IPFIXDecoder()
2402 # first load template
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
2415 if p.haslayer(Data):
2416 data = ipfix.decode_data_set(p.getlayer(Set))
2417 self.verify_ipfix_max_sessions(data, max_sessions_per_thread)
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)
2425 flags = self.config_flags.NAT44_EI_IF_INSIDE
2426 self.vapi.nat44_ei_interface_add_del_feature(
2427 sw_if_index=self.pg0.sw_if_index,
2428 flags=flags, is_add=1)
2429 self.vapi.nat44_ei_interface_add_del_feature(
2430 sw_if_index=self.pg1.sw_if_index,
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)
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)
2444 self.pg_enable_capture(self.pg_interfaces)
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)
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)
2454 flags = self.config_flags.NAT44_EI_IF_INSIDE
2455 self.vapi.nat44_ei_interface_add_del_feature(
2456 sw_if_index=self.pg0.sw_if_index,
2457 flags=flags, is_add=1)
2458 self.vapi.nat44_ei_interface_add_del_feature(
2459 sw_if_index=self.pg1.sw_if_index,
2461 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
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)
2470 capture = self.pg1.get_capture(1)
2471 self.assertTrue(capture[0].haslayer(ARP))
2472 self.assertTrue(capture[0][ARP].op, ARP.is_at)
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)
2481 capture = self.pg1.get_capture(1)
2482 self.assertTrue(capture[0].haslayer(ARP))
2483 self.assertTrue(capture[0][ARP].op, ARP.is_at)
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)
2492 self.pg1.assert_nothing_captured()
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,
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)
2505 self.pg1.assert_nothing_captured()
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)
2513 self.pg1.assert_nothing_captured()
2515 def test_vrf_mode(self):
2516 """ NAT44EI tenant VRF aware address pool mode """
2520 nat_ip1 = "10.0.0.10"
2521 nat_ip2 = "10.0.0.11"
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()
2534 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2535 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2536 flags = self.config_flags.NAT44_EI_IF_INSIDE
2537 self.vapi.nat44_ei_interface_add_del_feature(
2538 sw_if_index=self.pg0.sw_if_index,
2539 flags=flags, is_add=1)
2540 self.vapi.nat44_ei_interface_add_del_feature(
2541 sw_if_index=self.pg1.sw_if_index,
2542 flags=flags, is_add=1)
2543 self.vapi.nat44_ei_interface_add_del_feature(
2544 sw_if_index=self.pg2.sw_if_index,
2549 pkts = self.create_stream_in(self.pg0, self.pg2)
2550 self.pg0.add_stream(pkts)
2551 self.pg_enable_capture(self.pg_interfaces)
2553 capture = self.pg2.get_capture(len(pkts))
2554 self.verify_capture_out(capture, nat_ip1)
2557 pkts = self.create_stream_in(self.pg1, self.pg2)
2558 self.pg1.add_stream(pkts)
2559 self.pg_enable_capture(self.pg_interfaces)
2561 capture = self.pg2.get_capture(len(pkts))
2562 self.verify_capture_out(capture, nat_ip2)
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})
2576 def test_vrf_feature_independent(self):
2577 """ NAT44EI tenant VRF independent address pool mode """
2579 nat_ip1 = "10.0.0.10"
2580 nat_ip2 = "10.0.0.11"
2582 self.nat44_add_address(nat_ip1)
2583 self.nat44_add_address(nat_ip2, vrf_id=99)
2584 flags = self.config_flags.NAT44_EI_IF_INSIDE
2585 self.vapi.nat44_ei_interface_add_del_feature(
2586 sw_if_index=self.pg0.sw_if_index,
2587 flags=flags, is_add=1)
2588 self.vapi.nat44_ei_interface_add_del_feature(
2589 sw_if_index=self.pg1.sw_if_index,
2590 flags=flags, is_add=1)
2591 self.vapi.nat44_ei_interface_add_del_feature(
2592 sw_if_index=self.pg2.sw_if_index,
2596 pkts = self.create_stream_in(self.pg0, self.pg2)
2597 self.pg0.add_stream(pkts)
2598 self.pg_enable_capture(self.pg_interfaces)
2600 capture = self.pg2.get_capture(len(pkts))
2601 self.verify_capture_out(capture, nat_ip1)
2604 pkts = self.create_stream_in(self.pg1, self.pg2)
2605 self.pg1.add_stream(pkts)
2606 self.pg_enable_capture(self.pg_interfaces)
2608 capture = self.pg2.get_capture(len(pkts))
2609 self.verify_capture_out(capture, nat_ip1)
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)
2615 flags = self.config_flags.NAT44_EI_IF_INSIDE
2616 self.vapi.nat44_ei_interface_add_del_feature(
2617 sw_if_index=self.pg7.sw_if_index,
2618 flags=flags, is_add=1)
2619 self.vapi.nat44_ei_interface_add_del_feature(
2620 sw_if_index=self.pg8.sw_if_index,
2624 pkts = self.create_stream_in(self.pg7, self.pg8)
2625 self.pg7.add_stream(pkts)
2626 self.pg_enable_capture(self.pg_interfaces)
2628 capture = self.pg8.get_capture(len(pkts))
2629 self.verify_capture_out(capture)
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)
2636 capture = self.pg7.get_capture(len(pkts))
2637 self.verify_capture_in(capture, self.pg7)
2639 def test_static_ipless_interfaces(self):
2640 """ NAT44EI interfaces without configured IP address - 1:1 NAT """
2642 self.create_routes_and_neigbors()
2643 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2644 flags = self.config_flags.NAT44_EI_IF_INSIDE
2645 self.vapi.nat44_ei_interface_add_del_feature(
2646 sw_if_index=self.pg7.sw_if_index,
2647 flags=flags, is_add=1)
2648 self.vapi.nat44_ei_interface_add_del_feature(
2649 sw_if_index=self.pg8.sw_if_index,
2653 pkts = self.create_stream_out(self.pg8)
2654 self.pg8.add_stream(pkts)
2655 self.pg_enable_capture(self.pg_interfaces)
2657 capture = self.pg7.get_capture(len(pkts))
2658 self.verify_capture_in(capture, self.pg7)
2661 pkts = self.create_stream_in(self.pg7, self.pg8)
2662 self.pg7.add_stream(pkts)
2663 self.pg_enable_capture(self.pg_interfaces)
2665 capture = self.pg8.get_capture(len(pkts))
2666 self.verify_capture_out(capture, self.nat_addr, True)
2668 def test_static_with_port_ipless_interfaces(self):
2669 """ NAT44EI interfaces without configured IP address - 1:1 NAPT """
2671 self.tcp_port_out = 30606
2672 self.udp_port_out = 30607
2673 self.icmp_id_out = 30608
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)
2686 flags = self.config_flags.NAT44_EI_IF_INSIDE
2687 self.vapi.nat44_ei_interface_add_del_feature(
2688 sw_if_index=self.pg7.sw_if_index,
2689 flags=flags, is_add=1)
2690 self.vapi.nat44_ei_interface_add_del_feature(
2691 sw_if_index=self.pg8.sw_if_index,
2695 pkts = self.create_stream_out(self.pg8)
2696 self.pg8.add_stream(pkts)
2697 self.pg_enable_capture(self.pg_interfaces)
2699 capture = self.pg7.get_capture(len(pkts))
2700 self.verify_capture_in(capture, self.pg7)
2703 pkts = self.create_stream_in(self.pg7, self.pg8)
2704 self.pg7.add_stream(pkts)
2705 self.pg_enable_capture(self.pg_interfaces)
2707 capture = self.pg8.get_capture(len(pkts))
2708 self.verify_capture_out(capture)
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)
2714 flags = self.config_flags.NAT44_EI_IF_INSIDE
2715 self.vapi.nat44_ei_interface_add_del_feature(
2716 sw_if_index=self.pg0.sw_if_index,
2717 flags=flags, is_add=1)
2718 self.vapi.nat44_ei_interface_add_del_feature(
2719 sw_if_index=self.pg1.sw_if_index,
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) /
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)
2731 p = self.pg1.get_capture(1)
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)
2739 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2743 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2744 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
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)
2751 p = self.pg0.get_capture(1)
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)
2759 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2762 def test_hairpinning_static_unknown_proto(self):
2763 """ NAT44EI 1:1 translate packet with unknown protocol - hairpinning
2766 host = self.pg0.remote_hosts[0]
2767 server = self.pg0.remote_hosts[1]
2769 host_nat_ip = "10.0.0.10"
2770 server_nat_ip = "10.0.0.11"
2772 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2773 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2774 flags = self.config_flags.NAT44_EI_IF_INSIDE
2775 self.vapi.nat44_ei_interface_add_del_feature(
2776 sw_if_index=self.pg0.sw_if_index,
2777 flags=flags, is_add=1)
2778 self.vapi.nat44_ei_interface_add_del_feature(
2779 sw_if_index=self.pg1.sw_if_index,
2783 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2784 IP(src=host.ip4, dst=server_nat_ip) /
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)
2791 p = self.pg0.get_capture(1)
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)
2799 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2803 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2804 IP(src=server.ip4, dst=host_nat_ip) /
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)
2811 p = self.pg0.get_capture(1)
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)
2819 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2822 def test_output_feature(self):
2823 """ NAT44EI output feature (in2out postrouting) """
2824 self.nat44_add_address(self.nat_addr)
2825 self.vapi.nat44_ei_add_del_output_interface(
2826 sw_if_index=self.pg3.sw_if_index, is_add=1)
2829 pkts = self.create_stream_in(self.pg0, self.pg3)
2830 self.pg0.add_stream(pkts)
2831 self.pg_enable_capture(self.pg_interfaces)
2833 capture = self.pg3.get_capture(len(pkts))
2834 self.verify_capture_out(capture)
2837 pkts = self.create_stream_out(self.pg3)
2838 self.pg3.add_stream(pkts)
2839 self.pg_enable_capture(self.pg_interfaces)
2841 capture = self.pg0.get_capture(len(pkts))
2842 self.verify_capture_in(capture, self.pg0)
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)
2849 capture = self.pg0.get_capture(len(pkts))
2850 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
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"
2857 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2858 [VppRoutePath(self.pg3.remote_ip4,
2859 self.pg3.sw_if_index)],
2861 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2862 [VppRoutePath(self.pg3.remote_ip4,
2863 self.pg3.sw_if_index)],
2868 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2869 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2870 self.vapi.nat44_ei_add_del_output_interface(
2871 sw_if_index=self.pg3.sw_if_index, is_add=1)
2874 pkts = self.create_stream_in(self.pg4, self.pg3)
2875 self.pg4.add_stream(pkts)
2876 self.pg_enable_capture(self.pg_interfaces)
2878 capture = self.pg3.get_capture(len(pkts))
2879 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
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)
2886 capture = self.pg4.get_capture(len(pkts))
2887 self.verify_capture_in(capture, self.pg4)
2890 pkts = self.create_stream_in(self.pg6, self.pg3)
2891 self.pg6.add_stream(pkts)
2892 self.pg_enable_capture(self.pg_interfaces)
2894 capture = self.pg3.get_capture(len(pkts))
2895 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
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)
2902 capture = self.pg6.get_capture(len(pkts))
2903 self.verify_capture_in(capture, self.pg6)
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]
2911 server_in_port = 5678
2912 server_out_port = 8765
2914 self.nat44_add_address(self.nat_addr)
2915 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)
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)
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)
2932 capture = self.pg0.get_capture(1)
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
2944 self.logger.error(ppp("Unexpected or invalid packet:", p))
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)
2954 capture = self.pg0.get_capture(1)
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)
2965 self.logger.error(ppp("Unexpected or invalid packet:", p))
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]
2974 self.nat44_add_address(self.nat_addr)
2975 flags = self.config_flags.NAT44_EI_IF_INSIDE
2976 self.vapi.nat44_ei_interface_add_del_feature(
2977 sw_if_index=self.pg9.sw_if_index,
2979 self.vapi.nat44_ei_interface_add_del_feature(
2980 sw_if_index=self.pg9.sw_if_index,
2981 flags=flags, is_add=1)
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)
2990 capture = self.pg9.get_capture(1)
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)
3002 self.logger.error(ppp("Unexpected or invalid packet:", p))
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)
3012 capture = self.pg9.get_capture(1)
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)
3023 self.logger.error(ppp("Unexpected or invalid packet:", p))
3026 if self.vpp_worker_count > 1:
3027 node = "nat44-ei-handoff-classify"
3029 node = "nat44-ei-classify"
3031 err = self.statistics.get_err_counter('/err/%s/next in2out' % node)
3032 self.assertEqual(err, 1)
3033 err = self.statistics.get_err_counter('/err/%s/next out2in' % node)
3034 self.assertEqual(err, 1)
3036 def test_del_session(self):
3037 """ NAT44EI delete session """
3038 self.nat44_add_address(self.nat_addr)
3039 flags = self.config_flags.NAT44_EI_IF_INSIDE
3040 self.vapi.nat44_ei_interface_add_del_feature(
3041 sw_if_index=self.pg0.sw_if_index,
3042 flags=flags, is_add=1)
3043 self.vapi.nat44_ei_interface_add_del_feature(
3044 sw_if_index=self.pg1.sw_if_index,
3047 pkts = self.create_stream_in(self.pg0, self.pg1)
3048 self.pg0.add_stream(pkts)
3049 self.pg_enable_capture(self.pg_interfaces)
3051 self.pg1.get_capture(len(pkts))
3053 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
3054 nsessions = len(sessions)
3056 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)
3062 self.vapi.nat44_ei_del_session(
3063 address=sessions[1].outside_ip_address,
3064 port=sessions[1].outside_port,
3065 protocol=sessions[1].protocol)
3067 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
3068 self.assertEqual(nsessions - len(sessions), 2)
3070 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)
3076 self.verify_no_nat44_user()
3078 def test_frag_in_order(self):
3079 """ NAT44EI translate fragments arriving in order """
3081 self.nat44_add_address(self.nat_addr)
3082 flags = self.config_flags.NAT44_EI_IF_INSIDE
3083 self.vapi.nat44_ei_interface_add_del_feature(
3084 sw_if_index=self.pg0.sw_if_index,
3085 flags=flags, is_add=1)
3086 self.vapi.nat44_ei_interface_add_del_feature(
3087 sw_if_index=self.pg1.sw_if_index,
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)
3094 def test_frag_forwarding(self):
3095 """ NAT44EI forwarding fragment test """
3096 self.vapi.nat44_ei_add_del_interface_addr(
3098 sw_if_index=self.pg1.sw_if_index)
3099 flags = self.config_flags.NAT44_EI_IF_INSIDE
3100 self.vapi.nat44_ei_interface_add_del_feature(
3101 sw_if_index=self.pg0.sw_if_index,
3102 flags=flags, is_add=1)
3103 self.vapi.nat44_ei_interface_add_del_feature(
3104 sw_if_index=self.pg1.sw_if_index,
3106 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
3108 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3109 pkts = self.create_stream_frag(self.pg1,
3110 self.pg0.remote_ip4,
3114 proto=IP_PROTOS.udp)
3115 self.pg1.add_stream(pkts)
3116 self.pg_enable_capture(self.pg_interfaces)
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)
3126 def test_reass_hairpinning(self):
3127 """ NAT44EI fragments hairpinning """
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)
3134 self.nat44_add_address(self.nat_addr)
3135 flags = self.config_flags.NAT44_EI_IF_INSIDE
3136 self.vapi.nat44_ei_interface_add_del_feature(
3137 sw_if_index=self.pg0.sw_if_index,
3138 flags=flags, is_add=1)
3139 self.vapi.nat44_ei_interface_add_del_feature(
3140 sw_if_index=self.pg1.sw_if_index,
3142 # add static mapping for server
3143 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3146 proto=IP_PROTOS.tcp)
3147 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3150 proto=IP_PROTOS.udp)
3151 self.nat44_add_static_mapping(server_addr, self.nat_addr)
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)
3160 def test_frag_out_of_order(self):
3161 """ NAT44EI translate fragments arriving out of order """
3163 self.nat44_add_address(self.nat_addr)
3164 flags = self.config_flags.NAT44_EI_IF_INSIDE
3165 self.vapi.nat44_ei_interface_add_del_feature(
3166 sw_if_index=self.pg0.sw_if_index,
3167 flags=flags, is_add=1)
3168 self.vapi.nat44_ei_interface_add_del_feature(
3169 sw_if_index=self.pg1.sw_if_index,
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)
3176 def test_port_restricted(self):
3177 """ NAT44EI Port restricted NAT44EI (MAP-E CE) """
3178 self.nat44_add_address(self.nat_addr)
3179 flags = self.config_flags.NAT44_EI_IF_INSIDE
3180 self.vapi.nat44_ei_interface_add_del_feature(
3181 sw_if_index=self.pg0.sw_if_index,
3182 flags=flags, is_add=1)
3183 self.vapi.nat44_ei_interface_add_del_feature(
3184 sw_if_index=self.pg1.sw_if_index,
3186 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=1,
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)
3197 capture = self.pg1.get_capture(1)
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)
3209 self.logger.error(ppp("Unexpected or invalid packet:", p))
3212 def test_port_range(self):
3213 """ NAT44EI External address port range """
3214 self.nat44_add_address(self.nat_addr)
3215 flags = self.config_flags.NAT44_EI_IF_INSIDE
3216 self.vapi.nat44_ei_interface_add_del_feature(
3217 sw_if_index=self.pg0.sw_if_index,
3218 flags=flags, is_add=1)
3219 self.vapi.nat44_ei_interface_add_del_feature(
3220 sw_if_index=self.pg1.sw_if_index,
3222 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=2,
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))
3232 self.pg0.add_stream(pkts)
3233 self.pg_enable_capture(self.pg_interfaces)
3235 capture = self.pg1.get_capture(3)
3238 self.assertGreaterEqual(tcp.sport, 1025)
3239 self.assertLessEqual(tcp.sport, 1027)
3241 def test_multiple_outside_vrf(self):
3242 """ NAT44EI Multiple outside VRF """
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()
3257 self.nat44_add_address(self.nat_addr)
3258 flags = self.config_flags.NAT44_EI_IF_INSIDE
3259 self.vapi.nat44_ei_interface_add_del_feature(
3260 sw_if_index=self.pg0.sw_if_index,
3261 flags=flags, is_add=1)
3262 self.vapi.nat44_ei_interface_add_del_feature(
3263 sw_if_index=self.pg1.sw_if_index,
3265 self.vapi.nat44_ei_interface_add_del_feature(
3266 sw_if_index=self.pg2.sw_if_index,
3271 pkts = self.create_stream_in(self.pg0, self.pg1)
3272 self.pg0.add_stream(pkts)
3273 self.pg_enable_capture(self.pg_interfaces)
3275 capture = self.pg1.get_capture(len(pkts))
3276 self.verify_capture_out(capture, self.nat_addr)
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)
3282 capture = self.pg0.get_capture(len(pkts))
3283 self.verify_capture_in(capture, self.pg0)
3285 self.tcp_port_in = 60303
3286 self.udp_port_in = 60304
3287 self.icmp_id_in = 60305
3290 pkts = self.create_stream_in(self.pg0, self.pg2)
3291 self.pg0.add_stream(pkts)
3292 self.pg_enable_capture(self.pg_interfaces)
3294 capture = self.pg2.get_capture(len(pkts))
3295 self.verify_capture_out(capture, self.nat_addr)
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)
3301 capture = self.pg0.get_capture(len(pkts))
3302 self.verify_capture_in(capture, self.pg0)
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()
3315 def test_mss_clamping(self):
3316 """ NAT44EI TCP MSS clamping """
3317 self.nat44_add_address(self.nat_addr)
3318 flags = self.config_flags.NAT44_EI_IF_INSIDE
3319 self.vapi.nat44_ei_interface_add_del_feature(
3320 sw_if_index=self.pg0.sw_if_index,
3321 flags=flags, is_add=1)
3322 self.vapi.nat44_ei_interface_add_del_feature(
3323 sw_if_index=self.pg1.sw_if_index,
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)]))
3331 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1000)
3332 self.pg0.add_stream(p)
3333 self.pg_enable_capture(self.pg_interfaces)
3335 capture = self.pg1.get_capture(1)
3336 # Negotiated MSS value greater than configured - changed
3337 self.verify_mss_value(capture[0], 1000)
3339 self.vapi.nat44_ei_set_mss_clamping(enable=0, mss_value=1500)
3340 self.pg0.add_stream(p)
3341 self.pg_enable_capture(self.pg_interfaces)
3343 capture = self.pg1.get_capture(1)
3344 # MSS clamping disabled - negotiated MSS unchanged
3345 self.verify_mss_value(capture[0], 1400)
3347 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1500)
3348 self.pg0.add_stream(p)
3349 self.pg_enable_capture(self.pg_interfaces)
3351 capture = self.pg1.get_capture(1)
3352 # Negotiated MSS value smaller than configured - unchanged
3353 self.verify_mss_value(capture[0], 1400)
3355 def test_ha_send(self):
3356 """ NAT44EI Send HA session synchronization events (active) """
3357 flags = self.config_flags.NAT44_EI_IF_INSIDE
3358 self.vapi.nat44_ei_interface_add_del_feature(
3359 sw_if_index=self.pg0.sw_if_index,
3360 flags=flags, is_add=1)
3361 self.vapi.nat44_ei_interface_add_del_feature(
3362 sw_if_index=self.pg1.sw_if_index,
3364 self.nat44_add_address(self.nat_addr)
3366 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)
3371 bind_layers(UDP, HANATStateSync, sport=12345)
3374 pkts = self.create_stream_in(self.pg0, self.pg1)
3375 self.pg0.add_stream(pkts)
3376 self.pg_enable_capture(self.pg_interfaces)
3378 capture = self.pg1.get_capture(len(pkts))
3379 self.verify_capture_out(capture)
3380 # active send HA events
3381 self.vapi.nat44_ei_ha_flush()
3382 stats = self.statistics['/nat44-ei/ha/add-event-send']
3383 self.assertEqual(stats[:, 0].sum(), 3)
3384 capture = self.pg3.get_capture(1)
3386 self.assert_packet_checksums_valid(p)
3390 hanat = p[HANATStateSync]
3392 self.logger.error(ppp("Invalid packet:", p))
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)
3400 # self.assertEqual(hanat.thread_index, 0)
3401 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)
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) /
3413 HANATStateSync(sequence_number=seq, flags='ACK',
3414 thread_index=hanat.thread_index))
3415 self.pg3.add_stream(ack)
3417 stats = self.statistics['/nat44-ei/ha/ack-recv']
3418 self.assertEqual(stats[:, 0].sum(), 1)
3420 # delete one session
3421 self.pg_enable_capture(self.pg_interfaces)
3422 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()
3426 stats = self.statistics['/nat44-ei/ha/del-event-send']
3427 self.assertEqual(stats[:, 0].sum(), 1)
3428 capture = self.pg3.get_capture(1)
3431 hanat = p[HANATStateSync]
3433 self.logger.error(ppp("Invalid packet:", p))
3436 self.assertGreater(hanat.sequence_number, seq)
3438 # do not send ACK, active retry send HA event again
3439 self.pg_enable_capture(self.pg_interfaces)
3440 self.virtual_sleep(12)
3441 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)
3445 capture = self.pg3.get_capture(3)
3446 for packet in capture:
3447 self.assertEqual(packet, p)
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)
3454 self.pg0.get_capture(2)
3455 self.vapi.nat44_ei_ha_flush()
3456 stats = self.statistics['/nat44-ei/ha/refresh-event-send']
3457 self.assertEqual(stats[:, 0].sum(), 2)
3458 capture = self.pg3.get_capture(1)
3460 self.assert_packet_checksums_valid(p)
3464 hanat = p[HANATStateSync]
3466 self.logger.error(ppp("Invalid packet:", p))
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)
3483 stats = self.statistics['/nat44-ei/ha/ack-recv']
3484 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) /
3487 HANATStateSync(sequence_number=seq, flags='ACK',
3488 thread_index=hanat.thread_index))
3489 self.pg3.add_stream(ack)
3491 stats = self.statistics['/nat44-ei/ha/ack-recv']
3492 self.assertEqual(stats[:, 0].sum(), 2)
3494 def test_ha_recv(self):
3495 """ NAT44EI Receive HA session synchronization events (passive) """
3496 self.nat44_add_address(self.nat_addr)
3497 flags = self.config_flags.NAT44_EI_IF_INSIDE
3498 self.vapi.nat44_ei_interface_add_del_feature(
3499 sw_if_index=self.pg0.sw_if_index,
3500 flags=flags, is_add=1)
3501 self.vapi.nat44_ei_interface_add_del_feature(
3502 sw_if_index=self.pg1.sw_if_index,
3504 self.vapi.nat44_ei_ha_set_listener(ip_address=self.pg3.local_ip4,
3505 port=12345, path_mtu=512)
3506 bind_layers(UDP, HANATStateSync, sport=12345)
3508 # 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)
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)
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)
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,
3544 ehn_port=self.udp_external_port, fib_index=0)],
3545 thread_index=thread_index))
3547 self.pg3.add_stream(p)
3548 self.pg_enable_capture(self.pg_interfaces)
3551 capture = self.pg3.get_capture(1)
3554 hanat = p[HANATStateSync]
3556 self.logger.error(ppp("Invalid packet:", p))
3559 self.assertEqual(hanat.sequence_number, 1)
3560 self.assertEqual(hanat.flags, 'ACK')
3561 self.assertEqual(hanat.version, 1)
3562 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)
3571 users = self.vapi.nat44_ei_user_dump()
3572 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
3576 sessions = self.vapi.nat44_ei_user_session_dump(
3577 users[0].ip_address, users[0].vrf_id)
3578 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),
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])
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,
3601 ehn_port=self.udp_external_port, fib_index=0)],
3602 thread_index=thread_index))
3604 self.pg3.add_stream(p)
3605 self.pg_enable_capture(self.pg_interfaces)
3608 capture = self.pg3.get_capture(1)
3611 hanat = p[HANATStateSync]
3613 self.logger.error(ppp("Invalid packet:", p))
3616 self.assertEqual(hanat.sequence_number, 2)
3617 self.assertEqual(hanat.flags, 'ACK')
3618 self.assertEqual(hanat.version, 1)
3619 users = self.vapi.nat44_ei_user_dump()
3620 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
3624 sessions = self.vapi.nat44_ei_user_session_dump(users[0].ip_address,
3626 self.assertEqual(len(sessions), 1)
3627 stats = self.statistics['/nat44-ei/ha/del-event-recv']
3628 self.assertEqual(stats[:, 0].sum(), 1)
3630 stats = self.statistics.get_err_counter(
3631 '/err/nat44-ei-ha/pkts-processed')
3632 self.assertEqual(stats, 2)
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,
3646 total_bytes=1024, total_pkts=2)],
3647 thread_index=thread_index))
3648 self.pg3.add_stream(p)
3649 self.pg_enable_capture(self.pg_interfaces)
3652 capture = self.pg3.get_capture(1)
3655 hanat = p[HANATStateSync]
3657 self.logger.error(ppp("Invalid packet:", p))
3660 self.assertEqual(hanat.sequence_number, 3)
3661 self.assertEqual(hanat.flags, 'ACK')
3662 self.assertEqual(hanat.version, 1)
3663 users = self.vapi.nat44_ei_user_dump()
3664 self.assertEqual(len(users), 1)
3665 self.assertEqual(str(users[0].ip_address),
3666 self.pg0.remote_ip4)
3667 sessions = self.vapi.nat44_ei_user_session_dump(
3668 users[0].ip_address, users[0].vrf_id)
3669 self.assertEqual(len(sessions), 1)
3670 session = sessions[0]
3671 self.assertEqual(session.total_bytes, 1024)
3672 self.assertEqual(session.total_pkts, 2)
3673 stats = self.statistics['/nat44-ei/ha/refresh-event-recv']
3674 self.assertEqual(stats[:, 0].sum(), 1)
3676 stats = self.statistics.get_err_counter(
3677 '/err/nat44-ei-ha/pkts-processed')
3678 self.assertEqual(stats, 3)
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)
3687 capture = self.pg0.get_capture(1)
3693 self.logger.error(ppp("Invalid packet:", p))
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)
3701 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
3708 def test_set_frame_queue_nelts(self):
3709 """ NAT44EI API test - worker handoff frame queue elements """
3710 self.assertEqual(self.reconfigure_frame_queue_nelts(512), 512)
3712 def show_commands_at_teardown(self):
3713 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"))
3722 self.vapi.cli("show nat44 ei addr-port-assignment-alg"))
3724 def test_outside_address_distribution(self):
3725 """ Outside address distribution based on source address """
3730 for i in range(1, x):
3732 nat_addresses.append(a)
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,
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)
3747 self.pg0.generate_remote_hosts(x)
3751 info = self.create_packet_info(self.pg0, self.pg1)
3752 payload = self.info_to_payload(info)
3753 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) /
3756 UDP(sport=7000+i, dport=8000+i) /
3761 self.pg0.add_stream(pkts)
3762 self.pg_enable_capture(self.pg_interfaces)
3764 recvd = self.pg1.get_capture(len(pkts))
3765 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)
3772 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)]
3778 "Invalid packet (src IP %s translated to %s, but expected %s)"
3779 % (p_sent[IP].src, p_recvd[IP].src, a))
3781 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)
3788 class TestNAT44Out2InDPO(MethodHolder):
3789 """ NAT44EI Test Cases using out2in DPO """
3792 def setUpClass(cls):
3793 super(TestNAT44Out2InDPO, cls).setUpClass()
3794 cls.vapi.cli("set log class nat44-ei level debug")
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'
3805 cls.create_pg_interfaces(range(2))
3808 cls.pg0.config_ip4()
3809 cls.pg0.resolve_arp()
3812 cls.pg1.config_ip6()
3813 cls.pg1.resolve_ndp()
3815 r1 = VppIpRoute(cls, "::", 0,
3816 [VppRoutePath(cls.pg1.remote_ip6,
3817 cls.pg1.sw_if_index)],
3822 super(TestNAT44Out2InDPO, self).setUp()
3823 flags = self.config_flags.NAT44_EI_OUT2IN_DPO
3824 self.vapi.nat44_ei_plugin_enable_disable(enable=1, flags=flags)
3827 super(TestNAT44Out2InDPO, self).tearDown()
3828 if not self.vpp_dead:
3829 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3830 self.vapi.cli("clear logging")
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,
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,
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)
3845 @unittest.skip('Temporary disabled')
3846 def test_464xlat_ce(self):
3847 """ Test 464XLAT CE with NAT44EI """
3849 self.configure_xlat()
3851 flags = self.config_flags.NAT44_EI_IF_INSIDE
3852 self.vapi.nat44_ei_interface_add_del_feature(
3853 sw_if_index=self.pg0.sw_if_index,
3854 flags=flags, is_add=1)
3855 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)
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)
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)
3870 capture = self.pg1.get_capture(len(pkts))
3871 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
3874 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
3876 self.pg1.add_stream(pkts)
3877 self.pg_enable_capture(self.pg_interfaces)
3879 capture = self.pg0.get_capture(len(pkts))
3880 self.verify_capture_in(capture, self.pg0)
3882 self.vapi.nat44_ei_interface_add_del_feature(
3883 sw_if_index=self.pg0.sw_if_index,
3885 self.vapi.nat44_ei_add_del_address_range(
3886 first_ip_address=self.nat_addr_n,
3887 last_ip_address=self.nat_addr_n,
3890 @unittest.skip('Temporary disabled')
3891 def test_464xlat_ce_no_nat(self):
3892 """ Test 464XLAT CE without NAT44EI """
3894 self.configure_xlat()
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)
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)
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)
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)
3913 capture = self.pg0.get_capture(len(pkts))
3914 self.verify_capture_in(capture, self.pg0)
3917 class TestNAT44EIMW(MethodHolder):
3918 """ NAT44EI Test Cases (multiple workers) """
3919 vpp_worker_count = 2
3920 max_translations = 10240
3924 def setUpClass(cls):
3925 super(TestNAT44EIMW, cls).setUpClass()
3926 cls.vapi.cli("set log class nat level debug")
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
3940 cls.create_pg_interfaces(range(10))
3941 cls.interfaces = list(cls.pg_interfaces[0:4])
3943 for i in cls.interfaces:
3948 cls.pg0.generate_remote_hosts(3)
3949 cls.pg0.configure_ipv4_neighbors()
3951 cls.pg1.generate_remote_hosts(1)
3952 cls.pg1.configure_ipv4_neighbors()
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})
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:
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")
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()
3988 super(TestNAT44EIMW, self).setUp()
3989 self.vapi.nat44_ei_plugin_enable_disable(
3990 sessions=self.max_translations,
3991 users=self.max_users, enable=1)
3994 super(TestNAT44EIMW, self).tearDown()
3995 if not self.vpp_dead:
3996 self.vapi.nat44_ei_ipfix_enable_disable(
3997 domain_id=self.ipfix_domain_id,
3998 src_port=self.ipfix_src_port,
4000 self.ipfix_src_port = 4739
4001 self.ipfix_domain_id = 1
4003 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
4004 self.vapi.cli("clear logging")
4006 def test_hairpinning(self):
4007 """ NAT44EI hairpinning - 1:1 NAPT """
4009 host = self.pg0.remote_hosts[0]
4010 server = self.pg0.remote_hosts[1]
4013 server_in_port = 5678
4014 server_out_port = 8765
4018 self.nat44_add_address(self.nat_addr)
4019 flags = self.config_flags.NAT44_EI_IF_INSIDE
4020 self.vapi.nat44_ei_interface_add_del_feature(
4021 sw_if_index=self.pg0.sw_if_index,
4022 flags=flags, is_add=1)
4023 self.vapi.nat44_ei_interface_add_del_feature(
4024 sw_if_index=self.pg1.sw_if_index,
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)
4032 cnt = self.statistics['/nat44-ei/hairpinning']
4033 # 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)
4040 capture = self.pg0.get_capture(1)
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
4052 self.logger.error(ppp("Unexpected or invalid packet:", p))
4055 after = self.statistics['/nat44-ei/hairpinning']
4057 if_idx = self.pg0.sw_if_index
4058 self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1)
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)
4067 capture = self.pg0.get_capture(1)
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)
4078 self.logger.error(ppp("Unexpected or invalid packet:", p))
4081 after = self.statistics['/nat44-ei/hairpinning']
4082 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)
4086 def test_hairpinning2(self):
4087 """ NAT44EI hairpinning - 1:1 NAT"""
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
4097 self.nat44_add_address(self.nat_addr)
4098 flags = self.config_flags.NAT44_EI_IF_INSIDE
4099 self.vapi.nat44_ei_interface_add_del_feature(
4100 sw_if_index=self.pg0.sw_if_index,
4101 flags=flags, is_add=1)
4102 self.vapi.nat44_ei_interface_add_del_feature(
4103 sw_if_index=self.pg1.sw_if_index,
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)
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))
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))
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'))
4124 self.pg0.add_stream(pkts)
4125 self.pg_enable_capture(self.pg_interfaces)
4127 capture = self.pg0.get_capture(len(pkts))
4128 for packet in capture:
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
4142 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
4143 self.icmp_id_out = packet[ICMP].id
4145 self.logger.error(ppp("Unexpected or invalid packet:", packet))
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))
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))
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'))
4162 self.pg0.add_stream(pkts)
4163 self.pg_enable_capture(self.pg_interfaces)
4165 capture = self.pg0.get_capture(len(pkts))
4166 for packet in capture:
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)
4178 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4180 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4183 # server2 to server1
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))
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))
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'))
4197 self.pg0.add_stream(pkts)
4198 self.pg_enable_capture(self.pg_interfaces)
4200 capture = self.pg0.get_capture(len(pkts))
4201 for packet in capture:
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
4215 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4216 self.icmp_id_out = packet[ICMP].id
4218 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4221 # server1 to server2
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))
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))
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'))
4235 self.pg0.add_stream(pkts)
4236 self.pg_enable_capture(self.pg_interfaces)
4238 capture = self.pg0.get_capture(len(pkts))
4239 for packet in capture:
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)
4251 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4253 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4257 if __name__ == '__main__':
4258 unittest.main(testRunner=VppTestRunner)