12 from framework import VppTestCase, VppTestRunner, running_extended_tests
13 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
14 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
15 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
17 from scapy.data import IP_PROTOS
18 from scapy.layers.inet import IP, TCP, UDP, ICMP
19 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
20 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
21 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
22 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
23 from scapy.layers.l2 import Ether, ARP, GRE
24 from scapy.packet import Raw
25 from syslog_rfc5424_parser import SyslogMessage, ParseError
26 from syslog_rfc5424_parser.constants import SyslogSeverity
27 from util import ip4_range
28 from util import ppc, ppp
29 from vpp_acl import AclRule, VppAcl, VppAclInterface
30 from vpp_ip_route import VppIpRoute, VppRoutePath
31 from vpp_neighbor import VppNeighbor
32 from vpp_papi import VppEnum
35 # NAT HA protocol event data
38 fields_desc = [ByteEnumField("event_type", None,
39 {1: "add", 2: "del", 3: "refresh"}),
40 ByteEnumField("protocol", None,
41 {0: "other", 1: "udp", 2: "tcp", 3: "icmp"}),
42 ShortField("flags", 0),
43 IPField("in_addr", None),
44 IPField("out_addr", None),
45 ShortField("in_port", None),
46 ShortField("out_port", None),
47 IPField("eh_addr", None),
48 IPField("ehn_addr", None),
49 ShortField("eh_port", None),
50 ShortField("ehn_port", None),
51 IntField("fib_index", None),
52 IntField("total_pkts", 0),
53 LongField("total_bytes", 0)]
55 def extract_padding(self, s):
59 # NAT HA protocol header
60 class HANATStateSync(Packet):
61 name = "HA NAT state sync"
62 fields_desc = [XByteField("version", 1),
63 FlagsField("flags", 0, 8, ['ACK']),
64 FieldLenField("count", None, count_of="events"),
65 IntField("sequence_number", 1),
66 IntField("thread_index", 0),
67 PacketListField("events", [], Event,
68 count_from=lambda pkt: pkt.count)]
71 class MethodHolder(VppTestCase):
72 """ NAT create capture and verify method holder """
75 def config_flags(self):
76 return VppEnum.vl_api_nat_config_flags_t
79 def nat44_config_flags(self):
80 return VppEnum.vl_api_nat44_config_flags_t
83 def SYSLOG_SEVERITY(self):
84 return VppEnum.vl_api_syslog_severity_t
86 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
87 local_port=0, external_port=0, vrf_id=0,
88 is_add=1, external_sw_if_index=0xFFFFFFFF,
89 proto=0, tag="", flags=0):
91 Add/delete NAT44 static mapping
93 :param local_ip: Local IP address
94 :param external_ip: External IP address
95 :param local_port: Local port number (Optional)
96 :param external_port: External port number (Optional)
97 :param vrf_id: VRF ID (Default 0)
98 :param is_add: 1 if add, 0 if delete (Default add)
99 :param external_sw_if_index: External interface instead of IP address
100 :param proto: IP protocol (Mandatory if port specified)
101 :param tag: Opaque string tag
102 :param flags: NAT configuration flags
105 if not (local_port and external_port):
106 flags |= self.config_flags.NAT_IS_ADDR_ONLY
108 self.vapi.nat44_add_del_static_mapping(
110 local_ip_address=local_ip,
111 external_ip_address=external_ip,
112 external_sw_if_index=external_sw_if_index,
113 local_port=local_port,
114 external_port=external_port,
115 vrf_id=vrf_id, protocol=proto,
119 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
121 Add/delete NAT44 address
123 :param ip: IP address
124 :param is_add: 1 if add, 0 if delete (Default add)
125 :param twice_nat: twice NAT address for external hosts
127 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
128 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
134 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
136 Create packet stream for inside network
138 :param in_if: Inside interface
139 :param out_if: Outside interface
140 :param dst_ip: Destination address
141 :param ttl: TTL of generated packets
144 dst_ip = out_if.remote_ip4
148 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
149 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
150 TCP(sport=self.tcp_port_in, dport=20))
154 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
155 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
156 UDP(sport=self.udp_port_in, dport=20))
160 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
161 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
162 ICMP(id=self.icmp_id_in, type='echo-request'))
167 def compose_ip6(self, ip4, pref, plen):
169 Compose IPv4-embedded IPv6 addresses
171 :param ip4: IPv4 address
172 :param pref: IPv6 prefix
173 :param plen: IPv6 prefix length
174 :returns: IPv4-embedded IPv6 addresses
176 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
177 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
192 pref_n[10] = ip4_n[3]
196 pref_n[10] = ip4_n[2]
197 pref_n[11] = ip4_n[3]
200 pref_n[10] = ip4_n[1]
201 pref_n[11] = ip4_n[2]
202 pref_n[12] = ip4_n[3]
204 pref_n[12] = ip4_n[0]
205 pref_n[13] = ip4_n[1]
206 pref_n[14] = ip4_n[2]
207 pref_n[15] = ip4_n[3]
208 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
209 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
211 def extract_ip4(self, ip6, plen):
213 Extract IPv4 address embedded in IPv6 addresses
215 :param ip6: IPv6 address
216 :param plen: IPv6 prefix length
217 :returns: extracted IPv4 address
219 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
251 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
253 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
254 use_inside_ports=False):
256 Create packet stream for outside network
258 :param out_if: Outside interface
259 :param dst_ip: Destination IP address (Default use global NAT address)
260 :param ttl: TTL of generated packets
261 :param use_inside_ports: Use inside NAT ports as destination ports
262 instead of outside ports
265 dst_ip = self.nat_addr
266 if not use_inside_ports:
267 tcp_port = self.tcp_port_out
268 udp_port = self.udp_port_out
269 icmp_id = self.icmp_id_out
271 tcp_port = self.tcp_port_in
272 udp_port = self.udp_port_in
273 icmp_id = self.icmp_id_in
276 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
277 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
278 TCP(dport=tcp_port, sport=20))
282 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
283 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
284 UDP(dport=udp_port, sport=20))
288 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
289 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
290 ICMP(id=icmp_id, type='echo-reply'))
295 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
297 Create packet stream for outside network
299 :param out_if: Outside interface
300 :param dst_ip: Destination IP address (Default use global NAT address)
301 :param hl: HL of generated packets
305 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
306 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
307 TCP(dport=self.tcp_port_out, sport=20))
311 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
312 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
313 UDP(dport=self.udp_port_out, sport=20))
317 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
318 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
319 ICMPv6EchoReply(id=self.icmp_id_out))
324 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
325 dst_ip=None, is_ip6=False, ignore_port=False):
327 Verify captured packets on outside network
329 :param capture: Captured packets
330 :param nat_ip: Translated IP address (Default use global NAT address)
331 :param same_port: Source port number is not translated (Default False)
332 :param dst_ip: Destination IP address (Default do not verify)
333 :param is_ip6: If L3 protocol is IPv6 (Default False)
337 ICMP46 = ICMPv6EchoRequest
342 nat_ip = self.nat_addr
343 for packet in capture:
346 self.assert_packet_checksums_valid(packet)
347 self.assertEqual(packet[IP46].src, nat_ip)
348 if dst_ip is not None:
349 self.assertEqual(packet[IP46].dst, dst_ip)
350 if packet.haslayer(TCP):
354 packet[TCP].sport, self.tcp_port_in)
357 packet[TCP].sport, self.tcp_port_in)
358 self.tcp_port_out = packet[TCP].sport
359 self.assert_packet_checksums_valid(packet)
360 elif packet.haslayer(UDP):
364 packet[UDP].sport, self.udp_port_in)
367 packet[UDP].sport, self.udp_port_in)
368 self.udp_port_out = packet[UDP].sport
373 packet[ICMP46].id, self.icmp_id_in)
376 packet[ICMP46].id, self.icmp_id_in)
377 self.icmp_id_out = packet[ICMP46].id
378 self.assert_packet_checksums_valid(packet)
380 self.logger.error(ppp("Unexpected or invalid packet "
381 "(outside network):", packet))
384 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
387 Verify captured packets on outside network
389 :param capture: Captured packets
390 :param nat_ip: Translated IP address
391 :param same_port: Source port number is not translated (Default False)
392 :param dst_ip: Destination IP address (Default do not verify)
394 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
397 def verify_capture_in(self, capture, in_if):
399 Verify captured packets on inside network
401 :param capture: Captured packets
402 :param in_if: Inside interface
404 for packet in capture:
406 self.assert_packet_checksums_valid(packet)
407 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
408 if packet.haslayer(TCP):
409 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
410 elif packet.haslayer(UDP):
411 self.assertEqual(packet[UDP].dport, self.udp_port_in)
413 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
415 self.logger.error(ppp("Unexpected or invalid packet "
416 "(inside network):", packet))
419 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
421 Verify captured IPv6 packets on inside network
423 :param capture: Captured packets
424 :param src_ip: Source IP
425 :param dst_ip: Destination IP address
427 for packet in capture:
429 self.assertEqual(packet[IPv6].src, src_ip)
430 self.assertEqual(packet[IPv6].dst, dst_ip)
431 self.assert_packet_checksums_valid(packet)
432 if packet.haslayer(TCP):
433 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
434 elif packet.haslayer(UDP):
435 self.assertEqual(packet[UDP].dport, self.udp_port_in)
437 self.assertEqual(packet[ICMPv6EchoReply].id,
440 self.logger.error(ppp("Unexpected or invalid packet "
441 "(inside network):", packet))
444 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
446 Verify captured packet that don't have to be translated
448 :param capture: Captured packets
449 :param ingress_if: Ingress interface
450 :param egress_if: Egress interface
452 for packet in capture:
454 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
455 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
456 if packet.haslayer(TCP):
457 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
458 elif packet.haslayer(UDP):
459 self.assertEqual(packet[UDP].sport, self.udp_port_in)
461 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
463 self.logger.error(ppp("Unexpected or invalid packet "
464 "(inside network):", packet))
467 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
470 Verify captured packets with ICMP errors on outside network
472 :param capture: Captured packets
473 :param src_ip: Translated IP address or IP address of VPP
474 (Default use global NAT address)
475 :param icmp_type: Type of error ICMP packet
476 we are expecting (Default 11)
479 src_ip = self.nat_addr
480 for packet in capture:
482 self.assertEqual(packet[IP].src, src_ip)
483 self.assertEqual(packet.haslayer(ICMP), 1)
485 self.assertEqual(icmp.type, icmp_type)
486 self.assertTrue(icmp.haslayer(IPerror))
487 inner_ip = icmp[IPerror]
488 if inner_ip.haslayer(TCPerror):
489 self.assertEqual(inner_ip[TCPerror].dport,
491 elif inner_ip.haslayer(UDPerror):
492 self.assertEqual(inner_ip[UDPerror].dport,
495 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
497 self.logger.error(ppp("Unexpected or invalid packet "
498 "(outside network):", packet))
501 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
503 Verify captured packets with ICMP errors on inside network
505 :param capture: Captured packets
506 :param in_if: Inside interface
507 :param icmp_type: Type of error ICMP packet
508 we are expecting (Default 11)
510 for packet in capture:
512 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
513 self.assertEqual(packet.haslayer(ICMP), 1)
515 self.assertEqual(icmp.type, icmp_type)
516 self.assertTrue(icmp.haslayer(IPerror))
517 inner_ip = icmp[IPerror]
518 if inner_ip.haslayer(TCPerror):
519 self.assertEqual(inner_ip[TCPerror].sport,
521 elif inner_ip.haslayer(UDPerror):
522 self.assertEqual(inner_ip[UDPerror].sport,
525 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
527 self.logger.error(ppp("Unexpected or invalid packet "
528 "(inside network):", packet))
531 def create_stream_frag(self, src_if, dst, sport, dport, data,
532 proto=IP_PROTOS.tcp, echo_reply=False):
534 Create fragmented packet stream
536 :param src_if: Source interface
537 :param dst: Destination IPv4 address
538 :param sport: Source port
539 :param dport: Destination port
540 :param data: Payload data
541 :param proto: protocol (TCP, UDP, ICMP)
542 :param echo_reply: use echo_reply if protocol is ICMP
545 if proto == IP_PROTOS.tcp:
546 p = (IP(src=src_if.remote_ip4, dst=dst) /
547 TCP(sport=sport, dport=dport) /
549 p = p.__class__(scapy.compat.raw(p))
550 chksum = p[TCP].chksum
551 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
552 elif proto == IP_PROTOS.udp:
553 proto_header = UDP(sport=sport, dport=dport)
554 elif proto == IP_PROTOS.icmp:
556 proto_header = ICMP(id=sport, type='echo-request')
558 proto_header = ICMP(id=sport, type='echo-reply')
560 raise Exception("Unsupported protocol")
561 id = random.randint(0, 65535)
563 if proto == IP_PROTOS.tcp:
566 raw = Raw(data[0:16])
567 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
568 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
572 if proto == IP_PROTOS.tcp:
573 raw = Raw(data[4:20])
575 raw = Raw(data[16:32])
576 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
577 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
581 if proto == IP_PROTOS.tcp:
585 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
586 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
592 def reass_frags_and_verify(self, frags, src, dst):
594 Reassemble and verify fragmented packet
596 :param frags: Captured fragments
597 :param src: Source IPv4 address to verify
598 :param dst: Destination IPv4 address to verify
600 :returns: Reassembled IPv4 packet
604 self.assertEqual(p[IP].src, src)
605 self.assertEqual(p[IP].dst, dst)
606 self.assert_ip_checksum_valid(p)
607 buffer.seek(p[IP].frag * 8)
608 buffer.write(bytes(p[IP].payload))
609 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
610 proto=frags[0][IP].proto)
611 if ip.proto == IP_PROTOS.tcp:
612 p = (ip / TCP(buffer.getvalue()))
613 self.logger.debug(ppp("Reassembled:", p))
614 self.assert_tcp_checksum_valid(p)
615 elif ip.proto == IP_PROTOS.udp:
616 p = (ip / UDP(buffer.getvalue()[:8]) /
617 Raw(buffer.getvalue()[8:]))
618 elif ip.proto == IP_PROTOS.icmp:
619 p = (ip / ICMP(buffer.getvalue()))
622 def reass_frags_and_verify_ip6(self, frags, src, dst):
624 Reassemble and verify fragmented packet
626 :param frags: Captured fragments
627 :param src: Source IPv6 address to verify
628 :param dst: Destination IPv6 address to verify
630 :returns: Reassembled IPv6 packet
634 self.assertEqual(p[IPv6].src, src)
635 self.assertEqual(p[IPv6].dst, dst)
636 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
637 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
638 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
639 nh=frags[0][IPv6ExtHdrFragment].nh)
640 if ip.nh == IP_PROTOS.tcp:
641 p = (ip / TCP(buffer.getvalue()))
642 elif ip.nh == IP_PROTOS.udp:
643 p = (ip / UDP(buffer.getvalue()))
644 self.logger.debug(ppp("Reassembled:", p))
645 self.assert_packet_checksums_valid(p)
648 def initiate_tcp_session(self, in_if, out_if):
650 Initiates TCP session
652 :param in_if: Inside interface
653 :param out_if: Outside interface
657 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
658 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
659 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
662 self.pg_enable_capture(self.pg_interfaces)
664 capture = out_if.get_capture(1)
666 self.tcp_port_out = p[TCP].sport
668 # SYN + ACK packet out->in
669 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
670 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
671 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
674 self.pg_enable_capture(self.pg_interfaces)
679 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
680 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
681 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
684 self.pg_enable_capture(self.pg_interfaces)
686 out_if.get_capture(1)
689 self.logger.error("TCP 3 way handshake failed")
692 def verify_ipfix_nat44_ses(self, data):
694 Verify IPFIX NAT44 session create/delete event
696 :param data: Decoded IPFIX data records
698 nat44_ses_create_num = 0
699 nat44_ses_delete_num = 0
700 self.assertEqual(6, len(data))
703 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
704 if scapy.compat.orb(record[230]) == 4:
705 nat44_ses_create_num += 1
707 nat44_ses_delete_num += 1
709 self.assertEqual(self.pg0.remote_ip4,
710 str(ipaddress.IPv4Address(record[8])))
711 # postNATSourceIPv4Address
712 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
715 self.assertEqual(struct.pack("!I", 0), record[234])
716 # protocolIdentifier/sourceTransportPort
717 # /postNAPTSourceTransportPort
718 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
719 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
720 self.assertEqual(struct.pack("!H", self.icmp_id_out),
722 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
723 self.assertEqual(struct.pack("!H", self.tcp_port_in),
725 self.assertEqual(struct.pack("!H", self.tcp_port_out),
727 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
728 self.assertEqual(struct.pack("!H", self.udp_port_in),
730 self.assertEqual(struct.pack("!H", self.udp_port_out),
733 self.fail("Invalid protocol")
734 self.assertEqual(3, nat44_ses_create_num)
735 self.assertEqual(3, nat44_ses_delete_num)
737 def verify_ipfix_addr_exhausted(self, data):
739 Verify IPFIX NAT addresses event
741 :param data: Decoded IPFIX data records
743 self.assertEqual(1, len(data))
746 self.assertEqual(scapy.compat.orb(record[230]), 3)
748 self.assertEqual(struct.pack("!I", 0), record[283])
750 def verify_ipfix_max_sessions(self, data, limit):
752 Verify IPFIX maximum session entries exceeded event
754 :param data: Decoded IPFIX data records
755 :param limit: Number of maximum session entries that can be created.
757 self.assertEqual(1, len(data))
760 self.assertEqual(scapy.compat.orb(record[230]), 13)
761 # natQuotaExceededEvent
762 self.assertEqual(struct.pack("I", 1), record[466])
764 self.assertEqual(struct.pack("I", limit), record[471])
766 def verify_ipfix_max_bibs(self, data, limit):
768 Verify IPFIX maximum BIB entries exceeded event
770 :param data: Decoded IPFIX data records
771 :param limit: Number of maximum BIB entries that can be created.
773 self.assertEqual(1, len(data))
776 self.assertEqual(scapy.compat.orb(record[230]), 13)
777 # natQuotaExceededEvent
778 self.assertEqual(struct.pack("I", 2), record[466])
780 self.assertEqual(struct.pack("I", limit), record[472])
782 def verify_no_nat44_user(self):
783 """ Verify that there is no NAT44 user """
784 users = self.vapi.nat44_user_dump()
785 self.assertEqual(len(users), 0)
786 users = self.statistics.get_counter('/nat44/total-users')
787 self.assertEqual(users[0][0], 0)
788 sessions = self.statistics.get_counter('/nat44/total-sessions')
789 self.assertEqual(sessions[0][0], 0)
791 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
793 Verify IPFIX maximum entries per user exceeded event
795 :param data: Decoded IPFIX data records
796 :param limit: Number of maximum entries per user
797 :param src_addr: IPv4 source address
799 self.assertEqual(1, len(data))
802 self.assertEqual(scapy.compat.orb(record[230]), 13)
803 # natQuotaExceededEvent
804 self.assertEqual(struct.pack("I", 3), record[466])
806 self.assertEqual(struct.pack("I", limit), record[473])
808 self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
810 def verify_syslog_apmap(self, data, is_add=True):
811 message = data.decode('utf-8')
813 message = SyslogMessage.parse(message)
814 except ParseError as e:
818 self.assertEqual(message.severity, SyslogSeverity.info)
819 self.assertEqual(message.appname, 'NAT')
820 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
821 sd_params = message.sd.get('napmap')
822 self.assertTrue(sd_params is not None)
823 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
824 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
825 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
826 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
827 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
828 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
829 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
830 self.assertTrue(sd_params.get('SSUBIX') is not None)
831 self.assertEqual(sd_params.get('SVLAN'), '0')
833 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
834 message = data.decode('utf-8')
836 message = SyslogMessage.parse(message)
837 except ParseError as e:
841 self.assertEqual(message.severity, SyslogSeverity.info)
842 self.assertEqual(message.appname, 'NAT')
843 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
844 sd_params = message.sd.get('nsess')
845 self.assertTrue(sd_params is not None)
847 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
848 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
850 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
851 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
852 self.assertTrue(sd_params.get('SSUBIX') is not None)
853 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
854 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
855 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
856 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
857 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
858 self.assertEqual(sd_params.get('SVLAN'), '0')
859 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
860 self.assertEqual(sd_params.get('XDPORT'),
861 "%d" % self.tcp_external_port)
863 def verify_mss_value(self, pkt, mss):
870 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
871 raise TypeError("Not a TCP/IP packet")
873 for option in pkt[TCP].options:
874 if option[0] == 'MSS':
875 self.assertEqual(option[1], mss)
876 self.assert_tcp_checksum_valid(pkt)
879 def proto2layer(proto):
880 if proto == IP_PROTOS.tcp:
882 elif proto == IP_PROTOS.udp:
884 elif proto == IP_PROTOS.icmp:
887 raise Exception("Unsupported protocol")
889 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
891 layer = self.proto2layer(proto)
893 if proto == IP_PROTOS.tcp:
894 data = b"A" * 4 + b"B" * 16 + b"C" * 3
896 data = b"A" * 16 + b"B" * 16 + b"C" * 3
897 self.port_in = random.randint(1025, 65535)
900 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
901 self.port_in, 20, data, proto)
902 self.pg0.add_stream(pkts)
903 self.pg_enable_capture(self.pg_interfaces)
905 frags = self.pg1.get_capture(len(pkts))
906 if not dont_translate:
907 p = self.reass_frags_and_verify(frags,
911 p = self.reass_frags_and_verify(frags,
914 if proto != IP_PROTOS.icmp:
915 if not dont_translate:
916 self.assertEqual(p[layer].dport, 20)
918 self.assertNotEqual(p[layer].sport, self.port_in)
920 self.assertEqual(p[layer].sport, self.port_in)
923 if not dont_translate:
924 self.assertNotEqual(p[layer].id, self.port_in)
926 self.assertEqual(p[layer].id, self.port_in)
927 self.assertEqual(data, p[Raw].load)
930 if not dont_translate:
931 dst_addr = self.nat_addr
933 dst_addr = self.pg0.remote_ip4
934 if proto != IP_PROTOS.icmp:
936 dport = p[layer].sport
940 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
941 proto, echo_reply=True)
942 self.pg1.add_stream(pkts)
943 self.pg_enable_capture(self.pg_interfaces)
945 frags = self.pg0.get_capture(len(pkts))
946 p = self.reass_frags_and_verify(frags,
949 if proto != IP_PROTOS.icmp:
950 self.assertEqual(p[layer].sport, 20)
951 self.assertEqual(p[layer].dport, self.port_in)
953 self.assertEqual(p[layer].id, self.port_in)
954 self.assertEqual(data, p[Raw].load)
956 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
957 layer = self.proto2layer(proto)
959 if proto == IP_PROTOS.tcp:
960 data = b"A" * 4 + b"B" * 16 + b"C" * 3
962 data = b"A" * 16 + b"B" * 16 + b"C" * 3
963 self.port_in = random.randint(1025, 65535)
967 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
968 self.port_in, self.server_out_port,
970 self.pg0.add_stream(pkts)
971 self.pg_enable_capture(self.pg_interfaces)
973 frags = self.pg1.get_capture(len(pkts))
974 p = self.reass_frags_and_verify(frags,
977 if proto != IP_PROTOS.icmp:
978 self.assertEqual(p[layer].sport, self.port_in)
979 self.assertEqual(p[layer].dport, self.server_in_port)
981 self.assertEqual(p[layer].id, self.port_in)
982 self.assertEqual(data, p[Raw].load)
985 if proto != IP_PROTOS.icmp:
986 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
988 p[layer].sport, data, proto)
990 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
991 p[layer].id, 0, data, proto,
993 self.pg1.add_stream(pkts)
994 self.pg_enable_capture(self.pg_interfaces)
996 frags = self.pg0.get_capture(len(pkts))
997 p = self.reass_frags_and_verify(frags,
998 self.server_out_addr,
1000 if proto != IP_PROTOS.icmp:
1001 self.assertEqual(p[layer].sport, self.server_out_port)
1002 self.assertEqual(p[layer].dport, self.port_in)
1004 self.assertEqual(p[layer].id, self.port_in)
1005 self.assertEqual(data, p[Raw].load)
1007 def reass_hairpinning(self, proto=IP_PROTOS.tcp, ignore_port=False):
1008 layer = self.proto2layer(proto)
1010 if proto == IP_PROTOS.tcp:
1011 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1013 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1015 # send packet from host to server
1016 pkts = self.create_stream_frag(self.pg0,
1019 self.server_out_port,
1022 self.pg0.add_stream(pkts)
1023 self.pg_enable_capture(self.pg_interfaces)
1025 frags = self.pg0.get_capture(len(pkts))
1026 p = self.reass_frags_and_verify(frags,
1029 if proto != IP_PROTOS.icmp:
1031 self.assertNotEqual(p[layer].sport, self.host_in_port)
1032 self.assertEqual(p[layer].dport, self.server_in_port)
1035 self.assertNotEqual(p[layer].id, self.host_in_port)
1036 self.assertEqual(data, p[Raw].load)
1038 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
1040 layer = self.proto2layer(proto)
1042 if proto == IP_PROTOS.tcp:
1043 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1045 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1046 self.port_in = random.randint(1025, 65535)
1050 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1051 self.port_in, 20, data, proto)
1053 self.pg0.add_stream(pkts)
1054 self.pg_enable_capture(self.pg_interfaces)
1056 frags = self.pg1.get_capture(len(pkts))
1057 if not dont_translate:
1058 p = self.reass_frags_and_verify(frags,
1060 self.pg1.remote_ip4)
1062 p = self.reass_frags_and_verify(frags,
1063 self.pg0.remote_ip4,
1064 self.pg1.remote_ip4)
1065 if proto != IP_PROTOS.icmp:
1066 if not dont_translate:
1067 self.assertEqual(p[layer].dport, 20)
1069 self.assertNotEqual(p[layer].sport, self.port_in)
1071 self.assertEqual(p[layer].sport, self.port_in)
1074 if not dont_translate:
1075 self.assertNotEqual(p[layer].id, self.port_in)
1077 self.assertEqual(p[layer].id, self.port_in)
1078 self.assertEqual(data, p[Raw].load)
1081 if not dont_translate:
1082 dst_addr = self.nat_addr
1084 dst_addr = self.pg0.remote_ip4
1085 if proto != IP_PROTOS.icmp:
1087 dport = p[layer].sport
1091 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
1092 data, proto, echo_reply=True)
1094 self.pg1.add_stream(pkts)
1095 self.pg_enable_capture(self.pg_interfaces)
1097 frags = self.pg0.get_capture(len(pkts))
1098 p = self.reass_frags_and_verify(frags,
1099 self.pg1.remote_ip4,
1100 self.pg0.remote_ip4)
1101 if proto != IP_PROTOS.icmp:
1102 self.assertEqual(p[layer].sport, 20)
1103 self.assertEqual(p[layer].dport, self.port_in)
1105 self.assertEqual(p[layer].id, self.port_in)
1106 self.assertEqual(data, p[Raw].load)
1108 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1109 layer = self.proto2layer(proto)
1111 if proto == IP_PROTOS.tcp:
1112 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1114 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1115 self.port_in = random.randint(1025, 65535)
1119 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1120 self.port_in, self.server_out_port,
1123 self.pg0.add_stream(pkts)
1124 self.pg_enable_capture(self.pg_interfaces)
1126 frags = self.pg1.get_capture(len(pkts))
1127 p = self.reass_frags_and_verify(frags,
1128 self.pg0.remote_ip4,
1129 self.server_in_addr)
1130 if proto != IP_PROTOS.icmp:
1131 self.assertEqual(p[layer].dport, self.server_in_port)
1132 self.assertEqual(p[layer].sport, self.port_in)
1133 self.assertEqual(p[layer].dport, self.server_in_port)
1135 self.assertEqual(p[layer].id, self.port_in)
1136 self.assertEqual(data, p[Raw].load)
1139 if proto != IP_PROTOS.icmp:
1140 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1141 self.server_in_port,
1142 p[layer].sport, data, proto)
1144 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1145 p[layer].id, 0, data, proto,
1148 self.pg1.add_stream(pkts)
1149 self.pg_enable_capture(self.pg_interfaces)
1151 frags = self.pg0.get_capture(len(pkts))
1152 p = self.reass_frags_and_verify(frags,
1153 self.server_out_addr,
1154 self.pg0.remote_ip4)
1155 if proto != IP_PROTOS.icmp:
1156 self.assertEqual(p[layer].sport, self.server_out_port)
1157 self.assertEqual(p[layer].dport, self.port_in)
1159 self.assertEqual(p[layer].id, self.port_in)
1160 self.assertEqual(data, p[Raw].load)
1163 class TestNATMisc(MethodHolder):
1164 """ NAT misc Test Cases """
1166 max_translations = 10240
1170 super(TestNATMisc, self).setUp()
1171 self.vapi.nat44_plugin_enable_disable(
1172 sessions=self.max_translations,
1173 users=self.max_users, enable=1)
1176 super(TestNATMisc, self).tearDown()
1177 if not self.vpp_dead:
1178 self.vapi.nat44_plugin_enable_disable(enable=0)
1179 self.vapi.cli("clear logging")
1181 def test_show_max_translations(self):
1182 """ API test - max translations per thread """
1183 nat_config = self.vapi.nat_show_config_2()
1184 self.assertEqual(self.max_translations,
1185 nat_config.max_translations_per_thread)
1188 class TestNAT44(MethodHolder):
1189 """ NAT44 Test Cases """
1191 max_translations = 10240
1195 def setUpClass(cls):
1196 super(TestNAT44, cls).setUpClass()
1197 cls.vapi.cli("set log class nat level debug")
1199 cls.tcp_port_in = 6303
1200 cls.tcp_port_out = 6303
1201 cls.udp_port_in = 6304
1202 cls.udp_port_out = 6304
1203 cls.icmp_id_in = 6305
1204 cls.icmp_id_out = 6305
1205 cls.nat_addr = '10.0.0.3'
1206 cls.ipfix_src_port = 4739
1207 cls.ipfix_domain_id = 1
1208 cls.tcp_external_port = 80
1209 cls.udp_external_port = 69
1211 cls.create_pg_interfaces(range(10))
1212 cls.interfaces = list(cls.pg_interfaces[0:4])
1214 for i in cls.interfaces:
1219 cls.pg0.generate_remote_hosts(3)
1220 cls.pg0.configure_ipv4_neighbors()
1222 cls.pg1.generate_remote_hosts(1)
1223 cls.pg1.configure_ipv4_neighbors()
1225 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1226 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1227 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1229 cls.pg4._local_ip4 = "172.16.255.1"
1230 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1231 cls.pg4.set_table_ip4(10)
1232 cls.pg5._local_ip4 = "172.17.255.3"
1233 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1234 cls.pg5.set_table_ip4(10)
1235 cls.pg6._local_ip4 = "172.16.255.1"
1236 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1237 cls.pg6.set_table_ip4(20)
1238 for i in cls.overlapping_interfaces:
1246 cls.pg9.generate_remote_hosts(2)
1247 cls.pg9.config_ip4()
1248 cls.vapi.sw_interface_add_del_address(
1249 sw_if_index=cls.pg9.sw_if_index,
1250 prefix="10.0.0.1/24")
1253 cls.pg9.resolve_arp()
1254 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1255 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1256 cls.pg9.resolve_arp()
1259 super(TestNAT44, self).setUp()
1260 self.vapi.nat44_plugin_enable_disable(
1261 sessions=self.max_translations,
1262 users=self.max_users, enable=1)
1265 def tearDownClass(cls):
1266 super(TestNAT44, cls).tearDownClass()
1269 super(TestNAT44, self).tearDown()
1270 if not self.vpp_dead:
1271 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
1272 src_port=self.ipfix_src_port,
1274 self.ipfix_src_port = 4739
1275 self.ipfix_domain_id = 1
1277 self.vapi.nat44_plugin_enable_disable(enable=0)
1278 self.vapi.cli("clear logging")
1280 def test_clear_sessions(self):
1281 """ NAT44 session clearing test """
1283 self.nat44_add_address(self.nat_addr)
1284 flags = self.config_flags.NAT_IS_INSIDE
1285 self.vapi.nat44_interface_add_del_feature(
1286 sw_if_index=self.pg0.sw_if_index,
1287 flags=flags, is_add=1)
1288 self.vapi.nat44_interface_add_del_feature(
1289 sw_if_index=self.pg1.sw_if_index,
1292 nat_config = self.vapi.nat_show_config()
1293 self.assertEqual(0, nat_config.endpoint_dependent)
1295 pkts = self.create_stream_in(self.pg0, self.pg1)
1296 self.pg0.add_stream(pkts)
1297 self.pg_enable_capture(self.pg_interfaces)
1299 capture = self.pg1.get_capture(len(pkts))
1300 self.verify_capture_out(capture)
1302 sessions = self.statistics.get_counter('/nat44/total-sessions')
1303 self.assertTrue(sessions[0][0] > 0)
1304 self.logger.info("sessions before clearing: %s" % sessions[0][0])
1306 self.vapi.cli("clear nat44 sessions")
1308 sessions = self.statistics.get_counter('/nat44/total-sessions')
1309 self.assertEqual(sessions[0][0], 0)
1310 self.logger.info("sessions after clearing: %s" % sessions[0][0])
1312 def test_dynamic(self):
1313 """ NAT44 dynamic translation test """
1314 self.nat44_add_address(self.nat_addr)
1315 flags = self.config_flags.NAT_IS_INSIDE
1316 self.vapi.nat44_interface_add_del_feature(
1317 sw_if_index=self.pg0.sw_if_index,
1318 flags=flags, is_add=1)
1319 self.vapi.nat44_interface_add_del_feature(
1320 sw_if_index=self.pg1.sw_if_index,
1324 tcpn = self.statistics.get_counter('/nat44/in2out/slowpath/tcp')[0]
1325 udpn = self.statistics.get_counter('/nat44/in2out/slowpath/udp')[0]
1326 icmpn = self.statistics.get_counter('/nat44/in2out/slowpath/icmp')[0]
1327 drops = self.statistics.get_counter('/nat44/in2out/slowpath/drops')[0]
1329 pkts = self.create_stream_in(self.pg0, self.pg1)
1330 self.pg0.add_stream(pkts)
1331 self.pg_enable_capture(self.pg_interfaces)
1333 capture = self.pg1.get_capture(len(pkts))
1334 self.verify_capture_out(capture)
1336 if_idx = self.pg0.sw_if_index
1337 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/tcp')[0]
1338 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1339 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/udp')[0]
1340 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1341 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/icmp')[0]
1342 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1343 cnt = self.statistics.get_counter('/nat44/in2out/slowpath/drops')[0]
1344 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1347 tcpn = self.statistics.get_counter('/nat44/out2in/slowpath/tcp')[0]
1348 udpn = self.statistics.get_counter('/nat44/out2in/slowpath/udp')[0]
1349 icmpn = self.statistics.get_counter('/nat44/out2in/slowpath/icmp')[0]
1350 drops = self.statistics.get_counter('/nat44/out2in/slowpath/drops')[0]
1352 pkts = self.create_stream_out(self.pg1)
1353 self.pg1.add_stream(pkts)
1354 self.pg_enable_capture(self.pg_interfaces)
1356 capture = self.pg0.get_capture(len(pkts))
1357 self.verify_capture_in(capture, self.pg0)
1359 if_idx = self.pg1.sw_if_index
1360 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/tcp')[0]
1361 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1362 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/udp')[0]
1363 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1364 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/icmp')[0]
1365 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1366 cnt = self.statistics.get_counter('/nat44/out2in/slowpath/drops')[0]
1367 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1369 users = self.statistics.get_counter('/nat44/total-users')
1370 self.assertEqual(users[0][0], 1)
1371 sessions = self.statistics.get_counter('/nat44/total-sessions')
1372 self.assertEqual(sessions[0][0], 3)
1374 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1375 """ NAT44 handling of client packets with TTL=1 """
1377 self.nat44_add_address(self.nat_addr)
1378 flags = self.config_flags.NAT_IS_INSIDE
1379 self.vapi.nat44_interface_add_del_feature(
1380 sw_if_index=self.pg0.sw_if_index,
1381 flags=flags, is_add=1)
1382 self.vapi.nat44_interface_add_del_feature(
1383 sw_if_index=self.pg1.sw_if_index,
1386 # Client side - generate traffic
1387 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1388 self.pg0.add_stream(pkts)
1389 self.pg_enable_capture(self.pg_interfaces)
1392 # Client side - verify ICMP type 11 packets
1393 capture = self.pg0.get_capture(len(pkts))
1394 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1396 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1397 """ NAT44 handling of server packets with TTL=1 """
1399 self.nat44_add_address(self.nat_addr)
1400 flags = self.config_flags.NAT_IS_INSIDE
1401 self.vapi.nat44_interface_add_del_feature(
1402 sw_if_index=self.pg0.sw_if_index,
1403 flags=flags, is_add=1)
1404 self.vapi.nat44_interface_add_del_feature(
1405 sw_if_index=self.pg1.sw_if_index,
1408 # Client side - create sessions
1409 pkts = self.create_stream_in(self.pg0, self.pg1)
1410 self.pg0.add_stream(pkts)
1411 self.pg_enable_capture(self.pg_interfaces)
1414 # Server side - generate traffic
1415 capture = self.pg1.get_capture(len(pkts))
1416 self.verify_capture_out(capture)
1417 pkts = self.create_stream_out(self.pg1, ttl=1)
1418 self.pg1.add_stream(pkts)
1419 self.pg_enable_capture(self.pg_interfaces)
1422 # Server side - verify ICMP type 11 packets
1423 capture = self.pg1.get_capture(len(pkts))
1424 self.verify_capture_out_with_icmp_errors(capture,
1425 src_ip=self.pg1.local_ip4)
1427 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1428 """ NAT44 handling of error responses to client packets with TTL=2 """
1430 self.nat44_add_address(self.nat_addr)
1431 flags = self.config_flags.NAT_IS_INSIDE
1432 self.vapi.nat44_interface_add_del_feature(
1433 sw_if_index=self.pg0.sw_if_index,
1434 flags=flags, is_add=1)
1435 self.vapi.nat44_interface_add_del_feature(
1436 sw_if_index=self.pg1.sw_if_index,
1439 # Client side - generate traffic
1440 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1441 self.pg0.add_stream(pkts)
1442 self.pg_enable_capture(self.pg_interfaces)
1445 # Server side - simulate ICMP type 11 response
1446 capture = self.pg1.get_capture(len(pkts))
1447 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1448 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1449 ICMP(type=11) / packet[IP] for packet in capture]
1450 self.pg1.add_stream(pkts)
1451 self.pg_enable_capture(self.pg_interfaces)
1454 # Client side - verify ICMP type 11 packets
1455 capture = self.pg0.get_capture(len(pkts))
1456 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1458 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1459 """ NAT44 handling of error responses to server packets with TTL=2 """
1461 self.nat44_add_address(self.nat_addr)
1462 flags = self.config_flags.NAT_IS_INSIDE
1463 self.vapi.nat44_interface_add_del_feature(
1464 sw_if_index=self.pg0.sw_if_index,
1465 flags=flags, is_add=1)
1466 self.vapi.nat44_interface_add_del_feature(
1467 sw_if_index=self.pg1.sw_if_index,
1470 # Client side - create sessions
1471 pkts = self.create_stream_in(self.pg0, self.pg1)
1472 self.pg0.add_stream(pkts)
1473 self.pg_enable_capture(self.pg_interfaces)
1476 # Server side - generate traffic
1477 capture = self.pg1.get_capture(len(pkts))
1478 self.verify_capture_out(capture)
1479 pkts = self.create_stream_out(self.pg1, ttl=2)
1480 self.pg1.add_stream(pkts)
1481 self.pg_enable_capture(self.pg_interfaces)
1484 # Client side - simulate ICMP type 11 response
1485 capture = self.pg0.get_capture(len(pkts))
1486 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1487 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1488 ICMP(type=11) / packet[IP] for packet in capture]
1489 self.pg0.add_stream(pkts)
1490 self.pg_enable_capture(self.pg_interfaces)
1493 # Server side - verify ICMP type 11 packets
1494 capture = self.pg1.get_capture(len(pkts))
1495 self.verify_capture_out_with_icmp_errors(capture)
1497 def test_ping_out_interface_from_outside(self):
1498 """ Ping NAT44 out interface from outside network """
1500 self.nat44_add_address(self.nat_addr)
1501 flags = self.config_flags.NAT_IS_INSIDE
1502 self.vapi.nat44_interface_add_del_feature(
1503 sw_if_index=self.pg0.sw_if_index,
1504 flags=flags, is_add=1)
1505 self.vapi.nat44_interface_add_del_feature(
1506 sw_if_index=self.pg1.sw_if_index,
1509 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1510 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1511 ICMP(id=self.icmp_id_out, type='echo-request'))
1513 self.pg1.add_stream(pkts)
1514 self.pg_enable_capture(self.pg_interfaces)
1516 capture = self.pg1.get_capture(len(pkts))
1519 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1520 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1521 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1522 self.assertEqual(packet[ICMP].type, 0) # echo reply
1524 self.logger.error(ppp("Unexpected or invalid packet "
1525 "(outside network):", packet))
1528 def test_ping_internal_host_from_outside(self):
1529 """ Ping internal host from outside network """
1531 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1532 flags = self.config_flags.NAT_IS_INSIDE
1533 self.vapi.nat44_interface_add_del_feature(
1534 sw_if_index=self.pg0.sw_if_index,
1535 flags=flags, is_add=1)
1536 self.vapi.nat44_interface_add_del_feature(
1537 sw_if_index=self.pg1.sw_if_index,
1541 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1542 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1543 ICMP(id=self.icmp_id_out, type='echo-request'))
1544 self.pg1.add_stream(pkt)
1545 self.pg_enable_capture(self.pg_interfaces)
1547 capture = self.pg0.get_capture(1)
1548 self.verify_capture_in(capture, self.pg0)
1549 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1552 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1553 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1554 ICMP(id=self.icmp_id_in, type='echo-reply'))
1555 self.pg0.add_stream(pkt)
1556 self.pg_enable_capture(self.pg_interfaces)
1558 capture = self.pg1.get_capture(1)
1559 self.verify_capture_out(capture, same_port=True)
1560 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1562 def test_forwarding(self):
1563 """ NAT44 forwarding test """
1565 flags = self.config_flags.NAT_IS_INSIDE
1566 self.vapi.nat44_interface_add_del_feature(
1567 sw_if_index=self.pg0.sw_if_index,
1568 flags=flags, is_add=1)
1569 self.vapi.nat44_interface_add_del_feature(
1570 sw_if_index=self.pg1.sw_if_index,
1572 self.vapi.nat44_forwarding_enable_disable(enable=1)
1574 real_ip = self.pg0.remote_ip4
1575 alias_ip = self.nat_addr
1576 flags = self.config_flags.NAT_IS_ADDR_ONLY
1577 self.vapi.nat44_add_del_static_mapping(is_add=1,
1578 local_ip_address=real_ip,
1579 external_ip_address=alias_ip,
1580 external_sw_if_index=0xFFFFFFFF,
1584 # static mapping match
1586 pkts = self.create_stream_out(self.pg1)
1587 self.pg1.add_stream(pkts)
1588 self.pg_enable_capture(self.pg_interfaces)
1590 capture = self.pg0.get_capture(len(pkts))
1591 self.verify_capture_in(capture, self.pg0)
1593 pkts = self.create_stream_in(self.pg0, self.pg1)
1594 self.pg0.add_stream(pkts)
1595 self.pg_enable_capture(self.pg_interfaces)
1597 capture = self.pg1.get_capture(len(pkts))
1598 self.verify_capture_out(capture, same_port=True)
1600 # no static mapping match
1602 host0 = self.pg0.remote_hosts[0]
1603 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1605 pkts = self.create_stream_out(self.pg1,
1606 dst_ip=self.pg0.remote_ip4,
1607 use_inside_ports=True)
1608 self.pg1.add_stream(pkts)
1609 self.pg_enable_capture(self.pg_interfaces)
1611 capture = self.pg0.get_capture(len(pkts))
1612 self.verify_capture_in(capture, self.pg0)
1614 pkts = self.create_stream_in(self.pg0, self.pg1)
1615 self.pg0.add_stream(pkts)
1616 self.pg_enable_capture(self.pg_interfaces)
1618 capture = self.pg1.get_capture(len(pkts))
1619 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1622 self.pg0.remote_hosts[0] = host0
1625 self.vapi.nat44_forwarding_enable_disable(enable=0)
1626 flags = self.config_flags.NAT_IS_ADDR_ONLY
1627 self.vapi.nat44_add_del_static_mapping(
1629 local_ip_address=real_ip,
1630 external_ip_address=alias_ip,
1631 external_sw_if_index=0xFFFFFFFF,
1634 def test_static_in(self):
1635 """ 1:1 NAT initialized from inside network """
1637 nat_ip = "10.0.0.10"
1638 self.tcp_port_out = 6303
1639 self.udp_port_out = 6304
1640 self.icmp_id_out = 6305
1642 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1643 flags = self.config_flags.NAT_IS_INSIDE
1644 self.vapi.nat44_interface_add_del_feature(
1645 sw_if_index=self.pg0.sw_if_index,
1646 flags=flags, is_add=1)
1647 self.vapi.nat44_interface_add_del_feature(
1648 sw_if_index=self.pg1.sw_if_index,
1650 sm = self.vapi.nat44_static_mapping_dump()
1651 self.assertEqual(len(sm), 1)
1652 self.assertEqual(sm[0].tag, '')
1653 self.assertEqual(sm[0].protocol, 0)
1654 self.assertEqual(sm[0].local_port, 0)
1655 self.assertEqual(sm[0].external_port, 0)
1658 pkts = self.create_stream_in(self.pg0, self.pg1)
1659 self.pg0.add_stream(pkts)
1660 self.pg_enable_capture(self.pg_interfaces)
1662 capture = self.pg1.get_capture(len(pkts))
1663 self.verify_capture_out(capture, nat_ip, True)
1666 pkts = self.create_stream_out(self.pg1, nat_ip)
1667 self.pg1.add_stream(pkts)
1668 self.pg_enable_capture(self.pg_interfaces)
1670 capture = self.pg0.get_capture(len(pkts))
1671 self.verify_capture_in(capture, self.pg0)
1673 def test_static_out(self):
1674 """ 1:1 NAT initialized from outside network """
1676 nat_ip = "10.0.0.20"
1677 self.tcp_port_out = 6303
1678 self.udp_port_out = 6304
1679 self.icmp_id_out = 6305
1682 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1683 flags = self.config_flags.NAT_IS_INSIDE
1684 self.vapi.nat44_interface_add_del_feature(
1685 sw_if_index=self.pg0.sw_if_index,
1686 flags=flags, is_add=1)
1687 self.vapi.nat44_interface_add_del_feature(
1688 sw_if_index=self.pg1.sw_if_index,
1690 sm = self.vapi.nat44_static_mapping_dump()
1691 self.assertEqual(len(sm), 1)
1692 self.assertEqual(sm[0].tag, tag)
1695 pkts = self.create_stream_out(self.pg1, nat_ip)
1696 self.pg1.add_stream(pkts)
1697 self.pg_enable_capture(self.pg_interfaces)
1699 capture = self.pg0.get_capture(len(pkts))
1700 self.verify_capture_in(capture, self.pg0)
1703 pkts = self.create_stream_in(self.pg0, self.pg1)
1704 self.pg0.add_stream(pkts)
1705 self.pg_enable_capture(self.pg_interfaces)
1707 capture = self.pg1.get_capture(len(pkts))
1708 self.verify_capture_out(capture, nat_ip, True)
1710 def test_static_with_port_in(self):
1711 """ 1:1 NAPT initialized from inside network """
1713 self.tcp_port_out = 3606
1714 self.udp_port_out = 3607
1715 self.icmp_id_out = 3608
1717 self.nat44_add_address(self.nat_addr)
1718 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1719 self.tcp_port_in, self.tcp_port_out,
1720 proto=IP_PROTOS.tcp)
1721 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1722 self.udp_port_in, self.udp_port_out,
1723 proto=IP_PROTOS.udp)
1724 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1725 self.icmp_id_in, self.icmp_id_out,
1726 proto=IP_PROTOS.icmp)
1727 flags = self.config_flags.NAT_IS_INSIDE
1728 self.vapi.nat44_interface_add_del_feature(
1729 sw_if_index=self.pg0.sw_if_index,
1730 flags=flags, is_add=1)
1731 self.vapi.nat44_interface_add_del_feature(
1732 sw_if_index=self.pg1.sw_if_index,
1736 pkts = self.create_stream_in(self.pg0, self.pg1)
1737 self.pg0.add_stream(pkts)
1738 self.pg_enable_capture(self.pg_interfaces)
1740 capture = self.pg1.get_capture(len(pkts))
1741 self.verify_capture_out(capture)
1744 pkts = self.create_stream_out(self.pg1)
1745 self.pg1.add_stream(pkts)
1746 self.pg_enable_capture(self.pg_interfaces)
1748 capture = self.pg0.get_capture(len(pkts))
1749 self.verify_capture_in(capture, self.pg0)
1751 def test_static_with_port_out(self):
1752 """ 1:1 NAPT initialized from outside network """
1754 self.tcp_port_out = 30606
1755 self.udp_port_out = 30607
1756 self.icmp_id_out = 30608
1758 self.nat44_add_address(self.nat_addr)
1759 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1760 self.tcp_port_in, self.tcp_port_out,
1761 proto=IP_PROTOS.tcp)
1762 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1763 self.udp_port_in, self.udp_port_out,
1764 proto=IP_PROTOS.udp)
1765 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1766 self.icmp_id_in, self.icmp_id_out,
1767 proto=IP_PROTOS.icmp)
1768 flags = self.config_flags.NAT_IS_INSIDE
1769 self.vapi.nat44_interface_add_del_feature(
1770 sw_if_index=self.pg0.sw_if_index,
1771 flags=flags, is_add=1)
1772 self.vapi.nat44_interface_add_del_feature(
1773 sw_if_index=self.pg1.sw_if_index,
1777 pkts = self.create_stream_out(self.pg1)
1778 self.pg1.add_stream(pkts)
1779 self.pg_enable_capture(self.pg_interfaces)
1781 capture = self.pg0.get_capture(len(pkts))
1782 self.verify_capture_in(capture, self.pg0)
1785 pkts = self.create_stream_in(self.pg0, self.pg1)
1786 self.pg0.add_stream(pkts)
1787 self.pg_enable_capture(self.pg_interfaces)
1789 capture = self.pg1.get_capture(len(pkts))
1790 self.verify_capture_out(capture)
1792 def test_static_vrf_aware(self):
1793 """ 1:1 NAT VRF awareness """
1795 nat_ip1 = "10.0.0.30"
1796 nat_ip2 = "10.0.0.40"
1797 self.tcp_port_out = 6303
1798 self.udp_port_out = 6304
1799 self.icmp_id_out = 6305
1801 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1803 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1805 flags = self.config_flags.NAT_IS_INSIDE
1806 self.vapi.nat44_interface_add_del_feature(
1807 sw_if_index=self.pg3.sw_if_index,
1809 self.vapi.nat44_interface_add_del_feature(
1810 sw_if_index=self.pg0.sw_if_index,
1811 flags=flags, is_add=1)
1812 self.vapi.nat44_interface_add_del_feature(
1813 sw_if_index=self.pg4.sw_if_index,
1814 flags=flags, is_add=1)
1816 # inside interface VRF match NAT44 static mapping VRF
1817 pkts = self.create_stream_in(self.pg4, self.pg3)
1818 self.pg4.add_stream(pkts)
1819 self.pg_enable_capture(self.pg_interfaces)
1821 capture = self.pg3.get_capture(len(pkts))
1822 self.verify_capture_out(capture, nat_ip1, True)
1824 # inside interface VRF don't match NAT44 static mapping VRF (packets
1826 pkts = self.create_stream_in(self.pg0, self.pg3)
1827 self.pg0.add_stream(pkts)
1828 self.pg_enable_capture(self.pg_interfaces)
1830 self.pg3.assert_nothing_captured()
1832 def test_dynamic_to_static(self):
1833 """ Switch from dynamic translation to 1:1NAT """
1834 nat_ip = "10.0.0.10"
1835 self.tcp_port_out = 6303
1836 self.udp_port_out = 6304
1837 self.icmp_id_out = 6305
1839 self.nat44_add_address(self.nat_addr)
1840 flags = self.config_flags.NAT_IS_INSIDE
1841 self.vapi.nat44_interface_add_del_feature(
1842 sw_if_index=self.pg0.sw_if_index,
1843 flags=flags, is_add=1)
1844 self.vapi.nat44_interface_add_del_feature(
1845 sw_if_index=self.pg1.sw_if_index,
1849 pkts = self.create_stream_in(self.pg0, self.pg1)
1850 self.pg0.add_stream(pkts)
1851 self.pg_enable_capture(self.pg_interfaces)
1853 capture = self.pg1.get_capture(len(pkts))
1854 self.verify_capture_out(capture)
1857 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1858 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
1859 self.assertEqual(len(sessions), 0)
1860 pkts = self.create_stream_in(self.pg0, self.pg1)
1861 self.pg0.add_stream(pkts)
1862 self.pg_enable_capture(self.pg_interfaces)
1864 capture = self.pg1.get_capture(len(pkts))
1865 self.verify_capture_out(capture, nat_ip, True)
1867 def test_identity_nat(self):
1868 """ Identity NAT """
1869 flags = self.config_flags.NAT_IS_ADDR_ONLY
1870 self.vapi.nat44_add_del_identity_mapping(
1871 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1872 flags=flags, is_add=1)
1873 flags = self.config_flags.NAT_IS_INSIDE
1874 self.vapi.nat44_interface_add_del_feature(
1875 sw_if_index=self.pg0.sw_if_index,
1876 flags=flags, is_add=1)
1877 self.vapi.nat44_interface_add_del_feature(
1878 sw_if_index=self.pg1.sw_if_index,
1881 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1882 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1883 TCP(sport=12345, dport=56789))
1884 self.pg1.add_stream(p)
1885 self.pg_enable_capture(self.pg_interfaces)
1887 capture = self.pg0.get_capture(1)
1892 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1893 self.assertEqual(ip.src, self.pg1.remote_ip4)
1894 self.assertEqual(tcp.dport, 56789)
1895 self.assertEqual(tcp.sport, 12345)
1896 self.assert_packet_checksums_valid(p)
1898 self.logger.error(ppp("Unexpected or invalid packet:", p))
1901 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
1902 self.assertEqual(len(sessions), 0)
1903 flags = self.config_flags.NAT_IS_ADDR_ONLY
1904 self.vapi.nat44_add_del_identity_mapping(
1905 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1906 flags=flags, vrf_id=1, is_add=1)
1907 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1908 self.assertEqual(len(identity_mappings), 2)
1910 def test_multiple_inside_interfaces(self):
1911 """ NAT44 multiple non-overlapping address space inside interfaces """
1913 self.nat44_add_address(self.nat_addr)
1914 flags = self.config_flags.NAT_IS_INSIDE
1915 self.vapi.nat44_interface_add_del_feature(
1916 sw_if_index=self.pg0.sw_if_index,
1917 flags=flags, is_add=1)
1918 self.vapi.nat44_interface_add_del_feature(
1919 sw_if_index=self.pg1.sw_if_index,
1920 flags=flags, is_add=1)
1921 self.vapi.nat44_interface_add_del_feature(
1922 sw_if_index=self.pg3.sw_if_index,
1925 # between two NAT44 inside interfaces (no translation)
1926 pkts = self.create_stream_in(self.pg0, self.pg1)
1927 self.pg0.add_stream(pkts)
1928 self.pg_enable_capture(self.pg_interfaces)
1930 capture = self.pg1.get_capture(len(pkts))
1931 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1933 # from NAT44 inside to interface without NAT44 feature (no translation)
1934 pkts = self.create_stream_in(self.pg0, self.pg2)
1935 self.pg0.add_stream(pkts)
1936 self.pg_enable_capture(self.pg_interfaces)
1938 capture = self.pg2.get_capture(len(pkts))
1939 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1941 # in2out 1st interface
1942 pkts = self.create_stream_in(self.pg0, self.pg3)
1943 self.pg0.add_stream(pkts)
1944 self.pg_enable_capture(self.pg_interfaces)
1946 capture = self.pg3.get_capture(len(pkts))
1947 self.verify_capture_out(capture)
1949 # out2in 1st interface
1950 pkts = self.create_stream_out(self.pg3)
1951 self.pg3.add_stream(pkts)
1952 self.pg_enable_capture(self.pg_interfaces)
1954 capture = self.pg0.get_capture(len(pkts))
1955 self.verify_capture_in(capture, self.pg0)
1957 # in2out 2nd interface
1958 pkts = self.create_stream_in(self.pg1, self.pg3)
1959 self.pg1.add_stream(pkts)
1960 self.pg_enable_capture(self.pg_interfaces)
1962 capture = self.pg3.get_capture(len(pkts))
1963 self.verify_capture_out(capture)
1965 # out2in 2nd interface
1966 pkts = self.create_stream_out(self.pg3)
1967 self.pg3.add_stream(pkts)
1968 self.pg_enable_capture(self.pg_interfaces)
1970 capture = self.pg1.get_capture(len(pkts))
1971 self.verify_capture_in(capture, self.pg1)
1973 def test_inside_overlapping_interfaces(self):
1974 """ NAT44 multiple inside interfaces with overlapping address space """
1976 static_nat_ip = "10.0.0.10"
1977 self.nat44_add_address(self.nat_addr)
1978 flags = self.config_flags.NAT_IS_INSIDE
1979 self.vapi.nat44_interface_add_del_feature(
1980 sw_if_index=self.pg3.sw_if_index,
1982 self.vapi.nat44_interface_add_del_feature(
1983 sw_if_index=self.pg4.sw_if_index,
1984 flags=flags, is_add=1)
1985 self.vapi.nat44_interface_add_del_feature(
1986 sw_if_index=self.pg5.sw_if_index,
1987 flags=flags, is_add=1)
1988 self.vapi.nat44_interface_add_del_feature(
1989 sw_if_index=self.pg6.sw_if_index,
1990 flags=flags, is_add=1)
1991 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1994 # between NAT44 inside interfaces with same VRF (no translation)
1995 pkts = self.create_stream_in(self.pg4, self.pg5)
1996 self.pg4.add_stream(pkts)
1997 self.pg_enable_capture(self.pg_interfaces)
1999 capture = self.pg5.get_capture(len(pkts))
2000 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2002 # between NAT44 inside interfaces with different VRF (hairpinning)
2003 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2004 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2005 TCP(sport=1234, dport=5678))
2006 self.pg4.add_stream(p)
2007 self.pg_enable_capture(self.pg_interfaces)
2009 capture = self.pg6.get_capture(1)
2014 self.assertEqual(ip.src, self.nat_addr)
2015 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2016 self.assertNotEqual(tcp.sport, 1234)
2017 self.assertEqual(tcp.dport, 5678)
2019 self.logger.error(ppp("Unexpected or invalid packet:", p))
2022 # in2out 1st interface
2023 pkts = self.create_stream_in(self.pg4, self.pg3)
2024 self.pg4.add_stream(pkts)
2025 self.pg_enable_capture(self.pg_interfaces)
2027 capture = self.pg3.get_capture(len(pkts))
2028 self.verify_capture_out(capture)
2030 # out2in 1st interface
2031 pkts = self.create_stream_out(self.pg3)
2032 self.pg3.add_stream(pkts)
2033 self.pg_enable_capture(self.pg_interfaces)
2035 capture = self.pg4.get_capture(len(pkts))
2036 self.verify_capture_in(capture, self.pg4)
2038 # in2out 2nd interface
2039 pkts = self.create_stream_in(self.pg5, self.pg3)
2040 self.pg5.add_stream(pkts)
2041 self.pg_enable_capture(self.pg_interfaces)
2043 capture = self.pg3.get_capture(len(pkts))
2044 self.verify_capture_out(capture)
2046 # out2in 2nd interface
2047 pkts = self.create_stream_out(self.pg3)
2048 self.pg3.add_stream(pkts)
2049 self.pg_enable_capture(self.pg_interfaces)
2051 capture = self.pg5.get_capture(len(pkts))
2052 self.verify_capture_in(capture, self.pg5)
2055 addresses = self.vapi.nat44_address_dump()
2056 self.assertEqual(len(addresses), 1)
2057 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2058 self.assertEqual(len(sessions), 3)
2059 for session in sessions:
2060 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2061 self.assertEqual(str(session.inside_ip_address),
2062 self.pg5.remote_ip4)
2063 self.assertEqual(session.outside_ip_address,
2064 addresses[0].ip_address)
2065 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2066 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2067 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2068 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2069 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2070 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2071 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2072 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2073 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2075 # in2out 3rd interface
2076 pkts = self.create_stream_in(self.pg6, self.pg3)
2077 self.pg6.add_stream(pkts)
2078 self.pg_enable_capture(self.pg_interfaces)
2080 capture = self.pg3.get_capture(len(pkts))
2081 self.verify_capture_out(capture, static_nat_ip, True)
2083 # out2in 3rd interface
2084 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2085 self.pg3.add_stream(pkts)
2086 self.pg_enable_capture(self.pg_interfaces)
2088 capture = self.pg6.get_capture(len(pkts))
2089 self.verify_capture_in(capture, self.pg6)
2091 # general user and session dump verifications
2092 users = self.vapi.nat44_user_dump()
2093 self.assertGreaterEqual(len(users), 3)
2094 addresses = self.vapi.nat44_address_dump()
2095 self.assertEqual(len(addresses), 1)
2097 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2099 for session in sessions:
2100 self.assertEqual(user.ip_address, session.inside_ip_address)
2101 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2102 self.assertTrue(session.protocol in
2103 [IP_PROTOS.tcp, IP_PROTOS.udp,
2105 self.assertFalse(session.flags &
2106 self.config_flags.NAT_IS_EXT_HOST_VALID)
2109 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2110 self.assertGreaterEqual(len(sessions), 4)
2111 for session in sessions:
2112 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2113 self.assertEqual(str(session.inside_ip_address),
2114 self.pg4.remote_ip4)
2115 self.assertEqual(session.outside_ip_address,
2116 addresses[0].ip_address)
2119 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2120 self.assertGreaterEqual(len(sessions), 3)
2121 for session in sessions:
2122 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2123 self.assertEqual(str(session.inside_ip_address),
2124 self.pg6.remote_ip4)
2125 self.assertEqual(str(session.outside_ip_address),
2127 self.assertTrue(session.inside_port in
2128 [self.tcp_port_in, self.udp_port_in,
2131 def test_hairpinning(self):
2132 """ NAT44 hairpinning - 1:1 NAPT """
2134 host = self.pg0.remote_hosts[0]
2135 server = self.pg0.remote_hosts[1]
2138 server_in_port = 5678
2139 server_out_port = 8765
2141 self.nat44_add_address(self.nat_addr)
2142 flags = self.config_flags.NAT_IS_INSIDE
2143 self.vapi.nat44_interface_add_del_feature(
2144 sw_if_index=self.pg0.sw_if_index,
2145 flags=flags, is_add=1)
2146 self.vapi.nat44_interface_add_del_feature(
2147 sw_if_index=self.pg1.sw_if_index,
2150 # add static mapping for server
2151 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2152 server_in_port, server_out_port,
2153 proto=IP_PROTOS.tcp)
2155 cnt = self.statistics.get_counter('/nat44/hairpinning')[0]
2156 # send packet from host to server
2157 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2158 IP(src=host.ip4, dst=self.nat_addr) /
2159 TCP(sport=host_in_port, dport=server_out_port))
2160 self.pg0.add_stream(p)
2161 self.pg_enable_capture(self.pg_interfaces)
2163 capture = self.pg0.get_capture(1)
2168 self.assertEqual(ip.src, self.nat_addr)
2169 self.assertEqual(ip.dst, server.ip4)
2170 self.assertNotEqual(tcp.sport, host_in_port)
2171 self.assertEqual(tcp.dport, server_in_port)
2172 self.assert_packet_checksums_valid(p)
2173 host_out_port = tcp.sport
2175 self.logger.error(ppp("Unexpected or invalid packet:", p))
2178 after = self.statistics.get_counter('/nat44/hairpinning')[0]
2179 if_idx = self.pg0.sw_if_index
2180 self.assertEqual(after[if_idx] - cnt[if_idx], 1)
2182 # send reply from server to host
2183 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2184 IP(src=server.ip4, dst=self.nat_addr) /
2185 TCP(sport=server_in_port, dport=host_out_port))
2186 self.pg0.add_stream(p)
2187 self.pg_enable_capture(self.pg_interfaces)
2189 capture = self.pg0.get_capture(1)
2194 self.assertEqual(ip.src, self.nat_addr)
2195 self.assertEqual(ip.dst, host.ip4)
2196 self.assertEqual(tcp.sport, server_out_port)
2197 self.assertEqual(tcp.dport, host_in_port)
2198 self.assert_packet_checksums_valid(p)
2200 self.logger.error(ppp("Unexpected or invalid packet:", p))
2203 after = self.statistics.get_counter('/nat44/hairpinning')[0]
2204 if_idx = self.pg0.sw_if_index
2205 self.assertEqual(after[if_idx] - cnt[if_idx], 2)
2207 def test_hairpinning2(self):
2208 """ NAT44 hairpinning - 1:1 NAT"""
2210 server1_nat_ip = "10.0.0.10"
2211 server2_nat_ip = "10.0.0.11"
2212 host = self.pg0.remote_hosts[0]
2213 server1 = self.pg0.remote_hosts[1]
2214 server2 = self.pg0.remote_hosts[2]
2215 server_tcp_port = 22
2216 server_udp_port = 20
2218 self.nat44_add_address(self.nat_addr)
2219 flags = self.config_flags.NAT_IS_INSIDE
2220 self.vapi.nat44_interface_add_del_feature(
2221 sw_if_index=self.pg0.sw_if_index,
2222 flags=flags, is_add=1)
2223 self.vapi.nat44_interface_add_del_feature(
2224 sw_if_index=self.pg1.sw_if_index,
2227 # add static mapping for servers
2228 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2229 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2233 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2234 IP(src=host.ip4, dst=server1_nat_ip) /
2235 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2237 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2238 IP(src=host.ip4, dst=server1_nat_ip) /
2239 UDP(sport=self.udp_port_in, dport=server_udp_port))
2241 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2242 IP(src=host.ip4, dst=server1_nat_ip) /
2243 ICMP(id=self.icmp_id_in, type='echo-request'))
2245 self.pg0.add_stream(pkts)
2246 self.pg_enable_capture(self.pg_interfaces)
2248 capture = self.pg0.get_capture(len(pkts))
2249 for packet in capture:
2251 self.assertEqual(packet[IP].src, self.nat_addr)
2252 self.assertEqual(packet[IP].dst, server1.ip4)
2253 if packet.haslayer(TCP):
2254 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2255 self.assertEqual(packet[TCP].dport, server_tcp_port)
2256 self.tcp_port_out = packet[TCP].sport
2257 self.assert_packet_checksums_valid(packet)
2258 elif packet.haslayer(UDP):
2259 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2260 self.assertEqual(packet[UDP].dport, server_udp_port)
2261 self.udp_port_out = packet[UDP].sport
2263 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2264 self.icmp_id_out = packet[ICMP].id
2266 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2272 IP(src=server1.ip4, dst=self.nat_addr) /
2273 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2275 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2276 IP(src=server1.ip4, dst=self.nat_addr) /
2277 UDP(sport=server_udp_port, dport=self.udp_port_out))
2279 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2280 IP(src=server1.ip4, dst=self.nat_addr) /
2281 ICMP(id=self.icmp_id_out, type='echo-reply'))
2283 self.pg0.add_stream(pkts)
2284 self.pg_enable_capture(self.pg_interfaces)
2286 capture = self.pg0.get_capture(len(pkts))
2287 for packet in capture:
2289 self.assertEqual(packet[IP].src, server1_nat_ip)
2290 self.assertEqual(packet[IP].dst, host.ip4)
2291 if packet.haslayer(TCP):
2292 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2293 self.assertEqual(packet[TCP].sport, server_tcp_port)
2294 self.assert_packet_checksums_valid(packet)
2295 elif packet.haslayer(UDP):
2296 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2297 self.assertEqual(packet[UDP].sport, server_udp_port)
2299 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2301 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2304 # server2 to server1
2306 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2307 IP(src=server2.ip4, dst=server1_nat_ip) /
2308 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2310 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2311 IP(src=server2.ip4, dst=server1_nat_ip) /
2312 UDP(sport=self.udp_port_in, dport=server_udp_port))
2314 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2315 IP(src=server2.ip4, dst=server1_nat_ip) /
2316 ICMP(id=self.icmp_id_in, type='echo-request'))
2318 self.pg0.add_stream(pkts)
2319 self.pg_enable_capture(self.pg_interfaces)
2321 capture = self.pg0.get_capture(len(pkts))
2322 for packet in capture:
2324 self.assertEqual(packet[IP].src, server2_nat_ip)
2325 self.assertEqual(packet[IP].dst, server1.ip4)
2326 if packet.haslayer(TCP):
2327 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2328 self.assertEqual(packet[TCP].dport, server_tcp_port)
2329 self.tcp_port_out = packet[TCP].sport
2330 self.assert_packet_checksums_valid(packet)
2331 elif packet.haslayer(UDP):
2332 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2333 self.assertEqual(packet[UDP].dport, server_udp_port)
2334 self.udp_port_out = packet[UDP].sport
2336 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2337 self.icmp_id_out = packet[ICMP].id
2339 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2342 # server1 to server2
2344 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2345 IP(src=server1.ip4, dst=server2_nat_ip) /
2346 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2348 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2349 IP(src=server1.ip4, dst=server2_nat_ip) /
2350 UDP(sport=server_udp_port, dport=self.udp_port_out))
2352 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2353 IP(src=server1.ip4, dst=server2_nat_ip) /
2354 ICMP(id=self.icmp_id_out, type='echo-reply'))
2356 self.pg0.add_stream(pkts)
2357 self.pg_enable_capture(self.pg_interfaces)
2359 capture = self.pg0.get_capture(len(pkts))
2360 for packet in capture:
2362 self.assertEqual(packet[IP].src, server1_nat_ip)
2363 self.assertEqual(packet[IP].dst, server2.ip4)
2364 if packet.haslayer(TCP):
2365 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2366 self.assertEqual(packet[TCP].sport, server_tcp_port)
2367 self.assert_packet_checksums_valid(packet)
2368 elif packet.haslayer(UDP):
2369 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2370 self.assertEqual(packet[UDP].sport, server_udp_port)
2372 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2374 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2377 def test_hairpinning_avoid_inf_loop(self):
2378 """ NAT44 hairpinning - 1:1 NAPT avoid infinite loop """
2380 host = self.pg0.remote_hosts[0]
2381 server = self.pg0.remote_hosts[1]
2384 server_in_port = 5678
2385 server_out_port = 8765
2387 self.nat44_add_address(self.nat_addr)
2388 flags = self.config_flags.NAT_IS_INSIDE
2389 self.vapi.nat44_interface_add_del_feature(
2390 sw_if_index=self.pg0.sw_if_index,
2391 flags=flags, is_add=1)
2392 self.vapi.nat44_interface_add_del_feature(
2393 sw_if_index=self.pg1.sw_if_index,
2396 # add static mapping for server
2397 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2398 server_in_port, server_out_port,
2399 proto=IP_PROTOS.tcp)
2401 # add another static mapping that maps pg0.local_ip4 address to itself
2402 self.nat44_add_static_mapping(self.pg0.local_ip4, self.pg0.local_ip4)
2404 # send packet from host to VPP (the packet should get dropped)
2405 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2406 IP(src=host.ip4, dst=self.pg0.local_ip4) /
2407 TCP(sport=host_in_port, dport=server_out_port))
2408 self.pg0.add_stream(p)
2409 self.pg_enable_capture(self.pg_interfaces)
2411 # Here VPP used to crash due to an infinite loop
2413 cnt = self.statistics.get_counter('/nat44/hairpinning')[0]
2414 # send packet from host to server
2415 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2416 IP(src=host.ip4, dst=self.nat_addr) /
2417 TCP(sport=host_in_port, dport=server_out_port))
2418 self.pg0.add_stream(p)
2419 self.pg_enable_capture(self.pg_interfaces)
2421 capture = self.pg0.get_capture(1)
2426 self.assertEqual(ip.src, self.nat_addr)
2427 self.assertEqual(ip.dst, server.ip4)
2428 self.assertNotEqual(tcp.sport, host_in_port)
2429 self.assertEqual(tcp.dport, server_in_port)
2430 self.assert_packet_checksums_valid(p)
2431 host_out_port = tcp.sport
2433 self.logger.error(ppp("Unexpected or invalid packet:", p))
2436 after = self.statistics.get_counter('/nat44/hairpinning')[0]
2437 if_idx = self.pg0.sw_if_index
2438 self.assertEqual(after[if_idx] - cnt[if_idx], 1)
2440 # send reply from server to host
2441 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2442 IP(src=server.ip4, dst=self.nat_addr) /
2443 TCP(sport=server_in_port, dport=host_out_port))
2444 self.pg0.add_stream(p)
2445 self.pg_enable_capture(self.pg_interfaces)
2447 capture = self.pg0.get_capture(1)
2452 self.assertEqual(ip.src, self.nat_addr)
2453 self.assertEqual(ip.dst, host.ip4)
2454 self.assertEqual(tcp.sport, server_out_port)
2455 self.assertEqual(tcp.dport, host_in_port)
2456 self.assert_packet_checksums_valid(p)
2458 self.logger.error(ppp("Unexpected or invalid packet:", p))
2461 after = self.statistics.get_counter('/nat44/hairpinning')[0]
2462 if_idx = self.pg0.sw_if_index
2463 self.assertEqual(after[if_idx] - cnt[if_idx], 2)
2465 def test_interface_addr(self):
2466 """ Acquire NAT44 addresses from interface """
2467 self.vapi.nat44_add_del_interface_addr(
2469 sw_if_index=self.pg7.sw_if_index)
2471 # no address in NAT pool
2472 addresses = self.vapi.nat44_address_dump()
2473 self.assertEqual(0, len(addresses))
2475 # configure interface address and check NAT address pool
2476 self.pg7.config_ip4()
2477 addresses = self.vapi.nat44_address_dump()
2478 self.assertEqual(1, len(addresses))
2479 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2481 # remove interface address and check NAT address pool
2482 self.pg7.unconfig_ip4()
2483 addresses = self.vapi.nat44_address_dump()
2484 self.assertEqual(0, len(addresses))
2486 def test_interface_addr_static_mapping(self):
2487 """ Static mapping with addresses from interface """
2490 self.vapi.nat44_add_del_interface_addr(
2492 sw_if_index=self.pg7.sw_if_index)
2493 self.nat44_add_static_mapping(
2495 external_sw_if_index=self.pg7.sw_if_index,
2498 # static mappings with external interface
2499 static_mappings = self.vapi.nat44_static_mapping_dump()
2500 self.assertEqual(1, len(static_mappings))
2501 self.assertEqual(self.pg7.sw_if_index,
2502 static_mappings[0].external_sw_if_index)
2503 self.assertEqual(static_mappings[0].tag, tag)
2505 # configure interface address and check static mappings
2506 self.pg7.config_ip4()
2507 static_mappings = self.vapi.nat44_static_mapping_dump()
2508 self.assertEqual(2, len(static_mappings))
2510 for sm in static_mappings:
2511 if sm.external_sw_if_index == 0xFFFFFFFF:
2512 self.assertEqual(str(sm.external_ip_address),
2514 self.assertEqual(sm.tag, tag)
2516 self.assertTrue(resolved)
2518 # remove interface address and check static mappings
2519 self.pg7.unconfig_ip4()
2520 static_mappings = self.vapi.nat44_static_mapping_dump()
2521 self.assertEqual(1, len(static_mappings))
2522 self.assertEqual(self.pg7.sw_if_index,
2523 static_mappings[0].external_sw_if_index)
2524 self.assertEqual(static_mappings[0].tag, tag)
2526 # configure interface address again and check static mappings
2527 self.pg7.config_ip4()
2528 static_mappings = self.vapi.nat44_static_mapping_dump()
2529 self.assertEqual(2, len(static_mappings))
2531 for sm in static_mappings:
2532 if sm.external_sw_if_index == 0xFFFFFFFF:
2533 self.assertEqual(str(sm.external_ip_address),
2535 self.assertEqual(sm.tag, tag)
2537 self.assertTrue(resolved)
2539 # remove static mapping
2540 self.nat44_add_static_mapping(
2542 external_sw_if_index=self.pg7.sw_if_index,
2545 static_mappings = self.vapi.nat44_static_mapping_dump()
2546 self.assertEqual(0, len(static_mappings))
2548 def test_interface_addr_identity_nat(self):
2549 """ Identity NAT with addresses from interface """
2552 self.vapi.nat44_add_del_interface_addr(
2554 sw_if_index=self.pg7.sw_if_index)
2555 self.vapi.nat44_add_del_identity_mapping(
2557 sw_if_index=self.pg7.sw_if_index,
2559 protocol=IP_PROTOS.tcp,
2562 # identity mappings with external interface
2563 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2564 self.assertEqual(1, len(identity_mappings))
2565 self.assertEqual(self.pg7.sw_if_index,
2566 identity_mappings[0].sw_if_index)
2568 # configure interface address and check identity mappings
2569 self.pg7.config_ip4()
2570 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2572 self.assertEqual(2, len(identity_mappings))
2573 for sm in identity_mappings:
2574 if sm.sw_if_index == 0xFFFFFFFF:
2575 self.assertEqual(str(identity_mappings[0].ip_address),
2577 self.assertEqual(port, identity_mappings[0].port)
2578 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2580 self.assertTrue(resolved)
2582 # remove interface address and check identity mappings
2583 self.pg7.unconfig_ip4()
2584 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2585 self.assertEqual(1, len(identity_mappings))
2586 self.assertEqual(self.pg7.sw_if_index,
2587 identity_mappings[0].sw_if_index)
2589 def test_ipfix_nat44_sess(self):
2590 """ IPFIX logging NAT44 session created/deleted """
2591 self.ipfix_domain_id = 10
2592 self.ipfix_src_port = 20202
2593 collector_port = 30303
2594 bind_layers(UDP, IPFIX, dport=30303)
2595 self.nat44_add_address(self.nat_addr)
2596 flags = self.config_flags.NAT_IS_INSIDE
2597 self.vapi.nat44_interface_add_del_feature(
2598 sw_if_index=self.pg0.sw_if_index,
2599 flags=flags, is_add=1)
2600 self.vapi.nat44_interface_add_del_feature(
2601 sw_if_index=self.pg1.sw_if_index,
2603 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2604 src_address=self.pg3.local_ip4,
2606 template_interval=10,
2607 collector_port=collector_port)
2608 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2609 src_port=self.ipfix_src_port,
2612 pkts = self.create_stream_in(self.pg0, self.pg1)
2613 self.pg0.add_stream(pkts)
2614 self.pg_enable_capture(self.pg_interfaces)
2616 capture = self.pg1.get_capture(len(pkts))
2617 self.verify_capture_out(capture)
2618 self.nat44_add_address(self.nat_addr, is_add=0)
2619 self.vapi.ipfix_flush()
2620 capture = self.pg3.get_capture(7)
2621 ipfix = IPFIXDecoder()
2622 # first load template
2624 self.assertTrue(p.haslayer(IPFIX))
2625 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2626 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2627 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2628 self.assertEqual(p[UDP].dport, collector_port)
2629 self.assertEqual(p[IPFIX].observationDomainID,
2630 self.ipfix_domain_id)
2631 if p.haslayer(Template):
2632 ipfix.add_template(p.getlayer(Template))
2633 # verify events in data set
2635 if p.haslayer(Data):
2636 data = ipfix.decode_data_set(p.getlayer(Set))
2637 self.verify_ipfix_nat44_ses(data)
2639 def test_ipfix_addr_exhausted(self):
2640 """ IPFIX logging NAT addresses exhausted """
2641 flags = self.config_flags.NAT_IS_INSIDE
2642 self.vapi.nat44_interface_add_del_feature(
2643 sw_if_index=self.pg0.sw_if_index,
2644 flags=flags, is_add=1)
2645 self.vapi.nat44_interface_add_del_feature(
2646 sw_if_index=self.pg1.sw_if_index,
2648 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2649 src_address=self.pg3.local_ip4,
2651 template_interval=10)
2652 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2653 src_port=self.ipfix_src_port,
2656 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2657 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2659 self.pg0.add_stream(p)
2660 self.pg_enable_capture(self.pg_interfaces)
2662 self.pg1.assert_nothing_captured()
2664 self.vapi.ipfix_flush()
2665 capture = self.pg3.get_capture(7)
2666 ipfix = IPFIXDecoder()
2667 # first load template
2669 self.assertTrue(p.haslayer(IPFIX))
2670 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2671 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2672 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2673 self.assertEqual(p[UDP].dport, 4739)
2674 self.assertEqual(p[IPFIX].observationDomainID,
2675 self.ipfix_domain_id)
2676 if p.haslayer(Template):
2677 ipfix.add_template(p.getlayer(Template))
2678 # verify events in data set
2680 if p.haslayer(Data):
2681 data = ipfix.decode_data_set(p.getlayer(Set))
2682 self.verify_ipfix_addr_exhausted(data)
2684 def test_ipfix_max_sessions(self):
2685 """ IPFIX logging maximum session entries exceeded """
2686 self.nat44_add_address(self.nat_addr)
2687 flags = self.config_flags.NAT_IS_INSIDE
2688 self.vapi.nat44_interface_add_del_feature(
2689 sw_if_index=self.pg0.sw_if_index,
2690 flags=flags, is_add=1)
2691 self.vapi.nat44_interface_add_del_feature(
2692 sw_if_index=self.pg1.sw_if_index,
2695 max_sessions = self.max_translations
2698 for i in range(0, max_sessions):
2699 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2700 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2701 IP(src=src, dst=self.pg1.remote_ip4) /
2704 self.pg0.add_stream(pkts)
2705 self.pg_enable_capture(self.pg_interfaces)
2708 self.pg1.get_capture(max_sessions)
2709 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2710 src_address=self.pg3.local_ip4,
2712 template_interval=10)
2713 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2714 src_port=self.ipfix_src_port,
2717 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2718 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2720 self.pg0.add_stream(p)
2721 self.pg_enable_capture(self.pg_interfaces)
2723 self.pg1.assert_nothing_captured()
2725 self.vapi.ipfix_flush()
2726 capture = self.pg3.get_capture(7)
2727 ipfix = IPFIXDecoder()
2728 # first load template
2730 self.assertTrue(p.haslayer(IPFIX))
2731 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2732 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2733 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2734 self.assertEqual(p[UDP].dport, 4739)
2735 self.assertEqual(p[IPFIX].observationDomainID,
2736 self.ipfix_domain_id)
2737 if p.haslayer(Template):
2738 ipfix.add_template(p.getlayer(Template))
2739 # verify events in data set
2741 if p.haslayer(Data):
2742 data = ipfix.decode_data_set(p.getlayer(Set))
2743 self.verify_ipfix_max_sessions(data, max_sessions)
2745 def test_syslog_apmap(self):
2746 """ Test syslog address and port mapping creation and deletion """
2747 self.vapi.syslog_set_filter(
2748 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2749 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2750 self.nat44_add_address(self.nat_addr)
2751 flags = self.config_flags.NAT_IS_INSIDE
2752 self.vapi.nat44_interface_add_del_feature(
2753 sw_if_index=self.pg0.sw_if_index,
2754 flags=flags, is_add=1)
2755 self.vapi.nat44_interface_add_del_feature(
2756 sw_if_index=self.pg1.sw_if_index,
2759 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2760 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2761 TCP(sport=self.tcp_port_in, dport=20))
2762 self.pg0.add_stream(p)
2763 self.pg_enable_capture(self.pg_interfaces)
2765 capture = self.pg1.get_capture(1)
2766 self.tcp_port_out = capture[0][TCP].sport
2767 capture = self.pg3.get_capture(1)
2768 self.verify_syslog_apmap(capture[0][Raw].load)
2770 self.pg_enable_capture(self.pg_interfaces)
2772 self.nat44_add_address(self.nat_addr, is_add=0)
2773 capture = self.pg3.get_capture(1)
2774 self.verify_syslog_apmap(capture[0][Raw].load, False)
2776 def test_pool_addr_fib(self):
2777 """ NAT44 add pool addresses to FIB """
2778 static_addr = '10.0.0.10'
2779 self.nat44_add_address(self.nat_addr)
2780 flags = self.config_flags.NAT_IS_INSIDE
2781 self.vapi.nat44_interface_add_del_feature(
2782 sw_if_index=self.pg0.sw_if_index,
2783 flags=flags, is_add=1)
2784 self.vapi.nat44_interface_add_del_feature(
2785 sw_if_index=self.pg1.sw_if_index,
2787 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2790 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2791 ARP(op=ARP.who_has, pdst=self.nat_addr,
2792 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2793 self.pg1.add_stream(p)
2794 self.pg_enable_capture(self.pg_interfaces)
2796 capture = self.pg1.get_capture(1)
2797 self.assertTrue(capture[0].haslayer(ARP))
2798 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2801 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2802 ARP(op=ARP.who_has, pdst=static_addr,
2803 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2804 self.pg1.add_stream(p)
2805 self.pg_enable_capture(self.pg_interfaces)
2807 capture = self.pg1.get_capture(1)
2808 self.assertTrue(capture[0].haslayer(ARP))
2809 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2811 # send ARP to non-NAT44 interface
2812 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2813 ARP(op=ARP.who_has, pdst=self.nat_addr,
2814 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2815 self.pg2.add_stream(p)
2816 self.pg_enable_capture(self.pg_interfaces)
2818 self.pg1.assert_nothing_captured()
2820 # remove addresses and verify
2821 self.nat44_add_address(self.nat_addr, is_add=0)
2822 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2825 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2826 ARP(op=ARP.who_has, pdst=self.nat_addr,
2827 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2828 self.pg1.add_stream(p)
2829 self.pg_enable_capture(self.pg_interfaces)
2831 self.pg1.assert_nothing_captured()
2833 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2834 ARP(op=ARP.who_has, pdst=static_addr,
2835 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2836 self.pg1.add_stream(p)
2837 self.pg_enable_capture(self.pg_interfaces)
2839 self.pg1.assert_nothing_captured()
2841 def test_vrf_mode(self):
2842 """ NAT44 tenant VRF aware address pool mode """
2846 nat_ip1 = "10.0.0.10"
2847 nat_ip2 = "10.0.0.11"
2849 self.pg0.unconfig_ip4()
2850 self.pg1.unconfig_ip4()
2851 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2852 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2853 self.pg0.set_table_ip4(vrf_id1)
2854 self.pg1.set_table_ip4(vrf_id2)
2855 self.pg0.config_ip4()
2856 self.pg1.config_ip4()
2857 self.pg0.resolve_arp()
2858 self.pg1.resolve_arp()
2860 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2861 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2862 flags = self.config_flags.NAT_IS_INSIDE
2863 self.vapi.nat44_interface_add_del_feature(
2864 sw_if_index=self.pg0.sw_if_index,
2865 flags=flags, is_add=1)
2866 self.vapi.nat44_interface_add_del_feature(
2867 sw_if_index=self.pg1.sw_if_index,
2868 flags=flags, is_add=1)
2869 self.vapi.nat44_interface_add_del_feature(
2870 sw_if_index=self.pg2.sw_if_index,
2875 pkts = self.create_stream_in(self.pg0, self.pg2)
2876 self.pg0.add_stream(pkts)
2877 self.pg_enable_capture(self.pg_interfaces)
2879 capture = self.pg2.get_capture(len(pkts))
2880 self.verify_capture_out(capture, nat_ip1)
2883 pkts = self.create_stream_in(self.pg1, self.pg2)
2884 self.pg1.add_stream(pkts)
2885 self.pg_enable_capture(self.pg_interfaces)
2887 capture = self.pg2.get_capture(len(pkts))
2888 self.verify_capture_out(capture, nat_ip2)
2891 self.pg0.unconfig_ip4()
2892 self.pg1.unconfig_ip4()
2893 self.pg0.set_table_ip4(0)
2894 self.pg1.set_table_ip4(0)
2895 self.pg0.config_ip4()
2896 self.pg1.config_ip4()
2897 self.pg0.resolve_arp()
2898 self.pg1.resolve_arp()
2899 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2900 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2902 def test_vrf_feature_independent(self):
2903 """ NAT44 tenant VRF independent address pool mode """
2905 nat_ip1 = "10.0.0.10"
2906 nat_ip2 = "10.0.0.11"
2908 self.nat44_add_address(nat_ip1)
2909 self.nat44_add_address(nat_ip2, vrf_id=99)
2910 flags = self.config_flags.NAT_IS_INSIDE
2911 self.vapi.nat44_interface_add_del_feature(
2912 sw_if_index=self.pg0.sw_if_index,
2913 flags=flags, is_add=1)
2914 self.vapi.nat44_interface_add_del_feature(
2915 sw_if_index=self.pg1.sw_if_index,
2916 flags=flags, is_add=1)
2917 self.vapi.nat44_interface_add_del_feature(
2918 sw_if_index=self.pg2.sw_if_index,
2922 pkts = self.create_stream_in(self.pg0, self.pg2)
2923 self.pg0.add_stream(pkts)
2924 self.pg_enable_capture(self.pg_interfaces)
2926 capture = self.pg2.get_capture(len(pkts))
2927 self.verify_capture_out(capture, nat_ip1)
2930 pkts = self.create_stream_in(self.pg1, self.pg2)
2931 self.pg1.add_stream(pkts)
2932 self.pg_enable_capture(self.pg_interfaces)
2934 capture = self.pg2.get_capture(len(pkts))
2935 self.verify_capture_out(capture, nat_ip1)
2937 def create_routes_and_neigbors(self):
2938 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
2939 [VppRoutePath(self.pg7.remote_ip4,
2940 self.pg7.sw_if_index)])
2941 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
2942 [VppRoutePath(self.pg8.remote_ip4,
2943 self.pg8.sw_if_index)])
2947 n1 = VppNeighbor(self,
2948 self.pg7.sw_if_index,
2949 self.pg7.remote_mac,
2950 self.pg7.remote_ip4,
2952 n2 = VppNeighbor(self,
2953 self.pg8.sw_if_index,
2954 self.pg8.remote_mac,
2955 self.pg8.remote_ip4,
2960 def test_dynamic_ipless_interfaces(self):
2961 """ NAT44 interfaces without configured IP address """
2962 self.create_routes_and_neigbors()
2963 self.nat44_add_address(self.nat_addr)
2964 flags = self.config_flags.NAT_IS_INSIDE
2965 self.vapi.nat44_interface_add_del_feature(
2966 sw_if_index=self.pg7.sw_if_index,
2967 flags=flags, is_add=1)
2968 self.vapi.nat44_interface_add_del_feature(
2969 sw_if_index=self.pg8.sw_if_index,
2973 pkts = self.create_stream_in(self.pg7, self.pg8)
2974 self.pg7.add_stream(pkts)
2975 self.pg_enable_capture(self.pg_interfaces)
2977 capture = self.pg8.get_capture(len(pkts))
2978 self.verify_capture_out(capture)
2981 pkts = self.create_stream_out(self.pg8, self.nat_addr)
2982 self.pg8.add_stream(pkts)
2983 self.pg_enable_capture(self.pg_interfaces)
2985 capture = self.pg7.get_capture(len(pkts))
2986 self.verify_capture_in(capture, self.pg7)
2988 def test_static_ipless_interfaces(self):
2989 """ NAT44 interfaces without configured IP address - 1:1 NAT """
2991 self.create_routes_and_neigbors()
2992 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2993 flags = self.config_flags.NAT_IS_INSIDE
2994 self.vapi.nat44_interface_add_del_feature(
2995 sw_if_index=self.pg7.sw_if_index,
2996 flags=flags, is_add=1)
2997 self.vapi.nat44_interface_add_del_feature(
2998 sw_if_index=self.pg8.sw_if_index,
3002 pkts = self.create_stream_out(self.pg8)
3003 self.pg8.add_stream(pkts)
3004 self.pg_enable_capture(self.pg_interfaces)
3006 capture = self.pg7.get_capture(len(pkts))
3007 self.verify_capture_in(capture, self.pg7)
3010 pkts = self.create_stream_in(self.pg7, self.pg8)
3011 self.pg7.add_stream(pkts)
3012 self.pg_enable_capture(self.pg_interfaces)
3014 capture = self.pg8.get_capture(len(pkts))
3015 self.verify_capture_out(capture, self.nat_addr, True)
3017 def test_static_with_port_ipless_interfaces(self):
3018 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3020 self.tcp_port_out = 30606
3021 self.udp_port_out = 30607
3022 self.icmp_id_out = 30608
3024 self.create_routes_and_neigbors()
3025 self.nat44_add_address(self.nat_addr)
3026 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3027 self.tcp_port_in, self.tcp_port_out,
3028 proto=IP_PROTOS.tcp)
3029 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3030 self.udp_port_in, self.udp_port_out,
3031 proto=IP_PROTOS.udp)
3032 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3033 self.icmp_id_in, self.icmp_id_out,
3034 proto=IP_PROTOS.icmp)
3035 flags = self.config_flags.NAT_IS_INSIDE
3036 self.vapi.nat44_interface_add_del_feature(
3037 sw_if_index=self.pg7.sw_if_index,
3038 flags=flags, is_add=1)
3039 self.vapi.nat44_interface_add_del_feature(
3040 sw_if_index=self.pg8.sw_if_index,
3044 pkts = self.create_stream_out(self.pg8)
3045 self.pg8.add_stream(pkts)
3046 self.pg_enable_capture(self.pg_interfaces)
3048 capture = self.pg7.get_capture(len(pkts))
3049 self.verify_capture_in(capture, self.pg7)
3052 pkts = self.create_stream_in(self.pg7, self.pg8)
3053 self.pg7.add_stream(pkts)
3054 self.pg_enable_capture(self.pg_interfaces)
3056 capture = self.pg8.get_capture(len(pkts))
3057 self.verify_capture_out(capture)
3059 def test_static_unknown_proto(self):
3060 """ 1:1 NAT translate packet with unknown protocol """
3061 nat_ip = "10.0.0.10"
3062 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3063 flags = self.config_flags.NAT_IS_INSIDE
3064 self.vapi.nat44_interface_add_del_feature(
3065 sw_if_index=self.pg0.sw_if_index,
3066 flags=flags, is_add=1)
3067 self.vapi.nat44_interface_add_del_feature(
3068 sw_if_index=self.pg1.sw_if_index,
3072 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3073 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3075 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3076 TCP(sport=1234, dport=1234))
3077 self.pg0.add_stream(p)
3078 self.pg_enable_capture(self.pg_interfaces)
3080 p = self.pg1.get_capture(1)
3083 self.assertEqual(packet[IP].src, nat_ip)
3084 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3085 self.assertEqual(packet.haslayer(GRE), 1)
3086 self.assert_packet_checksums_valid(packet)
3088 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3092 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3093 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3095 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3096 TCP(sport=1234, dport=1234))
3097 self.pg1.add_stream(p)
3098 self.pg_enable_capture(self.pg_interfaces)
3100 p = self.pg0.get_capture(1)
3103 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3104 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3105 self.assertEqual(packet.haslayer(GRE), 1)
3106 self.assert_packet_checksums_valid(packet)
3108 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3111 def test_hairpinning_static_unknown_proto(self):
3112 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3114 host = self.pg0.remote_hosts[0]
3115 server = self.pg0.remote_hosts[1]
3117 host_nat_ip = "10.0.0.10"
3118 server_nat_ip = "10.0.0.11"
3120 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3121 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
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,
3131 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3132 IP(src=host.ip4, dst=server_nat_ip) /
3134 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3135 TCP(sport=1234, dport=1234))
3136 self.pg0.add_stream(p)
3137 self.pg_enable_capture(self.pg_interfaces)
3139 p = self.pg0.get_capture(1)
3142 self.assertEqual(packet[IP].src, host_nat_ip)
3143 self.assertEqual(packet[IP].dst, server.ip4)
3144 self.assertEqual(packet.haslayer(GRE), 1)
3145 self.assert_packet_checksums_valid(packet)
3147 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3151 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3152 IP(src=server.ip4, dst=host_nat_ip) /
3154 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3155 TCP(sport=1234, dport=1234))
3156 self.pg0.add_stream(p)
3157 self.pg_enable_capture(self.pg_interfaces)
3159 p = self.pg0.get_capture(1)
3162 self.assertEqual(packet[IP].src, server_nat_ip)
3163 self.assertEqual(packet[IP].dst, host.ip4)
3164 self.assertEqual(packet.haslayer(GRE), 1)
3165 self.assert_packet_checksums_valid(packet)
3167 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3170 def test_output_feature(self):
3171 """ NAT44 interface output feature (in2out postrouting) """
3172 self.nat44_add_address(self.nat_addr)
3173 flags = self.config_flags.NAT_IS_INSIDE
3174 self.vapi.nat44_interface_add_del_output_feature(
3175 is_add=1, flags=flags,
3176 sw_if_index=self.pg0.sw_if_index)
3177 self.vapi.nat44_interface_add_del_output_feature(
3178 is_add=1, flags=flags,
3179 sw_if_index=self.pg1.sw_if_index)
3180 self.vapi.nat44_interface_add_del_output_feature(
3182 sw_if_index=self.pg3.sw_if_index)
3185 pkts = self.create_stream_in(self.pg0, self.pg3)
3186 self.pg0.add_stream(pkts)
3187 self.pg_enable_capture(self.pg_interfaces)
3189 capture = self.pg3.get_capture(len(pkts))
3190 self.verify_capture_out(capture)
3193 pkts = self.create_stream_out(self.pg3)
3194 self.pg3.add_stream(pkts)
3195 self.pg_enable_capture(self.pg_interfaces)
3197 capture = self.pg0.get_capture(len(pkts))
3198 self.verify_capture_in(capture, self.pg0)
3200 # from non-NAT interface to NAT inside interface
3201 pkts = self.create_stream_in(self.pg2, self.pg0)
3202 self.pg2.add_stream(pkts)
3203 self.pg_enable_capture(self.pg_interfaces)
3205 capture = self.pg0.get_capture(len(pkts))
3206 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3208 def test_output_feature_vrf_aware(self):
3209 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3210 nat_ip_vrf10 = "10.0.0.10"
3211 nat_ip_vrf20 = "10.0.0.20"
3213 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3214 [VppRoutePath(self.pg3.remote_ip4,
3215 self.pg3.sw_if_index)],
3217 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3218 [VppRoutePath(self.pg3.remote_ip4,
3219 self.pg3.sw_if_index)],
3224 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3225 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3226 flags = self.config_flags.NAT_IS_INSIDE
3227 self.vapi.nat44_interface_add_del_output_feature(
3228 is_add=1, flags=flags,
3229 sw_if_index=self.pg4.sw_if_index)
3230 self.vapi.nat44_interface_add_del_output_feature(
3231 is_add=1, flags=flags,
3232 sw_if_index=self.pg6.sw_if_index)
3233 self.vapi.nat44_interface_add_del_output_feature(
3235 sw_if_index=self.pg3.sw_if_index)
3238 pkts = self.create_stream_in(self.pg4, self.pg3)
3239 self.pg4.add_stream(pkts)
3240 self.pg_enable_capture(self.pg_interfaces)
3242 capture = self.pg3.get_capture(len(pkts))
3243 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3246 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3247 self.pg3.add_stream(pkts)
3248 self.pg_enable_capture(self.pg_interfaces)
3250 capture = self.pg4.get_capture(len(pkts))
3251 self.verify_capture_in(capture, self.pg4)
3254 pkts = self.create_stream_in(self.pg6, self.pg3)
3255 self.pg6.add_stream(pkts)
3256 self.pg_enable_capture(self.pg_interfaces)
3258 capture = self.pg3.get_capture(len(pkts))
3259 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3262 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3263 self.pg3.add_stream(pkts)
3264 self.pg_enable_capture(self.pg_interfaces)
3266 capture = self.pg6.get_capture(len(pkts))
3267 self.verify_capture_in(capture, self.pg6)
3269 def test_output_feature_hairpinning(self):
3270 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3271 host = self.pg0.remote_hosts[0]
3272 server = self.pg0.remote_hosts[1]
3275 server_in_port = 5678
3276 server_out_port = 8765
3278 self.nat44_add_address(self.nat_addr)
3279 flags = self.config_flags.NAT_IS_INSIDE
3280 self.vapi.nat44_interface_add_del_output_feature(
3281 is_add=1, flags=flags,
3282 sw_if_index=self.pg0.sw_if_index)
3283 self.vapi.nat44_interface_add_del_output_feature(
3285 sw_if_index=self.pg1.sw_if_index)
3287 # add static mapping for server
3288 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3289 server_in_port, server_out_port,
3290 proto=IP_PROTOS.tcp)
3292 # send packet from host to server
3293 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3294 IP(src=host.ip4, dst=self.nat_addr) /
3295 TCP(sport=host_in_port, dport=server_out_port))
3296 self.pg0.add_stream(p)
3297 self.pg_enable_capture(self.pg_interfaces)
3299 capture = self.pg0.get_capture(1)
3304 self.assertEqual(ip.src, self.nat_addr)
3305 self.assertEqual(ip.dst, server.ip4)
3306 self.assertNotEqual(tcp.sport, host_in_port)
3307 self.assertEqual(tcp.dport, server_in_port)
3308 self.assert_packet_checksums_valid(p)
3309 host_out_port = tcp.sport
3311 self.logger.error(ppp("Unexpected or invalid packet:", p))
3314 # send reply from server to host
3315 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3316 IP(src=server.ip4, dst=self.nat_addr) /
3317 TCP(sport=server_in_port, dport=host_out_port))
3318 self.pg0.add_stream(p)
3319 self.pg_enable_capture(self.pg_interfaces)
3321 capture = self.pg0.get_capture(1)
3326 self.assertEqual(ip.src, self.nat_addr)
3327 self.assertEqual(ip.dst, host.ip4)
3328 self.assertEqual(tcp.sport, server_out_port)
3329 self.assertEqual(tcp.dport, host_in_port)
3330 self.assert_packet_checksums_valid(p)
3332 self.logger.error(ppp("Unexpected or invalid packet:", p))
3335 def test_one_armed_nat44(self):
3336 """ One armed NAT44 """
3337 remote_host = self.pg9.remote_hosts[0]
3338 local_host = self.pg9.remote_hosts[1]
3341 self.nat44_add_address(self.nat_addr)
3342 flags = self.config_flags.NAT_IS_INSIDE
3343 self.vapi.nat44_interface_add_del_feature(
3344 sw_if_index=self.pg9.sw_if_index,
3346 self.vapi.nat44_interface_add_del_feature(
3347 sw_if_index=self.pg9.sw_if_index,
3348 flags=flags, is_add=1)
3351 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3352 IP(src=local_host.ip4, dst=remote_host.ip4) /
3353 TCP(sport=12345, dport=80))
3354 self.pg9.add_stream(p)
3355 self.pg_enable_capture(self.pg_interfaces)
3357 capture = self.pg9.get_capture(1)
3362 self.assertEqual(ip.src, self.nat_addr)
3363 self.assertEqual(ip.dst, remote_host.ip4)
3364 self.assertNotEqual(tcp.sport, 12345)
3365 external_port = tcp.sport
3366 self.assertEqual(tcp.dport, 80)
3367 self.assert_packet_checksums_valid(p)
3369 self.logger.error(ppp("Unexpected or invalid packet:", p))
3373 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3374 IP(src=remote_host.ip4, dst=self.nat_addr) /
3375 TCP(sport=80, dport=external_port))
3376 self.pg9.add_stream(p)
3377 self.pg_enable_capture(self.pg_interfaces)
3379 capture = self.pg9.get_capture(1)
3384 self.assertEqual(ip.src, remote_host.ip4)
3385 self.assertEqual(ip.dst, local_host.ip4)
3386 self.assertEqual(tcp.sport, 80)
3387 self.assertEqual(tcp.dport, 12345)
3388 self.assert_packet_checksums_valid(p)
3390 self.logger.error(ppp("Unexpected or invalid packet:", p))
3393 err = self.statistics.get_err_counter(
3394 '/err/nat44-classify/next in2out')
3395 self.assertEqual(err, 1)
3396 err = self.statistics.get_err_counter(
3397 '/err/nat44-classify/next out2in')
3398 self.assertEqual(err, 1)
3400 def test_del_session(self):
3401 """ Delete NAT44 session """
3402 self.nat44_add_address(self.nat_addr)
3403 flags = self.config_flags.NAT_IS_INSIDE
3404 self.vapi.nat44_interface_add_del_feature(
3405 sw_if_index=self.pg0.sw_if_index,
3406 flags=flags, is_add=1)
3407 self.vapi.nat44_interface_add_del_feature(
3408 sw_if_index=self.pg1.sw_if_index,
3411 pkts = self.create_stream_in(self.pg0, self.pg1)
3412 self.pg0.add_stream(pkts)
3413 self.pg_enable_capture(self.pg_interfaces)
3415 self.pg1.get_capture(len(pkts))
3417 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3418 nsessions = len(sessions)
3420 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3421 port=sessions[0].inside_port,
3422 protocol=sessions[0].protocol,
3423 flags=self.config_flags.NAT_IS_INSIDE)
3424 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3425 port=sessions[1].outside_port,
3426 protocol=sessions[1].protocol)
3428 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3429 self.assertEqual(nsessions - len(sessions), 2)
3431 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3432 port=sessions[0].inside_port,
3433 protocol=sessions[0].protocol,
3434 flags=self.config_flags.NAT_IS_INSIDE)
3436 self.verify_no_nat44_user()
3438 def test_frag_in_order(self):
3439 """ NAT44 translate fragments arriving in order """
3441 self.nat44_add_address(self.nat_addr)
3442 flags = self.config_flags.NAT_IS_INSIDE
3443 self.vapi.nat44_interface_add_del_feature(
3444 sw_if_index=self.pg0.sw_if_index,
3445 flags=flags, is_add=1)
3446 self.vapi.nat44_interface_add_del_feature(
3447 sw_if_index=self.pg1.sw_if_index,
3450 self.frag_in_order(proto=IP_PROTOS.tcp)
3451 self.frag_in_order(proto=IP_PROTOS.udp)
3452 self.frag_in_order(proto=IP_PROTOS.icmp)
3454 def test_frag_forwarding(self):
3455 """ NAT44 forwarding fragment test """
3456 self.vapi.nat44_add_del_interface_addr(
3458 sw_if_index=self.pg1.sw_if_index)
3459 flags = self.config_flags.NAT_IS_INSIDE
3460 self.vapi.nat44_interface_add_del_feature(
3461 sw_if_index=self.pg0.sw_if_index,
3462 flags=flags, is_add=1)
3463 self.vapi.nat44_interface_add_del_feature(
3464 sw_if_index=self.pg1.sw_if_index,
3466 self.vapi.nat44_forwarding_enable_disable(enable=1)
3468 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3469 pkts = self.create_stream_frag(self.pg1,
3470 self.pg0.remote_ip4,
3474 proto=IP_PROTOS.udp)
3475 self.pg1.add_stream(pkts)
3476 self.pg_enable_capture(self.pg_interfaces)
3478 frags = self.pg0.get_capture(len(pkts))
3479 p = self.reass_frags_and_verify(frags,
3480 self.pg1.remote_ip4,
3481 self.pg0.remote_ip4)
3482 self.assertEqual(p[UDP].sport, 4789)
3483 self.assertEqual(p[UDP].dport, 4789)
3484 self.assertEqual(data, p[Raw].load)
3486 def test_reass_hairpinning(self):
3487 """ NAT44 fragments hairpinning """
3489 self.server = self.pg0.remote_hosts[1]
3490 self.host_in_port = random.randint(1025, 65535)
3491 self.server_in_port = random.randint(1025, 65535)
3492 self.server_out_port = random.randint(1025, 65535)
3494 self.nat44_add_address(self.nat_addr)
3495 flags = self.config_flags.NAT_IS_INSIDE
3496 self.vapi.nat44_interface_add_del_feature(
3497 sw_if_index=self.pg0.sw_if_index,
3498 flags=flags, is_add=1)
3499 self.vapi.nat44_interface_add_del_feature(
3500 sw_if_index=self.pg1.sw_if_index,
3502 # add static mapping for server
3503 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3504 self.server_in_port,
3505 self.server_out_port,
3506 proto=IP_PROTOS.tcp)
3507 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3508 self.server_in_port,
3509 self.server_out_port,
3510 proto=IP_PROTOS.udp)
3511 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3513 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3514 self.reass_hairpinning(proto=IP_PROTOS.udp)
3515 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3517 def test_frag_out_of_order(self):
3518 """ NAT44 translate fragments arriving out of order """
3520 self.nat44_add_address(self.nat_addr)
3521 flags = self.config_flags.NAT_IS_INSIDE
3522 self.vapi.nat44_interface_add_del_feature(
3523 sw_if_index=self.pg0.sw_if_index,
3524 flags=flags, is_add=1)
3525 self.vapi.nat44_interface_add_del_feature(
3526 sw_if_index=self.pg1.sw_if_index,
3529 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3530 self.frag_out_of_order(proto=IP_PROTOS.udp)
3531 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3533 def test_port_restricted(self):
3534 """ Port restricted NAT44 (MAP-E CE) """
3535 self.nat44_add_address(self.nat_addr)
3536 flags = self.config_flags.NAT_IS_INSIDE
3537 self.vapi.nat44_interface_add_del_feature(
3538 sw_if_index=self.pg0.sw_if_index,
3539 flags=flags, is_add=1)
3540 self.vapi.nat44_interface_add_del_feature(
3541 sw_if_index=self.pg1.sw_if_index,
3543 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3548 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3549 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3550 TCP(sport=4567, dport=22))
3551 self.pg0.add_stream(p)
3552 self.pg_enable_capture(self.pg_interfaces)
3554 capture = self.pg1.get_capture(1)
3559 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3560 self.assertEqual(ip.src, self.nat_addr)
3561 self.assertEqual(tcp.dport, 22)
3562 self.assertNotEqual(tcp.sport, 4567)
3563 self.assertEqual((tcp.sport >> 6) & 63, 10)
3564 self.assert_packet_checksums_valid(p)
3566 self.logger.error(ppp("Unexpected or invalid packet:", p))
3569 def test_port_range(self):
3570 """ External address port range """
3571 self.nat44_add_address(self.nat_addr)
3572 flags = self.config_flags.NAT_IS_INSIDE
3573 self.vapi.nat44_interface_add_del_feature(
3574 sw_if_index=self.pg0.sw_if_index,
3575 flags=flags, is_add=1)
3576 self.vapi.nat44_interface_add_del_feature(
3577 sw_if_index=self.pg1.sw_if_index,
3579 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3584 for port in range(0, 5):
3585 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3586 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3587 TCP(sport=1125 + port))
3589 self.pg0.add_stream(pkts)
3590 self.pg_enable_capture(self.pg_interfaces)
3592 capture = self.pg1.get_capture(3)
3595 self.assertGreaterEqual(tcp.sport, 1025)
3596 self.assertLessEqual(tcp.sport, 1027)
3598 def test_multiple_outside_vrf(self):
3599 """ Multiple outside VRF """
3603 self.pg1.unconfig_ip4()
3604 self.pg2.unconfig_ip4()
3605 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3606 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3607 self.pg1.set_table_ip4(vrf_id1)
3608 self.pg2.set_table_ip4(vrf_id2)
3609 self.pg1.config_ip4()
3610 self.pg2.config_ip4()
3611 self.pg1.resolve_arp()
3612 self.pg2.resolve_arp()
3614 self.nat44_add_address(self.nat_addr)
3615 flags = self.config_flags.NAT_IS_INSIDE
3616 self.vapi.nat44_interface_add_del_feature(
3617 sw_if_index=self.pg0.sw_if_index,
3618 flags=flags, is_add=1)
3619 self.vapi.nat44_interface_add_del_feature(
3620 sw_if_index=self.pg1.sw_if_index,
3622 self.vapi.nat44_interface_add_del_feature(
3623 sw_if_index=self.pg2.sw_if_index,
3628 pkts = self.create_stream_in(self.pg0, self.pg1)
3629 self.pg0.add_stream(pkts)
3630 self.pg_enable_capture(self.pg_interfaces)
3632 capture = self.pg1.get_capture(len(pkts))
3633 self.verify_capture_out(capture, self.nat_addr)
3635 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3636 self.pg1.add_stream(pkts)
3637 self.pg_enable_capture(self.pg_interfaces)
3639 capture = self.pg0.get_capture(len(pkts))
3640 self.verify_capture_in(capture, self.pg0)
3642 self.tcp_port_in = 60303
3643 self.udp_port_in = 60304
3644 self.icmp_id_in = 60305
3647 pkts = self.create_stream_in(self.pg0, self.pg2)
3648 self.pg0.add_stream(pkts)
3649 self.pg_enable_capture(self.pg_interfaces)
3651 capture = self.pg2.get_capture(len(pkts))
3652 self.verify_capture_out(capture, self.nat_addr)
3654 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3655 self.pg2.add_stream(pkts)
3656 self.pg_enable_capture(self.pg_interfaces)
3658 capture = self.pg0.get_capture(len(pkts))
3659 self.verify_capture_in(capture, self.pg0)
3662 self.nat44_add_address(self.nat_addr, is_add=0)
3663 self.pg1.unconfig_ip4()
3664 self.pg2.unconfig_ip4()
3665 self.pg1.set_table_ip4(0)
3666 self.pg2.set_table_ip4(0)
3667 self.pg1.config_ip4()
3668 self.pg2.config_ip4()
3669 self.pg1.resolve_arp()
3670 self.pg2.resolve_arp()
3672 def test_mss_clamping(self):
3673 """ TCP MSS clamping """
3674 self.nat44_add_address(self.nat_addr)
3675 flags = self.config_flags.NAT_IS_INSIDE
3676 self.vapi.nat44_interface_add_del_feature(
3677 sw_if_index=self.pg0.sw_if_index,
3678 flags=flags, is_add=1)
3679 self.vapi.nat44_interface_add_del_feature(
3680 sw_if_index=self.pg1.sw_if_index,
3683 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3684 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3685 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3686 flags="S", options=[('MSS', 1400)]))
3688 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3689 self.pg0.add_stream(p)
3690 self.pg_enable_capture(self.pg_interfaces)
3692 capture = self.pg1.get_capture(1)
3693 # Negotiated MSS value greater than configured - changed
3694 self.verify_mss_value(capture[0], 1000)
3696 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3697 self.pg0.add_stream(p)
3698 self.pg_enable_capture(self.pg_interfaces)
3700 capture = self.pg1.get_capture(1)
3701 # MSS clamping disabled - negotiated MSS unchanged
3702 self.verify_mss_value(capture[0], 1400)
3704 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3705 self.pg0.add_stream(p)
3706 self.pg_enable_capture(self.pg_interfaces)
3708 capture = self.pg1.get_capture(1)
3709 # Negotiated MSS value smaller than configured - unchanged
3710 self.verify_mss_value(capture[0], 1400)
3712 def test_ha_send(self):
3713 """ Send HA session synchronization events (active) """
3714 flags = self.config_flags.NAT_IS_INSIDE
3715 self.vapi.nat44_interface_add_del_feature(
3716 sw_if_index=self.pg0.sw_if_index,
3717 flags=flags, is_add=1)
3718 self.vapi.nat44_interface_add_del_feature(
3719 sw_if_index=self.pg1.sw_if_index,
3721 self.nat44_add_address(self.nat_addr)
3723 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3726 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3727 port=12346, session_refresh_interval=10)
3728 bind_layers(UDP, HANATStateSync, sport=12345)
3731 pkts = self.create_stream_in(self.pg0, self.pg1)
3732 self.pg0.add_stream(pkts)
3733 self.pg_enable_capture(self.pg_interfaces)
3735 capture = self.pg1.get_capture(len(pkts))
3736 self.verify_capture_out(capture)
3737 # active send HA events
3738 self.vapi.nat_ha_flush()
3739 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3740 self.assertEqual(stats[0][0], 3)
3741 capture = self.pg3.get_capture(1)
3743 self.assert_packet_checksums_valid(p)
3747 hanat = p[HANATStateSync]
3749 self.logger.error(ppp("Invalid packet:", p))
3752 self.assertEqual(ip.src, self.pg3.local_ip4)
3753 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3754 self.assertEqual(udp.sport, 12345)
3755 self.assertEqual(udp.dport, 12346)
3756 self.assertEqual(hanat.version, 1)
3757 self.assertEqual(hanat.thread_index, 0)
3758 self.assertEqual(hanat.count, 3)
3759 seq = hanat.sequence_number
3760 for event in hanat.events:
3761 self.assertEqual(event.event_type, 1)
3762 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3763 self.assertEqual(event.out_addr, self.nat_addr)
3764 self.assertEqual(event.fib_index, 0)
3766 # ACK received events
3767 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3768 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3769 UDP(sport=12346, dport=12345) /
3770 HANATStateSync(sequence_number=seq, flags='ACK'))
3771 self.pg3.add_stream(ack)
3773 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3774 self.assertEqual(stats[0][0], 1)
3776 # delete one session
3777 self.pg_enable_capture(self.pg_interfaces)
3778 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3779 port=self.tcp_port_in,
3780 protocol=IP_PROTOS.tcp,
3781 flags=self.config_flags.NAT_IS_INSIDE)
3782 self.vapi.nat_ha_flush()
3783 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3784 self.assertEqual(stats[0][0], 1)
3785 capture = self.pg3.get_capture(1)
3788 hanat = p[HANATStateSync]
3790 self.logger.error(ppp("Invalid packet:", p))
3793 self.assertGreater(hanat.sequence_number, seq)
3795 # do not send ACK, active retry send HA event again
3796 self.pg_enable_capture(self.pg_interfaces)
3798 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3799 self.assertEqual(stats[0][0], 3)
3800 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3801 self.assertEqual(stats[0][0], 1)
3802 capture = self.pg3.get_capture(3)
3803 for packet in capture:
3804 self.assertEqual(packet, p)
3806 # session counters refresh
3807 pkts = self.create_stream_out(self.pg1)
3808 self.pg1.add_stream(pkts)
3809 self.pg_enable_capture(self.pg_interfaces)
3811 self.pg0.get_capture(2)
3812 self.vapi.nat_ha_flush()
3813 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3814 self.assertEqual(stats[0][0], 2)
3815 capture = self.pg3.get_capture(1)
3817 self.assert_packet_checksums_valid(p)
3821 hanat = p[HANATStateSync]
3823 self.logger.error(ppp("Invalid packet:", p))
3826 self.assertEqual(ip.src, self.pg3.local_ip4)
3827 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3828 self.assertEqual(udp.sport, 12345)
3829 self.assertEqual(udp.dport, 12346)
3830 self.assertEqual(hanat.version, 1)
3831 self.assertEqual(hanat.count, 2)
3832 seq = hanat.sequence_number
3833 for event in hanat.events:
3834 self.assertEqual(event.event_type, 3)
3835 self.assertEqual(event.out_addr, self.nat_addr)
3836 self.assertEqual(event.fib_index, 0)
3837 self.assertEqual(event.total_pkts, 2)
3838 self.assertGreater(event.total_bytes, 0)
3840 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3841 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3842 UDP(sport=12346, dport=12345) /
3843 HANATStateSync(sequence_number=seq, flags='ACK'))
3844 self.pg3.add_stream(ack)
3846 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3847 self.assertEqual(stats[0][0], 2)
3849 def test_ha_recv(self):
3850 """ Receive HA session synchronization events (passive) """
3851 self.nat44_add_address(self.nat_addr)
3852 flags = self.config_flags.NAT_IS_INSIDE
3853 self.vapi.nat44_interface_add_del_feature(
3854 sw_if_index=self.pg0.sw_if_index,
3855 flags=flags, is_add=1)
3856 self.vapi.nat44_interface_add_del_feature(
3857 sw_if_index=self.pg1.sw_if_index,
3859 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3862 bind_layers(UDP, HANATStateSync, sport=12345)
3864 self.tcp_port_out = random.randint(1025, 65535)
3865 self.udp_port_out = random.randint(1025, 65535)
3867 # send HA session add events to failover/passive
3868 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3869 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3870 UDP(sport=12346, dport=12345) /
3871 HANATStateSync(sequence_number=1, events=[
3872 Event(event_type='add', protocol='tcp',
3873 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3874 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3875 eh_addr=self.pg1.remote_ip4,
3876 ehn_addr=self.pg1.remote_ip4,
3877 eh_port=self.tcp_external_port,
3878 ehn_port=self.tcp_external_port, fib_index=0),
3879 Event(event_type='add', protocol='udp',
3880 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3881 in_port=self.udp_port_in, out_port=self.udp_port_out,
3882 eh_addr=self.pg1.remote_ip4,
3883 ehn_addr=self.pg1.remote_ip4,
3884 eh_port=self.udp_external_port,
3885 ehn_port=self.udp_external_port, fib_index=0)]))
3887 self.pg3.add_stream(p)
3888 self.pg_enable_capture(self.pg_interfaces)
3891 capture = self.pg3.get_capture(1)
3894 hanat = p[HANATStateSync]
3896 self.logger.error(ppp("Invalid packet:", p))
3899 self.assertEqual(hanat.sequence_number, 1)
3900 self.assertEqual(hanat.flags, 'ACK')
3901 self.assertEqual(hanat.version, 1)
3902 self.assertEqual(hanat.thread_index, 0)
3903 stats = self.statistics.get_counter('/nat44/ha/ack-send')
3904 self.assertEqual(stats[0][0], 1)
3905 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
3906 self.assertEqual(stats[0][0], 2)
3907 users = self.statistics.get_counter('/nat44/total-users')
3908 self.assertEqual(users[0][0], 1)
3909 sessions = self.statistics.get_counter('/nat44/total-sessions')
3910 self.assertEqual(sessions[0][0], 2)
3911 users = self.vapi.nat44_user_dump()
3912 self.assertEqual(len(users), 1)
3913 self.assertEqual(str(users[0].ip_address),
3914 self.pg0.remote_ip4)
3915 # there should be 2 sessions created by HA
3916 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3918 self.assertEqual(len(sessions), 2)
3919 for session in sessions:
3920 self.assertEqual(str(session.inside_ip_address),
3921 self.pg0.remote_ip4)
3922 self.assertEqual(str(session.outside_ip_address),
3924 self.assertIn(session.inside_port,
3925 [self.tcp_port_in, self.udp_port_in])
3926 self.assertIn(session.outside_port,
3927 [self.tcp_port_out, self.udp_port_out])
3928 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3930 # send HA session delete event to failover/passive
3931 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3932 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3933 UDP(sport=12346, dport=12345) /
3934 HANATStateSync(sequence_number=2, events=[
3935 Event(event_type='del', protocol='udp',
3936 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3937 in_port=self.udp_port_in, out_port=self.udp_port_out,
3938 eh_addr=self.pg1.remote_ip4,
3939 ehn_addr=self.pg1.remote_ip4,
3940 eh_port=self.udp_external_port,
3941 ehn_port=self.udp_external_port, fib_index=0)]))
3943 self.pg3.add_stream(p)
3944 self.pg_enable_capture(self.pg_interfaces)
3947 capture = self.pg3.get_capture(1)
3950 hanat = p[HANATStateSync]
3952 self.logger.error(ppp("Invalid packet:", p))
3955 self.assertEqual(hanat.sequence_number, 2)
3956 self.assertEqual(hanat.flags, 'ACK')
3957 self.assertEqual(hanat.version, 1)
3958 users = self.vapi.nat44_user_dump()
3959 self.assertEqual(len(users), 1)
3960 self.assertEqual(str(users[0].ip_address),
3961 self.pg0.remote_ip4)
3962 # now we should have only 1 session, 1 deleted by HA
3963 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3965 self.assertEqual(len(sessions), 1)
3966 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
3967 self.assertEqual(stats[0][0], 1)
3969 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
3970 self.assertEqual(stats, 2)
3972 # send HA session refresh event to failover/passive
3973 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3974 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3975 UDP(sport=12346, dport=12345) /
3976 HANATStateSync(sequence_number=3, events=[
3977 Event(event_type='refresh', protocol='tcp',
3978 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3979 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3980 eh_addr=self.pg1.remote_ip4,
3981 ehn_addr=self.pg1.remote_ip4,
3982 eh_port=self.tcp_external_port,
3983 ehn_port=self.tcp_external_port, fib_index=0,
3984 total_bytes=1024, total_pkts=2)]))
3985 self.pg3.add_stream(p)
3986 self.pg_enable_capture(self.pg_interfaces)
3989 capture = self.pg3.get_capture(1)
3992 hanat = p[HANATStateSync]
3994 self.logger.error(ppp("Invalid packet:", p))
3997 self.assertEqual(hanat.sequence_number, 3)
3998 self.assertEqual(hanat.flags, 'ACK')
3999 self.assertEqual(hanat.version, 1)
4000 users = self.vapi.nat44_user_dump()
4001 self.assertEqual(len(users), 1)
4002 self.assertEqual(str(users[0].ip_address),
4003 self.pg0.remote_ip4)
4004 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4006 self.assertEqual(len(sessions), 1)
4007 session = sessions[0]
4008 self.assertEqual(session.total_bytes, 1024)
4009 self.assertEqual(session.total_pkts, 2)
4010 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4011 self.assertEqual(stats[0][0], 1)
4013 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4014 self.assertEqual(stats, 3)
4016 # send packet to test session created by HA
4017 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4018 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4019 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4020 self.pg1.add_stream(p)
4021 self.pg_enable_capture(self.pg_interfaces)
4023 capture = self.pg0.get_capture(1)
4029 self.logger.error(ppp("Invalid packet:", p))
4032 self.assertEqual(ip.src, self.pg1.remote_ip4)
4033 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4034 self.assertEqual(tcp.sport, self.tcp_external_port)
4035 self.assertEqual(tcp.dport, self.tcp_port_in)
4037 def show_commands_at_teardown(self):
4038 self.logger.info(self.vapi.cli("show nat44 addresses"))
4039 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4040 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4041 self.logger.info(self.vapi.cli("show nat44 interface address"))
4042 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4043 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4044 self.logger.info(self.vapi.cli("show nat timeouts"))
4046 self.vapi.cli("show nat addr-port-assignment-alg"))
4047 self.logger.info(self.vapi.cli("show nat ha"))
4050 class TestNAT44EndpointDependent2(MethodHolder):
4051 """ Endpoint-Dependent mapping and filtering test cases """
4054 def tearDownClass(cls):
4055 super(TestNAT44EndpointDependent2, cls).tearDownClass()
4058 super(TestNAT44EndpointDependent2, self).tearDown()
4061 def create_and_add_ip4_table(cls, i, table_id):
4062 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
4063 i.set_table_ip4(table_id)
4066 def setUpClass(cls):
4067 super(TestNAT44EndpointDependent2, cls).setUpClass()
4069 cls.create_pg_interfaces(range(3))
4070 cls.interfaces = list(cls.pg_interfaces)
4072 cls.create_and_add_ip4_table(cls.pg1, 10)
4074 for i in cls.interfaces:
4079 i.generate_remote_hosts(1)
4080 i.configure_ipv4_neighbors()
4083 super(TestNAT44EndpointDependent2, self).setUp()
4084 flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT
4085 self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
4088 super(TestNAT44EndpointDependent2, self).tearDown()
4089 if not self.vpp_dead:
4090 self.vapi.nat44_plugin_enable_disable(enable=0)
4091 self.vapi.cli("clear logging")
4093 def nat_add_inside_interface(self, i):
4094 self.vapi.nat44_interface_add_del_feature(
4095 flags=self.config_flags.NAT_IS_INSIDE,
4096 sw_if_index=i.sw_if_index, is_add=1)
4098 def nat_add_outside_interface(self, i):
4099 self.vapi.nat44_interface_add_del_feature(
4100 flags=self.config_flags.NAT_IS_OUTSIDE,
4101 sw_if_index=i.sw_if_index, is_add=1)
4103 def nat_add_interface_address(self, i):
4104 self.nat_addr = i.local_ip4
4105 self.vapi.nat44_add_del_interface_addr(
4106 sw_if_index=i.sw_if_index, is_add=1)
4108 def nat_add_address(self, address, vrf_id=0xFFFFFFFF):
4109 self.nat_addr = address
4110 self.nat44_add_address(address, vrf_id=vrf_id)
4112 def cli(self, command):
4113 result = self.vapi.cli(command)
4114 self.logger.info(result)
4117 def show_configuration(self):
4118 self.cli("show interface")
4119 self.cli("show interface address")
4120 self.cli("show nat44 addresses")
4121 self.cli("show nat44 interfaces")
4123 def create_tcp_stream(self, in_if, out_if, count):
4125 Create tcp packet stream
4127 :param in_if: Inside interface
4128 :param out_if: Outside interface
4129 :param count: count of packets to generate
4134 for i in range(count):
4135 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4136 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4137 TCP(sport=port + i, dport=20))
4142 def test_session_limit_per_vrf(self):
4145 inside_vrf10 = self.pg1
4150 # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
4151 # non existing vrf_id makes process core dump
4152 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
4154 self.nat_add_inside_interface(inside)
4155 self.nat_add_inside_interface(inside_vrf10)
4156 self.nat_add_outside_interface(outside)
4159 self.nat_add_interface_address(outside)
4161 # BUG: causing core dump - when bad vrf_id is specified
4162 # self.nat44_add_address(outside.local_ip4, vrf_id=20)
4164 self.show_configuration()
4166 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
4167 inside_vrf10.add_stream(stream)
4169 self.pg_enable_capture(self.pg_interfaces)
4172 capture = outside.get_capture(limit)
4174 stream = self.create_tcp_stream(inside, outside, limit * 2)
4175 inside.add_stream(stream)
4177 self.pg_enable_capture(self.pg_interfaces)
4180 capture = outside.get_capture(len(stream))
4183 class TestNAT44EndpointDependent(MethodHolder):
4184 """ Endpoint-Dependent mapping and filtering test cases """
4187 def setUpClass(cls):
4188 super(TestNAT44EndpointDependent, cls).setUpClass()
4189 cls.vapi.cli("set log class nat level debug")
4191 cls.tcp_port_in = 6303
4192 cls.tcp_port_out = 6303
4193 cls.udp_port_in = 6304
4194 cls.udp_port_out = 6304
4195 cls.icmp_id_in = 6305
4196 cls.icmp_id_out = 6305
4197 cls.nat_addr = '10.0.0.3'
4198 cls.ipfix_src_port = 4739
4199 cls.ipfix_domain_id = 1
4200 cls.tcp_external_port = 80
4202 cls.create_pg_interfaces(range(9))
4203 cls.interfaces = list(cls.pg_interfaces[0:3])
4205 for i in cls.interfaces:
4210 cls.pg0.generate_remote_hosts(3)
4211 cls.pg0.configure_ipv4_neighbors()
4215 cls.pg4.generate_remote_hosts(2)
4216 cls.pg4.config_ip4()
4217 cls.vapi.sw_interface_add_del_address(
4218 sw_if_index=cls.pg4.sw_if_index,
4219 prefix="10.0.0.1/24")
4222 cls.pg4.resolve_arp()
4223 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4224 cls.pg4.resolve_arp()
4226 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4227 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4229 cls.pg5._local_ip4 = "10.1.1.1"
4230 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4231 cls.pg5.set_table_ip4(1)
4232 cls.pg5.config_ip4()
4234 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4235 [VppRoutePath("0.0.0.0",
4236 cls.pg5.sw_if_index)],
4241 cls.pg6._local_ip4 = "10.1.2.1"
4242 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4243 cls.pg6.set_table_ip4(1)
4244 cls.pg6.config_ip4()
4247 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4248 [VppRoutePath("0.0.0.0",
4249 cls.pg6.sw_if_index)],
4252 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4253 [VppRoutePath("0.0.0.0",
4258 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4259 [VppRoutePath("0.0.0.0", 0xffffffff,
4263 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4264 [VppRoutePath(cls.pg1.local_ip4,
4265 cls.pg1.sw_if_index)],
4272 cls.pg5.resolve_arp()
4273 cls.pg6.resolve_arp()
4276 cls.pg7.config_ip4()
4277 cls.pg7.resolve_arp()
4278 cls.pg7.generate_remote_hosts(3)
4279 cls.pg7.configure_ipv4_neighbors()
4282 cls.pg8.config_ip4()
4283 cls.pg8.resolve_arp()
4286 def tearDownClass(cls):
4287 super(TestNAT44EndpointDependent, cls).tearDownClass()
4290 super(TestNAT44EndpointDependent, self).setUp()
4291 flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT
4292 self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
4293 self.vapi.nat_set_timeouts(
4294 udp=300, tcp_established=7440,
4295 tcp_transitory=240, icmp=60)
4298 super(TestNAT44EndpointDependent, self).tearDown()
4299 if not self.vpp_dead:
4300 self.vapi.nat44_plugin_enable_disable(enable=0)
4301 self.vapi.cli("clear logging")
4303 def test_frag_in_order(self):
4304 """ NAT44 translate fragments arriving in order """
4305 self.nat44_add_address(self.nat_addr)
4306 flags = self.config_flags.NAT_IS_INSIDE
4307 self.vapi.nat44_interface_add_del_feature(
4308 sw_if_index=self.pg0.sw_if_index,
4309 flags=flags, is_add=1)
4310 self.vapi.nat44_interface_add_del_feature(
4311 sw_if_index=self.pg1.sw_if_index,
4313 self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
4314 self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
4315 self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
4317 def test_frag_in_order_dont_translate(self):
4318 """ NAT44 don't translate fragments arriving in order """
4319 flags = self.config_flags.NAT_IS_INSIDE
4320 self.vapi.nat44_interface_add_del_feature(
4321 sw_if_index=self.pg0.sw_if_index,
4322 flags=flags, is_add=1)
4323 self.vapi.nat44_interface_add_del_feature(
4324 sw_if_index=self.pg1.sw_if_index,
4326 self.vapi.nat44_forwarding_enable_disable(enable=True)
4327 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4329 def test_frag_out_of_order(self):
4330 """ NAT44 translate fragments arriving out of order """
4331 self.nat44_add_address(self.nat_addr)
4332 flags = self.config_flags.NAT_IS_INSIDE
4333 self.vapi.nat44_interface_add_del_feature(
4334 sw_if_index=self.pg0.sw_if_index,
4335 flags=flags, is_add=1)
4336 self.vapi.nat44_interface_add_del_feature(
4337 sw_if_index=self.pg1.sw_if_index,
4339 self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
4340 self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
4341 self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
4343 def test_frag_out_of_order_dont_translate(self):
4344 """ NAT44 don't translate fragments arriving out of order """
4345 flags = self.config_flags.NAT_IS_INSIDE
4346 self.vapi.nat44_interface_add_del_feature(
4347 sw_if_index=self.pg0.sw_if_index,
4348 flags=flags, is_add=1)
4349 self.vapi.nat44_interface_add_del_feature(
4350 sw_if_index=self.pg1.sw_if_index,
4352 self.vapi.nat44_forwarding_enable_disable(enable=True)
4353 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4355 def test_frag_in_order_in_plus_out(self):
4356 """ in+out interface fragments in order """
4357 flags = self.config_flags.NAT_IS_INSIDE
4358 self.vapi.nat44_interface_add_del_feature(
4359 sw_if_index=self.pg0.sw_if_index,
4361 self.vapi.nat44_interface_add_del_feature(
4362 sw_if_index=self.pg0.sw_if_index,
4363 flags=flags, is_add=1)
4364 self.vapi.nat44_interface_add_del_feature(
4365 sw_if_index=self.pg1.sw_if_index,
4367 self.vapi.nat44_interface_add_del_feature(
4368 sw_if_index=self.pg1.sw_if_index,
4369 flags=flags, is_add=1)
4371 self.server = self.pg1.remote_hosts[0]
4373 self.server_in_addr = self.server.ip4
4374 self.server_out_addr = '11.11.11.11'
4375 self.server_in_port = random.randint(1025, 65535)
4376 self.server_out_port = random.randint(1025, 65535)
4378 self.nat44_add_address(self.server_out_addr)
4380 # add static mappings for server
4381 self.nat44_add_static_mapping(self.server_in_addr,
4382 self.server_out_addr,
4383 self.server_in_port,
4384 self.server_out_port,
4385 proto=IP_PROTOS.tcp)
4386 self.nat44_add_static_mapping(self.server_in_addr,
4387 self.server_out_addr,
4388 self.server_in_port,
4389 self.server_out_port,
4390 proto=IP_PROTOS.udp)
4391 self.nat44_add_static_mapping(self.server_in_addr,
4392 self.server_out_addr,
4393 proto=IP_PROTOS.icmp)
4395 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4396 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4397 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4399 def test_frag_out_of_order_in_plus_out(self):
4400 """ in+out interface fragments out of order """
4401 flags = self.config_flags.NAT_IS_INSIDE
4402 self.vapi.nat44_interface_add_del_feature(
4403 sw_if_index=self.pg0.sw_if_index,
4405 self.vapi.nat44_interface_add_del_feature(
4406 sw_if_index=self.pg0.sw_if_index,
4407 flags=flags, is_add=1)
4408 self.vapi.nat44_interface_add_del_feature(
4409 sw_if_index=self.pg1.sw_if_index,
4411 self.vapi.nat44_interface_add_del_feature(
4412 sw_if_index=self.pg1.sw_if_index,
4413 flags=flags, is_add=1)
4415 self.server = self.pg1.remote_hosts[0]
4417 self.server_in_addr = self.server.ip4
4418 self.server_out_addr = '11.11.11.11'
4419 self.server_in_port = random.randint(1025, 65535)
4420 self.server_out_port = random.randint(1025, 65535)
4422 self.nat44_add_address(self.server_out_addr)
4424 # add static mappings for server
4425 self.nat44_add_static_mapping(self.server_in_addr,
4426 self.server_out_addr,
4427 self.server_in_port,
4428 self.server_out_port,
4429 proto=IP_PROTOS.tcp)
4430 self.nat44_add_static_mapping(self.server_in_addr,
4431 self.server_out_addr,
4432 self.server_in_port,
4433 self.server_out_port,
4434 proto=IP_PROTOS.udp)
4435 self.nat44_add_static_mapping(self.server_in_addr,
4436 self.server_out_addr,
4437 proto=IP_PROTOS.icmp)
4439 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4440 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4441 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4443 def test_reass_hairpinning(self):
4444 """ NAT44 fragments hairpinning """
4445 self.server = self.pg0.remote_hosts[1]
4446 self.host_in_port = random.randint(1025, 65535)
4447 self.server_in_port = random.randint(1025, 65535)
4448 self.server_out_port = random.randint(1025, 65535)
4450 self.nat44_add_address(self.nat_addr)
4451 flags = self.config_flags.NAT_IS_INSIDE
4452 self.vapi.nat44_interface_add_del_feature(
4453 sw_if_index=self.pg0.sw_if_index,
4454 flags=flags, is_add=1)
4455 self.vapi.nat44_interface_add_del_feature(
4456 sw_if_index=self.pg1.sw_if_index,
4458 # add static mapping for server
4459 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4460 self.server_in_port,
4461 self.server_out_port,
4462 proto=IP_PROTOS.tcp)
4463 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4464 self.server_in_port,
4465 self.server_out_port,
4466 proto=IP_PROTOS.udp)
4467 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4469 self.reass_hairpinning(proto=IP_PROTOS.tcp, ignore_port=True)
4470 self.reass_hairpinning(proto=IP_PROTOS.udp, ignore_port=True)
4471 self.reass_hairpinning(proto=IP_PROTOS.icmp, ignore_port=True)
4473 def test_clear_sessions(self):
4474 """ NAT44 ED session clearing test """
4476 self.nat44_add_address(self.nat_addr)
4477 flags = self.config_flags.NAT_IS_INSIDE
4478 self.vapi.nat44_interface_add_del_feature(
4479 sw_if_index=self.pg0.sw_if_index,
4480 flags=flags, is_add=1)
4481 self.vapi.nat44_interface_add_del_feature(
4482 sw_if_index=self.pg1.sw_if_index,
4485 nat_config = self.vapi.nat_show_config()
4486 self.assertEqual(1, nat_config.endpoint_dependent)
4488 pkts = self.create_stream_in(self.pg0, self.pg1)
4489 self.pg0.add_stream(pkts)
4490 self.pg_enable_capture(self.pg_interfaces)
4492 capture = self.pg1.get_capture(len(pkts))
4493 self.verify_capture_out(capture, ignore_port=True)
4495 sessions = self.statistics.get_counter('/nat44/total-sessions')
4496 self.assertTrue(sessions[0][0] > 0)
4497 self.logger.info("sessions before clearing: %s" % sessions[0][0])
4499 # just for testing purposes
4500 self.logger.info(self.vapi.cli("show nat44 summary"))
4502 self.vapi.cli("clear nat44 sessions")
4504 self.logger.info(self.vapi.cli("show nat44 summary"))
4506 sessions = self.statistics.get_counter('/nat44/total-sessions')
4507 self.assertEqual(sessions[0][0], 0)
4508 self.logger.info("sessions after clearing: %s" % sessions[0][0])
4510 def test_dynamic(self):
4511 """ NAT44 dynamic translation test """
4513 self.nat44_add_address(self.nat_addr)
4514 flags = self.config_flags.NAT_IS_INSIDE
4515 self.vapi.nat44_interface_add_del_feature(
4516 sw_if_index=self.pg0.sw_if_index,
4517 flags=flags, is_add=1)
4518 self.vapi.nat44_interface_add_del_feature(
4519 sw_if_index=self.pg1.sw_if_index,
4522 nat_config = self.vapi.nat_show_config()
4523 self.assertEqual(1, nat_config.endpoint_dependent)
4526 tcpn = self.statistics.get_counter('/nat44/ed/in2out/slowpath/tcp')[0]
4527 udpn = self.statistics.get_counter('/nat44/ed/in2out/slowpath/udp')[0]
4528 icmpn = self.statistics.get_counter(
4529 '/nat44/ed/in2out/slowpath/icmp')[0]
4530 drops = self.statistics.get_counter(
4531 '/nat44/ed/in2out/slowpath/drops')[0]
4533 pkts = self.create_stream_in(self.pg0, self.pg1)
4534 self.pg0.add_stream(pkts)
4535 self.pg_enable_capture(self.pg_interfaces)
4537 capture = self.pg1.get_capture(len(pkts))
4538 self.verify_capture_out(capture, ignore_port=True)
4540 if_idx = self.pg0.sw_if_index
4541 cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/tcp')[0]
4542 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4543 cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/udp')[0]
4544 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4545 cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/icmp')[0]
4546 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4547 cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/drops')[0]
4548 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4551 tcpn = self.statistics.get_counter('/nat44/ed/out2in/fastpath/tcp')[0]
4552 udpn = self.statistics.get_counter('/nat44/ed/out2in/fastpath/udp')[0]
4553 icmpn = self.statistics.get_counter(
4554 '/nat44/ed/out2in/slowpath/icmp')[0]
4555 drops = self.statistics.get_counter(
4556 '/nat44/ed/out2in/fastpath/drops')[0]
4558 pkts = self.create_stream_out(self.pg1)
4559 self.pg1.add_stream(pkts)
4560 self.pg_enable_capture(self.pg_interfaces)
4562 capture = self.pg0.get_capture(len(pkts))
4563 self.verify_capture_in(capture, self.pg0)
4565 if_idx = self.pg1.sw_if_index
4566 cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/tcp')[0]
4567 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4568 cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/udp')[0]
4569 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4570 cnt = self.statistics.get_counter('/nat44/ed/out2in/slowpath/icmp')[0]
4571 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4572 cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/drops')[0]
4573 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4575 sessions = self.statistics.get_counter('/nat44/total-sessions')
4576 self.assertEqual(sessions[0][0], 3)
4578 def test_dynamic_out_of_ports(self):
4579 """ NAT44 dynamic translation test: out of ports """
4581 flags = self.config_flags.NAT_IS_INSIDE
4582 self.vapi.nat44_interface_add_del_feature(
4583 sw_if_index=self.pg0.sw_if_index,
4584 flags=flags, is_add=1)
4585 self.vapi.nat44_interface_add_del_feature(
4586 sw_if_index=self.pg1.sw_if_index,
4589 nat_config = self.vapi.nat_show_config()
4590 self.assertEqual(1, nat_config.endpoint_dependent)
4592 # in2out and no NAT addresses added
4593 err_old = self.statistics.get_err_counter(
4594 '/err/nat44-ed-in2out-slowpath/out of ports')
4596 pkts = self.create_stream_in(self.pg0, self.pg1)
4597 self.pg0.add_stream(pkts)
4598 self.pg_enable_capture(self.pg_interfaces)
4600 self.pg1.get_capture(0, timeout=1)
4602 err_new = self.statistics.get_err_counter(
4603 '/err/nat44-ed-in2out-slowpath/out of ports')
4605 self.assertEqual(err_new - err_old, len(pkts))
4607 # in2out after NAT addresses added
4608 self.nat44_add_address(self.nat_addr)
4610 err_old = self.statistics.get_err_counter(
4611 '/err/nat44-ed-in2out-slowpath/out of ports')
4613 pkts = self.create_stream_in(self.pg0, self.pg1)
4614 self.pg0.add_stream(pkts)
4615 self.pg_enable_capture(self.pg_interfaces)
4617 capture = self.pg1.get_capture(len(pkts))
4618 self.verify_capture_out(capture, ignore_port=True)
4620 err_new = self.statistics.get_err_counter(
4621 '/err/nat44-ed-in2out-slowpath/out of ports')
4623 self.assertEqual(err_new, err_old)
4625 def test_dynamic_output_feature_vrf(self):
4626 """ NAT44 dynamic translation test: output-feature, VRF"""
4628 # other then default (0)
4631 self.nat44_add_address(self.nat_addr)
4632 flags = self.config_flags.NAT_IS_INSIDE
4633 self.vapi.nat44_interface_add_del_output_feature(
4634 sw_if_index=self.pg7.sw_if_index,
4635 flags=flags, is_add=1)
4636 self.vapi.nat44_interface_add_del_output_feature(
4637 sw_if_index=self.pg8.sw_if_index,
4641 self.vapi.ip_table_add_del(is_add=1,
4642 table={'table_id': new_vrf_id})
4644 self.pg7.unconfig_ip4()
4645 self.pg7.set_table_ip4(new_vrf_id)
4646 self.pg7.config_ip4()
4647 self.pg7.resolve_arp()
4649 self.pg8.unconfig_ip4()
4650 self.pg8.set_table_ip4(new_vrf_id)
4651 self.pg8.config_ip4()
4652 self.pg8.resolve_arp()
4654 nat_config = self.vapi.nat_show_config()
4655 self.assertEqual(1, nat_config.endpoint_dependent)
4658 tcpn = self.statistics.get_counter(
4659 '/nat44/ed/in2out/slowpath/tcp')[0]
4660 udpn = self.statistics.get_counter(
4661 '/nat44/ed/in2out/slowpath/udp')[0]
4662 icmpn = self.statistics.get_counter(
4663 '/nat44/ed/in2out/slowpath/icmp')[0]
4664 drops = self.statistics.get_counter(
4665 '/nat44/ed/in2out/slowpath/drops')[0]
4667 pkts = self.create_stream_in(self.pg7, self.pg8)
4668 self.pg7.add_stream(pkts)
4669 self.pg_enable_capture(self.pg_interfaces)
4671 capture = self.pg8.get_capture(len(pkts))
4672 self.verify_capture_out(capture, ignore_port=True)
4674 if_idx = self.pg7.sw_if_index
4675 cnt = self.statistics.get_counter(
4676 '/nat44/ed/in2out/slowpath/tcp')[0]
4677 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4678 cnt = self.statistics.get_counter(
4679 '/nat44/ed/in2out/slowpath/udp')[0]
4680 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4681 cnt = self.statistics.get_counter(
4682 '/nat44/ed/in2out/slowpath/icmp')[0]
4683 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4684 cnt = self.statistics.get_counter(
4685 '/nat44/ed/in2out/slowpath/drops')[0]
4686 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4689 tcpn = self.statistics.get_counter(
4690 '/nat44/ed/out2in/fastpath/tcp')[0]
4691 udpn = self.statistics.get_counter(
4692 '/nat44/ed/out2in/fastpath/udp')[0]
4693 icmpn = self.statistics.get_counter(
4694 '/nat44/ed/out2in/slowpath/icmp')[0]
4695 drops = self.statistics.get_counter(
4696 '/nat44/ed/out2in/fastpath/drops')[0]
4698 pkts = self.create_stream_out(self.pg8)
4699 self.pg8.add_stream(pkts)
4700 self.pg_enable_capture(self.pg_interfaces)
4702 capture = self.pg7.get_capture(len(pkts))
4703 self.verify_capture_in(capture, self.pg7)
4705 if_idx = self.pg8.sw_if_index
4706 cnt = self.statistics.get_counter(
4707 '/nat44/ed/out2in/fastpath/tcp')[0]
4708 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4709 cnt = self.statistics.get_counter(
4710 '/nat44/ed/out2in/fastpath/udp')[0]
4711 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4712 cnt = self.statistics.get_counter(
4713 '/nat44/ed/out2in/slowpath/icmp')[0]
4714 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4715 cnt = self.statistics.get_counter(
4716 '/nat44/ed/out2in/fastpath/drops')[0]
4717 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4719 sessions = self.statistics.get_counter('/nat44/total-sessions')
4720 self.assertEqual(sessions[0][0], 3)
4723 self.pg7.unconfig_ip4()
4724 self.pg7.set_table_ip4(1)
4725 self.pg7.config_ip4()
4726 self.pg7.resolve_arp()
4728 self.pg8.unconfig_ip4()
4729 self.pg8.set_table_ip4(1)
4730 self.pg8.config_ip4()
4731 self.pg8.resolve_arp()
4733 self.vapi.ip_table_add_del(is_add=0,
4734 table={'table_id': new_vrf_id})
4736 def test_forwarding(self):
4737 """ NAT44 forwarding test """
4739 flags = self.config_flags.NAT_IS_INSIDE
4740 self.vapi.nat44_interface_add_del_feature(
4741 sw_if_index=self.pg0.sw_if_index,
4742 flags=flags, is_add=1)
4743 self.vapi.nat44_interface_add_del_feature(
4744 sw_if_index=self.pg1.sw_if_index,
4746 self.vapi.nat44_forwarding_enable_disable(enable=1)
4748 real_ip = self.pg0.remote_ip4
4749 alias_ip = self.nat_addr
4750 flags = self.config_flags.NAT_IS_ADDR_ONLY
4751 self.vapi.nat44_add_del_static_mapping(is_add=1,
4752 local_ip_address=real_ip,
4753 external_ip_address=alias_ip,
4754 external_sw_if_index=0xFFFFFFFF,
4758 # in2out - static mapping match
4760 pkts = self.create_stream_out(self.pg1)
4761 self.pg1.add_stream(pkts)
4762 self.pg_enable_capture(self.pg_interfaces)
4764 capture = self.pg0.get_capture(len(pkts))
4765 self.verify_capture_in(capture, self.pg0)
4767 pkts = self.create_stream_in(self.pg0, self.pg1)
4768 self.pg0.add_stream(pkts)
4769 self.pg_enable_capture(self.pg_interfaces)
4771 capture = self.pg1.get_capture(len(pkts))
4772 self.verify_capture_out(capture, same_port=True)
4774 # in2out - no static mapping match
4776 host0 = self.pg0.remote_hosts[0]
4777 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4779 pkts = self.create_stream_out(self.pg1,
4780 dst_ip=self.pg0.remote_ip4,
4781 use_inside_ports=True)
4782 self.pg1.add_stream(pkts)
4783 self.pg_enable_capture(self.pg_interfaces)
4785 capture = self.pg0.get_capture(len(pkts))
4786 self.verify_capture_in(capture, self.pg0)
4788 pkts = self.create_stream_in(self.pg0, self.pg1)
4789 self.pg0.add_stream(pkts)
4790 self.pg_enable_capture(self.pg_interfaces)
4792 capture = self.pg1.get_capture(len(pkts))
4793 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4796 self.pg0.remote_hosts[0] = host0
4798 user = self.pg0.remote_hosts[1]
4799 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4800 self.assertEqual(len(sessions), 3)
4801 self.assertTrue(sessions[0].flags &
4802 self.config_flags.NAT_IS_EXT_HOST_VALID)
4803 self.vapi.nat44_del_session(
4804 address=sessions[0].inside_ip_address,
4805 port=sessions[0].inside_port,
4806 protocol=sessions[0].protocol,
4807 flags=(self.config_flags.NAT_IS_INSIDE |
4808 self.config_flags.NAT_IS_EXT_HOST_VALID),
4809 ext_host_address=sessions[0].ext_host_address,
4810 ext_host_port=sessions[0].ext_host_port)
4811 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4812 self.assertEqual(len(sessions), 2)
4815 self.vapi.nat44_forwarding_enable_disable(enable=0)
4816 flags = self.config_flags.NAT_IS_ADDR_ONLY
4817 self.vapi.nat44_add_del_static_mapping(
4819 local_ip_address=real_ip,
4820 external_ip_address=alias_ip,
4821 external_sw_if_index=0xFFFFFFFF,
4824 def test_static_lb(self):
4825 """ NAT44 local service load balancing """
4826 external_addr_n = self.nat_addr
4829 server1 = self.pg0.remote_hosts[0]
4830 server2 = self.pg0.remote_hosts[1]
4832 locals = [{'addr': server1.ip4,
4836 {'addr': server2.ip4,
4841 self.nat44_add_address(self.nat_addr)
4842 self.vapi.nat44_add_del_lb_static_mapping(
4844 external_addr=external_addr_n,
4845 external_port=external_port,
4846 protocol=IP_PROTOS.tcp,
4847 local_num=len(locals),
4849 flags = self.config_flags.NAT_IS_INSIDE
4850 self.vapi.nat44_interface_add_del_feature(
4851 sw_if_index=self.pg0.sw_if_index,
4852 flags=flags, is_add=1)
4853 self.vapi.nat44_interface_add_del_feature(
4854 sw_if_index=self.pg1.sw_if_index,
4857 # from client to service
4858 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4859 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4860 TCP(sport=12345, dport=external_port))
4861 self.pg1.add_stream(p)
4862 self.pg_enable_capture(self.pg_interfaces)
4864 capture = self.pg0.get_capture(1)
4870 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4871 if ip.dst == server1.ip4:
4875 self.assertEqual(tcp.dport, local_port)
4876 self.assert_packet_checksums_valid(p)
4878 self.logger.error(ppp("Unexpected or invalid packet:", p))
4881 # from service back to client
4882 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4883 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4884 TCP(sport=local_port, dport=12345))
4885 self.pg0.add_stream(p)
4886 self.pg_enable_capture(self.pg_interfaces)
4888 capture = self.pg1.get_capture(1)
4893 self.assertEqual(ip.src, self.nat_addr)
4894 self.assertEqual(tcp.sport, external_port)
4895 self.assert_packet_checksums_valid(p)
4897 self.logger.error(ppp("Unexpected or invalid packet:", p))
4900 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4901 self.assertEqual(len(sessions), 1)
4902 self.assertTrue(sessions[0].flags &
4903 self.config_flags.NAT_IS_EXT_HOST_VALID)
4904 self.vapi.nat44_del_session(
4905 address=sessions[0].inside_ip_address,
4906 port=sessions[0].inside_port,
4907 protocol=sessions[0].protocol,
4908 flags=(self.config_flags.NAT_IS_INSIDE |
4909 self.config_flags.NAT_IS_EXT_HOST_VALID),
4910 ext_host_address=sessions[0].ext_host_address,
4911 ext_host_port=sessions[0].ext_host_port)
4912 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4913 self.assertEqual(len(sessions), 0)
4915 def test_static_lb_multi_clients(self):
4916 """ NAT44 local service load balancing - multiple clients"""
4918 external_addr = self.nat_addr
4921 server1 = self.pg0.remote_hosts[0]
4922 server2 = self.pg0.remote_hosts[1]
4923 server3 = self.pg0.remote_hosts[2]
4925 locals = [{'addr': server1.ip4,
4929 {'addr': server2.ip4,
4934 flags = self.config_flags.NAT_IS_INSIDE
4935 self.vapi.nat44_interface_add_del_feature(
4936 sw_if_index=self.pg0.sw_if_index,
4937 flags=flags, is_add=1)
4938 self.vapi.nat44_interface_add_del_feature(
4939 sw_if_index=self.pg1.sw_if_index,
4942 self.nat44_add_address(self.nat_addr)
4943 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4944 external_addr=external_addr,
4945 external_port=external_port,
4946 protocol=IP_PROTOS.tcp,
4947 local_num=len(locals),
4952 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4954 for client in clients:
4955 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4956 IP(src=client, dst=self.nat_addr) /
4957 TCP(sport=12345, dport=external_port))
4959 self.pg1.add_stream(pkts)
4960 self.pg_enable_capture(self.pg_interfaces)
4962 capture = self.pg0.get_capture(len(pkts))
4964 if p[IP].dst == server1.ip4:
4968 self.assertGreater(server1_n, server2_n)
4971 'addr': server3.ip4,
4978 self.vapi.nat44_lb_static_mapping_add_del_local(
4980 external_addr=external_addr,
4981 external_port=external_port,
4983 protocol=IP_PROTOS.tcp)
4987 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4989 for client in clients:
4990 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4991 IP(src=client, dst=self.nat_addr) /
4992 TCP(sport=12346, dport=external_port))
4994 self.assertGreater(len(pkts), 0)
4995 self.pg1.add_stream(pkts)
4996 self.pg_enable_capture(self.pg_interfaces)
4998 capture = self.pg0.get_capture(len(pkts))
5000 if p[IP].dst == server1.ip4:
5002 elif p[IP].dst == server2.ip4:
5006 self.assertGreater(server1_n, 0)
5007 self.assertGreater(server2_n, 0)
5008 self.assertGreater(server3_n, 0)
5011 'addr': server2.ip4,
5017 # remove one back-end
5018 self.vapi.nat44_lb_static_mapping_add_del_local(
5020 external_addr=external_addr,
5021 external_port=external_port,
5023 protocol=IP_PROTOS.tcp)
5027 self.pg1.add_stream(pkts)
5028 self.pg_enable_capture(self.pg_interfaces)
5030 capture = self.pg0.get_capture(len(pkts))
5032 if p[IP].dst == server1.ip4:
5034 elif p[IP].dst == server2.ip4:
5038 self.assertGreater(server1_n, 0)
5039 self.assertEqual(server2_n, 0)
5040 self.assertGreater(server3_n, 0)
5042 def test_static_lb_2(self):
5043 """ NAT44 local service load balancing (asymmetrical rule) """
5044 external_addr = self.nat_addr
5047 server1 = self.pg0.remote_hosts[0]
5048 server2 = self.pg0.remote_hosts[1]
5050 locals = [{'addr': server1.ip4,
5054 {'addr': server2.ip4,
5059 self.vapi.nat44_forwarding_enable_disable(enable=1)
5060 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5061 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5062 external_addr=external_addr,
5063 external_port=external_port,
5064 protocol=IP_PROTOS.tcp,
5065 local_num=len(locals),
5067 flags = self.config_flags.NAT_IS_INSIDE
5068 self.vapi.nat44_interface_add_del_feature(
5069 sw_if_index=self.pg0.sw_if_index,
5070 flags=flags, is_add=1)
5071 self.vapi.nat44_interface_add_del_feature(
5072 sw_if_index=self.pg1.sw_if_index,
5075 # from client to service
5076 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5077 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5078 TCP(sport=12345, dport=external_port))
5079 self.pg1.add_stream(p)
5080 self.pg_enable_capture(self.pg_interfaces)
5082 capture = self.pg0.get_capture(1)
5088 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5089 if ip.dst == server1.ip4:
5093 self.assertEqual(tcp.dport, local_port)
5094 self.assert_packet_checksums_valid(p)
5096 self.logger.error(ppp("Unexpected or invalid packet:", p))
5099 # from service back to client
5100 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5101 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5102 TCP(sport=local_port, dport=12345))
5103 self.pg0.add_stream(p)
5104 self.pg_enable_capture(self.pg_interfaces)
5106 capture = self.pg1.get_capture(1)
5111 self.assertEqual(ip.src, self.nat_addr)
5112 self.assertEqual(tcp.sport, external_port)
5113 self.assert_packet_checksums_valid(p)
5115 self.logger.error(ppp("Unexpected or invalid packet:", p))
5118 # from client to server (no translation)
5119 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5120 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5121 TCP(sport=12346, dport=local_port))
5122 self.pg1.add_stream(p)
5123 self.pg_enable_capture(self.pg_interfaces)
5125 capture = self.pg0.get_capture(1)
5131 self.assertEqual(ip.dst, server1.ip4)
5132 self.assertEqual(tcp.dport, local_port)
5133 self.assert_packet_checksums_valid(p)
5135 self.logger.error(ppp("Unexpected or invalid packet:", p))
5138 # from service back to client (no translation)
5139 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5140 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5141 TCP(sport=local_port, dport=12346))
5142 self.pg0.add_stream(p)
5143 self.pg_enable_capture(self.pg_interfaces)
5145 capture = self.pg1.get_capture(1)
5150 self.assertEqual(ip.src, server1.ip4)
5151 self.assertEqual(tcp.sport, local_port)
5152 self.assert_packet_checksums_valid(p)
5154 self.logger.error(ppp("Unexpected or invalid packet:", p))
5157 def test_lb_affinity(self):
5158 """ NAT44 local service load balancing affinity """
5159 external_addr = self.nat_addr
5162 server1 = self.pg0.remote_hosts[0]
5163 server2 = self.pg0.remote_hosts[1]
5165 locals = [{'addr': server1.ip4,
5169 {'addr': server2.ip4,
5174 self.nat44_add_address(self.nat_addr)
5175 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5176 external_addr=external_addr,
5177 external_port=external_port,
5178 protocol=IP_PROTOS.tcp,
5180 local_num=len(locals),
5182 flags = self.config_flags.NAT_IS_INSIDE
5183 self.vapi.nat44_interface_add_del_feature(
5184 sw_if_index=self.pg0.sw_if_index,
5185 flags=flags, is_add=1)
5186 self.vapi.nat44_interface_add_del_feature(
5187 sw_if_index=self.pg1.sw_if_index,
5190 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5191 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5192 TCP(sport=1025, dport=external_port))
5193 self.pg1.add_stream(p)
5194 self.pg_enable_capture(self.pg_interfaces)
5196 capture = self.pg0.get_capture(1)
5197 backend = capture[0][IP].dst
5199 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5200 self.assertEqual(len(sessions), 1)
5201 self.assertTrue(sessions[0].flags &
5202 self.config_flags.NAT_IS_EXT_HOST_VALID)
5203 self.vapi.nat44_del_session(
5204 address=sessions[0].inside_ip_address,
5205 port=sessions[0].inside_port,
5206 protocol=sessions[0].protocol,
5207 flags=(self.config_flags.NAT_IS_INSIDE |
5208 self.config_flags.NAT_IS_EXT_HOST_VALID),
5209 ext_host_address=sessions[0].ext_host_address,
5210 ext_host_port=sessions[0].ext_host_port)
5213 for port in range(1030, 1100):
5214 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5215 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5216 TCP(sport=port, dport=external_port))
5218 self.pg1.add_stream(pkts)
5219 self.pg_enable_capture(self.pg_interfaces)
5221 capture = self.pg0.get_capture(len(pkts))
5223 self.assertEqual(p[IP].dst, backend)
5225 def test_unknown_proto(self):
5226 """ NAT44 translate packet with unknown protocol """
5227 self.nat44_add_address(self.nat_addr)
5228 flags = self.config_flags.NAT_IS_INSIDE
5229 self.vapi.nat44_interface_add_del_feature(
5230 sw_if_index=self.pg0.sw_if_index,
5231 flags=flags, is_add=1)
5232 self.vapi.nat44_interface_add_del_feature(
5233 sw_if_index=self.pg1.sw_if_index,
5237 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5238 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5239 TCP(sport=self.tcp_port_in, dport=20))
5240 self.pg0.add_stream(p)
5241 self.pg_enable_capture(self.pg_interfaces)
5243 p = self.pg1.get_capture(1)
5245 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5246 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5248 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5249 TCP(sport=1234, dport=1234))
5250 self.pg0.add_stream(p)
5251 self.pg_enable_capture(self.pg_interfaces)
5253 p = self.pg1.get_capture(1)
5256 self.assertEqual(packet[IP].src, self.nat_addr)
5257 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5258 self.assertEqual(packet.haslayer(GRE), 1)
5259 self.assert_packet_checksums_valid(packet)
5261 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5265 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5266 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5268 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5269 TCP(sport=1234, dport=1234))
5270 self.pg1.add_stream(p)
5271 self.pg_enable_capture(self.pg_interfaces)
5273 p = self.pg0.get_capture(1)
5276 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5277 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5278 self.assertEqual(packet.haslayer(GRE), 1)
5279 self.assert_packet_checksums_valid(packet)
5281 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5284 def test_hairpinning_unknown_proto(self):
5285 """ NAT44 translate packet with unknown protocol - hairpinning """
5286 host = self.pg0.remote_hosts[0]
5287 server = self.pg0.remote_hosts[1]
5289 server_out_port = 8765
5290 server_nat_ip = "10.0.0.11"
5292 self.nat44_add_address(self.nat_addr)
5293 flags = self.config_flags.NAT_IS_INSIDE
5294 self.vapi.nat44_interface_add_del_feature(
5295 sw_if_index=self.pg0.sw_if_index,
5296 flags=flags, is_add=1)
5297 self.vapi.nat44_interface_add_del_feature(
5298 sw_if_index=self.pg1.sw_if_index,
5301 # add static mapping for server
5302 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5305 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5306 IP(src=host.ip4, dst=server_nat_ip) /
5307 TCP(sport=host_in_port, dport=server_out_port))
5308 self.pg0.add_stream(p)
5309 self.pg_enable_capture(self.pg_interfaces)
5311 self.pg0.get_capture(1)
5313 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5314 IP(src=host.ip4, dst=server_nat_ip) /
5316 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5317 TCP(sport=1234, dport=1234))
5318 self.pg0.add_stream(p)
5319 self.pg_enable_capture(self.pg_interfaces)
5321 p = self.pg0.get_capture(1)
5324 self.assertEqual(packet[IP].src, self.nat_addr)
5325 self.assertEqual(packet[IP].dst, server.ip4)
5326 self.assertEqual(packet.haslayer(GRE), 1)
5327 self.assert_packet_checksums_valid(packet)
5329 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5333 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5334 IP(src=server.ip4, dst=self.nat_addr) /
5336 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5337 TCP(sport=1234, dport=1234))
5338 self.pg0.add_stream(p)
5339 self.pg_enable_capture(self.pg_interfaces)
5341 p = self.pg0.get_capture(1)
5344 self.assertEqual(packet[IP].src, server_nat_ip)
5345 self.assertEqual(packet[IP].dst, host.ip4)
5346 self.assertEqual(packet.haslayer(GRE), 1)
5347 self.assert_packet_checksums_valid(packet)
5349 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5352 def test_output_feature_and_service(self):
5353 """ NAT44 interface output feature and services """
5354 external_addr = '1.2.3.4'
5358 self.vapi.nat44_forwarding_enable_disable(enable=1)
5359 self.nat44_add_address(self.nat_addr)
5360 flags = self.config_flags.NAT_IS_ADDR_ONLY
5361 self.vapi.nat44_add_del_identity_mapping(
5362 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5363 flags=flags, is_add=1)
5364 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5365 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5366 local_port, external_port,
5367 proto=IP_PROTOS.tcp, flags=flags)
5368 flags = self.config_flags.NAT_IS_INSIDE
5369 self.vapi.nat44_interface_add_del_feature(
5370 sw_if_index=self.pg0.sw_if_index,
5372 self.vapi.nat44_interface_add_del_feature(
5373 sw_if_index=self.pg0.sw_if_index,
5374 flags=flags, is_add=1)
5375 self.vapi.nat44_interface_add_del_output_feature(
5377 sw_if_index=self.pg1.sw_if_index)
5379 # from client to service
5380 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5381 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5382 TCP(sport=12345, dport=external_port))
5383 self.pg1.add_stream(p)
5384 self.pg_enable_capture(self.pg_interfaces)
5386 capture = self.pg0.get_capture(1)
5391 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5392 self.assertEqual(tcp.dport, local_port)
5393 self.assert_packet_checksums_valid(p)
5395 self.logger.error(ppp("Unexpected or invalid packet:", p))
5398 # from service back to client
5399 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5400 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5401 TCP(sport=local_port, dport=12345))
5402 self.pg0.add_stream(p)
5403 self.pg_enable_capture(self.pg_interfaces)
5405 capture = self.pg1.get_capture(1)
5410 self.assertEqual(ip.src, external_addr)
5411 self.assertEqual(tcp.sport, external_port)
5412 self.assert_packet_checksums_valid(p)
5414 self.logger.error(ppp("Unexpected or invalid packet:", p))
5417 # from local network host to external network
5418 pkts = self.create_stream_in(self.pg0, self.pg1)
5419 self.pg0.add_stream(pkts)
5420 self.pg_enable_capture(self.pg_interfaces)
5422 capture = self.pg1.get_capture(len(pkts))
5423 self.verify_capture_out(capture, ignore_port=True)
5424 pkts = self.create_stream_in(self.pg0, self.pg1)
5425 self.pg0.add_stream(pkts)
5426 self.pg_enable_capture(self.pg_interfaces)
5428 capture = self.pg1.get_capture(len(pkts))
5429 self.verify_capture_out(capture, ignore_port=True)
5431 # from external network back to local network host
5432 pkts = self.create_stream_out(self.pg1)
5433 self.pg1.add_stream(pkts)
5434 self.pg_enable_capture(self.pg_interfaces)
5436 capture = self.pg0.get_capture(len(pkts))
5437 self.verify_capture_in(capture, self.pg0)
5439 def test_output_feature_and_service2(self):
5440 """ NAT44 interface output feature and service host direct access """
5441 self.vapi.nat44_forwarding_enable_disable(enable=1)
5442 self.nat44_add_address(self.nat_addr)
5443 self.vapi.nat44_interface_add_del_output_feature(
5445 sw_if_index=self.pg1.sw_if_index)
5447 # session initiated from service host - translate
5448 pkts = self.create_stream_in(self.pg0, self.pg1)
5449 self.pg0.add_stream(pkts)
5450 self.pg_enable_capture(self.pg_interfaces)
5452 capture = self.pg1.get_capture(len(pkts))
5453 self.verify_capture_out(capture, ignore_port=True)
5455 pkts = self.create_stream_out(self.pg1)
5456 self.pg1.add_stream(pkts)
5457 self.pg_enable_capture(self.pg_interfaces)
5459 capture = self.pg0.get_capture(len(pkts))
5460 self.verify_capture_in(capture, self.pg0)
5462 # session initiated from remote host - do not translate
5463 self.tcp_port_in = 60303
5464 self.udp_port_in = 60304
5465 self.icmp_id_in = 60305
5466 pkts = self.create_stream_out(self.pg1,
5467 self.pg0.remote_ip4,
5468 use_inside_ports=True)
5469 self.pg1.add_stream(pkts)
5470 self.pg_enable_capture(self.pg_interfaces)
5472 capture = self.pg0.get_capture(len(pkts))
5473 self.verify_capture_in(capture, self.pg0)
5475 pkts = self.create_stream_in(self.pg0, self.pg1)
5476 self.pg0.add_stream(pkts)
5477 self.pg_enable_capture(self.pg_interfaces)
5479 capture = self.pg1.get_capture(len(pkts))
5480 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5483 def test_output_feature_and_service3(self):
5484 """ NAT44 interface output feature and DST NAT """
5485 external_addr = '1.2.3.4'
5489 self.vapi.nat44_forwarding_enable_disable(enable=1)
5490 self.nat44_add_address(self.nat_addr)
5491 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5492 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5493 local_port, external_port,
5494 proto=IP_PROTOS.tcp, flags=flags)
5495 flags = self.config_flags.NAT_IS_INSIDE
5496 self.vapi.nat44_interface_add_del_feature(
5497 sw_if_index=self.pg0.sw_if_index,
5499 self.vapi.nat44_interface_add_del_feature(
5500 sw_if_index=self.pg0.sw_if_index,
5501 flags=flags, is_add=1)
5502 self.vapi.nat44_interface_add_del_output_feature(
5504 sw_if_index=self.pg1.sw_if_index)
5506 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5507 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5508 TCP(sport=12345, dport=external_port))
5509 self.pg0.add_stream(p)
5510 self.pg_enable_capture(self.pg_interfaces)
5512 capture = self.pg1.get_capture(1)
5517 self.assertEqual(ip.src, self.pg0.remote_ip4)
5518 self.assertEqual(tcp.sport, 12345)
5519 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5520 self.assertEqual(tcp.dport, local_port)
5521 self.assert_packet_checksums_valid(p)
5523 self.logger.error(ppp("Unexpected or invalid packet:", p))
5526 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5527 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5528 TCP(sport=local_port, dport=12345))
5529 self.pg1.add_stream(p)
5530 self.pg_enable_capture(self.pg_interfaces)
5532 capture = self.pg0.get_capture(1)
5537 self.assertEqual(ip.src, external_addr)
5538 self.assertEqual(tcp.sport, external_port)
5539 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5540 self.assertEqual(tcp.dport, 12345)
5541 self.assert_packet_checksums_valid(p)
5543 self.logger.error(ppp("Unexpected or invalid packet:", p))
5546 def test_next_src_nat(self):
5547 """ On way back forward packet to nat44-in2out node. """
5548 twice_nat_addr = '10.0.1.3'
5551 post_twice_nat_port = 0
5553 self.vapi.nat44_forwarding_enable_disable(enable=1)
5554 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5555 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5556 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5557 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5558 local_port, external_port,
5559 proto=IP_PROTOS.tcp, vrf_id=1,
5561 self.vapi.nat44_interface_add_del_feature(
5562 sw_if_index=self.pg6.sw_if_index,
5565 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5566 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5567 TCP(sport=12345, dport=external_port))
5568 self.pg6.add_stream(p)
5569 self.pg_enable_capture(self.pg_interfaces)
5571 capture = self.pg6.get_capture(1)
5576 self.assertEqual(ip.src, twice_nat_addr)
5577 self.assertNotEqual(tcp.sport, 12345)
5578 post_twice_nat_port = tcp.sport
5579 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5580 self.assertEqual(tcp.dport, local_port)
5581 self.assert_packet_checksums_valid(p)
5583 self.logger.error(ppp("Unexpected or invalid packet:", p))
5586 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5587 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5588 TCP(sport=local_port, dport=post_twice_nat_port))
5589 self.pg6.add_stream(p)
5590 self.pg_enable_capture(self.pg_interfaces)
5592 capture = self.pg6.get_capture(1)
5597 self.assertEqual(ip.src, self.pg1.remote_ip4)
5598 self.assertEqual(tcp.sport, external_port)
5599 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5600 self.assertEqual(tcp.dport, 12345)
5601 self.assert_packet_checksums_valid(p)
5603 self.logger.error(ppp("Unexpected or invalid packet:", p))
5606 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5608 twice_nat_addr = '10.0.1.3'
5616 port_in1 = port_in + 1
5617 port_in2 = port_in + 2
5622 server1 = self.pg0.remote_hosts[0]
5623 server2 = self.pg0.remote_hosts[1]
5635 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5638 self.nat44_add_address(self.nat_addr)
5639 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5643 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5645 flags |= self.config_flags.NAT_IS_TWICE_NAT
5648 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5650 proto=IP_PROTOS.tcp,
5653 locals = [{'addr': server1.ip4,
5657 {'addr': server2.ip4,
5661 out_addr = self.nat_addr
5663 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5664 external_addr=out_addr,
5665 external_port=port_out,
5666 protocol=IP_PROTOS.tcp,
5667 local_num=len(locals),
5669 flags = self.config_flags.NAT_IS_INSIDE
5670 self.vapi.nat44_interface_add_del_feature(
5671 sw_if_index=pg0.sw_if_index,
5672 flags=flags, is_add=1)
5673 self.vapi.nat44_interface_add_del_feature(
5674 sw_if_index=pg1.sw_if_index,
5681 assert client_id is not None
5683 client = self.pg0.remote_hosts[0]
5684 elif client_id == 2:
5685 client = self.pg0.remote_hosts[1]
5687 client = pg1.remote_hosts[0]
5688 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5689 IP(src=client.ip4, dst=self.nat_addr) /
5690 TCP(sport=eh_port_out, dport=port_out))
5692 self.pg_enable_capture(self.pg_interfaces)
5694 capture = pg0.get_capture(1)
5700 if ip.dst == server1.ip4:
5706 self.assertEqual(ip.dst, server.ip4)
5708 self.assertIn(tcp.dport, [port_in1, port_in2])
5710 self.assertEqual(tcp.dport, port_in)
5712 self.assertEqual(ip.src, twice_nat_addr)
5713 self.assertNotEqual(tcp.sport, eh_port_out)
5715 self.assertEqual(ip.src, client.ip4)
5716 self.assertEqual(tcp.sport, eh_port_out)
5718 eh_port_in = tcp.sport
5719 saved_port_in = tcp.dport
5720 self.assert_packet_checksums_valid(p)
5722 self.logger.error(ppp("Unexpected or invalid packet:", p))
5725 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5726 IP(src=server.ip4, dst=eh_addr_in) /
5727 TCP(sport=saved_port_in, dport=eh_port_in))
5729 self.pg_enable_capture(self.pg_interfaces)
5731 capture = pg1.get_capture(1)
5736 self.assertEqual(ip.dst, client.ip4)
5737 self.assertEqual(ip.src, self.nat_addr)
5738 self.assertEqual(tcp.dport, eh_port_out)
5739 self.assertEqual(tcp.sport, port_out)
5740 self.assert_packet_checksums_valid(p)
5742 self.logger.error(ppp("Unexpected or invalid packet:", p))
5746 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5747 self.assertEqual(len(sessions), 1)
5748 self.assertTrue(sessions[0].flags &
5749 self.config_flags.NAT_IS_EXT_HOST_VALID)
5750 self.assertTrue(sessions[0].flags &
5751 self.config_flags.NAT_IS_TWICE_NAT)
5752 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5753 self.vapi.nat44_del_session(
5754 address=sessions[0].inside_ip_address,
5755 port=sessions[0].inside_port,
5756 protocol=sessions[0].protocol,
5757 flags=(self.config_flags.NAT_IS_INSIDE |
5758 self.config_flags.NAT_IS_EXT_HOST_VALID),
5759 ext_host_address=sessions[0].ext_host_nat_address,
5760 ext_host_port=sessions[0].ext_host_nat_port)
5761 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5762 self.assertEqual(len(sessions), 0)
5764 def test_twice_nat(self):
5766 self.twice_nat_common()
5768 def test_self_twice_nat_positive(self):
5769 """ Self Twice NAT44 (positive test) """
5770 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5772 def test_self_twice_nat_negative(self):
5773 """ Self Twice NAT44 (negative test) """
5774 self.twice_nat_common(self_twice_nat=True)
5776 def test_twice_nat_lb(self):
5777 """ Twice NAT44 local service load balancing """
5778 self.twice_nat_common(lb=True)
5780 def test_self_twice_nat_lb_positive(self):
5781 """ Self Twice NAT44 local service load balancing (positive test) """
5782 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5785 def test_self_twice_nat_lb_negative(self):
5786 """ Self Twice NAT44 local service load balancing (negative test) """
5787 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5790 def test_twice_nat_interface_addr(self):
5791 """ Acquire twice NAT44 addresses from interface """
5792 flags = self.config_flags.NAT_IS_TWICE_NAT
5793 self.vapi.nat44_add_del_interface_addr(
5795 sw_if_index=self.pg3.sw_if_index,
5798 # no address in NAT pool
5799 adresses = self.vapi.nat44_address_dump()
5800 self.assertEqual(0, len(adresses))
5802 # configure interface address and check NAT address pool
5803 self.pg3.config_ip4()
5804 adresses = self.vapi.nat44_address_dump()
5805 self.assertEqual(1, len(adresses))
5806 self.assertEqual(str(adresses[0].ip_address),
5808 self.assertEqual(adresses[0].flags, flags)
5810 # remove interface address and check NAT address pool
5811 self.pg3.unconfig_ip4()
5812 adresses = self.vapi.nat44_address_dump()
5813 self.assertEqual(0, len(adresses))
5815 def test_tcp_close(self):
5816 """ Close TCP session from inside network - output feature """
5817 old_timeouts = self.vapi.nat_get_timeouts()
5819 self.vapi.nat_set_timeouts(
5820 udp=old_timeouts.udp,
5821 tcp_established=old_timeouts.tcp_established,
5822 icmp=old_timeouts.icmp,
5823 tcp_transitory=new_transitory)
5825 self.vapi.nat44_forwarding_enable_disable(enable=1)
5826 self.nat44_add_address(self.pg1.local_ip4)
5827 twice_nat_addr = '10.0.1.3'
5828 service_ip = '192.168.16.150'
5829 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5830 flags = self.config_flags.NAT_IS_INSIDE
5831 self.vapi.nat44_interface_add_del_feature(
5832 sw_if_index=self.pg0.sw_if_index,
5834 self.vapi.nat44_interface_add_del_feature(
5835 sw_if_index=self.pg0.sw_if_index,
5836 flags=flags, is_add=1)
5837 self.vapi.nat44_interface_add_del_output_feature(
5839 sw_if_index=self.pg1.sw_if_index)
5840 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5841 self.config_flags.NAT_IS_TWICE_NAT)
5842 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5846 proto=IP_PROTOS.tcp,
5848 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5849 start_sessnum = len(sessions)
5851 # SYN packet out->in
5852 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5853 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5854 TCP(sport=33898, dport=80, flags="S"))
5855 self.pg1.add_stream(p)
5856 self.pg_enable_capture(self.pg_interfaces)
5858 capture = self.pg0.get_capture(1)
5860 tcp_port = p[TCP].sport
5862 # SYN + ACK packet in->out
5863 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5864 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5865 TCP(sport=80, dport=tcp_port, flags="SA"))
5866 self.pg0.add_stream(p)
5867 self.pg_enable_capture(self.pg_interfaces)
5869 self.pg1.get_capture(1)
5871 # ACK packet out->in
5872 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5873 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5874 TCP(sport=33898, dport=80, flags="A"))
5875 self.pg1.add_stream(p)
5876 self.pg_enable_capture(self.pg_interfaces)
5878 self.pg0.get_capture(1)
5880 # FIN packet in -> out
5881 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5882 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5883 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5884 self.pg0.add_stream(p)
5885 self.pg_enable_capture(self.pg_interfaces)
5887 self.pg1.get_capture(1)
5889 # FIN+ACK packet out -> in
5890 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5891 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5892 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5893 self.pg1.add_stream(p)
5894 self.pg_enable_capture(self.pg_interfaces)
5896 self.pg0.get_capture(1)
5898 # ACK packet in -> out
5899 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5900 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5901 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5902 self.pg0.add_stream(p)
5903 self.pg_enable_capture(self.pg_interfaces)
5905 self.pg1.get_capture(1)
5907 # session now in transitory timeout
5908 # try SYN packet out->in - should be dropped
5909 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5910 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5911 TCP(sport=33898, dport=80, flags="S"))
5912 self.pg1.add_stream(p)
5913 self.pg_enable_capture(self.pg_interfaces)
5916 self.sleep(new_transitory, "wait for transitory timeout")
5917 self.pg0.assert_nothing_captured(0)
5919 # session should still exist
5920 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5921 self.assertEqual(len(sessions) - start_sessnum, 1)
5923 # send FIN+ACK packet out -> in - will cause session to be wiped
5924 # but won't create a new session
5925 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5926 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5927 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5928 self.pg1.add_stream(p)
5929 self.pg_enable_capture(self.pg_interfaces)
5932 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5933 self.assertEqual(len(sessions) - start_sessnum, 0)
5934 self.pg0.assert_nothing_captured(0)
5936 def test_tcp_session_close_in(self):
5937 """ Close TCP session from inside network """
5938 self.tcp_port_out = 10505
5939 self.nat44_add_address(self.nat_addr)
5940 flags = self.config_flags.NAT_IS_TWICE_NAT
5941 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5945 proto=IP_PROTOS.tcp,
5947 flags = self.config_flags.NAT_IS_INSIDE
5948 self.vapi.nat44_interface_add_del_feature(
5949 sw_if_index=self.pg0.sw_if_index,
5950 flags=flags, is_add=1)
5951 self.vapi.nat44_interface_add_del_feature(
5952 sw_if_index=self.pg1.sw_if_index,
5955 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5956 start_sessnum = len(sessions)
5958 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5959 tcp_transitory=2, icmp=5)
5961 self.initiate_tcp_session(self.pg0, self.pg1)
5963 # FIN packet in -> out
5964 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5965 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5966 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5967 flags="FA", seq=100, ack=300))
5968 self.pg0.add_stream(p)
5969 self.pg_enable_capture(self.pg_interfaces)
5971 self.pg1.get_capture(1)
5975 # ACK packet out -> in
5976 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5977 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5978 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5979 flags="A", seq=300, ack=101))
5982 # FIN packet out -> in
5983 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5984 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5985 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5986 flags="FA", seq=300, ack=101))
5989 self.pg1.add_stream(pkts)
5990 self.pg_enable_capture(self.pg_interfaces)
5992 self.pg0.get_capture(2)
5994 # ACK packet in -> out
5995 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5996 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5997 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5998 flags="A", seq=101, ack=301))
5999 self.pg0.add_stream(p)
6000 self.pg_enable_capture(self.pg_interfaces)
6002 self.pg1.get_capture(1)
6004 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6005 self.assertEqual(len(sessions) - start_sessnum, 1)
6007 stats = self.statistics.get_counter(
6008 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6009 out2in_drops = stats[0]
6010 stats = self.statistics.get_counter(
6011 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6012 in2out_drops = stats[0]
6014 # extra FIN packet out -> in - this should be dropped
6015 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6016 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6017 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6018 flags="FA", seq=300, ack=101))
6020 self.pg1.add_stream(p)
6021 self.pg_enable_capture(self.pg_interfaces)
6023 self.pg0.assert_nothing_captured()
6025 # extra ACK packet in -> out - this should be dropped
6026 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6027 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6028 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6029 flags="A", seq=101, ack=301))
6030 self.pg0.add_stream(p)
6031 self.pg_enable_capture(self.pg_interfaces)
6033 self.pg1.assert_nothing_captured()
6035 stats = self.statistics.get_counter(
6036 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6037 self.assertEqual(stats[0] - out2in_drops, 1)
6038 stats = self.statistics.get_counter(
6039 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6040 self.assertEqual(stats[0] - in2out_drops, 1)
6043 # extra ACK packet in -> out - this will cause session to be wiped
6044 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6045 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6046 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6047 flags="A", seq=101, ack=301))
6048 self.pg0.add_stream(p)
6049 self.pg_enable_capture(self.pg_interfaces)
6051 self.pg1.assert_nothing_captured()
6052 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6053 self.assertEqual(len(sessions) - start_sessnum, 0)
6055 def test_tcp_session_close_out(self):
6056 """ Close TCP session from outside network """
6057 self.tcp_port_out = 10505
6058 self.nat44_add_address(self.nat_addr)
6059 flags = self.config_flags.NAT_IS_TWICE_NAT
6060 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6064 proto=IP_PROTOS.tcp,
6066 flags = self.config_flags.NAT_IS_INSIDE
6067 self.vapi.nat44_interface_add_del_feature(
6068 sw_if_index=self.pg0.sw_if_index,
6069 flags=flags, is_add=1)
6070 self.vapi.nat44_interface_add_del_feature(
6071 sw_if_index=self.pg1.sw_if_index,
6074 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6075 start_sessnum = len(sessions)
6077 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6078 tcp_transitory=2, icmp=5)
6080 self.initiate_tcp_session(self.pg0, self.pg1)
6082 # FIN packet out -> in
6083 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6084 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6085 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6086 flags="FA", seq=100, ack=300))
6087 self.pg1.add_stream(p)
6088 self.pg_enable_capture(self.pg_interfaces)
6090 self.pg0.get_capture(1)
6092 # FIN+ACK packet in -> out
6093 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6094 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6095 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6096 flags="FA", seq=300, ack=101))
6098 self.pg0.add_stream(p)
6099 self.pg_enable_capture(self.pg_interfaces)
6101 self.pg1.get_capture(1)
6103 # ACK packet out -> in
6104 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6105 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6106 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6107 flags="A", seq=101, ack=301))
6108 self.pg1.add_stream(p)
6109 self.pg_enable_capture(self.pg_interfaces)
6111 self.pg0.get_capture(1)
6113 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6114 self.assertEqual(len(sessions) - start_sessnum, 1)
6116 stats = self.statistics.get_counter(
6117 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6118 out2in_drops = stats[0]
6119 stats = self.statistics.get_counter(
6120 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6121 in2out_drops = stats[0]
6123 # extra FIN packet out -> in - this should be dropped
6124 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6125 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6126 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6127 flags="FA", seq=300, ack=101))
6129 self.pg1.add_stream(p)
6130 self.pg_enable_capture(self.pg_interfaces)
6132 self.pg0.assert_nothing_captured()
6134 # extra ACK packet in -> out - this should be dropped
6135 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6136 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6137 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6138 flags="A", seq=101, ack=301))
6139 self.pg0.add_stream(p)
6140 self.pg_enable_capture(self.pg_interfaces)
6142 self.pg1.assert_nothing_captured()
6144 stats = self.statistics.get_counter(
6145 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6146 self.assertEqual(stats[0] - out2in_drops, 1)
6147 stats = self.statistics.get_counter(
6148 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6149 self.assertEqual(stats[0] - in2out_drops, 1)
6152 # extra ACK packet in -> out - this will cause session to be wiped
6153 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6154 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6155 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6156 flags="A", seq=101, ack=301))
6157 self.pg0.add_stream(p)
6158 self.pg_enable_capture(self.pg_interfaces)
6160 self.pg1.assert_nothing_captured()
6161 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6162 self.assertEqual(len(sessions) - start_sessnum, 0)
6164 def test_tcp_session_close_simultaneous(self):
6165 """ Close TCP session from inside network """
6166 self.tcp_port_out = 10505
6167 self.nat44_add_address(self.nat_addr)
6168 flags = self.config_flags.NAT_IS_TWICE_NAT
6169 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6173 proto=IP_PROTOS.tcp,
6175 flags = self.config_flags.NAT_IS_INSIDE
6176 self.vapi.nat44_interface_add_del_feature(
6177 sw_if_index=self.pg0.sw_if_index,
6178 flags=flags, is_add=1)
6179 self.vapi.nat44_interface_add_del_feature(
6180 sw_if_index=self.pg1.sw_if_index,
6183 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6184 start_sessnum = len(sessions)
6186 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6187 tcp_transitory=2, icmp=5)
6189 self.initiate_tcp_session(self.pg0, self.pg1)
6191 # FIN packet in -> out
6192 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6193 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6194 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6195 flags="FA", seq=100, ack=300))
6196 self.pg0.add_stream(p)
6197 self.pg_enable_capture(self.pg_interfaces)
6199 self.pg1.get_capture(1)
6201 # FIN packet out -> in
6202 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6203 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6204 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6205 flags="FA", seq=300, ack=100))
6206 self.pg1.add_stream(p)
6207 self.pg_enable_capture(self.pg_interfaces)
6209 self.pg0.get_capture(1)
6211 # ACK packet in -> out
6212 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6213 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6214 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6215 flags="A", seq=101, ack=301))
6216 self.pg0.add_stream(p)
6217 self.pg_enable_capture(self.pg_interfaces)
6219 self.pg1.get_capture(1)
6221 # ACK packet out -> in
6222 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6223 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6224 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6225 flags="A", seq=301, ack=101))
6226 self.pg1.add_stream(p)
6227 self.pg_enable_capture(self.pg_interfaces)
6229 self.pg0.get_capture(1)
6231 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6232 self.assertEqual(len(sessions) - start_sessnum, 1)
6234 stats = self.statistics.get_counter(
6235 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6236 out2in_drops = stats[0]
6237 stats = self.statistics.get_counter(
6238 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6239 in2out_drops = stats[0]
6241 # extra FIN packet out -> in - this should be dropped
6242 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6243 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6244 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6245 flags="FA", seq=300, ack=101))
6247 self.pg1.add_stream(p)
6248 self.pg_enable_capture(self.pg_interfaces)
6250 self.pg0.assert_nothing_captured()
6252 # extra ACK packet in -> out - this should be dropped
6253 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6254 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6255 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6256 flags="A", seq=101, ack=301))
6257 self.pg0.add_stream(p)
6258 self.pg_enable_capture(self.pg_interfaces)
6260 self.pg1.assert_nothing_captured()
6262 stats = self.statistics.get_counter(
6263 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6264 self.assertEqual(stats[0] - out2in_drops, 1)
6265 stats = self.statistics.get_counter(
6266 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6267 self.assertEqual(stats[0] - in2out_drops, 1)
6270 # extra ACK packet in -> out - this will cause session to be wiped
6271 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6272 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6273 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6274 flags="A", seq=101, ack=301))
6275 self.pg0.add_stream(p)
6276 self.pg_enable_capture(self.pg_interfaces)
6278 self.pg1.assert_nothing_captured()
6279 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6280 self.assertEqual(len(sessions) - start_sessnum, 0)
6282 def test_one_armed_nat44_static(self):
6283 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6284 remote_host = self.pg4.remote_hosts[0]
6285 local_host = self.pg4.remote_hosts[1]
6290 self.vapi.nat44_forwarding_enable_disable(enable=1)
6291 self.nat44_add_address(self.nat_addr, twice_nat=1)
6292 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6293 self.config_flags.NAT_IS_TWICE_NAT)
6294 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6295 local_port, external_port,
6296 proto=IP_PROTOS.tcp, flags=flags)
6297 flags = self.config_flags.NAT_IS_INSIDE
6298 self.vapi.nat44_interface_add_del_feature(
6299 sw_if_index=self.pg4.sw_if_index,
6301 self.vapi.nat44_interface_add_del_feature(
6302 sw_if_index=self.pg4.sw_if_index,
6303 flags=flags, is_add=1)
6305 # from client to service
6306 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6307 IP(src=remote_host.ip4, dst=self.nat_addr) /
6308 TCP(sport=12345, dport=external_port))
6309 self.pg4.add_stream(p)
6310 self.pg_enable_capture(self.pg_interfaces)
6312 capture = self.pg4.get_capture(1)
6317 self.assertEqual(ip.dst, local_host.ip4)
6318 self.assertEqual(ip.src, self.nat_addr)
6319 self.assertEqual(tcp.dport, local_port)
6320 self.assertNotEqual(tcp.sport, 12345)
6321 eh_port_in = tcp.sport
6322 self.assert_packet_checksums_valid(p)
6324 self.logger.error(ppp("Unexpected or invalid packet:", p))
6327 # from service back to client
6328 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6329 IP(src=local_host.ip4, dst=self.nat_addr) /
6330 TCP(sport=local_port, dport=eh_port_in))
6331 self.pg4.add_stream(p)
6332 self.pg_enable_capture(self.pg_interfaces)
6334 capture = self.pg4.get_capture(1)
6339 self.assertEqual(ip.src, self.nat_addr)
6340 self.assertEqual(ip.dst, remote_host.ip4)
6341 self.assertEqual(tcp.sport, external_port)
6342 self.assertEqual(tcp.dport, 12345)
6343 self.assert_packet_checksums_valid(p)
6345 self.logger.error(ppp("Unexpected or invalid packet:", p))
6348 def test_static_with_port_out2(self):
6349 """ 1:1 NAPT asymmetrical rule """
6354 self.vapi.nat44_forwarding_enable_disable(enable=1)
6355 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6356 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6357 local_port, external_port,
6358 proto=IP_PROTOS.tcp, flags=flags)
6359 flags = self.config_flags.NAT_IS_INSIDE
6360 self.vapi.nat44_interface_add_del_feature(
6361 sw_if_index=self.pg0.sw_if_index,
6362 flags=flags, is_add=1)
6363 self.vapi.nat44_interface_add_del_feature(
6364 sw_if_index=self.pg1.sw_if_index,
6367 # from client to service
6368 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6369 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6370 TCP(sport=12345, dport=external_port))
6371 self.pg1.add_stream(p)
6372 self.pg_enable_capture(self.pg_interfaces)
6374 capture = self.pg0.get_capture(1)
6379 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6380 self.assertEqual(tcp.dport, local_port)
6381 self.assert_packet_checksums_valid(p)
6383 self.logger.error(ppp("Unexpected or invalid packet:", p))
6387 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6388 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6389 ICMP(type=11) / capture[0][IP])
6390 self.pg0.add_stream(p)
6391 self.pg_enable_capture(self.pg_interfaces)
6393 capture = self.pg1.get_capture(1)
6396 self.assertEqual(p[IP].src, self.nat_addr)
6398 self.assertEqual(inner.dst, self.nat_addr)
6399 self.assertEqual(inner[TCPerror].dport, external_port)
6401 self.logger.error(ppp("Unexpected or invalid packet:", p))
6404 # from service back to client
6405 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6406 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6407 TCP(sport=local_port, dport=12345))
6408 self.pg0.add_stream(p)
6409 self.pg_enable_capture(self.pg_interfaces)
6411 capture = self.pg1.get_capture(1)
6416 self.assertEqual(ip.src, self.nat_addr)
6417 self.assertEqual(tcp.sport, external_port)
6418 self.assert_packet_checksums_valid(p)
6420 self.logger.error(ppp("Unexpected or invalid packet:", p))
6424 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6425 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6426 ICMP(type=11) / capture[0][IP])
6427 self.pg1.add_stream(p)
6428 self.pg_enable_capture(self.pg_interfaces)
6430 capture = self.pg0.get_capture(1)
6433 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6435 self.assertEqual(inner.src, self.pg0.remote_ip4)
6436 self.assertEqual(inner[TCPerror].sport, local_port)
6438 self.logger.error(ppp("Unexpected or invalid packet:", p))
6441 # from client to server (no translation)
6442 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6443 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6444 TCP(sport=12346, dport=local_port))
6445 self.pg1.add_stream(p)
6446 self.pg_enable_capture(self.pg_interfaces)
6448 capture = self.pg0.get_capture(1)
6453 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6454 self.assertEqual(tcp.dport, local_port)
6455 self.assert_packet_checksums_valid(p)
6457 self.logger.error(ppp("Unexpected or invalid packet:", p))
6460 # from service back to client (no translation)
6461 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6462 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6463 TCP(sport=local_port, dport=12346))
6464 self.pg0.add_stream(p)
6465 self.pg_enable_capture(self.pg_interfaces)
6467 capture = self.pg1.get_capture(1)
6472 self.assertEqual(ip.src, self.pg0.remote_ip4)
6473 self.assertEqual(tcp.sport, local_port)
6474 self.assert_packet_checksums_valid(p)
6476 self.logger.error(ppp("Unexpected or invalid packet:", p))
6479 def test_output_feature(self):
6480 """ NAT44 interface output feature (in2out postrouting) """
6481 self.vapi.nat44_forwarding_enable_disable(enable=1)
6482 self.nat44_add_address(self.nat_addr)
6483 self.vapi.nat44_interface_add_del_feature(
6484 sw_if_index=self.pg0.sw_if_index,
6486 self.vapi.nat44_interface_add_del_output_feature(
6488 sw_if_index=self.pg1.sw_if_index)
6491 pkts = self.create_stream_in(self.pg0, self.pg1)
6492 self.pg0.add_stream(pkts)
6493 self.pg_enable_capture(self.pg_interfaces)
6495 capture = self.pg1.get_capture(len(pkts))
6496 self.verify_capture_out(capture, ignore_port=True)
6499 pkts = self.create_stream_out(self.pg1)
6500 self.pg1.add_stream(pkts)
6501 self.pg_enable_capture(self.pg_interfaces)
6503 capture = self.pg0.get_capture(len(pkts))
6504 self.verify_capture_in(capture, self.pg0)
6506 def test_output_feature_stateful_acl(self):
6507 """ NAT44 endpoint-dependent output feature works with stateful ACL """
6508 self.nat44_add_address(self.nat_addr)
6509 self.vapi.nat44_interface_add_del_output_feature(
6510 sw_if_index=self.pg0.sw_if_index,
6511 flags=self.config_flags.NAT_IS_INSIDE,
6513 self.vapi.nat44_interface_add_del_output_feature(
6514 sw_if_index=self.pg1.sw_if_index,
6515 flags=self.config_flags.NAT_IS_OUTSIDE,
6518 # First ensure that the NAT is working sans ACL
6520 # send packets out2in, no sessions yet so packets should drop
6521 pkts_out2in = self.create_stream_out(self.pg1)
6522 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6524 # send packets into inside intf, ensure received via outside intf
6525 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6526 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6528 self.verify_capture_out(capture, ignore_port=True)
6530 # send out2in again, with sessions created it should work now
6531 pkts_out2in = self.create_stream_out(self.pg1)
6532 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6534 self.verify_capture_in(capture, self.pg0)
6536 # Create an ACL blocking everything
6537 out2in_deny_rule = AclRule(is_permit=0)
6538 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6539 out2in_acl.add_vpp_config()
6541 # create an ACL to permit/reflect everything
6542 in2out_reflect_rule = AclRule(is_permit=2)
6543 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6544 in2out_acl.add_vpp_config()
6546 # apply as input acl on interface and confirm it blocks everything
6547 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6548 n_input=1, acls=[out2in_acl])
6549 acl_if.add_vpp_config()
6550 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6553 acl_if.acls = [out2in_acl, in2out_acl]
6554 acl_if.add_vpp_config()
6555 # send in2out to generate ACL state (NAT state was created earlier)
6556 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6558 self.verify_capture_out(capture, ignore_port=True)
6560 # send out2in again. ACL state exists so it should work now.
6561 # TCP packets with the syn flag set also need the ack flag
6562 for p in pkts_out2in:
6563 if p.haslayer(TCP) and p[TCP].flags & 0x02:
6564 p[TCP].flags |= 0x10
6565 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6567 self.verify_capture_in(capture, self.pg0)
6568 self.logger.info(self.vapi.cli("show trace"))
6570 def test_multiple_vrf(self):
6571 """ Multiple VRF setup """
6572 external_addr = '1.2.3.4'
6577 self.vapi.nat44_forwarding_enable_disable(enable=1)
6578 self.nat44_add_address(self.nat_addr)
6579 flags = self.config_flags.NAT_IS_INSIDE
6580 self.vapi.nat44_interface_add_del_feature(
6581 sw_if_index=self.pg0.sw_if_index,
6583 self.vapi.nat44_interface_add_del_feature(
6584 sw_if_index=self.pg0.sw_if_index,
6585 is_add=1, flags=flags)
6586 self.vapi.nat44_interface_add_del_output_feature(
6587 sw_if_index=self.pg1.sw_if_index,
6589 self.vapi.nat44_interface_add_del_feature(
6590 sw_if_index=self.pg5.sw_if_index,
6592 self.vapi.nat44_interface_add_del_feature(
6593 sw_if_index=self.pg5.sw_if_index,
6594 is_add=1, flags=flags)
6595 self.vapi.nat44_interface_add_del_feature(
6596 sw_if_index=self.pg6.sw_if_index,
6598 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6599 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6600 local_port, external_port, vrf_id=1,
6601 proto=IP_PROTOS.tcp, flags=flags)
6602 self.nat44_add_static_mapping(
6603 self.pg0.remote_ip4,
6604 external_sw_if_index=self.pg0.sw_if_index,
6605 local_port=local_port,
6607 external_port=external_port,
6608 proto=IP_PROTOS.tcp,
6612 # from client to service (both VRF1)
6613 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6614 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6615 TCP(sport=12345, dport=external_port))
6616 self.pg6.add_stream(p)
6617 self.pg_enable_capture(self.pg_interfaces)
6619 capture = self.pg5.get_capture(1)
6624 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6625 self.assertEqual(tcp.dport, local_port)
6626 self.assert_packet_checksums_valid(p)
6628 self.logger.error(ppp("Unexpected or invalid packet:", p))
6631 # from service back to client (both VRF1)
6632 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6633 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6634 TCP(sport=local_port, dport=12345))
6635 self.pg5.add_stream(p)
6636 self.pg_enable_capture(self.pg_interfaces)
6638 capture = self.pg6.get_capture(1)
6643 self.assertEqual(ip.src, external_addr)
6644 self.assertEqual(tcp.sport, external_port)
6645 self.assert_packet_checksums_valid(p)
6647 self.logger.error(ppp("Unexpected or invalid packet:", p))
6650 # dynamic NAT from VRF1 to VRF0 (output-feature)
6651 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6652 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6653 TCP(sport=2345, dport=22))
6654 self.pg5.add_stream(p)
6655 self.pg_enable_capture(self.pg_interfaces)
6657 capture = self.pg1.get_capture(1)
6662 self.assertEqual(ip.src, self.nat_addr)
6663 self.assert_packet_checksums_valid(p)
6666 self.logger.error(ppp("Unexpected or invalid packet:", p))
6669 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6670 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6671 TCP(sport=22, dport=port))
6672 self.pg1.add_stream(p)
6673 self.pg_enable_capture(self.pg_interfaces)
6675 capture = self.pg5.get_capture(1)
6680 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6681 self.assertEqual(tcp.dport, 2345)
6682 self.assert_packet_checksums_valid(p)
6684 self.logger.error(ppp("Unexpected or invalid packet:", p))
6687 # from client VRF1 to service VRF0
6688 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6689 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6690 TCP(sport=12346, dport=external_port))
6691 self.pg6.add_stream(p)
6692 self.pg_enable_capture(self.pg_interfaces)
6694 capture = self.pg0.get_capture(1)
6699 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6700 self.assertEqual(tcp.dport, local_port)
6701 self.assert_packet_checksums_valid(p)
6703 self.logger.error(ppp("Unexpected or invalid packet:", p))
6706 # from service VRF0 back to client VRF1
6707 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6708 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6709 TCP(sport=local_port, dport=12346))
6710 self.pg0.add_stream(p)
6711 self.pg_enable_capture(self.pg_interfaces)
6713 capture = self.pg6.get_capture(1)
6718 self.assertEqual(ip.src, self.pg0.local_ip4)
6719 self.assertEqual(tcp.sport, external_port)
6720 self.assert_packet_checksums_valid(p)
6722 self.logger.error(ppp("Unexpected or invalid packet:", p))
6725 # from client VRF0 to service VRF1
6726 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6727 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6728 TCP(sport=12347, dport=external_port))
6729 self.pg0.add_stream(p)
6730 self.pg_enable_capture(self.pg_interfaces)
6732 capture = self.pg5.get_capture(1)
6737 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6738 self.assertEqual(tcp.dport, local_port)
6739 self.assert_packet_checksums_valid(p)
6741 self.logger.error(ppp("Unexpected or invalid packet:", p))
6744 # from service VRF1 back to client VRF0
6745 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6746 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6747 TCP(sport=local_port, dport=12347))
6748 self.pg5.add_stream(p)
6749 self.pg_enable_capture(self.pg_interfaces)
6751 capture = self.pg0.get_capture(1)
6756 self.assertEqual(ip.src, external_addr)
6757 self.assertEqual(tcp.sport, external_port)
6758 self.assert_packet_checksums_valid(p)
6760 self.logger.error(ppp("Unexpected or invalid packet:", p))
6763 # from client to server (both VRF1, no translation)
6764 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6765 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6766 TCP(sport=12348, dport=local_port))
6767 self.pg6.add_stream(p)
6768 self.pg_enable_capture(self.pg_interfaces)
6770 capture = self.pg5.get_capture(1)
6775 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6776 self.assertEqual(tcp.dport, local_port)
6777 self.assert_packet_checksums_valid(p)
6779 self.logger.error(ppp("Unexpected or invalid packet:", p))
6782 # from server back to client (both VRF1, no translation)
6783 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6784 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6785 TCP(sport=local_port, dport=12348))
6786 self.pg5.add_stream(p)
6787 self.pg_enable_capture(self.pg_interfaces)
6789 capture = self.pg6.get_capture(1)
6794 self.assertEqual(ip.src, self.pg5.remote_ip4)
6795 self.assertEqual(tcp.sport, local_port)
6796 self.assert_packet_checksums_valid(p)
6798 self.logger.error(ppp("Unexpected or invalid packet:", p))
6801 # from client VRF1 to server VRF0 (no translation)
6802 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6803 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6804 TCP(sport=local_port, dport=12349))
6805 self.pg0.add_stream(p)
6806 self.pg_enable_capture(self.pg_interfaces)
6808 capture = self.pg6.get_capture(1)
6813 self.assertEqual(ip.src, self.pg0.remote_ip4)
6814 self.assertEqual(tcp.sport, local_port)
6815 self.assert_packet_checksums_valid(p)
6817 self.logger.error(ppp("Unexpected or invalid packet:", p))
6820 # from server VRF0 back to client VRF1 (no translation)
6821 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6822 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6823 TCP(sport=local_port, dport=12349))
6824 self.pg0.add_stream(p)
6825 self.pg_enable_capture(self.pg_interfaces)
6827 capture = self.pg6.get_capture(1)
6832 self.assertEqual(ip.src, self.pg0.remote_ip4)
6833 self.assertEqual(tcp.sport, local_port)
6834 self.assert_packet_checksums_valid(p)
6836 self.logger.error(ppp("Unexpected or invalid packet:", p))
6839 # from client VRF0 to server VRF1 (no translation)
6840 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6841 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6842 TCP(sport=12344, dport=local_port))
6843 self.pg0.add_stream(p)
6844 self.pg_enable_capture(self.pg_interfaces)
6846 capture = self.pg5.get_capture(1)
6851 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6852 self.assertEqual(tcp.dport, local_port)
6853 self.assert_packet_checksums_valid(p)
6855 self.logger.error(ppp("Unexpected or invalid packet:", p))
6858 # from server VRF1 back to client VRF0 (no translation)
6859 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6860 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6861 TCP(sport=local_port, dport=12344))
6862 self.pg5.add_stream(p)
6863 self.pg_enable_capture(self.pg_interfaces)
6865 capture = self.pg0.get_capture(1)
6870 self.assertEqual(ip.src, self.pg5.remote_ip4)
6871 self.assertEqual(tcp.sport, local_port)
6872 self.assert_packet_checksums_valid(p)
6874 self.logger.error(ppp("Unexpected or invalid packet:", p))
6877 def test_session_rst_timeout(self):
6878 """ NAT44 session RST timeouts """
6879 self.nat44_add_address(self.nat_addr)
6880 flags = self.config_flags.NAT_IS_INSIDE
6881 self.vapi.nat44_interface_add_del_feature(
6882 sw_if_index=self.pg0.sw_if_index,
6883 flags=flags, is_add=1)
6884 self.vapi.nat44_interface_add_del_feature(
6885 sw_if_index=self.pg1.sw_if_index,
6887 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6888 tcp_transitory=5, icmp=60)
6890 self.initiate_tcp_session(self.pg0, self.pg1)
6891 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6892 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6893 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6895 self.pg0.add_stream(p)
6896 self.pg_enable_capture(self.pg_interfaces)
6898 self.pg1.get_capture(1)
6902 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6903 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6904 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6906 self.pg0.add_stream(p)
6907 self.pg_enable_capture(self.pg_interfaces)
6909 self.pg1.get_capture(1)
6911 def test_syslog_sess(self):
6912 """ Test syslog session creation and deletion """
6913 self.vapi.syslog_set_filter(
6914 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6915 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6916 self.nat44_add_address(self.nat_addr)
6917 flags = self.config_flags.NAT_IS_INSIDE
6918 self.vapi.nat44_interface_add_del_feature(
6919 sw_if_index=self.pg0.sw_if_index,
6920 flags=flags, is_add=1)
6921 self.vapi.nat44_interface_add_del_feature(
6922 sw_if_index=self.pg1.sw_if_index,
6925 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6926 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6927 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6928 self.pg0.add_stream(p)
6929 self.pg_enable_capture(self.pg_interfaces)
6931 capture = self.pg1.get_capture(1)
6932 self.tcp_port_out = capture[0][TCP].sport
6933 capture = self.pg2.get_capture(1)
6934 self.verify_syslog_sess(capture[0][Raw].load)
6936 self.pg_enable_capture(self.pg_interfaces)
6938 self.nat44_add_address(self.nat_addr, is_add=0)
6939 capture = self.pg2.get_capture(1)
6940 self.verify_syslog_sess(capture[0][Raw].load, False)
6942 def test_ed_users_dump(self):
6943 """ API test - nat44_user_dump """
6944 flags = self.config_flags.NAT_IS_INSIDE
6945 self.vapi.nat44_interface_add_del_feature(
6946 sw_if_index=self.pg0.sw_if_index,
6947 flags=flags, is_add=1)
6948 self.vapi.nat44_interface_add_del_feature(
6949 sw_if_index=self.pg1.sw_if_index,
6951 self.vapi.nat44_forwarding_enable_disable(enable=1)
6953 real_ip = self.pg0.remote_ip4
6954 alias_ip = self.nat_addr
6955 flags = self.config_flags.NAT_IS_ADDR_ONLY
6956 self.vapi.nat44_add_del_static_mapping(is_add=1,
6957 local_ip_address=real_ip,
6958 external_ip_address=alias_ip,
6959 external_sw_if_index=0xFFFFFFFF,
6962 users = self.vapi.nat44_user_dump()
6963 self.assertEqual(len(users), 0)
6965 # in2out - static mapping match
6967 pkts = self.create_stream_out(self.pg1)
6968 self.pg1.add_stream(pkts)
6969 self.pg_enable_capture(self.pg_interfaces)
6971 capture = self.pg0.get_capture(len(pkts))
6972 self.verify_capture_in(capture, self.pg0)
6974 pkts = self.create_stream_in(self.pg0, self.pg1)
6975 self.pg0.add_stream(pkts)
6976 self.pg_enable_capture(self.pg_interfaces)
6978 capture = self.pg1.get_capture(len(pkts))
6979 self.verify_capture_out(capture, same_port=True)
6981 users = self.vapi.nat44_user_dump()
6982 self.assertEqual(len(users), 1)
6983 static_user = users[0]
6984 self.assertEqual(static_user.nstaticsessions, 3)
6985 self.assertEqual(static_user.nsessions, 0)
6987 # in2out - no static mapping match
6989 host0 = self.pg0.remote_hosts[0]
6990 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
6992 pkts = self.create_stream_out(self.pg1,
6993 dst_ip=self.pg0.remote_ip4,
6994 use_inside_ports=True)
6995 self.pg1.add_stream(pkts)
6996 self.pg_enable_capture(self.pg_interfaces)
6998 capture = self.pg0.get_capture(len(pkts))
6999 self.verify_capture_in(capture, self.pg0)
7001 pkts = self.create_stream_in(self.pg0, self.pg1)
7002 self.pg0.add_stream(pkts)
7003 self.pg_enable_capture(self.pg_interfaces)
7005 capture = self.pg1.get_capture(len(pkts))
7006 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
7009 self.pg0.remote_hosts[0] = host0
7011 users = self.vapi.nat44_user_dump()
7012 self.assertEqual(len(users), 2)
7013 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
7014 non_static_user = users[1]
7015 static_user = users[0]
7017 non_static_user = users[0]
7018 static_user = users[1]
7019 self.assertEqual(static_user.nstaticsessions, 3)
7020 self.assertEqual(static_user.nsessions, 0)
7021 self.assertEqual(non_static_user.nstaticsessions, 0)
7022 self.assertEqual(non_static_user.nsessions, 3)
7024 users = self.vapi.nat44_user_dump()
7025 self.assertEqual(len(users), 2)
7026 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
7027 non_static_user = users[1]
7028 static_user = users[0]
7030 non_static_user = users[0]
7031 static_user = users[1]
7032 self.assertEqual(static_user.nstaticsessions, 3)
7033 self.assertEqual(static_user.nsessions, 0)
7034 self.assertEqual(non_static_user.nstaticsessions, 0)
7035 self.assertEqual(non_static_user.nsessions, 3)
7038 self.vapi.nat44_forwarding_enable_disable(enable=0)
7039 flags = self.config_flags.NAT_IS_ADDR_ONLY
7040 self.vapi.nat44_add_del_static_mapping(
7042 local_ip_address=real_ip,
7043 external_ip_address=alias_ip,
7044 external_sw_if_index=0xFFFFFFFF,
7047 def show_commands_at_teardown(self):
7048 self.logger.info(self.vapi.cli("show errors"))
7049 self.logger.info(self.vapi.cli("show nat44 addresses"))
7050 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7051 self.logger.info(self.vapi.cli("show nat44 static mappings"))
7052 self.logger.info(self.vapi.cli("show nat44 interface address"))
7053 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
7054 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
7055 self.logger.info(self.vapi.cli("show nat timeouts"))
7056 self.logger.info(self.vapi.cli("debug nat44 fib registration"))
7059 class TestNAT44EndpointDependent3(MethodHolder):
7060 """ Endpoint-Dependent mapping and filtering extra test cases """
7062 max_translations = 50
7065 def setUpClass(cls):
7066 super(TestNAT44EndpointDependent3, cls).setUpClass()
7067 cls.vapi.cli("set log class nat level debug")
7069 cls.nat_addr = '10.0.0.3'
7071 cls.create_pg_interfaces(range(2))
7073 for i in cls.pg_interfaces:
7079 super(TestNAT44EndpointDependent3, self).setUp()
7080 flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT
7081 self.vapi.nat44_plugin_enable_disable(
7082 sessions=self.max_translations,
7083 flags=flags, enable=1)
7084 self.vapi.nat_set_timeouts(
7085 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
7087 self.nat44_add_address(self.nat_addr)
7088 flags = self.config_flags.NAT_IS_INSIDE
7089 self.vapi.nat44_interface_add_del_feature(
7090 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1)
7091 self.vapi.nat44_interface_add_del_feature(
7092 sw_if_index=self.pg1.sw_if_index, is_add=1)
7095 def tearDownClass(cls):
7096 super(TestNAT44EndpointDependent3, cls).tearDownClass()
7099 super(TestNAT44EndpointDependent3, self).tearDown()
7100 if not self.vpp_dead:
7101 self.vapi.nat44_plugin_enable_disable(enable=0)
7102 self.vapi.cli("clear logging")
7104 def init_tcp_session(self, in_if, out_if, sport, ext_dport):
7105 # SYN packet in->out
7106 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
7107 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
7108 TCP(sport=sport, dport=ext_dport, flags="S"))
7110 self.pg_enable_capture(self.pg_interfaces)
7112 capture = out_if.get_capture(1)
7114 tcp_port_out = p[TCP].sport
7116 # SYN + ACK packet out->in
7117 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
7118 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
7119 TCP(sport=ext_dport, dport=tcp_port_out, flags="SA"))
7120 out_if.add_stream(p)
7121 self.pg_enable_capture(self.pg_interfaces)
7123 in_if.get_capture(1)
7125 # ACK packet in->out
7126 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
7127 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
7128 TCP(sport=sport, dport=ext_dport, flags="A"))
7130 self.pg_enable_capture(self.pg_interfaces)
7132 out_if.get_capture(1)
7136 def test_lru_cleanup(self):
7137 """ LRU cleanup algorithm """
7138 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
7140 for i in range(0, self.max_translations - 1):
7141 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7142 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
7143 UDP(sport=7000+i, dport=80))
7146 self.pg0.add_stream(pkts)
7147 self.pg_enable_capture(self.pg_interfaces)
7149 self.pg1.get_capture(len(pkts))
7150 self.sleep(1.5, "wait for timeouts")
7153 for i in range(0, self.max_translations - 1):
7154 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7155 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
7156 ICMP(id=8000+i, type='echo-request'))
7159 self.pg0.add_stream(pkts)
7160 self.pg_enable_capture(self.pg_interfaces)
7162 self.pg1.get_capture(len(pkts))
7165 class TestNAT44Out2InDPO(MethodHolder):
7166 """ NAT44 Test Cases using out2in DPO """
7169 def setUpClass(cls):
7170 super(TestNAT44Out2InDPO, cls).setUpClass()
7171 cls.vapi.cli("set log class nat level debug")
7173 cls.tcp_port_in = 6303
7174 cls.tcp_port_out = 6303
7175 cls.udp_port_in = 6304
7176 cls.udp_port_out = 6304
7177 cls.icmp_id_in = 6305
7178 cls.icmp_id_out = 6305
7179 cls.nat_addr = '10.0.0.3'
7180 cls.dst_ip4 = '192.168.70.1'
7182 cls.create_pg_interfaces(range(2))
7185 cls.pg0.config_ip4()
7186 cls.pg0.resolve_arp()
7189 cls.pg1.config_ip6()
7190 cls.pg1.resolve_ndp()
7192 r1 = VppIpRoute(cls, "::", 0,
7193 [VppRoutePath(cls.pg1.remote_ip6,
7194 cls.pg1.sw_if_index)],
7199 def tearDownClass(cls):
7200 super(TestNAT44Out2InDPO, cls).tearDownClass()
7203 super(TestNAT44Out2InDPO, self).setUp()
7204 flags = self.nat44_config_flags.NAT44_API_IS_OUT2IN_DPO
7205 self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
7208 super(TestNAT44Out2InDPO, self).tearDown()
7209 if not self.vpp_dead:
7210 self.vapi.nat44_plugin_enable_disable(enable=0)
7211 self.vapi.cli("clear logging")
7213 def configure_xlat(self):
7214 self.dst_ip6_pfx = '1:2:3::'
7215 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7217 self.dst_ip6_pfx_len = 96
7218 self.src_ip6_pfx = '4:5:6::'
7219 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7221 self.src_ip6_pfx_len = 96
7222 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7223 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7224 '\x00\x00\x00\x00', 0)
7226 @unittest.skip('Temporary disabled')
7227 def test_464xlat_ce(self):
7228 """ Test 464XLAT CE with NAT44 """
7230 nat_config = self.vapi.nat_show_config()
7231 self.assertEqual(1, nat_config.out2in_dpo)
7233 self.configure_xlat()
7235 flags = self.config_flags.NAT_IS_INSIDE
7236 self.vapi.nat44_interface_add_del_feature(
7237 sw_if_index=self.pg0.sw_if_index,
7238 flags=flags, is_add=1)
7239 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7240 last_ip_address=self.nat_addr_n,
7241 vrf_id=0xFFFFFFFF, is_add=1)
7243 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7244 self.dst_ip6_pfx_len)
7245 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7246 self.src_ip6_pfx_len)
7249 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7250 self.pg0.add_stream(pkts)
7251 self.pg_enable_capture(self.pg_interfaces)
7253 capture = self.pg1.get_capture(len(pkts))
7254 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7257 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7259 self.pg1.add_stream(pkts)
7260 self.pg_enable_capture(self.pg_interfaces)
7262 capture = self.pg0.get_capture(len(pkts))
7263 self.verify_capture_in(capture, self.pg0)
7265 self.vapi.nat44_interface_add_del_feature(
7266 sw_if_index=self.pg0.sw_if_index,
7268 self.vapi.nat44_add_del_address_range(
7269 first_ip_address=self.nat_addr_n,
7270 last_ip_address=self.nat_addr_n,
7273 @unittest.skip('Temporary disabled')
7274 def test_464xlat_ce_no_nat(self):
7275 """ Test 464XLAT CE without NAT44 """
7277 self.configure_xlat()
7279 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7280 self.dst_ip6_pfx_len)
7281 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7282 self.src_ip6_pfx_len)
7284 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7285 self.pg0.add_stream(pkts)
7286 self.pg_enable_capture(self.pg_interfaces)
7288 capture = self.pg1.get_capture(len(pkts))
7289 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7290 nat_ip=out_dst_ip6, same_port=True)
7292 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7293 self.pg1.add_stream(pkts)
7294 self.pg_enable_capture(self.pg_interfaces)
7296 capture = self.pg0.get_capture(len(pkts))
7297 self.verify_capture_in(capture, self.pg0)
7300 if __name__ == '__main__':
7301 unittest.main(testRunner=VppTestRunner)