8 from framework import VppTestCase, VppTestRunner, running_extended_tests
11 from scapy.layers.inet import IP, TCP, UDP, ICMP
12 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
13 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
14 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
15 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
16 from scapy.layers.l2 import Ether, ARP, GRE
17 from scapy.data import IP_PROTOS
18 from scapy.packet import bind_layers, Raw
20 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
21 from time import sleep
22 from util import ip4_range
23 from vpp_papi import mac_pton
24 from syslog_rfc5424_parser import SyslogMessage, ParseError
25 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
26 from io import BytesIO
27 from vpp_papi import VppEnum
28 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
29 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
31 from ipaddress import IPv6Network
34 # NAT HA protocol event data
37 fields_desc = [ByteEnumField("event_type", None,
38 {1: "add", 2: "del", 3: "refresh"}),
39 ByteEnumField("protocol", None,
40 {0: "udp", 1: "tcp", 2: "icmp"}),
41 ShortField("flags", 0),
42 IPField("in_addr", None),
43 IPField("out_addr", None),
44 ShortField("in_port", None),
45 ShortField("out_port", None),
46 IPField("eh_addr", None),
47 IPField("ehn_addr", None),
48 ShortField("eh_port", None),
49 ShortField("ehn_port", None),
50 IntField("fib_index", None),
51 IntField("total_pkts", 0),
52 LongField("total_bytes", 0)]
54 def extract_padding(self, s):
58 # NAT HA protocol header
59 class HANATStateSync(Packet):
60 name = "HA NAT state sync"
61 fields_desc = [XByteField("version", 1),
62 FlagsField("flags", 0, 8, ['ACK']),
63 FieldLenField("count", None, count_of="events"),
64 IntField("sequence_number", 1),
65 IntField("thread_index", 0),
66 PacketListField("events", [], Event,
67 count_from=lambda pkt: pkt.count)]
70 class MethodHolder(VppTestCase):
71 """ NAT create capture and verify method holder """
74 def config_flags(self):
75 return VppEnum.vl_api_nat_config_flags_t
78 def SYSLOG_SEVERITY(self):
79 return VppEnum.vl_api_syslog_severity_t
81 def clear_nat44(self):
83 Clear NAT44 configuration.
85 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
86 # I found no elegant way to do this
87 self.vapi.ip_add_del_route(
88 dst_address=self.pg7.remote_ip4n,
89 dst_address_length=32,
90 next_hop_address=self.pg7.remote_ip4n,
91 next_hop_sw_if_index=self.pg7.sw_if_index,
93 self.vapi.ip_add_del_route(
94 dst_address=self.pg8.remote_ip4n,
95 dst_address_length=32,
96 next_hop_address=self.pg8.remote_ip4n,
97 next_hop_sw_if_index=self.pg8.sw_if_index,
100 for intf in [self.pg7, self.pg8]:
101 self.vapi.ip_neighbor_add_del(
105 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
106 IP_API_NEIGHBOR_FLAG_STATIC),
109 if self.pg7.has_ip4_config:
110 self.pg7.unconfig_ip4()
112 self.vapi.nat44_forwarding_enable_disable(enable=0)
114 interfaces = self.vapi.nat44_interface_addr_dump()
115 for intf in interfaces:
116 self.vapi.nat44_add_del_interface_addr(
118 sw_if_index=intf.sw_if_index,
121 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
122 src_port=self.ipfix_src_port,
124 self.ipfix_src_port = 4739
125 self.ipfix_domain_id = 1
127 self.vapi.syslog_set_filter(
128 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
130 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
132 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
133 session_refresh_interval=10)
135 interfaces = self.vapi.nat44_interface_dump()
136 for intf in interfaces:
137 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
138 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
139 self.vapi.nat44_interface_add_del_feature(
140 sw_if_index=intf.sw_if_index)
141 self.vapi.nat44_interface_add_del_feature(
142 sw_if_index=intf.sw_if_index,
145 interfaces = self.vapi.nat44_interface_output_feature_dump()
146 for intf in interfaces:
147 self.vapi.nat44_interface_add_del_output_feature(
150 sw_if_index=intf.sw_if_index)
151 static_mappings = self.vapi.nat44_static_mapping_dump()
152 for sm in static_mappings:
153 self.vapi.nat44_add_del_static_mapping(
155 local_ip_address=sm.local_ip_address,
156 external_ip_address=sm.external_ip_address,
157 external_sw_if_index=sm.external_sw_if_index,
158 local_port=sm.local_port,
159 external_port=sm.external_port,
161 protocol=sm.protocol,
162 flags=sm.flags, tag=sm.tag)
164 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
165 for lb_sm in lb_static_mappings:
166 self.vapi.nat44_add_del_lb_static_mapping(
169 external_addr=lb_sm.external_addr,
170 external_port=lb_sm.external_port,
171 protocol=lb_sm.protocol,
172 local_num=0, locals=[],
175 identity_mappings = self.vapi.nat44_identity_mapping_dump()
176 for id_m in identity_mappings:
177 self.vapi.nat44_add_del_identity_mapping(
178 ip_address=id_m.ip_address,
179 sw_if_index=id_m.sw_if_index,
183 protocol=id_m.protocol)
185 addresses = self.vapi.nat44_address_dump()
186 for addr in addresses:
187 self.vapi.nat44_add_del_address_range(
188 first_ip_address=addr.ip_address,
189 last_ip_address=addr.ip_address,
190 vrf_id=0xFFFFFFFF, flags=addr.flags)
192 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
194 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
195 drop_frag=0, is_ip6=1)
196 self.verify_no_nat44_user()
197 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
198 tcp_transitory=240, icmp=60)
199 self.vapi.nat_set_addr_and_port_alloc_alg()
200 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
202 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
203 local_port=0, external_port=0, vrf_id=0,
204 is_add=1, external_sw_if_index=0xFFFFFFFF,
205 proto=0, tag="", flags=0):
207 Add/delete NAT44 static mapping
209 :param local_ip: Local IP address
210 :param external_ip: External IP address
211 :param local_port: Local port number (Optional)
212 :param external_port: External port number (Optional)
213 :param vrf_id: VRF ID (Default 0)
214 :param is_add: 1 if add, 0 if delete (Default add)
215 :param external_sw_if_index: External interface instead of IP address
216 :param proto: IP protocol (Mandatory if port specified)
217 :param tag: Opaque string tag
218 :param flags: NAT configuration flags
221 if not (local_port and external_port):
222 flags |= self.config_flags.NAT_IS_ADDR_ONLY
224 self.vapi.nat44_add_del_static_mapping(
226 local_ip_address=local_ip,
227 external_ip_address=external_ip,
228 external_sw_if_index=external_sw_if_index,
229 local_port=local_port,
230 external_port=external_port,
231 vrf_id=vrf_id, protocol=proto,
235 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
237 Add/delete NAT44 address
239 :param ip: IP address
240 :param is_add: 1 if add, 0 if delete (Default add)
241 :param twice_nat: twice NAT address for external hosts
243 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
244 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
250 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
252 Create packet stream for inside network
254 :param in_if: Inside interface
255 :param out_if: Outside interface
256 :param dst_ip: Destination address
257 :param ttl: TTL of generated packets
260 dst_ip = out_if.remote_ip4
264 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
265 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
266 TCP(sport=self.tcp_port_in, dport=20))
270 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
271 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
272 UDP(sport=self.udp_port_in, dport=20))
276 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
277 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
278 ICMP(id=self.icmp_id_in, type='echo-request'))
283 def compose_ip6(self, ip4, pref, plen):
285 Compose IPv4-embedded IPv6 addresses
287 :param ip4: IPv4 address
288 :param pref: IPv6 prefix
289 :param plen: IPv6 prefix length
290 :returns: IPv4-embedded IPv6 addresses
292 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
293 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
308 pref_n[10] = ip4_n[3]
312 pref_n[10] = ip4_n[2]
313 pref_n[11] = ip4_n[3]
316 pref_n[10] = ip4_n[1]
317 pref_n[11] = ip4_n[2]
318 pref_n[12] = ip4_n[3]
320 pref_n[12] = ip4_n[0]
321 pref_n[13] = ip4_n[1]
322 pref_n[14] = ip4_n[2]
323 pref_n[15] = ip4_n[3]
324 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
325 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
327 def extract_ip4(self, ip6, plen):
329 Extract IPv4 address embedded in IPv6 addresses
331 :param ip6: IPv6 address
332 :param plen: IPv6 prefix length
333 :returns: extracted IPv4 address
335 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
367 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
369 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
371 Create IPv6 packet stream for inside network
373 :param in_if: Inside interface
374 :param out_if: Outside interface
375 :param ttl: Hop Limit of generated packets
376 :param pref: NAT64 prefix
377 :param plen: NAT64 prefix length
381 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
383 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
386 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
387 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
388 TCP(sport=self.tcp_port_in, dport=20))
392 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
393 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
394 UDP(sport=self.udp_port_in, dport=20))
398 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
399 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
400 ICMPv6EchoRequest(id=self.icmp_id_in))
405 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
406 use_inside_ports=False):
408 Create packet stream for outside network
410 :param out_if: Outside interface
411 :param dst_ip: Destination IP address (Default use global NAT address)
412 :param ttl: TTL of generated packets
413 :param use_inside_ports: Use inside NAT ports as destination ports
414 instead of outside ports
417 dst_ip = self.nat_addr
418 if not use_inside_ports:
419 tcp_port = self.tcp_port_out
420 udp_port = self.udp_port_out
421 icmp_id = self.icmp_id_out
423 tcp_port = self.tcp_port_in
424 udp_port = self.udp_port_in
425 icmp_id = self.icmp_id_in
428 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
429 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
430 TCP(dport=tcp_port, sport=20))
434 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
435 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
436 UDP(dport=udp_port, sport=20))
440 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
441 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
442 ICMP(id=icmp_id, type='echo-reply'))
447 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
449 Create packet stream for outside network
451 :param out_if: Outside interface
452 :param dst_ip: Destination IP address (Default use global NAT address)
453 :param hl: HL of generated packets
457 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
458 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
459 TCP(dport=self.tcp_port_out, sport=20))
463 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
464 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
465 UDP(dport=self.udp_port_out, sport=20))
469 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
470 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
471 ICMPv6EchoReply(id=self.icmp_id_out))
476 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
477 dst_ip=None, is_ip6=False):
479 Verify captured packets on outside network
481 :param capture: Captured packets
482 :param nat_ip: Translated IP address (Default use global NAT address)
483 :param same_port: Source port number is not translated (Default False)
484 :param dst_ip: Destination IP address (Default do not verify)
485 :param is_ip6: If L3 protocol is IPv6 (Default False)
489 ICMP46 = ICMPv6EchoRequest
494 nat_ip = self.nat_addr
495 for packet in capture:
498 self.assert_packet_checksums_valid(packet)
499 self.assertEqual(packet[IP46].src, nat_ip)
500 if dst_ip is not None:
501 self.assertEqual(packet[IP46].dst, dst_ip)
502 if packet.haslayer(TCP):
504 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
507 packet[TCP].sport, self.tcp_port_in)
508 self.tcp_port_out = packet[TCP].sport
509 self.assert_packet_checksums_valid(packet)
510 elif packet.haslayer(UDP):
512 self.assertEqual(packet[UDP].sport, self.udp_port_in)
515 packet[UDP].sport, self.udp_port_in)
516 self.udp_port_out = packet[UDP].sport
519 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
521 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
522 self.icmp_id_out = packet[ICMP46].id
523 self.assert_packet_checksums_valid(packet)
525 self.logger.error(ppp("Unexpected or invalid packet "
526 "(outside network):", packet))
529 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
532 Verify captured packets on outside network
534 :param capture: Captured packets
535 :param nat_ip: Translated IP address
536 :param same_port: Source port number is not translated (Default False)
537 :param dst_ip: Destination IP address (Default do not verify)
539 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
542 def verify_capture_in(self, capture, in_if):
544 Verify captured packets on inside network
546 :param capture: Captured packets
547 :param in_if: Inside interface
549 for packet in capture:
551 self.assert_packet_checksums_valid(packet)
552 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
553 if packet.haslayer(TCP):
554 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
555 elif packet.haslayer(UDP):
556 self.assertEqual(packet[UDP].dport, self.udp_port_in)
558 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
560 self.logger.error(ppp("Unexpected or invalid packet "
561 "(inside network):", packet))
564 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
566 Verify captured IPv6 packets on inside network
568 :param capture: Captured packets
569 :param src_ip: Source IP
570 :param dst_ip: Destination IP address
572 for packet in capture:
574 self.assertEqual(packet[IPv6].src, src_ip)
575 self.assertEqual(packet[IPv6].dst, dst_ip)
576 self.assert_packet_checksums_valid(packet)
577 if packet.haslayer(TCP):
578 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
579 elif packet.haslayer(UDP):
580 self.assertEqual(packet[UDP].dport, self.udp_port_in)
582 self.assertEqual(packet[ICMPv6EchoReply].id,
585 self.logger.error(ppp("Unexpected or invalid packet "
586 "(inside network):", packet))
589 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
591 Verify captured packet that don't have to be translated
593 :param capture: Captured packets
594 :param ingress_if: Ingress interface
595 :param egress_if: Egress interface
597 for packet in capture:
599 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
600 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
601 if packet.haslayer(TCP):
602 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
603 elif packet.haslayer(UDP):
604 self.assertEqual(packet[UDP].sport, self.udp_port_in)
606 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
608 self.logger.error(ppp("Unexpected or invalid packet "
609 "(inside network):", packet))
612 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
615 Verify captured packets with ICMP errors on outside network
617 :param capture: Captured packets
618 :param src_ip: Translated IP address or IP address of VPP
619 (Default use global NAT address)
620 :param icmp_type: Type of error ICMP packet
621 we are expecting (Default 11)
624 src_ip = self.nat_addr
625 for packet in capture:
627 self.assertEqual(packet[IP].src, src_ip)
628 self.assertEqual(packet.haslayer(ICMP), 1)
630 self.assertEqual(icmp.type, icmp_type)
631 self.assertTrue(icmp.haslayer(IPerror))
632 inner_ip = icmp[IPerror]
633 if inner_ip.haslayer(TCPerror):
634 self.assertEqual(inner_ip[TCPerror].dport,
636 elif inner_ip.haslayer(UDPerror):
637 self.assertEqual(inner_ip[UDPerror].dport,
640 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
642 self.logger.error(ppp("Unexpected or invalid packet "
643 "(outside network):", packet))
646 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
648 Verify captured packets with ICMP errors on inside network
650 :param capture: Captured packets
651 :param in_if: Inside interface
652 :param icmp_type: Type of error ICMP packet
653 we are expecting (Default 11)
655 for packet in capture:
657 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
658 self.assertEqual(packet.haslayer(ICMP), 1)
660 self.assertEqual(icmp.type, icmp_type)
661 self.assertTrue(icmp.haslayer(IPerror))
662 inner_ip = icmp[IPerror]
663 if inner_ip.haslayer(TCPerror):
664 self.assertEqual(inner_ip[TCPerror].sport,
666 elif inner_ip.haslayer(UDPerror):
667 self.assertEqual(inner_ip[UDPerror].sport,
670 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
672 self.logger.error(ppp("Unexpected or invalid packet "
673 "(inside network):", packet))
676 def create_stream_frag(self, src_if, dst, sport, dport, data,
677 proto=IP_PROTOS.tcp, echo_reply=False):
679 Create fragmented packet stream
681 :param src_if: Source interface
682 :param dst: Destination IPv4 address
683 :param sport: Source port
684 :param dport: Destination port
685 :param data: Payload data
686 :param proto: protocol (TCP, UDP, ICMP)
687 :param echo_reply: use echo_reply if protocol is ICMP
690 if proto == IP_PROTOS.tcp:
691 p = (IP(src=src_if.remote_ip4, dst=dst) /
692 TCP(sport=sport, dport=dport) /
694 p = p.__class__(scapy.compat.raw(p))
695 chksum = p[TCP].chksum
696 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
697 elif proto == IP_PROTOS.udp:
698 proto_header = UDP(sport=sport, dport=dport)
699 elif proto == IP_PROTOS.icmp:
701 proto_header = ICMP(id=sport, type='echo-request')
703 proto_header = ICMP(id=sport, type='echo-reply')
705 raise Exception("Unsupported protocol")
706 id = random.randint(0, 65535)
708 if proto == IP_PROTOS.tcp:
711 raw = Raw(data[0:16])
712 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
713 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
717 if proto == IP_PROTOS.tcp:
718 raw = Raw(data[4:20])
720 raw = Raw(data[16:32])
721 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
722 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
726 if proto == IP_PROTOS.tcp:
730 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
731 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
737 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
738 pref=None, plen=0, frag_size=128):
740 Create fragmented packet stream
742 :param src_if: Source interface
743 :param dst: Destination IPv4 address
744 :param sport: Source TCP port
745 :param dport: Destination TCP port
746 :param data: Payload data
747 :param pref: NAT64 prefix
748 :param plen: NAT64 prefix length
749 :param fragsize: size of fragments
753 dst_ip6 = ''.join(['64:ff9b::', dst])
755 dst_ip6 = self.compose_ip6(dst, pref, plen)
757 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
758 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
759 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
760 TCP(sport=sport, dport=dport) /
763 return fragment6(p, frag_size)
765 def reass_frags_and_verify(self, frags, src, dst):
767 Reassemble and verify fragmented packet
769 :param frags: Captured fragments
770 :param src: Source IPv4 address to verify
771 :param dst: Destination IPv4 address to verify
773 :returns: Reassembled IPv4 packet
777 self.assertEqual(p[IP].src, src)
778 self.assertEqual(p[IP].dst, dst)
779 self.assert_ip_checksum_valid(p)
780 buffer.seek(p[IP].frag * 8)
781 buffer.write(bytes(p[IP].payload))
782 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
783 proto=frags[0][IP].proto)
784 if ip.proto == IP_PROTOS.tcp:
785 p = (ip / TCP(buffer.getvalue()))
786 self.assert_tcp_checksum_valid(p)
787 elif ip.proto == IP_PROTOS.udp:
788 p = (ip / UDP(buffer.getvalue()[:8]) /
789 Raw(buffer.getvalue()[8:]))
790 elif ip.proto == IP_PROTOS.icmp:
791 p = (ip / ICMP(buffer.getvalue()))
794 def reass_frags_and_verify_ip6(self, frags, src, dst):
796 Reassemble and verify fragmented packet
798 :param frags: Captured fragments
799 :param src: Source IPv6 address to verify
800 :param dst: Destination IPv6 address to verify
802 :returns: Reassembled IPv6 packet
806 self.assertEqual(p[IPv6].src, src)
807 self.assertEqual(p[IPv6].dst, dst)
808 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
809 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
810 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
811 nh=frags[0][IPv6ExtHdrFragment].nh)
812 if ip.nh == IP_PROTOS.tcp:
813 p = (ip / TCP(buffer.getvalue()))
814 elif ip.nh == IP_PROTOS.udp:
815 p = (ip / UDP(buffer.getvalue()))
816 self.assert_packet_checksums_valid(p)
819 def initiate_tcp_session(self, in_if, out_if):
821 Initiates TCP session
823 :param in_if: Inside interface
824 :param out_if: Outside interface
828 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
829 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
830 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
833 self.pg_enable_capture(self.pg_interfaces)
835 capture = out_if.get_capture(1)
837 self.tcp_port_out = p[TCP].sport
839 # SYN + ACK packet out->in
840 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
841 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
842 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
845 self.pg_enable_capture(self.pg_interfaces)
850 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
851 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
852 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
855 self.pg_enable_capture(self.pg_interfaces)
857 out_if.get_capture(1)
860 self.logger.error("TCP 3 way handshake failed")
863 def verify_ipfix_nat44_ses(self, data):
865 Verify IPFIX NAT44 session create/delete event
867 :param data: Decoded IPFIX data records
869 nat44_ses_create_num = 0
870 nat44_ses_delete_num = 0
871 self.assertEqual(6, len(data))
874 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
875 if scapy.compat.orb(record[230]) == 4:
876 nat44_ses_create_num += 1
878 nat44_ses_delete_num += 1
880 self.assertEqual(self.pg0.remote_ip4n, record[8])
881 # postNATSourceIPv4Address
882 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
885 self.assertEqual(struct.pack("!I", 0), record[234])
886 # protocolIdentifier/sourceTransportPort
887 # /postNAPTSourceTransportPort
888 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
889 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
890 self.assertEqual(struct.pack("!H", self.icmp_id_out),
892 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
893 self.assertEqual(struct.pack("!H", self.tcp_port_in),
895 self.assertEqual(struct.pack("!H", self.tcp_port_out),
897 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
898 self.assertEqual(struct.pack("!H", self.udp_port_in),
900 self.assertEqual(struct.pack("!H", self.udp_port_out),
903 self.fail("Invalid protocol")
904 self.assertEqual(3, nat44_ses_create_num)
905 self.assertEqual(3, nat44_ses_delete_num)
907 def verify_ipfix_addr_exhausted(self, data):
909 Verify IPFIX NAT addresses event
911 :param data: Decoded IPFIX data records
913 self.assertEqual(1, len(data))
916 self.assertEqual(scapy.compat.orb(record[230]), 3)
918 self.assertEqual(struct.pack("!I", 0), record[283])
920 def verify_ipfix_max_sessions(self, data, limit):
922 Verify IPFIX maximum session entries exceeded event
924 :param data: Decoded IPFIX data records
925 :param limit: Number of maximum session entries that can be created.
927 self.assertEqual(1, len(data))
930 self.assertEqual(scapy.compat.orb(record[230]), 13)
931 # natQuotaExceededEvent
932 self.assertEqual(struct.pack("I", 1), record[466])
934 self.assertEqual(struct.pack("I", limit), record[471])
936 def verify_ipfix_max_bibs(self, data, limit):
938 Verify IPFIX maximum BIB entries exceeded event
940 :param data: Decoded IPFIX data records
941 :param limit: Number of maximum BIB entries that can be created.
943 self.assertEqual(1, len(data))
946 self.assertEqual(scapy.compat.orb(record[230]), 13)
947 # natQuotaExceededEvent
948 self.assertEqual(struct.pack("I", 2), record[466])
950 self.assertEqual(struct.pack("I", limit), record[472])
952 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
954 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
956 :param data: Decoded IPFIX data records
957 :param limit: Number of maximum fragments pending reassembly
958 :param src_addr: IPv6 source address
960 self.assertEqual(1, len(data))
963 self.assertEqual(scapy.compat.orb(record[230]), 13)
964 # natQuotaExceededEvent
965 self.assertEqual(struct.pack("I", 5), record[466])
966 # maxFragmentsPendingReassembly
967 self.assertEqual(struct.pack("I", limit), record[475])
969 self.assertEqual(src_addr, record[27])
971 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
973 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
975 :param data: Decoded IPFIX data records
976 :param limit: Number of maximum fragments pending reassembly
977 :param src_addr: IPv4 source address
979 self.assertEqual(1, len(data))
982 self.assertEqual(scapy.compat.orb(record[230]), 13)
983 # natQuotaExceededEvent
984 self.assertEqual(struct.pack("I", 5), record[466])
985 # maxFragmentsPendingReassembly
986 self.assertEqual(struct.pack("I", limit), record[475])
988 self.assertEqual(src_addr, record[8])
990 def verify_ipfix_bib(self, data, is_create, src_addr):
992 Verify IPFIX NAT64 BIB create and delete events
994 :param data: Decoded IPFIX data records
995 :param is_create: Create event if nonzero value otherwise delete event
996 :param src_addr: IPv6 source address
998 self.assertEqual(1, len(data))
1002 self.assertEqual(scapy.compat.orb(record[230]), 10)
1004 self.assertEqual(scapy.compat.orb(record[230]), 11)
1006 self.assertEqual(src_addr, record[27])
1007 # postNATSourceIPv4Address
1008 self.assertEqual(self.nat_addr_n, record[225])
1009 # protocolIdentifier
1010 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1012 self.assertEqual(struct.pack("!I", 0), record[234])
1013 # sourceTransportPort
1014 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1015 # postNAPTSourceTransportPort
1016 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1018 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1021 Verify IPFIX NAT64 session create and delete events
1023 :param data: Decoded IPFIX data records
1024 :param is_create: Create event if nonzero value otherwise delete event
1025 :param src_addr: IPv6 source address
1026 :param dst_addr: IPv4 destination address
1027 :param dst_port: destination TCP port
1029 self.assertEqual(1, len(data))
1033 self.assertEqual(scapy.compat.orb(record[230]), 6)
1035 self.assertEqual(scapy.compat.orb(record[230]), 7)
1037 self.assertEqual(src_addr, record[27])
1038 # destinationIPv6Address
1039 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1040 self.compose_ip6(dst_addr,
1044 # postNATSourceIPv4Address
1045 self.assertEqual(self.nat_addr_n, record[225])
1046 # postNATDestinationIPv4Address
1047 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1049 # protocolIdentifier
1050 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1052 self.assertEqual(struct.pack("!I", 0), record[234])
1053 # sourceTransportPort
1054 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1055 # postNAPTSourceTransportPort
1056 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1057 # destinationTransportPort
1058 self.assertEqual(struct.pack("!H", dst_port), record[11])
1059 # postNAPTDestinationTransportPort
1060 self.assertEqual(struct.pack("!H", dst_port), record[228])
1062 def verify_no_nat44_user(self):
1063 """ Verify that there is no NAT44 user """
1064 users = self.vapi.nat44_user_dump()
1065 self.assertEqual(len(users), 0)
1066 users = self.statistics.get_counter('/nat44/total-users')
1067 self.assertEqual(users[0][0], 0)
1068 sessions = self.statistics.get_counter('/nat44/total-sessions')
1069 self.assertEqual(sessions[0][0], 0)
1071 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1073 Verify IPFIX maximum entries per user exceeded event
1075 :param data: Decoded IPFIX data records
1076 :param limit: Number of maximum entries per user
1077 :param src_addr: IPv4 source address
1079 self.assertEqual(1, len(data))
1082 self.assertEqual(scapy.compat.orb(record[230]), 13)
1083 # natQuotaExceededEvent
1084 self.assertEqual(struct.pack("I", 3), record[466])
1086 self.assertEqual(struct.pack("I", limit), record[473])
1088 self.assertEqual(src_addr, record[8])
1090 def verify_syslog_apmap(self, data, is_add=True):
1091 message = data.decode('utf-8')
1093 message = SyslogMessage.parse(message)
1094 except ParseError as e:
1095 self.logger.error(e)
1098 self.assertEqual(message.severity, SyslogSeverity.info)
1099 self.assertEqual(message.appname, 'NAT')
1100 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1101 sd_params = message.sd.get('napmap')
1102 self.assertTrue(sd_params is not None)
1103 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1104 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1105 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1106 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1107 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1108 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1109 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1110 self.assertTrue(sd_params.get('SSUBIX') is not None)
1111 self.assertEqual(sd_params.get('SVLAN'), '0')
1113 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1114 message = data.decode('utf-8')
1116 message = SyslogMessage.parse(message)
1117 except ParseError as e:
1118 self.logger.error(e)
1121 self.assertEqual(message.severity, SyslogSeverity.info)
1122 self.assertEqual(message.appname, 'NAT')
1123 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1124 sd_params = message.sd.get('nsess')
1125 self.assertTrue(sd_params is not None)
1127 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1128 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1130 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1131 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1132 self.assertTrue(sd_params.get('SSUBIX') is not None)
1133 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1134 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1135 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1136 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1137 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1138 self.assertEqual(sd_params.get('SVLAN'), '0')
1139 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1140 self.assertEqual(sd_params.get('XDPORT'),
1141 "%d" % self.tcp_external_port)
1143 def verify_mss_value(self, pkt, mss):
1145 Verify TCP MSS value
1150 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1151 raise TypeError("Not a TCP/IP packet")
1153 for option in pkt[TCP].options:
1154 if option[0] == 'MSS':
1155 self.assertEqual(option[1], mss)
1156 self.assert_tcp_checksum_valid(pkt)
1159 def proto2layer(proto):
1160 if proto == IP_PROTOS.tcp:
1162 elif proto == IP_PROTOS.udp:
1164 elif proto == IP_PROTOS.icmp:
1167 raise Exception("Unsupported protocol")
1169 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1170 layer = self.proto2layer(proto)
1172 if proto == IP_PROTOS.tcp:
1173 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1175 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1176 self.port_in = random.randint(1025, 65535)
1178 reass = self.vapi.nat_reass_dump()
1179 reass_n_start = len(reass)
1182 pkts = self.create_stream_frag(self.pg0,
1183 self.pg1.remote_ip4,
1188 self.pg0.add_stream(pkts)
1189 self.pg_enable_capture(self.pg_interfaces)
1191 frags = self.pg1.get_capture(len(pkts))
1192 if not dont_translate:
1193 p = self.reass_frags_and_verify(frags,
1195 self.pg1.remote_ip4)
1197 p = self.reass_frags_and_verify(frags,
1198 self.pg0.remote_ip4,
1199 self.pg1.remote_ip4)
1200 if proto != IP_PROTOS.icmp:
1201 if not dont_translate:
1202 self.assertEqual(p[layer].dport, 20)
1203 self.assertNotEqual(p[layer].sport, self.port_in)
1205 self.assertEqual(p[layer].sport, self.port_in)
1207 if not dont_translate:
1208 self.assertNotEqual(p[layer].id, self.port_in)
1210 self.assertEqual(p[layer].id, self.port_in)
1211 self.assertEqual(data, p[Raw].load)
1214 if not dont_translate:
1215 dst_addr = self.nat_addr
1217 dst_addr = self.pg0.remote_ip4
1218 if proto != IP_PROTOS.icmp:
1220 dport = p[layer].sport
1224 pkts = self.create_stream_frag(self.pg1,
1231 self.pg1.add_stream(pkts)
1232 self.pg_enable_capture(self.pg_interfaces)
1234 frags = self.pg0.get_capture(len(pkts))
1235 p = self.reass_frags_and_verify(frags,
1236 self.pg1.remote_ip4,
1237 self.pg0.remote_ip4)
1238 if proto != IP_PROTOS.icmp:
1239 self.assertEqual(p[layer].sport, 20)
1240 self.assertEqual(p[layer].dport, self.port_in)
1242 self.assertEqual(p[layer].id, self.port_in)
1243 self.assertEqual(data, p[Raw].load)
1245 reass = self.vapi.nat_reass_dump()
1246 reass_n_end = len(reass)
1248 self.assertEqual(reass_n_end - reass_n_start, 2)
1250 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1251 layer = self.proto2layer(proto)
1253 if proto == IP_PROTOS.tcp:
1254 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1256 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1257 self.port_in = random.randint(1025, 65535)
1260 reass = self.vapi.nat_reass_dump()
1261 reass_n_start = len(reass)
1264 pkts = self.create_stream_frag(self.pg0,
1265 self.server_out_addr,
1267 self.server_out_port,
1270 self.pg0.add_stream(pkts)
1271 self.pg_enable_capture(self.pg_interfaces)
1273 frags = self.pg1.get_capture(len(pkts))
1274 p = self.reass_frags_and_verify(frags,
1275 self.pg0.remote_ip4,
1276 self.server_in_addr)
1277 if proto != IP_PROTOS.icmp:
1278 self.assertEqual(p[layer].sport, self.port_in)
1279 self.assertEqual(p[layer].dport, self.server_in_port)
1281 self.assertEqual(p[layer].id, self.port_in)
1282 self.assertEqual(data, p[Raw].load)
1285 if proto != IP_PROTOS.icmp:
1286 pkts = self.create_stream_frag(self.pg1,
1287 self.pg0.remote_ip4,
1288 self.server_in_port,
1293 pkts = self.create_stream_frag(self.pg1,
1294 self.pg0.remote_ip4,
1300 self.pg1.add_stream(pkts)
1301 self.pg_enable_capture(self.pg_interfaces)
1303 frags = self.pg0.get_capture(len(pkts))
1304 p = self.reass_frags_and_verify(frags,
1305 self.server_out_addr,
1306 self.pg0.remote_ip4)
1307 if proto != IP_PROTOS.icmp:
1308 self.assertEqual(p[layer].sport, self.server_out_port)
1309 self.assertEqual(p[layer].dport, self.port_in)
1311 self.assertEqual(p[layer].id, self.port_in)
1312 self.assertEqual(data, p[Raw].load)
1314 reass = self.vapi.nat_reass_dump()
1315 reass_n_end = len(reass)
1317 self.assertEqual(reass_n_end - reass_n_start, 2)
1319 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1320 layer = self.proto2layer(proto)
1322 if proto == IP_PROTOS.tcp:
1323 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1325 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1327 # send packet from host to server
1328 pkts = self.create_stream_frag(self.pg0,
1331 self.server_out_port,
1334 self.pg0.add_stream(pkts)
1335 self.pg_enable_capture(self.pg_interfaces)
1337 frags = self.pg0.get_capture(len(pkts))
1338 p = self.reass_frags_and_verify(frags,
1341 if proto != IP_PROTOS.icmp:
1342 self.assertNotEqual(p[layer].sport, self.host_in_port)
1343 self.assertEqual(p[layer].dport, self.server_in_port)
1345 self.assertNotEqual(p[layer].id, self.host_in_port)
1346 self.assertEqual(data, p[Raw].load)
1348 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1349 layer = self.proto2layer(proto)
1351 if proto == IP_PROTOS.tcp:
1352 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1354 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1355 self.port_in = random.randint(1025, 65535)
1359 pkts = self.create_stream_frag(self.pg0,
1360 self.pg1.remote_ip4,
1366 self.pg0.add_stream(pkts)
1367 self.pg_enable_capture(self.pg_interfaces)
1369 frags = self.pg1.get_capture(len(pkts))
1370 if not dont_translate:
1371 p = self.reass_frags_and_verify(frags,
1373 self.pg1.remote_ip4)
1375 p = self.reass_frags_and_verify(frags,
1376 self.pg0.remote_ip4,
1377 self.pg1.remote_ip4)
1378 if proto != IP_PROTOS.icmp:
1379 if not dont_translate:
1380 self.assertEqual(p[layer].dport, 20)
1381 self.assertNotEqual(p[layer].sport, self.port_in)
1383 self.assertEqual(p[layer].sport, self.port_in)
1385 if not dont_translate:
1386 self.assertNotEqual(p[layer].id, self.port_in)
1388 self.assertEqual(p[layer].id, self.port_in)
1389 self.assertEqual(data, p[Raw].load)
1392 if not dont_translate:
1393 dst_addr = self.nat_addr
1395 dst_addr = self.pg0.remote_ip4
1396 if proto != IP_PROTOS.icmp:
1398 dport = p[layer].sport
1402 pkts = self.create_stream_frag(self.pg1,
1410 self.pg1.add_stream(pkts)
1411 self.pg_enable_capture(self.pg_interfaces)
1413 frags = self.pg0.get_capture(len(pkts))
1414 p = self.reass_frags_and_verify(frags,
1415 self.pg1.remote_ip4,
1416 self.pg0.remote_ip4)
1417 if proto != IP_PROTOS.icmp:
1418 self.assertEqual(p[layer].sport, 20)
1419 self.assertEqual(p[layer].dport, self.port_in)
1421 self.assertEqual(p[layer].id, self.port_in)
1422 self.assertEqual(data, p[Raw].load)
1424 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1425 layer = self.proto2layer(proto)
1427 if proto == IP_PROTOS.tcp:
1428 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1430 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1431 self.port_in = random.randint(1025, 65535)
1435 pkts = self.create_stream_frag(self.pg0,
1436 self.server_out_addr,
1438 self.server_out_port,
1442 self.pg0.add_stream(pkts)
1443 self.pg_enable_capture(self.pg_interfaces)
1445 frags = self.pg1.get_capture(len(pkts))
1446 p = self.reass_frags_and_verify(frags,
1447 self.pg0.remote_ip4,
1448 self.server_in_addr)
1449 if proto != IP_PROTOS.icmp:
1450 self.assertEqual(p[layer].dport, self.server_in_port)
1451 self.assertEqual(p[layer].sport, self.port_in)
1452 self.assertEqual(p[layer].dport, self.server_in_port)
1454 self.assertEqual(p[layer].id, self.port_in)
1455 self.assertEqual(data, p[Raw].load)
1458 if proto != IP_PROTOS.icmp:
1459 pkts = self.create_stream_frag(self.pg1,
1460 self.pg0.remote_ip4,
1461 self.server_in_port,
1466 pkts = self.create_stream_frag(self.pg1,
1467 self.pg0.remote_ip4,
1474 self.pg1.add_stream(pkts)
1475 self.pg_enable_capture(self.pg_interfaces)
1477 frags = self.pg0.get_capture(len(pkts))
1478 p = self.reass_frags_and_verify(frags,
1479 self.server_out_addr,
1480 self.pg0.remote_ip4)
1481 if proto != IP_PROTOS.icmp:
1482 self.assertEqual(p[layer].sport, self.server_out_port)
1483 self.assertEqual(p[layer].dport, self.port_in)
1485 self.assertEqual(p[layer].id, self.port_in)
1486 self.assertEqual(data, p[Raw].load)
1489 class TestNAT44(MethodHolder):
1490 """ NAT44 Test Cases """
1493 def setUpClass(cls):
1494 super(TestNAT44, cls).setUpClass()
1495 cls.vapi.cli("set log class nat level debug")
1498 cls.tcp_port_in = 6303
1499 cls.tcp_port_out = 6303
1500 cls.udp_port_in = 6304
1501 cls.udp_port_out = 6304
1502 cls.icmp_id_in = 6305
1503 cls.icmp_id_out = 6305
1504 cls.nat_addr = '10.0.0.3'
1505 cls.ipfix_src_port = 4739
1506 cls.ipfix_domain_id = 1
1507 cls.tcp_external_port = 80
1508 cls.udp_external_port = 69
1510 cls.create_pg_interfaces(range(10))
1511 cls.interfaces = list(cls.pg_interfaces[0:4])
1513 for i in cls.interfaces:
1518 cls.pg0.generate_remote_hosts(3)
1519 cls.pg0.configure_ipv4_neighbors()
1521 cls.pg1.generate_remote_hosts(1)
1522 cls.pg1.configure_ipv4_neighbors()
1524 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1525 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1526 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
1528 cls.pg4._local_ip4 = "172.16.255.1"
1529 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1530 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1531 cls.pg4.set_table_ip4(10)
1532 cls.pg5._local_ip4 = "172.17.255.3"
1533 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1534 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1535 cls.pg5.set_table_ip4(10)
1536 cls.pg6._local_ip4 = "172.16.255.1"
1537 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1538 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1539 cls.pg6.set_table_ip4(20)
1540 for i in cls.overlapping_interfaces:
1548 cls.pg9.generate_remote_hosts(2)
1549 cls.pg9.config_ip4()
1550 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1551 cls.vapi.sw_interface_add_del_address(
1552 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1555 cls.pg9.resolve_arp()
1556 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1557 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1558 cls.pg9.resolve_arp()
1561 super(TestNAT44, cls).tearDownClass()
1565 def tearDownClass(cls):
1566 super(TestNAT44, cls).tearDownClass()
1568 def test_dynamic(self):
1569 """ NAT44 dynamic translation test """
1570 self.nat44_add_address(self.nat_addr)
1571 flags = self.config_flags.NAT_IS_INSIDE
1572 self.vapi.nat44_interface_add_del_feature(
1573 sw_if_index=self.pg0.sw_if_index,
1574 flags=flags, is_add=1)
1575 self.vapi.nat44_interface_add_del_feature(
1576 sw_if_index=self.pg1.sw_if_index,
1580 tcpn = self.statistics.get_counter(
1581 '/err/nat44-in2out-slowpath/TCP packets')
1582 udpn = self.statistics.get_counter(
1583 '/err/nat44-in2out-slowpath/UDP packets')
1584 icmpn = self.statistics.get_counter(
1585 '/err/nat44-in2out-slowpath/ICMP packets')
1586 totaln = self.statistics.get_counter(
1587 '/err/nat44-in2out-slowpath/good in2out packets processed')
1589 pkts = self.create_stream_in(self.pg0, self.pg1)
1590 self.pg0.add_stream(pkts)
1591 self.pg_enable_capture(self.pg_interfaces)
1593 capture = self.pg1.get_capture(len(pkts))
1594 self.verify_capture_out(capture)
1596 err = self.statistics.get_counter(
1597 '/err/nat44-in2out-slowpath/TCP packets')
1598 self.assertEqual(err - tcpn, 1)
1599 err = self.statistics.get_counter(
1600 '/err/nat44-in2out-slowpath/UDP packets')
1601 self.assertEqual(err - udpn, 1)
1602 err = self.statistics.get_counter(
1603 '/err/nat44-in2out-slowpath/ICMP packets')
1604 self.assertEqual(err - icmpn, 1)
1605 err = self.statistics.get_counter(
1606 '/err/nat44-in2out-slowpath/good in2out packets processed')
1607 self.assertEqual(err - totaln, 3)
1610 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1611 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1612 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1613 totaln = self.statistics.get_counter(
1614 '/err/nat44-out2in/good out2in packets processed')
1616 pkts = self.create_stream_out(self.pg1)
1617 self.pg1.add_stream(pkts)
1618 self.pg_enable_capture(self.pg_interfaces)
1620 capture = self.pg0.get_capture(len(pkts))
1621 self.verify_capture_in(capture, self.pg0)
1623 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1624 self.assertEqual(err - tcpn, 1)
1625 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1626 self.assertEqual(err - udpn, 1)
1627 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1628 self.assertEqual(err - icmpn, 1)
1629 err = self.statistics.get_counter(
1630 '/err/nat44-out2in/good out2in packets processed')
1631 self.assertEqual(err - totaln, 3)
1633 users = self.statistics.get_counter('/nat44/total-users')
1634 self.assertEqual(users[0][0], 1)
1635 sessions = self.statistics.get_counter('/nat44/total-sessions')
1636 self.assertEqual(sessions[0][0], 3)
1638 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1639 """ NAT44 handling of client packets with TTL=1 """
1641 self.nat44_add_address(self.nat_addr)
1642 flags = self.config_flags.NAT_IS_INSIDE
1643 self.vapi.nat44_interface_add_del_feature(
1644 sw_if_index=self.pg0.sw_if_index,
1645 flags=flags, is_add=1)
1646 self.vapi.nat44_interface_add_del_feature(
1647 sw_if_index=self.pg1.sw_if_index,
1650 # Client side - generate traffic
1651 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1652 self.pg0.add_stream(pkts)
1653 self.pg_enable_capture(self.pg_interfaces)
1656 # Client side - verify ICMP type 11 packets
1657 capture = self.pg0.get_capture(len(pkts))
1658 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1660 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1661 """ NAT44 handling of server packets with TTL=1 """
1663 self.nat44_add_address(self.nat_addr)
1664 flags = self.config_flags.NAT_IS_INSIDE
1665 self.vapi.nat44_interface_add_del_feature(
1666 sw_if_index=self.pg0.sw_if_index,
1667 flags=flags, is_add=1)
1668 self.vapi.nat44_interface_add_del_feature(
1669 sw_if_index=self.pg1.sw_if_index,
1672 # Client side - create sessions
1673 pkts = self.create_stream_in(self.pg0, self.pg1)
1674 self.pg0.add_stream(pkts)
1675 self.pg_enable_capture(self.pg_interfaces)
1678 # Server side - generate traffic
1679 capture = self.pg1.get_capture(len(pkts))
1680 self.verify_capture_out(capture)
1681 pkts = self.create_stream_out(self.pg1, ttl=1)
1682 self.pg1.add_stream(pkts)
1683 self.pg_enable_capture(self.pg_interfaces)
1686 # Server side - verify ICMP type 11 packets
1687 capture = self.pg1.get_capture(len(pkts))
1688 self.verify_capture_out_with_icmp_errors(capture,
1689 src_ip=self.pg1.local_ip4)
1691 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1692 """ NAT44 handling of error responses to client packets with TTL=2 """
1694 self.nat44_add_address(self.nat_addr)
1695 flags = self.config_flags.NAT_IS_INSIDE
1696 self.vapi.nat44_interface_add_del_feature(
1697 sw_if_index=self.pg0.sw_if_index,
1698 flags=flags, is_add=1)
1699 self.vapi.nat44_interface_add_del_feature(
1700 sw_if_index=self.pg1.sw_if_index,
1703 # Client side - generate traffic
1704 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1705 self.pg0.add_stream(pkts)
1706 self.pg_enable_capture(self.pg_interfaces)
1709 # Server side - simulate ICMP type 11 response
1710 capture = self.pg1.get_capture(len(pkts))
1711 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1712 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1713 ICMP(type=11) / packet[IP] for packet in capture]
1714 self.pg1.add_stream(pkts)
1715 self.pg_enable_capture(self.pg_interfaces)
1718 # Client side - verify ICMP type 11 packets
1719 capture = self.pg0.get_capture(len(pkts))
1720 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1722 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1723 """ NAT44 handling of error responses to server packets with TTL=2 """
1725 self.nat44_add_address(self.nat_addr)
1726 flags = self.config_flags.NAT_IS_INSIDE
1727 self.vapi.nat44_interface_add_del_feature(
1728 sw_if_index=self.pg0.sw_if_index,
1729 flags=flags, is_add=1)
1730 self.vapi.nat44_interface_add_del_feature(
1731 sw_if_index=self.pg1.sw_if_index,
1734 # Client side - create sessions
1735 pkts = self.create_stream_in(self.pg0, self.pg1)
1736 self.pg0.add_stream(pkts)
1737 self.pg_enable_capture(self.pg_interfaces)
1740 # Server side - generate traffic
1741 capture = self.pg1.get_capture(len(pkts))
1742 self.verify_capture_out(capture)
1743 pkts = self.create_stream_out(self.pg1, ttl=2)
1744 self.pg1.add_stream(pkts)
1745 self.pg_enable_capture(self.pg_interfaces)
1748 # Client side - simulate ICMP type 11 response
1749 capture = self.pg0.get_capture(len(pkts))
1750 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1751 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1752 ICMP(type=11) / packet[IP] for packet in capture]
1753 self.pg0.add_stream(pkts)
1754 self.pg_enable_capture(self.pg_interfaces)
1757 # Server side - verify ICMP type 11 packets
1758 capture = self.pg1.get_capture(len(pkts))
1759 self.verify_capture_out_with_icmp_errors(capture)
1761 def test_ping_out_interface_from_outside(self):
1762 """ Ping NAT44 out interface from outside network """
1764 self.nat44_add_address(self.nat_addr)
1765 flags = self.config_flags.NAT_IS_INSIDE
1766 self.vapi.nat44_interface_add_del_feature(
1767 sw_if_index=self.pg0.sw_if_index,
1768 flags=flags, is_add=1)
1769 self.vapi.nat44_interface_add_del_feature(
1770 sw_if_index=self.pg1.sw_if_index,
1773 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1774 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1775 ICMP(id=self.icmp_id_out, type='echo-request'))
1777 self.pg1.add_stream(pkts)
1778 self.pg_enable_capture(self.pg_interfaces)
1780 capture = self.pg1.get_capture(len(pkts))
1783 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1784 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1785 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1786 self.assertEqual(packet[ICMP].type, 0) # echo reply
1788 self.logger.error(ppp("Unexpected or invalid packet "
1789 "(outside network):", packet))
1792 def test_ping_internal_host_from_outside(self):
1793 """ Ping internal host from outside network """
1795 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1796 flags = self.config_flags.NAT_IS_INSIDE
1797 self.vapi.nat44_interface_add_del_feature(
1798 sw_if_index=self.pg0.sw_if_index,
1799 flags=flags, is_add=1)
1800 self.vapi.nat44_interface_add_del_feature(
1801 sw_if_index=self.pg1.sw_if_index,
1805 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1806 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1807 ICMP(id=self.icmp_id_out, type='echo-request'))
1808 self.pg1.add_stream(pkt)
1809 self.pg_enable_capture(self.pg_interfaces)
1811 capture = self.pg0.get_capture(1)
1812 self.verify_capture_in(capture, self.pg0)
1813 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1816 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1817 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1818 ICMP(id=self.icmp_id_in, type='echo-reply'))
1819 self.pg0.add_stream(pkt)
1820 self.pg_enable_capture(self.pg_interfaces)
1822 capture = self.pg1.get_capture(1)
1823 self.verify_capture_out(capture, same_port=True)
1824 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1826 def test_forwarding(self):
1827 """ NAT44 forwarding test """
1829 flags = self.config_flags.NAT_IS_INSIDE
1830 self.vapi.nat44_interface_add_del_feature(
1831 sw_if_index=self.pg0.sw_if_index,
1832 flags=flags, is_add=1)
1833 self.vapi.nat44_interface_add_del_feature(
1834 sw_if_index=self.pg1.sw_if_index,
1836 self.vapi.nat44_forwarding_enable_disable(enable=1)
1838 real_ip = self.pg0.remote_ip4n
1839 alias_ip = self.nat_addr
1840 flags = self.config_flags.NAT_IS_ADDR_ONLY
1841 self.vapi.nat44_add_del_static_mapping(is_add=1,
1842 local_ip_address=real_ip,
1843 external_ip_address=alias_ip,
1844 external_sw_if_index=0xFFFFFFFF,
1848 # static mapping match
1850 pkts = self.create_stream_out(self.pg1)
1851 self.pg1.add_stream(pkts)
1852 self.pg_enable_capture(self.pg_interfaces)
1854 capture = self.pg0.get_capture(len(pkts))
1855 self.verify_capture_in(capture, self.pg0)
1857 pkts = self.create_stream_in(self.pg0, self.pg1)
1858 self.pg0.add_stream(pkts)
1859 self.pg_enable_capture(self.pg_interfaces)
1861 capture = self.pg1.get_capture(len(pkts))
1862 self.verify_capture_out(capture, same_port=True)
1864 # no static mapping match
1866 host0 = self.pg0.remote_hosts[0]
1867 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1869 pkts = self.create_stream_out(self.pg1,
1870 dst_ip=self.pg0.remote_ip4,
1871 use_inside_ports=True)
1872 self.pg1.add_stream(pkts)
1873 self.pg_enable_capture(self.pg_interfaces)
1875 capture = self.pg0.get_capture(len(pkts))
1876 self.verify_capture_in(capture, self.pg0)
1878 pkts = self.create_stream_in(self.pg0, self.pg1)
1879 self.pg0.add_stream(pkts)
1880 self.pg_enable_capture(self.pg_interfaces)
1882 capture = self.pg1.get_capture(len(pkts))
1883 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1886 self.pg0.remote_hosts[0] = host0
1889 self.vapi.nat44_forwarding_enable_disable(enable=0)
1890 flags = self.config_flags.NAT_IS_ADDR_ONLY
1891 self.vapi.nat44_add_del_static_mapping(
1893 local_ip_address=real_ip,
1894 external_ip_address=alias_ip,
1895 external_sw_if_index=0xFFFFFFFF,
1898 def test_static_in(self):
1899 """ 1:1 NAT initialized from inside network """
1901 nat_ip = "10.0.0.10"
1902 self.tcp_port_out = 6303
1903 self.udp_port_out = 6304
1904 self.icmp_id_out = 6305
1906 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1907 flags = self.config_flags.NAT_IS_INSIDE
1908 self.vapi.nat44_interface_add_del_feature(
1909 sw_if_index=self.pg0.sw_if_index,
1910 flags=flags, is_add=1)
1911 self.vapi.nat44_interface_add_del_feature(
1912 sw_if_index=self.pg1.sw_if_index,
1914 sm = self.vapi.nat44_static_mapping_dump()
1915 self.assertEqual(len(sm), 1)
1916 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
1917 self.assertEqual(sm[0].protocol, 0)
1918 self.assertEqual(sm[0].local_port, 0)
1919 self.assertEqual(sm[0].external_port, 0)
1922 pkts = self.create_stream_in(self.pg0, self.pg1)
1923 self.pg0.add_stream(pkts)
1924 self.pg_enable_capture(self.pg_interfaces)
1926 capture = self.pg1.get_capture(len(pkts))
1927 self.verify_capture_out(capture, nat_ip, True)
1930 pkts = self.create_stream_out(self.pg1, nat_ip)
1931 self.pg1.add_stream(pkts)
1932 self.pg_enable_capture(self.pg_interfaces)
1934 capture = self.pg0.get_capture(len(pkts))
1935 self.verify_capture_in(capture, self.pg0)
1937 def test_static_out(self):
1938 """ 1:1 NAT initialized from outside network """
1940 nat_ip = "10.0.0.20"
1941 self.tcp_port_out = 6303
1942 self.udp_port_out = 6304
1943 self.icmp_id_out = 6305
1946 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1947 flags = self.config_flags.NAT_IS_INSIDE
1948 self.vapi.nat44_interface_add_del_feature(
1949 sw_if_index=self.pg0.sw_if_index,
1950 flags=flags, is_add=1)
1951 self.vapi.nat44_interface_add_del_feature(
1952 sw_if_index=self.pg1.sw_if_index,
1954 sm = self.vapi.nat44_static_mapping_dump()
1955 self.assertEqual(len(sm), 1)
1956 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
1959 pkts = self.create_stream_out(self.pg1, nat_ip)
1960 self.pg1.add_stream(pkts)
1961 self.pg_enable_capture(self.pg_interfaces)
1963 capture = self.pg0.get_capture(len(pkts))
1964 self.verify_capture_in(capture, self.pg0)
1967 pkts = self.create_stream_in(self.pg0, self.pg1)
1968 self.pg0.add_stream(pkts)
1969 self.pg_enable_capture(self.pg_interfaces)
1971 capture = self.pg1.get_capture(len(pkts))
1972 self.verify_capture_out(capture, nat_ip, True)
1974 def test_static_with_port_in(self):
1975 """ 1:1 NAPT initialized from inside network """
1977 self.tcp_port_out = 3606
1978 self.udp_port_out = 3607
1979 self.icmp_id_out = 3608
1981 self.nat44_add_address(self.nat_addr)
1982 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1983 self.tcp_port_in, self.tcp_port_out,
1984 proto=IP_PROTOS.tcp)
1985 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1986 self.udp_port_in, self.udp_port_out,
1987 proto=IP_PROTOS.udp)
1988 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1989 self.icmp_id_in, self.icmp_id_out,
1990 proto=IP_PROTOS.icmp)
1991 flags = self.config_flags.NAT_IS_INSIDE
1992 self.vapi.nat44_interface_add_del_feature(
1993 sw_if_index=self.pg0.sw_if_index,
1994 flags=flags, is_add=1)
1995 self.vapi.nat44_interface_add_del_feature(
1996 sw_if_index=self.pg1.sw_if_index,
2000 pkts = self.create_stream_in(self.pg0, self.pg1)
2001 self.pg0.add_stream(pkts)
2002 self.pg_enable_capture(self.pg_interfaces)
2004 capture = self.pg1.get_capture(len(pkts))
2005 self.verify_capture_out(capture)
2008 pkts = self.create_stream_out(self.pg1)
2009 self.pg1.add_stream(pkts)
2010 self.pg_enable_capture(self.pg_interfaces)
2012 capture = self.pg0.get_capture(len(pkts))
2013 self.verify_capture_in(capture, self.pg0)
2015 def test_static_with_port_out(self):
2016 """ 1:1 NAPT initialized from outside network """
2018 self.tcp_port_out = 30606
2019 self.udp_port_out = 30607
2020 self.icmp_id_out = 30608
2022 self.nat44_add_address(self.nat_addr)
2023 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2024 self.tcp_port_in, self.tcp_port_out,
2025 proto=IP_PROTOS.tcp)
2026 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2027 self.udp_port_in, self.udp_port_out,
2028 proto=IP_PROTOS.udp)
2029 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2030 self.icmp_id_in, self.icmp_id_out,
2031 proto=IP_PROTOS.icmp)
2032 flags = self.config_flags.NAT_IS_INSIDE
2033 self.vapi.nat44_interface_add_del_feature(
2034 sw_if_index=self.pg0.sw_if_index,
2035 flags=flags, is_add=1)
2036 self.vapi.nat44_interface_add_del_feature(
2037 sw_if_index=self.pg1.sw_if_index,
2041 pkts = self.create_stream_out(self.pg1)
2042 self.pg1.add_stream(pkts)
2043 self.pg_enable_capture(self.pg_interfaces)
2045 capture = self.pg0.get_capture(len(pkts))
2046 self.verify_capture_in(capture, self.pg0)
2049 pkts = self.create_stream_in(self.pg0, self.pg1)
2050 self.pg0.add_stream(pkts)
2051 self.pg_enable_capture(self.pg_interfaces)
2053 capture = self.pg1.get_capture(len(pkts))
2054 self.verify_capture_out(capture)
2056 def test_static_vrf_aware(self):
2057 """ 1:1 NAT VRF awareness """
2059 nat_ip1 = "10.0.0.30"
2060 nat_ip2 = "10.0.0.40"
2061 self.tcp_port_out = 6303
2062 self.udp_port_out = 6304
2063 self.icmp_id_out = 6305
2065 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2067 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2069 flags = self.config_flags.NAT_IS_INSIDE
2070 self.vapi.nat44_interface_add_del_feature(
2071 sw_if_index=self.pg3.sw_if_index,
2073 self.vapi.nat44_interface_add_del_feature(
2074 sw_if_index=self.pg0.sw_if_index,
2075 flags=flags, is_add=1)
2076 self.vapi.nat44_interface_add_del_feature(
2077 sw_if_index=self.pg4.sw_if_index,
2078 flags=flags, is_add=1)
2080 # inside interface VRF match NAT44 static mapping VRF
2081 pkts = self.create_stream_in(self.pg4, self.pg3)
2082 self.pg4.add_stream(pkts)
2083 self.pg_enable_capture(self.pg_interfaces)
2085 capture = self.pg3.get_capture(len(pkts))
2086 self.verify_capture_out(capture, nat_ip1, True)
2088 # inside interface VRF don't match NAT44 static mapping VRF (packets
2090 pkts = self.create_stream_in(self.pg0, self.pg3)
2091 self.pg0.add_stream(pkts)
2092 self.pg_enable_capture(self.pg_interfaces)
2094 self.pg3.assert_nothing_captured()
2096 def test_dynamic_to_static(self):
2097 """ Switch from dynamic translation to 1:1NAT """
2098 nat_ip = "10.0.0.10"
2099 self.tcp_port_out = 6303
2100 self.udp_port_out = 6304
2101 self.icmp_id_out = 6305
2103 self.nat44_add_address(self.nat_addr)
2104 flags = self.config_flags.NAT_IS_INSIDE
2105 self.vapi.nat44_interface_add_del_feature(
2106 sw_if_index=self.pg0.sw_if_index,
2107 flags=flags, is_add=1)
2108 self.vapi.nat44_interface_add_del_feature(
2109 sw_if_index=self.pg1.sw_if_index,
2113 pkts = self.create_stream_in(self.pg0, self.pg1)
2114 self.pg0.add_stream(pkts)
2115 self.pg_enable_capture(self.pg_interfaces)
2117 capture = self.pg1.get_capture(len(pkts))
2118 self.verify_capture_out(capture)
2121 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2122 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2123 self.assertEqual(len(sessions), 0)
2124 pkts = self.create_stream_in(self.pg0, self.pg1)
2125 self.pg0.add_stream(pkts)
2126 self.pg_enable_capture(self.pg_interfaces)
2128 capture = self.pg1.get_capture(len(pkts))
2129 self.verify_capture_out(capture, nat_ip, True)
2131 def test_identity_nat(self):
2132 """ Identity NAT """
2133 flags = self.config_flags.NAT_IS_ADDR_ONLY
2134 self.vapi.nat44_add_del_identity_mapping(
2135 ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
2136 flags=flags, is_add=1)
2137 flags = self.config_flags.NAT_IS_INSIDE
2138 self.vapi.nat44_interface_add_del_feature(
2139 sw_if_index=self.pg0.sw_if_index,
2140 flags=flags, is_add=1)
2141 self.vapi.nat44_interface_add_del_feature(
2142 sw_if_index=self.pg1.sw_if_index,
2145 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2146 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2147 TCP(sport=12345, dport=56789))
2148 self.pg1.add_stream(p)
2149 self.pg_enable_capture(self.pg_interfaces)
2151 capture = self.pg0.get_capture(1)
2156 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2157 self.assertEqual(ip.src, self.pg1.remote_ip4)
2158 self.assertEqual(tcp.dport, 56789)
2159 self.assertEqual(tcp.sport, 12345)
2160 self.assert_packet_checksums_valid(p)
2162 self.logger.error(ppp("Unexpected or invalid packet:", p))
2165 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2166 self.assertEqual(len(sessions), 0)
2167 flags = self.config_flags.NAT_IS_ADDR_ONLY
2168 self.vapi.nat44_add_del_identity_mapping(
2169 ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
2170 flags=flags, vrf_id=1, is_add=1)
2171 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2172 self.assertEqual(len(identity_mappings), 2)
2174 def test_multiple_inside_interfaces(self):
2175 """ NAT44 multiple non-overlapping address space inside interfaces """
2177 self.nat44_add_address(self.nat_addr)
2178 flags = self.config_flags.NAT_IS_INSIDE
2179 self.vapi.nat44_interface_add_del_feature(
2180 sw_if_index=self.pg0.sw_if_index,
2181 flags=flags, is_add=1)
2182 self.vapi.nat44_interface_add_del_feature(
2183 sw_if_index=self.pg1.sw_if_index,
2184 flags=flags, is_add=1)
2185 self.vapi.nat44_interface_add_del_feature(
2186 sw_if_index=self.pg3.sw_if_index,
2189 # between two NAT44 inside interfaces (no translation)
2190 pkts = self.create_stream_in(self.pg0, self.pg1)
2191 self.pg0.add_stream(pkts)
2192 self.pg_enable_capture(self.pg_interfaces)
2194 capture = self.pg1.get_capture(len(pkts))
2195 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2197 # from NAT44 inside to interface without NAT44 feature (no translation)
2198 pkts = self.create_stream_in(self.pg0, self.pg2)
2199 self.pg0.add_stream(pkts)
2200 self.pg_enable_capture(self.pg_interfaces)
2202 capture = self.pg2.get_capture(len(pkts))
2203 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2205 # in2out 1st interface
2206 pkts = self.create_stream_in(self.pg0, self.pg3)
2207 self.pg0.add_stream(pkts)
2208 self.pg_enable_capture(self.pg_interfaces)
2210 capture = self.pg3.get_capture(len(pkts))
2211 self.verify_capture_out(capture)
2213 # out2in 1st interface
2214 pkts = self.create_stream_out(self.pg3)
2215 self.pg3.add_stream(pkts)
2216 self.pg_enable_capture(self.pg_interfaces)
2218 capture = self.pg0.get_capture(len(pkts))
2219 self.verify_capture_in(capture, self.pg0)
2221 # in2out 2nd interface
2222 pkts = self.create_stream_in(self.pg1, self.pg3)
2223 self.pg1.add_stream(pkts)
2224 self.pg_enable_capture(self.pg_interfaces)
2226 capture = self.pg3.get_capture(len(pkts))
2227 self.verify_capture_out(capture)
2229 # out2in 2nd interface
2230 pkts = self.create_stream_out(self.pg3)
2231 self.pg3.add_stream(pkts)
2232 self.pg_enable_capture(self.pg_interfaces)
2234 capture = self.pg1.get_capture(len(pkts))
2235 self.verify_capture_in(capture, self.pg1)
2237 def test_inside_overlapping_interfaces(self):
2238 """ NAT44 multiple inside interfaces with overlapping address space """
2240 static_nat_ip = "10.0.0.10"
2241 self.nat44_add_address(self.nat_addr)
2242 flags = self.config_flags.NAT_IS_INSIDE
2243 self.vapi.nat44_interface_add_del_feature(
2244 sw_if_index=self.pg3.sw_if_index,
2246 self.vapi.nat44_interface_add_del_feature(
2247 sw_if_index=self.pg4.sw_if_index,
2248 flags=flags, is_add=1)
2249 self.vapi.nat44_interface_add_del_feature(
2250 sw_if_index=self.pg5.sw_if_index,
2251 flags=flags, is_add=1)
2252 self.vapi.nat44_interface_add_del_feature(
2253 sw_if_index=self.pg6.sw_if_index,
2254 flags=flags, is_add=1)
2255 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2258 # between NAT44 inside interfaces with same VRF (no translation)
2259 pkts = self.create_stream_in(self.pg4, self.pg5)
2260 self.pg4.add_stream(pkts)
2261 self.pg_enable_capture(self.pg_interfaces)
2263 capture = self.pg5.get_capture(len(pkts))
2264 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2266 # between NAT44 inside interfaces with different VRF (hairpinning)
2267 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2268 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2269 TCP(sport=1234, dport=5678))
2270 self.pg4.add_stream(p)
2271 self.pg_enable_capture(self.pg_interfaces)
2273 capture = self.pg6.get_capture(1)
2278 self.assertEqual(ip.src, self.nat_addr)
2279 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2280 self.assertNotEqual(tcp.sport, 1234)
2281 self.assertEqual(tcp.dport, 5678)
2283 self.logger.error(ppp("Unexpected or invalid packet:", p))
2286 # in2out 1st interface
2287 pkts = self.create_stream_in(self.pg4, self.pg3)
2288 self.pg4.add_stream(pkts)
2289 self.pg_enable_capture(self.pg_interfaces)
2291 capture = self.pg3.get_capture(len(pkts))
2292 self.verify_capture_out(capture)
2294 # out2in 1st interface
2295 pkts = self.create_stream_out(self.pg3)
2296 self.pg3.add_stream(pkts)
2297 self.pg_enable_capture(self.pg_interfaces)
2299 capture = self.pg4.get_capture(len(pkts))
2300 self.verify_capture_in(capture, self.pg4)
2302 # in2out 2nd interface
2303 pkts = self.create_stream_in(self.pg5, self.pg3)
2304 self.pg5.add_stream(pkts)
2305 self.pg_enable_capture(self.pg_interfaces)
2307 capture = self.pg3.get_capture(len(pkts))
2308 self.verify_capture_out(capture)
2310 # out2in 2nd interface
2311 pkts = self.create_stream_out(self.pg3)
2312 self.pg3.add_stream(pkts)
2313 self.pg_enable_capture(self.pg_interfaces)
2315 capture = self.pg5.get_capture(len(pkts))
2316 self.verify_capture_in(capture, self.pg5)
2319 addresses = self.vapi.nat44_address_dump()
2320 self.assertEqual(len(addresses), 1)
2321 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
2322 self.assertEqual(len(sessions), 3)
2323 for session in sessions:
2324 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2325 self.assertEqual(str(session.inside_ip_address),
2326 self.pg5.remote_ip4)
2327 self.assertEqual(session.outside_ip_address,
2328 addresses[0].ip_address)
2329 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2330 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2331 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2332 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2333 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2334 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2335 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2336 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2337 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2339 # in2out 3rd interface
2340 pkts = self.create_stream_in(self.pg6, self.pg3)
2341 self.pg6.add_stream(pkts)
2342 self.pg_enable_capture(self.pg_interfaces)
2344 capture = self.pg3.get_capture(len(pkts))
2345 self.verify_capture_out(capture, static_nat_ip, True)
2347 # out2in 3rd interface
2348 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2349 self.pg3.add_stream(pkts)
2350 self.pg_enable_capture(self.pg_interfaces)
2352 capture = self.pg6.get_capture(len(pkts))
2353 self.verify_capture_in(capture, self.pg6)
2355 # general user and session dump verifications
2356 users = self.vapi.nat44_user_dump()
2357 self.assertGreaterEqual(len(users), 3)
2358 addresses = self.vapi.nat44_address_dump()
2359 self.assertEqual(len(addresses), 1)
2361 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2363 for session in sessions:
2364 self.assertEqual(user.ip_address, session.inside_ip_address)
2365 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2366 self.assertTrue(session.protocol in
2367 [IP_PROTOS.tcp, IP_PROTOS.udp,
2369 self.assertFalse(session.flags &
2370 self.config_flags.NAT_IS_EXT_HOST_VALID)
2373 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
2374 self.assertGreaterEqual(len(sessions), 4)
2375 for session in sessions:
2376 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2377 self.assertEqual(str(session.inside_ip_address),
2378 self.pg4.remote_ip4)
2379 self.assertEqual(session.outside_ip_address,
2380 addresses[0].ip_address)
2383 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
2384 self.assertGreaterEqual(len(sessions), 3)
2385 for session in sessions:
2386 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2387 self.assertEqual(str(session.inside_ip_address),
2388 self.pg6.remote_ip4)
2389 self.assertEqual(str(session.outside_ip_address),
2391 self.assertTrue(session.inside_port in
2392 [self.tcp_port_in, self.udp_port_in,
2395 def test_hairpinning(self):
2396 """ NAT44 hairpinning - 1:1 NAPT """
2398 host = self.pg0.remote_hosts[0]
2399 server = self.pg0.remote_hosts[1]
2402 server_in_port = 5678
2403 server_out_port = 8765
2405 self.nat44_add_address(self.nat_addr)
2406 flags = self.config_flags.NAT_IS_INSIDE
2407 self.vapi.nat44_interface_add_del_feature(
2408 sw_if_index=self.pg0.sw_if_index,
2409 flags=flags, is_add=1)
2410 self.vapi.nat44_interface_add_del_feature(
2411 sw_if_index=self.pg1.sw_if_index,
2414 # add static mapping for server
2415 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2416 server_in_port, server_out_port,
2417 proto=IP_PROTOS.tcp)
2419 # send packet from host to server
2420 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2421 IP(src=host.ip4, dst=self.nat_addr) /
2422 TCP(sport=host_in_port, dport=server_out_port))
2423 self.pg0.add_stream(p)
2424 self.pg_enable_capture(self.pg_interfaces)
2426 capture = self.pg0.get_capture(1)
2431 self.assertEqual(ip.src, self.nat_addr)
2432 self.assertEqual(ip.dst, server.ip4)
2433 self.assertNotEqual(tcp.sport, host_in_port)
2434 self.assertEqual(tcp.dport, server_in_port)
2435 self.assert_packet_checksums_valid(p)
2436 host_out_port = tcp.sport
2438 self.logger.error(ppp("Unexpected or invalid packet:", p))
2441 # send reply from server to host
2442 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2443 IP(src=server.ip4, dst=self.nat_addr) /
2444 TCP(sport=server_in_port, dport=host_out_port))
2445 self.pg0.add_stream(p)
2446 self.pg_enable_capture(self.pg_interfaces)
2448 capture = self.pg0.get_capture(1)
2453 self.assertEqual(ip.src, self.nat_addr)
2454 self.assertEqual(ip.dst, host.ip4)
2455 self.assertEqual(tcp.sport, server_out_port)
2456 self.assertEqual(tcp.dport, host_in_port)
2457 self.assert_packet_checksums_valid(p)
2459 self.logger.error(ppp("Unexpected or invalid packet:", p))
2462 def test_hairpinning2(self):
2463 """ NAT44 hairpinning - 1:1 NAT"""
2465 server1_nat_ip = "10.0.0.10"
2466 server2_nat_ip = "10.0.0.11"
2467 host = self.pg0.remote_hosts[0]
2468 server1 = self.pg0.remote_hosts[1]
2469 server2 = self.pg0.remote_hosts[2]
2470 server_tcp_port = 22
2471 server_udp_port = 20
2473 self.nat44_add_address(self.nat_addr)
2474 flags = self.config_flags.NAT_IS_INSIDE
2475 self.vapi.nat44_interface_add_del_feature(
2476 sw_if_index=self.pg0.sw_if_index,
2477 flags=flags, is_add=1)
2478 self.vapi.nat44_interface_add_del_feature(
2479 sw_if_index=self.pg1.sw_if_index,
2482 # add static mapping for servers
2483 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2484 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2488 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2489 IP(src=host.ip4, dst=server1_nat_ip) /
2490 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2492 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2493 IP(src=host.ip4, dst=server1_nat_ip) /
2494 UDP(sport=self.udp_port_in, dport=server_udp_port))
2496 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2497 IP(src=host.ip4, dst=server1_nat_ip) /
2498 ICMP(id=self.icmp_id_in, type='echo-request'))
2500 self.pg0.add_stream(pkts)
2501 self.pg_enable_capture(self.pg_interfaces)
2503 capture = self.pg0.get_capture(len(pkts))
2504 for packet in capture:
2506 self.assertEqual(packet[IP].src, self.nat_addr)
2507 self.assertEqual(packet[IP].dst, server1.ip4)
2508 if packet.haslayer(TCP):
2509 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2510 self.assertEqual(packet[TCP].dport, server_tcp_port)
2511 self.tcp_port_out = packet[TCP].sport
2512 self.assert_packet_checksums_valid(packet)
2513 elif packet.haslayer(UDP):
2514 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2515 self.assertEqual(packet[UDP].dport, server_udp_port)
2516 self.udp_port_out = packet[UDP].sport
2518 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2519 self.icmp_id_out = packet[ICMP].id
2521 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2526 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2527 IP(src=server1.ip4, dst=self.nat_addr) /
2528 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2530 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2531 IP(src=server1.ip4, dst=self.nat_addr) /
2532 UDP(sport=server_udp_port, dport=self.udp_port_out))
2534 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2535 IP(src=server1.ip4, dst=self.nat_addr) /
2536 ICMP(id=self.icmp_id_out, type='echo-reply'))
2538 self.pg0.add_stream(pkts)
2539 self.pg_enable_capture(self.pg_interfaces)
2541 capture = self.pg0.get_capture(len(pkts))
2542 for packet in capture:
2544 self.assertEqual(packet[IP].src, server1_nat_ip)
2545 self.assertEqual(packet[IP].dst, host.ip4)
2546 if packet.haslayer(TCP):
2547 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2548 self.assertEqual(packet[TCP].sport, server_tcp_port)
2549 self.assert_packet_checksums_valid(packet)
2550 elif packet.haslayer(UDP):
2551 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2552 self.assertEqual(packet[UDP].sport, server_udp_port)
2554 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2556 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2559 # server2 to server1
2561 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2562 IP(src=server2.ip4, dst=server1_nat_ip) /
2563 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2565 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2566 IP(src=server2.ip4, dst=server1_nat_ip) /
2567 UDP(sport=self.udp_port_in, dport=server_udp_port))
2569 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2570 IP(src=server2.ip4, dst=server1_nat_ip) /
2571 ICMP(id=self.icmp_id_in, type='echo-request'))
2573 self.pg0.add_stream(pkts)
2574 self.pg_enable_capture(self.pg_interfaces)
2576 capture = self.pg0.get_capture(len(pkts))
2577 for packet in capture:
2579 self.assertEqual(packet[IP].src, server2_nat_ip)
2580 self.assertEqual(packet[IP].dst, server1.ip4)
2581 if packet.haslayer(TCP):
2582 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2583 self.assertEqual(packet[TCP].dport, server_tcp_port)
2584 self.tcp_port_out = packet[TCP].sport
2585 self.assert_packet_checksums_valid(packet)
2586 elif packet.haslayer(UDP):
2587 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2588 self.assertEqual(packet[UDP].dport, server_udp_port)
2589 self.udp_port_out = packet[UDP].sport
2591 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2592 self.icmp_id_out = packet[ICMP].id
2594 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2597 # server1 to server2
2599 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2600 IP(src=server1.ip4, dst=server2_nat_ip) /
2601 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2603 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2604 IP(src=server1.ip4, dst=server2_nat_ip) /
2605 UDP(sport=server_udp_port, dport=self.udp_port_out))
2607 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2608 IP(src=server1.ip4, dst=server2_nat_ip) /
2609 ICMP(id=self.icmp_id_out, type='echo-reply'))
2611 self.pg0.add_stream(pkts)
2612 self.pg_enable_capture(self.pg_interfaces)
2614 capture = self.pg0.get_capture(len(pkts))
2615 for packet in capture:
2617 self.assertEqual(packet[IP].src, server1_nat_ip)
2618 self.assertEqual(packet[IP].dst, server2.ip4)
2619 if packet.haslayer(TCP):
2620 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2621 self.assertEqual(packet[TCP].sport, server_tcp_port)
2622 self.assert_packet_checksums_valid(packet)
2623 elif packet.haslayer(UDP):
2624 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2625 self.assertEqual(packet[UDP].sport, server_udp_port)
2627 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2629 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2632 def test_max_translations_per_user(self):
2633 """ MAX translations per user - recycle the least recently used """
2635 self.nat44_add_address(self.nat_addr)
2636 flags = self.config_flags.NAT_IS_INSIDE
2637 self.vapi.nat44_interface_add_del_feature(
2638 sw_if_index=self.pg0.sw_if_index,
2639 flags=flags, is_add=1)
2640 self.vapi.nat44_interface_add_del_feature(
2641 sw_if_index=self.pg1.sw_if_index,
2644 # get maximum number of translations per user
2645 nat44_config = self.vapi.nat_show_config()
2647 # send more than maximum number of translations per user packets
2648 pkts_num = nat44_config.max_translations_per_user + 5
2650 for port in range(0, pkts_num):
2651 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2652 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2653 TCP(sport=1025 + port))
2655 self.pg0.add_stream(pkts)
2656 self.pg_enable_capture(self.pg_interfaces)
2659 # verify number of translated packet
2660 self.pg1.get_capture(pkts_num)
2662 users = self.vapi.nat44_user_dump()
2664 if user.ip_address == self.pg0.remote_ip4n:
2665 self.assertEqual(user.nsessions,
2666 nat44_config.max_translations_per_user)
2667 self.assertEqual(user.nstaticsessions, 0)
2670 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2672 proto=IP_PROTOS.tcp)
2673 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2674 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2675 TCP(sport=tcp_port))
2676 self.pg0.add_stream(p)
2677 self.pg_enable_capture(self.pg_interfaces)
2679 self.pg1.get_capture(1)
2680 users = self.vapi.nat44_user_dump()
2682 if user.ip_address == self.pg0.remote_ip4n:
2683 self.assertEqual(user.nsessions,
2684 nat44_config.max_translations_per_user - 1)
2685 self.assertEqual(user.nstaticsessions, 1)
2687 def test_interface_addr(self):
2688 """ Acquire NAT44 addresses from interface """
2689 self.vapi.nat44_add_del_interface_addr(
2691 sw_if_index=self.pg7.sw_if_index)
2693 # no address in NAT pool
2694 addresses = self.vapi.nat44_address_dump()
2695 self.assertEqual(0, len(addresses))
2697 # configure interface address and check NAT address pool
2698 self.pg7.config_ip4()
2699 addresses = self.vapi.nat44_address_dump()
2700 self.assertEqual(1, len(addresses))
2701 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2703 # remove interface address and check NAT address pool
2704 self.pg7.unconfig_ip4()
2705 addresses = self.vapi.nat44_address_dump()
2706 self.assertEqual(0, len(addresses))
2708 def test_interface_addr_static_mapping(self):
2709 """ Static mapping with addresses from interface """
2712 self.vapi.nat44_add_del_interface_addr(
2714 sw_if_index=self.pg7.sw_if_index)
2715 self.nat44_add_static_mapping(
2717 external_sw_if_index=self.pg7.sw_if_index,
2720 # static mappings with external interface
2721 static_mappings = self.vapi.nat44_static_mapping_dump()
2722 self.assertEqual(1, len(static_mappings))
2723 self.assertEqual(self.pg7.sw_if_index,
2724 static_mappings[0].external_sw_if_index)
2725 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
2727 # configure interface address and check static mappings
2728 self.pg7.config_ip4()
2729 static_mappings = self.vapi.nat44_static_mapping_dump()
2730 self.assertEqual(2, len(static_mappings))
2732 for sm in static_mappings:
2733 if sm.external_sw_if_index == 0xFFFFFFFF:
2734 self.assertEqual(str(sm.external_ip_address),
2736 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
2738 self.assertTrue(resolved)
2740 # remove interface address and check static mappings
2741 self.pg7.unconfig_ip4()
2742 static_mappings = self.vapi.nat44_static_mapping_dump()
2743 self.assertEqual(1, len(static_mappings))
2744 self.assertEqual(self.pg7.sw_if_index,
2745 static_mappings[0].external_sw_if_index)
2746 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
2748 # configure interface address again and check static mappings
2749 self.pg7.config_ip4()
2750 static_mappings = self.vapi.nat44_static_mapping_dump()
2751 self.assertEqual(2, len(static_mappings))
2753 for sm in static_mappings:
2754 if sm.external_sw_if_index == 0xFFFFFFFF:
2755 self.assertEqual(str(sm.external_ip_address),
2757 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
2759 self.assertTrue(resolved)
2761 # remove static mapping
2762 self.nat44_add_static_mapping(
2764 external_sw_if_index=self.pg7.sw_if_index,
2767 static_mappings = self.vapi.nat44_static_mapping_dump()
2768 self.assertEqual(0, len(static_mappings))
2770 def test_interface_addr_identity_nat(self):
2771 """ Identity NAT with addresses from interface """
2774 self.vapi.nat44_add_del_interface_addr(
2776 sw_if_index=self.pg7.sw_if_index)
2777 self.vapi.nat44_add_del_identity_mapping(
2779 sw_if_index=self.pg7.sw_if_index,
2781 protocol=IP_PROTOS.tcp,
2784 # identity mappings with external interface
2785 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2786 self.assertEqual(1, len(identity_mappings))
2787 self.assertEqual(self.pg7.sw_if_index,
2788 identity_mappings[0].sw_if_index)
2790 # configure interface address and check identity mappings
2791 self.pg7.config_ip4()
2792 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2794 self.assertEqual(2, len(identity_mappings))
2795 for sm in identity_mappings:
2796 if sm.sw_if_index == 0xFFFFFFFF:
2797 self.assertEqual(str(identity_mappings[0].ip_address),
2799 self.assertEqual(port, identity_mappings[0].port)
2800 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2802 self.assertTrue(resolved)
2804 # remove interface address and check identity mappings
2805 self.pg7.unconfig_ip4()
2806 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2807 self.assertEqual(1, len(identity_mappings))
2808 self.assertEqual(self.pg7.sw_if_index,
2809 identity_mappings[0].sw_if_index)
2811 def test_ipfix_nat44_sess(self):
2812 """ IPFIX logging NAT44 session created/deleted """
2813 self.ipfix_domain_id = 10
2814 self.ipfix_src_port = 20202
2815 collector_port = 30303
2816 bind_layers(UDP, IPFIX, dport=30303)
2817 self.nat44_add_address(self.nat_addr)
2818 flags = self.config_flags.NAT_IS_INSIDE
2819 self.vapi.nat44_interface_add_del_feature(
2820 sw_if_index=self.pg0.sw_if_index,
2821 flags=flags, is_add=1)
2822 self.vapi.nat44_interface_add_del_feature(
2823 sw_if_index=self.pg1.sw_if_index,
2825 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2826 src_address=self.pg3.local_ip4n,
2828 template_interval=10,
2829 collector_port=collector_port)
2830 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2831 src_port=self.ipfix_src_port,
2834 pkts = self.create_stream_in(self.pg0, self.pg1)
2835 self.pg0.add_stream(pkts)
2836 self.pg_enable_capture(self.pg_interfaces)
2838 capture = self.pg1.get_capture(len(pkts))
2839 self.verify_capture_out(capture)
2840 self.nat44_add_address(self.nat_addr, is_add=0)
2841 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2842 capture = self.pg3.get_capture(9)
2843 ipfix = IPFIXDecoder()
2844 # first load template
2846 self.assertTrue(p.haslayer(IPFIX))
2847 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2848 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2849 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2850 self.assertEqual(p[UDP].dport, collector_port)
2851 self.assertEqual(p[IPFIX].observationDomainID,
2852 self.ipfix_domain_id)
2853 if p.haslayer(Template):
2854 ipfix.add_template(p.getlayer(Template))
2855 # verify events in data set
2857 if p.haslayer(Data):
2858 data = ipfix.decode_data_set(p.getlayer(Set))
2859 self.verify_ipfix_nat44_ses(data)
2861 def test_ipfix_addr_exhausted(self):
2862 """ IPFIX logging NAT addresses exhausted """
2863 flags = self.config_flags.NAT_IS_INSIDE
2864 self.vapi.nat44_interface_add_del_feature(
2865 sw_if_index=self.pg0.sw_if_index,
2866 flags=flags, is_add=1)
2867 self.vapi.nat44_interface_add_del_feature(
2868 sw_if_index=self.pg1.sw_if_index,
2870 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2871 src_address=self.pg3.local_ip4n,
2873 template_interval=10)
2874 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2875 src_port=self.ipfix_src_port,
2878 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2879 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2881 self.pg0.add_stream(p)
2882 self.pg_enable_capture(self.pg_interfaces)
2884 self.pg1.assert_nothing_captured()
2886 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2887 capture = self.pg3.get_capture(9)
2888 ipfix = IPFIXDecoder()
2889 # first load template
2891 self.assertTrue(p.haslayer(IPFIX))
2892 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2893 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2894 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2895 self.assertEqual(p[UDP].dport, 4739)
2896 self.assertEqual(p[IPFIX].observationDomainID,
2897 self.ipfix_domain_id)
2898 if p.haslayer(Template):
2899 ipfix.add_template(p.getlayer(Template))
2900 # verify events in data set
2902 if p.haslayer(Data):
2903 data = ipfix.decode_data_set(p.getlayer(Set))
2904 self.verify_ipfix_addr_exhausted(data)
2906 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2907 def test_ipfix_max_sessions(self):
2908 """ IPFIX logging maximum session entries exceeded """
2909 self.nat44_add_address(self.nat_addr)
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,
2918 nat44_config = self.vapi.nat_show_config()
2919 max_sessions = 10 * nat44_config.translation_buckets
2922 for i in range(0, max_sessions):
2923 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2924 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2925 IP(src=src, dst=self.pg1.remote_ip4) /
2928 self.pg0.add_stream(pkts)
2929 self.pg_enable_capture(self.pg_interfaces)
2932 self.pg1.get_capture(max_sessions)
2933 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2934 src_address=self.pg3.local_ip4n,
2936 template_interval=10)
2937 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2938 src_port=self.ipfix_src_port,
2941 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2942 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2944 self.pg0.add_stream(p)
2945 self.pg_enable_capture(self.pg_interfaces)
2947 self.pg1.assert_nothing_captured()
2949 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2950 capture = self.pg3.get_capture(9)
2951 ipfix = IPFIXDecoder()
2952 # first load template
2954 self.assertTrue(p.haslayer(IPFIX))
2955 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2956 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2957 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2958 self.assertEqual(p[UDP].dport, 4739)
2959 self.assertEqual(p[IPFIX].observationDomainID,
2960 self.ipfix_domain_id)
2961 if p.haslayer(Template):
2962 ipfix.add_template(p.getlayer(Template))
2963 # verify events in data set
2965 if p.haslayer(Data):
2966 data = ipfix.decode_data_set(p.getlayer(Set))
2967 self.verify_ipfix_max_sessions(data, max_sessions)
2969 def test_syslog_apmap(self):
2970 """ Test syslog address and port mapping creation and deletion """
2971 self.vapi.syslog_set_filter(
2972 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2973 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
2974 self.nat44_add_address(self.nat_addr)
2975 flags = self.config_flags.NAT_IS_INSIDE
2976 self.vapi.nat44_interface_add_del_feature(
2977 sw_if_index=self.pg0.sw_if_index,
2978 flags=flags, is_add=1)
2979 self.vapi.nat44_interface_add_del_feature(
2980 sw_if_index=self.pg1.sw_if_index,
2983 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2984 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2985 TCP(sport=self.tcp_port_in, dport=20))
2986 self.pg0.add_stream(p)
2987 self.pg_enable_capture(self.pg_interfaces)
2989 capture = self.pg1.get_capture(1)
2990 self.tcp_port_out = capture[0][TCP].sport
2991 capture = self.pg3.get_capture(1)
2992 self.verify_syslog_apmap(capture[0][Raw].load)
2994 self.pg_enable_capture(self.pg_interfaces)
2996 self.nat44_add_address(self.nat_addr, is_add=0)
2997 capture = self.pg3.get_capture(1)
2998 self.verify_syslog_apmap(capture[0][Raw].load, False)
3000 def test_pool_addr_fib(self):
3001 """ NAT44 add pool addresses to FIB """
3002 static_addr = '10.0.0.10'
3003 self.nat44_add_address(self.nat_addr)
3004 flags = self.config_flags.NAT_IS_INSIDE
3005 self.vapi.nat44_interface_add_del_feature(
3006 sw_if_index=self.pg0.sw_if_index,
3007 flags=flags, is_add=1)
3008 self.vapi.nat44_interface_add_del_feature(
3009 sw_if_index=self.pg1.sw_if_index,
3011 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
3014 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3015 ARP(op=ARP.who_has, pdst=self.nat_addr,
3016 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3017 self.pg1.add_stream(p)
3018 self.pg_enable_capture(self.pg_interfaces)
3020 capture = self.pg1.get_capture(1)
3021 self.assertTrue(capture[0].haslayer(ARP))
3022 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3025 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3026 ARP(op=ARP.who_has, pdst=static_addr,
3027 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3028 self.pg1.add_stream(p)
3029 self.pg_enable_capture(self.pg_interfaces)
3031 capture = self.pg1.get_capture(1)
3032 self.assertTrue(capture[0].haslayer(ARP))
3033 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3035 # send ARP to non-NAT44 interface
3036 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3037 ARP(op=ARP.who_has, pdst=self.nat_addr,
3038 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
3039 self.pg2.add_stream(p)
3040 self.pg_enable_capture(self.pg_interfaces)
3042 self.pg1.assert_nothing_captured()
3044 # remove addresses and verify
3045 self.nat44_add_address(self.nat_addr, is_add=0)
3046 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
3049 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3050 ARP(op=ARP.who_has, pdst=self.nat_addr,
3051 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3052 self.pg1.add_stream(p)
3053 self.pg_enable_capture(self.pg_interfaces)
3055 self.pg1.assert_nothing_captured()
3057 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3058 ARP(op=ARP.who_has, pdst=static_addr,
3059 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3060 self.pg1.add_stream(p)
3061 self.pg_enable_capture(self.pg_interfaces)
3063 self.pg1.assert_nothing_captured()
3065 def test_vrf_mode(self):
3066 """ NAT44 tenant VRF aware address pool mode """
3070 nat_ip1 = "10.0.0.10"
3071 nat_ip2 = "10.0.0.11"
3073 self.pg0.unconfig_ip4()
3074 self.pg1.unconfig_ip4()
3075 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3076 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
3077 self.pg0.set_table_ip4(vrf_id1)
3078 self.pg1.set_table_ip4(vrf_id2)
3079 self.pg0.config_ip4()
3080 self.pg1.config_ip4()
3081 self.pg0.resolve_arp()
3082 self.pg1.resolve_arp()
3084 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
3085 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
3086 flags = self.config_flags.NAT_IS_INSIDE
3087 self.vapi.nat44_interface_add_del_feature(
3088 sw_if_index=self.pg0.sw_if_index,
3089 flags=flags, is_add=1)
3090 self.vapi.nat44_interface_add_del_feature(
3091 sw_if_index=self.pg1.sw_if_index,
3092 flags=flags, is_add=1)
3093 self.vapi.nat44_interface_add_del_feature(
3094 sw_if_index=self.pg2.sw_if_index,
3099 pkts = self.create_stream_in(self.pg0, self.pg2)
3100 self.pg0.add_stream(pkts)
3101 self.pg_enable_capture(self.pg_interfaces)
3103 capture = self.pg2.get_capture(len(pkts))
3104 self.verify_capture_out(capture, nat_ip1)
3107 pkts = self.create_stream_in(self.pg1, self.pg2)
3108 self.pg1.add_stream(pkts)
3109 self.pg_enable_capture(self.pg_interfaces)
3111 capture = self.pg2.get_capture(len(pkts))
3112 self.verify_capture_out(capture, nat_ip2)
3115 self.pg0.unconfig_ip4()
3116 self.pg1.unconfig_ip4()
3117 self.pg0.set_table_ip4(0)
3118 self.pg1.set_table_ip4(0)
3119 self.pg0.config_ip4()
3120 self.pg1.config_ip4()
3121 self.pg0.resolve_arp()
3122 self.pg1.resolve_arp()
3123 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
3124 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
3126 def test_vrf_feature_independent(self):
3127 """ NAT44 tenant VRF independent address pool mode """
3129 nat_ip1 = "10.0.0.10"
3130 nat_ip2 = "10.0.0.11"
3132 self.nat44_add_address(nat_ip1)
3133 self.nat44_add_address(nat_ip2, vrf_id=99)
3134 flags = self.config_flags.NAT_IS_INSIDE
3135 self.vapi.nat44_interface_add_del_feature(
3136 sw_if_index=self.pg0.sw_if_index,
3137 flags=flags, is_add=1)
3138 self.vapi.nat44_interface_add_del_feature(
3139 sw_if_index=self.pg1.sw_if_index,
3140 flags=flags, is_add=1)
3141 self.vapi.nat44_interface_add_del_feature(
3142 sw_if_index=self.pg2.sw_if_index,
3146 pkts = self.create_stream_in(self.pg0, self.pg2)
3147 self.pg0.add_stream(pkts)
3148 self.pg_enable_capture(self.pg_interfaces)
3150 capture = self.pg2.get_capture(len(pkts))
3151 self.verify_capture_out(capture, nat_ip1)
3154 pkts = self.create_stream_in(self.pg1, self.pg2)
3155 self.pg1.add_stream(pkts)
3156 self.pg_enable_capture(self.pg_interfaces)
3158 capture = self.pg2.get_capture(len(pkts))
3159 self.verify_capture_out(capture, nat_ip1)
3161 def test_dynamic_ipless_interfaces(self):
3162 """ NAT44 interfaces without configured IP address """
3164 self.vapi.ip_neighbor_add_del(
3165 self.pg7.sw_if_index,
3166 self.pg7.remote_mac,
3167 self.pg7.remote_ip4,
3168 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3169 IP_API_NEIGHBOR_FLAG_STATIC))
3170 self.vapi.ip_neighbor_add_del(
3171 self.pg8.sw_if_index,
3172 self.pg8.remote_mac,
3173 self.pg8.remote_ip4,
3174 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3175 IP_API_NEIGHBOR_FLAG_STATIC))
3177 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3178 dst_address_length=32,
3179 next_hop_address=self.pg7.remote_ip4n,
3180 next_hop_sw_if_index=self.pg7.sw_if_index)
3181 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3182 dst_address_length=32,
3183 next_hop_address=self.pg8.remote_ip4n,
3184 next_hop_sw_if_index=self.pg8.sw_if_index)
3186 self.nat44_add_address(self.nat_addr)
3187 flags = self.config_flags.NAT_IS_INSIDE
3188 self.vapi.nat44_interface_add_del_feature(
3189 sw_if_index=self.pg7.sw_if_index,
3190 flags=flags, is_add=1)
3191 self.vapi.nat44_interface_add_del_feature(
3192 sw_if_index=self.pg8.sw_if_index,
3196 pkts = self.create_stream_in(self.pg7, self.pg8)
3197 self.pg7.add_stream(pkts)
3198 self.pg_enable_capture(self.pg_interfaces)
3200 capture = self.pg8.get_capture(len(pkts))
3201 self.verify_capture_out(capture)
3204 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3205 self.pg8.add_stream(pkts)
3206 self.pg_enable_capture(self.pg_interfaces)
3208 capture = self.pg7.get_capture(len(pkts))
3209 self.verify_capture_in(capture, self.pg7)
3211 def test_static_ipless_interfaces(self):
3212 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3214 self.vapi.ip_neighbor_add_del(
3215 self.pg7.sw_if_index,
3216 self.pg7.remote_mac,
3217 self.pg7.remote_ip4,
3218 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3219 IP_API_NEIGHBOR_FLAG_STATIC))
3220 self.vapi.ip_neighbor_add_del(
3221 self.pg8.sw_if_index,
3222 self.pg8.remote_mac,
3223 self.pg8.remote_ip4,
3224 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3225 IP_API_NEIGHBOR_FLAG_STATIC))
3227 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3228 dst_address_length=32,
3229 next_hop_address=self.pg7.remote_ip4n,
3230 next_hop_sw_if_index=self.pg7.sw_if_index)
3231 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3232 dst_address_length=32,
3233 next_hop_address=self.pg8.remote_ip4n,
3234 next_hop_sw_if_index=self.pg8.sw_if_index)
3236 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3237 flags = self.config_flags.NAT_IS_INSIDE
3238 self.vapi.nat44_interface_add_del_feature(
3239 sw_if_index=self.pg7.sw_if_index,
3240 flags=flags, is_add=1)
3241 self.vapi.nat44_interface_add_del_feature(
3242 sw_if_index=self.pg8.sw_if_index,
3246 pkts = self.create_stream_out(self.pg8)
3247 self.pg8.add_stream(pkts)
3248 self.pg_enable_capture(self.pg_interfaces)
3250 capture = self.pg7.get_capture(len(pkts))
3251 self.verify_capture_in(capture, self.pg7)
3254 pkts = self.create_stream_in(self.pg7, self.pg8)
3255 self.pg7.add_stream(pkts)
3256 self.pg_enable_capture(self.pg_interfaces)
3258 capture = self.pg8.get_capture(len(pkts))
3259 self.verify_capture_out(capture, self.nat_addr, True)
3261 def test_static_with_port_ipless_interfaces(self):
3262 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3264 self.tcp_port_out = 30606
3265 self.udp_port_out = 30607
3266 self.icmp_id_out = 30608
3268 self.vapi.ip_neighbor_add_del(
3269 self.pg7.sw_if_index,
3270 self.pg7.remote_mac,
3271 self.pg7.remote_ip4,
3272 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3273 IP_API_NEIGHBOR_FLAG_STATIC))
3274 self.vapi.ip_neighbor_add_del(
3275 self.pg8.sw_if_index,
3276 self.pg8.remote_mac,
3277 self.pg8.remote_ip4,
3278 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3279 IP_API_NEIGHBOR_FLAG_STATIC))
3281 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3282 dst_address_length=32,
3283 next_hop_address=self.pg7.remote_ip4n,
3284 next_hop_sw_if_index=self.pg7.sw_if_index)
3285 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3286 dst_address_length=32,
3287 next_hop_address=self.pg8.remote_ip4n,
3288 next_hop_sw_if_index=self.pg8.sw_if_index)
3290 self.nat44_add_address(self.nat_addr)
3291 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3292 self.tcp_port_in, self.tcp_port_out,
3293 proto=IP_PROTOS.tcp)
3294 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3295 self.udp_port_in, self.udp_port_out,
3296 proto=IP_PROTOS.udp)
3297 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3298 self.icmp_id_in, self.icmp_id_out,
3299 proto=IP_PROTOS.icmp)
3300 flags = self.config_flags.NAT_IS_INSIDE
3301 self.vapi.nat44_interface_add_del_feature(
3302 sw_if_index=self.pg7.sw_if_index,
3303 flags=flags, is_add=1)
3304 self.vapi.nat44_interface_add_del_feature(
3305 sw_if_index=self.pg8.sw_if_index,
3309 pkts = self.create_stream_out(self.pg8)
3310 self.pg8.add_stream(pkts)
3311 self.pg_enable_capture(self.pg_interfaces)
3313 capture = self.pg7.get_capture(len(pkts))
3314 self.verify_capture_in(capture, self.pg7)
3317 pkts = self.create_stream_in(self.pg7, self.pg8)
3318 self.pg7.add_stream(pkts)
3319 self.pg_enable_capture(self.pg_interfaces)
3321 capture = self.pg8.get_capture(len(pkts))
3322 self.verify_capture_out(capture)
3324 def test_static_unknown_proto(self):
3325 """ 1:1 NAT translate packet with unknown protocol """
3326 nat_ip = "10.0.0.10"
3327 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3328 flags = self.config_flags.NAT_IS_INSIDE
3329 self.vapi.nat44_interface_add_del_feature(
3330 sw_if_index=self.pg0.sw_if_index,
3331 flags=flags, is_add=1)
3332 self.vapi.nat44_interface_add_del_feature(
3333 sw_if_index=self.pg1.sw_if_index,
3337 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3338 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3340 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3341 TCP(sport=1234, dport=1234))
3342 self.pg0.add_stream(p)
3343 self.pg_enable_capture(self.pg_interfaces)
3345 p = self.pg1.get_capture(1)
3348 self.assertEqual(packet[IP].src, nat_ip)
3349 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3350 self.assertEqual(packet.haslayer(GRE), 1)
3351 self.assert_packet_checksums_valid(packet)
3353 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3357 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3358 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3360 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3361 TCP(sport=1234, dport=1234))
3362 self.pg1.add_stream(p)
3363 self.pg_enable_capture(self.pg_interfaces)
3365 p = self.pg0.get_capture(1)
3368 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3369 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3370 self.assertEqual(packet.haslayer(GRE), 1)
3371 self.assert_packet_checksums_valid(packet)
3373 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3376 def test_hairpinning_static_unknown_proto(self):
3377 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3379 host = self.pg0.remote_hosts[0]
3380 server = self.pg0.remote_hosts[1]
3382 host_nat_ip = "10.0.0.10"
3383 server_nat_ip = "10.0.0.11"
3385 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3386 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3387 flags = self.config_flags.NAT_IS_INSIDE
3388 self.vapi.nat44_interface_add_del_feature(
3389 sw_if_index=self.pg0.sw_if_index,
3390 flags=flags, is_add=1)
3391 self.vapi.nat44_interface_add_del_feature(
3392 sw_if_index=self.pg1.sw_if_index,
3396 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3397 IP(src=host.ip4, dst=server_nat_ip) /
3399 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3400 TCP(sport=1234, dport=1234))
3401 self.pg0.add_stream(p)
3402 self.pg_enable_capture(self.pg_interfaces)
3404 p = self.pg0.get_capture(1)
3407 self.assertEqual(packet[IP].src, host_nat_ip)
3408 self.assertEqual(packet[IP].dst, server.ip4)
3409 self.assertEqual(packet.haslayer(GRE), 1)
3410 self.assert_packet_checksums_valid(packet)
3412 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3416 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3417 IP(src=server.ip4, dst=host_nat_ip) /
3419 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3420 TCP(sport=1234, dport=1234))
3421 self.pg0.add_stream(p)
3422 self.pg_enable_capture(self.pg_interfaces)
3424 p = self.pg0.get_capture(1)
3427 self.assertEqual(packet[IP].src, server_nat_ip)
3428 self.assertEqual(packet[IP].dst, host.ip4)
3429 self.assertEqual(packet.haslayer(GRE), 1)
3430 self.assert_packet_checksums_valid(packet)
3432 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3435 def test_output_feature(self):
3436 """ NAT44 interface output feature (in2out postrouting) """
3437 self.nat44_add_address(self.nat_addr)
3438 flags = self.config_flags.NAT_IS_INSIDE
3439 self.vapi.nat44_interface_add_del_output_feature(
3440 is_add=1, flags=flags,
3441 sw_if_index=self.pg0.sw_if_index)
3442 self.vapi.nat44_interface_add_del_output_feature(
3443 is_add=1, flags=flags,
3444 sw_if_index=self.pg1.sw_if_index)
3445 self.vapi.nat44_interface_add_del_output_feature(
3447 sw_if_index=self.pg3.sw_if_index)
3450 pkts = self.create_stream_in(self.pg0, self.pg3)
3451 self.pg0.add_stream(pkts)
3452 self.pg_enable_capture(self.pg_interfaces)
3454 capture = self.pg3.get_capture(len(pkts))
3455 self.verify_capture_out(capture)
3458 pkts = self.create_stream_out(self.pg3)
3459 self.pg3.add_stream(pkts)
3460 self.pg_enable_capture(self.pg_interfaces)
3462 capture = self.pg0.get_capture(len(pkts))
3463 self.verify_capture_in(capture, self.pg0)
3465 # from non-NAT interface to NAT inside interface
3466 pkts = self.create_stream_in(self.pg2, self.pg0)
3467 self.pg2.add_stream(pkts)
3468 self.pg_enable_capture(self.pg_interfaces)
3470 capture = self.pg0.get_capture(len(pkts))
3471 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3473 def test_output_feature_vrf_aware(self):
3474 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3475 nat_ip_vrf10 = "10.0.0.10"
3476 nat_ip_vrf20 = "10.0.0.20"
3478 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3479 dst_address_length=32,
3480 next_hop_address=self.pg3.remote_ip4n,
3481 next_hop_sw_if_index=self.pg3.sw_if_index,
3483 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3484 dst_address_length=32,
3485 next_hop_address=self.pg3.remote_ip4n,
3486 next_hop_sw_if_index=self.pg3.sw_if_index,
3489 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3490 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3491 flags = self.config_flags.NAT_IS_INSIDE
3492 self.vapi.nat44_interface_add_del_output_feature(
3493 is_add=1, flags=flags,
3494 sw_if_index=self.pg4.sw_if_index)
3495 self.vapi.nat44_interface_add_del_output_feature(
3496 is_add=1, flags=flags,
3497 sw_if_index=self.pg6.sw_if_index)
3498 self.vapi.nat44_interface_add_del_output_feature(
3500 sw_if_index=self.pg3.sw_if_index)
3503 pkts = self.create_stream_in(self.pg4, self.pg3)
3504 self.pg4.add_stream(pkts)
3505 self.pg_enable_capture(self.pg_interfaces)
3507 capture = self.pg3.get_capture(len(pkts))
3508 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3511 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3512 self.pg3.add_stream(pkts)
3513 self.pg_enable_capture(self.pg_interfaces)
3515 capture = self.pg4.get_capture(len(pkts))
3516 self.verify_capture_in(capture, self.pg4)
3519 pkts = self.create_stream_in(self.pg6, self.pg3)
3520 self.pg6.add_stream(pkts)
3521 self.pg_enable_capture(self.pg_interfaces)
3523 capture = self.pg3.get_capture(len(pkts))
3524 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3527 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3528 self.pg3.add_stream(pkts)
3529 self.pg_enable_capture(self.pg_interfaces)
3531 capture = self.pg6.get_capture(len(pkts))
3532 self.verify_capture_in(capture, self.pg6)
3534 def test_output_feature_hairpinning(self):
3535 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3536 host = self.pg0.remote_hosts[0]
3537 server = self.pg0.remote_hosts[1]
3540 server_in_port = 5678
3541 server_out_port = 8765
3543 self.nat44_add_address(self.nat_addr)
3544 flags = self.config_flags.NAT_IS_INSIDE
3545 self.vapi.nat44_interface_add_del_output_feature(
3546 is_add=1, flags=flags,
3547 sw_if_index=self.pg0.sw_if_index)
3548 self.vapi.nat44_interface_add_del_output_feature(
3550 sw_if_index=self.pg1.sw_if_index)
3552 # add static mapping for server
3553 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3554 server_in_port, server_out_port,
3555 proto=IP_PROTOS.tcp)
3557 # send packet from host to server
3558 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3559 IP(src=host.ip4, dst=self.nat_addr) /
3560 TCP(sport=host_in_port, dport=server_out_port))
3561 self.pg0.add_stream(p)
3562 self.pg_enable_capture(self.pg_interfaces)
3564 capture = self.pg0.get_capture(1)
3569 self.assertEqual(ip.src, self.nat_addr)
3570 self.assertEqual(ip.dst, server.ip4)
3571 self.assertNotEqual(tcp.sport, host_in_port)
3572 self.assertEqual(tcp.dport, server_in_port)
3573 self.assert_packet_checksums_valid(p)
3574 host_out_port = tcp.sport
3576 self.logger.error(ppp("Unexpected or invalid packet:", p))
3579 # send reply from server to host
3580 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3581 IP(src=server.ip4, dst=self.nat_addr) /
3582 TCP(sport=server_in_port, dport=host_out_port))
3583 self.pg0.add_stream(p)
3584 self.pg_enable_capture(self.pg_interfaces)
3586 capture = self.pg0.get_capture(1)
3591 self.assertEqual(ip.src, self.nat_addr)
3592 self.assertEqual(ip.dst, host.ip4)
3593 self.assertEqual(tcp.sport, server_out_port)
3594 self.assertEqual(tcp.dport, host_in_port)
3595 self.assert_packet_checksums_valid(p)
3597 self.logger.error(ppp("Unexpected or invalid packet:", p))
3600 def test_one_armed_nat44(self):
3601 """ One armed NAT44 """
3602 remote_host = self.pg9.remote_hosts[0]
3603 local_host = self.pg9.remote_hosts[1]
3606 self.nat44_add_address(self.nat_addr)
3607 flags = self.config_flags.NAT_IS_INSIDE
3608 self.vapi.nat44_interface_add_del_feature(
3609 sw_if_index=self.pg9.sw_if_index,
3611 self.vapi.nat44_interface_add_del_feature(
3612 sw_if_index=self.pg9.sw_if_index,
3613 flags=flags, is_add=1)
3616 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3617 IP(src=local_host.ip4, dst=remote_host.ip4) /
3618 TCP(sport=12345, dport=80))
3619 self.pg9.add_stream(p)
3620 self.pg_enable_capture(self.pg_interfaces)
3622 capture = self.pg9.get_capture(1)
3627 self.assertEqual(ip.src, self.nat_addr)
3628 self.assertEqual(ip.dst, remote_host.ip4)
3629 self.assertNotEqual(tcp.sport, 12345)
3630 external_port = tcp.sport
3631 self.assertEqual(tcp.dport, 80)
3632 self.assert_packet_checksums_valid(p)
3634 self.logger.error(ppp("Unexpected or invalid packet:", p))
3638 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3639 IP(src=remote_host.ip4, dst=self.nat_addr) /
3640 TCP(sport=80, dport=external_port))
3641 self.pg9.add_stream(p)
3642 self.pg_enable_capture(self.pg_interfaces)
3644 capture = self.pg9.get_capture(1)
3649 self.assertEqual(ip.src, remote_host.ip4)
3650 self.assertEqual(ip.dst, local_host.ip4)
3651 self.assertEqual(tcp.sport, 80)
3652 self.assertEqual(tcp.dport, 12345)
3653 self.assert_packet_checksums_valid(p)
3655 self.logger.error(ppp("Unexpected or invalid packet:", p))
3658 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3659 self.assertEqual(err, 1)
3660 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3661 self.assertEqual(err, 1)
3663 def test_del_session(self):
3664 """ Delete NAT44 session """
3665 self.nat44_add_address(self.nat_addr)
3666 flags = self.config_flags.NAT_IS_INSIDE
3667 self.vapi.nat44_interface_add_del_feature(
3668 sw_if_index=self.pg0.sw_if_index,
3669 flags=flags, is_add=1)
3670 self.vapi.nat44_interface_add_del_feature(
3671 sw_if_index=self.pg1.sw_if_index,
3674 pkts = self.create_stream_in(self.pg0, self.pg1)
3675 self.pg0.add_stream(pkts)
3676 self.pg_enable_capture(self.pg_interfaces)
3678 self.pg1.get_capture(len(pkts))
3680 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3681 nsessions = len(sessions)
3683 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3684 port=sessions[0].inside_port,
3685 protocol=sessions[0].protocol,
3686 flags=self.config_flags.NAT_IS_INSIDE)
3687 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3688 port=sessions[1].outside_port,
3689 protocol=sessions[1].protocol)
3691 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3692 self.assertEqual(nsessions - len(sessions), 2)
3694 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3695 port=sessions[0].inside_port,
3696 protocol=sessions[0].protocol,
3697 flags=self.config_flags.NAT_IS_INSIDE)
3699 self.verify_no_nat44_user()
3701 def test_set_get_reass(self):
3702 """ NAT44 set/get virtual fragmentation reassembly """
3703 reas_cfg1 = self.vapi.nat_get_reass()
3705 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3706 max_reass=reas_cfg1.ip4_max_reass * 2,
3707 max_frag=reas_cfg1.ip4_max_frag * 2,
3710 reas_cfg2 = self.vapi.nat_get_reass()
3712 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3713 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3714 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3716 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
3718 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3720 def test_frag_in_order(self):
3721 """ NAT44 translate fragments arriving in order """
3723 self.nat44_add_address(self.nat_addr)
3724 flags = self.config_flags.NAT_IS_INSIDE
3725 self.vapi.nat44_interface_add_del_feature(
3726 sw_if_index=self.pg0.sw_if_index,
3727 flags=flags, is_add=1)
3728 self.vapi.nat44_interface_add_del_feature(
3729 sw_if_index=self.pg1.sw_if_index,
3732 self.frag_in_order(proto=IP_PROTOS.tcp)
3733 self.frag_in_order(proto=IP_PROTOS.udp)
3734 self.frag_in_order(proto=IP_PROTOS.icmp)
3736 def test_frag_forwarding(self):
3737 """ NAT44 forwarding fragment test """
3738 self.vapi.nat44_add_del_interface_addr(
3740 sw_if_index=self.pg1.sw_if_index)
3741 flags = self.config_flags.NAT_IS_INSIDE
3742 self.vapi.nat44_interface_add_del_feature(
3743 sw_if_index=self.pg0.sw_if_index,
3744 flags=flags, is_add=1)
3745 self.vapi.nat44_interface_add_del_feature(
3746 sw_if_index=self.pg1.sw_if_index,
3748 self.vapi.nat44_forwarding_enable_disable(enable=1)
3750 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3751 pkts = self.create_stream_frag(self.pg1,
3752 self.pg0.remote_ip4,
3756 proto=IP_PROTOS.udp)
3757 self.pg1.add_stream(pkts)
3758 self.pg_enable_capture(self.pg_interfaces)
3760 frags = self.pg0.get_capture(len(pkts))
3761 p = self.reass_frags_and_verify(frags,
3762 self.pg1.remote_ip4,
3763 self.pg0.remote_ip4)
3764 self.assertEqual(p[UDP].sport, 4789)
3765 self.assertEqual(p[UDP].dport, 4789)
3766 self.assertEqual(data, p[Raw].load)
3768 def test_reass_hairpinning(self):
3769 """ NAT44 fragments hairpinning """
3771 self.server = self.pg0.remote_hosts[1]
3772 self.host_in_port = random.randint(1025, 65535)
3773 self.server_in_port = random.randint(1025, 65535)
3774 self.server_out_port = random.randint(1025, 65535)
3776 self.nat44_add_address(self.nat_addr)
3777 flags = self.config_flags.NAT_IS_INSIDE
3778 self.vapi.nat44_interface_add_del_feature(
3779 sw_if_index=self.pg0.sw_if_index,
3780 flags=flags, is_add=1)
3781 self.vapi.nat44_interface_add_del_feature(
3782 sw_if_index=self.pg1.sw_if_index,
3784 # add static mapping for server
3785 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3786 self.server_in_port,
3787 self.server_out_port,
3788 proto=IP_PROTOS.tcp)
3789 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3790 self.server_in_port,
3791 self.server_out_port,
3792 proto=IP_PROTOS.udp)
3793 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3795 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3796 self.reass_hairpinning(proto=IP_PROTOS.udp)
3797 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3799 def test_frag_out_of_order(self):
3800 """ NAT44 translate fragments arriving out of order """
3802 self.nat44_add_address(self.nat_addr)
3803 flags = self.config_flags.NAT_IS_INSIDE
3804 self.vapi.nat44_interface_add_del_feature(
3805 sw_if_index=self.pg0.sw_if_index,
3806 flags=flags, is_add=1)
3807 self.vapi.nat44_interface_add_del_feature(
3808 sw_if_index=self.pg1.sw_if_index,
3811 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3812 self.frag_out_of_order(proto=IP_PROTOS.udp)
3813 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3815 def test_port_restricted(self):
3816 """ Port restricted NAT44 (MAP-E CE) """
3817 self.nat44_add_address(self.nat_addr)
3818 flags = self.config_flags.NAT_IS_INSIDE
3819 self.vapi.nat44_interface_add_del_feature(
3820 sw_if_index=self.pg0.sw_if_index,
3821 flags=flags, is_add=1)
3822 self.vapi.nat44_interface_add_del_feature(
3823 sw_if_index=self.pg1.sw_if_index,
3825 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3830 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3831 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3832 TCP(sport=4567, dport=22))
3833 self.pg0.add_stream(p)
3834 self.pg_enable_capture(self.pg_interfaces)
3836 capture = self.pg1.get_capture(1)
3841 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3842 self.assertEqual(ip.src, self.nat_addr)
3843 self.assertEqual(tcp.dport, 22)
3844 self.assertNotEqual(tcp.sport, 4567)
3845 self.assertEqual((tcp.sport >> 6) & 63, 10)
3846 self.assert_packet_checksums_valid(p)
3848 self.logger.error(ppp("Unexpected or invalid packet:", p))
3851 def test_port_range(self):
3852 """ External address port range """
3853 self.nat44_add_address(self.nat_addr)
3854 flags = self.config_flags.NAT_IS_INSIDE
3855 self.vapi.nat44_interface_add_del_feature(
3856 sw_if_index=self.pg0.sw_if_index,
3857 flags=flags, is_add=1)
3858 self.vapi.nat44_interface_add_del_feature(
3859 sw_if_index=self.pg1.sw_if_index,
3861 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3866 for port in range(0, 5):
3867 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3868 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3869 TCP(sport=1125 + port))
3871 self.pg0.add_stream(pkts)
3872 self.pg_enable_capture(self.pg_interfaces)
3874 capture = self.pg1.get_capture(3)
3877 self.assertGreaterEqual(tcp.sport, 1025)
3878 self.assertLessEqual(tcp.sport, 1027)
3880 def test_ipfix_max_frags(self):
3881 """ IPFIX logging maximum fragments pending reassembly exceeded """
3882 self.nat44_add_address(self.nat_addr)
3883 flags = self.config_flags.NAT_IS_INSIDE
3884 self.vapi.nat44_interface_add_del_feature(
3885 sw_if_index=self.pg0.sw_if_index,
3886 flags=flags, is_add=1)
3887 self.vapi.nat44_interface_add_del_feature(
3888 sw_if_index=self.pg1.sw_if_index,
3890 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
3892 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3893 src_address=self.pg3.local_ip4n,
3895 template_interval=10)
3896 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3897 src_port=self.ipfix_src_port,
3900 data = b"A" * 4 + b"B" * 16 + b"C" * 3
3901 self.tcp_port_in = random.randint(1025, 65535)
3902 pkts = self.create_stream_frag(self.pg0,
3903 self.pg1.remote_ip4,
3908 self.pg0.add_stream(pkts)
3909 self.pg_enable_capture(self.pg_interfaces)
3911 self.pg1.assert_nothing_captured()
3913 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3914 capture = self.pg3.get_capture(9)
3915 ipfix = IPFIXDecoder()
3916 # first load template
3918 self.assertTrue(p.haslayer(IPFIX))
3919 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3920 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3921 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3922 self.assertEqual(p[UDP].dport, 4739)
3923 self.assertEqual(p[IPFIX].observationDomainID,
3924 self.ipfix_domain_id)
3925 if p.haslayer(Template):
3926 ipfix.add_template(p.getlayer(Template))
3927 # verify events in data set
3929 if p.haslayer(Data):
3930 data = ipfix.decode_data_set(p.getlayer(Set))
3931 self.verify_ipfix_max_fragments_ip4(data, 1,
3932 self.pg0.remote_ip4n)
3934 def test_multiple_outside_vrf(self):
3935 """ Multiple outside VRF """
3939 self.pg1.unconfig_ip4()
3940 self.pg2.unconfig_ip4()
3941 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3942 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
3943 self.pg1.set_table_ip4(vrf_id1)
3944 self.pg2.set_table_ip4(vrf_id2)
3945 self.pg1.config_ip4()
3946 self.pg2.config_ip4()
3947 self.pg1.resolve_arp()
3948 self.pg2.resolve_arp()
3950 self.nat44_add_address(self.nat_addr)
3951 flags = self.config_flags.NAT_IS_INSIDE
3952 self.vapi.nat44_interface_add_del_feature(
3953 sw_if_index=self.pg0.sw_if_index,
3954 flags=flags, is_add=1)
3955 self.vapi.nat44_interface_add_del_feature(
3956 sw_if_index=self.pg1.sw_if_index,
3958 self.vapi.nat44_interface_add_del_feature(
3959 sw_if_index=self.pg2.sw_if_index,
3964 pkts = self.create_stream_in(self.pg0, self.pg1)
3965 self.pg0.add_stream(pkts)
3966 self.pg_enable_capture(self.pg_interfaces)
3968 capture = self.pg1.get_capture(len(pkts))
3969 self.verify_capture_out(capture, self.nat_addr)
3971 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3972 self.pg1.add_stream(pkts)
3973 self.pg_enable_capture(self.pg_interfaces)
3975 capture = self.pg0.get_capture(len(pkts))
3976 self.verify_capture_in(capture, self.pg0)
3978 self.tcp_port_in = 60303
3979 self.udp_port_in = 60304
3980 self.icmp_id_in = 60305
3983 pkts = self.create_stream_in(self.pg0, self.pg2)
3984 self.pg0.add_stream(pkts)
3985 self.pg_enable_capture(self.pg_interfaces)
3987 capture = self.pg2.get_capture(len(pkts))
3988 self.verify_capture_out(capture, self.nat_addr)
3990 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3991 self.pg2.add_stream(pkts)
3992 self.pg_enable_capture(self.pg_interfaces)
3994 capture = self.pg0.get_capture(len(pkts))
3995 self.verify_capture_in(capture, self.pg0)
3998 self.nat44_add_address(self.nat_addr, is_add=0)
3999 self.pg1.unconfig_ip4()
4000 self.pg2.unconfig_ip4()
4001 self.pg1.set_table_ip4(0)
4002 self.pg2.set_table_ip4(0)
4003 self.pg1.config_ip4()
4004 self.pg2.config_ip4()
4005 self.pg1.resolve_arp()
4006 self.pg2.resolve_arp()
4008 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4009 def test_session_timeout(self):
4010 """ NAT44 session timeouts """
4011 self.nat44_add_address(self.nat_addr)
4012 flags = self.config_flags.NAT_IS_INSIDE
4013 self.vapi.nat44_interface_add_del_feature(
4014 sw_if_index=self.pg0.sw_if_index,
4015 flags=flags, is_add=1)
4016 self.vapi.nat44_interface_add_del_feature(
4017 sw_if_index=self.pg1.sw_if_index,
4019 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
4020 tcp_transitory=240, icmp=60)
4024 for i in range(0, max_sessions):
4025 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
4026 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4027 IP(src=src, dst=self.pg1.remote_ip4) /
4028 UDP(sport=1025, dport=53))
4030 self.pg0.add_stream(pkts)
4031 self.pg_enable_capture(self.pg_interfaces)
4033 self.pg1.get_capture(max_sessions)
4038 for i in range(0, max_sessions):
4039 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
4040 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4041 IP(src=src, dst=self.pg1.remote_ip4) /
4042 UDP(sport=1026, dport=53))
4044 self.pg0.add_stream(pkts)
4045 self.pg_enable_capture(self.pg_interfaces)
4047 self.pg1.get_capture(max_sessions)
4050 users = self.vapi.nat44_user_dump()
4052 nsessions = nsessions + user.nsessions
4053 self.assertLess(nsessions, 2 * max_sessions)
4055 def test_mss_clamping(self):
4056 """ TCP MSS clamping """
4057 self.nat44_add_address(self.nat_addr)
4058 flags = self.config_flags.NAT_IS_INSIDE
4059 self.vapi.nat44_interface_add_del_feature(
4060 sw_if_index=self.pg0.sw_if_index,
4061 flags=flags, is_add=1)
4062 self.vapi.nat44_interface_add_del_feature(
4063 sw_if_index=self.pg1.sw_if_index,
4066 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4067 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4068 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4069 flags="S", options=[('MSS', 1400)]))
4071 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
4072 self.pg0.add_stream(p)
4073 self.pg_enable_capture(self.pg_interfaces)
4075 capture = self.pg1.get_capture(1)
4076 # Negotiated MSS value greater than configured - changed
4077 self.verify_mss_value(capture[0], 1000)
4079 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
4080 self.pg0.add_stream(p)
4081 self.pg_enable_capture(self.pg_interfaces)
4083 capture = self.pg1.get_capture(1)
4084 # MSS clamping disabled - negotiated MSS unchanged
4085 self.verify_mss_value(capture[0], 1400)
4087 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
4088 self.pg0.add_stream(p)
4089 self.pg_enable_capture(self.pg_interfaces)
4091 capture = self.pg1.get_capture(1)
4092 # Negotiated MSS value smaller than configured - unchanged
4093 self.verify_mss_value(capture[0], 1400)
4095 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4096 def test_ha_send(self):
4097 """ Send HA session synchronization events (active) """
4098 self.nat44_add_address(self.nat_addr)
4099 flags = self.config_flags.NAT_IS_INSIDE
4100 self.vapi.nat44_interface_add_del_feature(
4101 sw_if_index=self.pg0.sw_if_index,
4102 flags=flags, is_add=1)
4103 self.vapi.nat44_interface_add_del_feature(
4104 sw_if_index=self.pg1.sw_if_index,
4106 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4109 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
4110 port=12346, session_refresh_interval=10)
4111 bind_layers(UDP, HANATStateSync, sport=12345)
4114 pkts = self.create_stream_in(self.pg0, self.pg1)
4115 self.pg0.add_stream(pkts)
4116 self.pg_enable_capture(self.pg_interfaces)
4118 capture = self.pg1.get_capture(len(pkts))
4119 self.verify_capture_out(capture)
4120 # active send HA events
4121 self.vapi.nat_ha_flush()
4122 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
4123 self.assertEqual(stats[0][0], 3)
4124 capture = self.pg3.get_capture(1)
4126 self.assert_packet_checksums_valid(p)
4130 hanat = p[HANATStateSync]
4132 self.logger.error(ppp("Invalid packet:", p))
4135 self.assertEqual(ip.src, self.pg3.local_ip4)
4136 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4137 self.assertEqual(udp.sport, 12345)
4138 self.assertEqual(udp.dport, 12346)
4139 self.assertEqual(hanat.version, 1)
4140 self.assertEqual(hanat.thread_index, 0)
4141 self.assertEqual(hanat.count, 3)
4142 seq = hanat.sequence_number
4143 for event in hanat.events:
4144 self.assertEqual(event.event_type, 1)
4145 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
4146 self.assertEqual(event.out_addr, self.nat_addr)
4147 self.assertEqual(event.fib_index, 0)
4149 # ACK received events
4150 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4151 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4152 UDP(sport=12346, dport=12345) /
4153 HANATStateSync(sequence_number=seq, flags='ACK'))
4154 self.pg3.add_stream(ack)
4156 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4157 self.assertEqual(stats[0][0], 1)
4159 # delete one session
4160 self.pg_enable_capture(self.pg_interfaces)
4161 self.vapi.nat44_del_session(address=self.pg0.remote_ip4n,
4162 port=self.tcp_port_in,
4163 protocol=IP_PROTOS.tcp,
4164 flags=self.config_flags.NAT_IS_INSIDE)
4165 self.vapi.nat_ha_flush()
4166 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
4167 self.assertEqual(stats[0][0], 1)
4168 capture = self.pg3.get_capture(1)
4171 hanat = p[HANATStateSync]
4173 self.logger.error(ppp("Invalid packet:", p))
4176 self.assertGreater(hanat.sequence_number, seq)
4178 # do not send ACK, active retry send HA event again
4179 self.pg_enable_capture(self.pg_interfaces)
4181 stats = self.statistics.get_counter('/nat44/ha/retry-count')
4182 self.assertEqual(stats[0][0], 3)
4183 stats = self.statistics.get_counter('/nat44/ha/missed-count')
4184 self.assertEqual(stats[0][0], 1)
4185 capture = self.pg3.get_capture(3)
4186 for packet in capture:
4187 self.assertEqual(packet, p)
4189 # session counters refresh
4190 pkts = self.create_stream_out(self.pg1)
4191 self.pg1.add_stream(pkts)
4192 self.pg_enable_capture(self.pg_interfaces)
4194 self.pg0.get_capture(2)
4195 self.vapi.nat_ha_flush()
4196 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
4197 self.assertEqual(stats[0][0], 2)
4198 capture = self.pg3.get_capture(1)
4200 self.assert_packet_checksums_valid(p)
4204 hanat = p[HANATStateSync]
4206 self.logger.error(ppp("Invalid packet:", p))
4209 self.assertEqual(ip.src, self.pg3.local_ip4)
4210 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4211 self.assertEqual(udp.sport, 12345)
4212 self.assertEqual(udp.dport, 12346)
4213 self.assertEqual(hanat.version, 1)
4214 self.assertEqual(hanat.count, 2)
4215 seq = hanat.sequence_number
4216 for event in hanat.events:
4217 self.assertEqual(event.event_type, 3)
4218 self.assertEqual(event.out_addr, self.nat_addr)
4219 self.assertEqual(event.fib_index, 0)
4220 self.assertEqual(event.total_pkts, 2)
4221 self.assertGreater(event.total_bytes, 0)
4223 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4224 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4225 UDP(sport=12346, dport=12345) /
4226 HANATStateSync(sequence_number=seq, flags='ACK'))
4227 self.pg3.add_stream(ack)
4229 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4230 self.assertEqual(stats[0][0], 2)
4232 def test_ha_recv(self):
4233 """ Receive HA session synchronization events (passive) """
4234 self.nat44_add_address(self.nat_addr)
4235 flags = self.config_flags.NAT_IS_INSIDE
4236 self.vapi.nat44_interface_add_del_feature(
4237 sw_if_index=self.pg0.sw_if_index,
4238 flags=flags, is_add=1)
4239 self.vapi.nat44_interface_add_del_feature(
4240 sw_if_index=self.pg1.sw_if_index,
4242 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4245 bind_layers(UDP, HANATStateSync, sport=12345)
4247 self.tcp_port_out = random.randint(1025, 65535)
4248 self.udp_port_out = random.randint(1025, 65535)
4250 # send HA session add events to failover/passive
4251 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4252 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4253 UDP(sport=12346, dport=12345) /
4254 HANATStateSync(sequence_number=1, events=[
4255 Event(event_type='add', protocol='tcp',
4256 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4257 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4258 eh_addr=self.pg1.remote_ip4,
4259 ehn_addr=self.pg1.remote_ip4,
4260 eh_port=self.tcp_external_port,
4261 ehn_port=self.tcp_external_port, fib_index=0),
4262 Event(event_type='add', protocol='udp',
4263 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4264 in_port=self.udp_port_in, out_port=self.udp_port_out,
4265 eh_addr=self.pg1.remote_ip4,
4266 ehn_addr=self.pg1.remote_ip4,
4267 eh_port=self.udp_external_port,
4268 ehn_port=self.udp_external_port, fib_index=0)]))
4270 self.pg3.add_stream(p)
4271 self.pg_enable_capture(self.pg_interfaces)
4274 capture = self.pg3.get_capture(1)
4277 hanat = p[HANATStateSync]
4279 self.logger.error(ppp("Invalid packet:", p))
4282 self.assertEqual(hanat.sequence_number, 1)
4283 self.assertEqual(hanat.flags, 'ACK')
4284 self.assertEqual(hanat.version, 1)
4285 self.assertEqual(hanat.thread_index, 0)
4286 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4287 self.assertEqual(stats[0][0], 1)
4288 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4289 self.assertEqual(stats[0][0], 2)
4290 users = self.statistics.get_counter('/nat44/total-users')
4291 self.assertEqual(users[0][0], 1)
4292 sessions = self.statistics.get_counter('/nat44/total-sessions')
4293 self.assertEqual(sessions[0][0], 2)
4294 users = self.vapi.nat44_user_dump()
4295 self.assertEqual(len(users), 1)
4296 self.assertEqual(str(users[0].ip_address),
4297 self.pg0.remote_ip4)
4298 # there should be 2 sessions created by HA
4299 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4301 self.assertEqual(len(sessions), 2)
4302 for session in sessions:
4303 self.assertEqual(str(session.inside_ip_address),
4304 self.pg0.remote_ip4)
4305 self.assertEqual(str(session.outside_ip_address),
4307 self.assertIn(session.inside_port,
4308 [self.tcp_port_in, self.udp_port_in])
4309 self.assertIn(session.outside_port,
4310 [self.tcp_port_out, self.udp_port_out])
4311 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4313 # send HA session delete event to failover/passive
4314 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4315 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4316 UDP(sport=12346, dport=12345) /
4317 HANATStateSync(sequence_number=2, events=[
4318 Event(event_type='del', protocol='udp',
4319 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4320 in_port=self.udp_port_in, out_port=self.udp_port_out,
4321 eh_addr=self.pg1.remote_ip4,
4322 ehn_addr=self.pg1.remote_ip4,
4323 eh_port=self.udp_external_port,
4324 ehn_port=self.udp_external_port, fib_index=0)]))
4326 self.pg3.add_stream(p)
4327 self.pg_enable_capture(self.pg_interfaces)
4330 capture = self.pg3.get_capture(1)
4333 hanat = p[HANATStateSync]
4335 self.logger.error(ppp("Invalid packet:", p))
4338 self.assertEqual(hanat.sequence_number, 2)
4339 self.assertEqual(hanat.flags, 'ACK')
4340 self.assertEqual(hanat.version, 1)
4341 users = self.vapi.nat44_user_dump()
4342 self.assertEqual(len(users), 1)
4343 self.assertEqual(str(users[0].ip_address),
4344 self.pg0.remote_ip4)
4345 # now we should have only 1 session, 1 deleted by HA
4346 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4348 self.assertEqual(len(sessions), 1)
4349 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4350 self.assertEqual(stats[0][0], 1)
4352 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4353 self.assertEqual(stats, 2)
4355 # send HA session refresh event to failover/passive
4356 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4357 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4358 UDP(sport=12346, dport=12345) /
4359 HANATStateSync(sequence_number=3, events=[
4360 Event(event_type='refresh', protocol='tcp',
4361 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4362 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4363 eh_addr=self.pg1.remote_ip4,
4364 ehn_addr=self.pg1.remote_ip4,
4365 eh_port=self.tcp_external_port,
4366 ehn_port=self.tcp_external_port, fib_index=0,
4367 total_bytes=1024, total_pkts=2)]))
4368 self.pg3.add_stream(p)
4369 self.pg_enable_capture(self.pg_interfaces)
4372 capture = self.pg3.get_capture(1)
4375 hanat = p[HANATStateSync]
4377 self.logger.error(ppp("Invalid packet:", p))
4380 self.assertEqual(hanat.sequence_number, 3)
4381 self.assertEqual(hanat.flags, 'ACK')
4382 self.assertEqual(hanat.version, 1)
4383 users = self.vapi.nat44_user_dump()
4384 self.assertEqual(len(users), 1)
4385 self.assertEqual(str(users[0].ip_address),
4386 self.pg0.remote_ip4)
4387 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4389 self.assertEqual(len(sessions), 1)
4390 session = sessions[0]
4391 self.assertEqual(session.total_bytes, 1024)
4392 self.assertEqual(session.total_pkts, 2)
4393 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4394 self.assertEqual(stats[0][0], 1)
4396 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4397 self.assertEqual(stats, 3)
4399 # send packet to test session created by HA
4400 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4401 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4402 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4403 self.pg1.add_stream(p)
4404 self.pg_enable_capture(self.pg_interfaces)
4406 capture = self.pg0.get_capture(1)
4412 self.logger.error(ppp("Invalid packet:", p))
4415 self.assertEqual(ip.src, self.pg1.remote_ip4)
4416 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4417 self.assertEqual(tcp.sport, self.tcp_external_port)
4418 self.assertEqual(tcp.dport, self.tcp_port_in)
4421 super(TestNAT44, self).tearDown()
4423 self.vapi.cli("clear logging")
4425 def show_commands_at_teardown(self):
4426 self.logger.info(self.vapi.cli("show nat44 addresses"))
4427 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4428 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4429 self.logger.info(self.vapi.cli("show nat44 interface address"))
4430 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4431 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4432 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4433 self.logger.info(self.vapi.cli("show nat timeouts"))
4435 self.vapi.cli("show nat addr-port-assignment-alg"))
4436 self.logger.info(self.vapi.cli("show nat ha"))
4439 class TestNAT44EndpointDependent(MethodHolder):
4440 """ Endpoint-Dependent mapping and filtering test cases """
4443 def setUpConstants(cls):
4444 super(TestNAT44EndpointDependent, cls).setUpConstants()
4445 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4448 def setUpClass(cls):
4449 super(TestNAT44EndpointDependent, cls).setUpClass()
4450 cls.vapi.cli("set log class nat level debug")
4452 cls.tcp_port_in = 6303
4453 cls.tcp_port_out = 6303
4454 cls.udp_port_in = 6304
4455 cls.udp_port_out = 6304
4456 cls.icmp_id_in = 6305
4457 cls.icmp_id_out = 6305
4458 cls.nat_addr = '10.0.0.3'
4459 cls.ipfix_src_port = 4739
4460 cls.ipfix_domain_id = 1
4461 cls.tcp_external_port = 80
4463 cls.create_pg_interfaces(range(7))
4464 cls.interfaces = list(cls.pg_interfaces[0:3])
4466 for i in cls.interfaces:
4471 cls.pg0.generate_remote_hosts(3)
4472 cls.pg0.configure_ipv4_neighbors()
4476 cls.pg4.generate_remote_hosts(2)
4477 cls.pg4.config_ip4()
4478 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
4479 cls.vapi.sw_interface_add_del_address(
4480 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4483 cls.pg4.resolve_arp()
4484 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4485 cls.pg4.resolve_arp()
4487 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4488 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
4490 cls.pg5._local_ip4 = "10.1.1.1"
4491 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4493 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4494 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4495 socket.AF_INET, cls.pg5.remote_ip4)
4496 cls.pg5.set_table_ip4(1)
4497 cls.pg5.config_ip4()
4499 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4500 dst_address_length=32,
4501 next_hop_address=zero_ip4n,
4502 next_hop_sw_if_index=cls.pg5.sw_if_index,
4505 cls.pg6._local_ip4 = "10.1.2.1"
4506 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4508 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4509 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4510 socket.AF_INET, cls.pg6.remote_ip4)
4511 cls.pg6.set_table_ip4(1)
4512 cls.pg6.config_ip4()
4514 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4515 dst_address_length=32,
4516 next_hop_address=zero_ip4n,
4517 next_hop_sw_if_index=cls.pg6.sw_if_index,
4520 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4521 dst_address_length=16,
4522 next_hop_address=zero_ip4n, table_id=0,
4523 next_hop_table_id=1)
4524 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4525 dst_address_length=0,
4526 next_hop_address=zero_ip4n, table_id=1,
4527 next_hop_table_id=0)
4528 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4529 dst_address_length=0,
4530 next_hop_address=cls.pg1.local_ip4n,
4531 next_hop_sw_if_index=cls.pg1.sw_if_index,
4534 cls.pg5.resolve_arp()
4535 cls.pg6.resolve_arp()
4538 super(TestNAT44EndpointDependent, cls).tearDownClass()
4542 def tearDownClass(cls):
4543 super(TestNAT44EndpointDependent, cls).tearDownClass()
4545 def test_frag_in_order(self):
4546 """ NAT44 translate fragments arriving in order """
4547 self.nat44_add_address(self.nat_addr)
4548 flags = self.config_flags.NAT_IS_INSIDE
4549 self.vapi.nat44_interface_add_del_feature(
4550 sw_if_index=self.pg0.sw_if_index,
4551 flags=flags, is_add=1)
4552 self.vapi.nat44_interface_add_del_feature(
4553 sw_if_index=self.pg1.sw_if_index,
4555 self.frag_in_order(proto=IP_PROTOS.tcp)
4556 self.frag_in_order(proto=IP_PROTOS.udp)
4557 self.frag_in_order(proto=IP_PROTOS.icmp)
4559 def test_frag_in_order_dont_translate(self):
4560 """ NAT44 don't translate fragments arriving in order """
4561 flags = self.config_flags.NAT_IS_INSIDE
4562 self.vapi.nat44_interface_add_del_feature(
4563 sw_if_index=self.pg0.sw_if_index,
4564 flags=flags, is_add=1)
4565 self.vapi.nat44_interface_add_del_feature(
4566 sw_if_index=self.pg1.sw_if_index,
4568 self.vapi.nat44_forwarding_enable_disable(enable=True)
4569 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4571 def test_frag_out_of_order(self):
4572 """ NAT44 translate fragments arriving out of order """
4573 self.nat44_add_address(self.nat_addr)
4574 flags = self.config_flags.NAT_IS_INSIDE
4575 self.vapi.nat44_interface_add_del_feature(
4576 sw_if_index=self.pg0.sw_if_index,
4577 flags=flags, is_add=1)
4578 self.vapi.nat44_interface_add_del_feature(
4579 sw_if_index=self.pg1.sw_if_index,
4581 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4582 self.frag_out_of_order(proto=IP_PROTOS.udp)
4583 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4585 def test_frag_out_of_order_dont_translate(self):
4586 """ NAT44 don't translate fragments arriving out of order """
4587 flags = self.config_flags.NAT_IS_INSIDE
4588 self.vapi.nat44_interface_add_del_feature(
4589 sw_if_index=self.pg0.sw_if_index,
4590 flags=flags, is_add=1)
4591 self.vapi.nat44_interface_add_del_feature(
4592 sw_if_index=self.pg1.sw_if_index,
4594 self.vapi.nat44_forwarding_enable_disable(enable=True)
4595 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4597 def test_frag_in_order_in_plus_out(self):
4598 """ in+out interface fragments in order """
4599 flags = self.config_flags.NAT_IS_INSIDE
4600 self.vapi.nat44_interface_add_del_feature(
4601 sw_if_index=self.pg0.sw_if_index,
4603 self.vapi.nat44_interface_add_del_feature(
4604 sw_if_index=self.pg0.sw_if_index,
4605 flags=flags, is_add=1)
4606 self.vapi.nat44_interface_add_del_feature(
4607 sw_if_index=self.pg1.sw_if_index,
4609 self.vapi.nat44_interface_add_del_feature(
4610 sw_if_index=self.pg1.sw_if_index,
4611 flags=flags, is_add=1)
4613 self.server = self.pg1.remote_hosts[0]
4615 self.server_in_addr = self.server.ip4
4616 self.server_out_addr = '11.11.11.11'
4617 self.server_in_port = random.randint(1025, 65535)
4618 self.server_out_port = random.randint(1025, 65535)
4620 self.nat44_add_address(self.server_out_addr)
4622 # add static mappings for server
4623 self.nat44_add_static_mapping(self.server_in_addr,
4624 self.server_out_addr,
4625 self.server_in_port,
4626 self.server_out_port,
4627 proto=IP_PROTOS.tcp)
4628 self.nat44_add_static_mapping(self.server_in_addr,
4629 self.server_out_addr,
4630 self.server_in_port,
4631 self.server_out_port,
4632 proto=IP_PROTOS.udp)
4633 self.nat44_add_static_mapping(self.server_in_addr,
4634 self.server_out_addr,
4635 proto=IP_PROTOS.icmp)
4637 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4640 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4641 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4642 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4644 def test_frag_out_of_order_in_plus_out(self):
4645 """ in+out interface fragments out of order """
4646 flags = self.config_flags.NAT_IS_INSIDE
4647 self.vapi.nat44_interface_add_del_feature(
4648 sw_if_index=self.pg0.sw_if_index,
4650 self.vapi.nat44_interface_add_del_feature(
4651 sw_if_index=self.pg0.sw_if_index,
4652 flags=flags, is_add=1)
4653 self.vapi.nat44_interface_add_del_feature(
4654 sw_if_index=self.pg1.sw_if_index,
4656 self.vapi.nat44_interface_add_del_feature(
4657 sw_if_index=self.pg1.sw_if_index,
4658 flags=flags, is_add=1)
4660 self.server = self.pg1.remote_hosts[0]
4662 self.server_in_addr = self.server.ip4
4663 self.server_out_addr = '11.11.11.11'
4664 self.server_in_port = random.randint(1025, 65535)
4665 self.server_out_port = random.randint(1025, 65535)
4667 self.nat44_add_address(self.server_out_addr)
4669 # add static mappings for server
4670 self.nat44_add_static_mapping(self.server_in_addr,
4671 self.server_out_addr,
4672 self.server_in_port,
4673 self.server_out_port,
4674 proto=IP_PROTOS.tcp)
4675 self.nat44_add_static_mapping(self.server_in_addr,
4676 self.server_out_addr,
4677 self.server_in_port,
4678 self.server_out_port,
4679 proto=IP_PROTOS.udp)
4680 self.nat44_add_static_mapping(self.server_in_addr,
4681 self.server_out_addr,
4682 proto=IP_PROTOS.icmp)
4684 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4687 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4688 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4689 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4691 def test_reass_hairpinning(self):
4692 """ NAT44 fragments hairpinning """
4693 self.server = self.pg0.remote_hosts[1]
4694 self.host_in_port = random.randint(1025, 65535)
4695 self.server_in_port = random.randint(1025, 65535)
4696 self.server_out_port = random.randint(1025, 65535)
4698 self.nat44_add_address(self.nat_addr)
4699 flags = self.config_flags.NAT_IS_INSIDE
4700 self.vapi.nat44_interface_add_del_feature(
4701 sw_if_index=self.pg0.sw_if_index,
4702 flags=flags, is_add=1)
4703 self.vapi.nat44_interface_add_del_feature(
4704 sw_if_index=self.pg1.sw_if_index,
4706 # add static mapping for server
4707 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4708 self.server_in_port,
4709 self.server_out_port,
4710 proto=IP_PROTOS.tcp)
4711 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4712 self.server_in_port,
4713 self.server_out_port,
4714 proto=IP_PROTOS.udp)
4715 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4717 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4718 self.reass_hairpinning(proto=IP_PROTOS.udp)
4719 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4721 def test_dynamic(self):
4722 """ NAT44 dynamic translation test """
4724 self.nat44_add_address(self.nat_addr)
4725 flags = self.config_flags.NAT_IS_INSIDE
4726 self.vapi.nat44_interface_add_del_feature(
4727 sw_if_index=self.pg0.sw_if_index,
4728 flags=flags, is_add=1)
4729 self.vapi.nat44_interface_add_del_feature(
4730 sw_if_index=self.pg1.sw_if_index,
4733 nat_config = self.vapi.nat_show_config()
4734 self.assertEqual(1, nat_config.endpoint_dependent)
4737 tcpn = self.statistics.get_counter(
4738 '/err/nat44-ed-in2out-slowpath/TCP packets')
4739 udpn = self.statistics.get_counter(
4740 '/err/nat44-ed-in2out-slowpath/UDP packets')
4741 icmpn = self.statistics.get_counter(
4742 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4743 totaln = self.statistics.get_counter(
4744 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4746 pkts = self.create_stream_in(self.pg0, self.pg1)
4747 self.pg0.add_stream(pkts)
4748 self.pg_enable_capture(self.pg_interfaces)
4750 capture = self.pg1.get_capture(len(pkts))
4751 self.verify_capture_out(capture)
4753 err = self.statistics.get_counter(
4754 '/err/nat44-ed-in2out-slowpath/TCP packets')
4755 self.assertEqual(err - tcpn, 1)
4756 err = self.statistics.get_counter(
4757 '/err/nat44-ed-in2out-slowpath/UDP packets')
4758 self.assertEqual(err - udpn, 1)
4759 err = self.statistics.get_counter(
4760 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4761 self.assertEqual(err - icmpn, 1)
4762 err = self.statistics.get_counter(
4763 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4764 self.assertEqual(err - totaln, 3)
4767 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4768 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4769 icmpn = self.statistics.get_counter(
4770 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4771 totaln = self.statistics.get_counter(
4772 '/err/nat44-ed-out2in/good out2in packets processed')
4774 pkts = self.create_stream_out(self.pg1)
4775 self.pg1.add_stream(pkts)
4776 self.pg_enable_capture(self.pg_interfaces)
4778 capture = self.pg0.get_capture(len(pkts))
4779 self.verify_capture_in(capture, self.pg0)
4781 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4782 self.assertEqual(err - tcpn, 1)
4783 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4784 self.assertEqual(err - udpn, 1)
4785 err = self.statistics.get_counter(
4786 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4787 self.assertEqual(err - icmpn, 1)
4788 err = self.statistics.get_counter(
4789 '/err/nat44-ed-out2in/good out2in packets processed')
4790 self.assertEqual(err - totaln, 2)
4792 users = self.statistics.get_counter('/nat44/total-users')
4793 self.assertEqual(users[0][0], 1)
4794 sessions = self.statistics.get_counter('/nat44/total-sessions')
4795 self.assertEqual(sessions[0][0], 3)
4797 def test_forwarding(self):
4798 """ NAT44 forwarding test """
4800 flags = self.config_flags.NAT_IS_INSIDE
4801 self.vapi.nat44_interface_add_del_feature(
4802 sw_if_index=self.pg0.sw_if_index,
4803 flags=flags, is_add=1)
4804 self.vapi.nat44_interface_add_del_feature(
4805 sw_if_index=self.pg1.sw_if_index,
4807 self.vapi.nat44_forwarding_enable_disable(enable=1)
4809 real_ip = self.pg0.remote_ip4
4810 alias_ip = self.nat_addr
4811 flags = self.config_flags.NAT_IS_ADDR_ONLY
4812 self.vapi.nat44_add_del_static_mapping(is_add=1,
4813 local_ip_address=real_ip,
4814 external_ip_address=alias_ip,
4815 external_sw_if_index=0xFFFFFFFF,
4819 # in2out - static mapping match
4821 pkts = self.create_stream_out(self.pg1)
4822 self.pg1.add_stream(pkts)
4823 self.pg_enable_capture(self.pg_interfaces)
4825 capture = self.pg0.get_capture(len(pkts))
4826 self.verify_capture_in(capture, self.pg0)
4828 pkts = self.create_stream_in(self.pg0, self.pg1)
4829 self.pg0.add_stream(pkts)
4830 self.pg_enable_capture(self.pg_interfaces)
4832 capture = self.pg1.get_capture(len(pkts))
4833 self.verify_capture_out(capture, same_port=True)
4835 # in2out - no static mapping match
4837 host0 = self.pg0.remote_hosts[0]
4838 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4840 pkts = self.create_stream_out(self.pg1,
4841 dst_ip=self.pg0.remote_ip4,
4842 use_inside_ports=True)
4843 self.pg1.add_stream(pkts)
4844 self.pg_enable_capture(self.pg_interfaces)
4846 capture = self.pg0.get_capture(len(pkts))
4847 self.verify_capture_in(capture, self.pg0)
4849 pkts = self.create_stream_in(self.pg0, self.pg1)
4850 self.pg0.add_stream(pkts)
4851 self.pg_enable_capture(self.pg_interfaces)
4853 capture = self.pg1.get_capture(len(pkts))
4854 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4857 self.pg0.remote_hosts[0] = host0
4859 user = self.pg0.remote_hosts[1]
4860 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4861 self.assertEqual(len(sessions), 3)
4862 self.assertTrue(sessions[0].flags &
4863 self.config_flags.NAT_IS_EXT_HOST_VALID)
4864 self.vapi.nat44_del_session(
4865 address=sessions[0].inside_ip_address,
4866 port=sessions[0].inside_port,
4867 protocol=sessions[0].protocol,
4868 flags=(self.config_flags.NAT_IS_INSIDE |
4869 self.config_flags.NAT_IS_EXT_HOST_VALID),
4870 ext_host_address=sessions[0].ext_host_address,
4871 ext_host_port=sessions[0].ext_host_port)
4872 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4873 self.assertEqual(len(sessions), 2)
4876 self.vapi.nat44_forwarding_enable_disable(enable=0)
4877 flags = self.config_flags.NAT_IS_ADDR_ONLY
4878 self.vapi.nat44_add_del_static_mapping(
4880 local_ip_address=real_ip,
4881 external_ip_address=alias_ip,
4882 external_sw_if_index=0xFFFFFFFF,
4885 def test_static_lb(self):
4886 """ NAT44 local service load balancing """
4887 external_addr_n = self.nat_addr
4890 server1 = self.pg0.remote_hosts[0]
4891 server2 = self.pg0.remote_hosts[1]
4893 locals = [{'addr': server1.ip4n,
4897 {'addr': server2.ip4n,
4902 self.nat44_add_address(self.nat_addr)
4903 self.vapi.nat44_add_del_lb_static_mapping(
4905 external_addr=external_addr_n,
4906 external_port=external_port,
4907 protocol=IP_PROTOS.tcp,
4908 local_num=len(locals),
4910 flags = self.config_flags.NAT_IS_INSIDE
4911 self.vapi.nat44_interface_add_del_feature(
4912 sw_if_index=self.pg0.sw_if_index,
4913 flags=flags, is_add=1)
4914 self.vapi.nat44_interface_add_del_feature(
4915 sw_if_index=self.pg1.sw_if_index,
4918 # from client to service
4919 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4920 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4921 TCP(sport=12345, dport=external_port))
4922 self.pg1.add_stream(p)
4923 self.pg_enable_capture(self.pg_interfaces)
4925 capture = self.pg0.get_capture(1)
4931 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4932 if ip.dst == server1.ip4:
4936 self.assertEqual(tcp.dport, local_port)
4937 self.assert_packet_checksums_valid(p)
4939 self.logger.error(ppp("Unexpected or invalid packet:", p))
4942 # from service back to client
4943 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4944 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4945 TCP(sport=local_port, dport=12345))
4946 self.pg0.add_stream(p)
4947 self.pg_enable_capture(self.pg_interfaces)
4949 capture = self.pg1.get_capture(1)
4954 self.assertEqual(ip.src, self.nat_addr)
4955 self.assertEqual(tcp.sport, external_port)
4956 self.assert_packet_checksums_valid(p)
4958 self.logger.error(ppp("Unexpected or invalid packet:", p))
4961 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4962 self.assertEqual(len(sessions), 1)
4963 self.assertTrue(sessions[0].flags &
4964 self.config_flags.NAT_IS_EXT_HOST_VALID)
4965 self.vapi.nat44_del_session(
4966 address=sessions[0].inside_ip_address,
4967 port=sessions[0].inside_port,
4968 protocol=sessions[0].protocol,
4969 flags=(self.config_flags.NAT_IS_INSIDE |
4970 self.config_flags.NAT_IS_EXT_HOST_VALID),
4971 ext_host_address=sessions[0].ext_host_address,
4972 ext_host_port=sessions[0].ext_host_port)
4973 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4974 self.assertEqual(len(sessions), 0)
4976 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4977 def test_static_lb_multi_clients(self):
4978 """ NAT44 local service load balancing - multiple clients"""
4980 external_addr = self.nat_addr
4983 server1 = self.pg0.remote_hosts[0]
4984 server2 = self.pg0.remote_hosts[1]
4985 server3 = self.pg0.remote_hosts[2]
4987 locals = [{'addr': server1.ip4n,
4991 {'addr': server2.ip4n,
4996 self.nat44_add_address(self.nat_addr)
4997 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4998 external_addr=external_addr,
4999 external_port=external_port,
5000 protocol=IP_PROTOS.tcp,
5001 local_num=len(locals),
5003 flags = self.config_flags.NAT_IS_INSIDE
5004 self.vapi.nat44_interface_add_del_feature(
5005 sw_if_index=self.pg0.sw_if_index,
5006 flags=flags, is_add=1)
5007 self.vapi.nat44_interface_add_del_feature(
5008 sw_if_index=self.pg1.sw_if_index,
5013 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
5015 for client in clients:
5016 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5017 IP(src=client, dst=self.nat_addr) /
5018 TCP(sport=12345, dport=external_port))
5020 self.pg1.add_stream(pkts)
5021 self.pg_enable_capture(self.pg_interfaces)
5023 capture = self.pg0.get_capture(len(pkts))
5025 if p[IP].dst == server1.ip4:
5029 self.assertGreater(server1_n, server2_n)
5032 'addr': server3.ip4n,
5039 self.vapi.nat44_lb_static_mapping_add_del_local(
5041 external_addr=external_addr,
5042 external_port=external_port,
5044 protocol=IP_PROTOS.tcp)
5048 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5050 for client in clients:
5051 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5052 IP(src=client, dst=self.nat_addr) /
5053 TCP(sport=12346, dport=external_port))
5055 self.assertGreater(len(pkts), 0)
5056 self.pg1.add_stream(pkts)
5057 self.pg_enable_capture(self.pg_interfaces)
5059 capture = self.pg0.get_capture(len(pkts))
5061 if p[IP].dst == server1.ip4:
5063 elif p[IP].dst == server2.ip4:
5067 self.assertGreater(server1_n, 0)
5068 self.assertGreater(server2_n, 0)
5069 self.assertGreater(server3_n, 0)
5072 'addr': server2.ip4n,
5078 # remove one back-end
5079 self.vapi.nat44_lb_static_mapping_add_del_local(
5081 external_addr=external_addr,
5082 external_port=external_port,
5084 protocol=IP_PROTOS.tcp)
5088 self.pg1.add_stream(pkts)
5089 self.pg_enable_capture(self.pg_interfaces)
5091 capture = self.pg0.get_capture(len(pkts))
5093 if p[IP].dst == server1.ip4:
5095 elif p[IP].dst == server2.ip4:
5099 self.assertGreater(server1_n, 0)
5100 self.assertEqual(server2_n, 0)
5101 self.assertGreater(server3_n, 0)
5103 def test_static_lb_2(self):
5104 """ NAT44 local service load balancing (asymmetrical rule) """
5105 external_addr = self.nat_addr
5108 server1 = self.pg0.remote_hosts[0]
5109 server2 = self.pg0.remote_hosts[1]
5111 locals = [{'addr': server1.ip4n,
5115 {'addr': server2.ip4n,
5120 self.vapi.nat44_forwarding_enable_disable(enable=1)
5121 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5122 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5123 external_addr=external_addr,
5124 external_port=external_port,
5125 protocol=IP_PROTOS.tcp,
5126 local_num=len(locals),
5128 flags = self.config_flags.NAT_IS_INSIDE
5129 self.vapi.nat44_interface_add_del_feature(
5130 sw_if_index=self.pg0.sw_if_index,
5131 flags=flags, is_add=1)
5132 self.vapi.nat44_interface_add_del_feature(
5133 sw_if_index=self.pg1.sw_if_index,
5136 # from client to service
5137 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5138 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5139 TCP(sport=12345, dport=external_port))
5140 self.pg1.add_stream(p)
5141 self.pg_enable_capture(self.pg_interfaces)
5143 capture = self.pg0.get_capture(1)
5149 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5150 if ip.dst == server1.ip4:
5154 self.assertEqual(tcp.dport, local_port)
5155 self.assert_packet_checksums_valid(p)
5157 self.logger.error(ppp("Unexpected or invalid packet:", p))
5160 # from service back to client
5161 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5162 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5163 TCP(sport=local_port, dport=12345))
5164 self.pg0.add_stream(p)
5165 self.pg_enable_capture(self.pg_interfaces)
5167 capture = self.pg1.get_capture(1)
5172 self.assertEqual(ip.src, self.nat_addr)
5173 self.assertEqual(tcp.sport, external_port)
5174 self.assert_packet_checksums_valid(p)
5176 self.logger.error(ppp("Unexpected or invalid packet:", p))
5179 # from client to server (no translation)
5180 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5181 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5182 TCP(sport=12346, dport=local_port))
5183 self.pg1.add_stream(p)
5184 self.pg_enable_capture(self.pg_interfaces)
5186 capture = self.pg0.get_capture(1)
5192 self.assertEqual(ip.dst, server1.ip4)
5193 self.assertEqual(tcp.dport, local_port)
5194 self.assert_packet_checksums_valid(p)
5196 self.logger.error(ppp("Unexpected or invalid packet:", p))
5199 # from service back to client (no translation)
5200 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5201 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5202 TCP(sport=local_port, dport=12346))
5203 self.pg0.add_stream(p)
5204 self.pg_enable_capture(self.pg_interfaces)
5206 capture = self.pg1.get_capture(1)
5211 self.assertEqual(ip.src, server1.ip4)
5212 self.assertEqual(tcp.sport, local_port)
5213 self.assert_packet_checksums_valid(p)
5215 self.logger.error(ppp("Unexpected or invalid packet:", p))
5218 def test_lb_affinity(self):
5219 """ NAT44 local service load balancing affinity """
5220 external_addr = self.nat_addr
5223 server1 = self.pg0.remote_hosts[0]
5224 server2 = self.pg0.remote_hosts[1]
5226 locals = [{'addr': server1.ip4n,
5230 {'addr': server2.ip4n,
5235 self.nat44_add_address(self.nat_addr)
5236 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5237 external_addr=external_addr,
5238 external_port=external_port,
5239 protocol=IP_PROTOS.tcp,
5241 local_num=len(locals),
5243 flags = self.config_flags.NAT_IS_INSIDE
5244 self.vapi.nat44_interface_add_del_feature(
5245 sw_if_index=self.pg0.sw_if_index,
5246 flags=flags, is_add=1)
5247 self.vapi.nat44_interface_add_del_feature(
5248 sw_if_index=self.pg1.sw_if_index,
5251 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5252 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5253 TCP(sport=1025, dport=external_port))
5254 self.pg1.add_stream(p)
5255 self.pg_enable_capture(self.pg_interfaces)
5257 capture = self.pg0.get_capture(1)
5258 backend = capture[0][IP].dst
5260 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5261 self.assertEqual(len(sessions), 1)
5262 self.assertTrue(sessions[0].flags &
5263 self.config_flags.NAT_IS_EXT_HOST_VALID)
5264 self.vapi.nat44_del_session(
5265 address=sessions[0].inside_ip_address,
5266 port=sessions[0].inside_port,
5267 protocol=sessions[0].protocol,
5268 flags=(self.config_flags.NAT_IS_INSIDE |
5269 self.config_flags.NAT_IS_EXT_HOST_VALID),
5270 ext_host_address=sessions[0].ext_host_address,
5271 ext_host_port=sessions[0].ext_host_port)
5274 for port in range(1030, 1100):
5275 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5276 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5277 TCP(sport=port, dport=external_port))
5279 self.pg1.add_stream(pkts)
5280 self.pg_enable_capture(self.pg_interfaces)
5282 capture = self.pg0.get_capture(len(pkts))
5284 self.assertEqual(p[IP].dst, backend)
5286 def test_unknown_proto(self):
5287 """ NAT44 translate packet with unknown protocol """
5288 self.nat44_add_address(self.nat_addr)
5289 flags = self.config_flags.NAT_IS_INSIDE
5290 self.vapi.nat44_interface_add_del_feature(
5291 sw_if_index=self.pg0.sw_if_index,
5292 flags=flags, is_add=1)
5293 self.vapi.nat44_interface_add_del_feature(
5294 sw_if_index=self.pg1.sw_if_index,
5298 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5299 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5300 TCP(sport=self.tcp_port_in, dport=20))
5301 self.pg0.add_stream(p)
5302 self.pg_enable_capture(self.pg_interfaces)
5304 p = self.pg1.get_capture(1)
5306 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5307 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5309 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5310 TCP(sport=1234, dport=1234))
5311 self.pg0.add_stream(p)
5312 self.pg_enable_capture(self.pg_interfaces)
5314 p = self.pg1.get_capture(1)
5317 self.assertEqual(packet[IP].src, self.nat_addr)
5318 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5319 self.assertEqual(packet.haslayer(GRE), 1)
5320 self.assert_packet_checksums_valid(packet)
5322 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5326 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5327 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5329 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5330 TCP(sport=1234, dport=1234))
5331 self.pg1.add_stream(p)
5332 self.pg_enable_capture(self.pg_interfaces)
5334 p = self.pg0.get_capture(1)
5337 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5338 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5339 self.assertEqual(packet.haslayer(GRE), 1)
5340 self.assert_packet_checksums_valid(packet)
5342 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5345 def test_hairpinning_unknown_proto(self):
5346 """ NAT44 translate packet with unknown protocol - hairpinning """
5347 host = self.pg0.remote_hosts[0]
5348 server = self.pg0.remote_hosts[1]
5350 server_out_port = 8765
5351 server_nat_ip = "10.0.0.11"
5353 self.nat44_add_address(self.nat_addr)
5354 flags = self.config_flags.NAT_IS_INSIDE
5355 self.vapi.nat44_interface_add_del_feature(
5356 sw_if_index=self.pg0.sw_if_index,
5357 flags=flags, is_add=1)
5358 self.vapi.nat44_interface_add_del_feature(
5359 sw_if_index=self.pg1.sw_if_index,
5362 # add static mapping for server
5363 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5366 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5367 IP(src=host.ip4, dst=server_nat_ip) /
5368 TCP(sport=host_in_port, dport=server_out_port))
5369 self.pg0.add_stream(p)
5370 self.pg_enable_capture(self.pg_interfaces)
5372 self.pg0.get_capture(1)
5374 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5375 IP(src=host.ip4, dst=server_nat_ip) /
5377 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5378 TCP(sport=1234, dport=1234))
5379 self.pg0.add_stream(p)
5380 self.pg_enable_capture(self.pg_interfaces)
5382 p = self.pg0.get_capture(1)
5385 self.assertEqual(packet[IP].src, self.nat_addr)
5386 self.assertEqual(packet[IP].dst, server.ip4)
5387 self.assertEqual(packet.haslayer(GRE), 1)
5388 self.assert_packet_checksums_valid(packet)
5390 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5394 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5395 IP(src=server.ip4, dst=self.nat_addr) /
5397 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5398 TCP(sport=1234, dport=1234))
5399 self.pg0.add_stream(p)
5400 self.pg_enable_capture(self.pg_interfaces)
5402 p = self.pg0.get_capture(1)
5405 self.assertEqual(packet[IP].src, server_nat_ip)
5406 self.assertEqual(packet[IP].dst, host.ip4)
5407 self.assertEqual(packet.haslayer(GRE), 1)
5408 self.assert_packet_checksums_valid(packet)
5410 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5413 def test_output_feature_and_service(self):
5414 """ NAT44 interface output feature and services """
5415 external_addr = '1.2.3.4'
5419 self.vapi.nat44_forwarding_enable_disable(enable=1)
5420 self.nat44_add_address(self.nat_addr)
5421 flags = self.config_flags.NAT_IS_ADDR_ONLY
5422 self.vapi.nat44_add_del_identity_mapping(
5423 ip_address=self.pg1.remote_ip4n, sw_if_index=0xFFFFFFFF,
5424 flags=flags, is_add=1)
5425 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5426 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5427 local_port, external_port,
5428 proto=IP_PROTOS.tcp, flags=flags)
5429 flags = self.config_flags.NAT_IS_INSIDE
5430 self.vapi.nat44_interface_add_del_feature(
5431 sw_if_index=self.pg0.sw_if_index,
5433 self.vapi.nat44_interface_add_del_feature(
5434 sw_if_index=self.pg0.sw_if_index,
5435 flags=flags, is_add=1)
5436 self.vapi.nat44_interface_add_del_output_feature(
5438 sw_if_index=self.pg1.sw_if_index)
5440 # from client to service
5441 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5442 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5443 TCP(sport=12345, dport=external_port))
5444 self.pg1.add_stream(p)
5445 self.pg_enable_capture(self.pg_interfaces)
5447 capture = self.pg0.get_capture(1)
5452 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5453 self.assertEqual(tcp.dport, local_port)
5454 self.assert_packet_checksums_valid(p)
5456 self.logger.error(ppp("Unexpected or invalid packet:", p))
5459 # from service back to client
5460 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5461 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5462 TCP(sport=local_port, dport=12345))
5463 self.pg0.add_stream(p)
5464 self.pg_enable_capture(self.pg_interfaces)
5466 capture = self.pg1.get_capture(1)
5471 self.assertEqual(ip.src, external_addr)
5472 self.assertEqual(tcp.sport, external_port)
5473 self.assert_packet_checksums_valid(p)
5475 self.logger.error(ppp("Unexpected or invalid packet:", p))
5478 # from local network host to external network
5479 pkts = self.create_stream_in(self.pg0, self.pg1)
5480 self.pg0.add_stream(pkts)
5481 self.pg_enable_capture(self.pg_interfaces)
5483 capture = self.pg1.get_capture(len(pkts))
5484 self.verify_capture_out(capture)
5485 pkts = self.create_stream_in(self.pg0, self.pg1)
5486 self.pg0.add_stream(pkts)
5487 self.pg_enable_capture(self.pg_interfaces)
5489 capture = self.pg1.get_capture(len(pkts))
5490 self.verify_capture_out(capture)
5492 # from external network back to local network host
5493 pkts = self.create_stream_out(self.pg1)
5494 self.pg1.add_stream(pkts)
5495 self.pg_enable_capture(self.pg_interfaces)
5497 capture = self.pg0.get_capture(len(pkts))
5498 self.verify_capture_in(capture, self.pg0)
5500 def test_output_feature_and_service2(self):
5501 """ NAT44 interface output feature and service host direct access """
5502 self.vapi.nat44_forwarding_enable_disable(enable=1)
5503 self.nat44_add_address(self.nat_addr)
5504 self.vapi.nat44_interface_add_del_output_feature(
5506 sw_if_index=self.pg1.sw_if_index)
5508 # session initiated from service host - translate
5509 pkts = self.create_stream_in(self.pg0, self.pg1)
5510 self.pg0.add_stream(pkts)
5511 self.pg_enable_capture(self.pg_interfaces)
5513 capture = self.pg1.get_capture(len(pkts))
5514 self.verify_capture_out(capture)
5516 pkts = self.create_stream_out(self.pg1)
5517 self.pg1.add_stream(pkts)
5518 self.pg_enable_capture(self.pg_interfaces)
5520 capture = self.pg0.get_capture(len(pkts))
5521 self.verify_capture_in(capture, self.pg0)
5523 # session initiated from remote host - do not translate
5524 self.tcp_port_in = 60303
5525 self.udp_port_in = 60304
5526 self.icmp_id_in = 60305
5527 pkts = self.create_stream_out(self.pg1,
5528 self.pg0.remote_ip4,
5529 use_inside_ports=True)
5530 self.pg1.add_stream(pkts)
5531 self.pg_enable_capture(self.pg_interfaces)
5533 capture = self.pg0.get_capture(len(pkts))
5534 self.verify_capture_in(capture, self.pg0)
5536 pkts = self.create_stream_in(self.pg0, self.pg1)
5537 self.pg0.add_stream(pkts)
5538 self.pg_enable_capture(self.pg_interfaces)
5540 capture = self.pg1.get_capture(len(pkts))
5541 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5544 def test_output_feature_and_service3(self):
5545 """ NAT44 interface output feature and DST NAT """
5546 external_addr = '1.2.3.4'
5550 self.vapi.nat44_forwarding_enable_disable(enable=1)
5551 self.nat44_add_address(self.nat_addr)
5552 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5553 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5554 local_port, external_port,
5555 proto=IP_PROTOS.tcp, flags=flags)
5556 flags = self.config_flags.NAT_IS_INSIDE
5557 self.vapi.nat44_interface_add_del_feature(
5558 sw_if_index=self.pg0.sw_if_index,
5560 self.vapi.nat44_interface_add_del_feature(
5561 sw_if_index=self.pg0.sw_if_index,
5562 flags=flags, is_add=1)
5563 self.vapi.nat44_interface_add_del_output_feature(
5565 sw_if_index=self.pg1.sw_if_index)
5567 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5568 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5569 TCP(sport=12345, dport=external_port))
5570 self.pg0.add_stream(p)
5571 self.pg_enable_capture(self.pg_interfaces)
5573 capture = self.pg1.get_capture(1)
5578 self.assertEqual(ip.src, self.pg0.remote_ip4)
5579 self.assertEqual(tcp.sport, 12345)
5580 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5581 self.assertEqual(tcp.dport, local_port)
5582 self.assert_packet_checksums_valid(p)
5584 self.logger.error(ppp("Unexpected or invalid packet:", p))
5587 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5588 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5589 TCP(sport=local_port, dport=12345))
5590 self.pg1.add_stream(p)
5591 self.pg_enable_capture(self.pg_interfaces)
5593 capture = self.pg0.get_capture(1)
5598 self.assertEqual(ip.src, external_addr)
5599 self.assertEqual(tcp.sport, external_port)
5600 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5601 self.assertEqual(tcp.dport, 12345)
5602 self.assert_packet_checksums_valid(p)
5604 self.logger.error(ppp("Unexpected or invalid packet:", p))
5607 def test_next_src_nat(self):
5608 """ On way back forward packet to nat44-in2out node. """
5609 twice_nat_addr = '10.0.1.3'
5612 post_twice_nat_port = 0
5614 self.vapi.nat44_forwarding_enable_disable(enable=1)
5615 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5616 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5617 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5618 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5619 local_port, external_port,
5620 proto=IP_PROTOS.tcp, vrf_id=1,
5622 self.vapi.nat44_interface_add_del_feature(
5623 sw_if_index=self.pg6.sw_if_index,
5626 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5627 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5628 TCP(sport=12345, dport=external_port))
5629 self.pg6.add_stream(p)
5630 self.pg_enable_capture(self.pg_interfaces)
5632 capture = self.pg6.get_capture(1)
5637 self.assertEqual(ip.src, twice_nat_addr)
5638 self.assertNotEqual(tcp.sport, 12345)
5639 post_twice_nat_port = tcp.sport
5640 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5641 self.assertEqual(tcp.dport, local_port)
5642 self.assert_packet_checksums_valid(p)
5644 self.logger.error(ppp("Unexpected or invalid packet:", p))
5647 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5648 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5649 TCP(sport=local_port, dport=post_twice_nat_port))
5650 self.pg6.add_stream(p)
5651 self.pg_enable_capture(self.pg_interfaces)
5653 capture = self.pg6.get_capture(1)
5658 self.assertEqual(ip.src, self.pg1.remote_ip4)
5659 self.assertEqual(tcp.sport, external_port)
5660 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5661 self.assertEqual(tcp.dport, 12345)
5662 self.assert_packet_checksums_valid(p)
5664 self.logger.error(ppp("Unexpected or invalid packet:", p))
5667 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5669 twice_nat_addr = '10.0.1.3'
5677 port_in1 = port_in + 1
5678 port_in2 = port_in + 2
5683 server1 = self.pg0.remote_hosts[0]
5684 server2 = self.pg0.remote_hosts[1]
5696 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5699 self.nat44_add_address(self.nat_addr)
5700 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5704 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5706 flags |= self.config_flags.NAT_IS_TWICE_NAT
5709 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5711 proto=IP_PROTOS.tcp,
5714 locals = [{'addr': server1.ip4n,
5718 {'addr': server2.ip4n,
5722 out_addr = self.nat_addr
5724 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5725 external_addr=out_addr,
5726 external_port=port_out,
5727 protocol=IP_PROTOS.tcp,
5728 local_num=len(locals),
5730 flags = self.config_flags.NAT_IS_INSIDE
5731 self.vapi.nat44_interface_add_del_feature(
5732 sw_if_index=pg0.sw_if_index,
5733 flags=flags, is_add=1)
5734 self.vapi.nat44_interface_add_del_feature(
5735 sw_if_index=pg1.sw_if_index,
5742 assert client_id is not None
5744 client = self.pg0.remote_hosts[0]
5745 elif client_id == 2:
5746 client = self.pg0.remote_hosts[1]
5748 client = pg1.remote_hosts[0]
5749 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5750 IP(src=client.ip4, dst=self.nat_addr) /
5751 TCP(sport=eh_port_out, dport=port_out))
5753 self.pg_enable_capture(self.pg_interfaces)
5755 capture = pg0.get_capture(1)
5761 if ip.dst == server1.ip4:
5767 self.assertEqual(ip.dst, server.ip4)
5769 self.assertIn(tcp.dport, [port_in1, port_in2])
5771 self.assertEqual(tcp.dport, port_in)
5773 self.assertEqual(ip.src, twice_nat_addr)
5774 self.assertNotEqual(tcp.sport, eh_port_out)
5776 self.assertEqual(ip.src, client.ip4)
5777 self.assertEqual(tcp.sport, eh_port_out)
5779 eh_port_in = tcp.sport
5780 saved_port_in = tcp.dport
5781 self.assert_packet_checksums_valid(p)
5783 self.logger.error(ppp("Unexpected or invalid packet:", p))
5786 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5787 IP(src=server.ip4, dst=eh_addr_in) /
5788 TCP(sport=saved_port_in, dport=eh_port_in))
5790 self.pg_enable_capture(self.pg_interfaces)
5792 capture = pg1.get_capture(1)
5797 self.assertEqual(ip.dst, client.ip4)
5798 self.assertEqual(ip.src, self.nat_addr)
5799 self.assertEqual(tcp.dport, eh_port_out)
5800 self.assertEqual(tcp.sport, port_out)
5801 self.assert_packet_checksums_valid(p)
5803 self.logger.error(ppp("Unexpected or invalid packet:", p))
5807 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5808 self.assertEqual(len(sessions), 1)
5809 self.assertTrue(sessions[0].flags &
5810 self.config_flags.NAT_IS_EXT_HOST_VALID)
5811 self.assertTrue(sessions[0].flags &
5812 self.config_flags.NAT_IS_TWICE_NAT)
5813 self.logger.error(self.vapi.cli("show nat44 sessions detail"))
5814 self.vapi.nat44_del_session(
5815 address=sessions[0].inside_ip_address,
5816 port=sessions[0].inside_port,
5817 protocol=sessions[0].protocol,
5818 flags=(self.config_flags.NAT_IS_INSIDE |
5819 self.config_flags.NAT_IS_EXT_HOST_VALID),
5820 ext_host_address=sessions[0].ext_host_nat_address,
5821 ext_host_port=sessions[0].ext_host_nat_port)
5822 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5823 self.assertEqual(len(sessions), 0)
5825 def test_twice_nat(self):
5827 self.twice_nat_common()
5829 def test_self_twice_nat_positive(self):
5830 """ Self Twice NAT44 (positive test) """
5831 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5833 def test_self_twice_nat_negative(self):
5834 """ Self Twice NAT44 (negative test) """
5835 self.twice_nat_common(self_twice_nat=True)
5837 def test_twice_nat_lb(self):
5838 """ Twice NAT44 local service load balancing """
5839 self.twice_nat_common(lb=True)
5841 def test_self_twice_nat_lb_positive(self):
5842 """ Self Twice NAT44 local service load balancing (positive test) """
5843 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5846 def test_self_twice_nat_lb_negative(self):
5847 """ Self Twice NAT44 local service load balancing (negative test) """
5848 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5851 def test_twice_nat_interface_addr(self):
5852 """ Acquire twice NAT44 addresses from interface """
5853 flags = self.config_flags.NAT_IS_TWICE_NAT
5854 self.vapi.nat44_add_del_interface_addr(
5856 sw_if_index=self.pg3.sw_if_index,
5859 # no address in NAT pool
5860 adresses = self.vapi.nat44_address_dump()
5861 self.assertEqual(0, len(adresses))
5863 # configure interface address and check NAT address pool
5864 self.pg3.config_ip4()
5865 adresses = self.vapi.nat44_address_dump()
5866 self.assertEqual(1, len(adresses))
5867 self.assertEqual(str(adresses[0].ip_address),
5869 self.assertEqual(adresses[0].flags, flags)
5871 # remove interface address and check NAT address pool
5872 self.pg3.unconfig_ip4()
5873 adresses = self.vapi.nat44_address_dump()
5874 self.assertEqual(0, len(adresses))
5876 def test_tcp_close(self):
5877 """ Close TCP session from inside network - output feature """
5878 self.vapi.nat44_forwarding_enable_disable(enable=1)
5879 self.nat44_add_address(self.pg1.local_ip4)
5880 twice_nat_addr = '10.0.1.3'
5881 service_ip = '192.168.16.150'
5882 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5883 flags = self.config_flags.NAT_IS_INSIDE
5884 self.vapi.nat44_interface_add_del_feature(
5885 sw_if_index=self.pg0.sw_if_index,
5887 self.vapi.nat44_interface_add_del_feature(
5888 sw_if_index=self.pg0.sw_if_index,
5889 flags=flags, is_add=1)
5890 self.vapi.nat44_interface_add_del_output_feature(
5892 sw_if_index=self.pg1.sw_if_index)
5893 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5894 self.config_flags.NAT_IS_TWICE_NAT)
5895 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5899 proto=IP_PROTOS.tcp,
5901 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5902 start_sessnum = len(sessions)
5904 # SYN packet out->in
5905 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5906 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5907 TCP(sport=33898, dport=80, flags="S"))
5908 self.pg1.add_stream(p)
5909 self.pg_enable_capture(self.pg_interfaces)
5911 capture = self.pg0.get_capture(1)
5913 tcp_port = p[TCP].sport
5915 # SYN + ACK packet in->out
5916 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5917 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5918 TCP(sport=80, dport=tcp_port, flags="SA"))
5919 self.pg0.add_stream(p)
5920 self.pg_enable_capture(self.pg_interfaces)
5922 self.pg1.get_capture(1)
5924 # ACK packet out->in
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="A"))
5928 self.pg1.add_stream(p)
5929 self.pg_enable_capture(self.pg_interfaces)
5931 self.pg0.get_capture(1)
5933 # FIN packet in -> out
5934 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5935 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5936 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5937 self.pg0.add_stream(p)
5938 self.pg_enable_capture(self.pg_interfaces)
5940 self.pg1.get_capture(1)
5942 # FIN+ACK packet out -> in
5943 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5944 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5945 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5946 self.pg1.add_stream(p)
5947 self.pg_enable_capture(self.pg_interfaces)
5949 self.pg0.get_capture(1)
5951 # ACK packet in -> out
5952 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5953 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5954 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5955 self.pg0.add_stream(p)
5956 self.pg_enable_capture(self.pg_interfaces)
5958 self.pg1.get_capture(1)
5960 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5962 self.assertEqual(len(sessions) - start_sessnum, 0)
5964 def test_tcp_session_close_in(self):
5965 """ Close TCP session from inside network """
5966 self.tcp_port_out = 10505
5967 self.nat44_add_address(self.nat_addr)
5968 flags = self.config_flags.NAT_IS_TWICE_NAT
5969 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5973 proto=IP_PROTOS.tcp,
5975 flags = self.config_flags.NAT_IS_INSIDE
5976 self.vapi.nat44_interface_add_del_feature(
5977 sw_if_index=self.pg0.sw_if_index,
5978 flags=flags, is_add=1)
5979 self.vapi.nat44_interface_add_del_feature(
5980 sw_if_index=self.pg1.sw_if_index,
5983 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5984 start_sessnum = len(sessions)
5986 self.initiate_tcp_session(self.pg0, self.pg1)
5988 # FIN packet in -> out
5989 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5990 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5991 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5992 flags="FA", seq=100, ack=300))
5993 self.pg0.add_stream(p)
5994 self.pg_enable_capture(self.pg_interfaces)
5996 self.pg1.get_capture(1)
6000 # ACK packet out -> in
6001 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6002 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6003 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6004 flags="A", seq=300, ack=101))
6007 # FIN packet out -> in
6008 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6009 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6010 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6011 flags="FA", seq=300, ack=101))
6014 self.pg1.add_stream(pkts)
6015 self.pg_enable_capture(self.pg_interfaces)
6017 self.pg0.get_capture(2)
6019 # ACK packet in -> out
6020 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6021 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6022 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6023 flags="A", seq=101, ack=301))
6024 self.pg0.add_stream(p)
6025 self.pg_enable_capture(self.pg_interfaces)
6027 self.pg1.get_capture(1)
6029 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6031 self.assertEqual(len(sessions) - start_sessnum, 0)
6033 def test_tcp_session_close_out(self):
6034 """ Close TCP session from outside network """
6035 self.tcp_port_out = 10505
6036 self.nat44_add_address(self.nat_addr)
6037 flags = self.config_flags.NAT_IS_TWICE_NAT
6038 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6042 proto=IP_PROTOS.tcp,
6044 flags = self.config_flags.NAT_IS_INSIDE
6045 self.vapi.nat44_interface_add_del_feature(
6046 sw_if_index=self.pg0.sw_if_index,
6047 flags=flags, is_add=1)
6048 self.vapi.nat44_interface_add_del_feature(
6049 sw_if_index=self.pg1.sw_if_index,
6052 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
6053 start_sessnum = len(sessions)
6055 self.initiate_tcp_session(self.pg0, self.pg1)
6057 # FIN packet out -> in
6058 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6059 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6060 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6061 flags="FA", seq=100, ack=300))
6062 self.pg1.add_stream(p)
6063 self.pg_enable_capture(self.pg_interfaces)
6065 self.pg0.get_capture(1)
6067 # FIN+ACK packet in -> out
6068 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6069 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6070 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6071 flags="FA", seq=300, ack=101))
6073 self.pg0.add_stream(p)
6074 self.pg_enable_capture(self.pg_interfaces)
6076 self.pg1.get_capture(1)
6078 # ACK packet out -> in
6079 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6080 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6081 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6082 flags="A", seq=101, ack=301))
6083 self.pg1.add_stream(p)
6084 self.pg_enable_capture(self.pg_interfaces)
6086 self.pg0.get_capture(1)
6088 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6090 self.assertEqual(len(sessions) - start_sessnum, 0)
6092 def test_tcp_session_close_simultaneous(self):
6093 """ Close TCP session from inside network """
6094 self.tcp_port_out = 10505
6095 self.nat44_add_address(self.nat_addr)
6096 flags = self.config_flags.NAT_IS_TWICE_NAT
6097 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6101 proto=IP_PROTOS.tcp,
6103 flags = self.config_flags.NAT_IS_INSIDE
6104 self.vapi.nat44_interface_add_del_feature(
6105 sw_if_index=self.pg0.sw_if_index,
6106 flags=flags, is_add=1)
6107 self.vapi.nat44_interface_add_del_feature(
6108 sw_if_index=self.pg1.sw_if_index,
6111 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
6112 start_sessnum = len(sessions)
6114 self.initiate_tcp_session(self.pg0, self.pg1)
6116 # FIN packet in -> out
6117 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6118 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6119 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6120 flags="FA", seq=100, ack=300))
6121 self.pg0.add_stream(p)
6122 self.pg_enable_capture(self.pg_interfaces)
6124 self.pg1.get_capture(1)
6126 # FIN packet out -> in
6127 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6128 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6129 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6130 flags="FA", seq=300, ack=100))
6131 self.pg1.add_stream(p)
6132 self.pg_enable_capture(self.pg_interfaces)
6134 self.pg0.get_capture(1)
6136 # ACK packet in -> out
6137 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6138 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6139 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6140 flags="A", seq=101, ack=301))
6141 self.pg0.add_stream(p)
6142 self.pg_enable_capture(self.pg_interfaces)
6144 self.pg1.get_capture(1)
6146 # ACK packet out -> in
6147 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6148 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6149 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6150 flags="A", seq=301, ack=101))
6151 self.pg1.add_stream(p)
6152 self.pg_enable_capture(self.pg_interfaces)
6154 self.pg0.get_capture(1)
6156 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6158 self.assertEqual(len(sessions) - start_sessnum, 0)
6160 def test_one_armed_nat44_static(self):
6161 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6162 remote_host = self.pg4.remote_hosts[0]
6163 local_host = self.pg4.remote_hosts[1]
6168 self.vapi.nat44_forwarding_enable_disable(enable=1)
6169 self.nat44_add_address(self.nat_addr, twice_nat=1)
6170 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6171 self.config_flags.NAT_IS_TWICE_NAT)
6172 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6173 local_port, external_port,
6174 proto=IP_PROTOS.tcp, flags=flags)
6175 flags = self.config_flags.NAT_IS_INSIDE
6176 self.vapi.nat44_interface_add_del_feature(
6177 sw_if_index=self.pg4.sw_if_index,
6179 self.vapi.nat44_interface_add_del_feature(
6180 sw_if_index=self.pg4.sw_if_index,
6181 flags=flags, is_add=1)
6183 # from client to service
6184 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6185 IP(src=remote_host.ip4, dst=self.nat_addr) /
6186 TCP(sport=12345, dport=external_port))
6187 self.pg4.add_stream(p)
6188 self.pg_enable_capture(self.pg_interfaces)
6190 capture = self.pg4.get_capture(1)
6195 self.assertEqual(ip.dst, local_host.ip4)
6196 self.assertEqual(ip.src, self.nat_addr)
6197 self.assertEqual(tcp.dport, local_port)
6198 self.assertNotEqual(tcp.sport, 12345)
6199 eh_port_in = tcp.sport
6200 self.assert_packet_checksums_valid(p)
6202 self.logger.error(ppp("Unexpected or invalid packet:", p))
6205 # from service back to client
6206 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6207 IP(src=local_host.ip4, dst=self.nat_addr) /
6208 TCP(sport=local_port, dport=eh_port_in))
6209 self.pg4.add_stream(p)
6210 self.pg_enable_capture(self.pg_interfaces)
6212 capture = self.pg4.get_capture(1)
6217 self.assertEqual(ip.src, self.nat_addr)
6218 self.assertEqual(ip.dst, remote_host.ip4)
6219 self.assertEqual(tcp.sport, external_port)
6220 self.assertEqual(tcp.dport, 12345)
6221 self.assert_packet_checksums_valid(p)
6223 self.logger.error(ppp("Unexpected or invalid packet:", p))
6226 def test_static_with_port_out2(self):
6227 """ 1:1 NAPT asymmetrical rule """
6232 self.vapi.nat44_forwarding_enable_disable(enable=1)
6233 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6234 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6235 local_port, external_port,
6236 proto=IP_PROTOS.tcp, flags=flags)
6237 flags = self.config_flags.NAT_IS_INSIDE
6238 self.vapi.nat44_interface_add_del_feature(
6239 sw_if_index=self.pg0.sw_if_index,
6240 flags=flags, is_add=1)
6241 self.vapi.nat44_interface_add_del_feature(
6242 sw_if_index=self.pg1.sw_if_index,
6245 # from client to service
6246 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6247 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6248 TCP(sport=12345, dport=external_port))
6249 self.pg1.add_stream(p)
6250 self.pg_enable_capture(self.pg_interfaces)
6252 capture = self.pg0.get_capture(1)
6257 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6258 self.assertEqual(tcp.dport, local_port)
6259 self.assert_packet_checksums_valid(p)
6261 self.logger.error(ppp("Unexpected or invalid packet:", p))
6265 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6266 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6267 ICMP(type=11) / capture[0][IP])
6268 self.pg0.add_stream(p)
6269 self.pg_enable_capture(self.pg_interfaces)
6271 capture = self.pg1.get_capture(1)
6274 self.assertEqual(p[IP].src, self.nat_addr)
6276 self.assertEqual(inner.dst, self.nat_addr)
6277 self.assertEqual(inner[TCPerror].dport, external_port)
6279 self.logger.error(ppp("Unexpected or invalid packet:", p))
6282 # from service back to client
6283 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6284 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6285 TCP(sport=local_port, dport=12345))
6286 self.pg0.add_stream(p)
6287 self.pg_enable_capture(self.pg_interfaces)
6289 capture = self.pg1.get_capture(1)
6294 self.assertEqual(ip.src, self.nat_addr)
6295 self.assertEqual(tcp.sport, external_port)
6296 self.assert_packet_checksums_valid(p)
6298 self.logger.error(ppp("Unexpected or invalid packet:", p))
6302 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6303 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6304 ICMP(type=11) / capture[0][IP])
6305 self.pg1.add_stream(p)
6306 self.pg_enable_capture(self.pg_interfaces)
6308 capture = self.pg0.get_capture(1)
6311 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6313 self.assertEqual(inner.src, self.pg0.remote_ip4)
6314 self.assertEqual(inner[TCPerror].sport, local_port)
6316 self.logger.error(ppp("Unexpected or invalid packet:", p))
6319 # from client to server (no translation)
6320 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6321 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6322 TCP(sport=12346, dport=local_port))
6323 self.pg1.add_stream(p)
6324 self.pg_enable_capture(self.pg_interfaces)
6326 capture = self.pg0.get_capture(1)
6331 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6332 self.assertEqual(tcp.dport, local_port)
6333 self.assert_packet_checksums_valid(p)
6335 self.logger.error(ppp("Unexpected or invalid packet:", p))
6338 # from service back to client (no translation)
6339 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6340 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6341 TCP(sport=local_port, dport=12346))
6342 self.pg0.add_stream(p)
6343 self.pg_enable_capture(self.pg_interfaces)
6345 capture = self.pg1.get_capture(1)
6350 self.assertEqual(ip.src, self.pg0.remote_ip4)
6351 self.assertEqual(tcp.sport, local_port)
6352 self.assert_packet_checksums_valid(p)
6354 self.logger.error(ppp("Unexpected or invalid packet:", p))
6357 def test_output_feature(self):
6358 """ NAT44 interface output feature (in2out postrouting) """
6359 self.vapi.nat44_forwarding_enable_disable(enable=1)
6360 self.nat44_add_address(self.nat_addr)
6361 self.vapi.nat44_interface_add_del_feature(
6362 sw_if_index=self.pg0.sw_if_index,
6364 self.vapi.nat44_interface_add_del_output_feature(
6366 sw_if_index=self.pg1.sw_if_index)
6369 pkts = self.create_stream_in(self.pg0, self.pg1)
6370 self.pg0.add_stream(pkts)
6371 self.pg_enable_capture(self.pg_interfaces)
6373 capture = self.pg1.get_capture(len(pkts))
6374 self.verify_capture_out(capture)
6377 pkts = self.create_stream_out(self.pg1)
6378 self.pg1.add_stream(pkts)
6379 self.pg_enable_capture(self.pg_interfaces)
6381 capture = self.pg0.get_capture(len(pkts))
6382 self.verify_capture_in(capture, self.pg0)
6384 def test_multiple_vrf(self):
6385 """ Multiple VRF setup """
6386 external_addr = '1.2.3.4'
6391 self.vapi.nat44_forwarding_enable_disable(enable=1)
6392 self.nat44_add_address(self.nat_addr)
6393 flags = self.config_flags.NAT_IS_INSIDE
6394 self.vapi.nat44_interface_add_del_feature(
6395 sw_if_index=self.pg0.sw_if_index,
6397 self.vapi.nat44_interface_add_del_feature(
6398 sw_if_index=self.pg0.sw_if_index,
6399 flags=flags, is_add=1)
6400 self.vapi.nat44_interface_add_del_output_feature(
6402 sw_if_index=self.pg1.sw_if_index)
6403 self.vapi.nat44_interface_add_del_feature(
6404 sw_if_index=self.pg5.sw_if_index,
6406 self.vapi.nat44_interface_add_del_feature(
6407 sw_if_index=self.pg5.sw_if_index,
6408 flags=flags, is_add=1)
6409 self.vapi.nat44_interface_add_del_feature(
6410 sw_if_index=self.pg6.sw_if_index,
6412 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6413 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6414 local_port, external_port, vrf_id=1,
6415 proto=IP_PROTOS.tcp, flags=flags)
6416 self.nat44_add_static_mapping(
6417 self.pg0.remote_ip4,
6418 external_sw_if_index=self.pg0.sw_if_index,
6419 local_port=local_port,
6421 external_port=external_port,
6422 proto=IP_PROTOS.tcp,
6426 # from client to service (both VRF1)
6427 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6428 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6429 TCP(sport=12345, dport=external_port))
6430 self.pg6.add_stream(p)
6431 self.pg_enable_capture(self.pg_interfaces)
6433 capture = self.pg5.get_capture(1)
6438 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6439 self.assertEqual(tcp.dport, local_port)
6440 self.assert_packet_checksums_valid(p)
6442 self.logger.error(ppp("Unexpected or invalid packet:", p))
6445 # from service back to client (both VRF1)
6446 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6447 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6448 TCP(sport=local_port, dport=12345))
6449 self.pg5.add_stream(p)
6450 self.pg_enable_capture(self.pg_interfaces)
6452 capture = self.pg6.get_capture(1)
6457 self.assertEqual(ip.src, external_addr)
6458 self.assertEqual(tcp.sport, external_port)
6459 self.assert_packet_checksums_valid(p)
6461 self.logger.error(ppp("Unexpected or invalid packet:", p))
6464 # dynamic NAT from VRF1 to VRF0 (output-feature)
6465 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6466 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6467 TCP(sport=2345, dport=22))
6468 self.pg5.add_stream(p)
6469 self.pg_enable_capture(self.pg_interfaces)
6471 capture = self.pg1.get_capture(1)
6476 self.assertEqual(ip.src, self.nat_addr)
6477 self.assertNotEqual(tcp.sport, 2345)
6478 self.assert_packet_checksums_valid(p)
6481 self.logger.error(ppp("Unexpected or invalid packet:", p))
6484 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6485 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6486 TCP(sport=22, dport=port))
6487 self.pg1.add_stream(p)
6488 self.pg_enable_capture(self.pg_interfaces)
6490 capture = self.pg5.get_capture(1)
6495 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6496 self.assertEqual(tcp.dport, 2345)
6497 self.assert_packet_checksums_valid(p)
6499 self.logger.error(ppp("Unexpected or invalid packet:", p))
6502 # from client VRF1 to service VRF0
6503 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6504 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6505 TCP(sport=12346, dport=external_port))
6506 self.pg6.add_stream(p)
6507 self.pg_enable_capture(self.pg_interfaces)
6509 capture = self.pg0.get_capture(1)
6514 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6515 self.assertEqual(tcp.dport, local_port)
6516 self.assert_packet_checksums_valid(p)
6518 self.logger.error(ppp("Unexpected or invalid packet:", p))
6521 # from service VRF0 back to client VRF1
6522 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6523 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6524 TCP(sport=local_port, dport=12346))
6525 self.pg0.add_stream(p)
6526 self.pg_enable_capture(self.pg_interfaces)
6528 capture = self.pg6.get_capture(1)
6533 self.assertEqual(ip.src, self.pg0.local_ip4)
6534 self.assertEqual(tcp.sport, external_port)
6535 self.assert_packet_checksums_valid(p)
6537 self.logger.error(ppp("Unexpected or invalid packet:", p))
6540 # from client VRF0 to service VRF1
6541 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6542 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6543 TCP(sport=12347, dport=external_port))
6544 self.pg0.add_stream(p)
6545 self.pg_enable_capture(self.pg_interfaces)
6547 capture = self.pg5.get_capture(1)
6552 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6553 self.assertEqual(tcp.dport, local_port)
6554 self.assert_packet_checksums_valid(p)
6556 self.logger.error(ppp("Unexpected or invalid packet:", p))
6559 # from service VRF1 back to client VRF0
6560 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6561 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6562 TCP(sport=local_port, dport=12347))
6563 self.pg5.add_stream(p)
6564 self.pg_enable_capture(self.pg_interfaces)
6566 capture = self.pg0.get_capture(1)
6571 self.assertEqual(ip.src, external_addr)
6572 self.assertEqual(tcp.sport, external_port)
6573 self.assert_packet_checksums_valid(p)
6575 self.logger.error(ppp("Unexpected or invalid packet:", p))
6578 # from client to server (both VRF1, no translation)
6579 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6580 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6581 TCP(sport=12348, dport=local_port))
6582 self.pg6.add_stream(p)
6583 self.pg_enable_capture(self.pg_interfaces)
6585 capture = self.pg5.get_capture(1)
6590 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6591 self.assertEqual(tcp.dport, local_port)
6592 self.assert_packet_checksums_valid(p)
6594 self.logger.error(ppp("Unexpected or invalid packet:", p))
6597 # from server back to client (both VRF1, no translation)
6598 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6599 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6600 TCP(sport=local_port, dport=12348))
6601 self.pg5.add_stream(p)
6602 self.pg_enable_capture(self.pg_interfaces)
6604 capture = self.pg6.get_capture(1)
6609 self.assertEqual(ip.src, self.pg5.remote_ip4)
6610 self.assertEqual(tcp.sport, local_port)
6611 self.assert_packet_checksums_valid(p)
6613 self.logger.error(ppp("Unexpected or invalid packet:", p))
6616 # from client VRF1 to server VRF0 (no translation)
6617 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6618 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6619 TCP(sport=local_port, dport=12349))
6620 self.pg0.add_stream(p)
6621 self.pg_enable_capture(self.pg_interfaces)
6623 capture = self.pg6.get_capture(1)
6628 self.assertEqual(ip.src, self.pg0.remote_ip4)
6629 self.assertEqual(tcp.sport, local_port)
6630 self.assert_packet_checksums_valid(p)
6632 self.logger.error(ppp("Unexpected or invalid packet:", p))
6635 # from server VRF0 back to client VRF1 (no translation)
6636 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6637 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6638 TCP(sport=local_port, dport=12349))
6639 self.pg0.add_stream(p)
6640 self.pg_enable_capture(self.pg_interfaces)
6642 capture = self.pg6.get_capture(1)
6647 self.assertEqual(ip.src, self.pg0.remote_ip4)
6648 self.assertEqual(tcp.sport, local_port)
6649 self.assert_packet_checksums_valid(p)
6651 self.logger.error(ppp("Unexpected or invalid packet:", p))
6654 # from client VRF0 to server VRF1 (no translation)
6655 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6656 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6657 TCP(sport=12344, dport=local_port))
6658 self.pg0.add_stream(p)
6659 self.pg_enable_capture(self.pg_interfaces)
6661 capture = self.pg5.get_capture(1)
6666 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6667 self.assertEqual(tcp.dport, local_port)
6668 self.assert_packet_checksums_valid(p)
6670 self.logger.error(ppp("Unexpected or invalid packet:", p))
6673 # from server VRF1 back to client VRF0 (no translation)
6674 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6675 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6676 TCP(sport=local_port, dport=12344))
6677 self.pg5.add_stream(p)
6678 self.pg_enable_capture(self.pg_interfaces)
6680 capture = self.pg0.get_capture(1)
6685 self.assertEqual(ip.src, self.pg5.remote_ip4)
6686 self.assertEqual(tcp.sport, local_port)
6687 self.assert_packet_checksums_valid(p)
6689 self.logger.error(ppp("Unexpected or invalid packet:", p))
6692 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6693 def test_session_timeout(self):
6694 """ NAT44 session timeouts """
6695 self.nat44_add_address(self.nat_addr)
6696 flags = self.config_flags.NAT_IS_INSIDE
6697 self.vapi.nat44_interface_add_del_feature(
6698 sw_if_index=self.pg0.sw_if_index,
6699 flags=flags, is_add=1)
6700 self.vapi.nat44_interface_add_del_feature(
6701 sw_if_index=self.pg1.sw_if_index,
6703 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6704 tcp_transitory=240, icmp=5)
6708 for i in range(0, max_sessions):
6709 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6710 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6711 IP(src=src, dst=self.pg1.remote_ip4) /
6712 ICMP(id=1025, type='echo-request'))
6714 self.pg0.add_stream(pkts)
6715 self.pg_enable_capture(self.pg_interfaces)
6717 self.pg1.get_capture(max_sessions)
6722 for i in range(0, max_sessions):
6723 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6724 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6725 IP(src=src, dst=self.pg1.remote_ip4) /
6726 ICMP(id=1026, type='echo-request'))
6728 self.pg0.add_stream(pkts)
6729 self.pg_enable_capture(self.pg_interfaces)
6731 self.pg1.get_capture(max_sessions)
6734 users = self.vapi.nat44_user_dump()
6736 nsessions = nsessions + user.nsessions
6737 self.assertLess(nsessions, 2 * max_sessions)
6739 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6740 def test_session_rst_timeout(self):
6741 """ NAT44 session RST timeouts """
6742 self.nat44_add_address(self.nat_addr)
6743 flags = self.config_flags.NAT_IS_INSIDE
6744 self.vapi.nat44_interface_add_del_feature(
6745 sw_if_index=self.pg0.sw_if_index,
6746 flags=flags, is_add=1)
6747 self.vapi.nat44_interface_add_del_feature(
6748 sw_if_index=self.pg1.sw_if_index,
6750 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6751 tcp_transitory=5, icmp=60)
6753 self.initiate_tcp_session(self.pg0, self.pg1)
6754 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6755 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6756 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6758 self.pg0.add_stream(p)
6759 self.pg_enable_capture(self.pg_interfaces)
6761 self.pg1.get_capture(1)
6765 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6766 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6767 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6769 self.pg0.add_stream(p)
6770 self.pg_enable_capture(self.pg_interfaces)
6772 self.pg1.get_capture(1)
6775 users = self.vapi.nat44_user_dump()
6776 self.assertEqual(len(users), 1)
6777 self.assertEqual(str(users[0].ip_address),
6778 self.pg0.remote_ip4)
6779 self.assertEqual(users[0].nsessions, 1)
6781 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6782 def test_session_limit_per_user(self):
6783 """ Maximum sessions per user limit """
6784 self.nat44_add_address(self.nat_addr)
6785 flags = self.config_flags.NAT_IS_INSIDE
6786 self.vapi.nat44_interface_add_del_feature(
6787 sw_if_index=self.pg0.sw_if_index,
6788 flags=flags, is_add=1)
6789 self.vapi.nat44_interface_add_del_feature(
6790 sw_if_index=self.pg1.sw_if_index,
6792 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6793 src_address=self.pg2.local_ip4n,
6795 template_interval=10)
6796 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
6797 tcp_transitory=240, icmp=60)
6799 # get maximum number of translations per user
6800 nat44_config = self.vapi.nat_show_config()
6803 for port in range(0, nat44_config.max_translations_per_user):
6804 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6805 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6806 UDP(sport=1025 + port, dport=1025 + port))
6809 self.pg0.add_stream(pkts)
6810 self.pg_enable_capture(self.pg_interfaces)
6812 capture = self.pg1.get_capture(len(pkts))
6814 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6815 src_port=self.ipfix_src_port,
6818 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6819 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6820 UDP(sport=3001, dport=3002))
6821 self.pg0.add_stream(p)
6822 self.pg_enable_capture(self.pg_interfaces)
6824 capture = self.pg1.assert_nothing_captured()
6826 # verify IPFIX logging
6827 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6829 capture = self.pg2.get_capture(10)
6830 ipfix = IPFIXDecoder()
6831 # first load template
6833 self.assertTrue(p.haslayer(IPFIX))
6834 if p.haslayer(Template):
6835 ipfix.add_template(p.getlayer(Template))
6836 # verify events in data set
6838 if p.haslayer(Data):
6839 data = ipfix.decode_data_set(p.getlayer(Set))
6840 self.verify_ipfix_max_entries_per_user(
6842 nat44_config.max_translations_per_user,
6843 self.pg0.remote_ip4n)
6846 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6847 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6848 UDP(sport=3001, dport=3002))
6849 self.pg0.add_stream(p)
6850 self.pg_enable_capture(self.pg_interfaces)
6852 self.pg1.get_capture(1)
6854 def test_syslog_sess(self):
6855 """ Test syslog session creation and deletion """
6856 self.vapi.syslog_set_filter(
6857 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6858 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
6859 self.nat44_add_address(self.nat_addr)
6860 flags = self.config_flags.NAT_IS_INSIDE
6861 self.vapi.nat44_interface_add_del_feature(
6862 sw_if_index=self.pg0.sw_if_index,
6863 flags=flags, is_add=1)
6864 self.vapi.nat44_interface_add_del_feature(
6865 sw_if_index=self.pg1.sw_if_index,
6868 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6869 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6870 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6871 self.pg0.add_stream(p)
6872 self.pg_enable_capture(self.pg_interfaces)
6874 capture = self.pg1.get_capture(1)
6875 self.tcp_port_out = capture[0][TCP].sport
6876 capture = self.pg2.get_capture(1)
6877 self.verify_syslog_sess(capture[0][Raw].load)
6879 self.pg_enable_capture(self.pg_interfaces)
6881 self.nat44_add_address(self.nat_addr, is_add=0)
6882 capture = self.pg2.get_capture(1)
6883 self.verify_syslog_sess(capture[0][Raw].load, False)
6886 super(TestNAT44EndpointDependent, self).tearDown()
6887 if not self.vpp_dead:
6889 self.vapi.cli("clear logging")
6891 def show_commands_at_teardown(self):
6892 self.logger.info(self.vapi.cli("show nat44 addresses"))
6893 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6894 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6895 self.logger.info(self.vapi.cli("show nat44 interface address"))
6896 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6897 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6898 self.logger.info(self.vapi.cli("show nat timeouts"))
6901 class TestNAT44Out2InDPO(MethodHolder):
6902 """ NAT44 Test Cases using out2in DPO """
6905 def setUpConstants(cls):
6906 super(TestNAT44Out2InDPO, cls).setUpConstants()
6907 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6910 def setUpClass(cls):
6911 super(TestNAT44Out2InDPO, cls).setUpClass()
6912 cls.vapi.cli("set log class nat level debug")
6915 cls.tcp_port_in = 6303
6916 cls.tcp_port_out = 6303
6917 cls.udp_port_in = 6304
6918 cls.udp_port_out = 6304
6919 cls.icmp_id_in = 6305
6920 cls.icmp_id_out = 6305
6921 cls.nat_addr = '10.0.0.3'
6922 cls.dst_ip4 = '192.168.70.1'
6924 cls.create_pg_interfaces(range(2))
6927 cls.pg0.config_ip4()
6928 cls.pg0.resolve_arp()
6931 cls.pg1.config_ip6()
6932 cls.pg1.resolve_ndp()
6934 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
6935 dst_address_length=0,
6936 next_hop_address=cls.pg1.remote_ip6n,
6937 next_hop_sw_if_index=cls.pg1.sw_if_index,
6941 super(TestNAT44Out2InDPO, cls).tearDownClass()
6945 def tearDownClass(cls):
6946 super(TestNAT44Out2InDPO, cls).tearDownClass()
6948 def configure_xlat(self):
6949 self.dst_ip6_pfx = '1:2:3::'
6950 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6952 self.dst_ip6_pfx_len = 96
6953 self.src_ip6_pfx = '4:5:6::'
6954 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6956 self.src_ip6_pfx_len = 96
6957 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6958 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6959 '\x00\x00\x00\x00', 0)
6961 @unittest.skip('Temporary disabled')
6962 def test_464xlat_ce(self):
6963 """ Test 464XLAT CE with NAT44 """
6965 nat_config = self.vapi.nat_show_config()
6966 self.assertEqual(1, nat_config.out2in_dpo)
6968 self.configure_xlat()
6970 flags = self.config_flags.NAT_IS_INSIDE
6971 self.vapi.nat44_interface_add_del_feature(
6972 sw_if_index=self.pg0.sw_if_index,
6973 flags=flags, is_add=1)
6974 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
6975 last_ip_address=self.nat_addr_n,
6976 vrf_id=0xFFFFFFFF, is_add=1)
6978 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6979 self.dst_ip6_pfx_len)
6980 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6981 self.src_ip6_pfx_len)
6984 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6985 self.pg0.add_stream(pkts)
6986 self.pg_enable_capture(self.pg_interfaces)
6988 capture = self.pg1.get_capture(len(pkts))
6989 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6992 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6994 self.pg1.add_stream(pkts)
6995 self.pg_enable_capture(self.pg_interfaces)
6997 capture = self.pg0.get_capture(len(pkts))
6998 self.verify_capture_in(capture, self.pg0)
7000 self.vapi.nat44_interface_add_del_feature(
7001 sw_if_index=self.pg0.sw_if_index,
7003 self.vapi.nat44_add_del_address_range(
7004 first_ip_address=self.nat_addr_n,
7005 last_ip_address=self.nat_addr_n,
7008 @unittest.skip('Temporary disabled')
7009 def test_464xlat_ce_no_nat(self):
7010 """ Test 464XLAT CE without NAT44 """
7012 self.configure_xlat()
7014 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7015 self.dst_ip6_pfx_len)
7016 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7017 self.src_ip6_pfx_len)
7019 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7020 self.pg0.add_stream(pkts)
7021 self.pg_enable_capture(self.pg_interfaces)
7023 capture = self.pg1.get_capture(len(pkts))
7024 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7025 nat_ip=out_dst_ip6, same_port=True)
7027 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7028 self.pg1.add_stream(pkts)
7029 self.pg_enable_capture(self.pg_interfaces)
7031 capture = self.pg0.get_capture(len(pkts))
7032 self.verify_capture_in(capture, self.pg0)
7035 class TestDeterministicNAT(MethodHolder):
7036 """ Deterministic NAT Test Cases """
7039 def setUpConstants(cls):
7040 super(TestDeterministicNAT, cls).setUpConstants()
7041 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7044 def setUpClass(cls):
7045 super(TestDeterministicNAT, cls).setUpClass()
7046 cls.vapi.cli("set log class nat level debug")
7049 cls.tcp_port_in = 6303
7050 cls.tcp_external_port = 6303
7051 cls.udp_port_in = 6304
7052 cls.udp_external_port = 6304
7053 cls.icmp_id_in = 6305
7054 cls.nat_addr = '10.0.0.3'
7056 cls.create_pg_interfaces(range(3))
7057 cls.interfaces = list(cls.pg_interfaces)
7059 for i in cls.interfaces:
7064 cls.pg0.generate_remote_hosts(2)
7065 cls.pg0.configure_ipv4_neighbors()
7068 super(TestDeterministicNAT, cls).tearDownClass()
7072 def tearDownClass(cls):
7073 super(TestDeterministicNAT, cls).tearDownClass()
7075 def create_stream_in(self, in_if, out_if, ttl=64):
7077 Create packet stream for inside network
7079 :param in_if: Inside interface
7080 :param out_if: Outside interface
7081 :param ttl: TTL of generated packets
7085 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7086 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7087 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7091 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7092 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7093 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7097 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7098 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7099 ICMP(id=self.icmp_id_in, type='echo-request'))
7104 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7106 Create packet stream for outside network
7108 :param out_if: Outside interface
7109 :param dst_ip: Destination IP address (Default use global NAT address)
7110 :param ttl: TTL of generated packets
7113 dst_ip = self.nat_addr
7116 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7117 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7118 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7122 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7123 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7124 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7128 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7129 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7130 ICMP(id=self.icmp_external_id, type='echo-reply'))
7135 def verify_capture_out(self, capture, nat_ip=None):
7137 Verify captured packets on outside network
7139 :param capture: Captured packets
7140 :param nat_ip: Translated IP address (Default use global NAT address)
7141 :param same_port: Source port number is not translated (Default False)
7144 nat_ip = self.nat_addr
7145 for packet in capture:
7147 self.assertEqual(packet[IP].src, nat_ip)
7148 if packet.haslayer(TCP):
7149 self.tcp_port_out = packet[TCP].sport
7150 elif packet.haslayer(UDP):
7151 self.udp_port_out = packet[UDP].sport
7153 self.icmp_external_id = packet[ICMP].id
7155 self.logger.error(ppp("Unexpected or invalid packet "
7156 "(outside network):", packet))
7159 def test_deterministic_mode(self):
7160 """ NAT plugin run deterministic mode """
7161 in_addr = '172.16.255.0'
7162 out_addr = '172.17.255.50'
7163 in_addr_t = '172.16.255.20'
7167 nat_config = self.vapi.nat_show_config()
7168 self.assertEqual(1, nat_config.deterministic)
7170 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7171 in_plen=in_plen, out_addr=out_addr,
7174 rep1 = self.vapi.nat_det_forward(in_addr_t)
7175 self.assertEqual(str(rep1.out_addr), out_addr)
7176 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7178 self.assertEqual(str(rep2.in_addr), in_addr_t)
7180 deterministic_mappings = self.vapi.nat_det_map_dump()
7181 self.assertEqual(len(deterministic_mappings), 1)
7182 dsm = deterministic_mappings[0]
7183 self.assertEqual(in_addr, str(dsm.in_addr))
7184 self.assertEqual(in_plen, dsm.in_plen)
7185 self.assertEqual(out_addr, str(dsm.out_addr))
7186 self.assertEqual(out_plen, dsm.out_plen)
7188 self.clear_nat_det()
7189 deterministic_mappings = self.vapi.nat_det_map_dump()
7190 self.assertEqual(len(deterministic_mappings), 0)
7192 def test_set_timeouts(self):
7193 """ Set deterministic NAT timeouts """
7194 timeouts_before = self.vapi.nat_get_timeouts()
7196 self.vapi.nat_set_timeouts(
7197 udp=timeouts_before.udp + 10,
7198 tcp_established=timeouts_before.tcp_established + 10,
7199 tcp_transitory=timeouts_before.tcp_transitory + 10,
7200 icmp=timeouts_before.icmp + 10)
7202 timeouts_after = self.vapi.nat_get_timeouts()
7204 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7205 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7206 self.assertNotEqual(timeouts_before.tcp_established,
7207 timeouts_after.tcp_established)
7208 self.assertNotEqual(timeouts_before.tcp_transitory,
7209 timeouts_after.tcp_transitory)
7211 def test_det_in(self):
7212 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7214 nat_ip = "10.0.0.10"
7216 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7218 out_addr=socket.inet_aton(nat_ip),
7221 flags = self.config_flags.NAT_IS_INSIDE
7222 self.vapi.nat44_interface_add_del_feature(
7223 sw_if_index=self.pg0.sw_if_index,
7224 flags=flags, is_add=1)
7225 self.vapi.nat44_interface_add_del_feature(
7226 sw_if_index=self.pg1.sw_if_index,
7230 pkts = self.create_stream_in(self.pg0, self.pg1)
7231 self.pg0.add_stream(pkts)
7232 self.pg_enable_capture(self.pg_interfaces)
7234 capture = self.pg1.get_capture(len(pkts))
7235 self.verify_capture_out(capture, nat_ip)
7238 pkts = self.create_stream_out(self.pg1, nat_ip)
7239 self.pg1.add_stream(pkts)
7240 self.pg_enable_capture(self.pg_interfaces)
7242 capture = self.pg0.get_capture(len(pkts))
7243 self.verify_capture_in(capture, self.pg0)
7246 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
7247 self.assertEqual(len(sessions), 3)
7251 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7252 self.assertEqual(s.in_port, self.tcp_port_in)
7253 self.assertEqual(s.out_port, self.tcp_port_out)
7254 self.assertEqual(s.ext_port, self.tcp_external_port)
7258 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7259 self.assertEqual(s.in_port, self.udp_port_in)
7260 self.assertEqual(s.out_port, self.udp_port_out)
7261 self.assertEqual(s.ext_port, self.udp_external_port)
7265 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7266 self.assertEqual(s.in_port, self.icmp_id_in)
7267 self.assertEqual(s.out_port, self.icmp_external_id)
7269 def test_multiple_users(self):
7270 """ Deterministic NAT multiple users """
7272 nat_ip = "10.0.0.10"
7274 external_port = 6303
7276 host0 = self.pg0.remote_hosts[0]
7277 host1 = self.pg0.remote_hosts[1]
7279 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4n, in_plen=24,
7280 out_addr=socket.inet_aton(nat_ip),
7282 flags = self.config_flags.NAT_IS_INSIDE
7283 self.vapi.nat44_interface_add_del_feature(
7284 sw_if_index=self.pg0.sw_if_index,
7285 flags=flags, is_add=1)
7286 self.vapi.nat44_interface_add_del_feature(
7287 sw_if_index=self.pg1.sw_if_index,
7291 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7292 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7293 TCP(sport=port_in, dport=external_port))
7294 self.pg0.add_stream(p)
7295 self.pg_enable_capture(self.pg_interfaces)
7297 capture = self.pg1.get_capture(1)
7302 self.assertEqual(ip.src, nat_ip)
7303 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7304 self.assertEqual(tcp.dport, external_port)
7305 port_out0 = tcp.sport
7307 self.logger.error(ppp("Unexpected or invalid packet:", p))
7311 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7312 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7313 TCP(sport=port_in, dport=external_port))
7314 self.pg0.add_stream(p)
7315 self.pg_enable_capture(self.pg_interfaces)
7317 capture = self.pg1.get_capture(1)
7322 self.assertEqual(ip.src, nat_ip)
7323 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7324 self.assertEqual(tcp.dport, external_port)
7325 port_out1 = tcp.sport
7327 self.logger.error(ppp("Unexpected or invalid packet:", p))
7330 dms = self.vapi.nat_det_map_dump()
7331 self.assertEqual(1, len(dms))
7332 self.assertEqual(2, dms[0].ses_num)
7335 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7336 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7337 TCP(sport=external_port, dport=port_out0))
7338 self.pg1.add_stream(p)
7339 self.pg_enable_capture(self.pg_interfaces)
7341 capture = self.pg0.get_capture(1)
7346 self.assertEqual(ip.src, self.pg1.remote_ip4)
7347 self.assertEqual(ip.dst, host0.ip4)
7348 self.assertEqual(tcp.dport, port_in)
7349 self.assertEqual(tcp.sport, external_port)
7351 self.logger.error(ppp("Unexpected or invalid packet:", p))
7355 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7356 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7357 TCP(sport=external_port, dport=port_out1))
7358 self.pg1.add_stream(p)
7359 self.pg_enable_capture(self.pg_interfaces)
7361 capture = self.pg0.get_capture(1)
7366 self.assertEqual(ip.src, self.pg1.remote_ip4)
7367 self.assertEqual(ip.dst, host1.ip4)
7368 self.assertEqual(tcp.dport, port_in)
7369 self.assertEqual(tcp.sport, external_port)
7371 self.logger.error(ppp("Unexpected or invalid packet", p))
7374 # session close api test
7375 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7377 self.pg1.remote_ip4n,
7379 dms = self.vapi.nat_det_map_dump()
7380 self.assertEqual(dms[0].ses_num, 1)
7382 self.vapi.nat_det_close_session_in(host0.ip4n,
7384 self.pg1.remote_ip4n,
7386 dms = self.vapi.nat_det_map_dump()
7387 self.assertEqual(dms[0].ses_num, 0)
7389 def test_tcp_session_close_detection_in(self):
7390 """ Deterministic NAT TCP session close from inside network """
7391 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7393 out_addr=socket.inet_aton(self.nat_addr),
7395 flags = self.config_flags.NAT_IS_INSIDE
7396 self.vapi.nat44_interface_add_del_feature(
7397 sw_if_index=self.pg0.sw_if_index,
7398 flags=flags, is_add=1)
7399 self.vapi.nat44_interface_add_del_feature(
7400 sw_if_index=self.pg1.sw_if_index,
7403 self.initiate_tcp_session(self.pg0, self.pg1)
7405 # close the session from inside
7407 # FIN packet in -> out
7408 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7409 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7410 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7412 self.pg0.add_stream(p)
7413 self.pg_enable_capture(self.pg_interfaces)
7415 self.pg1.get_capture(1)
7419 # ACK packet out -> in
7420 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7421 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7422 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7426 # FIN packet out -> in
7427 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7428 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7429 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7433 self.pg1.add_stream(pkts)
7434 self.pg_enable_capture(self.pg_interfaces)
7436 self.pg0.get_capture(2)
7438 # ACK packet in -> out
7439 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7440 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7441 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7443 self.pg0.add_stream(p)
7444 self.pg_enable_capture(self.pg_interfaces)
7446 self.pg1.get_capture(1)
7448 # Check if deterministic NAT44 closed the session
7449 dms = self.vapi.nat_det_map_dump()
7450 self.assertEqual(0, dms[0].ses_num)
7452 self.logger.error("TCP session termination failed")
7455 def test_tcp_session_close_detection_out(self):
7456 """ Deterministic NAT TCP session close from outside network """
7457 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7459 out_addr=socket.inet_aton(self.nat_addr),
7461 flags = self.config_flags.NAT_IS_INSIDE
7462 self.vapi.nat44_interface_add_del_feature(
7463 sw_if_index=self.pg0.sw_if_index,
7464 flags=flags, is_add=1)
7465 self.vapi.nat44_interface_add_del_feature(
7466 sw_if_index=self.pg1.sw_if_index,
7469 self.initiate_tcp_session(self.pg0, self.pg1)
7471 # close the session from outside
7473 # FIN packet out -> in
7474 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7475 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7476 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7478 self.pg1.add_stream(p)
7479 self.pg_enable_capture(self.pg_interfaces)
7481 self.pg0.get_capture(1)
7485 # ACK packet in -> out
7486 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7487 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7488 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7492 # ACK packet in -> out
7493 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7494 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7495 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7499 self.pg0.add_stream(pkts)
7500 self.pg_enable_capture(self.pg_interfaces)
7502 self.pg1.get_capture(2)
7504 # ACK packet out -> in
7505 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7506 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7507 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7509 self.pg1.add_stream(p)
7510 self.pg_enable_capture(self.pg_interfaces)
7512 self.pg0.get_capture(1)
7514 # Check if deterministic NAT44 closed the session
7515 dms = self.vapi.nat_det_map_dump()
7516 self.assertEqual(0, dms[0].ses_num)
7518 self.logger.error("TCP session termination failed")
7521 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7522 def test_session_timeout(self):
7523 """ Deterministic NAT session timeouts """
7524 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7526 out_addr=socket.inet_aton(self.nat_addr),
7528 flags = self.config_flags.NAT_IS_INSIDE
7529 self.vapi.nat44_interface_add_del_feature(
7530 sw_if_index=self.pg0.sw_if_index,
7531 flags=flags, is_add=1)
7532 self.vapi.nat44_interface_add_del_feature(
7533 sw_if_index=self.pg1.sw_if_index,
7536 self.initiate_tcp_session(self.pg0, self.pg1)
7537 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7539 pkts = self.create_stream_in(self.pg0, self.pg1)
7540 self.pg0.add_stream(pkts)
7541 self.pg_enable_capture(self.pg_interfaces)
7543 capture = self.pg1.get_capture(len(pkts))
7546 dms = self.vapi.nat_det_map_dump()
7547 self.assertEqual(0, dms[0].ses_num)
7549 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7550 def test_session_limit_per_user(self):
7551 """ Deterministic NAT maximum sessions per user limit """
7552 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7554 out_addr=socket.inet_aton(self.nat_addr),
7556 flags = self.config_flags.NAT_IS_INSIDE
7557 self.vapi.nat44_interface_add_del_feature(
7558 sw_if_index=self.pg0.sw_if_index,
7559 flags=flags, is_add=1)
7560 self.vapi.nat44_interface_add_del_feature(
7561 sw_if_index=self.pg1.sw_if_index,
7563 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7564 src_address=self.pg2.local_ip4n,
7566 template_interval=10)
7567 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7571 for port in range(1025, 2025):
7572 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7573 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7574 UDP(sport=port, dport=port))
7577 self.pg0.add_stream(pkts)
7578 self.pg_enable_capture(self.pg_interfaces)
7580 capture = self.pg1.get_capture(len(pkts))
7582 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7583 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7584 UDP(sport=3001, dport=3002))
7585 self.pg0.add_stream(p)
7586 self.pg_enable_capture(self.pg_interfaces)
7588 capture = self.pg1.assert_nothing_captured()
7590 # verify ICMP error packet
7591 capture = self.pg0.get_capture(1)
7593 self.assertTrue(p.haslayer(ICMP))
7595 self.assertEqual(icmp.type, 3)
7596 self.assertEqual(icmp.code, 1)
7597 self.assertTrue(icmp.haslayer(IPerror))
7598 inner_ip = icmp[IPerror]
7599 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7600 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7602 dms = self.vapi.nat_det_map_dump()
7604 self.assertEqual(1000, dms[0].ses_num)
7606 # verify IPFIX logging
7607 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7609 capture = self.pg2.get_capture(2)
7610 ipfix = IPFIXDecoder()
7611 # first load template
7613 self.assertTrue(p.haslayer(IPFIX))
7614 if p.haslayer(Template):
7615 ipfix.add_template(p.getlayer(Template))
7616 # verify events in data set
7618 if p.haslayer(Data):
7619 data = ipfix.decode_data_set(p.getlayer(Set))
7620 self.verify_ipfix_max_entries_per_user(data,
7622 self.pg0.remote_ip4n)
7624 def clear_nat_det(self):
7626 Clear deterministic NAT configuration.
7628 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7630 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7631 tcp_transitory=240, icmp=60)
7632 deterministic_mappings = self.vapi.nat_det_map_dump()
7633 for dsm in deterministic_mappings:
7634 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7635 in_plen=dsm.in_plen,
7636 out_addr=dsm.out_addr,
7637 out_plen=dsm.out_plen)
7639 interfaces = self.vapi.nat44_interface_dump()
7640 for intf in interfaces:
7641 self.vapi.nat44_interface_add_del_feature(
7642 sw_if_index=intf.sw_if_index,
7646 super(TestDeterministicNAT, self).tearDown()
7647 if not self.vpp_dead:
7648 self.clear_nat_det()
7650 def show_commands_at_teardown(self):
7651 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7652 self.logger.info(self.vapi.cli("show nat timeouts"))
7654 self.vapi.cli("show nat44 deterministic mappings"))
7656 self.vapi.cli("show nat44 deterministic sessions"))
7659 class TestNAT64(MethodHolder):
7660 """ NAT64 Test Cases """
7663 def setUpConstants(cls):
7664 super(TestNAT64, cls).setUpConstants()
7665 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7666 "nat64 st hash buckets 256", "}"])
7669 def setUpClass(cls):
7670 super(TestNAT64, cls).setUpClass()
7673 cls.tcp_port_in = 6303
7674 cls.tcp_port_out = 6303
7675 cls.udp_port_in = 6304
7676 cls.udp_port_out = 6304
7677 cls.icmp_id_in = 6305
7678 cls.icmp_id_out = 6305
7679 cls.tcp_external_port = 80
7680 cls.nat_addr = '10.0.0.3'
7681 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7683 cls.vrf1_nat_addr = '10.0.10.3'
7684 cls.ipfix_src_port = 4739
7685 cls.ipfix_domain_id = 1
7687 cls.create_pg_interfaces(range(6))
7688 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7689 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7690 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7692 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7693 table_id=cls.vrf1_id)
7695 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7697 cls.pg0.generate_remote_hosts(2)
7699 for i in cls.ip6_interfaces:
7702 i.configure_ipv6_neighbors()
7704 for i in cls.ip4_interfaces:
7710 cls.pg3.config_ip4()
7711 cls.pg3.resolve_arp()
7712 cls.pg3.config_ip6()
7713 cls.pg3.configure_ipv6_neighbors()
7716 cls.pg5.config_ip6()
7719 super(TestNAT64, cls).tearDownClass()
7723 def tearDownClass(cls):
7724 super(TestNAT64, cls).tearDownClass()
7726 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7727 """ NAT64 inside interface handles Neighbor Advertisement """
7729 flags = self.config_flags.NAT_IS_INSIDE
7730 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7731 sw_if_index=self.pg5.sw_if_index)
7734 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7735 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7736 ICMPv6EchoRequest())
7738 self.pg5.add_stream(pkts)
7739 self.pg_enable_capture(self.pg_interfaces)
7742 # Wait for Neighbor Solicitation
7743 capture = self.pg5.get_capture(len(pkts))
7746 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7747 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7748 tgt = packet[ICMPv6ND_NS].tgt
7750 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7753 # Send Neighbor Advertisement
7754 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7755 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7756 ICMPv6ND_NA(tgt=tgt) /
7757 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7759 self.pg5.add_stream(pkts)
7760 self.pg_enable_capture(self.pg_interfaces)
7763 # Try to send ping again
7765 self.pg5.add_stream(pkts)
7766 self.pg_enable_capture(self.pg_interfaces)
7769 # Wait for ping reply
7770 capture = self.pg5.get_capture(len(pkts))
7773 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7774 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7775 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7777 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7780 def test_pool(self):
7781 """ Add/delete address to NAT64 pool """
7782 nat_addr = '1.2.3.4'
7784 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7786 vrf_id=0xFFFFFFFF, is_add=1)
7788 addresses = self.vapi.nat64_pool_addr_dump()
7789 self.assertEqual(len(addresses), 1)
7790 self.assertEqual(str(addresses[0].address), nat_addr)
7792 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7794 vrf_id=0xFFFFFFFF, is_add=0)
7796 addresses = self.vapi.nat64_pool_addr_dump()
7797 self.assertEqual(len(addresses), 0)
7799 def test_interface(self):
7800 """ Enable/disable NAT64 feature on the interface """
7801 flags = self.config_flags.NAT_IS_INSIDE
7802 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7803 sw_if_index=self.pg0.sw_if_index)
7804 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7805 sw_if_index=self.pg1.sw_if_index)
7807 interfaces = self.vapi.nat64_interface_dump()
7808 self.assertEqual(len(interfaces), 2)
7811 for intf in interfaces:
7812 if intf.sw_if_index == self.pg0.sw_if_index:
7813 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7815 elif intf.sw_if_index == self.pg1.sw_if_index:
7816 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7818 self.assertTrue(pg0_found)
7819 self.assertTrue(pg1_found)
7821 features = self.vapi.cli("show interface features pg0")
7822 self.assertIn('nat64-in2out', features)
7823 features = self.vapi.cli("show interface features pg1")
7824 self.assertIn('nat64-out2in', features)
7826 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7827 sw_if_index=self.pg0.sw_if_index)
7828 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7829 sw_if_index=self.pg1.sw_if_index)
7831 interfaces = self.vapi.nat64_interface_dump()
7832 self.assertEqual(len(interfaces), 0)
7834 def test_static_bib(self):
7835 """ Add/delete static BIB entry """
7836 in_addr = '2001:db8:85a3::8a2e:370:7334'
7837 out_addr = '10.1.1.3'
7840 proto = IP_PROTOS.tcp
7842 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7843 i_port=in_port, o_port=out_port,
7844 proto=proto, vrf_id=0, is_add=1)
7845 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7848 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7850 self.assertEqual(str(bibe.i_addr), in_addr)
7851 self.assertEqual(str(bibe.o_addr), out_addr)
7852 self.assertEqual(bibe.i_port, in_port)
7853 self.assertEqual(bibe.o_port, out_port)
7854 self.assertEqual(static_bib_num, 1)
7855 bibs = self.statistics.get_counter('/nat64/total-bibs')
7856 self.assertEqual(bibs[0][0], 1)
7858 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7859 i_port=in_port, o_port=out_port,
7860 proto=proto, vrf_id=0, is_add=0)
7861 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7864 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7866 self.assertEqual(static_bib_num, 0)
7867 bibs = self.statistics.get_counter('/nat64/total-bibs')
7868 self.assertEqual(bibs[0][0], 0)
7870 def test_set_timeouts(self):
7871 """ Set NAT64 timeouts """
7872 # verify default values
7873 timeouts = self.vapi.nat_get_timeouts()
7874 self.assertEqual(timeouts.udp, 300)
7875 self.assertEqual(timeouts.icmp, 60)
7876 self.assertEqual(timeouts.tcp_transitory, 240)
7877 self.assertEqual(timeouts.tcp_established, 7440)
7879 # set and verify custom values
7880 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7881 tcp_transitory=250, icmp=30)
7882 timeouts = self.vapi.nat_get_timeouts()
7883 self.assertEqual(timeouts.udp, 200)
7884 self.assertEqual(timeouts.icmp, 30)
7885 self.assertEqual(timeouts.tcp_transitory, 250)
7886 self.assertEqual(timeouts.tcp_established, 7450)
7888 def test_dynamic(self):
7889 """ NAT64 dynamic translation test """
7890 self.tcp_port_in = 6303
7891 self.udp_port_in = 6304
7892 self.icmp_id_in = 6305
7894 ses_num_start = self.nat64_get_ses_num()
7896 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7897 end_addr=self.nat_addr,
7900 flags = self.config_flags.NAT_IS_INSIDE
7901 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7902 sw_if_index=self.pg0.sw_if_index)
7903 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7904 sw_if_index=self.pg1.sw_if_index)
7907 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7908 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7909 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7910 totaln = self.statistics.get_counter(
7911 '/err/nat64-in2out/good in2out packets processed')
7913 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7914 self.pg0.add_stream(pkts)
7915 self.pg_enable_capture(self.pg_interfaces)
7917 capture = self.pg1.get_capture(len(pkts))
7918 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7919 dst_ip=self.pg1.remote_ip4)
7921 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7922 self.assertEqual(err - tcpn, 1)
7923 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7924 self.assertEqual(err - udpn, 1)
7925 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7926 self.assertEqual(err - icmpn, 1)
7927 err = self.statistics.get_counter(
7928 '/err/nat64-in2out/good in2out packets processed')
7929 self.assertEqual(err - totaln, 3)
7932 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7933 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7934 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7935 totaln = self.statistics.get_counter(
7936 '/err/nat64-out2in/good out2in packets processed')
7938 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7939 self.pg1.add_stream(pkts)
7940 self.pg_enable_capture(self.pg_interfaces)
7942 capture = self.pg0.get_capture(len(pkts))
7943 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7944 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7946 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7947 self.assertEqual(err - tcpn, 1)
7948 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7949 self.assertEqual(err - udpn, 1)
7950 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7951 self.assertEqual(err - icmpn, 1)
7952 err = self.statistics.get_counter(
7953 '/err/nat64-out2in/good out2in packets processed')
7954 self.assertEqual(err - totaln, 3)
7956 bibs = self.statistics.get_counter('/nat64/total-bibs')
7957 self.assertEqual(bibs[0][0], 3)
7958 sessions = self.statistics.get_counter('/nat64/total-sessions')
7959 self.assertEqual(sessions[0][0], 3)
7962 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7963 self.pg0.add_stream(pkts)
7964 self.pg_enable_capture(self.pg_interfaces)
7966 capture = self.pg1.get_capture(len(pkts))
7967 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7968 dst_ip=self.pg1.remote_ip4)
7971 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7972 self.pg1.add_stream(pkts)
7973 self.pg_enable_capture(self.pg_interfaces)
7975 capture = self.pg0.get_capture(len(pkts))
7976 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7978 ses_num_end = self.nat64_get_ses_num()
7980 self.assertEqual(ses_num_end - ses_num_start, 3)
7982 # tenant with specific VRF
7983 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
7984 end_addr=self.vrf1_nat_addr,
7985 vrf_id=self.vrf1_id, is_add=1)
7986 flags = self.config_flags.NAT_IS_INSIDE
7987 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7988 sw_if_index=self.pg2.sw_if_index)
7990 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7991 self.pg2.add_stream(pkts)
7992 self.pg_enable_capture(self.pg_interfaces)
7994 capture = self.pg1.get_capture(len(pkts))
7995 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7996 dst_ip=self.pg1.remote_ip4)
7998 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7999 self.pg1.add_stream(pkts)
8000 self.pg_enable_capture(self.pg_interfaces)
8002 capture = self.pg2.get_capture(len(pkts))
8003 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8005 def test_static(self):
8006 """ NAT64 static translation test """
8007 self.tcp_port_in = 60303
8008 self.udp_port_in = 60304
8009 self.icmp_id_in = 60305
8010 self.tcp_port_out = 60303
8011 self.udp_port_out = 60304
8012 self.icmp_id_out = 60305
8014 ses_num_start = self.nat64_get_ses_num()
8016 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8017 end_addr=self.nat_addr,
8020 flags = self.config_flags.NAT_IS_INSIDE
8021 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8022 sw_if_index=self.pg0.sw_if_index)
8023 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8024 sw_if_index=self.pg1.sw_if_index)
8026 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8027 o_addr=self.nat_addr,
8028 i_port=self.tcp_port_in,
8029 o_port=self.tcp_port_out,
8030 proto=IP_PROTOS.tcp, vrf_id=0,
8032 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8033 o_addr=self.nat_addr,
8034 i_port=self.udp_port_in,
8035 o_port=self.udp_port_out,
8036 proto=IP_PROTOS.udp, vrf_id=0,
8038 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8039 o_addr=self.nat_addr,
8040 i_port=self.icmp_id_in,
8041 o_port=self.icmp_id_out,
8042 proto=IP_PROTOS.icmp, vrf_id=0,
8046 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8047 self.pg0.add_stream(pkts)
8048 self.pg_enable_capture(self.pg_interfaces)
8050 capture = self.pg1.get_capture(len(pkts))
8051 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8052 dst_ip=self.pg1.remote_ip4, same_port=True)
8055 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8056 self.pg1.add_stream(pkts)
8057 self.pg_enable_capture(self.pg_interfaces)
8059 capture = self.pg0.get_capture(len(pkts))
8060 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8061 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8063 ses_num_end = self.nat64_get_ses_num()
8065 self.assertEqual(ses_num_end - ses_num_start, 3)
8067 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8068 def test_session_timeout(self):
8069 """ NAT64 session timeout """
8070 self.icmp_id_in = 1234
8071 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8072 end_addr=self.nat_addr,
8075 flags = self.config_flags.NAT_IS_INSIDE
8076 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8077 sw_if_index=self.pg0.sw_if_index)
8078 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8079 sw_if_index=self.pg1.sw_if_index)
8080 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8084 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8085 self.pg0.add_stream(pkts)
8086 self.pg_enable_capture(self.pg_interfaces)
8088 capture = self.pg1.get_capture(len(pkts))
8090 ses_num_before_timeout = self.nat64_get_ses_num()
8094 # ICMP and TCP session after timeout
8095 ses_num_after_timeout = self.nat64_get_ses_num()
8096 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8098 def test_icmp_error(self):
8099 """ NAT64 ICMP Error message translation """
8100 self.tcp_port_in = 6303
8101 self.udp_port_in = 6304
8102 self.icmp_id_in = 6305
8104 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8105 end_addr=self.nat_addr,
8108 flags = self.config_flags.NAT_IS_INSIDE
8109 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8110 sw_if_index=self.pg0.sw_if_index)
8111 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8112 sw_if_index=self.pg1.sw_if_index)
8114 # send some packets to create sessions
8115 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8116 self.pg0.add_stream(pkts)
8117 self.pg_enable_capture(self.pg_interfaces)
8119 capture_ip4 = self.pg1.get_capture(len(pkts))
8120 self.verify_capture_out(capture_ip4,
8121 nat_ip=self.nat_addr,
8122 dst_ip=self.pg1.remote_ip4)
8124 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8125 self.pg1.add_stream(pkts)
8126 self.pg_enable_capture(self.pg_interfaces)
8128 capture_ip6 = self.pg0.get_capture(len(pkts))
8129 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8130 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8131 self.pg0.remote_ip6)
8134 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8135 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8136 ICMPv6DestUnreach(code=1) /
8137 packet[IPv6] for packet in capture_ip6]
8138 self.pg0.add_stream(pkts)
8139 self.pg_enable_capture(self.pg_interfaces)
8141 capture = self.pg1.get_capture(len(pkts))
8142 for packet in capture:
8144 self.assertEqual(packet[IP].src, self.nat_addr)
8145 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8146 self.assertEqual(packet[ICMP].type, 3)
8147 self.assertEqual(packet[ICMP].code, 13)
8148 inner = packet[IPerror]
8149 self.assertEqual(inner.src, self.pg1.remote_ip4)
8150 self.assertEqual(inner.dst, self.nat_addr)
8151 self.assert_packet_checksums_valid(packet)
8152 if inner.haslayer(TCPerror):
8153 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8154 elif inner.haslayer(UDPerror):
8155 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8157 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8159 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8163 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8164 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8165 ICMP(type=3, code=13) /
8166 packet[IP] for packet in capture_ip4]
8167 self.pg1.add_stream(pkts)
8168 self.pg_enable_capture(self.pg_interfaces)
8170 capture = self.pg0.get_capture(len(pkts))
8171 for packet in capture:
8173 self.assertEqual(packet[IPv6].src, ip.src)
8174 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8175 icmp = packet[ICMPv6DestUnreach]
8176 self.assertEqual(icmp.code, 1)
8177 inner = icmp[IPerror6]
8178 self.assertEqual(inner.src, self.pg0.remote_ip6)
8179 self.assertEqual(inner.dst, ip.src)
8180 self.assert_icmpv6_checksum_valid(packet)
8181 if inner.haslayer(TCPerror):
8182 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8183 elif inner.haslayer(UDPerror):
8184 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8186 self.assertEqual(inner[ICMPv6EchoRequest].id,
8189 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8192 def test_hairpinning(self):
8193 """ NAT64 hairpinning """
8195 client = self.pg0.remote_hosts[0]
8196 server = self.pg0.remote_hosts[1]
8197 server_tcp_in_port = 22
8198 server_tcp_out_port = 4022
8199 server_udp_in_port = 23
8200 server_udp_out_port = 4023
8201 client_tcp_in_port = 1234
8202 client_udp_in_port = 1235
8203 client_tcp_out_port = 0
8204 client_udp_out_port = 0
8205 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8206 nat_addr_ip6 = ip.src
8208 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8209 end_addr=self.nat_addr,
8212 flags = self.config_flags.NAT_IS_INSIDE
8213 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8214 sw_if_index=self.pg0.sw_if_index)
8215 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8216 sw_if_index=self.pg1.sw_if_index)
8218 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8219 o_addr=self.nat_addr,
8220 i_port=server_tcp_in_port,
8221 o_port=server_tcp_out_port,
8222 proto=IP_PROTOS.tcp, vrf_id=0,
8224 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8225 o_addr=self.nat_addr,
8226 i_port=server_udp_in_port,
8227 o_port=server_udp_out_port,
8228 proto=IP_PROTOS.udp, vrf_id=0,
8233 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8234 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8235 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8237 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8238 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8239 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8241 self.pg0.add_stream(pkts)
8242 self.pg_enable_capture(self.pg_interfaces)
8244 capture = self.pg0.get_capture(len(pkts))
8245 for packet in capture:
8247 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8248 self.assertEqual(packet[IPv6].dst, server.ip6)
8249 self.assert_packet_checksums_valid(packet)
8250 if packet.haslayer(TCP):
8251 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8252 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8253 client_tcp_out_port = packet[TCP].sport
8255 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8256 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8257 client_udp_out_port = packet[UDP].sport
8259 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8264 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8265 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8266 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8268 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8269 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8270 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8272 self.pg0.add_stream(pkts)
8273 self.pg_enable_capture(self.pg_interfaces)
8275 capture = self.pg0.get_capture(len(pkts))
8276 for packet in capture:
8278 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8279 self.assertEqual(packet[IPv6].dst, client.ip6)
8280 self.assert_packet_checksums_valid(packet)
8281 if packet.haslayer(TCP):
8282 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8283 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8285 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8286 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8288 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8293 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8294 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8295 ICMPv6DestUnreach(code=1) /
8296 packet[IPv6] for packet in capture]
8297 self.pg0.add_stream(pkts)
8298 self.pg_enable_capture(self.pg_interfaces)
8300 capture = self.pg0.get_capture(len(pkts))
8301 for packet in capture:
8303 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8304 self.assertEqual(packet[IPv6].dst, server.ip6)
8305 icmp = packet[ICMPv6DestUnreach]
8306 self.assertEqual(icmp.code, 1)
8307 inner = icmp[IPerror6]
8308 self.assertEqual(inner.src, server.ip6)
8309 self.assertEqual(inner.dst, nat_addr_ip6)
8310 self.assert_packet_checksums_valid(packet)
8311 if inner.haslayer(TCPerror):
8312 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8313 self.assertEqual(inner[TCPerror].dport,
8314 client_tcp_out_port)
8316 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8317 self.assertEqual(inner[UDPerror].dport,
8318 client_udp_out_port)
8320 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8323 def test_prefix(self):
8324 """ NAT64 Network-Specific Prefix """
8326 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8327 end_addr=self.nat_addr,
8330 flags = self.config_flags.NAT_IS_INSIDE
8331 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8332 sw_if_index=self.pg0.sw_if_index)
8333 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8334 sw_if_index=self.pg1.sw_if_index)
8335 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8336 end_addr=self.vrf1_nat_addr,
8337 vrf_id=self.vrf1_id, is_add=1)
8338 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8339 sw_if_index=self.pg2.sw_if_index)
8342 global_pref64 = "2001:db8::"
8343 global_pref64_len = 32
8344 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8345 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8348 prefix = self.vapi.nat64_prefix_dump()
8349 self.assertEqual(len(prefix), 1)
8350 self.assertEqual(prefix[0].prefix,
8351 IPv6Network(unicode(global_pref64_str)))
8352 self.assertEqual(prefix[0].vrf_id, 0)
8354 # Add tenant specific prefix
8355 vrf1_pref64 = "2001:db8:122:300::"
8356 vrf1_pref64_len = 56
8357 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8358 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8359 vrf_id=self.vrf1_id, is_add=1)
8361 prefix = self.vapi.nat64_prefix_dump()
8362 self.assertEqual(len(prefix), 2)
8365 pkts = self.create_stream_in_ip6(self.pg0,
8368 plen=global_pref64_len)
8369 self.pg0.add_stream(pkts)
8370 self.pg_enable_capture(self.pg_interfaces)
8372 capture = self.pg1.get_capture(len(pkts))
8373 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8374 dst_ip=self.pg1.remote_ip4)
8376 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8377 self.pg1.add_stream(pkts)
8378 self.pg_enable_capture(self.pg_interfaces)
8380 capture = self.pg0.get_capture(len(pkts))
8381 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8384 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8386 # Tenant specific prefix
8387 pkts = self.create_stream_in_ip6(self.pg2,
8390 plen=vrf1_pref64_len)
8391 self.pg2.add_stream(pkts)
8392 self.pg_enable_capture(self.pg_interfaces)
8394 capture = self.pg1.get_capture(len(pkts))
8395 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8396 dst_ip=self.pg1.remote_ip4)
8398 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8399 self.pg1.add_stream(pkts)
8400 self.pg_enable_capture(self.pg_interfaces)
8402 capture = self.pg2.get_capture(len(pkts))
8403 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8406 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8408 def test_unknown_proto(self):
8409 """ NAT64 translate packet with unknown protocol """
8411 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8412 end_addr=self.nat_addr,
8415 flags = self.config_flags.NAT_IS_INSIDE
8416 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8417 sw_if_index=self.pg0.sw_if_index)
8418 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8419 sw_if_index=self.pg1.sw_if_index)
8420 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8423 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8424 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8425 TCP(sport=self.tcp_port_in, dport=20))
8426 self.pg0.add_stream(p)
8427 self.pg_enable_capture(self.pg_interfaces)
8429 p = self.pg1.get_capture(1)
8431 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8432 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8434 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8435 TCP(sport=1234, dport=1234))
8436 self.pg0.add_stream(p)
8437 self.pg_enable_capture(self.pg_interfaces)
8439 p = self.pg1.get_capture(1)
8442 self.assertEqual(packet[IP].src, self.nat_addr)
8443 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8444 self.assertEqual(packet.haslayer(GRE), 1)
8445 self.assert_packet_checksums_valid(packet)
8447 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8451 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8452 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8454 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8455 TCP(sport=1234, dport=1234))
8456 self.pg1.add_stream(p)
8457 self.pg_enable_capture(self.pg_interfaces)
8459 p = self.pg0.get_capture(1)
8462 self.assertEqual(packet[IPv6].src, remote_ip6)
8463 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8464 self.assertEqual(packet[IPv6].nh, 47)
8466 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8469 def test_hairpinning_unknown_proto(self):
8470 """ NAT64 translate packet with unknown protocol - hairpinning """
8472 client = self.pg0.remote_hosts[0]
8473 server = self.pg0.remote_hosts[1]
8474 server_tcp_in_port = 22
8475 server_tcp_out_port = 4022
8476 client_tcp_in_port = 1234
8477 client_tcp_out_port = 1235
8478 server_nat_ip = "10.0.0.100"
8479 client_nat_ip = "10.0.0.110"
8480 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8481 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8483 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8484 end_addr=client_nat_ip,
8487 flags = self.config_flags.NAT_IS_INSIDE
8488 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8489 sw_if_index=self.pg0.sw_if_index)
8490 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8491 sw_if_index=self.pg1.sw_if_index)
8493 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8494 o_addr=server_nat_ip,
8495 i_port=server_tcp_in_port,
8496 o_port=server_tcp_out_port,
8497 proto=IP_PROTOS.tcp, vrf_id=0,
8500 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8501 o_addr=server_nat_ip, i_port=0,
8503 proto=IP_PROTOS.gre, vrf_id=0,
8506 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8507 o_addr=client_nat_ip,
8508 i_port=client_tcp_in_port,
8509 o_port=client_tcp_out_port,
8510 proto=IP_PROTOS.tcp, vrf_id=0,
8514 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8515 IPv6(src=client.ip6, dst=server_nat_ip6) /
8516 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8517 self.pg0.add_stream(p)
8518 self.pg_enable_capture(self.pg_interfaces)
8520 p = self.pg0.get_capture(1)
8522 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8523 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8525 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8526 TCP(sport=1234, dport=1234))
8527 self.pg0.add_stream(p)
8528 self.pg_enable_capture(self.pg_interfaces)
8530 p = self.pg0.get_capture(1)
8533 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8534 self.assertEqual(packet[IPv6].dst, server.ip6)
8535 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8537 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8541 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8542 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8544 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8545 TCP(sport=1234, dport=1234))
8546 self.pg0.add_stream(p)
8547 self.pg_enable_capture(self.pg_interfaces)
8549 p = self.pg0.get_capture(1)
8552 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8553 self.assertEqual(packet[IPv6].dst, client.ip6)
8554 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8556 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8559 def test_one_armed_nat64(self):
8560 """ One armed NAT64 """
8562 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8566 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8567 end_addr=self.nat_addr,
8570 flags = self.config_flags.NAT_IS_INSIDE
8571 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8572 sw_if_index=self.pg3.sw_if_index)
8573 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8574 sw_if_index=self.pg3.sw_if_index)
8577 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8578 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8579 TCP(sport=12345, dport=80))
8580 self.pg3.add_stream(p)
8581 self.pg_enable_capture(self.pg_interfaces)
8583 capture = self.pg3.get_capture(1)
8588 self.assertEqual(ip.src, self.nat_addr)
8589 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8590 self.assertNotEqual(tcp.sport, 12345)
8591 external_port = tcp.sport
8592 self.assertEqual(tcp.dport, 80)
8593 self.assert_packet_checksums_valid(p)
8595 self.logger.error(ppp("Unexpected or invalid packet:", p))
8599 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8600 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8601 TCP(sport=80, dport=external_port))
8602 self.pg3.add_stream(p)
8603 self.pg_enable_capture(self.pg_interfaces)
8605 capture = self.pg3.get_capture(1)
8610 self.assertEqual(ip.src, remote_host_ip6)
8611 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8612 self.assertEqual(tcp.sport, 80)
8613 self.assertEqual(tcp.dport, 12345)
8614 self.assert_packet_checksums_valid(p)
8616 self.logger.error(ppp("Unexpected or invalid packet:", p))
8619 def test_frag_in_order(self):
8620 """ NAT64 translate fragments arriving in order """
8621 self.tcp_port_in = random.randint(1025, 65535)
8623 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8624 end_addr=self.nat_addr,
8627 flags = self.config_flags.NAT_IS_INSIDE
8628 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8629 sw_if_index=self.pg0.sw_if_index)
8630 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8631 sw_if_index=self.pg1.sw_if_index)
8633 reass = self.vapi.nat_reass_dump()
8634 reass_n_start = len(reass)
8638 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8639 self.tcp_port_in, 20, data)
8640 self.pg0.add_stream(pkts)
8641 self.pg_enable_capture(self.pg_interfaces)
8643 frags = self.pg1.get_capture(len(pkts))
8644 p = self.reass_frags_and_verify(frags,
8646 self.pg1.remote_ip4)
8647 self.assertEqual(p[TCP].dport, 20)
8648 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8649 self.tcp_port_out = p[TCP].sport
8650 self.assertEqual(data, p[Raw].load)
8653 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8654 pkts = self.create_stream_frag(self.pg1,
8659 self.pg1.add_stream(pkts)
8660 self.pg_enable_capture(self.pg_interfaces)
8662 frags = self.pg0.get_capture(len(pkts))
8663 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8664 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8665 self.assertEqual(p[TCP].sport, 20)
8666 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8667 self.assertEqual(data, p[Raw].load)
8669 reass = self.vapi.nat_reass_dump()
8670 reass_n_end = len(reass)
8672 self.assertEqual(reass_n_end - reass_n_start, 2)
8674 def test_reass_hairpinning(self):
8675 """ NAT64 fragments hairpinning """
8677 server = self.pg0.remote_hosts[1]
8678 server_in_port = random.randint(1025, 65535)
8679 server_out_port = random.randint(1025, 65535)
8680 client_in_port = random.randint(1025, 65535)
8681 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8682 nat_addr_ip6 = ip.src
8684 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8685 end_addr=self.nat_addr,
8688 flags = self.config_flags.NAT_IS_INSIDE
8689 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8690 sw_if_index=self.pg0.sw_if_index)
8691 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8692 sw_if_index=self.pg1.sw_if_index)
8694 # add static BIB entry for server
8695 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8696 o_addr=self.nat_addr,
8697 i_port=server_in_port,
8698 o_port=server_out_port,
8699 proto=IP_PROTOS.tcp, vrf_id=0,
8702 # send packet from host to server
8703 pkts = self.create_stream_frag_ip6(self.pg0,
8708 self.pg0.add_stream(pkts)
8709 self.pg_enable_capture(self.pg_interfaces)
8711 frags = self.pg0.get_capture(len(pkts))
8712 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8713 self.assertNotEqual(p[TCP].sport, client_in_port)
8714 self.assertEqual(p[TCP].dport, server_in_port)
8715 self.assertEqual(data, p[Raw].load)
8717 def test_frag_out_of_order(self):
8718 """ NAT64 translate fragments arriving out of order """
8719 self.tcp_port_in = random.randint(1025, 65535)
8721 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8722 end_addr=self.nat_addr,
8725 flags = self.config_flags.NAT_IS_INSIDE
8726 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8727 sw_if_index=self.pg0.sw_if_index)
8728 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8729 sw_if_index=self.pg1.sw_if_index)
8733 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8734 self.tcp_port_in, 20, data)
8736 self.pg0.add_stream(pkts)
8737 self.pg_enable_capture(self.pg_interfaces)
8739 frags = self.pg1.get_capture(len(pkts))
8740 p = self.reass_frags_and_verify(frags,
8742 self.pg1.remote_ip4)
8743 self.assertEqual(p[TCP].dport, 20)
8744 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8745 self.tcp_port_out = p[TCP].sport
8746 self.assertEqual(data, p[Raw].load)
8749 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8750 pkts = self.create_stream_frag(self.pg1,
8756 self.pg1.add_stream(pkts)
8757 self.pg_enable_capture(self.pg_interfaces)
8759 frags = self.pg0.get_capture(len(pkts))
8760 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8761 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8762 self.assertEqual(p[TCP].sport, 20)
8763 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8764 self.assertEqual(data, p[Raw].load)
8766 def test_interface_addr(self):
8767 """ Acquire NAT64 pool addresses from interface """
8768 self.vapi.nat64_add_del_interface_addr(
8770 sw_if_index=self.pg4.sw_if_index)
8772 # no address in NAT64 pool
8773 addresses = self.vapi.nat44_address_dump()
8774 self.assertEqual(0, len(addresses))
8776 # configure interface address and check NAT64 address pool
8777 self.pg4.config_ip4()
8778 addresses = self.vapi.nat64_pool_addr_dump()
8779 self.assertEqual(len(addresses), 1)
8781 self.assertEqual(str(addresses[0].address),
8784 # remove interface address and check NAT64 address pool
8785 self.pg4.unconfig_ip4()
8786 addresses = self.vapi.nat64_pool_addr_dump()
8787 self.assertEqual(0, len(addresses))
8789 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8790 def test_ipfix_max_bibs_sessions(self):
8791 """ IPFIX logging maximum session and BIB entries exceeded """
8794 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8798 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8799 end_addr=self.nat_addr,
8802 flags = self.config_flags.NAT_IS_INSIDE
8803 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8804 sw_if_index=self.pg0.sw_if_index)
8805 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8806 sw_if_index=self.pg1.sw_if_index)
8810 for i in range(0, max_bibs):
8811 src = "fd01:aa::%x" % (i)
8812 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8813 IPv6(src=src, dst=remote_host_ip6) /
8814 TCP(sport=12345, dport=80))
8816 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8817 IPv6(src=src, dst=remote_host_ip6) /
8818 TCP(sport=12345, dport=22))
8820 self.pg0.add_stream(pkts)
8821 self.pg_enable_capture(self.pg_interfaces)
8823 self.pg1.get_capture(max_sessions)
8825 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8826 src_address=self.pg3.local_ip4n,
8828 template_interval=10)
8829 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8830 src_port=self.ipfix_src_port,
8833 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8834 IPv6(src=src, dst=remote_host_ip6) /
8835 TCP(sport=12345, dport=25))
8836 self.pg0.add_stream(p)
8837 self.pg_enable_capture(self.pg_interfaces)
8839 self.pg1.assert_nothing_captured()
8841 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8842 capture = self.pg3.get_capture(9)
8843 ipfix = IPFIXDecoder()
8844 # first load template
8846 self.assertTrue(p.haslayer(IPFIX))
8847 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8848 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8849 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8850 self.assertEqual(p[UDP].dport, 4739)
8851 self.assertEqual(p[IPFIX].observationDomainID,
8852 self.ipfix_domain_id)
8853 if p.haslayer(Template):
8854 ipfix.add_template(p.getlayer(Template))
8855 # verify events in data set
8857 if p.haslayer(Data):
8858 data = ipfix.decode_data_set(p.getlayer(Set))
8859 self.verify_ipfix_max_sessions(data, max_sessions)
8861 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8862 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8863 TCP(sport=12345, dport=80))
8864 self.pg0.add_stream(p)
8865 self.pg_enable_capture(self.pg_interfaces)
8867 self.pg1.assert_nothing_captured()
8869 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8870 capture = self.pg3.get_capture(1)
8871 # verify events in data set
8873 self.assertTrue(p.haslayer(IPFIX))
8874 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8875 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8876 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8877 self.assertEqual(p[UDP].dport, 4739)
8878 self.assertEqual(p[IPFIX].observationDomainID,
8879 self.ipfix_domain_id)
8880 if p.haslayer(Data):
8881 data = ipfix.decode_data_set(p.getlayer(Set))
8882 self.verify_ipfix_max_bibs(data, max_bibs)
8884 def test_ipfix_max_frags(self):
8885 """ IPFIX logging maximum fragments pending reassembly exceeded """
8886 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8887 end_addr=self.nat_addr,
8890 flags = self.config_flags.NAT_IS_INSIDE
8891 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8892 sw_if_index=self.pg0.sw_if_index)
8893 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8894 sw_if_index=self.pg1.sw_if_index)
8895 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
8896 drop_frag=0, is_ip6=1)
8897 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8898 src_address=self.pg3.local_ip4n,
8900 template_interval=10)
8901 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8902 src_port=self.ipfix_src_port,
8906 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8907 self.tcp_port_in, 20, data)
8909 self.pg0.add_stream(pkts)
8910 self.pg_enable_capture(self.pg_interfaces)
8912 self.pg1.assert_nothing_captured()
8914 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8915 capture = self.pg3.get_capture(9)
8916 ipfix = IPFIXDecoder()
8917 # first load template
8919 self.assertTrue(p.haslayer(IPFIX))
8920 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8921 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8922 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8923 self.assertEqual(p[UDP].dport, 4739)
8924 self.assertEqual(p[IPFIX].observationDomainID,
8925 self.ipfix_domain_id)
8926 if p.haslayer(Template):
8927 ipfix.add_template(p.getlayer(Template))
8928 # verify events in data set
8930 if p.haslayer(Data):
8931 data = ipfix.decode_data_set(p.getlayer(Set))
8932 self.verify_ipfix_max_fragments_ip6(data, 1,
8933 self.pg0.remote_ip6n)
8935 def test_ipfix_bib_ses(self):
8936 """ IPFIX logging NAT64 BIB/session create and delete events """
8937 self.tcp_port_in = random.randint(1025, 65535)
8938 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8942 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8943 end_addr=self.nat_addr,
8946 flags = self.config_flags.NAT_IS_INSIDE
8947 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8948 sw_if_index=self.pg0.sw_if_index)
8949 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8950 sw_if_index=self.pg1.sw_if_index)
8951 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8952 src_address=self.pg3.local_ip4n,
8954 template_interval=10)
8955 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8956 src_port=self.ipfix_src_port,
8960 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8961 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8962 TCP(sport=self.tcp_port_in, dport=25))
8963 self.pg0.add_stream(p)
8964 self.pg_enable_capture(self.pg_interfaces)
8966 p = self.pg1.get_capture(1)
8967 self.tcp_port_out = p[0][TCP].sport
8968 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8969 capture = self.pg3.get_capture(10)
8970 ipfix = IPFIXDecoder()
8971 # first load template
8973 self.assertTrue(p.haslayer(IPFIX))
8974 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8975 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8976 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8977 self.assertEqual(p[UDP].dport, 4739)
8978 self.assertEqual(p[IPFIX].observationDomainID,
8979 self.ipfix_domain_id)
8980 if p.haslayer(Template):
8981 ipfix.add_template(p.getlayer(Template))
8982 # verify events in data set
8984 if p.haslayer(Data):
8985 data = ipfix.decode_data_set(p.getlayer(Set))
8986 if scapy.compat.orb(data[0][230]) == 10:
8987 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8988 elif scapy.compat.orb(data[0][230]) == 6:
8989 self.verify_ipfix_nat64_ses(data,
8991 self.pg0.remote_ip6n,
8992 self.pg1.remote_ip4,
8995 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8998 self.pg_enable_capture(self.pg_interfaces)
8999 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9000 end_addr=self.nat_addr,
9003 self.vapi.cli("ipfix flush") # FIXME this should be an API call
9004 capture = self.pg3.get_capture(2)
9005 # verify events in data set
9007 self.assertTrue(p.haslayer(IPFIX))
9008 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9009 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9010 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9011 self.assertEqual(p[UDP].dport, 4739)
9012 self.assertEqual(p[IPFIX].observationDomainID,
9013 self.ipfix_domain_id)
9014 if p.haslayer(Data):
9015 data = ipfix.decode_data_set(p.getlayer(Set))
9016 if scapy.compat.orb(data[0][230]) == 11:
9017 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
9018 elif scapy.compat.orb(data[0][230]) == 7:
9019 self.verify_ipfix_nat64_ses(data,
9021 self.pg0.remote_ip6n,
9022 self.pg1.remote_ip4,
9025 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9027 def test_syslog_sess(self):
9028 """ Test syslog session creation and deletion """
9029 self.tcp_port_in = random.randint(1025, 65535)
9030 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9034 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9035 end_addr=self.nat_addr,
9038 flags = self.config_flags.NAT_IS_INSIDE
9039 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9040 sw_if_index=self.pg0.sw_if_index)
9041 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9042 sw_if_index=self.pg1.sw_if_index)
9043 self.vapi.syslog_set_filter(
9044 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9045 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
9047 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9048 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9049 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9050 self.pg0.add_stream(p)
9051 self.pg_enable_capture(self.pg_interfaces)
9053 p = self.pg1.get_capture(1)
9054 self.tcp_port_out = p[0][TCP].sport
9055 capture = self.pg3.get_capture(1)
9056 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9058 self.pg_enable_capture(self.pg_interfaces)
9060 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9061 end_addr=self.nat_addr,
9064 capture = self.pg3.get_capture(1)
9065 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9067 def nat64_get_ses_num(self):
9069 Return number of active NAT64 sessions.
9071 st = self.vapi.nat64_st_dump(proto=255)
9074 def clear_nat64(self):
9076 Clear NAT64 configuration.
9078 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9079 src_port=self.ipfix_src_port,
9081 self.ipfix_src_port = 4739
9082 self.ipfix_domain_id = 1
9084 self.vapi.syslog_set_filter(
9085 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9087 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9088 tcp_transitory=240, icmp=60)
9090 interfaces = self.vapi.nat64_interface_dump()
9091 for intf in interfaces:
9092 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9093 sw_if_index=intf.sw_if_index)
9095 bib = self.vapi.nat64_bib_dump(proto=255)
9097 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9098 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9106 adresses = self.vapi.nat64_pool_addr_dump()
9107 for addr in adresses:
9108 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9109 end_addr=addr.address,
9113 prefixes = self.vapi.nat64_prefix_dump()
9114 for prefix in prefixes:
9115 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9116 vrf_id=prefix.vrf_id, is_add=0)
9118 bibs = self.statistics.get_counter('/nat64/total-bibs')
9119 self.assertEqual(bibs[0][0], 0)
9120 sessions = self.statistics.get_counter('/nat64/total-sessions')
9121 self.assertEqual(sessions[0][0], 0)
9124 super(TestNAT64, self).tearDown()
9125 if not self.vpp_dead:
9128 def show_commands_at_teardown(self):
9129 self.logger.info(self.vapi.cli("show nat64 pool"))
9130 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9131 self.logger.info(self.vapi.cli("show nat64 prefix"))
9132 self.logger.info(self.vapi.cli("show nat64 bib all"))
9133 self.logger.info(self.vapi.cli("show nat64 session table all"))
9134 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
9137 class TestDSlite(MethodHolder):
9138 """ DS-Lite Test Cases """
9141 def setUpClass(cls):
9142 super(TestDSlite, cls).setUpClass()
9145 cls.nat_addr = '10.0.0.3'
9147 cls.create_pg_interfaces(range(3))
9149 cls.pg0.config_ip4()
9150 cls.pg0.resolve_arp()
9152 cls.pg1.config_ip6()
9153 cls.pg1.generate_remote_hosts(2)
9154 cls.pg1.configure_ipv6_neighbors()
9156 cls.pg2.config_ip4()
9157 cls.pg2.resolve_arp()
9160 super(TestDSlite, cls).tearDownClass()
9164 def tearDownClass(cls):
9165 super(TestDSlite, cls).tearDownClass()
9167 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
9169 message = data.decode('utf-8')
9171 message = SyslogMessage.parse(message)
9172 except ParseError as e:
9173 self.logger.error(e)
9175 self.assertEqual(message.severity, SyslogSeverity.info)
9176 self.assertEqual(message.appname, 'NAT')
9177 self.assertEqual(message.msgid, 'APMADD')
9178 sd_params = message.sd.get('napmap')
9179 self.assertTrue(sd_params is not None)
9180 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
9181 self.assertEqual(sd_params.get('ISADDR'), isaddr)
9182 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
9183 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
9184 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
9185 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
9186 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
9187 self.assertTrue(sd_params.get('SSUBIX') is not None)
9188 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
9190 def test_dslite(self):
9191 """ Test DS-Lite """
9192 nat_config = self.vapi.nat_show_config()
9193 self.assertEqual(0, nat_config.dslite_ce)
9195 self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr,
9196 end_addr=self.nat_addr,
9198 aftr_ip4 = '192.0.0.1'
9199 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
9200 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
9201 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
9204 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9205 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
9206 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9207 UDP(sport=20000, dport=10000))
9208 self.pg1.add_stream(p)
9209 self.pg_enable_capture(self.pg_interfaces)
9211 capture = self.pg0.get_capture(1)
9212 capture = capture[0]
9213 self.assertFalse(capture.haslayer(IPv6))
9214 self.assertEqual(capture[IP].src, self.nat_addr)
9215 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9216 self.assertNotEqual(capture[UDP].sport, 20000)
9217 self.assertEqual(capture[UDP].dport, 10000)
9218 self.assert_packet_checksums_valid(capture)
9219 out_port = capture[UDP].sport
9220 capture = self.pg2.get_capture(1)
9221 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
9222 20000, self.nat_addr, out_port,
9223 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
9225 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9226 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9227 UDP(sport=10000, dport=out_port))
9228 self.pg0.add_stream(p)
9229 self.pg_enable_capture(self.pg_interfaces)
9231 capture = self.pg1.get_capture(1)
9232 capture = capture[0]
9233 self.assertEqual(capture[IPv6].src, aftr_ip6)
9234 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9235 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9236 self.assertEqual(capture[IP].dst, '192.168.1.1')
9237 self.assertEqual(capture[UDP].sport, 10000)
9238 self.assertEqual(capture[UDP].dport, 20000)
9239 self.assert_packet_checksums_valid(capture)
9242 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9243 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9244 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9245 TCP(sport=20001, dport=10001))
9246 self.pg1.add_stream(p)
9247 self.pg_enable_capture(self.pg_interfaces)
9249 capture = self.pg0.get_capture(1)
9250 capture = capture[0]
9251 self.assertFalse(capture.haslayer(IPv6))
9252 self.assertEqual(capture[IP].src, self.nat_addr)
9253 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9254 self.assertNotEqual(capture[TCP].sport, 20001)
9255 self.assertEqual(capture[TCP].dport, 10001)
9256 self.assert_packet_checksums_valid(capture)
9257 out_port = capture[TCP].sport
9259 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9260 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9261 TCP(sport=10001, dport=out_port))
9262 self.pg0.add_stream(p)
9263 self.pg_enable_capture(self.pg_interfaces)
9265 capture = self.pg1.get_capture(1)
9266 capture = capture[0]
9267 self.assertEqual(capture[IPv6].src, aftr_ip6)
9268 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9269 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9270 self.assertEqual(capture[IP].dst, '192.168.1.1')
9271 self.assertEqual(capture[TCP].sport, 10001)
9272 self.assertEqual(capture[TCP].dport, 20001)
9273 self.assert_packet_checksums_valid(capture)
9276 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9277 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9278 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9279 ICMP(id=4000, type='echo-request'))
9280 self.pg1.add_stream(p)
9281 self.pg_enable_capture(self.pg_interfaces)
9283 capture = self.pg0.get_capture(1)
9284 capture = capture[0]
9285 self.assertFalse(capture.haslayer(IPv6))
9286 self.assertEqual(capture[IP].src, self.nat_addr)
9287 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9288 self.assertNotEqual(capture[ICMP].id, 4000)
9289 self.assert_packet_checksums_valid(capture)
9290 out_id = capture[ICMP].id
9292 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9293 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9294 ICMP(id=out_id, type='echo-reply'))
9295 self.pg0.add_stream(p)
9296 self.pg_enable_capture(self.pg_interfaces)
9298 capture = self.pg1.get_capture(1)
9299 capture = capture[0]
9300 self.assertEqual(capture[IPv6].src, aftr_ip6)
9301 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9302 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9303 self.assertEqual(capture[IP].dst, '192.168.1.1')
9304 self.assertEqual(capture[ICMP].id, 4000)
9305 self.assert_packet_checksums_valid(capture)
9307 # ping DS-Lite AFTR tunnel endpoint address
9308 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9309 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
9310 ICMPv6EchoRequest())
9311 self.pg1.add_stream(p)
9312 self.pg_enable_capture(self.pg_interfaces)
9314 capture = self.pg1.get_capture(1)
9315 capture = capture[0]
9316 self.assertEqual(capture[IPv6].src, aftr_ip6)
9317 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9318 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9320 b4s = self.statistics.get_counter('/dslite/total-b4s')
9321 self.assertEqual(b4s[0][0], 2)
9322 sessions = self.statistics.get_counter('/dslite/total-sessions')
9323 self.assertEqual(sessions[0][0], 3)
9326 super(TestDSlite, self).tearDown()
9328 def show_commands_at_teardown(self):
9329 self.logger.info(self.vapi.cli("show dslite pool"))
9331 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9332 self.logger.info(self.vapi.cli("show dslite sessions"))
9335 class TestDSliteCE(MethodHolder):
9336 """ DS-Lite CE Test Cases """
9339 def setUpConstants(cls):
9340 super(TestDSliteCE, cls).setUpConstants()
9341 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
9344 def setUpClass(cls):
9345 super(TestDSliteCE, cls).setUpClass()
9348 cls.create_pg_interfaces(range(2))
9350 cls.pg0.config_ip4()
9351 cls.pg0.resolve_arp()
9353 cls.pg1.config_ip6()
9354 cls.pg1.generate_remote_hosts(1)
9355 cls.pg1.configure_ipv6_neighbors()
9358 super(TestDSliteCE, cls).tearDownClass()
9362 def tearDownClass(cls):
9363 super(TestDSliteCE, cls).tearDownClass()
9365 def test_dslite_ce(self):
9366 """ Test DS-Lite CE """
9368 nat_config = self.vapi.nat_show_config()
9369 self.assertEqual(1, nat_config.dslite_ce)
9371 b4_ip4 = '192.0.0.2'
9372 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
9373 self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6)
9375 aftr_ip4 = '192.0.0.1'
9376 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
9377 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
9378 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
9380 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
9381 dst_address_length=128,
9382 next_hop_address=self.pg1.remote_ip6n,
9383 next_hop_sw_if_index=self.pg1.sw_if_index,
9387 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9388 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
9389 UDP(sport=10000, dport=20000))
9390 self.pg0.add_stream(p)
9391 self.pg_enable_capture(self.pg_interfaces)
9393 capture = self.pg1.get_capture(1)
9394 capture = capture[0]
9395 self.assertEqual(capture[IPv6].src, b4_ip6)
9396 self.assertEqual(capture[IPv6].dst, aftr_ip6)
9397 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9398 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
9399 self.assertEqual(capture[UDP].sport, 10000)
9400 self.assertEqual(capture[UDP].dport, 20000)
9401 self.assert_packet_checksums_valid(capture)
9404 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9405 IPv6(dst=b4_ip6, src=aftr_ip6) /
9406 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
9407 UDP(sport=20000, dport=10000))
9408 self.pg1.add_stream(p)
9409 self.pg_enable_capture(self.pg_interfaces)
9411 capture = self.pg0.get_capture(1)
9412 capture = capture[0]
9413 self.assertFalse(capture.haslayer(IPv6))
9414 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
9415 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9416 self.assertEqual(capture[UDP].sport, 20000)
9417 self.assertEqual(capture[UDP].dport, 10000)
9418 self.assert_packet_checksums_valid(capture)
9420 # ping DS-Lite B4 tunnel endpoint address
9421 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9422 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
9423 ICMPv6EchoRequest())
9424 self.pg1.add_stream(p)
9425 self.pg_enable_capture(self.pg_interfaces)
9427 capture = self.pg1.get_capture(1)
9428 capture = capture[0]
9429 self.assertEqual(capture[IPv6].src, b4_ip6)
9430 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9431 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9434 super(TestDSliteCE, self).tearDown()
9436 def show_commands_at_teardown(self):
9438 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9440 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
9443 class TestNAT66(MethodHolder):
9444 """ NAT66 Test Cases """
9447 def setUpClass(cls):
9448 super(TestNAT66, cls).setUpClass()
9451 cls.nat_addr = 'fd01:ff::2'
9453 cls.create_pg_interfaces(range(2))
9454 cls.interfaces = list(cls.pg_interfaces)
9456 for i in cls.interfaces:
9459 i.configure_ipv6_neighbors()
9462 super(TestNAT66, cls).tearDownClass()
9466 def tearDownClass(cls):
9467 super(TestNAT66, cls).tearDownClass()
9469 def test_static(self):
9470 """ 1:1 NAT66 test """
9471 flags = self.config_flags.NAT_IS_INSIDE
9472 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9473 sw_if_index=self.pg0.sw_if_index)
9474 self.vapi.nat66_add_del_interface(is_add=1,
9475 sw_if_index=self.pg1.sw_if_index)
9476 self.vapi.nat66_add_del_static_mapping(
9477 local_ip_address=self.pg0.remote_ip6n,
9478 external_ip_address=self.nat_addr,
9483 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9484 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9487 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9488 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9491 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9492 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9493 ICMPv6EchoRequest())
9495 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9496 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9497 GRE() / IP() / TCP())
9499 self.pg0.add_stream(pkts)
9500 self.pg_enable_capture(self.pg_interfaces)
9502 capture = self.pg1.get_capture(len(pkts))
9503 for packet in capture:
9505 self.assertEqual(packet[IPv6].src, self.nat_addr)
9506 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9507 self.assert_packet_checksums_valid(packet)
9509 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9514 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9515 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9518 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9519 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9522 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9523 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9526 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9527 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9528 GRE() / IP() / TCP())
9530 self.pg1.add_stream(pkts)
9531 self.pg_enable_capture(self.pg_interfaces)
9533 capture = self.pg0.get_capture(len(pkts))
9534 for packet in capture:
9536 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9537 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9538 self.assert_packet_checksums_valid(packet)
9540 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9543 sm = self.vapi.nat66_static_mapping_dump()
9544 self.assertEqual(len(sm), 1)
9545 self.assertEqual(sm[0].total_pkts, 8)
9547 def test_check_no_translate(self):
9548 """ NAT66 translate only when egress interface is outside interface """
9549 flags = self.config_flags.NAT_IS_INSIDE
9550 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9551 sw_if_index=self.pg0.sw_if_index)
9552 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9553 sw_if_index=self.pg1.sw_if_index)
9554 self.vapi.nat66_add_del_static_mapping(
9555 local_ip_address=self.pg0.remote_ip6n,
9556 external_ip_address=self.nat_addr,
9560 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9561 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9563 self.pg0.add_stream([p])
9564 self.pg_enable_capture(self.pg_interfaces)
9566 capture = self.pg1.get_capture(1)
9569 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9570 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9572 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9575 def clear_nat66(self):
9577 Clear NAT66 configuration.
9579 interfaces = self.vapi.nat66_interface_dump()
9580 for intf in interfaces:
9581 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9582 sw_if_index=intf.sw_if_index)
9584 static_mappings = self.vapi.nat66_static_mapping_dump()
9585 for sm in static_mappings:
9586 self.vapi.nat66_add_del_static_mapping(
9587 local_ip_address=sm.local_ip_address,
9588 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9592 super(TestNAT66, self).tearDown()
9595 def show_commands_at_teardown(self):
9596 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9597 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9600 if __name__ == '__main__':
9601 unittest.main(testRunner=VppTestRunner)