12 from framework import tag_fixme_vpp_workers
13 from framework import VppTestCase, VppTestRunner
14 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
15 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
16 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
18 from scapy.data import IP_PROTOS
19 from scapy.layers.inet import IP, TCP, UDP, ICMP
20 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
21 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
22 from scapy.layers.l2 import Ether, ARP, GRE
23 from scapy.packet import Raw
24 from syslog_rfc5424_parser import SyslogMessage, ParseError
25 from syslog_rfc5424_parser.constants import SyslogSeverity
27 from vpp_ip_route import VppIpRoute, VppRoutePath
28 from vpp_neighbor import VppNeighbor
29 from vpp_papi import VppEnum
32 # NAT HA protocol event data
35 fields_desc = [ByteEnumField("event_type", None,
36 {1: "add", 2: "del", 3: "refresh"}),
37 ByteEnumField("protocol", None,
38 {0: "other", 1: "udp", 2: "tcp", 3: "icmp"}),
39 ShortField("flags", 0),
40 IPField("in_addr", None),
41 IPField("out_addr", None),
42 ShortField("in_port", None),
43 ShortField("out_port", None),
44 IPField("eh_addr", None),
45 IPField("ehn_addr", None),
46 ShortField("eh_port", None),
47 ShortField("ehn_port", None),
48 IntField("fib_index", None),
49 IntField("total_pkts", 0),
50 LongField("total_bytes", 0)]
52 def extract_padding(self, s):
56 # NAT HA protocol header
57 class HANATStateSync(Packet):
58 name = "HA NAT state sync"
59 fields_desc = [XByteField("version", 1),
60 FlagsField("flags", 0, 8, ['ACK']),
61 FieldLenField("count", None, count_of="events"),
62 IntField("sequence_number", 1),
63 IntField("thread_index", 0),
64 PacketListField("events", [], Event,
65 count_from=lambda pkt: pkt.count)]
68 class MethodHolder(VppTestCase):
69 """ NAT create capture and verify method holder """
72 def config_flags(self):
73 return VppEnum.vl_api_nat_config_flags_t
76 def nat44_config_flags(self):
77 return VppEnum.vl_api_nat44_config_flags_t
80 def SYSLOG_SEVERITY(self):
81 return VppEnum.vl_api_syslog_severity_t
83 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
84 local_port=0, external_port=0, vrf_id=0,
85 is_add=1, external_sw_if_index=0xFFFFFFFF,
86 proto=0, tag="", flags=0):
88 Add/delete NAT44EI static mapping
90 :param local_ip: Local IP address
91 :param external_ip: External IP address
92 :param local_port: Local port number (Optional)
93 :param external_port: External port number (Optional)
94 :param vrf_id: VRF ID (Default 0)
95 :param is_add: 1 if add, 0 if delete (Default add)
96 :param external_sw_if_index: External interface instead of IP address
97 :param proto: IP protocol (Mandatory if port specified)
98 :param tag: Opaque string tag
99 :param flags: NAT configuration flags
102 if not (local_port and external_port):
103 flags |= self.config_flags.NAT_IS_ADDR_ONLY
105 self.vapi.nat44_add_del_static_mapping(
107 local_ip_address=local_ip,
108 external_ip_address=external_ip,
109 external_sw_if_index=external_sw_if_index,
110 local_port=local_port,
111 external_port=external_port,
112 vrf_id=vrf_id, protocol=proto,
116 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
118 Add/delete NAT44EI address
120 :param ip: IP address
121 :param is_add: 1 if add, 0 if delete (Default add)
122 :param twice_nat: twice NAT address for external hosts
124 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
125 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
131 def create_routes_and_neigbors(self):
132 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
133 [VppRoutePath(self.pg7.remote_ip4,
134 self.pg7.sw_if_index)])
135 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
136 [VppRoutePath(self.pg8.remote_ip4,
137 self.pg8.sw_if_index)])
141 n1 = VppNeighbor(self,
142 self.pg7.sw_if_index,
146 n2 = VppNeighbor(self,
147 self.pg8.sw_if_index,
154 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
156 Create packet stream for inside network
158 :param in_if: Inside interface
159 :param out_if: Outside interface
160 :param dst_ip: Destination address
161 :param ttl: TTL of generated packets
164 dst_ip = out_if.remote_ip4
168 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
169 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
170 TCP(sport=self.tcp_port_in, dport=20))
174 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
175 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
176 UDP(sport=self.udp_port_in, dport=20))
180 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
181 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
182 ICMP(id=self.icmp_id_in, type='echo-request'))
187 def compose_ip6(self, ip4, pref, plen):
189 Compose IPv4-embedded IPv6 addresses
191 :param ip4: IPv4 address
192 :param pref: IPv6 prefix
193 :param plen: IPv6 prefix length
194 :returns: IPv4-embedded IPv6 addresses
196 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
197 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
212 pref_n[10] = ip4_n[3]
216 pref_n[10] = ip4_n[2]
217 pref_n[11] = ip4_n[3]
220 pref_n[10] = ip4_n[1]
221 pref_n[11] = ip4_n[2]
222 pref_n[12] = ip4_n[3]
224 pref_n[12] = ip4_n[0]
225 pref_n[13] = ip4_n[1]
226 pref_n[14] = ip4_n[2]
227 pref_n[15] = ip4_n[3]
228 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
229 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
231 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
232 use_inside_ports=False):
234 Create packet stream for outside network
236 :param out_if: Outside interface
237 :param dst_ip: Destination IP address (Default use global NAT address)
238 :param ttl: TTL of generated packets
239 :param use_inside_ports: Use inside NAT ports as destination ports
240 instead of outside ports
243 dst_ip = self.nat_addr
244 if not use_inside_ports:
245 tcp_port = self.tcp_port_out
246 udp_port = self.udp_port_out
247 icmp_id = self.icmp_id_out
249 tcp_port = self.tcp_port_in
250 udp_port = self.udp_port_in
251 icmp_id = self.icmp_id_in
254 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
255 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
256 TCP(dport=tcp_port, sport=20))
260 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
261 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
262 UDP(dport=udp_port, sport=20))
266 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
267 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
268 ICMP(id=icmp_id, type='echo-reply'))
273 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
275 Create packet stream for outside network
277 :param out_if: Outside interface
278 :param dst_ip: Destination IP address (Default use global NAT address)
279 :param hl: HL of generated packets
283 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
284 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
285 TCP(dport=self.tcp_port_out, sport=20))
289 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
290 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
291 UDP(dport=self.udp_port_out, sport=20))
295 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
296 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
297 ICMPv6EchoReply(id=self.icmp_id_out))
302 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
303 dst_ip=None, is_ip6=False, ignore_port=False):
305 Verify captured packets on outside network
307 :param capture: Captured packets
308 :param nat_ip: Translated IP address (Default use global NAT address)
309 :param same_port: Source port number is not translated (Default False)
310 :param dst_ip: Destination IP address (Default do not verify)
311 :param is_ip6: If L3 protocol is IPv6 (Default False)
315 ICMP46 = ICMPv6EchoRequest
320 nat_ip = self.nat_addr
321 for packet in capture:
324 self.assert_packet_checksums_valid(packet)
325 self.assertEqual(packet[IP46].src, nat_ip)
326 if dst_ip is not None:
327 self.assertEqual(packet[IP46].dst, dst_ip)
328 if packet.haslayer(TCP):
332 packet[TCP].sport, self.tcp_port_in)
335 packet[TCP].sport, self.tcp_port_in)
336 self.tcp_port_out = packet[TCP].sport
337 self.assert_packet_checksums_valid(packet)
338 elif packet.haslayer(UDP):
342 packet[UDP].sport, self.udp_port_in)
345 packet[UDP].sport, self.udp_port_in)
346 self.udp_port_out = packet[UDP].sport
351 packet[ICMP46].id, self.icmp_id_in)
354 packet[ICMP46].id, self.icmp_id_in)
355 self.icmp_id_out = packet[ICMP46].id
356 self.assert_packet_checksums_valid(packet)
358 self.logger.error(ppp("Unexpected or invalid packet "
359 "(outside network):", packet))
362 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
365 Verify captured packets on outside network
367 :param capture: Captured packets
368 :param nat_ip: Translated IP address
369 :param same_port: Source port number is not translated (Default False)
370 :param dst_ip: Destination IP address (Default do not verify)
372 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
375 def verify_capture_in(self, capture, in_if):
377 Verify captured packets on inside network
379 :param capture: Captured packets
380 :param in_if: Inside interface
382 for packet in capture:
384 self.assert_packet_checksums_valid(packet)
385 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
386 if packet.haslayer(TCP):
387 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
388 elif packet.haslayer(UDP):
389 self.assertEqual(packet[UDP].dport, self.udp_port_in)
391 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
393 self.logger.error(ppp("Unexpected or invalid packet "
394 "(inside network):", packet))
397 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
399 Verify captured packet that don't have to be translated
401 :param capture: Captured packets
402 :param ingress_if: Ingress interface
403 :param egress_if: Egress interface
405 for packet in capture:
407 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
408 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
409 if packet.haslayer(TCP):
410 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
411 elif packet.haslayer(UDP):
412 self.assertEqual(packet[UDP].sport, self.udp_port_in)
414 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
416 self.logger.error(ppp("Unexpected or invalid packet "
417 "(inside network):", packet))
420 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
423 Verify captured packets with ICMP errors on outside network
425 :param capture: Captured packets
426 :param src_ip: Translated IP address or IP address of VPP
427 (Default use global NAT address)
428 :param icmp_type: Type of error ICMP packet
429 we are expecting (Default 11)
432 src_ip = self.nat_addr
433 for packet in capture:
435 self.assertEqual(packet[IP].src, src_ip)
436 self.assertEqual(packet.haslayer(ICMP), 1)
438 self.assertEqual(icmp.type, icmp_type)
439 self.assertTrue(icmp.haslayer(IPerror))
440 inner_ip = icmp[IPerror]
441 if inner_ip.haslayer(TCPerror):
442 self.assertEqual(inner_ip[TCPerror].dport,
444 elif inner_ip.haslayer(UDPerror):
445 self.assertEqual(inner_ip[UDPerror].dport,
448 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
450 self.logger.error(ppp("Unexpected or invalid packet "
451 "(outside network):", packet))
454 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
456 Verify captured packets with ICMP errors on inside network
458 :param capture: Captured packets
459 :param in_if: Inside interface
460 :param icmp_type: Type of error ICMP packet
461 we are expecting (Default 11)
463 for packet in capture:
465 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
466 self.assertEqual(packet.haslayer(ICMP), 1)
468 self.assertEqual(icmp.type, icmp_type)
469 self.assertTrue(icmp.haslayer(IPerror))
470 inner_ip = icmp[IPerror]
471 if inner_ip.haslayer(TCPerror):
472 self.assertEqual(inner_ip[TCPerror].sport,
474 elif inner_ip.haslayer(UDPerror):
475 self.assertEqual(inner_ip[UDPerror].sport,
478 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
480 self.logger.error(ppp("Unexpected or invalid packet "
481 "(inside network):", packet))
484 def create_stream_frag(self, src_if, dst, sport, dport, data,
485 proto=IP_PROTOS.tcp, echo_reply=False):
487 Create fragmented packet stream
489 :param src_if: Source interface
490 :param dst: Destination IPv4 address
491 :param sport: Source port
492 :param dport: Destination port
493 :param data: Payload data
494 :param proto: protocol (TCP, UDP, ICMP)
495 :param echo_reply: use echo_reply if protocol is ICMP
498 if proto == IP_PROTOS.tcp:
499 p = (IP(src=src_if.remote_ip4, dst=dst) /
500 TCP(sport=sport, dport=dport) /
502 p = p.__class__(scapy.compat.raw(p))
503 chksum = p[TCP].chksum
504 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
505 elif proto == IP_PROTOS.udp:
506 proto_header = UDP(sport=sport, dport=dport)
507 elif proto == IP_PROTOS.icmp:
509 proto_header = ICMP(id=sport, type='echo-request')
511 proto_header = ICMP(id=sport, type='echo-reply')
513 raise Exception("Unsupported protocol")
514 id = random.randint(0, 65535)
516 if proto == IP_PROTOS.tcp:
519 raw = Raw(data[0:16])
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=0, id=id) /
525 if proto == IP_PROTOS.tcp:
526 raw = Raw(data[4:20])
528 raw = Raw(data[16:32])
529 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
530 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
534 if proto == IP_PROTOS.tcp:
538 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
539 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
545 def reass_frags_and_verify(self, frags, src, dst):
547 Reassemble and verify fragmented packet
549 :param frags: Captured fragments
550 :param src: Source IPv4 address to verify
551 :param dst: Destination IPv4 address to verify
553 :returns: Reassembled IPv4 packet
557 self.assertEqual(p[IP].src, src)
558 self.assertEqual(p[IP].dst, dst)
559 self.assert_ip_checksum_valid(p)
560 buffer.seek(p[IP].frag * 8)
561 buffer.write(bytes(p[IP].payload))
562 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
563 proto=frags[0][IP].proto)
564 if ip.proto == IP_PROTOS.tcp:
565 p = (ip / TCP(buffer.getvalue()))
566 self.logger.debug(ppp("Reassembled:", p))
567 self.assert_tcp_checksum_valid(p)
568 elif ip.proto == IP_PROTOS.udp:
569 p = (ip / UDP(buffer.getvalue()[:8]) /
570 Raw(buffer.getvalue()[8:]))
571 elif ip.proto == IP_PROTOS.icmp:
572 p = (ip / ICMP(buffer.getvalue()))
575 def verify_ipfix_nat44_ses(self, data):
577 Verify IPFIX NAT44EI session create/delete event
579 :param data: Decoded IPFIX data records
581 nat44_ses_create_num = 0
582 nat44_ses_delete_num = 0
583 self.assertEqual(6, len(data))
586 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
587 if scapy.compat.orb(record[230]) == 4:
588 nat44_ses_create_num += 1
590 nat44_ses_delete_num += 1
592 self.assertEqual(self.pg0.remote_ip4,
593 str(ipaddress.IPv4Address(record[8])))
594 # postNATSourceIPv4Address
595 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
598 self.assertEqual(struct.pack("!I", 0), record[234])
599 # protocolIdentifier/sourceTransportPort
600 # /postNAPTSourceTransportPort
601 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
602 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
603 self.assertEqual(struct.pack("!H", self.icmp_id_out),
605 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
606 self.assertEqual(struct.pack("!H", self.tcp_port_in),
608 self.assertEqual(struct.pack("!H", self.tcp_port_out),
610 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
611 self.assertEqual(struct.pack("!H", self.udp_port_in),
613 self.assertEqual(struct.pack("!H", self.udp_port_out),
616 self.fail("Invalid protocol")
617 self.assertEqual(3, nat44_ses_create_num)
618 self.assertEqual(3, nat44_ses_delete_num)
620 def verify_ipfix_addr_exhausted(self, data):
621 self.assertEqual(1, len(data))
624 self.assertEqual(scapy.compat.orb(record[230]), 3)
626 self.assertEqual(struct.pack("!I", 0), record[283])
628 def verify_ipfix_max_sessions(self, data, limit):
629 self.assertEqual(1, len(data))
632 self.assertEqual(scapy.compat.orb(record[230]), 13)
633 # natQuotaExceededEvent
634 self.assertEqual(struct.pack("I", 1), record[466])
636 self.assertEqual(struct.pack("I", limit), record[471])
638 def verify_no_nat44_user(self):
639 """ Verify that there is no NAT44EI user """
640 users = self.vapi.nat44_user_dump()
641 self.assertEqual(len(users), 0)
642 users = self.statistics.get_counter('/nat44/total-users')
643 self.assertEqual(users[0][0], 0)
644 sessions = self.statistics.get_counter('/nat44/total-sessions')
645 self.assertEqual(sessions[0][0], 0)
647 def verify_syslog_apmap(self, data, is_add=True):
648 message = data.decode('utf-8')
650 message = SyslogMessage.parse(message)
651 except ParseError as e:
655 self.assertEqual(message.severity, SyslogSeverity.info)
656 self.assertEqual(message.appname, 'NAT')
657 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
658 sd_params = message.sd.get('napmap')
659 self.assertTrue(sd_params is not None)
660 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
661 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
662 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
663 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
664 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
665 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
666 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
667 self.assertTrue(sd_params.get('SSUBIX') is not None)
668 self.assertEqual(sd_params.get('SVLAN'), '0')
670 def verify_mss_value(self, pkt, mss):
671 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
672 raise TypeError("Not a TCP/IP packet")
674 for option in pkt[TCP].options:
675 if option[0] == 'MSS':
676 self.assertEqual(option[1], mss)
677 self.assert_tcp_checksum_valid(pkt)
680 def proto2layer(proto):
681 if proto == IP_PROTOS.tcp:
683 elif proto == IP_PROTOS.udp:
685 elif proto == IP_PROTOS.icmp:
688 raise Exception("Unsupported protocol")
690 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
692 layer = self.proto2layer(proto)
694 if proto == IP_PROTOS.tcp:
695 data = b"A" * 4 + b"B" * 16 + b"C" * 3
697 data = b"A" * 16 + b"B" * 16 + b"C" * 3
698 self.port_in = random.randint(1025, 65535)
701 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
702 self.port_in, 20, data, proto)
703 self.pg0.add_stream(pkts)
704 self.pg_enable_capture(self.pg_interfaces)
706 frags = self.pg1.get_capture(len(pkts))
707 if not dont_translate:
708 p = self.reass_frags_and_verify(frags,
712 p = self.reass_frags_and_verify(frags,
715 if proto != IP_PROTOS.icmp:
716 if not dont_translate:
717 self.assertEqual(p[layer].dport, 20)
719 self.assertNotEqual(p[layer].sport, self.port_in)
721 self.assertEqual(p[layer].sport, self.port_in)
724 if not dont_translate:
725 self.assertNotEqual(p[layer].id, self.port_in)
727 self.assertEqual(p[layer].id, self.port_in)
728 self.assertEqual(data, p[Raw].load)
731 if not dont_translate:
732 dst_addr = self.nat_addr
734 dst_addr = self.pg0.remote_ip4
735 if proto != IP_PROTOS.icmp:
737 dport = p[layer].sport
741 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
742 proto, echo_reply=True)
743 self.pg1.add_stream(pkts)
744 self.pg_enable_capture(self.pg_interfaces)
746 frags = self.pg0.get_capture(len(pkts))
747 p = self.reass_frags_and_verify(frags,
750 if proto != IP_PROTOS.icmp:
751 self.assertEqual(p[layer].sport, 20)
752 self.assertEqual(p[layer].dport, self.port_in)
754 self.assertEqual(p[layer].id, self.port_in)
755 self.assertEqual(data, p[Raw].load)
757 def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
758 host_in_port, proto=IP_PROTOS.tcp,
761 layer = self.proto2layer(proto)
763 if proto == IP_PROTOS.tcp:
764 data = b"A" * 4 + b"B" * 16 + b"C" * 3
766 data = b"A" * 16 + b"B" * 16 + b"C" * 3
768 # send packet from host to server
769 pkts = self.create_stream_frag(self.pg0,
775 self.pg0.add_stream(pkts)
776 self.pg_enable_capture(self.pg_interfaces)
778 frags = self.pg0.get_capture(len(pkts))
779 p = self.reass_frags_and_verify(frags,
782 if proto != IP_PROTOS.icmp:
784 self.assertNotEqual(p[layer].sport, host_in_port)
785 self.assertEqual(p[layer].dport, server_in_port)
788 self.assertNotEqual(p[layer].id, host_in_port)
789 self.assertEqual(data, p[Raw].load)
791 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
793 layer = self.proto2layer(proto)
795 if proto == IP_PROTOS.tcp:
796 data = b"A" * 4 + b"B" * 16 + b"C" * 3
798 data = b"A" * 16 + b"B" * 16 + b"C" * 3
799 self.port_in = random.randint(1025, 65535)
803 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
804 self.port_in, 20, data, proto)
806 self.pg0.add_stream(pkts)
807 self.pg_enable_capture(self.pg_interfaces)
809 frags = self.pg1.get_capture(len(pkts))
810 if not dont_translate:
811 p = self.reass_frags_and_verify(frags,
815 p = self.reass_frags_and_verify(frags,
818 if proto != IP_PROTOS.icmp:
819 if not dont_translate:
820 self.assertEqual(p[layer].dport, 20)
822 self.assertNotEqual(p[layer].sport, self.port_in)
824 self.assertEqual(p[layer].sport, self.port_in)
827 if not dont_translate:
828 self.assertNotEqual(p[layer].id, self.port_in)
830 self.assertEqual(p[layer].id, self.port_in)
831 self.assertEqual(data, p[Raw].load)
834 if not dont_translate:
835 dst_addr = self.nat_addr
837 dst_addr = self.pg0.remote_ip4
838 if proto != IP_PROTOS.icmp:
840 dport = p[layer].sport
844 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
845 data, proto, echo_reply=True)
847 self.pg1.add_stream(pkts)
848 self.pg_enable_capture(self.pg_interfaces)
850 frags = self.pg0.get_capture(len(pkts))
851 p = self.reass_frags_and_verify(frags,
854 if proto != IP_PROTOS.icmp:
855 self.assertEqual(p[layer].sport, 20)
856 self.assertEqual(p[layer].dport, self.port_in)
858 self.assertEqual(p[layer].id, self.port_in)
859 self.assertEqual(data, p[Raw].load)
862 class TestNAT44EIAPI(MethodHolder):
863 """ NAT44EI API Test Cases """
868 super(TestNAT44EIAPI, self).setUp()
869 self.vapi.nat_set_fq_options(frame_queue_nelts=self.fq_nelts)
870 self.vapi.nat44_plugin_enable_disable(enable=1)
873 super(TestNAT44EIAPI, self).tearDown()
874 if not self.vpp_dead:
875 self.vapi.nat44_plugin_enable_disable(enable=0)
876 self.vapi.cli("clear logging")
878 def test_show_frame_queue_nelts(self):
879 """ API test - worker handoff frame queue elements """
880 nat_config = self.vapi.nat_show_fq_options()
881 self.assertEqual(self.fq_nelts, nat_config.frame_queue_nelts)
882 self.vapi.nat44_plugin_enable_disable(enable=0)
883 self.vapi.cli("set nat frame-queue-nelts 256")
884 self.vapi.nat44_plugin_enable_disable(enable=1)
885 nat_config = self.vapi.nat_show_fq_options()
886 self.assertEqual(256, nat_config.frame_queue_nelts)
889 @tag_fixme_vpp_workers
890 class TestNAT44EI(MethodHolder):
891 """ NAT44EI Test Cases """
893 max_translations = 10240
898 super(TestNAT44EI, cls).setUpClass()
899 cls.vapi.cli("set log class nat level debug")
901 cls.tcp_port_in = 6303
902 cls.tcp_port_out = 6303
903 cls.udp_port_in = 6304
904 cls.udp_port_out = 6304
905 cls.icmp_id_in = 6305
906 cls.icmp_id_out = 6305
907 cls.nat_addr = '10.0.0.3'
908 cls.ipfix_src_port = 4739
909 cls.ipfix_domain_id = 1
910 cls.tcp_external_port = 80
911 cls.udp_external_port = 69
913 cls.create_pg_interfaces(range(10))
914 cls.interfaces = list(cls.pg_interfaces[0:4])
916 for i in cls.interfaces:
921 cls.pg0.generate_remote_hosts(3)
922 cls.pg0.configure_ipv4_neighbors()
924 cls.pg1.generate_remote_hosts(1)
925 cls.pg1.configure_ipv4_neighbors()
927 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
928 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
929 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
931 cls.pg4._local_ip4 = "172.16.255.1"
932 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
933 cls.pg4.set_table_ip4(10)
934 cls.pg5._local_ip4 = "172.17.255.3"
935 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
936 cls.pg5.set_table_ip4(10)
937 cls.pg6._local_ip4 = "172.16.255.1"
938 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
939 cls.pg6.set_table_ip4(20)
940 for i in cls.overlapping_interfaces:
948 cls.pg9.generate_remote_hosts(2)
950 cls.vapi.sw_interface_add_del_address(
951 sw_if_index=cls.pg9.sw_if_index,
952 prefix="10.0.0.1/24")
955 cls.pg9.resolve_arp()
956 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
957 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
958 cls.pg9.resolve_arp()
961 super(TestNAT44EI, self).setUp()
962 self.vapi.nat44_plugin_enable_disable(
963 sessions=self.max_translations,
964 users=self.max_users, enable=1)
967 super(TestNAT44EI, self).tearDown()
968 if not self.vpp_dead:
969 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
970 src_port=self.ipfix_src_port,
972 self.ipfix_src_port = 4739
973 self.ipfix_domain_id = 1
975 self.vapi.nat44_plugin_enable_disable(enable=0)
976 self.vapi.cli("clear logging")
978 def test_clear_sessions(self):
979 """ NAT44EI session clearing test """
981 self.nat44_add_address(self.nat_addr)
982 flags = self.config_flags.NAT_IS_INSIDE
983 self.vapi.nat44_interface_add_del_feature(
984 sw_if_index=self.pg0.sw_if_index,
985 flags=flags, is_add=1)
986 self.vapi.nat44_interface_add_del_feature(
987 sw_if_index=self.pg1.sw_if_index,
990 nat_config = self.vapi.nat_show_config()
991 self.assertEqual(0, nat_config.endpoint_dependent)
993 pkts = self.create_stream_in(self.pg0, self.pg1)
994 self.pg0.add_stream(pkts)
995 self.pg_enable_capture(self.pg_interfaces)
997 capture = self.pg1.get_capture(len(pkts))
998 self.verify_capture_out(capture)
1000 sessions = self.statistics.get_counter('/nat44/total-sessions')
1001 self.assertTrue(sessions[0][0] > 0)
1002 self.logger.info("sessions before clearing: %s" % sessions[0][0])
1004 self.vapi.cli("clear nat44 sessions")
1006 sessions = self.statistics.get_counter('/nat44/total-sessions')
1007 self.assertEqual(sessions[0][0], 0)
1008 self.logger.info("sessions after clearing: %s" % sessions[0][0])
1010 def test_dynamic(self):
1011 """ NAT44EI dynamic translation test """
1012 self.nat44_add_address(self.nat_addr)
1013 flags = self.config_flags.NAT_IS_INSIDE
1014 self.vapi.nat44_interface_add_del_feature(
1015 sw_if_index=self.pg0.sw_if_index,
1016 flags=flags, is_add=1)
1017 self.vapi.nat44_interface_add_del_feature(
1018 sw_if_index=self.pg1.sw_if_index,
1022 tcpn = self.statistics.get_counter('/nat44/in2out/slowpath/tcp')[0]
1023 udpn = self.statistics.get_counter('/nat44/in2out/slowpath/udp')[0]
1024 icmpn = self.statistics.get_counter('/nat44/in2out/slowpath/icmp')[0]
1025 drops = self.statistics.get_counter('/nat44/in2out/slowpath/drops')[0]
1027 pkts = self.create_stream_in(self.pg0, self.pg1)
1028 self.pg0.add_stream(pkts)
1029 self.pg_enable_capture(self.pg_interfaces)
1031 capture = self.pg1.get_capture(len(pkts))
1032 self.verify_capture_out(capture)
1034 if_idx = self.pg0.sw_if_index
1035 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/tcp')[0]
1036 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1037 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/udp')[0]
1038 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1039 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/icmp')[0]
1040 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1041 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/drops')[0]
1042 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1045 tcpn = self.statistics.get_counter('/nat44/out2in/slowpath/tcp')[0]
1046 udpn = self.statistics.get_counter('/nat44/out2in/slowpath/udp')[0]
1047 icmpn = self.statistics.get_counter('/nat44/out2in/slowpath/icmp')[0]
1048 drops = self.statistics.get_counter('/nat44/out2in/slowpath/drops')[0]
1050 pkts = self.create_stream_out(self.pg1)
1051 self.pg1.add_stream(pkts)
1052 self.pg_enable_capture(self.pg_interfaces)
1054 capture = self.pg0.get_capture(len(pkts))
1055 self.verify_capture_in(capture, self.pg0)
1057 if_idx = self.pg1.sw_if_index
1058 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/tcp')[0]
1059 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1060 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/udp')[0]
1061 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1062 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/icmp')[0]
1063 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1064 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/drops')[0]
1065 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1067 users = self.statistics.get_counter('/nat44/total-users')
1068 self.assertEqual(users[0][0], 1)
1069 sessions = self.statistics.get_counter('/nat44/total-sessions')
1070 self.assertEqual(sessions[0][0], 3)
1072 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1073 """ NAT44EI handling of client packets with TTL=1 """
1075 self.nat44_add_address(self.nat_addr)
1076 flags = self.config_flags.NAT_IS_INSIDE
1077 self.vapi.nat44_interface_add_del_feature(
1078 sw_if_index=self.pg0.sw_if_index,
1079 flags=flags, is_add=1)
1080 self.vapi.nat44_interface_add_del_feature(
1081 sw_if_index=self.pg1.sw_if_index,
1084 # Client side - generate traffic
1085 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1086 self.pg0.add_stream(pkts)
1087 self.pg_enable_capture(self.pg_interfaces)
1090 # Client side - verify ICMP type 11 packets
1091 capture = self.pg0.get_capture(len(pkts))
1092 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1094 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1095 """ NAT44EI handling of server packets with TTL=1 """
1097 self.nat44_add_address(self.nat_addr)
1098 flags = self.config_flags.NAT_IS_INSIDE
1099 self.vapi.nat44_interface_add_del_feature(
1100 sw_if_index=self.pg0.sw_if_index,
1101 flags=flags, is_add=1)
1102 self.vapi.nat44_interface_add_del_feature(
1103 sw_if_index=self.pg1.sw_if_index,
1106 # Client side - create sessions
1107 pkts = self.create_stream_in(self.pg0, self.pg1)
1108 self.pg0.add_stream(pkts)
1109 self.pg_enable_capture(self.pg_interfaces)
1112 # Server side - generate traffic
1113 capture = self.pg1.get_capture(len(pkts))
1114 self.verify_capture_out(capture)
1115 pkts = self.create_stream_out(self.pg1, ttl=1)
1116 self.pg1.add_stream(pkts)
1117 self.pg_enable_capture(self.pg_interfaces)
1120 # Server side - verify ICMP type 11 packets
1121 capture = self.pg1.get_capture(len(pkts))
1122 self.verify_capture_out_with_icmp_errors(capture,
1123 src_ip=self.pg1.local_ip4)
1125 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1126 """ NAT44EI handling of error responses to client packets with TTL=2
1129 self.nat44_add_address(self.nat_addr)
1130 flags = self.config_flags.NAT_IS_INSIDE
1131 self.vapi.nat44_interface_add_del_feature(
1132 sw_if_index=self.pg0.sw_if_index,
1133 flags=flags, is_add=1)
1134 self.vapi.nat44_interface_add_del_feature(
1135 sw_if_index=self.pg1.sw_if_index,
1138 # Client side - generate traffic
1139 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1140 self.pg0.add_stream(pkts)
1141 self.pg_enable_capture(self.pg_interfaces)
1144 # Server side - simulate ICMP type 11 response
1145 capture = self.pg1.get_capture(len(pkts))
1146 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1147 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1148 ICMP(type=11) / packet[IP] for packet in capture]
1149 self.pg1.add_stream(pkts)
1150 self.pg_enable_capture(self.pg_interfaces)
1153 # Client side - verify ICMP type 11 packets
1154 capture = self.pg0.get_capture(len(pkts))
1155 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1157 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1158 """ NAT44EI handling of error responses to server packets with TTL=2
1161 self.nat44_add_address(self.nat_addr)
1162 flags = self.config_flags.NAT_IS_INSIDE
1163 self.vapi.nat44_interface_add_del_feature(
1164 sw_if_index=self.pg0.sw_if_index,
1165 flags=flags, is_add=1)
1166 self.vapi.nat44_interface_add_del_feature(
1167 sw_if_index=self.pg1.sw_if_index,
1170 # Client side - create sessions
1171 pkts = self.create_stream_in(self.pg0, self.pg1)
1172 self.pg0.add_stream(pkts)
1173 self.pg_enable_capture(self.pg_interfaces)
1176 # Server side - generate traffic
1177 capture = self.pg1.get_capture(len(pkts))
1178 self.verify_capture_out(capture)
1179 pkts = self.create_stream_out(self.pg1, ttl=2)
1180 self.pg1.add_stream(pkts)
1181 self.pg_enable_capture(self.pg_interfaces)
1184 # Client side - simulate ICMP type 11 response
1185 capture = self.pg0.get_capture(len(pkts))
1186 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1187 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1188 ICMP(type=11) / packet[IP] for packet in capture]
1189 self.pg0.add_stream(pkts)
1190 self.pg_enable_capture(self.pg_interfaces)
1193 # Server side - verify ICMP type 11 packets
1194 capture = self.pg1.get_capture(len(pkts))
1195 self.verify_capture_out_with_icmp_errors(capture)
1197 def test_ping_out_interface_from_outside(self):
1198 """ NAT44EI ping out interface from outside network """
1200 self.nat44_add_address(self.nat_addr)
1201 flags = self.config_flags.NAT_IS_INSIDE
1202 self.vapi.nat44_interface_add_del_feature(
1203 sw_if_index=self.pg0.sw_if_index,
1204 flags=flags, is_add=1)
1205 self.vapi.nat44_interface_add_del_feature(
1206 sw_if_index=self.pg1.sw_if_index,
1209 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1210 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1211 ICMP(id=self.icmp_id_out, type='echo-request'))
1213 self.pg1.add_stream(pkts)
1214 self.pg_enable_capture(self.pg_interfaces)
1216 capture = self.pg1.get_capture(len(pkts))
1219 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1220 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1221 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1222 self.assertEqual(packet[ICMP].type, 0) # echo reply
1224 self.logger.error(ppp("Unexpected or invalid packet "
1225 "(outside network):", packet))
1228 def test_ping_internal_host_from_outside(self):
1229 """ NAT44EI ping internal host from outside network """
1231 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1232 flags = self.config_flags.NAT_IS_INSIDE
1233 self.vapi.nat44_interface_add_del_feature(
1234 sw_if_index=self.pg0.sw_if_index,
1235 flags=flags, is_add=1)
1236 self.vapi.nat44_interface_add_del_feature(
1237 sw_if_index=self.pg1.sw_if_index,
1241 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1242 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1243 ICMP(id=self.icmp_id_out, type='echo-request'))
1244 self.pg1.add_stream(pkt)
1245 self.pg_enable_capture(self.pg_interfaces)
1247 capture = self.pg0.get_capture(1)
1248 self.verify_capture_in(capture, self.pg0)
1249 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1252 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1253 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1254 ICMP(id=self.icmp_id_in, type='echo-reply'))
1255 self.pg0.add_stream(pkt)
1256 self.pg_enable_capture(self.pg_interfaces)
1258 capture = self.pg1.get_capture(1)
1259 self.verify_capture_out(capture, same_port=True)
1260 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1262 def test_forwarding(self):
1263 """ NAT44EI forwarding test """
1265 flags = self.config_flags.NAT_IS_INSIDE
1266 self.vapi.nat44_interface_add_del_feature(
1267 sw_if_index=self.pg0.sw_if_index,
1268 flags=flags, is_add=1)
1269 self.vapi.nat44_interface_add_del_feature(
1270 sw_if_index=self.pg1.sw_if_index,
1272 self.vapi.nat44_forwarding_enable_disable(enable=1)
1274 real_ip = self.pg0.remote_ip4
1275 alias_ip = self.nat_addr
1276 flags = self.config_flags.NAT_IS_ADDR_ONLY
1277 self.vapi.nat44_add_del_static_mapping(is_add=1,
1278 local_ip_address=real_ip,
1279 external_ip_address=alias_ip,
1280 external_sw_if_index=0xFFFFFFFF,
1284 # static mapping match
1286 pkts = self.create_stream_out(self.pg1)
1287 self.pg1.add_stream(pkts)
1288 self.pg_enable_capture(self.pg_interfaces)
1290 capture = self.pg0.get_capture(len(pkts))
1291 self.verify_capture_in(capture, self.pg0)
1293 pkts = self.create_stream_in(self.pg0, self.pg1)
1294 self.pg0.add_stream(pkts)
1295 self.pg_enable_capture(self.pg_interfaces)
1297 capture = self.pg1.get_capture(len(pkts))
1298 self.verify_capture_out(capture, same_port=True)
1300 # no static mapping match
1302 host0 = self.pg0.remote_hosts[0]
1303 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1305 pkts = self.create_stream_out(self.pg1,
1306 dst_ip=self.pg0.remote_ip4,
1307 use_inside_ports=True)
1308 self.pg1.add_stream(pkts)
1309 self.pg_enable_capture(self.pg_interfaces)
1311 capture = self.pg0.get_capture(len(pkts))
1312 self.verify_capture_in(capture, self.pg0)
1314 pkts = self.create_stream_in(self.pg0, self.pg1)
1315 self.pg0.add_stream(pkts)
1316 self.pg_enable_capture(self.pg_interfaces)
1318 capture = self.pg1.get_capture(len(pkts))
1319 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1322 self.pg0.remote_hosts[0] = host0
1325 self.vapi.nat44_forwarding_enable_disable(enable=0)
1326 flags = self.config_flags.NAT_IS_ADDR_ONLY
1327 self.vapi.nat44_add_del_static_mapping(
1329 local_ip_address=real_ip,
1330 external_ip_address=alias_ip,
1331 external_sw_if_index=0xFFFFFFFF,
1334 def test_static_in(self):
1335 """ NAT44EI 1:1 NAT initialized from inside network """
1337 nat_ip = "10.0.0.10"
1338 self.tcp_port_out = 6303
1339 self.udp_port_out = 6304
1340 self.icmp_id_out = 6305
1342 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1343 flags = self.config_flags.NAT_IS_INSIDE
1344 self.vapi.nat44_interface_add_del_feature(
1345 sw_if_index=self.pg0.sw_if_index,
1346 flags=flags, is_add=1)
1347 self.vapi.nat44_interface_add_del_feature(
1348 sw_if_index=self.pg1.sw_if_index,
1350 sm = self.vapi.nat44_static_mapping_dump()
1351 self.assertEqual(len(sm), 1)
1352 self.assertEqual(sm[0].tag, '')
1353 self.assertEqual(sm[0].protocol, 0)
1354 self.assertEqual(sm[0].local_port, 0)
1355 self.assertEqual(sm[0].external_port, 0)
1358 pkts = self.create_stream_in(self.pg0, self.pg1)
1359 self.pg0.add_stream(pkts)
1360 self.pg_enable_capture(self.pg_interfaces)
1362 capture = self.pg1.get_capture(len(pkts))
1363 self.verify_capture_out(capture, nat_ip, True)
1366 pkts = self.create_stream_out(self.pg1, nat_ip)
1367 self.pg1.add_stream(pkts)
1368 self.pg_enable_capture(self.pg_interfaces)
1370 capture = self.pg0.get_capture(len(pkts))
1371 self.verify_capture_in(capture, self.pg0)
1373 def test_static_out(self):
1374 """ NAT44EI 1:1 NAT initialized from outside network """
1376 nat_ip = "10.0.0.20"
1377 self.tcp_port_out = 6303
1378 self.udp_port_out = 6304
1379 self.icmp_id_out = 6305
1382 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1383 flags = self.config_flags.NAT_IS_INSIDE
1384 self.vapi.nat44_interface_add_del_feature(
1385 sw_if_index=self.pg0.sw_if_index,
1386 flags=flags, is_add=1)
1387 self.vapi.nat44_interface_add_del_feature(
1388 sw_if_index=self.pg1.sw_if_index,
1390 sm = self.vapi.nat44_static_mapping_dump()
1391 self.assertEqual(len(sm), 1)
1392 self.assertEqual(sm[0].tag, tag)
1395 pkts = self.create_stream_out(self.pg1, nat_ip)
1396 self.pg1.add_stream(pkts)
1397 self.pg_enable_capture(self.pg_interfaces)
1399 capture = self.pg0.get_capture(len(pkts))
1400 self.verify_capture_in(capture, self.pg0)
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, nat_ip, True)
1410 def test_static_with_port_in(self):
1411 """ NAT44EI 1:1 NAPT initialized from inside network """
1413 self.tcp_port_out = 3606
1414 self.udp_port_out = 3607
1415 self.icmp_id_out = 3608
1417 self.nat44_add_address(self.nat_addr)
1418 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1419 self.tcp_port_in, self.tcp_port_out,
1420 proto=IP_PROTOS.tcp)
1421 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1422 self.udp_port_in, self.udp_port_out,
1423 proto=IP_PROTOS.udp)
1424 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1425 self.icmp_id_in, self.icmp_id_out,
1426 proto=IP_PROTOS.icmp)
1427 flags = self.config_flags.NAT_IS_INSIDE
1428 self.vapi.nat44_interface_add_del_feature(
1429 sw_if_index=self.pg0.sw_if_index,
1430 flags=flags, is_add=1)
1431 self.vapi.nat44_interface_add_del_feature(
1432 sw_if_index=self.pg1.sw_if_index,
1436 pkts = self.create_stream_in(self.pg0, self.pg1)
1437 self.pg0.add_stream(pkts)
1438 self.pg_enable_capture(self.pg_interfaces)
1440 capture = self.pg1.get_capture(len(pkts))
1441 self.verify_capture_out(capture)
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)
1451 def test_static_with_port_out(self):
1452 """ NAT44EI 1:1 NAPT initialized from outside network """
1454 self.tcp_port_out = 30606
1455 self.udp_port_out = 30607
1456 self.icmp_id_out = 30608
1458 self.nat44_add_address(self.nat_addr)
1459 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1460 self.tcp_port_in, self.tcp_port_out,
1461 proto=IP_PROTOS.tcp)
1462 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1463 self.udp_port_in, self.udp_port_out,
1464 proto=IP_PROTOS.udp)
1465 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1466 self.icmp_id_in, self.icmp_id_out,
1467 proto=IP_PROTOS.icmp)
1468 flags = self.config_flags.NAT_IS_INSIDE
1469 self.vapi.nat44_interface_add_del_feature(
1470 sw_if_index=self.pg0.sw_if_index,
1471 flags=flags, is_add=1)
1472 self.vapi.nat44_interface_add_del_feature(
1473 sw_if_index=self.pg1.sw_if_index,
1477 pkts = self.create_stream_out(self.pg1)
1478 self.pg1.add_stream(pkts)
1479 self.pg_enable_capture(self.pg_interfaces)
1481 capture = self.pg0.get_capture(len(pkts))
1482 self.verify_capture_in(capture, self.pg0)
1485 pkts = self.create_stream_in(self.pg0, self.pg1)
1486 self.pg0.add_stream(pkts)
1487 self.pg_enable_capture(self.pg_interfaces)
1489 capture = self.pg1.get_capture(len(pkts))
1490 self.verify_capture_out(capture)
1492 def test_static_vrf_aware(self):
1493 """ NAT44EI 1:1 NAT VRF awareness """
1495 nat_ip1 = "10.0.0.30"
1496 nat_ip2 = "10.0.0.40"
1497 self.tcp_port_out = 6303
1498 self.udp_port_out = 6304
1499 self.icmp_id_out = 6305
1501 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1503 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1505 flags = self.config_flags.NAT_IS_INSIDE
1506 self.vapi.nat44_interface_add_del_feature(
1507 sw_if_index=self.pg3.sw_if_index,
1509 self.vapi.nat44_interface_add_del_feature(
1510 sw_if_index=self.pg0.sw_if_index,
1511 flags=flags, is_add=1)
1512 self.vapi.nat44_interface_add_del_feature(
1513 sw_if_index=self.pg4.sw_if_index,
1514 flags=flags, is_add=1)
1516 # inside interface VRF match NAT44EI static mapping VRF
1517 pkts = self.create_stream_in(self.pg4, self.pg3)
1518 self.pg4.add_stream(pkts)
1519 self.pg_enable_capture(self.pg_interfaces)
1521 capture = self.pg3.get_capture(len(pkts))
1522 self.verify_capture_out(capture, nat_ip1, True)
1524 # inside interface VRF don't match NAT44EI static mapping VRF (packets
1526 pkts = self.create_stream_in(self.pg0, self.pg3)
1527 self.pg0.add_stream(pkts)
1528 self.pg_enable_capture(self.pg_interfaces)
1530 self.pg3.assert_nothing_captured()
1532 def test_dynamic_to_static(self):
1533 """ NAT44EI Switch from dynamic translation to 1:1NAT """
1534 nat_ip = "10.0.0.10"
1535 self.tcp_port_out = 6303
1536 self.udp_port_out = 6304
1537 self.icmp_id_out = 6305
1539 self.nat44_add_address(self.nat_addr)
1540 flags = self.config_flags.NAT_IS_INSIDE
1541 self.vapi.nat44_interface_add_del_feature(
1542 sw_if_index=self.pg0.sw_if_index,
1543 flags=flags, is_add=1)
1544 self.vapi.nat44_interface_add_del_feature(
1545 sw_if_index=self.pg1.sw_if_index,
1549 pkts = self.create_stream_in(self.pg0, self.pg1)
1550 self.pg0.add_stream(pkts)
1551 self.pg_enable_capture(self.pg_interfaces)
1553 capture = self.pg1.get_capture(len(pkts))
1554 self.verify_capture_out(capture)
1557 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1558 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
1559 self.assertEqual(len(sessions), 0)
1560 pkts = self.create_stream_in(self.pg0, self.pg1)
1561 self.pg0.add_stream(pkts)
1562 self.pg_enable_capture(self.pg_interfaces)
1564 capture = self.pg1.get_capture(len(pkts))
1565 self.verify_capture_out(capture, nat_ip, True)
1567 def test_identity_nat(self):
1568 """ NAT44EI Identity NAT """
1569 flags = self.config_flags.NAT_IS_ADDR_ONLY
1570 self.vapi.nat44_add_del_identity_mapping(
1571 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1572 flags=flags, is_add=1)
1573 flags = self.config_flags.NAT_IS_INSIDE
1574 self.vapi.nat44_interface_add_del_feature(
1575 sw_if_index=self.pg0.sw_if_index,
1576 flags=flags, is_add=1)
1577 self.vapi.nat44_interface_add_del_feature(
1578 sw_if_index=self.pg1.sw_if_index,
1581 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1582 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1583 TCP(sport=12345, dport=56789))
1584 self.pg1.add_stream(p)
1585 self.pg_enable_capture(self.pg_interfaces)
1587 capture = self.pg0.get_capture(1)
1592 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1593 self.assertEqual(ip.src, self.pg1.remote_ip4)
1594 self.assertEqual(tcp.dport, 56789)
1595 self.assertEqual(tcp.sport, 12345)
1596 self.assert_packet_checksums_valid(p)
1598 self.logger.error(ppp("Unexpected or invalid packet:", p))
1601 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
1602 self.assertEqual(len(sessions), 0)
1603 flags = self.config_flags.NAT_IS_ADDR_ONLY
1604 self.vapi.nat44_add_del_identity_mapping(
1605 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1606 flags=flags, vrf_id=1, is_add=1)
1607 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1608 self.assertEqual(len(identity_mappings), 2)
1610 def test_multiple_inside_interfaces(self):
1611 """ NAT44EI multiple non-overlapping address space inside interfaces
1614 self.nat44_add_address(self.nat_addr)
1615 flags = self.config_flags.NAT_IS_INSIDE
1616 self.vapi.nat44_interface_add_del_feature(
1617 sw_if_index=self.pg0.sw_if_index,
1618 flags=flags, is_add=1)
1619 self.vapi.nat44_interface_add_del_feature(
1620 sw_if_index=self.pg1.sw_if_index,
1621 flags=flags, is_add=1)
1622 self.vapi.nat44_interface_add_del_feature(
1623 sw_if_index=self.pg3.sw_if_index,
1626 # between two NAT44EI inside interfaces (no translation)
1627 pkts = self.create_stream_in(self.pg0, self.pg1)
1628 self.pg0.add_stream(pkts)
1629 self.pg_enable_capture(self.pg_interfaces)
1631 capture = self.pg1.get_capture(len(pkts))
1632 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1634 # from inside to interface without translation
1635 pkts = self.create_stream_in(self.pg0, self.pg2)
1636 self.pg0.add_stream(pkts)
1637 self.pg_enable_capture(self.pg_interfaces)
1639 capture = self.pg2.get_capture(len(pkts))
1640 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1642 # in2out 1st interface
1643 pkts = self.create_stream_in(self.pg0, self.pg3)
1644 self.pg0.add_stream(pkts)
1645 self.pg_enable_capture(self.pg_interfaces)
1647 capture = self.pg3.get_capture(len(pkts))
1648 self.verify_capture_out(capture)
1650 # out2in 1st interface
1651 pkts = self.create_stream_out(self.pg3)
1652 self.pg3.add_stream(pkts)
1653 self.pg_enable_capture(self.pg_interfaces)
1655 capture = self.pg0.get_capture(len(pkts))
1656 self.verify_capture_in(capture, self.pg0)
1658 # in2out 2nd interface
1659 pkts = self.create_stream_in(self.pg1, self.pg3)
1660 self.pg1.add_stream(pkts)
1661 self.pg_enable_capture(self.pg_interfaces)
1663 capture = self.pg3.get_capture(len(pkts))
1664 self.verify_capture_out(capture)
1666 # out2in 2nd interface
1667 pkts = self.create_stream_out(self.pg3)
1668 self.pg3.add_stream(pkts)
1669 self.pg_enable_capture(self.pg_interfaces)
1671 capture = self.pg1.get_capture(len(pkts))
1672 self.verify_capture_in(capture, self.pg1)
1674 def test_inside_overlapping_interfaces(self):
1675 """ NAT44EI multiple inside interfaces with overlapping address space
1678 static_nat_ip = "10.0.0.10"
1679 self.nat44_add_address(self.nat_addr)
1680 flags = self.config_flags.NAT_IS_INSIDE
1681 self.vapi.nat44_interface_add_del_feature(
1682 sw_if_index=self.pg3.sw_if_index,
1684 self.vapi.nat44_interface_add_del_feature(
1685 sw_if_index=self.pg4.sw_if_index,
1686 flags=flags, is_add=1)
1687 self.vapi.nat44_interface_add_del_feature(
1688 sw_if_index=self.pg5.sw_if_index,
1689 flags=flags, is_add=1)
1690 self.vapi.nat44_interface_add_del_feature(
1691 sw_if_index=self.pg6.sw_if_index,
1692 flags=flags, is_add=1)
1693 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1696 # between NAT44EI inside interfaces with same VRF (no translation)
1697 pkts = self.create_stream_in(self.pg4, self.pg5)
1698 self.pg4.add_stream(pkts)
1699 self.pg_enable_capture(self.pg_interfaces)
1701 capture = self.pg5.get_capture(len(pkts))
1702 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1704 # between NAT44EI inside interfaces with different VRF (hairpinning)
1705 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1706 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1707 TCP(sport=1234, dport=5678))
1708 self.pg4.add_stream(p)
1709 self.pg_enable_capture(self.pg_interfaces)
1711 capture = self.pg6.get_capture(1)
1716 self.assertEqual(ip.src, self.nat_addr)
1717 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1718 self.assertNotEqual(tcp.sport, 1234)
1719 self.assertEqual(tcp.dport, 5678)
1721 self.logger.error(ppp("Unexpected or invalid packet:", p))
1724 # in2out 1st interface
1725 pkts = self.create_stream_in(self.pg4, self.pg3)
1726 self.pg4.add_stream(pkts)
1727 self.pg_enable_capture(self.pg_interfaces)
1729 capture = self.pg3.get_capture(len(pkts))
1730 self.verify_capture_out(capture)
1732 # out2in 1st interface
1733 pkts = self.create_stream_out(self.pg3)
1734 self.pg3.add_stream(pkts)
1735 self.pg_enable_capture(self.pg_interfaces)
1737 capture = self.pg4.get_capture(len(pkts))
1738 self.verify_capture_in(capture, self.pg4)
1740 # in2out 2nd interface
1741 pkts = self.create_stream_in(self.pg5, self.pg3)
1742 self.pg5.add_stream(pkts)
1743 self.pg_enable_capture(self.pg_interfaces)
1745 capture = self.pg3.get_capture(len(pkts))
1746 self.verify_capture_out(capture)
1748 # out2in 2nd interface
1749 pkts = self.create_stream_out(self.pg3)
1750 self.pg3.add_stream(pkts)
1751 self.pg_enable_capture(self.pg_interfaces)
1753 capture = self.pg5.get_capture(len(pkts))
1754 self.verify_capture_in(capture, self.pg5)
1757 addresses = self.vapi.nat44_address_dump()
1758 self.assertEqual(len(addresses), 1)
1759 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
1760 self.assertEqual(len(sessions), 3)
1761 for session in sessions:
1762 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
1763 self.assertEqual(str(session.inside_ip_address),
1764 self.pg5.remote_ip4)
1765 self.assertEqual(session.outside_ip_address,
1766 addresses[0].ip_address)
1767 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1768 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1769 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1770 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1771 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1772 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1773 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1774 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1775 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1777 # in2out 3rd interface
1778 pkts = self.create_stream_in(self.pg6, self.pg3)
1779 self.pg6.add_stream(pkts)
1780 self.pg_enable_capture(self.pg_interfaces)
1782 capture = self.pg3.get_capture(len(pkts))
1783 self.verify_capture_out(capture, static_nat_ip, True)
1785 # out2in 3rd interface
1786 pkts = self.create_stream_out(self.pg3, static_nat_ip)
1787 self.pg3.add_stream(pkts)
1788 self.pg_enable_capture(self.pg_interfaces)
1790 capture = self.pg6.get_capture(len(pkts))
1791 self.verify_capture_in(capture, self.pg6)
1793 # general user and session dump verifications
1794 users = self.vapi.nat44_user_dump()
1795 self.assertGreaterEqual(len(users), 3)
1796 addresses = self.vapi.nat44_address_dump()
1797 self.assertEqual(len(addresses), 1)
1799 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
1801 for session in sessions:
1802 self.assertEqual(user.ip_address, session.inside_ip_address)
1803 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1804 self.assertTrue(session.protocol in
1805 [IP_PROTOS.tcp, IP_PROTOS.udp,
1807 self.assertFalse(session.flags &
1808 self.config_flags.NAT_IS_EXT_HOST_VALID)
1811 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
1812 self.assertGreaterEqual(len(sessions), 4)
1813 for session in sessions:
1814 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
1815 self.assertEqual(str(session.inside_ip_address),
1816 self.pg4.remote_ip4)
1817 self.assertEqual(session.outside_ip_address,
1818 addresses[0].ip_address)
1821 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
1822 self.assertGreaterEqual(len(sessions), 3)
1823 for session in sessions:
1824 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
1825 self.assertEqual(str(session.inside_ip_address),
1826 self.pg6.remote_ip4)
1827 self.assertEqual(str(session.outside_ip_address),
1829 self.assertTrue(session.inside_port in
1830 [self.tcp_port_in, self.udp_port_in,
1833 def test_hairpinning(self):
1834 """ NAT44EI hairpinning - 1:1 NAPT """
1836 host = self.pg0.remote_hosts[0]
1837 server = self.pg0.remote_hosts[1]
1840 server_in_port = 5678
1841 server_out_port = 8765
1843 self.nat44_add_address(self.nat_addr)
1844 flags = self.config_flags.NAT_IS_INSIDE
1845 self.vapi.nat44_interface_add_del_feature(
1846 sw_if_index=self.pg0.sw_if_index,
1847 flags=flags, is_add=1)
1848 self.vapi.nat44_interface_add_del_feature(
1849 sw_if_index=self.pg1.sw_if_index,
1852 # add static mapping for server
1853 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1854 server_in_port, server_out_port,
1855 proto=IP_PROTOS.tcp)
1857 cnt = self.statistics.get_counter('/nat44/hairpinning')[0]
1858 # send packet from host to server
1859 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
1860 IP(src=host.ip4, dst=self.nat_addr) /
1861 TCP(sport=host_in_port, dport=server_out_port))
1862 self.pg0.add_stream(p)
1863 self.pg_enable_capture(self.pg_interfaces)
1865 capture = self.pg0.get_capture(1)
1870 self.assertEqual(ip.src, self.nat_addr)
1871 self.assertEqual(ip.dst, server.ip4)
1872 self.assertNotEqual(tcp.sport, host_in_port)
1873 self.assertEqual(tcp.dport, server_in_port)
1874 self.assert_packet_checksums_valid(p)
1875 host_out_port = tcp.sport
1877 self.logger.error(ppp("Unexpected or invalid packet:", p))
1880 after = self.statistics.get_counter('/nat44/hairpinning')[0]
1881 if_idx = self.pg0.sw_if_index
1882 self.assertEqual(after[if_idx] - cnt[if_idx], 1)
1884 # send reply from server to host
1885 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1886 IP(src=server.ip4, dst=self.nat_addr) /
1887 TCP(sport=server_in_port, dport=host_out_port))
1888 self.pg0.add_stream(p)
1889 self.pg_enable_capture(self.pg_interfaces)
1891 capture = self.pg0.get_capture(1)
1896 self.assertEqual(ip.src, self.nat_addr)
1897 self.assertEqual(ip.dst, host.ip4)
1898 self.assertEqual(tcp.sport, server_out_port)
1899 self.assertEqual(tcp.dport, host_in_port)
1900 self.assert_packet_checksums_valid(p)
1902 self.logger.error(ppp("Unexpected or invalid packet:", p))
1905 after = self.statistics.get_counter('/nat44/hairpinning')[0]
1906 if_idx = self.pg0.sw_if_index
1907 self.assertEqual(after[if_idx] - cnt[if_idx], 2)
1909 def test_hairpinning2(self):
1910 """ NAT44EI hairpinning - 1:1 NAT"""
1912 server1_nat_ip = "10.0.0.10"
1913 server2_nat_ip = "10.0.0.11"
1914 host = self.pg0.remote_hosts[0]
1915 server1 = self.pg0.remote_hosts[1]
1916 server2 = self.pg0.remote_hosts[2]
1917 server_tcp_port = 22
1918 server_udp_port = 20
1920 self.nat44_add_address(self.nat_addr)
1921 flags = self.config_flags.NAT_IS_INSIDE
1922 self.vapi.nat44_interface_add_del_feature(
1923 sw_if_index=self.pg0.sw_if_index,
1924 flags=flags, is_add=1)
1925 self.vapi.nat44_interface_add_del_feature(
1926 sw_if_index=self.pg1.sw_if_index,
1929 # add static mapping for servers
1930 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1931 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
1935 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1936 IP(src=host.ip4, dst=server1_nat_ip) /
1937 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1939 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1940 IP(src=host.ip4, dst=server1_nat_ip) /
1941 UDP(sport=self.udp_port_in, dport=server_udp_port))
1943 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1944 IP(src=host.ip4, dst=server1_nat_ip) /
1945 ICMP(id=self.icmp_id_in, type='echo-request'))
1947 self.pg0.add_stream(pkts)
1948 self.pg_enable_capture(self.pg_interfaces)
1950 capture = self.pg0.get_capture(len(pkts))
1951 for packet in capture:
1953 self.assertEqual(packet[IP].src, self.nat_addr)
1954 self.assertEqual(packet[IP].dst, server1.ip4)
1955 if packet.haslayer(TCP):
1956 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1957 self.assertEqual(packet[TCP].dport, server_tcp_port)
1958 self.tcp_port_out = packet[TCP].sport
1959 self.assert_packet_checksums_valid(packet)
1960 elif packet.haslayer(UDP):
1961 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1962 self.assertEqual(packet[UDP].dport, server_udp_port)
1963 self.udp_port_out = packet[UDP].sport
1965 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1966 self.icmp_id_out = packet[ICMP].id
1968 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1973 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1974 IP(src=server1.ip4, dst=self.nat_addr) /
1975 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1977 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1978 IP(src=server1.ip4, dst=self.nat_addr) /
1979 UDP(sport=server_udp_port, dport=self.udp_port_out))
1981 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1982 IP(src=server1.ip4, dst=self.nat_addr) /
1983 ICMP(id=self.icmp_id_out, type='echo-reply'))
1985 self.pg0.add_stream(pkts)
1986 self.pg_enable_capture(self.pg_interfaces)
1988 capture = self.pg0.get_capture(len(pkts))
1989 for packet in capture:
1991 self.assertEqual(packet[IP].src, server1_nat_ip)
1992 self.assertEqual(packet[IP].dst, host.ip4)
1993 if packet.haslayer(TCP):
1994 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1995 self.assertEqual(packet[TCP].sport, server_tcp_port)
1996 self.assert_packet_checksums_valid(packet)
1997 elif packet.haslayer(UDP):
1998 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1999 self.assertEqual(packet[UDP].sport, server_udp_port)
2001 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2003 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2006 # server2 to server1
2008 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2009 IP(src=server2.ip4, dst=server1_nat_ip) /
2010 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2012 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2013 IP(src=server2.ip4, dst=server1_nat_ip) /
2014 UDP(sport=self.udp_port_in, dport=server_udp_port))
2016 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2017 IP(src=server2.ip4, dst=server1_nat_ip) /
2018 ICMP(id=self.icmp_id_in, type='echo-request'))
2020 self.pg0.add_stream(pkts)
2021 self.pg_enable_capture(self.pg_interfaces)
2023 capture = self.pg0.get_capture(len(pkts))
2024 for packet in capture:
2026 self.assertEqual(packet[IP].src, server2_nat_ip)
2027 self.assertEqual(packet[IP].dst, server1.ip4)
2028 if packet.haslayer(TCP):
2029 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2030 self.assertEqual(packet[TCP].dport, server_tcp_port)
2031 self.tcp_port_out = packet[TCP].sport
2032 self.assert_packet_checksums_valid(packet)
2033 elif packet.haslayer(UDP):
2034 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2035 self.assertEqual(packet[UDP].dport, server_udp_port)
2036 self.udp_port_out = packet[UDP].sport
2038 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2039 self.icmp_id_out = packet[ICMP].id
2041 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2044 # server1 to server2
2046 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2047 IP(src=server1.ip4, dst=server2_nat_ip) /
2048 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2050 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2051 IP(src=server1.ip4, dst=server2_nat_ip) /
2052 UDP(sport=server_udp_port, dport=self.udp_port_out))
2054 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2055 IP(src=server1.ip4, dst=server2_nat_ip) /
2056 ICMP(id=self.icmp_id_out, type='echo-reply'))
2058 self.pg0.add_stream(pkts)
2059 self.pg_enable_capture(self.pg_interfaces)
2061 capture = self.pg0.get_capture(len(pkts))
2062 for packet in capture:
2064 self.assertEqual(packet[IP].src, server1_nat_ip)
2065 self.assertEqual(packet[IP].dst, server2.ip4)
2066 if packet.haslayer(TCP):
2067 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2068 self.assertEqual(packet[TCP].sport, server_tcp_port)
2069 self.assert_packet_checksums_valid(packet)
2070 elif packet.haslayer(UDP):
2071 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2072 self.assertEqual(packet[UDP].sport, server_udp_port)
2074 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2076 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2079 def test_hairpinning_avoid_inf_loop(self):
2080 """ NAT44 hairpinning - 1:1 NAPT avoid infinite loop """
2082 host = self.pg0.remote_hosts[0]
2083 server = self.pg0.remote_hosts[1]
2086 server_in_port = 5678
2087 server_out_port = 8765
2089 self.nat44_add_address(self.nat_addr)
2090 flags = self.config_flags.NAT_IS_INSIDE
2091 self.vapi.nat44_interface_add_del_feature(
2092 sw_if_index=self.pg0.sw_if_index,
2093 flags=flags, is_add=1)
2094 self.vapi.nat44_interface_add_del_feature(
2095 sw_if_index=self.pg1.sw_if_index,
2098 # add static mapping for server
2099 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2100 server_in_port, server_out_port,
2101 proto=IP_PROTOS.tcp)
2103 # add another static mapping that maps pg0.local_ip4 address to itself
2104 self.nat44_add_static_mapping(self.pg0.local_ip4, self.pg0.local_ip4)
2106 # send packet from host to VPP (the packet should get dropped)
2107 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2108 IP(src=host.ip4, dst=self.pg0.local_ip4) /
2109 TCP(sport=host_in_port, dport=server_out_port))
2110 self.pg0.add_stream(p)
2111 self.pg_enable_capture(self.pg_interfaces)
2113 # Here VPP used to crash due to an infinite loop
2115 cnt = self.statistics.get_counter('/nat44/hairpinning')[0]
2116 # send packet from host to server
2117 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2118 IP(src=host.ip4, dst=self.nat_addr) /
2119 TCP(sport=host_in_port, dport=server_out_port))
2120 self.pg0.add_stream(p)
2121 self.pg_enable_capture(self.pg_interfaces)
2123 capture = self.pg0.get_capture(1)
2128 self.assertEqual(ip.src, self.nat_addr)
2129 self.assertEqual(ip.dst, server.ip4)
2130 self.assertNotEqual(tcp.sport, host_in_port)
2131 self.assertEqual(tcp.dport, server_in_port)
2132 self.assert_packet_checksums_valid(p)
2133 host_out_port = tcp.sport
2135 self.logger.error(ppp("Unexpected or invalid packet:", p))
2138 after = self.statistics.get_counter('/nat44/hairpinning')[0]
2139 if_idx = self.pg0.sw_if_index
2140 self.assertEqual(after[if_idx] - cnt[if_idx], 1)
2142 # send reply from server to host
2143 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2144 IP(src=server.ip4, dst=self.nat_addr) /
2145 TCP(sport=server_in_port, dport=host_out_port))
2146 self.pg0.add_stream(p)
2147 self.pg_enable_capture(self.pg_interfaces)
2149 capture = self.pg0.get_capture(1)
2154 self.assertEqual(ip.src, self.nat_addr)
2155 self.assertEqual(ip.dst, host.ip4)
2156 self.assertEqual(tcp.sport, server_out_port)
2157 self.assertEqual(tcp.dport, host_in_port)
2158 self.assert_packet_checksums_valid(p)
2160 self.logger.error(ppp("Unexpected or invalid packet:", p))
2163 after = self.statistics.get_counter('/nat44/hairpinning')[0]
2164 if_idx = self.pg0.sw_if_index
2165 self.assertEqual(after[if_idx] - cnt[if_idx], 2)
2167 def test_interface_addr(self):
2168 """ NAT44EI acquire addresses from interface """
2169 self.vapi.nat44_add_del_interface_addr(
2171 sw_if_index=self.pg7.sw_if_index)
2173 # no address in NAT pool
2174 addresses = self.vapi.nat44_address_dump()
2175 self.assertEqual(0, len(addresses))
2177 # configure interface address and check NAT address pool
2178 self.pg7.config_ip4()
2179 addresses = self.vapi.nat44_address_dump()
2180 self.assertEqual(1, len(addresses))
2181 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2183 # remove interface address and check NAT address pool
2184 self.pg7.unconfig_ip4()
2185 addresses = self.vapi.nat44_address_dump()
2186 self.assertEqual(0, len(addresses))
2188 def test_interface_addr_static_mapping(self):
2189 """ NAT44EI Static mapping with addresses from interface """
2192 self.vapi.nat44_add_del_interface_addr(
2194 sw_if_index=self.pg7.sw_if_index)
2195 self.nat44_add_static_mapping(
2197 external_sw_if_index=self.pg7.sw_if_index,
2200 # static mappings with external interface
2201 static_mappings = self.vapi.nat44_static_mapping_dump()
2202 self.assertEqual(1, len(static_mappings))
2203 self.assertEqual(self.pg7.sw_if_index,
2204 static_mappings[0].external_sw_if_index)
2205 self.assertEqual(static_mappings[0].tag, tag)
2207 # configure interface address and check static mappings
2208 self.pg7.config_ip4()
2209 static_mappings = self.vapi.nat44_static_mapping_dump()
2210 self.assertEqual(2, len(static_mappings))
2212 for sm in static_mappings:
2213 if sm.external_sw_if_index == 0xFFFFFFFF:
2214 self.assertEqual(str(sm.external_ip_address),
2216 self.assertEqual(sm.tag, tag)
2218 self.assertTrue(resolved)
2220 # remove interface address and check static mappings
2221 self.pg7.unconfig_ip4()
2222 static_mappings = self.vapi.nat44_static_mapping_dump()
2223 self.assertEqual(1, len(static_mappings))
2224 self.assertEqual(self.pg7.sw_if_index,
2225 static_mappings[0].external_sw_if_index)
2226 self.assertEqual(static_mappings[0].tag, tag)
2228 # configure interface address again and check static mappings
2229 self.pg7.config_ip4()
2230 static_mappings = self.vapi.nat44_static_mapping_dump()
2231 self.assertEqual(2, len(static_mappings))
2233 for sm in static_mappings:
2234 if sm.external_sw_if_index == 0xFFFFFFFF:
2235 self.assertEqual(str(sm.external_ip_address),
2237 self.assertEqual(sm.tag, tag)
2239 self.assertTrue(resolved)
2241 # remove static mapping
2242 self.nat44_add_static_mapping(
2244 external_sw_if_index=self.pg7.sw_if_index,
2247 static_mappings = self.vapi.nat44_static_mapping_dump()
2248 self.assertEqual(0, len(static_mappings))
2250 def test_interface_addr_identity_nat(self):
2251 """ NAT44EI Identity NAT with addresses from interface """
2254 self.vapi.nat44_add_del_interface_addr(
2256 sw_if_index=self.pg7.sw_if_index)
2257 self.vapi.nat44_add_del_identity_mapping(
2259 sw_if_index=self.pg7.sw_if_index,
2261 protocol=IP_PROTOS.tcp,
2264 # identity mappings with external interface
2265 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2266 self.assertEqual(1, len(identity_mappings))
2267 self.assertEqual(self.pg7.sw_if_index,
2268 identity_mappings[0].sw_if_index)
2270 # configure interface address and check identity mappings
2271 self.pg7.config_ip4()
2272 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2274 self.assertEqual(2, len(identity_mappings))
2275 for sm in identity_mappings:
2276 if sm.sw_if_index == 0xFFFFFFFF:
2277 self.assertEqual(str(identity_mappings[0].ip_address),
2279 self.assertEqual(port, identity_mappings[0].port)
2280 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2282 self.assertTrue(resolved)
2284 # remove interface address and check identity mappings
2285 self.pg7.unconfig_ip4()
2286 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2287 self.assertEqual(1, len(identity_mappings))
2288 self.assertEqual(self.pg7.sw_if_index,
2289 identity_mappings[0].sw_if_index)
2291 def test_ipfix_nat44_sess(self):
2292 """ NAT44EI IPFIX logging NAT44EI session created/deleted """
2293 self.ipfix_domain_id = 10
2294 self.ipfix_src_port = 20202
2295 collector_port = 30303
2296 bind_layers(UDP, IPFIX, dport=30303)
2297 self.nat44_add_address(self.nat_addr)
2298 flags = self.config_flags.NAT_IS_INSIDE
2299 self.vapi.nat44_interface_add_del_feature(
2300 sw_if_index=self.pg0.sw_if_index,
2301 flags=flags, is_add=1)
2302 self.vapi.nat44_interface_add_del_feature(
2303 sw_if_index=self.pg1.sw_if_index,
2305 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2306 src_address=self.pg3.local_ip4,
2308 template_interval=10,
2309 collector_port=collector_port)
2310 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2311 src_port=self.ipfix_src_port,
2314 pkts = self.create_stream_in(self.pg0, self.pg1)
2315 self.pg0.add_stream(pkts)
2316 self.pg_enable_capture(self.pg_interfaces)
2318 capture = self.pg1.get_capture(len(pkts))
2319 self.verify_capture_out(capture)
2320 self.nat44_add_address(self.nat_addr, is_add=0)
2321 self.vapi.ipfix_flush()
2322 capture = self.pg3.get_capture(7)
2323 ipfix = IPFIXDecoder()
2324 # first load template
2326 self.assertTrue(p.haslayer(IPFIX))
2327 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2328 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2329 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2330 self.assertEqual(p[UDP].dport, collector_port)
2331 self.assertEqual(p[IPFIX].observationDomainID,
2332 self.ipfix_domain_id)
2333 if p.haslayer(Template):
2334 ipfix.add_template(p.getlayer(Template))
2335 # verify events in data set
2337 if p.haslayer(Data):
2338 data = ipfix.decode_data_set(p.getlayer(Set))
2339 self.verify_ipfix_nat44_ses(data)
2341 def test_ipfix_addr_exhausted(self):
2342 """ NAT44EI IPFIX logging NAT addresses exhausted """
2343 flags = self.config_flags.NAT_IS_INSIDE
2344 self.vapi.nat44_interface_add_del_feature(
2345 sw_if_index=self.pg0.sw_if_index,
2346 flags=flags, is_add=1)
2347 self.vapi.nat44_interface_add_del_feature(
2348 sw_if_index=self.pg1.sw_if_index,
2350 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2351 src_address=self.pg3.local_ip4,
2353 template_interval=10)
2354 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2355 src_port=self.ipfix_src_port,
2358 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2359 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2361 self.pg0.add_stream(p)
2362 self.pg_enable_capture(self.pg_interfaces)
2364 self.pg1.assert_nothing_captured()
2366 self.vapi.ipfix_flush()
2367 capture = self.pg3.get_capture(7)
2368 ipfix = IPFIXDecoder()
2369 # first load template
2371 self.assertTrue(p.haslayer(IPFIX))
2372 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2373 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2374 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2375 self.assertEqual(p[UDP].dport, 4739)
2376 self.assertEqual(p[IPFIX].observationDomainID,
2377 self.ipfix_domain_id)
2378 if p.haslayer(Template):
2379 ipfix.add_template(p.getlayer(Template))
2380 # verify events in data set
2382 if p.haslayer(Data):
2383 data = ipfix.decode_data_set(p.getlayer(Set))
2384 self.verify_ipfix_addr_exhausted(data)
2386 def test_ipfix_max_sessions(self):
2387 """ NAT44EI IPFIX logging maximum session entries exceeded """
2388 self.nat44_add_address(self.nat_addr)
2389 flags = self.config_flags.NAT_IS_INSIDE
2390 self.vapi.nat44_interface_add_del_feature(
2391 sw_if_index=self.pg0.sw_if_index,
2392 flags=flags, is_add=1)
2393 self.vapi.nat44_interface_add_del_feature(
2394 sw_if_index=self.pg1.sw_if_index,
2397 max_sessions = self.max_translations
2400 for i in range(0, max_sessions):
2401 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2402 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2403 IP(src=src, dst=self.pg1.remote_ip4) /
2406 self.pg0.add_stream(pkts)
2407 self.pg_enable_capture(self.pg_interfaces)
2410 self.pg1.get_capture(max_sessions)
2411 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2412 src_address=self.pg3.local_ip4,
2414 template_interval=10)
2415 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2416 src_port=self.ipfix_src_port,
2419 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2420 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2422 self.pg0.add_stream(p)
2423 self.pg_enable_capture(self.pg_interfaces)
2425 self.pg1.assert_nothing_captured()
2427 self.vapi.ipfix_flush()
2428 capture = self.pg3.get_capture(7)
2429 ipfix = IPFIXDecoder()
2430 # first load template
2432 self.assertTrue(p.haslayer(IPFIX))
2433 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2434 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2435 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2436 self.assertEqual(p[UDP].dport, 4739)
2437 self.assertEqual(p[IPFIX].observationDomainID,
2438 self.ipfix_domain_id)
2439 if p.haslayer(Template):
2440 ipfix.add_template(p.getlayer(Template))
2441 # verify events in data set
2443 if p.haslayer(Data):
2444 data = ipfix.decode_data_set(p.getlayer(Set))
2445 self.verify_ipfix_max_sessions(data, max_sessions)
2447 def test_syslog_apmap(self):
2448 """ NAT44EI syslog address and port mapping creation and deletion """
2449 self.vapi.syslog_set_filter(
2450 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2451 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2452 self.nat44_add_address(self.nat_addr)
2453 flags = self.config_flags.NAT_IS_INSIDE
2454 self.vapi.nat44_interface_add_del_feature(
2455 sw_if_index=self.pg0.sw_if_index,
2456 flags=flags, is_add=1)
2457 self.vapi.nat44_interface_add_del_feature(
2458 sw_if_index=self.pg1.sw_if_index,
2461 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2462 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2463 TCP(sport=self.tcp_port_in, dport=20))
2464 self.pg0.add_stream(p)
2465 self.pg_enable_capture(self.pg_interfaces)
2467 capture = self.pg1.get_capture(1)
2468 self.tcp_port_out = capture[0][TCP].sport
2469 capture = self.pg3.get_capture(1)
2470 self.verify_syslog_apmap(capture[0][Raw].load)
2472 self.pg_enable_capture(self.pg_interfaces)
2474 self.nat44_add_address(self.nat_addr, is_add=0)
2475 capture = self.pg3.get_capture(1)
2476 self.verify_syslog_apmap(capture[0][Raw].load, False)
2478 def test_pool_addr_fib(self):
2479 """ NAT44EI add pool addresses to FIB """
2480 static_addr = '10.0.0.10'
2481 self.nat44_add_address(self.nat_addr)
2482 flags = self.config_flags.NAT_IS_INSIDE
2483 self.vapi.nat44_interface_add_del_feature(
2484 sw_if_index=self.pg0.sw_if_index,
2485 flags=flags, is_add=1)
2486 self.vapi.nat44_interface_add_del_feature(
2487 sw_if_index=self.pg1.sw_if_index,
2489 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2492 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2493 ARP(op=ARP.who_has, pdst=self.nat_addr,
2494 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2495 self.pg1.add_stream(p)
2496 self.pg_enable_capture(self.pg_interfaces)
2498 capture = self.pg1.get_capture(1)
2499 self.assertTrue(capture[0].haslayer(ARP))
2500 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2503 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2504 ARP(op=ARP.who_has, pdst=static_addr,
2505 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2506 self.pg1.add_stream(p)
2507 self.pg_enable_capture(self.pg_interfaces)
2509 capture = self.pg1.get_capture(1)
2510 self.assertTrue(capture[0].haslayer(ARP))
2511 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2513 # send ARP to non-NAT44EI interface
2514 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2515 ARP(op=ARP.who_has, pdst=self.nat_addr,
2516 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2517 self.pg2.add_stream(p)
2518 self.pg_enable_capture(self.pg_interfaces)
2520 self.pg1.assert_nothing_captured()
2522 # remove addresses and verify
2523 self.nat44_add_address(self.nat_addr, is_add=0)
2524 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2527 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2528 ARP(op=ARP.who_has, pdst=self.nat_addr,
2529 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2530 self.pg1.add_stream(p)
2531 self.pg_enable_capture(self.pg_interfaces)
2533 self.pg1.assert_nothing_captured()
2535 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2536 ARP(op=ARP.who_has, pdst=static_addr,
2537 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2538 self.pg1.add_stream(p)
2539 self.pg_enable_capture(self.pg_interfaces)
2541 self.pg1.assert_nothing_captured()
2543 def test_vrf_mode(self):
2544 """ NAT44EI tenant VRF aware address pool mode """
2548 nat_ip1 = "10.0.0.10"
2549 nat_ip2 = "10.0.0.11"
2551 self.pg0.unconfig_ip4()
2552 self.pg1.unconfig_ip4()
2553 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2554 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2555 self.pg0.set_table_ip4(vrf_id1)
2556 self.pg1.set_table_ip4(vrf_id2)
2557 self.pg0.config_ip4()
2558 self.pg1.config_ip4()
2559 self.pg0.resolve_arp()
2560 self.pg1.resolve_arp()
2562 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2563 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2564 flags = self.config_flags.NAT_IS_INSIDE
2565 self.vapi.nat44_interface_add_del_feature(
2566 sw_if_index=self.pg0.sw_if_index,
2567 flags=flags, is_add=1)
2568 self.vapi.nat44_interface_add_del_feature(
2569 sw_if_index=self.pg1.sw_if_index,
2570 flags=flags, is_add=1)
2571 self.vapi.nat44_interface_add_del_feature(
2572 sw_if_index=self.pg2.sw_if_index,
2577 pkts = self.create_stream_in(self.pg0, self.pg2)
2578 self.pg0.add_stream(pkts)
2579 self.pg_enable_capture(self.pg_interfaces)
2581 capture = self.pg2.get_capture(len(pkts))
2582 self.verify_capture_out(capture, nat_ip1)
2585 pkts = self.create_stream_in(self.pg1, self.pg2)
2586 self.pg1.add_stream(pkts)
2587 self.pg_enable_capture(self.pg_interfaces)
2589 capture = self.pg2.get_capture(len(pkts))
2590 self.verify_capture_out(capture, nat_ip2)
2593 self.pg0.unconfig_ip4()
2594 self.pg1.unconfig_ip4()
2595 self.pg0.set_table_ip4(0)
2596 self.pg1.set_table_ip4(0)
2597 self.pg0.config_ip4()
2598 self.pg1.config_ip4()
2599 self.pg0.resolve_arp()
2600 self.pg1.resolve_arp()
2601 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2602 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2604 def test_vrf_feature_independent(self):
2605 """ NAT44EI tenant VRF independent address pool mode """
2607 nat_ip1 = "10.0.0.10"
2608 nat_ip2 = "10.0.0.11"
2610 self.nat44_add_address(nat_ip1)
2611 self.nat44_add_address(nat_ip2, vrf_id=99)
2612 flags = self.config_flags.NAT_IS_INSIDE
2613 self.vapi.nat44_interface_add_del_feature(
2614 sw_if_index=self.pg0.sw_if_index,
2615 flags=flags, is_add=1)
2616 self.vapi.nat44_interface_add_del_feature(
2617 sw_if_index=self.pg1.sw_if_index,
2618 flags=flags, is_add=1)
2619 self.vapi.nat44_interface_add_del_feature(
2620 sw_if_index=self.pg2.sw_if_index,
2624 pkts = self.create_stream_in(self.pg0, self.pg2)
2625 self.pg0.add_stream(pkts)
2626 self.pg_enable_capture(self.pg_interfaces)
2628 capture = self.pg2.get_capture(len(pkts))
2629 self.verify_capture_out(capture, nat_ip1)
2632 pkts = self.create_stream_in(self.pg1, self.pg2)
2633 self.pg1.add_stream(pkts)
2634 self.pg_enable_capture(self.pg_interfaces)
2636 capture = self.pg2.get_capture(len(pkts))
2637 self.verify_capture_out(capture, nat_ip1)
2639 def test_dynamic_ipless_interfaces(self):
2640 """ NAT44EI interfaces without configured IP address """
2641 self.create_routes_and_neigbors()
2642 self.nat44_add_address(self.nat_addr)
2643 flags = self.config_flags.NAT_IS_INSIDE
2644 self.vapi.nat44_interface_add_del_feature(
2645 sw_if_index=self.pg7.sw_if_index,
2646 flags=flags, is_add=1)
2647 self.vapi.nat44_interface_add_del_feature(
2648 sw_if_index=self.pg8.sw_if_index,
2652 pkts = self.create_stream_in(self.pg7, self.pg8)
2653 self.pg7.add_stream(pkts)
2654 self.pg_enable_capture(self.pg_interfaces)
2656 capture = self.pg8.get_capture(len(pkts))
2657 self.verify_capture_out(capture)
2660 pkts = self.create_stream_out(self.pg8, self.nat_addr)
2661 self.pg8.add_stream(pkts)
2662 self.pg_enable_capture(self.pg_interfaces)
2664 capture = self.pg7.get_capture(len(pkts))
2665 self.verify_capture_in(capture, self.pg7)
2667 def test_static_ipless_interfaces(self):
2668 """ NAT44EI interfaces without configured IP address - 1:1 NAT """
2670 self.create_routes_and_neigbors()
2671 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2672 flags = self.config_flags.NAT_IS_INSIDE
2673 self.vapi.nat44_interface_add_del_feature(
2674 sw_if_index=self.pg7.sw_if_index,
2675 flags=flags, is_add=1)
2676 self.vapi.nat44_interface_add_del_feature(
2677 sw_if_index=self.pg8.sw_if_index,
2681 pkts = self.create_stream_out(self.pg8)
2682 self.pg8.add_stream(pkts)
2683 self.pg_enable_capture(self.pg_interfaces)
2685 capture = self.pg7.get_capture(len(pkts))
2686 self.verify_capture_in(capture, self.pg7)
2689 pkts = self.create_stream_in(self.pg7, self.pg8)
2690 self.pg7.add_stream(pkts)
2691 self.pg_enable_capture(self.pg_interfaces)
2693 capture = self.pg8.get_capture(len(pkts))
2694 self.verify_capture_out(capture, self.nat_addr, True)
2696 def test_static_with_port_ipless_interfaces(self):
2697 """ NAT44EI interfaces without configured IP address - 1:1 NAPT """
2699 self.tcp_port_out = 30606
2700 self.udp_port_out = 30607
2701 self.icmp_id_out = 30608
2703 self.create_routes_and_neigbors()
2704 self.nat44_add_address(self.nat_addr)
2705 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2706 self.tcp_port_in, self.tcp_port_out,
2707 proto=IP_PROTOS.tcp)
2708 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2709 self.udp_port_in, self.udp_port_out,
2710 proto=IP_PROTOS.udp)
2711 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2712 self.icmp_id_in, self.icmp_id_out,
2713 proto=IP_PROTOS.icmp)
2714 flags = self.config_flags.NAT_IS_INSIDE
2715 self.vapi.nat44_interface_add_del_feature(
2716 sw_if_index=self.pg7.sw_if_index,
2717 flags=flags, is_add=1)
2718 self.vapi.nat44_interface_add_del_feature(
2719 sw_if_index=self.pg8.sw_if_index,
2723 pkts = self.create_stream_out(self.pg8)
2724 self.pg8.add_stream(pkts)
2725 self.pg_enable_capture(self.pg_interfaces)
2727 capture = self.pg7.get_capture(len(pkts))
2728 self.verify_capture_in(capture, self.pg7)
2731 pkts = self.create_stream_in(self.pg7, self.pg8)
2732 self.pg7.add_stream(pkts)
2733 self.pg_enable_capture(self.pg_interfaces)
2735 capture = self.pg8.get_capture(len(pkts))
2736 self.verify_capture_out(capture)
2738 def test_static_unknown_proto(self):
2739 """ NAT44EI 1:1 translate packet with unknown protocol """
2740 nat_ip = "10.0.0.10"
2741 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2742 flags = self.config_flags.NAT_IS_INSIDE
2743 self.vapi.nat44_interface_add_del_feature(
2744 sw_if_index=self.pg0.sw_if_index,
2745 flags=flags, is_add=1)
2746 self.vapi.nat44_interface_add_del_feature(
2747 sw_if_index=self.pg1.sw_if_index,
2751 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2752 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2754 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2755 TCP(sport=1234, dport=1234))
2756 self.pg0.add_stream(p)
2757 self.pg_enable_capture(self.pg_interfaces)
2759 p = self.pg1.get_capture(1)
2762 self.assertEqual(packet[IP].src, nat_ip)
2763 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2764 self.assertEqual(packet.haslayer(GRE), 1)
2765 self.assert_packet_checksums_valid(packet)
2767 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2771 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2772 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2774 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2775 TCP(sport=1234, dport=1234))
2776 self.pg1.add_stream(p)
2777 self.pg_enable_capture(self.pg_interfaces)
2779 p = self.pg0.get_capture(1)
2782 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2783 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2784 self.assertEqual(packet.haslayer(GRE), 1)
2785 self.assert_packet_checksums_valid(packet)
2787 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2790 def test_hairpinning_static_unknown_proto(self):
2791 """ NAT44EI 1:1 translate packet with unknown protocol - hairpinning
2794 host = self.pg0.remote_hosts[0]
2795 server = self.pg0.remote_hosts[1]
2797 host_nat_ip = "10.0.0.10"
2798 server_nat_ip = "10.0.0.11"
2800 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2801 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2802 flags = self.config_flags.NAT_IS_INSIDE
2803 self.vapi.nat44_interface_add_del_feature(
2804 sw_if_index=self.pg0.sw_if_index,
2805 flags=flags, is_add=1)
2806 self.vapi.nat44_interface_add_del_feature(
2807 sw_if_index=self.pg1.sw_if_index,
2811 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2812 IP(src=host.ip4, dst=server_nat_ip) /
2814 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2815 TCP(sport=1234, dport=1234))
2816 self.pg0.add_stream(p)
2817 self.pg_enable_capture(self.pg_interfaces)
2819 p = self.pg0.get_capture(1)
2822 self.assertEqual(packet[IP].src, host_nat_ip)
2823 self.assertEqual(packet[IP].dst, server.ip4)
2824 self.assertEqual(packet.haslayer(GRE), 1)
2825 self.assert_packet_checksums_valid(packet)
2827 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2831 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2832 IP(src=server.ip4, dst=host_nat_ip) /
2834 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2835 TCP(sport=1234, dport=1234))
2836 self.pg0.add_stream(p)
2837 self.pg_enable_capture(self.pg_interfaces)
2839 p = self.pg0.get_capture(1)
2842 self.assertEqual(packet[IP].src, server_nat_ip)
2843 self.assertEqual(packet[IP].dst, host.ip4)
2844 self.assertEqual(packet.haslayer(GRE), 1)
2845 self.assert_packet_checksums_valid(packet)
2847 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2850 def test_output_feature(self):
2851 """ NAT44EI output feature (in2out postrouting) """
2852 self.nat44_add_address(self.nat_addr)
2853 flags = self.config_flags.NAT_IS_INSIDE
2854 self.vapi.nat44_interface_add_del_output_feature(
2855 is_add=1, flags=flags,
2856 sw_if_index=self.pg0.sw_if_index)
2857 self.vapi.nat44_interface_add_del_output_feature(
2858 is_add=1, flags=flags,
2859 sw_if_index=self.pg1.sw_if_index)
2860 self.vapi.nat44_interface_add_del_output_feature(
2862 sw_if_index=self.pg3.sw_if_index)
2865 pkts = self.create_stream_in(self.pg0, self.pg3)
2866 self.pg0.add_stream(pkts)
2867 self.pg_enable_capture(self.pg_interfaces)
2869 capture = self.pg3.get_capture(len(pkts))
2870 self.verify_capture_out(capture)
2873 pkts = self.create_stream_out(self.pg3)
2874 self.pg3.add_stream(pkts)
2875 self.pg_enable_capture(self.pg_interfaces)
2877 capture = self.pg0.get_capture(len(pkts))
2878 self.verify_capture_in(capture, self.pg0)
2880 # from non-NAT interface to NAT inside interface
2881 pkts = self.create_stream_in(self.pg2, self.pg0)
2882 self.pg2.add_stream(pkts)
2883 self.pg_enable_capture(self.pg_interfaces)
2885 capture = self.pg0.get_capture(len(pkts))
2886 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2888 def test_output_feature_vrf_aware(self):
2889 """ NAT44EI output feature VRF aware (in2out postrouting) """
2890 nat_ip_vrf10 = "10.0.0.10"
2891 nat_ip_vrf20 = "10.0.0.20"
2893 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2894 [VppRoutePath(self.pg3.remote_ip4,
2895 self.pg3.sw_if_index)],
2897 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2898 [VppRoutePath(self.pg3.remote_ip4,
2899 self.pg3.sw_if_index)],
2904 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2905 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2906 flags = self.config_flags.NAT_IS_INSIDE
2907 self.vapi.nat44_interface_add_del_output_feature(
2908 is_add=1, flags=flags,
2909 sw_if_index=self.pg4.sw_if_index)
2910 self.vapi.nat44_interface_add_del_output_feature(
2911 is_add=1, flags=flags,
2912 sw_if_index=self.pg6.sw_if_index)
2913 self.vapi.nat44_interface_add_del_output_feature(
2915 sw_if_index=self.pg3.sw_if_index)
2918 pkts = self.create_stream_in(self.pg4, self.pg3)
2919 self.pg4.add_stream(pkts)
2920 self.pg_enable_capture(self.pg_interfaces)
2922 capture = self.pg3.get_capture(len(pkts))
2923 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2926 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2927 self.pg3.add_stream(pkts)
2928 self.pg_enable_capture(self.pg_interfaces)
2930 capture = self.pg4.get_capture(len(pkts))
2931 self.verify_capture_in(capture, self.pg4)
2934 pkts = self.create_stream_in(self.pg6, self.pg3)
2935 self.pg6.add_stream(pkts)
2936 self.pg_enable_capture(self.pg_interfaces)
2938 capture = self.pg3.get_capture(len(pkts))
2939 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2942 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2943 self.pg3.add_stream(pkts)
2944 self.pg_enable_capture(self.pg_interfaces)
2946 capture = self.pg6.get_capture(len(pkts))
2947 self.verify_capture_in(capture, self.pg6)
2949 def test_output_feature_hairpinning(self):
2950 """ NAT44EI output feature hairpinning (in2out postrouting) """
2951 host = self.pg0.remote_hosts[0]
2952 server = self.pg0.remote_hosts[1]
2955 server_in_port = 5678
2956 server_out_port = 8765
2958 self.nat44_add_address(self.nat_addr)
2959 flags = self.config_flags.NAT_IS_INSIDE
2960 self.vapi.nat44_interface_add_del_output_feature(
2961 is_add=1, flags=flags,
2962 sw_if_index=self.pg0.sw_if_index)
2963 self.vapi.nat44_interface_add_del_output_feature(
2965 sw_if_index=self.pg1.sw_if_index)
2967 # add static mapping for server
2968 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2969 server_in_port, server_out_port,
2970 proto=IP_PROTOS.tcp)
2972 # send packet from host to server
2973 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2974 IP(src=host.ip4, dst=self.nat_addr) /
2975 TCP(sport=host_in_port, dport=server_out_port))
2976 self.pg0.add_stream(p)
2977 self.pg_enable_capture(self.pg_interfaces)
2979 capture = self.pg0.get_capture(1)
2984 self.assertEqual(ip.src, self.nat_addr)
2985 self.assertEqual(ip.dst, server.ip4)
2986 self.assertNotEqual(tcp.sport, host_in_port)
2987 self.assertEqual(tcp.dport, server_in_port)
2988 self.assert_packet_checksums_valid(p)
2989 host_out_port = tcp.sport
2991 self.logger.error(ppp("Unexpected or invalid packet:", p))
2994 # send reply from server to host
2995 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2996 IP(src=server.ip4, dst=self.nat_addr) /
2997 TCP(sport=server_in_port, dport=host_out_port))
2998 self.pg0.add_stream(p)
2999 self.pg_enable_capture(self.pg_interfaces)
3001 capture = self.pg0.get_capture(1)
3006 self.assertEqual(ip.src, self.nat_addr)
3007 self.assertEqual(ip.dst, host.ip4)
3008 self.assertEqual(tcp.sport, server_out_port)
3009 self.assertEqual(tcp.dport, host_in_port)
3010 self.assert_packet_checksums_valid(p)
3012 self.logger.error(ppp("Unexpected or invalid packet:", p))
3015 def test_one_armed_nat44(self):
3016 """ NAT44EI One armed NAT """
3017 remote_host = self.pg9.remote_hosts[0]
3018 local_host = self.pg9.remote_hosts[1]
3021 self.nat44_add_address(self.nat_addr)
3022 flags = self.config_flags.NAT_IS_INSIDE
3023 self.vapi.nat44_interface_add_del_feature(
3024 sw_if_index=self.pg9.sw_if_index,
3026 self.vapi.nat44_interface_add_del_feature(
3027 sw_if_index=self.pg9.sw_if_index,
3028 flags=flags, is_add=1)
3031 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3032 IP(src=local_host.ip4, dst=remote_host.ip4) /
3033 TCP(sport=12345, dport=80))
3034 self.pg9.add_stream(p)
3035 self.pg_enable_capture(self.pg_interfaces)
3037 capture = self.pg9.get_capture(1)
3042 self.assertEqual(ip.src, self.nat_addr)
3043 self.assertEqual(ip.dst, remote_host.ip4)
3044 self.assertNotEqual(tcp.sport, 12345)
3045 external_port = tcp.sport
3046 self.assertEqual(tcp.dport, 80)
3047 self.assert_packet_checksums_valid(p)
3049 self.logger.error(ppp("Unexpected or invalid packet:", p))
3053 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3054 IP(src=remote_host.ip4, dst=self.nat_addr) /
3055 TCP(sport=80, dport=external_port))
3056 self.pg9.add_stream(p)
3057 self.pg_enable_capture(self.pg_interfaces)
3059 capture = self.pg9.get_capture(1)
3064 self.assertEqual(ip.src, remote_host.ip4)
3065 self.assertEqual(ip.dst, local_host.ip4)
3066 self.assertEqual(tcp.sport, 80)
3067 self.assertEqual(tcp.dport, 12345)
3068 self.assert_packet_checksums_valid(p)
3070 self.logger.error(ppp("Unexpected or invalid packet:", p))
3073 err = self.statistics.get_err_counter(
3074 '/err/nat44-classify/next in2out')
3075 self.assertEqual(err, 1)
3076 err = self.statistics.get_err_counter(
3077 '/err/nat44-classify/next out2in')
3078 self.assertEqual(err, 1)
3080 def test_del_session(self):
3081 """ NAT44EI delete session """
3082 self.nat44_add_address(self.nat_addr)
3083 flags = self.config_flags.NAT_IS_INSIDE
3084 self.vapi.nat44_interface_add_del_feature(
3085 sw_if_index=self.pg0.sw_if_index,
3086 flags=flags, is_add=1)
3087 self.vapi.nat44_interface_add_del_feature(
3088 sw_if_index=self.pg1.sw_if_index,
3091 pkts = self.create_stream_in(self.pg0, self.pg1)
3092 self.pg0.add_stream(pkts)
3093 self.pg_enable_capture(self.pg_interfaces)
3095 self.pg1.get_capture(len(pkts))
3097 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3098 nsessions = len(sessions)
3100 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3101 port=sessions[0].inside_port,
3102 protocol=sessions[0].protocol,
3103 flags=self.config_flags.NAT_IS_INSIDE)
3104 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3105 port=sessions[1].outside_port,
3106 protocol=sessions[1].protocol)
3108 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3109 self.assertEqual(nsessions - len(sessions), 2)
3111 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3112 port=sessions[0].inside_port,
3113 protocol=sessions[0].protocol,
3114 flags=self.config_flags.NAT_IS_INSIDE)
3116 self.verify_no_nat44_user()
3118 def test_frag_in_order(self):
3119 """ NAT44EI translate fragments arriving in order """
3121 self.nat44_add_address(self.nat_addr)
3122 flags = self.config_flags.NAT_IS_INSIDE
3123 self.vapi.nat44_interface_add_del_feature(
3124 sw_if_index=self.pg0.sw_if_index,
3125 flags=flags, is_add=1)
3126 self.vapi.nat44_interface_add_del_feature(
3127 sw_if_index=self.pg1.sw_if_index,
3130 self.frag_in_order(proto=IP_PROTOS.tcp)
3131 self.frag_in_order(proto=IP_PROTOS.udp)
3132 self.frag_in_order(proto=IP_PROTOS.icmp)
3134 def test_frag_forwarding(self):
3135 """ NAT44EI forwarding fragment test """
3136 self.vapi.nat44_add_del_interface_addr(
3138 sw_if_index=self.pg1.sw_if_index)
3139 flags = self.config_flags.NAT_IS_INSIDE
3140 self.vapi.nat44_interface_add_del_feature(
3141 sw_if_index=self.pg0.sw_if_index,
3142 flags=flags, is_add=1)
3143 self.vapi.nat44_interface_add_del_feature(
3144 sw_if_index=self.pg1.sw_if_index,
3146 self.vapi.nat44_forwarding_enable_disable(enable=1)
3148 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3149 pkts = self.create_stream_frag(self.pg1,
3150 self.pg0.remote_ip4,
3154 proto=IP_PROTOS.udp)
3155 self.pg1.add_stream(pkts)
3156 self.pg_enable_capture(self.pg_interfaces)
3158 frags = self.pg0.get_capture(len(pkts))
3159 p = self.reass_frags_and_verify(frags,
3160 self.pg1.remote_ip4,
3161 self.pg0.remote_ip4)
3162 self.assertEqual(p[UDP].sport, 4789)
3163 self.assertEqual(p[UDP].dport, 4789)
3164 self.assertEqual(data, p[Raw].load)
3166 def test_reass_hairpinning(self):
3167 """ NAT44EI fragments hairpinning """
3169 server_addr = self.pg0.remote_hosts[1].ip4
3170 host_in_port = random.randint(1025, 65535)
3171 server_in_port = random.randint(1025, 65535)
3172 server_out_port = random.randint(1025, 65535)
3174 self.nat44_add_address(self.nat_addr)
3175 flags = self.config_flags.NAT_IS_INSIDE
3176 self.vapi.nat44_interface_add_del_feature(
3177 sw_if_index=self.pg0.sw_if_index,
3178 flags=flags, is_add=1)
3179 self.vapi.nat44_interface_add_del_feature(
3180 sw_if_index=self.pg1.sw_if_index,
3182 # add static mapping for server
3183 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3186 proto=IP_PROTOS.tcp)
3187 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3190 proto=IP_PROTOS.udp)
3191 self.nat44_add_static_mapping(server_addr, self.nat_addr)
3193 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3194 host_in_port, proto=IP_PROTOS.tcp)
3195 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3196 host_in_port, proto=IP_PROTOS.udp)
3197 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3198 host_in_port, proto=IP_PROTOS.icmp)
3200 def test_frag_out_of_order(self):
3201 """ NAT44EI translate fragments arriving out of order """
3203 self.nat44_add_address(self.nat_addr)
3204 flags = self.config_flags.NAT_IS_INSIDE
3205 self.vapi.nat44_interface_add_del_feature(
3206 sw_if_index=self.pg0.sw_if_index,
3207 flags=flags, is_add=1)
3208 self.vapi.nat44_interface_add_del_feature(
3209 sw_if_index=self.pg1.sw_if_index,
3212 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3213 self.frag_out_of_order(proto=IP_PROTOS.udp)
3214 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3216 def test_port_restricted(self):
3217 """ NAT44EI Port restricted NAT44EI (MAP-E CE) """
3218 self.nat44_add_address(self.nat_addr)
3219 flags = self.config_flags.NAT_IS_INSIDE
3220 self.vapi.nat44_interface_add_del_feature(
3221 sw_if_index=self.pg0.sw_if_index,
3222 flags=flags, is_add=1)
3223 self.vapi.nat44_interface_add_del_feature(
3224 sw_if_index=self.pg1.sw_if_index,
3226 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3231 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3232 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3233 TCP(sport=4567, dport=22))
3234 self.pg0.add_stream(p)
3235 self.pg_enable_capture(self.pg_interfaces)
3237 capture = self.pg1.get_capture(1)
3242 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3243 self.assertEqual(ip.src, self.nat_addr)
3244 self.assertEqual(tcp.dport, 22)
3245 self.assertNotEqual(tcp.sport, 4567)
3246 self.assertEqual((tcp.sport >> 6) & 63, 10)
3247 self.assert_packet_checksums_valid(p)
3249 self.logger.error(ppp("Unexpected or invalid packet:", p))
3252 def test_port_range(self):
3253 """ NAT44EI External address port range """
3254 self.nat44_add_address(self.nat_addr)
3255 flags = self.config_flags.NAT_IS_INSIDE
3256 self.vapi.nat44_interface_add_del_feature(
3257 sw_if_index=self.pg0.sw_if_index,
3258 flags=flags, is_add=1)
3259 self.vapi.nat44_interface_add_del_feature(
3260 sw_if_index=self.pg1.sw_if_index,
3262 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3267 for port in range(0, 5):
3268 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3269 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3270 TCP(sport=1125 + port))
3272 self.pg0.add_stream(pkts)
3273 self.pg_enable_capture(self.pg_interfaces)
3275 capture = self.pg1.get_capture(3)
3278 self.assertGreaterEqual(tcp.sport, 1025)
3279 self.assertLessEqual(tcp.sport, 1027)
3281 def test_multiple_outside_vrf(self):
3282 """ NAT44EI Multiple outside VRF """
3286 self.pg1.unconfig_ip4()
3287 self.pg2.unconfig_ip4()
3288 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3289 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3290 self.pg1.set_table_ip4(vrf_id1)
3291 self.pg2.set_table_ip4(vrf_id2)
3292 self.pg1.config_ip4()
3293 self.pg2.config_ip4()
3294 self.pg1.resolve_arp()
3295 self.pg2.resolve_arp()
3297 self.nat44_add_address(self.nat_addr)
3298 flags = self.config_flags.NAT_IS_INSIDE
3299 self.vapi.nat44_interface_add_del_feature(
3300 sw_if_index=self.pg0.sw_if_index,
3301 flags=flags, is_add=1)
3302 self.vapi.nat44_interface_add_del_feature(
3303 sw_if_index=self.pg1.sw_if_index,
3305 self.vapi.nat44_interface_add_del_feature(
3306 sw_if_index=self.pg2.sw_if_index,
3311 pkts = self.create_stream_in(self.pg0, self.pg1)
3312 self.pg0.add_stream(pkts)
3313 self.pg_enable_capture(self.pg_interfaces)
3315 capture = self.pg1.get_capture(len(pkts))
3316 self.verify_capture_out(capture, self.nat_addr)
3318 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3319 self.pg1.add_stream(pkts)
3320 self.pg_enable_capture(self.pg_interfaces)
3322 capture = self.pg0.get_capture(len(pkts))
3323 self.verify_capture_in(capture, self.pg0)
3325 self.tcp_port_in = 60303
3326 self.udp_port_in = 60304
3327 self.icmp_id_in = 60305
3330 pkts = self.create_stream_in(self.pg0, self.pg2)
3331 self.pg0.add_stream(pkts)
3332 self.pg_enable_capture(self.pg_interfaces)
3334 capture = self.pg2.get_capture(len(pkts))
3335 self.verify_capture_out(capture, self.nat_addr)
3337 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3338 self.pg2.add_stream(pkts)
3339 self.pg_enable_capture(self.pg_interfaces)
3341 capture = self.pg0.get_capture(len(pkts))
3342 self.verify_capture_in(capture, self.pg0)
3345 self.nat44_add_address(self.nat_addr, is_add=0)
3346 self.pg1.unconfig_ip4()
3347 self.pg2.unconfig_ip4()
3348 self.pg1.set_table_ip4(0)
3349 self.pg2.set_table_ip4(0)
3350 self.pg1.config_ip4()
3351 self.pg2.config_ip4()
3352 self.pg1.resolve_arp()
3353 self.pg2.resolve_arp()
3355 def test_mss_clamping(self):
3356 """ NAT44EI TCP MSS clamping """
3357 self.nat44_add_address(self.nat_addr)
3358 flags = self.config_flags.NAT_IS_INSIDE
3359 self.vapi.nat44_interface_add_del_feature(
3360 sw_if_index=self.pg0.sw_if_index,
3361 flags=flags, is_add=1)
3362 self.vapi.nat44_interface_add_del_feature(
3363 sw_if_index=self.pg1.sw_if_index,
3366 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3367 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3368 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3369 flags="S", options=[('MSS', 1400)]))
3371 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3372 self.pg0.add_stream(p)
3373 self.pg_enable_capture(self.pg_interfaces)
3375 capture = self.pg1.get_capture(1)
3376 # Negotiated MSS value greater than configured - changed
3377 self.verify_mss_value(capture[0], 1000)
3379 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3380 self.pg0.add_stream(p)
3381 self.pg_enable_capture(self.pg_interfaces)
3383 capture = self.pg1.get_capture(1)
3384 # MSS clamping disabled - negotiated MSS unchanged
3385 self.verify_mss_value(capture[0], 1400)
3387 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3388 self.pg0.add_stream(p)
3389 self.pg_enable_capture(self.pg_interfaces)
3391 capture = self.pg1.get_capture(1)
3392 # Negotiated MSS value smaller than configured - unchanged
3393 self.verify_mss_value(capture[0], 1400)
3395 def test_ha_send(self):
3396 """ NAT44EI Send HA session synchronization events (active) """
3397 flags = self.config_flags.NAT_IS_INSIDE
3398 self.vapi.nat44_interface_add_del_feature(
3399 sw_if_index=self.pg0.sw_if_index,
3400 flags=flags, is_add=1)
3401 self.vapi.nat44_interface_add_del_feature(
3402 sw_if_index=self.pg1.sw_if_index,
3404 self.nat44_add_address(self.nat_addr)
3406 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3409 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3410 port=12346, session_refresh_interval=10)
3411 bind_layers(UDP, HANATStateSync, sport=12345)
3414 pkts = self.create_stream_in(self.pg0, self.pg1)
3415 self.pg0.add_stream(pkts)
3416 self.pg_enable_capture(self.pg_interfaces)
3418 capture = self.pg1.get_capture(len(pkts))
3419 self.verify_capture_out(capture)
3420 # active send HA events
3421 self.vapi.nat_ha_flush()
3422 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3423 self.assertEqual(stats[0][0], 3)
3424 capture = self.pg3.get_capture(1)
3426 self.assert_packet_checksums_valid(p)
3430 hanat = p[HANATStateSync]
3432 self.logger.error(ppp("Invalid packet:", p))
3435 self.assertEqual(ip.src, self.pg3.local_ip4)
3436 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3437 self.assertEqual(udp.sport, 12345)
3438 self.assertEqual(udp.dport, 12346)
3439 self.assertEqual(hanat.version, 1)
3440 self.assertEqual(hanat.thread_index, 0)
3441 self.assertEqual(hanat.count, 3)
3442 seq = hanat.sequence_number
3443 for event in hanat.events:
3444 self.assertEqual(event.event_type, 1)
3445 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3446 self.assertEqual(event.out_addr, self.nat_addr)
3447 self.assertEqual(event.fib_index, 0)
3449 # ACK received events
3450 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3451 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3452 UDP(sport=12346, dport=12345) /
3453 HANATStateSync(sequence_number=seq, flags='ACK'))
3454 self.pg3.add_stream(ack)
3456 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3457 self.assertEqual(stats[0][0], 1)
3459 # delete one session
3460 self.pg_enable_capture(self.pg_interfaces)
3461 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3462 port=self.tcp_port_in,
3463 protocol=IP_PROTOS.tcp,
3464 flags=self.config_flags.NAT_IS_INSIDE)
3465 self.vapi.nat_ha_flush()
3466 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3467 self.assertEqual(stats[0][0], 1)
3468 capture = self.pg3.get_capture(1)
3471 hanat = p[HANATStateSync]
3473 self.logger.error(ppp("Invalid packet:", p))
3476 self.assertGreater(hanat.sequence_number, seq)
3478 # do not send ACK, active retry send HA event again
3479 self.pg_enable_capture(self.pg_interfaces)
3481 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3482 self.assertEqual(stats[0][0], 3)
3483 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3484 self.assertEqual(stats[0][0], 1)
3485 capture = self.pg3.get_capture(3)
3486 for packet in capture:
3487 self.assertEqual(packet, p)
3489 # session counters refresh
3490 pkts = self.create_stream_out(self.pg1)
3491 self.pg1.add_stream(pkts)
3492 self.pg_enable_capture(self.pg_interfaces)
3494 self.pg0.get_capture(2)
3495 self.vapi.nat_ha_flush()
3496 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3497 self.assertEqual(stats[0][0], 2)
3498 capture = self.pg3.get_capture(1)
3500 self.assert_packet_checksums_valid(p)
3504 hanat = p[HANATStateSync]
3506 self.logger.error(ppp("Invalid packet:", p))
3509 self.assertEqual(ip.src, self.pg3.local_ip4)
3510 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3511 self.assertEqual(udp.sport, 12345)
3512 self.assertEqual(udp.dport, 12346)
3513 self.assertEqual(hanat.version, 1)
3514 self.assertEqual(hanat.count, 2)
3515 seq = hanat.sequence_number
3516 for event in hanat.events:
3517 self.assertEqual(event.event_type, 3)
3518 self.assertEqual(event.out_addr, self.nat_addr)
3519 self.assertEqual(event.fib_index, 0)
3520 self.assertEqual(event.total_pkts, 2)
3521 self.assertGreater(event.total_bytes, 0)
3523 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3524 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3525 UDP(sport=12346, dport=12345) /
3526 HANATStateSync(sequence_number=seq, flags='ACK'))
3527 self.pg3.add_stream(ack)
3529 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3530 self.assertEqual(stats[0][0], 2)
3532 def test_ha_recv(self):
3533 """ NAT44EI Receive HA session synchronization events (passive) """
3534 self.nat44_add_address(self.nat_addr)
3535 flags = self.config_flags.NAT_IS_INSIDE
3536 self.vapi.nat44_interface_add_del_feature(
3537 sw_if_index=self.pg0.sw_if_index,
3538 flags=flags, is_add=1)
3539 self.vapi.nat44_interface_add_del_feature(
3540 sw_if_index=self.pg1.sw_if_index,
3542 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3545 bind_layers(UDP, HANATStateSync, sport=12345)
3547 self.tcp_port_out = random.randint(1025, 65535)
3548 self.udp_port_out = random.randint(1025, 65535)
3550 # send HA session add events to failover/passive
3551 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3552 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3553 UDP(sport=12346, dport=12345) /
3554 HANATStateSync(sequence_number=1, events=[
3555 Event(event_type='add', protocol='tcp',
3556 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3557 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3558 eh_addr=self.pg1.remote_ip4,
3559 ehn_addr=self.pg1.remote_ip4,
3560 eh_port=self.tcp_external_port,
3561 ehn_port=self.tcp_external_port, fib_index=0),
3562 Event(event_type='add', protocol='udp',
3563 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3564 in_port=self.udp_port_in, out_port=self.udp_port_out,
3565 eh_addr=self.pg1.remote_ip4,
3566 ehn_addr=self.pg1.remote_ip4,
3567 eh_port=self.udp_external_port,
3568 ehn_port=self.udp_external_port, fib_index=0)]))
3570 self.pg3.add_stream(p)
3571 self.pg_enable_capture(self.pg_interfaces)
3574 capture = self.pg3.get_capture(1)
3577 hanat = p[HANATStateSync]
3579 self.logger.error(ppp("Invalid packet:", p))
3582 self.assertEqual(hanat.sequence_number, 1)
3583 self.assertEqual(hanat.flags, 'ACK')
3584 self.assertEqual(hanat.version, 1)
3585 self.assertEqual(hanat.thread_index, 0)
3586 stats = self.statistics.get_counter('/nat44/ha/ack-send')
3587 self.assertEqual(stats[0][0], 1)
3588 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
3589 self.assertEqual(stats[0][0], 2)
3590 users = self.statistics.get_counter('/nat44/total-users')
3591 self.assertEqual(users[0][0], 1)
3592 sessions = self.statistics.get_counter('/nat44/total-sessions')
3593 self.assertEqual(sessions[0][0], 2)
3594 users = self.vapi.nat44_user_dump()
3595 self.assertEqual(len(users), 1)
3596 self.assertEqual(str(users[0].ip_address),
3597 self.pg0.remote_ip4)
3598 # there should be 2 sessions created by HA
3599 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3601 self.assertEqual(len(sessions), 2)
3602 for session in sessions:
3603 self.assertEqual(str(session.inside_ip_address),
3604 self.pg0.remote_ip4)
3605 self.assertEqual(str(session.outside_ip_address),
3607 self.assertIn(session.inside_port,
3608 [self.tcp_port_in, self.udp_port_in])
3609 self.assertIn(session.outside_port,
3610 [self.tcp_port_out, self.udp_port_out])
3611 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3613 # send HA session delete event to failover/passive
3614 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3615 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3616 UDP(sport=12346, dport=12345) /
3617 HANATStateSync(sequence_number=2, events=[
3618 Event(event_type='del', protocol='udp',
3619 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3620 in_port=self.udp_port_in, out_port=self.udp_port_out,
3621 eh_addr=self.pg1.remote_ip4,
3622 ehn_addr=self.pg1.remote_ip4,
3623 eh_port=self.udp_external_port,
3624 ehn_port=self.udp_external_port, fib_index=0)]))
3626 self.pg3.add_stream(p)
3627 self.pg_enable_capture(self.pg_interfaces)
3630 capture = self.pg3.get_capture(1)
3633 hanat = p[HANATStateSync]
3635 self.logger.error(ppp("Invalid packet:", p))
3638 self.assertEqual(hanat.sequence_number, 2)
3639 self.assertEqual(hanat.flags, 'ACK')
3640 self.assertEqual(hanat.version, 1)
3641 users = self.vapi.nat44_user_dump()
3642 self.assertEqual(len(users), 1)
3643 self.assertEqual(str(users[0].ip_address),
3644 self.pg0.remote_ip4)
3645 # now we should have only 1 session, 1 deleted by HA
3646 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3648 self.assertEqual(len(sessions), 1)
3649 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
3650 self.assertEqual(stats[0][0], 1)
3652 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
3653 self.assertEqual(stats, 2)
3655 # send HA session refresh event to failover/passive
3656 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3657 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3658 UDP(sport=12346, dport=12345) /
3659 HANATStateSync(sequence_number=3, events=[
3660 Event(event_type='refresh', protocol='tcp',
3661 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3662 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3663 eh_addr=self.pg1.remote_ip4,
3664 ehn_addr=self.pg1.remote_ip4,
3665 eh_port=self.tcp_external_port,
3666 ehn_port=self.tcp_external_port, fib_index=0,
3667 total_bytes=1024, total_pkts=2)]))
3668 self.pg3.add_stream(p)
3669 self.pg_enable_capture(self.pg_interfaces)
3672 capture = self.pg3.get_capture(1)
3675 hanat = p[HANATStateSync]
3677 self.logger.error(ppp("Invalid packet:", p))
3680 self.assertEqual(hanat.sequence_number, 3)
3681 self.assertEqual(hanat.flags, 'ACK')
3682 self.assertEqual(hanat.version, 1)
3683 users = self.vapi.nat44_user_dump()
3684 self.assertEqual(len(users), 1)
3685 self.assertEqual(str(users[0].ip_address),
3686 self.pg0.remote_ip4)
3687 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3689 self.assertEqual(len(sessions), 1)
3690 session = sessions[0]
3691 self.assertEqual(session.total_bytes, 1024)
3692 self.assertEqual(session.total_pkts, 2)
3693 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
3694 self.assertEqual(stats[0][0], 1)
3696 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
3697 self.assertEqual(stats, 3)
3699 # send packet to test session created by HA
3700 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3701 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3702 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3703 self.pg1.add_stream(p)
3704 self.pg_enable_capture(self.pg_interfaces)
3706 capture = self.pg0.get_capture(1)
3712 self.logger.error(ppp("Invalid packet:", p))
3715 self.assertEqual(ip.src, self.pg1.remote_ip4)
3716 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3717 self.assertEqual(tcp.sport, self.tcp_external_port)
3718 self.assertEqual(tcp.dport, self.tcp_port_in)
3720 def show_commands_at_teardown(self):
3721 self.logger.info(self.vapi.cli("show nat44 addresses"))
3722 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3723 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3724 self.logger.info(self.vapi.cli("show nat44 interface address"))
3725 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3726 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
3727 self.logger.info(self.vapi.cli("show nat timeouts"))
3729 self.vapi.cli("show nat addr-port-assignment-alg"))
3730 self.logger.info(self.vapi.cli("show nat ha"))
3733 class TestNAT44Out2InDPO(MethodHolder):
3734 """ NAT44EI Test Cases using out2in DPO """
3737 def setUpClass(cls):
3738 super(TestNAT44Out2InDPO, cls).setUpClass()
3739 cls.vapi.cli("set log class nat level debug")
3741 cls.tcp_port_in = 6303
3742 cls.tcp_port_out = 6303
3743 cls.udp_port_in = 6304
3744 cls.udp_port_out = 6304
3745 cls.icmp_id_in = 6305
3746 cls.icmp_id_out = 6305
3747 cls.nat_addr = '10.0.0.3'
3748 cls.dst_ip4 = '192.168.70.1'
3750 cls.create_pg_interfaces(range(2))
3753 cls.pg0.config_ip4()
3754 cls.pg0.resolve_arp()
3757 cls.pg1.config_ip6()
3758 cls.pg1.resolve_ndp()
3760 r1 = VppIpRoute(cls, "::", 0,
3761 [VppRoutePath(cls.pg1.remote_ip6,
3762 cls.pg1.sw_if_index)],
3767 super(TestNAT44Out2InDPO, self).setUp()
3768 flags = self.nat44_config_flags.NAT44_API_IS_OUT2IN_DPO
3769 self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
3772 super(TestNAT44Out2InDPO, self).tearDown()
3773 if not self.vpp_dead:
3774 self.vapi.nat44_plugin_enable_disable(enable=0)
3775 self.vapi.cli("clear logging")
3777 def configure_xlat(self):
3778 self.dst_ip6_pfx = '1:2:3::'
3779 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3781 self.dst_ip6_pfx_len = 96
3782 self.src_ip6_pfx = '4:5:6::'
3783 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3785 self.src_ip6_pfx_len = 96
3786 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
3787 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
3788 '\x00\x00\x00\x00', 0)
3790 @unittest.skip('Temporary disabled')
3791 def test_464xlat_ce(self):
3792 """ Test 464XLAT CE with NAT44EI """
3794 nat_config = self.vapi.nat_show_config()
3795 self.assertEqual(1, nat_config.out2in_dpo)
3797 self.configure_xlat()
3799 flags = self.config_flags.NAT_IS_INSIDE
3800 self.vapi.nat44_interface_add_del_feature(
3801 sw_if_index=self.pg0.sw_if_index,
3802 flags=flags, is_add=1)
3803 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
3804 last_ip_address=self.nat_addr_n,
3805 vrf_id=0xFFFFFFFF, is_add=1)
3807 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3808 self.dst_ip6_pfx_len)
3809 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
3810 self.src_ip6_pfx_len)
3813 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3814 self.pg0.add_stream(pkts)
3815 self.pg_enable_capture(self.pg_interfaces)
3817 capture = self.pg1.get_capture(len(pkts))
3818 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
3821 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
3823 self.pg1.add_stream(pkts)
3824 self.pg_enable_capture(self.pg_interfaces)
3826 capture = self.pg0.get_capture(len(pkts))
3827 self.verify_capture_in(capture, self.pg0)
3829 self.vapi.nat44_interface_add_del_feature(
3830 sw_if_index=self.pg0.sw_if_index,
3832 self.vapi.nat44_add_del_address_range(
3833 first_ip_address=self.nat_addr_n,
3834 last_ip_address=self.nat_addr_n,
3837 @unittest.skip('Temporary disabled')
3838 def test_464xlat_ce_no_nat(self):
3839 """ Test 464XLAT CE without NAT44EI """
3841 self.configure_xlat()
3843 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3844 self.dst_ip6_pfx_len)
3845 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
3846 self.src_ip6_pfx_len)
3848 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3849 self.pg0.add_stream(pkts)
3850 self.pg_enable_capture(self.pg_interfaces)
3852 capture = self.pg1.get_capture(len(pkts))
3853 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
3854 nat_ip=out_dst_ip6, same_port=True)
3856 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
3857 self.pg1.add_stream(pkts)
3858 self.pg_enable_capture(self.pg_interfaces)
3860 capture = self.pg0.get_capture(len(pkts))
3861 self.verify_capture_in(capture, self.pg0)
3864 class TestNAT44EIMW(MethodHolder):
3865 """ NAT44EI Test Cases (multiple workers) """
3867 worker_config = "workers %d" % 2
3869 max_translations = 10240
3873 def setUpClass(cls):
3874 super(TestNAT44EIMW, cls).setUpClass()
3875 cls.vapi.cli("set log class nat level debug")
3877 cls.tcp_port_in = 6303
3878 cls.tcp_port_out = 6303
3879 cls.udp_port_in = 6304
3880 cls.udp_port_out = 6304
3881 cls.icmp_id_in = 6305
3882 cls.icmp_id_out = 6305
3883 cls.nat_addr = '10.0.0.3'
3884 cls.ipfix_src_port = 4739
3885 cls.ipfix_domain_id = 1
3886 cls.tcp_external_port = 80
3887 cls.udp_external_port = 69
3889 cls.create_pg_interfaces(range(10))
3890 cls.interfaces = list(cls.pg_interfaces[0:4])
3892 for i in cls.interfaces:
3897 cls.pg0.generate_remote_hosts(3)
3898 cls.pg0.configure_ipv4_neighbors()
3900 cls.pg1.generate_remote_hosts(1)
3901 cls.pg1.configure_ipv4_neighbors()
3903 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
3904 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
3905 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
3907 cls.pg4._local_ip4 = "172.16.255.1"
3908 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
3909 cls.pg4.set_table_ip4(10)
3910 cls.pg5._local_ip4 = "172.17.255.3"
3911 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
3912 cls.pg5.set_table_ip4(10)
3913 cls.pg6._local_ip4 = "172.16.255.1"
3914 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
3915 cls.pg6.set_table_ip4(20)
3916 for i in cls.overlapping_interfaces:
3924 cls.pg9.generate_remote_hosts(2)
3925 cls.pg9.config_ip4()
3926 cls.vapi.sw_interface_add_del_address(
3927 sw_if_index=cls.pg9.sw_if_index,
3928 prefix="10.0.0.1/24")
3931 cls.pg9.resolve_arp()
3932 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
3933 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
3934 cls.pg9.resolve_arp()
3937 super(TestNAT44EIMW, self).setUp()
3938 self.vapi.nat44_plugin_enable_disable(
3939 sessions=self.max_translations,
3940 users=self.max_users, enable=1)
3943 super(TestNAT44EIMW, self).tearDown()
3944 if not self.vpp_dead:
3945 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3946 src_port=self.ipfix_src_port,
3948 self.ipfix_src_port = 4739
3949 self.ipfix_domain_id = 1
3951 self.vapi.nat44_plugin_enable_disable(enable=0)
3952 self.vapi.cli("clear logging")
3954 def test_hairpinning(self):
3955 """ NAT44EI hairpinning - 1:1 NAPT """
3957 host = self.pg0.remote_hosts[0]
3958 server = self.pg0.remote_hosts[1]
3961 server_in_port = 5678
3962 server_out_port = 8765
3966 self.nat44_add_address(self.nat_addr)
3967 flags = self.config_flags.NAT_IS_INSIDE
3968 self.vapi.nat44_interface_add_del_feature(
3969 sw_if_index=self.pg0.sw_if_index,
3970 flags=flags, is_add=1)
3971 self.vapi.nat44_interface_add_del_feature(
3972 sw_if_index=self.pg1.sw_if_index,
3975 # add static mapping for server
3976 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3977 server_in_port, server_out_port,
3978 proto=IP_PROTOS.tcp)
3980 cnt = self.statistics.get_counter('/nat44/hairpinning')
3981 # send packet from host to server
3982 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3983 IP(src=host.ip4, dst=self.nat_addr) /
3984 TCP(sport=host_in_port, dport=server_out_port))
3985 self.pg0.add_stream(p)
3986 self.pg_enable_capture(self.pg_interfaces)
3988 capture = self.pg0.get_capture(1)
3993 self.assertEqual(ip.src, self.nat_addr)
3994 self.assertEqual(ip.dst, server.ip4)
3995 self.assertNotEqual(tcp.sport, host_in_port)
3996 self.assertEqual(tcp.dport, server_in_port)
3997 self.assert_packet_checksums_valid(p)
3998 host_out_port = tcp.sport
4000 self.logger.error(ppp("Unexpected or invalid packet:", p))
4003 after = self.statistics.get_counter('/nat44/hairpinning')
4005 if_idx = self.pg0.sw_if_index
4006 self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1)
4008 # send reply from server to host
4009 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4010 IP(src=server.ip4, dst=self.nat_addr) /
4011 TCP(sport=server_in_port, dport=host_out_port))
4012 self.pg0.add_stream(p)
4013 self.pg_enable_capture(self.pg_interfaces)
4015 capture = self.pg0.get_capture(1)
4020 self.assertEqual(ip.src, self.nat_addr)
4021 self.assertEqual(ip.dst, host.ip4)
4022 self.assertEqual(tcp.sport, server_out_port)
4023 self.assertEqual(tcp.dport, host_in_port)
4024 self.assert_packet_checksums_valid(p)
4026 self.logger.error(ppp("Unexpected or invalid packet:", p))
4029 after = self.statistics.get_counter('/nat44/hairpinning')
4030 if_idx = self.pg0.sw_if_index
4031 self.assertEqual(after[worker_1][if_idx] - cnt[worker_1][if_idx], 1)
4032 self.assertEqual(after[worker_2][if_idx] - cnt[worker_2][if_idx], 2)
4034 def test_hairpinning2(self):
4035 """ NAT44EI hairpinning - 1:1 NAT"""
4037 server1_nat_ip = "10.0.0.10"
4038 server2_nat_ip = "10.0.0.11"
4039 host = self.pg0.remote_hosts[0]
4040 server1 = self.pg0.remote_hosts[1]
4041 server2 = self.pg0.remote_hosts[2]
4042 server_tcp_port = 22
4043 server_udp_port = 20
4045 self.nat44_add_address(self.nat_addr)
4046 flags = self.config_flags.NAT_IS_INSIDE
4047 self.vapi.nat44_interface_add_del_feature(
4048 sw_if_index=self.pg0.sw_if_index,
4049 flags=flags, is_add=1)
4050 self.vapi.nat44_interface_add_del_feature(
4051 sw_if_index=self.pg1.sw_if_index,
4054 # add static mapping for servers
4055 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
4056 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
4060 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4061 IP(src=host.ip4, dst=server1_nat_ip) /
4062 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4064 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4065 IP(src=host.ip4, dst=server1_nat_ip) /
4066 UDP(sport=self.udp_port_in, dport=server_udp_port))
4068 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4069 IP(src=host.ip4, dst=server1_nat_ip) /
4070 ICMP(id=self.icmp_id_in, type='echo-request'))
4072 self.pg0.add_stream(pkts)
4073 self.pg_enable_capture(self.pg_interfaces)
4075 capture = self.pg0.get_capture(len(pkts))
4076 for packet in capture:
4078 self.assertEqual(packet[IP].src, self.nat_addr)
4079 self.assertEqual(packet[IP].dst, server1.ip4)
4080 if packet.haslayer(TCP):
4081 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
4082 self.assertEqual(packet[TCP].dport, server_tcp_port)
4083 self.tcp_port_out = packet[TCP].sport
4084 self.assert_packet_checksums_valid(packet)
4085 elif packet.haslayer(UDP):
4086 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
4087 self.assertEqual(packet[UDP].dport, server_udp_port)
4088 self.udp_port_out = packet[UDP].sport
4090 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
4091 self.icmp_id_out = packet[ICMP].id
4093 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4098 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4099 IP(src=server1.ip4, dst=self.nat_addr) /
4100 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4102 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4103 IP(src=server1.ip4, dst=self.nat_addr) /
4104 UDP(sport=server_udp_port, dport=self.udp_port_out))
4106 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4107 IP(src=server1.ip4, dst=self.nat_addr) /
4108 ICMP(id=self.icmp_id_out, type='echo-reply'))
4110 self.pg0.add_stream(pkts)
4111 self.pg_enable_capture(self.pg_interfaces)
4113 capture = self.pg0.get_capture(len(pkts))
4114 for packet in capture:
4116 self.assertEqual(packet[IP].src, server1_nat_ip)
4117 self.assertEqual(packet[IP].dst, host.ip4)
4118 if packet.haslayer(TCP):
4119 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4120 self.assertEqual(packet[TCP].sport, server_tcp_port)
4121 self.assert_packet_checksums_valid(packet)
4122 elif packet.haslayer(UDP):
4123 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4124 self.assertEqual(packet[UDP].sport, server_udp_port)
4126 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4128 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4131 # server2 to server1
4133 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4134 IP(src=server2.ip4, dst=server1_nat_ip) /
4135 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4137 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4138 IP(src=server2.ip4, dst=server1_nat_ip) /
4139 UDP(sport=self.udp_port_in, dport=server_udp_port))
4141 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4142 IP(src=server2.ip4, dst=server1_nat_ip) /
4143 ICMP(id=self.icmp_id_in, type='echo-request'))
4145 self.pg0.add_stream(pkts)
4146 self.pg_enable_capture(self.pg_interfaces)
4148 capture = self.pg0.get_capture(len(pkts))
4149 for packet in capture:
4151 self.assertEqual(packet[IP].src, server2_nat_ip)
4152 self.assertEqual(packet[IP].dst, server1.ip4)
4153 if packet.haslayer(TCP):
4154 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
4155 self.assertEqual(packet[TCP].dport, server_tcp_port)
4156 self.tcp_port_out = packet[TCP].sport
4157 self.assert_packet_checksums_valid(packet)
4158 elif packet.haslayer(UDP):
4159 self.assertEqual(packet[UDP].sport, self.udp_port_in)
4160 self.assertEqual(packet[UDP].dport, server_udp_port)
4161 self.udp_port_out = packet[UDP].sport
4163 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4164 self.icmp_id_out = packet[ICMP].id
4166 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4169 # server1 to server2
4171 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4172 IP(src=server1.ip4, dst=server2_nat_ip) /
4173 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4175 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4176 IP(src=server1.ip4, dst=server2_nat_ip) /
4177 UDP(sport=server_udp_port, dport=self.udp_port_out))
4179 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4180 IP(src=server1.ip4, dst=server2_nat_ip) /
4181 ICMP(id=self.icmp_id_out, type='echo-reply'))
4183 self.pg0.add_stream(pkts)
4184 self.pg_enable_capture(self.pg_interfaces)
4186 capture = self.pg0.get_capture(len(pkts))
4187 for packet in capture:
4189 self.assertEqual(packet[IP].src, server1_nat_ip)
4190 self.assertEqual(packet[IP].dst, server2.ip4)
4191 if packet.haslayer(TCP):
4192 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4193 self.assertEqual(packet[TCP].sport, server_tcp_port)
4194 self.assert_packet_checksums_valid(packet)
4195 elif packet.haslayer(UDP):
4196 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4197 self.assertEqual(packet[UDP].sport, server_udp_port)
4199 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4201 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4204 if __name__ == '__main__':
4205 unittest.main(testRunner=VppTestRunner)