12 from framework import tag_fixme_vpp_workers
13 from framework import VppTestCase, VppTestRunner
14 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
15 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
16 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
18 from scapy.data import IP_PROTOS
19 from scapy.layers.inet import IP, TCP, UDP, ICMP
20 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
21 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
22 from scapy.layers.l2 import Ether, ARP, GRE
23 from scapy.packet import Raw
24 from syslog_rfc5424_parser import SyslogMessage, ParseError
25 from syslog_rfc5424_parser.constants import SyslogSeverity
27 from vpp_ip_route import VppIpRoute, VppRoutePath
28 from vpp_neighbor import VppNeighbor
29 from vpp_papi import VppEnum
32 # NAT HA protocol event data
35 fields_desc = [ByteEnumField("event_type", None,
36 {1: "add", 2: "del", 3: "refresh"}),
37 ByteEnumField("protocol", None,
38 {0: "other", 1: "udp", 2: "tcp", 3: "icmp"}),
39 ShortField("flags", 0),
40 IPField("in_addr", None),
41 IPField("out_addr", None),
42 ShortField("in_port", None),
43 ShortField("out_port", None),
44 IPField("eh_addr", None),
45 IPField("ehn_addr", None),
46 ShortField("eh_port", None),
47 ShortField("ehn_port", None),
48 IntField("fib_index", None),
49 IntField("total_pkts", 0),
50 LongField("total_bytes", 0)]
52 def extract_padding(self, s):
56 # NAT HA protocol header
57 class HANATStateSync(Packet):
58 name = "HA NAT state sync"
59 fields_desc = [XByteField("version", 1),
60 FlagsField("flags", 0, 8, ['ACK']),
61 FieldLenField("count", None, count_of="events"),
62 IntField("sequence_number", 1),
63 IntField("thread_index", 0),
64 PacketListField("events", [], Event,
65 count_from=lambda pkt: pkt.count)]
68 class MethodHolder(VppTestCase):
69 """ NAT create capture and verify method holder """
72 def config_flags(self):
73 return VppEnum.vl_api_nat44_ei_config_flags_t
76 def SYSLOG_SEVERITY(self):
77 return VppEnum.vl_api_syslog_severity_t
79 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
80 local_port=0, external_port=0, vrf_id=0,
81 is_add=1, external_sw_if_index=0xFFFFFFFF,
82 proto=0, tag="", flags=0):
84 Add/delete NAT44EI static mapping
86 :param local_ip: Local IP address
87 :param external_ip: External IP address
88 :param local_port: Local port number (Optional)
89 :param external_port: External port number (Optional)
90 :param vrf_id: VRF ID (Default 0)
91 :param is_add: 1 if add, 0 if delete (Default add)
92 :param external_sw_if_index: External interface instead of IP address
93 :param proto: IP protocol (Mandatory if port specified)
94 :param tag: Opaque string tag
95 :param flags: NAT configuration flags
98 if not (local_port and external_port):
99 flags |= self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
101 self.vapi.nat44_ei_add_del_static_mapping(
103 local_ip_address=local_ip,
104 external_ip_address=external_ip,
105 external_sw_if_index=external_sw_if_index,
106 local_port=local_port,
107 external_port=external_port,
108 vrf_id=vrf_id, protocol=proto,
112 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF):
114 Add/delete NAT44EI address
116 :param ip: IP address
117 :param is_add: 1 if add, 0 if delete (Default add)
119 self.vapi.nat44_ei_add_del_address_range(first_ip_address=ip,
124 def create_routes_and_neigbors(self):
125 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
126 [VppRoutePath(self.pg7.remote_ip4,
127 self.pg7.sw_if_index)])
128 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
129 [VppRoutePath(self.pg8.remote_ip4,
130 self.pg8.sw_if_index)])
134 n1 = VppNeighbor(self,
135 self.pg7.sw_if_index,
139 n2 = VppNeighbor(self,
140 self.pg8.sw_if_index,
147 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
149 Create packet stream for inside network
151 :param in_if: Inside interface
152 :param out_if: Outside interface
153 :param dst_ip: Destination address
154 :param ttl: TTL of generated packets
157 dst_ip = out_if.remote_ip4
161 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
162 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
163 TCP(sport=self.tcp_port_in, dport=20))
167 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
168 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
169 UDP(sport=self.udp_port_in, dport=20))
173 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
174 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
175 ICMP(id=self.icmp_id_in, type='echo-request'))
180 def compose_ip6(self, ip4, pref, plen):
182 Compose IPv4-embedded IPv6 addresses
184 :param ip4: IPv4 address
185 :param pref: IPv6 prefix
186 :param plen: IPv6 prefix length
187 :returns: IPv4-embedded IPv6 addresses
189 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
190 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
205 pref_n[10] = ip4_n[3]
209 pref_n[10] = ip4_n[2]
210 pref_n[11] = ip4_n[3]
213 pref_n[10] = ip4_n[1]
214 pref_n[11] = ip4_n[2]
215 pref_n[12] = ip4_n[3]
217 pref_n[12] = ip4_n[0]
218 pref_n[13] = ip4_n[1]
219 pref_n[14] = ip4_n[2]
220 pref_n[15] = ip4_n[3]
221 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
222 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
224 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
225 use_inside_ports=False):
227 Create packet stream for outside network
229 :param out_if: Outside interface
230 :param dst_ip: Destination IP address (Default use global NAT address)
231 :param ttl: TTL of generated packets
232 :param use_inside_ports: Use inside NAT ports as destination ports
233 instead of outside ports
236 dst_ip = self.nat_addr
237 if not use_inside_ports:
238 tcp_port = self.tcp_port_out
239 udp_port = self.udp_port_out
240 icmp_id = self.icmp_id_out
242 tcp_port = self.tcp_port_in
243 udp_port = self.udp_port_in
244 icmp_id = self.icmp_id_in
247 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
248 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
249 TCP(dport=tcp_port, sport=20))
253 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
254 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
255 UDP(dport=udp_port, sport=20))
259 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
260 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
261 ICMP(id=icmp_id, type='echo-reply'))
266 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
268 Create packet stream for outside network
270 :param out_if: Outside interface
271 :param dst_ip: Destination IP address (Default use global NAT address)
272 :param hl: HL of generated packets
276 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
277 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
278 TCP(dport=self.tcp_port_out, sport=20))
282 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
283 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
284 UDP(dport=self.udp_port_out, sport=20))
288 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
289 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
290 ICMPv6EchoReply(id=self.icmp_id_out))
295 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
296 dst_ip=None, is_ip6=False, ignore_port=False):
298 Verify captured packets on outside network
300 :param capture: Captured packets
301 :param nat_ip: Translated IP address (Default use global NAT address)
302 :param same_port: Source port number is not translated (Default False)
303 :param dst_ip: Destination IP address (Default do not verify)
304 :param is_ip6: If L3 protocol is IPv6 (Default False)
308 ICMP46 = ICMPv6EchoRequest
313 nat_ip = self.nat_addr
314 for packet in capture:
317 self.assert_packet_checksums_valid(packet)
318 self.assertEqual(packet[IP46].src, nat_ip)
319 if dst_ip is not None:
320 self.assertEqual(packet[IP46].dst, dst_ip)
321 if packet.haslayer(TCP):
325 packet[TCP].sport, self.tcp_port_in)
328 packet[TCP].sport, self.tcp_port_in)
329 self.tcp_port_out = packet[TCP].sport
330 self.assert_packet_checksums_valid(packet)
331 elif packet.haslayer(UDP):
335 packet[UDP].sport, self.udp_port_in)
338 packet[UDP].sport, self.udp_port_in)
339 self.udp_port_out = packet[UDP].sport
344 packet[ICMP46].id, self.icmp_id_in)
347 packet[ICMP46].id, self.icmp_id_in)
348 self.icmp_id_out = packet[ICMP46].id
349 self.assert_packet_checksums_valid(packet)
351 self.logger.error(ppp("Unexpected or invalid packet "
352 "(outside network):", packet))
355 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
358 Verify captured packets on outside network
360 :param capture: Captured packets
361 :param nat_ip: Translated IP address
362 :param same_port: Source port number is not translated (Default False)
363 :param dst_ip: Destination IP address (Default do not verify)
365 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
368 def verify_capture_in(self, capture, in_if):
370 Verify captured packets on inside network
372 :param capture: Captured packets
373 :param in_if: Inside interface
375 for packet in capture:
377 self.assert_packet_checksums_valid(packet)
378 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
379 if packet.haslayer(TCP):
380 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
381 elif packet.haslayer(UDP):
382 self.assertEqual(packet[UDP].dport, self.udp_port_in)
384 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
386 self.logger.error(ppp("Unexpected or invalid packet "
387 "(inside network):", packet))
390 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
392 Verify captured packet that don't have to be translated
394 :param capture: Captured packets
395 :param ingress_if: Ingress interface
396 :param egress_if: Egress interface
398 for packet in capture:
400 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
401 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
402 if packet.haslayer(TCP):
403 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
404 elif packet.haslayer(UDP):
405 self.assertEqual(packet[UDP].sport, self.udp_port_in)
407 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
409 self.logger.error(ppp("Unexpected or invalid packet "
410 "(inside network):", packet))
413 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
416 Verify captured packets with ICMP errors on outside network
418 :param capture: Captured packets
419 :param src_ip: Translated IP address or IP address of VPP
420 (Default use global NAT address)
421 :param icmp_type: Type of error ICMP packet
422 we are expecting (Default 11)
425 src_ip = self.nat_addr
426 for packet in capture:
428 self.assertEqual(packet[IP].src, src_ip)
429 self.assertEqual(packet.haslayer(ICMP), 1)
431 self.assertEqual(icmp.type, icmp_type)
432 self.assertTrue(icmp.haslayer(IPerror))
433 inner_ip = icmp[IPerror]
434 if inner_ip.haslayer(TCPerror):
435 self.assertEqual(inner_ip[TCPerror].dport,
437 elif inner_ip.haslayer(UDPerror):
438 self.assertEqual(inner_ip[UDPerror].dport,
441 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
443 self.logger.error(ppp("Unexpected or invalid packet "
444 "(outside network):", packet))
447 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
449 Verify captured packets with ICMP errors on inside network
451 :param capture: Captured packets
452 :param in_if: Inside interface
453 :param icmp_type: Type of error ICMP packet
454 we are expecting (Default 11)
456 for packet in capture:
458 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
459 self.assertEqual(packet.haslayer(ICMP), 1)
461 self.assertEqual(icmp.type, icmp_type)
462 self.assertTrue(icmp.haslayer(IPerror))
463 inner_ip = icmp[IPerror]
464 if inner_ip.haslayer(TCPerror):
465 self.assertEqual(inner_ip[TCPerror].sport,
467 elif inner_ip.haslayer(UDPerror):
468 self.assertEqual(inner_ip[UDPerror].sport,
471 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
473 self.logger.error(ppp("Unexpected or invalid packet "
474 "(inside network):", packet))
477 def create_stream_frag(self, src_if, dst, sport, dport, data,
478 proto=IP_PROTOS.tcp, echo_reply=False):
480 Create fragmented packet stream
482 :param src_if: Source interface
483 :param dst: Destination IPv4 address
484 :param sport: Source port
485 :param dport: Destination port
486 :param data: Payload data
487 :param proto: protocol (TCP, UDP, ICMP)
488 :param echo_reply: use echo_reply if protocol is ICMP
491 if proto == IP_PROTOS.tcp:
492 p = (IP(src=src_if.remote_ip4, dst=dst) /
493 TCP(sport=sport, dport=dport) /
495 p = p.__class__(scapy.compat.raw(p))
496 chksum = p[TCP].chksum
497 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
498 elif proto == IP_PROTOS.udp:
499 proto_header = UDP(sport=sport, dport=dport)
500 elif proto == IP_PROTOS.icmp:
502 proto_header = ICMP(id=sport, type='echo-request')
504 proto_header = ICMP(id=sport, type='echo-reply')
506 raise Exception("Unsupported protocol")
507 id = random.randint(0, 65535)
509 if proto == IP_PROTOS.tcp:
512 raw = Raw(data[0:16])
513 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
514 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
518 if proto == IP_PROTOS.tcp:
519 raw = Raw(data[4:20])
521 raw = Raw(data[16:32])
522 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
523 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
527 if proto == IP_PROTOS.tcp:
531 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
532 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
538 def reass_frags_and_verify(self, frags, src, dst):
540 Reassemble and verify fragmented packet
542 :param frags: Captured fragments
543 :param src: Source IPv4 address to verify
544 :param dst: Destination IPv4 address to verify
546 :returns: Reassembled IPv4 packet
550 self.assertEqual(p[IP].src, src)
551 self.assertEqual(p[IP].dst, dst)
552 self.assert_ip_checksum_valid(p)
553 buffer.seek(p[IP].frag * 8)
554 buffer.write(bytes(p[IP].payload))
555 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
556 proto=frags[0][IP].proto)
557 if ip.proto == IP_PROTOS.tcp:
558 p = (ip / TCP(buffer.getvalue()))
559 self.logger.debug(ppp("Reassembled:", p))
560 self.assert_tcp_checksum_valid(p)
561 elif ip.proto == IP_PROTOS.udp:
562 p = (ip / UDP(buffer.getvalue()[:8]) /
563 Raw(buffer.getvalue()[8:]))
564 elif ip.proto == IP_PROTOS.icmp:
565 p = (ip / ICMP(buffer.getvalue()))
568 def verify_ipfix_nat44_ses(self, data):
570 Verify IPFIX NAT44EI session create/delete event
572 :param data: Decoded IPFIX data records
574 nat44_ses_create_num = 0
575 nat44_ses_delete_num = 0
576 self.assertEqual(6, len(data))
579 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
580 if scapy.compat.orb(record[230]) == 4:
581 nat44_ses_create_num += 1
583 nat44_ses_delete_num += 1
585 self.assertEqual(self.pg0.remote_ip4,
586 str(ipaddress.IPv4Address(record[8])))
587 # postNATSourceIPv4Address
588 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
591 self.assertEqual(struct.pack("!I", 0), record[234])
592 # protocolIdentifier/sourceTransportPort
593 # /postNAPTSourceTransportPort
594 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
595 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
596 self.assertEqual(struct.pack("!H", self.icmp_id_out),
598 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
599 self.assertEqual(struct.pack("!H", self.tcp_port_in),
601 self.assertEqual(struct.pack("!H", self.tcp_port_out),
603 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
604 self.assertEqual(struct.pack("!H", self.udp_port_in),
606 self.assertEqual(struct.pack("!H", self.udp_port_out),
609 self.fail("Invalid protocol")
610 self.assertEqual(3, nat44_ses_create_num)
611 self.assertEqual(3, nat44_ses_delete_num)
613 def verify_ipfix_addr_exhausted(self, data):
614 self.assertEqual(1, len(data))
617 self.assertEqual(scapy.compat.orb(record[230]), 3)
619 self.assertEqual(struct.pack("!I", 0), record[283])
621 def verify_ipfix_max_sessions(self, data, limit):
622 self.assertEqual(1, len(data))
625 self.assertEqual(scapy.compat.orb(record[230]), 13)
626 # natQuotaExceededEvent
627 self.assertEqual(struct.pack("I", 1), record[466])
629 self.assertEqual(struct.pack("I", limit), record[471])
631 def verify_no_nat44_user(self):
632 """ Verify that there is no NAT44EI user """
633 users = self.vapi.nat44_ei_user_dump()
634 self.assertEqual(len(users), 0)
635 users = self.statistics.get_counter('/nat44-ei/total-users')
636 self.assertEqual(users[0][0], 0)
637 sessions = self.statistics.get_counter('/nat44-ei/total-sessions')
638 self.assertEqual(sessions[0][0], 0)
640 def verify_syslog_apmap(self, data, is_add=True):
641 message = data.decode('utf-8')
643 message = SyslogMessage.parse(message)
644 except ParseError as e:
648 self.assertEqual(message.severity, SyslogSeverity.info)
649 self.assertEqual(message.appname, 'NAT')
650 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
651 sd_params = message.sd.get('napmap')
652 self.assertTrue(sd_params is not None)
653 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
654 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
655 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
656 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
657 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
658 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
659 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
660 self.assertTrue(sd_params.get('SSUBIX') is not None)
661 self.assertEqual(sd_params.get('SVLAN'), '0')
663 def verify_mss_value(self, pkt, mss):
664 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
665 raise TypeError("Not a TCP/IP packet")
667 for option in pkt[TCP].options:
668 if option[0] == 'MSS':
669 self.assertEqual(option[1], mss)
670 self.assert_tcp_checksum_valid(pkt)
673 def proto2layer(proto):
674 if proto == IP_PROTOS.tcp:
676 elif proto == IP_PROTOS.udp:
678 elif proto == IP_PROTOS.icmp:
681 raise Exception("Unsupported protocol")
683 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
685 layer = self.proto2layer(proto)
687 if proto == IP_PROTOS.tcp:
688 data = b"A" * 4 + b"B" * 16 + b"C" * 3
690 data = b"A" * 16 + b"B" * 16 + b"C" * 3
691 self.port_in = random.randint(1025, 65535)
694 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
695 self.port_in, 20, data, proto)
696 self.pg0.add_stream(pkts)
697 self.pg_enable_capture(self.pg_interfaces)
699 frags = self.pg1.get_capture(len(pkts))
700 if not dont_translate:
701 p = self.reass_frags_and_verify(frags,
705 p = self.reass_frags_and_verify(frags,
708 if proto != IP_PROTOS.icmp:
709 if not dont_translate:
710 self.assertEqual(p[layer].dport, 20)
712 self.assertNotEqual(p[layer].sport, self.port_in)
714 self.assertEqual(p[layer].sport, self.port_in)
717 if not dont_translate:
718 self.assertNotEqual(p[layer].id, self.port_in)
720 self.assertEqual(p[layer].id, self.port_in)
721 self.assertEqual(data, p[Raw].load)
724 if not dont_translate:
725 dst_addr = self.nat_addr
727 dst_addr = self.pg0.remote_ip4
728 if proto != IP_PROTOS.icmp:
730 dport = p[layer].sport
734 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
735 proto, echo_reply=True)
736 self.pg1.add_stream(pkts)
737 self.pg_enable_capture(self.pg_interfaces)
739 frags = self.pg0.get_capture(len(pkts))
740 p = self.reass_frags_and_verify(frags,
743 if proto != IP_PROTOS.icmp:
744 self.assertEqual(p[layer].sport, 20)
745 self.assertEqual(p[layer].dport, self.port_in)
747 self.assertEqual(p[layer].id, self.port_in)
748 self.assertEqual(data, p[Raw].load)
750 def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
751 host_in_port, proto=IP_PROTOS.tcp,
754 layer = self.proto2layer(proto)
756 if proto == IP_PROTOS.tcp:
757 data = b"A" * 4 + b"B" * 16 + b"C" * 3
759 data = b"A" * 16 + b"B" * 16 + b"C" * 3
761 # send packet from host to server
762 pkts = self.create_stream_frag(self.pg0,
768 self.pg0.add_stream(pkts)
769 self.pg_enable_capture(self.pg_interfaces)
771 frags = self.pg0.get_capture(len(pkts))
772 p = self.reass_frags_and_verify(frags,
775 if proto != IP_PROTOS.icmp:
777 self.assertNotEqual(p[layer].sport, host_in_port)
778 self.assertEqual(p[layer].dport, server_in_port)
781 self.assertNotEqual(p[layer].id, host_in_port)
782 self.assertEqual(data, p[Raw].load)
784 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
786 layer = self.proto2layer(proto)
788 if proto == IP_PROTOS.tcp:
789 data = b"A" * 4 + b"B" * 16 + b"C" * 3
791 data = b"A" * 16 + b"B" * 16 + b"C" * 3
792 self.port_in = random.randint(1025, 65535)
796 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
797 self.port_in, 20, data, proto)
799 self.pg0.add_stream(pkts)
800 self.pg_enable_capture(self.pg_interfaces)
802 frags = self.pg1.get_capture(len(pkts))
803 if not dont_translate:
804 p = self.reass_frags_and_verify(frags,
808 p = self.reass_frags_and_verify(frags,
811 if proto != IP_PROTOS.icmp:
812 if not dont_translate:
813 self.assertEqual(p[layer].dport, 20)
815 self.assertNotEqual(p[layer].sport, self.port_in)
817 self.assertEqual(p[layer].sport, self.port_in)
820 if not dont_translate:
821 self.assertNotEqual(p[layer].id, self.port_in)
823 self.assertEqual(p[layer].id, self.port_in)
824 self.assertEqual(data, p[Raw].load)
827 if not dont_translate:
828 dst_addr = self.nat_addr
830 dst_addr = self.pg0.remote_ip4
831 if proto != IP_PROTOS.icmp:
833 dport = p[layer].sport
837 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
838 data, proto, echo_reply=True)
840 self.pg1.add_stream(pkts)
841 self.pg_enable_capture(self.pg_interfaces)
843 frags = self.pg0.get_capture(len(pkts))
844 p = self.reass_frags_and_verify(frags,
847 if proto != IP_PROTOS.icmp:
848 self.assertEqual(p[layer].sport, 20)
849 self.assertEqual(p[layer].dport, self.port_in)
851 self.assertEqual(p[layer].id, self.port_in)
852 self.assertEqual(data, p[Raw].load)
855 @tag_fixme_vpp_workers
856 class TestNAT44EI(MethodHolder):
857 """ NAT44EI Test Cases """
859 max_translations = 10240
864 super(TestNAT44EI, cls).setUpClass()
865 cls.vapi.cli("set log class nat44-ei level debug")
867 cls.tcp_port_in = 6303
868 cls.tcp_port_out = 6303
869 cls.udp_port_in = 6304
870 cls.udp_port_out = 6304
871 cls.icmp_id_in = 6305
872 cls.icmp_id_out = 6305
873 cls.nat_addr = '10.0.0.3'
874 cls.ipfix_src_port = 4739
875 cls.ipfix_domain_id = 1
876 cls.tcp_external_port = 80
877 cls.udp_external_port = 69
879 cls.create_pg_interfaces(range(10))
880 cls.interfaces = list(cls.pg_interfaces[0:4])
882 for i in cls.interfaces:
887 cls.pg0.generate_remote_hosts(3)
888 cls.pg0.configure_ipv4_neighbors()
890 cls.pg1.generate_remote_hosts(1)
891 cls.pg1.configure_ipv4_neighbors()
893 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
894 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
895 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
897 cls.pg4._local_ip4 = "172.16.255.1"
898 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
899 cls.pg4.set_table_ip4(10)
900 cls.pg5._local_ip4 = "172.17.255.3"
901 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
902 cls.pg5.set_table_ip4(10)
903 cls.pg6._local_ip4 = "172.16.255.1"
904 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
905 cls.pg6.set_table_ip4(20)
906 for i in cls.overlapping_interfaces:
914 cls.pg9.generate_remote_hosts(2)
916 cls.vapi.sw_interface_add_del_address(
917 sw_if_index=cls.pg9.sw_if_index,
918 prefix="10.0.0.1/24")
921 cls.pg9.resolve_arp()
922 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
923 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
924 cls.pg9.resolve_arp()
926 def plugin_enable(self):
927 self.vapi.nat44_ei_plugin_enable_disable(
928 sessions=self.max_translations,
929 users=self.max_users, enable=1)
932 super(TestNAT44EI, self).setUp()
936 super(TestNAT44EI, self).tearDown()
937 if not self.vpp_dead:
938 self.vapi.nat44_ei_ipfix_enable_disable(
939 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port,
941 self.ipfix_src_port = 4739
942 self.ipfix_domain_id = 1
944 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
945 self.vapi.cli("clear logging")
947 def test_clear_sessions(self):
948 """ NAT44EI session clearing test """
950 self.nat44_add_address(self.nat_addr)
951 flags = self.config_flags.NAT44_EI_IF_INSIDE
952 self.vapi.nat44_ei_interface_add_del_feature(
953 sw_if_index=self.pg0.sw_if_index,
954 flags=flags, is_add=1)
955 self.vapi.nat44_ei_interface_add_del_feature(
956 sw_if_index=self.pg1.sw_if_index,
959 pkts = self.create_stream_in(self.pg0, self.pg1)
960 self.pg0.add_stream(pkts)
961 self.pg_enable_capture(self.pg_interfaces)
963 capture = self.pg1.get_capture(len(pkts))
964 self.verify_capture_out(capture)
966 sessions = self.statistics.get_counter('/nat44-ei/total-sessions')
967 self.assertTrue(sessions[0][0] > 0)
968 self.logger.info("sessions before clearing: %s" % sessions[0][0])
970 self.vapi.cli("clear nat44 ei sessions")
972 sessions = self.statistics.get_counter('/nat44-ei/total-sessions')
973 self.assertEqual(sessions[0][0], 0)
974 self.logger.info("sessions after clearing: %s" % sessions[0][0])
976 def test_dynamic(self):
977 """ NAT44EI dynamic translation test """
978 self.nat44_add_address(self.nat_addr)
979 flags = self.config_flags.NAT44_EI_IF_INSIDE
980 self.vapi.nat44_ei_interface_add_del_feature(
981 sw_if_index=self.pg0.sw_if_index,
982 flags=flags, is_add=1)
983 self.vapi.nat44_ei_interface_add_del_feature(
984 sw_if_index=self.pg1.sw_if_index,
988 tcpn = self.statistics.get_counter('/nat44-ei/in2out/slowpath/tcp')[0]
989 udpn = self.statistics.get_counter('/nat44-ei/in2out/slowpath/udp')[0]
990 icmpn = self.statistics.get_counter(
991 '/nat44-ei/in2out/slowpath/icmp')[0]
992 drops = self.statistics.get_counter(
993 '/nat44-ei/in2out/slowpath/drops')[0]
995 pkts = self.create_stream_in(self.pg0, self.pg1)
996 self.pg0.add_stream(pkts)
997 self.pg_enable_capture(self.pg_interfaces)
999 capture = self.pg1.get_capture(len(pkts))
1000 self.verify_capture_out(capture)
1002 if_idx = self.pg0.sw_if_index
1003 cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/tcp')[0]
1004 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1005 cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/udp')[0]
1006 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1007 cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/icmp')[0]
1008 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1009 cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/drops')[0]
1010 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1013 tcpn = self.statistics.get_counter('/nat44-ei/out2in/slowpath/tcp')[0]
1014 udpn = self.statistics.get_counter('/nat44-ei/out2in/slowpath/udp')[0]
1015 icmpn = self.statistics.get_counter(
1016 '/nat44-ei/out2in/slowpath/icmp')[0]
1017 drops = self.statistics.get_counter(
1018 '/nat44-ei/out2in/slowpath/drops')[0]
1020 pkts = self.create_stream_out(self.pg1)
1021 self.pg1.add_stream(pkts)
1022 self.pg_enable_capture(self.pg_interfaces)
1024 capture = self.pg0.get_capture(len(pkts))
1025 self.verify_capture_in(capture, self.pg0)
1027 if_idx = self.pg1.sw_if_index
1028 cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/tcp')[0]
1029 self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1030 cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/udp')[0]
1031 self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1032 cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/icmp')[0]
1033 self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1034 cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/drops')[0]
1035 self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1037 users = self.statistics.get_counter('/nat44-ei/total-users')
1038 self.assertEqual(users[0][0], 1)
1039 sessions = self.statistics.get_counter('/nat44-ei/total-sessions')
1040 self.assertEqual(sessions[0][0], 3)
1042 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1043 """ NAT44EI handling of client packets with TTL=1 """
1045 self.nat44_add_address(self.nat_addr)
1046 flags = self.config_flags.NAT44_EI_IF_INSIDE
1047 self.vapi.nat44_ei_interface_add_del_feature(
1048 sw_if_index=self.pg0.sw_if_index,
1049 flags=flags, is_add=1)
1050 self.vapi.nat44_ei_interface_add_del_feature(
1051 sw_if_index=self.pg1.sw_if_index,
1054 # Client side - generate traffic
1055 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1056 self.pg0.add_stream(pkts)
1057 self.pg_enable_capture(self.pg_interfaces)
1060 # Client side - verify ICMP type 11 packets
1061 capture = self.pg0.get_capture(len(pkts))
1062 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1064 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1065 """ NAT44EI handling of server packets with TTL=1 """
1067 self.nat44_add_address(self.nat_addr)
1068 flags = self.config_flags.NAT44_EI_IF_INSIDE
1069 self.vapi.nat44_ei_interface_add_del_feature(
1070 sw_if_index=self.pg0.sw_if_index,
1071 flags=flags, is_add=1)
1072 self.vapi.nat44_ei_interface_add_del_feature(
1073 sw_if_index=self.pg1.sw_if_index,
1076 # Client side - create sessions
1077 pkts = self.create_stream_in(self.pg0, self.pg1)
1078 self.pg0.add_stream(pkts)
1079 self.pg_enable_capture(self.pg_interfaces)
1082 # Server side - generate traffic
1083 capture = self.pg1.get_capture(len(pkts))
1084 self.verify_capture_out(capture)
1085 pkts = self.create_stream_out(self.pg1, ttl=1)
1086 self.pg1.add_stream(pkts)
1087 self.pg_enable_capture(self.pg_interfaces)
1090 # Server side - verify ICMP type 11 packets
1091 capture = self.pg1.get_capture(len(pkts))
1092 self.verify_capture_out_with_icmp_errors(capture,
1093 src_ip=self.pg1.local_ip4)
1095 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1096 """ NAT44EI handling of error responses to client packets with TTL=2
1099 self.nat44_add_address(self.nat_addr)
1100 flags = self.config_flags.NAT44_EI_IF_INSIDE
1101 self.vapi.nat44_ei_interface_add_del_feature(
1102 sw_if_index=self.pg0.sw_if_index,
1103 flags=flags, is_add=1)
1104 self.vapi.nat44_ei_interface_add_del_feature(
1105 sw_if_index=self.pg1.sw_if_index,
1108 # Client side - generate traffic
1109 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1110 self.pg0.add_stream(pkts)
1111 self.pg_enable_capture(self.pg_interfaces)
1114 # Server side - simulate ICMP type 11 response
1115 capture = self.pg1.get_capture(len(pkts))
1116 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1117 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1118 ICMP(type=11) / packet[IP] for packet in capture]
1119 self.pg1.add_stream(pkts)
1120 self.pg_enable_capture(self.pg_interfaces)
1123 # Client side - verify ICMP type 11 packets
1124 capture = self.pg0.get_capture(len(pkts))
1125 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1127 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1128 """ NAT44EI handling of error responses to server packets with TTL=2
1131 self.nat44_add_address(self.nat_addr)
1132 flags = self.config_flags.NAT44_EI_IF_INSIDE
1133 self.vapi.nat44_ei_interface_add_del_feature(
1134 sw_if_index=self.pg0.sw_if_index,
1135 flags=flags, is_add=1)
1136 self.vapi.nat44_ei_interface_add_del_feature(
1137 sw_if_index=self.pg1.sw_if_index,
1140 # Client side - create sessions
1141 pkts = self.create_stream_in(self.pg0, self.pg1)
1142 self.pg0.add_stream(pkts)
1143 self.pg_enable_capture(self.pg_interfaces)
1146 # Server side - generate traffic
1147 capture = self.pg1.get_capture(len(pkts))
1148 self.verify_capture_out(capture)
1149 pkts = self.create_stream_out(self.pg1, ttl=2)
1150 self.pg1.add_stream(pkts)
1151 self.pg_enable_capture(self.pg_interfaces)
1154 # Client side - simulate ICMP type 11 response
1155 capture = self.pg0.get_capture(len(pkts))
1156 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1157 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1158 ICMP(type=11) / packet[IP] for packet in capture]
1159 self.pg0.add_stream(pkts)
1160 self.pg_enable_capture(self.pg_interfaces)
1163 # Server side - verify ICMP type 11 packets
1164 capture = self.pg1.get_capture(len(pkts))
1165 self.verify_capture_out_with_icmp_errors(capture)
1167 def test_ping_out_interface_from_outside(self):
1168 """ NAT44EI ping out interface from outside network """
1170 self.nat44_add_address(self.nat_addr)
1171 flags = self.config_flags.NAT44_EI_IF_INSIDE
1172 self.vapi.nat44_ei_interface_add_del_feature(
1173 sw_if_index=self.pg0.sw_if_index,
1174 flags=flags, is_add=1)
1175 self.vapi.nat44_ei_interface_add_del_feature(
1176 sw_if_index=self.pg1.sw_if_index,
1179 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1180 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1181 ICMP(id=self.icmp_id_out, type='echo-request'))
1183 self.pg1.add_stream(pkts)
1184 self.pg_enable_capture(self.pg_interfaces)
1186 capture = self.pg1.get_capture(len(pkts))
1189 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1190 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1191 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1192 self.assertEqual(packet[ICMP].type, 0) # echo reply
1194 self.logger.error(ppp("Unexpected or invalid packet "
1195 "(outside network):", packet))
1198 def test_ping_internal_host_from_outside(self):
1199 """ NAT44EI ping internal host from outside network """
1201 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1202 flags = self.config_flags.NAT44_EI_IF_INSIDE
1203 self.vapi.nat44_ei_interface_add_del_feature(
1204 sw_if_index=self.pg0.sw_if_index,
1205 flags=flags, is_add=1)
1206 self.vapi.nat44_ei_interface_add_del_feature(
1207 sw_if_index=self.pg1.sw_if_index,
1211 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1212 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1213 ICMP(id=self.icmp_id_out, type='echo-request'))
1214 self.pg1.add_stream(pkt)
1215 self.pg_enable_capture(self.pg_interfaces)
1217 capture = self.pg0.get_capture(1)
1218 self.verify_capture_in(capture, self.pg0)
1219 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1222 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1223 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1224 ICMP(id=self.icmp_id_in, type='echo-reply'))
1225 self.pg0.add_stream(pkt)
1226 self.pg_enable_capture(self.pg_interfaces)
1228 capture = self.pg1.get_capture(1)
1229 self.verify_capture_out(capture, same_port=True)
1230 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1232 def test_forwarding(self):
1233 """ NAT44EI forwarding test """
1235 flags = self.config_flags.NAT44_EI_IF_INSIDE
1236 self.vapi.nat44_ei_interface_add_del_feature(
1237 sw_if_index=self.pg0.sw_if_index,
1238 flags=flags, is_add=1)
1239 self.vapi.nat44_ei_interface_add_del_feature(
1240 sw_if_index=self.pg1.sw_if_index,
1242 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
1244 real_ip = self.pg0.remote_ip4
1245 alias_ip = self.nat_addr
1246 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1247 self.vapi.nat44_ei_add_del_static_mapping(
1248 is_add=1, local_ip_address=real_ip,
1249 external_ip_address=alias_ip,
1250 external_sw_if_index=0xFFFFFFFF,
1254 # static mapping match
1256 pkts = self.create_stream_out(self.pg1)
1257 self.pg1.add_stream(pkts)
1258 self.pg_enable_capture(self.pg_interfaces)
1260 capture = self.pg0.get_capture(len(pkts))
1261 self.verify_capture_in(capture, self.pg0)
1263 pkts = self.create_stream_in(self.pg0, self.pg1)
1264 self.pg0.add_stream(pkts)
1265 self.pg_enable_capture(self.pg_interfaces)
1267 capture = self.pg1.get_capture(len(pkts))
1268 self.verify_capture_out(capture, same_port=True)
1270 # no static mapping match
1272 host0 = self.pg0.remote_hosts[0]
1273 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1275 pkts = self.create_stream_out(self.pg1,
1276 dst_ip=self.pg0.remote_ip4,
1277 use_inside_ports=True)
1278 self.pg1.add_stream(pkts)
1279 self.pg_enable_capture(self.pg_interfaces)
1281 capture = self.pg0.get_capture(len(pkts))
1282 self.verify_capture_in(capture, self.pg0)
1284 pkts = self.create_stream_in(self.pg0, self.pg1)
1285 self.pg0.add_stream(pkts)
1286 self.pg_enable_capture(self.pg_interfaces)
1288 capture = self.pg1.get_capture(len(pkts))
1289 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1292 self.pg0.remote_hosts[0] = host0
1295 self.vapi.nat44_ei_forwarding_enable_disable(enable=0)
1296 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1297 self.vapi.nat44_ei_add_del_static_mapping(
1299 local_ip_address=real_ip,
1300 external_ip_address=alias_ip,
1301 external_sw_if_index=0xFFFFFFFF,
1304 def test_static_in(self):
1305 """ NAT44EI 1:1 NAT initialized from inside network """
1307 nat_ip = "10.0.0.10"
1308 self.tcp_port_out = 6303
1309 self.udp_port_out = 6304
1310 self.icmp_id_out = 6305
1312 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1313 flags = self.config_flags.NAT44_EI_IF_INSIDE
1314 self.vapi.nat44_ei_interface_add_del_feature(
1315 sw_if_index=self.pg0.sw_if_index,
1316 flags=flags, is_add=1)
1317 self.vapi.nat44_ei_interface_add_del_feature(
1318 sw_if_index=self.pg1.sw_if_index,
1320 sm = self.vapi.nat44_ei_static_mapping_dump()
1321 self.assertEqual(len(sm), 1)
1322 self.assertEqual(sm[0].tag, '')
1323 self.assertEqual(sm[0].protocol, 0)
1324 self.assertEqual(sm[0].local_port, 0)
1325 self.assertEqual(sm[0].external_port, 0)
1328 pkts = self.create_stream_in(self.pg0, self.pg1)
1329 self.pg0.add_stream(pkts)
1330 self.pg_enable_capture(self.pg_interfaces)
1332 capture = self.pg1.get_capture(len(pkts))
1333 self.verify_capture_out(capture, nat_ip, True)
1336 pkts = self.create_stream_out(self.pg1, nat_ip)
1337 self.pg1.add_stream(pkts)
1338 self.pg_enable_capture(self.pg_interfaces)
1340 capture = self.pg0.get_capture(len(pkts))
1341 self.verify_capture_in(capture, self.pg0)
1343 def test_static_out(self):
1344 """ NAT44EI 1:1 NAT initialized from outside network """
1346 nat_ip = "10.0.0.20"
1347 self.tcp_port_out = 6303
1348 self.udp_port_out = 6304
1349 self.icmp_id_out = 6305
1352 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1353 flags = self.config_flags.NAT44_EI_IF_INSIDE
1354 self.vapi.nat44_ei_interface_add_del_feature(
1355 sw_if_index=self.pg0.sw_if_index,
1356 flags=flags, is_add=1)
1357 self.vapi.nat44_ei_interface_add_del_feature(
1358 sw_if_index=self.pg1.sw_if_index,
1360 sm = self.vapi.nat44_ei_static_mapping_dump()
1361 self.assertEqual(len(sm), 1)
1362 self.assertEqual(sm[0].tag, tag)
1365 pkts = self.create_stream_out(self.pg1, nat_ip)
1366 self.pg1.add_stream(pkts)
1367 self.pg_enable_capture(self.pg_interfaces)
1369 capture = self.pg0.get_capture(len(pkts))
1370 self.verify_capture_in(capture, self.pg0)
1373 pkts = self.create_stream_in(self.pg0, self.pg1)
1374 self.pg0.add_stream(pkts)
1375 self.pg_enable_capture(self.pg_interfaces)
1377 capture = self.pg1.get_capture(len(pkts))
1378 self.verify_capture_out(capture, nat_ip, True)
1380 def test_static_with_port_in(self):
1381 """ NAT44EI 1:1 NAPT initialized from inside network """
1383 self.tcp_port_out = 3606
1384 self.udp_port_out = 3607
1385 self.icmp_id_out = 3608
1387 self.nat44_add_address(self.nat_addr)
1388 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1389 self.tcp_port_in, self.tcp_port_out,
1390 proto=IP_PROTOS.tcp)
1391 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1392 self.udp_port_in, self.udp_port_out,
1393 proto=IP_PROTOS.udp)
1394 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1395 self.icmp_id_in, self.icmp_id_out,
1396 proto=IP_PROTOS.icmp)
1397 flags = self.config_flags.NAT44_EI_IF_INSIDE
1398 self.vapi.nat44_ei_interface_add_del_feature(
1399 sw_if_index=self.pg0.sw_if_index,
1400 flags=flags, is_add=1)
1401 self.vapi.nat44_ei_interface_add_del_feature(
1402 sw_if_index=self.pg1.sw_if_index,
1406 pkts = self.create_stream_in(self.pg0, self.pg1)
1407 self.pg0.add_stream(pkts)
1408 self.pg_enable_capture(self.pg_interfaces)
1410 capture = self.pg1.get_capture(len(pkts))
1411 self.verify_capture_out(capture)
1414 pkts = self.create_stream_out(self.pg1)
1415 self.pg1.add_stream(pkts)
1416 self.pg_enable_capture(self.pg_interfaces)
1418 capture = self.pg0.get_capture(len(pkts))
1419 self.verify_capture_in(capture, self.pg0)
1421 def test_static_with_port_out(self):
1422 """ NAT44EI 1:1 NAPT initialized from outside network """
1424 self.tcp_port_out = 30606
1425 self.udp_port_out = 30607
1426 self.icmp_id_out = 30608
1428 self.nat44_add_address(self.nat_addr)
1429 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1430 self.tcp_port_in, self.tcp_port_out,
1431 proto=IP_PROTOS.tcp)
1432 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1433 self.udp_port_in, self.udp_port_out,
1434 proto=IP_PROTOS.udp)
1435 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1436 self.icmp_id_in, self.icmp_id_out,
1437 proto=IP_PROTOS.icmp)
1438 flags = self.config_flags.NAT44_EI_IF_INSIDE
1439 self.vapi.nat44_ei_interface_add_del_feature(
1440 sw_if_index=self.pg0.sw_if_index,
1441 flags=flags, is_add=1)
1442 self.vapi.nat44_ei_interface_add_del_feature(
1443 sw_if_index=self.pg1.sw_if_index,
1447 pkts = self.create_stream_out(self.pg1)
1448 self.pg1.add_stream(pkts)
1449 self.pg_enable_capture(self.pg_interfaces)
1451 capture = self.pg0.get_capture(len(pkts))
1452 self.verify_capture_in(capture, self.pg0)
1455 pkts = self.create_stream_in(self.pg0, self.pg1)
1456 self.pg0.add_stream(pkts)
1457 self.pg_enable_capture(self.pg_interfaces)
1459 capture = self.pg1.get_capture(len(pkts))
1460 self.verify_capture_out(capture)
1462 def test_static_vrf_aware(self):
1463 """ NAT44EI 1:1 NAT VRF awareness """
1465 nat_ip1 = "10.0.0.30"
1466 nat_ip2 = "10.0.0.40"
1467 self.tcp_port_out = 6303
1468 self.udp_port_out = 6304
1469 self.icmp_id_out = 6305
1471 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1473 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1475 flags = self.config_flags.NAT44_EI_IF_INSIDE
1476 self.vapi.nat44_ei_interface_add_del_feature(
1477 sw_if_index=self.pg3.sw_if_index,
1479 self.vapi.nat44_ei_interface_add_del_feature(
1480 sw_if_index=self.pg0.sw_if_index,
1481 flags=flags, is_add=1)
1482 self.vapi.nat44_ei_interface_add_del_feature(
1483 sw_if_index=self.pg4.sw_if_index,
1484 flags=flags, is_add=1)
1486 # inside interface VRF match NAT44EI static mapping VRF
1487 pkts = self.create_stream_in(self.pg4, self.pg3)
1488 self.pg4.add_stream(pkts)
1489 self.pg_enable_capture(self.pg_interfaces)
1491 capture = self.pg3.get_capture(len(pkts))
1492 self.verify_capture_out(capture, nat_ip1, True)
1494 # inside interface VRF don't match NAT44EI static mapping VRF (packets
1496 pkts = self.create_stream_in(self.pg0, self.pg3)
1497 self.pg0.add_stream(pkts)
1498 self.pg_enable_capture(self.pg_interfaces)
1500 self.pg3.assert_nothing_captured()
1502 def test_dynamic_to_static(self):
1503 """ NAT44EI Switch from dynamic translation to 1:1NAT """
1504 nat_ip = "10.0.0.10"
1505 self.tcp_port_out = 6303
1506 self.udp_port_out = 6304
1507 self.icmp_id_out = 6305
1509 self.nat44_add_address(self.nat_addr)
1510 flags = self.config_flags.NAT44_EI_IF_INSIDE
1511 self.vapi.nat44_ei_interface_add_del_feature(
1512 sw_if_index=self.pg0.sw_if_index,
1513 flags=flags, is_add=1)
1514 self.vapi.nat44_ei_interface_add_del_feature(
1515 sw_if_index=self.pg1.sw_if_index,
1519 pkts = self.create_stream_in(self.pg0, self.pg1)
1520 self.pg0.add_stream(pkts)
1521 self.pg_enable_capture(self.pg_interfaces)
1523 capture = self.pg1.get_capture(len(pkts))
1524 self.verify_capture_out(capture)
1527 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1528 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
1529 self.assertEqual(len(sessions), 0)
1530 pkts = self.create_stream_in(self.pg0, self.pg1)
1531 self.pg0.add_stream(pkts)
1532 self.pg_enable_capture(self.pg_interfaces)
1534 capture = self.pg1.get_capture(len(pkts))
1535 self.verify_capture_out(capture, nat_ip, True)
1537 def test_identity_nat(self):
1538 """ NAT44EI Identity NAT """
1539 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1540 self.vapi.nat44_ei_add_del_identity_mapping(
1541 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1542 flags=flags, is_add=1)
1543 flags = self.config_flags.NAT44_EI_IF_INSIDE
1544 self.vapi.nat44_ei_interface_add_del_feature(
1545 sw_if_index=self.pg0.sw_if_index,
1546 flags=flags, is_add=1)
1547 self.vapi.nat44_ei_interface_add_del_feature(
1548 sw_if_index=self.pg1.sw_if_index,
1551 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1552 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1553 TCP(sport=12345, dport=56789))
1554 self.pg1.add_stream(p)
1555 self.pg_enable_capture(self.pg_interfaces)
1557 capture = self.pg0.get_capture(1)
1562 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1563 self.assertEqual(ip.src, self.pg1.remote_ip4)
1564 self.assertEqual(tcp.dport, 56789)
1565 self.assertEqual(tcp.sport, 12345)
1566 self.assert_packet_checksums_valid(p)
1568 self.logger.error(ppp("Unexpected or invalid packet:", p))
1571 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
1572 self.assertEqual(len(sessions), 0)
1573 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1574 self.vapi.nat44_ei_add_del_identity_mapping(
1575 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1576 flags=flags, vrf_id=1, is_add=1)
1577 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
1578 self.assertEqual(len(identity_mappings), 2)
1580 def test_multiple_inside_interfaces(self):
1581 """ NAT44EI multiple non-overlapping address space inside interfaces
1584 self.nat44_add_address(self.nat_addr)
1585 flags = self.config_flags.NAT44_EI_IF_INSIDE
1586 self.vapi.nat44_ei_interface_add_del_feature(
1587 sw_if_index=self.pg0.sw_if_index,
1588 flags=flags, is_add=1)
1589 self.vapi.nat44_ei_interface_add_del_feature(
1590 sw_if_index=self.pg1.sw_if_index,
1591 flags=flags, is_add=1)
1592 self.vapi.nat44_ei_interface_add_del_feature(
1593 sw_if_index=self.pg3.sw_if_index,
1596 # between two NAT44EI inside interfaces (no translation)
1597 pkts = self.create_stream_in(self.pg0, self.pg1)
1598 self.pg0.add_stream(pkts)
1599 self.pg_enable_capture(self.pg_interfaces)
1601 capture = self.pg1.get_capture(len(pkts))
1602 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1604 # from inside to interface without translation
1605 pkts = self.create_stream_in(self.pg0, self.pg2)
1606 self.pg0.add_stream(pkts)
1607 self.pg_enable_capture(self.pg_interfaces)
1609 capture = self.pg2.get_capture(len(pkts))
1610 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1612 # in2out 1st interface
1613 pkts = self.create_stream_in(self.pg0, self.pg3)
1614 self.pg0.add_stream(pkts)
1615 self.pg_enable_capture(self.pg_interfaces)
1617 capture = self.pg3.get_capture(len(pkts))
1618 self.verify_capture_out(capture)
1620 # out2in 1st interface
1621 pkts = self.create_stream_out(self.pg3)
1622 self.pg3.add_stream(pkts)
1623 self.pg_enable_capture(self.pg_interfaces)
1625 capture = self.pg0.get_capture(len(pkts))
1626 self.verify_capture_in(capture, self.pg0)
1628 # in2out 2nd interface
1629 pkts = self.create_stream_in(self.pg1, self.pg3)
1630 self.pg1.add_stream(pkts)
1631 self.pg_enable_capture(self.pg_interfaces)
1633 capture = self.pg3.get_capture(len(pkts))
1634 self.verify_capture_out(capture)
1636 # out2in 2nd interface
1637 pkts = self.create_stream_out(self.pg3)
1638 self.pg3.add_stream(pkts)
1639 self.pg_enable_capture(self.pg_interfaces)
1641 capture = self.pg1.get_capture(len(pkts))
1642 self.verify_capture_in(capture, self.pg1)
1644 def test_inside_overlapping_interfaces(self):
1645 """ NAT44EI multiple inside interfaces with overlapping address space
1648 static_nat_ip = "10.0.0.10"
1649 self.nat44_add_address(self.nat_addr)
1650 flags = self.config_flags.NAT44_EI_IF_INSIDE
1651 self.vapi.nat44_ei_interface_add_del_feature(
1652 sw_if_index=self.pg3.sw_if_index,
1654 self.vapi.nat44_ei_interface_add_del_feature(
1655 sw_if_index=self.pg4.sw_if_index,
1656 flags=flags, is_add=1)
1657 self.vapi.nat44_ei_interface_add_del_feature(
1658 sw_if_index=self.pg5.sw_if_index,
1659 flags=flags, is_add=1)
1660 self.vapi.nat44_ei_interface_add_del_feature(
1661 sw_if_index=self.pg6.sw_if_index,
1662 flags=flags, is_add=1)
1663 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1666 # between NAT44EI inside interfaces with same VRF (no translation)
1667 pkts = self.create_stream_in(self.pg4, self.pg5)
1668 self.pg4.add_stream(pkts)
1669 self.pg_enable_capture(self.pg_interfaces)
1671 capture = self.pg5.get_capture(len(pkts))
1672 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1674 # between NAT44EI inside interfaces with different VRF (hairpinning)
1675 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1676 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1677 TCP(sport=1234, dport=5678))
1678 self.pg4.add_stream(p)
1679 self.pg_enable_capture(self.pg_interfaces)
1681 capture = self.pg6.get_capture(1)
1686 self.assertEqual(ip.src, self.nat_addr)
1687 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1688 self.assertNotEqual(tcp.sport, 1234)
1689 self.assertEqual(tcp.dport, 5678)
1691 self.logger.error(ppp("Unexpected or invalid packet:", p))
1694 # in2out 1st interface
1695 pkts = self.create_stream_in(self.pg4, self.pg3)
1696 self.pg4.add_stream(pkts)
1697 self.pg_enable_capture(self.pg_interfaces)
1699 capture = self.pg3.get_capture(len(pkts))
1700 self.verify_capture_out(capture)
1702 # out2in 1st interface
1703 pkts = self.create_stream_out(self.pg3)
1704 self.pg3.add_stream(pkts)
1705 self.pg_enable_capture(self.pg_interfaces)
1707 capture = self.pg4.get_capture(len(pkts))
1708 self.verify_capture_in(capture, self.pg4)
1710 # in2out 2nd interface
1711 pkts = self.create_stream_in(self.pg5, self.pg3)
1712 self.pg5.add_stream(pkts)
1713 self.pg_enable_capture(self.pg_interfaces)
1715 capture = self.pg3.get_capture(len(pkts))
1716 self.verify_capture_out(capture)
1718 # out2in 2nd interface
1719 pkts = self.create_stream_out(self.pg3)
1720 self.pg3.add_stream(pkts)
1721 self.pg_enable_capture(self.pg_interfaces)
1723 capture = self.pg5.get_capture(len(pkts))
1724 self.verify_capture_in(capture, self.pg5)
1727 addresses = self.vapi.nat44_ei_address_dump()
1728 self.assertEqual(len(addresses), 1)
1729 sessions = self.vapi.nat44_ei_user_session_dump(
1730 self.pg5.remote_ip4, 10)
1731 self.assertEqual(len(sessions), 3)
1732 for session in sessions:
1733 self.assertFalse(session.flags &
1734 self.config_flags.NAT44_EI_STATIC_MAPPING)
1735 self.assertEqual(str(session.inside_ip_address),
1736 self.pg5.remote_ip4)
1737 self.assertEqual(session.outside_ip_address,
1738 addresses[0].ip_address)
1739 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1740 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1741 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1742 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1743 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1744 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1745 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1746 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1747 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1749 # in2out 3rd interface
1750 pkts = self.create_stream_in(self.pg6, self.pg3)
1751 self.pg6.add_stream(pkts)
1752 self.pg_enable_capture(self.pg_interfaces)
1754 capture = self.pg3.get_capture(len(pkts))
1755 self.verify_capture_out(capture, static_nat_ip, True)
1757 # out2in 3rd interface
1758 pkts = self.create_stream_out(self.pg3, static_nat_ip)
1759 self.pg3.add_stream(pkts)
1760 self.pg_enable_capture(self.pg_interfaces)
1762 capture = self.pg6.get_capture(len(pkts))
1763 self.verify_capture_in(capture, self.pg6)
1765 # general user and session dump verifications
1766 users = self.vapi.nat44_ei_user_dump()
1767 self.assertGreaterEqual(len(users), 3)
1768 addresses = self.vapi.nat44_ei_address_dump()
1769 self.assertEqual(len(addresses), 1)
1771 sessions = self.vapi.nat44_ei_user_session_dump(user.ip_address,
1773 for session in sessions:
1774 self.assertEqual(user.ip_address, session.inside_ip_address)
1775 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1776 self.assertTrue(session.protocol in
1777 [IP_PROTOS.tcp, IP_PROTOS.udp,
1781 sessions = self.vapi.nat44_ei_user_session_dump(
1782 self.pg4.remote_ip4, 10)
1783 self.assertGreaterEqual(len(sessions), 4)
1784 for session in sessions:
1786 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1787 self.assertEqual(str(session.inside_ip_address),
1788 self.pg4.remote_ip4)
1789 self.assertEqual(session.outside_ip_address,
1790 addresses[0].ip_address)
1793 sessions = self.vapi.nat44_ei_user_session_dump(
1794 self.pg6.remote_ip4, 20)
1795 self.assertGreaterEqual(len(sessions), 3)
1796 for session in sessions:
1798 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1799 self.assertEqual(str(session.inside_ip_address),
1800 self.pg6.remote_ip4)
1801 self.assertEqual(str(session.outside_ip_address),
1803 self.assertTrue(session.inside_port in
1804 [self.tcp_port_in, self.udp_port_in,
1807 def test_hairpinning(self):
1808 """ NAT44EI hairpinning - 1:1 NAPT """
1810 host = self.pg0.remote_hosts[0]
1811 server = self.pg0.remote_hosts[1]
1814 server_in_port = 5678
1815 server_out_port = 8765
1817 self.nat44_add_address(self.nat_addr)
1818 flags = self.config_flags.NAT44_EI_IF_INSIDE
1819 self.vapi.nat44_ei_interface_add_del_feature(
1820 sw_if_index=self.pg0.sw_if_index,
1821 flags=flags, is_add=1)
1822 self.vapi.nat44_ei_interface_add_del_feature(
1823 sw_if_index=self.pg1.sw_if_index,
1826 # add static mapping for server
1827 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1828 server_in_port, server_out_port,
1829 proto=IP_PROTOS.tcp)
1831 cnt = self.statistics.get_counter('/nat44-ei/hairpinning')[0]
1832 # send packet from host to server
1833 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
1834 IP(src=host.ip4, dst=self.nat_addr) /
1835 TCP(sport=host_in_port, dport=server_out_port))
1836 self.pg0.add_stream(p)
1837 self.pg_enable_capture(self.pg_interfaces)
1839 capture = self.pg0.get_capture(1)
1844 self.assertEqual(ip.src, self.nat_addr)
1845 self.assertEqual(ip.dst, server.ip4)
1846 self.assertNotEqual(tcp.sport, host_in_port)
1847 self.assertEqual(tcp.dport, server_in_port)
1848 self.assert_packet_checksums_valid(p)
1849 host_out_port = tcp.sport
1851 self.logger.error(ppp("Unexpected or invalid packet:", p))
1854 after = self.statistics.get_counter('/nat44-ei/hairpinning')[0]
1855 if_idx = self.pg0.sw_if_index
1856 self.assertEqual(after[if_idx] - cnt[if_idx], 1)
1858 # send reply from server to host
1859 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1860 IP(src=server.ip4, dst=self.nat_addr) /
1861 TCP(sport=server_in_port, dport=host_out_port))
1862 self.pg0.add_stream(p)
1863 self.pg_enable_capture(self.pg_interfaces)
1865 capture = self.pg0.get_capture(1)
1870 self.assertEqual(ip.src, self.nat_addr)
1871 self.assertEqual(ip.dst, host.ip4)
1872 self.assertEqual(tcp.sport, server_out_port)
1873 self.assertEqual(tcp.dport, host_in_port)
1874 self.assert_packet_checksums_valid(p)
1876 self.logger.error(ppp("Unexpected or invalid packet:", p))
1879 after = self.statistics.get_counter('/nat44-ei/hairpinning')[0]
1880 if_idx = self.pg0.sw_if_index
1881 self.assertEqual(after[if_idx] - cnt[if_idx], 2)
1883 def test_hairpinning2(self):
1884 """ NAT44EI hairpinning - 1:1 NAT"""
1886 server1_nat_ip = "10.0.0.10"
1887 server2_nat_ip = "10.0.0.11"
1888 host = self.pg0.remote_hosts[0]
1889 server1 = self.pg0.remote_hosts[1]
1890 server2 = self.pg0.remote_hosts[2]
1891 server_tcp_port = 22
1892 server_udp_port = 20
1894 self.nat44_add_address(self.nat_addr)
1895 flags = self.config_flags.NAT44_EI_IF_INSIDE
1896 self.vapi.nat44_ei_interface_add_del_feature(
1897 sw_if_index=self.pg0.sw_if_index,
1898 flags=flags, is_add=1)
1899 self.vapi.nat44_ei_interface_add_del_feature(
1900 sw_if_index=self.pg1.sw_if_index,
1903 # add static mapping for servers
1904 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1905 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
1909 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1910 IP(src=host.ip4, dst=server1_nat_ip) /
1911 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1913 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1914 IP(src=host.ip4, dst=server1_nat_ip) /
1915 UDP(sport=self.udp_port_in, dport=server_udp_port))
1917 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1918 IP(src=host.ip4, dst=server1_nat_ip) /
1919 ICMP(id=self.icmp_id_in, type='echo-request'))
1921 self.pg0.add_stream(pkts)
1922 self.pg_enable_capture(self.pg_interfaces)
1924 capture = self.pg0.get_capture(len(pkts))
1925 for packet in capture:
1927 self.assertEqual(packet[IP].src, self.nat_addr)
1928 self.assertEqual(packet[IP].dst, server1.ip4)
1929 if packet.haslayer(TCP):
1930 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1931 self.assertEqual(packet[TCP].dport, server_tcp_port)
1932 self.tcp_port_out = packet[TCP].sport
1933 self.assert_packet_checksums_valid(packet)
1934 elif packet.haslayer(UDP):
1935 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1936 self.assertEqual(packet[UDP].dport, server_udp_port)
1937 self.udp_port_out = packet[UDP].sport
1939 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1940 self.icmp_id_out = packet[ICMP].id
1942 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1947 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1948 IP(src=server1.ip4, dst=self.nat_addr) /
1949 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1951 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1952 IP(src=server1.ip4, dst=self.nat_addr) /
1953 UDP(sport=server_udp_port, dport=self.udp_port_out))
1955 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1956 IP(src=server1.ip4, dst=self.nat_addr) /
1957 ICMP(id=self.icmp_id_out, type='echo-reply'))
1959 self.pg0.add_stream(pkts)
1960 self.pg_enable_capture(self.pg_interfaces)
1962 capture = self.pg0.get_capture(len(pkts))
1963 for packet in capture:
1965 self.assertEqual(packet[IP].src, server1_nat_ip)
1966 self.assertEqual(packet[IP].dst, host.ip4)
1967 if packet.haslayer(TCP):
1968 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1969 self.assertEqual(packet[TCP].sport, server_tcp_port)
1970 self.assert_packet_checksums_valid(packet)
1971 elif packet.haslayer(UDP):
1972 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1973 self.assertEqual(packet[UDP].sport, server_udp_port)
1975 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1977 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1980 # server2 to server1
1982 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1983 IP(src=server2.ip4, dst=server1_nat_ip) /
1984 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1986 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1987 IP(src=server2.ip4, dst=server1_nat_ip) /
1988 UDP(sport=self.udp_port_in, dport=server_udp_port))
1990 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1991 IP(src=server2.ip4, dst=server1_nat_ip) /
1992 ICMP(id=self.icmp_id_in, type='echo-request'))
1994 self.pg0.add_stream(pkts)
1995 self.pg_enable_capture(self.pg_interfaces)
1997 capture = self.pg0.get_capture(len(pkts))
1998 for packet in capture:
2000 self.assertEqual(packet[IP].src, server2_nat_ip)
2001 self.assertEqual(packet[IP].dst, server1.ip4)
2002 if packet.haslayer(TCP):
2003 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2004 self.assertEqual(packet[TCP].dport, server_tcp_port)
2005 self.tcp_port_out = packet[TCP].sport
2006 self.assert_packet_checksums_valid(packet)
2007 elif packet.haslayer(UDP):
2008 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2009 self.assertEqual(packet[UDP].dport, server_udp_port)
2010 self.udp_port_out = packet[UDP].sport
2012 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2013 self.icmp_id_out = packet[ICMP].id
2015 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2018 # server1 to server2
2020 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2021 IP(src=server1.ip4, dst=server2_nat_ip) /
2022 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2024 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2025 IP(src=server1.ip4, dst=server2_nat_ip) /
2026 UDP(sport=server_udp_port, dport=self.udp_port_out))
2028 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2029 IP(src=server1.ip4, dst=server2_nat_ip) /
2030 ICMP(id=self.icmp_id_out, type='echo-reply'))
2032 self.pg0.add_stream(pkts)
2033 self.pg_enable_capture(self.pg_interfaces)
2035 capture = self.pg0.get_capture(len(pkts))
2036 for packet in capture:
2038 self.assertEqual(packet[IP].src, server1_nat_ip)
2039 self.assertEqual(packet[IP].dst, server2.ip4)
2040 if packet.haslayer(TCP):
2041 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2042 self.assertEqual(packet[TCP].sport, server_tcp_port)
2043 self.assert_packet_checksums_valid(packet)
2044 elif packet.haslayer(UDP):
2045 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2046 self.assertEqual(packet[UDP].sport, server_udp_port)
2048 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2050 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2053 def test_hairpinning_avoid_inf_loop(self):
2054 """ NAT44EI hairpinning - 1:1 NAPT avoid infinite loop """
2056 host = self.pg0.remote_hosts[0]
2057 server = self.pg0.remote_hosts[1]
2060 server_in_port = 5678
2061 server_out_port = 8765
2063 self.nat44_add_address(self.nat_addr)
2064 flags = self.config_flags.NAT44_EI_IF_INSIDE
2065 self.vapi.nat44_ei_interface_add_del_feature(
2066 sw_if_index=self.pg0.sw_if_index,
2067 flags=flags, is_add=1)
2068 self.vapi.nat44_ei_interface_add_del_feature(
2069 sw_if_index=self.pg1.sw_if_index,
2072 # add static mapping for server
2073 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2074 server_in_port, server_out_port,
2075 proto=IP_PROTOS.tcp)
2077 # add another static mapping that maps pg0.local_ip4 address to itself
2078 self.nat44_add_static_mapping(self.pg0.local_ip4, self.pg0.local_ip4)
2080 # send packet from host to VPP (the packet should get dropped)
2081 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2082 IP(src=host.ip4, dst=self.pg0.local_ip4) /
2083 TCP(sport=host_in_port, dport=server_out_port))
2084 self.pg0.add_stream(p)
2085 self.pg_enable_capture(self.pg_interfaces)
2087 # Here VPP used to crash due to an infinite loop
2089 cnt = self.statistics.get_counter('/nat44-ei/hairpinning')[0]
2090 # send packet from host to server
2091 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2092 IP(src=host.ip4, dst=self.nat_addr) /
2093 TCP(sport=host_in_port, dport=server_out_port))
2094 self.pg0.add_stream(p)
2095 self.pg_enable_capture(self.pg_interfaces)
2097 capture = self.pg0.get_capture(1)
2102 self.assertEqual(ip.src, self.nat_addr)
2103 self.assertEqual(ip.dst, server.ip4)
2104 self.assertNotEqual(tcp.sport, host_in_port)
2105 self.assertEqual(tcp.dport, server_in_port)
2106 self.assert_packet_checksums_valid(p)
2107 host_out_port = tcp.sport
2109 self.logger.error(ppp("Unexpected or invalid packet:", p))
2112 after = self.statistics.get_counter('/nat44-ei/hairpinning')[0]
2113 if_idx = self.pg0.sw_if_index
2114 self.assertEqual(after[if_idx] - cnt[if_idx], 1)
2116 # send reply from server to host
2117 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2118 IP(src=server.ip4, dst=self.nat_addr) /
2119 TCP(sport=server_in_port, dport=host_out_port))
2120 self.pg0.add_stream(p)
2121 self.pg_enable_capture(self.pg_interfaces)
2123 capture = self.pg0.get_capture(1)
2128 self.assertEqual(ip.src, self.nat_addr)
2129 self.assertEqual(ip.dst, host.ip4)
2130 self.assertEqual(tcp.sport, server_out_port)
2131 self.assertEqual(tcp.dport, host_in_port)
2132 self.assert_packet_checksums_valid(p)
2134 self.logger.error(ppp("Unexpected or invalid packet:", p))
2137 after = self.statistics.get_counter('/nat44-ei/hairpinning')[0]
2138 if_idx = self.pg0.sw_if_index
2139 self.assertEqual(after[if_idx] - cnt[if_idx], 2)
2141 def test_interface_addr(self):
2142 """ NAT44EI acquire addresses from interface """
2143 self.vapi.nat44_ei_add_del_interface_addr(
2145 sw_if_index=self.pg7.sw_if_index)
2147 # no address in NAT pool
2148 addresses = self.vapi.nat44_ei_address_dump()
2149 self.assertEqual(0, len(addresses))
2151 # configure interface address and check NAT address pool
2152 self.pg7.config_ip4()
2153 addresses = self.vapi.nat44_ei_address_dump()
2154 self.assertEqual(1, len(addresses))
2155 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2157 # remove interface address and check NAT address pool
2158 self.pg7.unconfig_ip4()
2159 addresses = self.vapi.nat44_ei_address_dump()
2160 self.assertEqual(0, len(addresses))
2162 def test_interface_addr_static_mapping(self):
2163 """ NAT44EI Static mapping with addresses from interface """
2166 self.vapi.nat44_ei_add_del_interface_addr(
2168 sw_if_index=self.pg7.sw_if_index)
2169 self.nat44_add_static_mapping(
2171 external_sw_if_index=self.pg7.sw_if_index,
2174 # static mappings with external interface
2175 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2176 self.assertEqual(1, len(static_mappings))
2177 self.assertEqual(self.pg7.sw_if_index,
2178 static_mappings[0].external_sw_if_index)
2179 self.assertEqual(static_mappings[0].tag, tag)
2181 # configure interface address and check static mappings
2182 self.pg7.config_ip4()
2183 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2184 self.assertEqual(2, len(static_mappings))
2186 for sm in static_mappings:
2187 if sm.external_sw_if_index == 0xFFFFFFFF:
2188 self.assertEqual(str(sm.external_ip_address),
2190 self.assertEqual(sm.tag, tag)
2192 self.assertTrue(resolved)
2194 # remove interface address and check static mappings
2195 self.pg7.unconfig_ip4()
2196 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2197 self.assertEqual(1, len(static_mappings))
2198 self.assertEqual(self.pg7.sw_if_index,
2199 static_mappings[0].external_sw_if_index)
2200 self.assertEqual(static_mappings[0].tag, tag)
2202 # configure interface address again and check static mappings
2203 self.pg7.config_ip4()
2204 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2205 self.assertEqual(2, len(static_mappings))
2207 for sm in static_mappings:
2208 if sm.external_sw_if_index == 0xFFFFFFFF:
2209 self.assertEqual(str(sm.external_ip_address),
2211 self.assertEqual(sm.tag, tag)
2213 self.assertTrue(resolved)
2215 # remove static mapping
2216 self.nat44_add_static_mapping(
2218 external_sw_if_index=self.pg7.sw_if_index,
2221 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2222 self.assertEqual(0, len(static_mappings))
2224 def test_interface_addr_identity_nat(self):
2225 """ NAT44EI Identity NAT with addresses from interface """
2228 self.vapi.nat44_ei_add_del_interface_addr(
2230 sw_if_index=self.pg7.sw_if_index)
2231 self.vapi.nat44_ei_add_del_identity_mapping(
2233 sw_if_index=self.pg7.sw_if_index,
2235 protocol=IP_PROTOS.tcp,
2238 # identity mappings with external interface
2239 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2240 self.assertEqual(1, len(identity_mappings))
2241 self.assertEqual(self.pg7.sw_if_index,
2242 identity_mappings[0].sw_if_index)
2244 # configure interface address and check identity mappings
2245 self.pg7.config_ip4()
2246 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2248 self.assertEqual(2, len(identity_mappings))
2249 for sm in identity_mappings:
2250 if sm.sw_if_index == 0xFFFFFFFF:
2251 self.assertEqual(str(identity_mappings[0].ip_address),
2253 self.assertEqual(port, identity_mappings[0].port)
2254 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2256 self.assertTrue(resolved)
2258 # remove interface address and check identity mappings
2259 self.pg7.unconfig_ip4()
2260 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2261 self.assertEqual(1, len(identity_mappings))
2262 self.assertEqual(self.pg7.sw_if_index,
2263 identity_mappings[0].sw_if_index)
2265 def test_ipfix_nat44_sess(self):
2266 """ NAT44EI IPFIX logging NAT44EI session created/deleted """
2267 self.ipfix_domain_id = 10
2268 self.ipfix_src_port = 20202
2269 collector_port = 30303
2270 bind_layers(UDP, IPFIX, dport=30303)
2271 self.nat44_add_address(self.nat_addr)
2272 flags = self.config_flags.NAT44_EI_IF_INSIDE
2273 self.vapi.nat44_ei_interface_add_del_feature(
2274 sw_if_index=self.pg0.sw_if_index,
2275 flags=flags, is_add=1)
2276 self.vapi.nat44_ei_interface_add_del_feature(
2277 sw_if_index=self.pg1.sw_if_index,
2279 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2280 src_address=self.pg3.local_ip4,
2282 template_interval=10,
2283 collector_port=collector_port)
2284 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2285 src_port=self.ipfix_src_port,
2288 pkts = self.create_stream_in(self.pg0, self.pg1)
2289 self.pg0.add_stream(pkts)
2290 self.pg_enable_capture(self.pg_interfaces)
2292 capture = self.pg1.get_capture(len(pkts))
2293 self.verify_capture_out(capture)
2294 self.nat44_add_address(self.nat_addr, is_add=0)
2295 self.vapi.ipfix_flush()
2296 capture = self.pg3.get_capture(7)
2297 ipfix = IPFIXDecoder()
2298 # first load template
2300 self.assertTrue(p.haslayer(IPFIX))
2301 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2302 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2303 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2304 self.assertEqual(p[UDP].dport, collector_port)
2305 self.assertEqual(p[IPFIX].observationDomainID,
2306 self.ipfix_domain_id)
2307 if p.haslayer(Template):
2308 ipfix.add_template(p.getlayer(Template))
2309 # verify events in data set
2311 if p.haslayer(Data):
2312 data = ipfix.decode_data_set(p.getlayer(Set))
2313 self.verify_ipfix_nat44_ses(data)
2315 def test_ipfix_addr_exhausted(self):
2316 """ NAT44EI IPFIX logging NAT addresses exhausted """
2317 flags = self.config_flags.NAT44_EI_IF_INSIDE
2318 self.vapi.nat44_ei_interface_add_del_feature(
2319 sw_if_index=self.pg0.sw_if_index,
2320 flags=flags, is_add=1)
2321 self.vapi.nat44_ei_interface_add_del_feature(
2322 sw_if_index=self.pg1.sw_if_index,
2324 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2325 src_address=self.pg3.local_ip4,
2327 template_interval=10)
2328 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2329 src_port=self.ipfix_src_port,
2332 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2333 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2335 self.pg0.add_stream(p)
2336 self.pg_enable_capture(self.pg_interfaces)
2338 self.pg1.assert_nothing_captured()
2340 self.vapi.ipfix_flush()
2341 capture = self.pg3.get_capture(7)
2342 ipfix = IPFIXDecoder()
2343 # first load template
2345 self.assertTrue(p.haslayer(IPFIX))
2346 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2347 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2348 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2349 self.assertEqual(p[UDP].dport, 4739)
2350 self.assertEqual(p[IPFIX].observationDomainID,
2351 self.ipfix_domain_id)
2352 if p.haslayer(Template):
2353 ipfix.add_template(p.getlayer(Template))
2354 # verify events in data set
2356 if p.haslayer(Data):
2357 data = ipfix.decode_data_set(p.getlayer(Set))
2358 self.verify_ipfix_addr_exhausted(data)
2360 def test_ipfix_max_sessions(self):
2361 """ NAT44EI IPFIX logging maximum session entries exceeded """
2362 self.nat44_add_address(self.nat_addr)
2363 flags = self.config_flags.NAT44_EI_IF_INSIDE
2364 self.vapi.nat44_ei_interface_add_del_feature(
2365 sw_if_index=self.pg0.sw_if_index,
2366 flags=flags, is_add=1)
2367 self.vapi.nat44_ei_interface_add_del_feature(
2368 sw_if_index=self.pg1.sw_if_index,
2371 max_sessions = self.max_translations
2374 for i in range(0, max_sessions):
2375 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2376 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2377 IP(src=src, dst=self.pg1.remote_ip4) /
2380 self.pg0.add_stream(pkts)
2381 self.pg_enable_capture(self.pg_interfaces)
2384 self.pg1.get_capture(max_sessions)
2385 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2386 src_address=self.pg3.local_ip4,
2388 template_interval=10)
2389 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2390 src_port=self.ipfix_src_port,
2393 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2394 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2396 self.pg0.add_stream(p)
2397 self.pg_enable_capture(self.pg_interfaces)
2399 self.pg1.assert_nothing_captured()
2401 self.vapi.ipfix_flush()
2402 capture = self.pg3.get_capture(7)
2403 ipfix = IPFIXDecoder()
2404 # first load template
2406 self.assertTrue(p.haslayer(IPFIX))
2407 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2408 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2409 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2410 self.assertEqual(p[UDP].dport, 4739)
2411 self.assertEqual(p[IPFIX].observationDomainID,
2412 self.ipfix_domain_id)
2413 if p.haslayer(Template):
2414 ipfix.add_template(p.getlayer(Template))
2415 # verify events in data set
2417 if p.haslayer(Data):
2418 data = ipfix.decode_data_set(p.getlayer(Set))
2419 self.verify_ipfix_max_sessions(data, max_sessions)
2421 def test_syslog_apmap(self):
2422 """ NAT44EI syslog address and port mapping creation and deletion """
2423 self.vapi.syslog_set_filter(
2424 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2425 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2426 self.nat44_add_address(self.nat_addr)
2427 flags = self.config_flags.NAT44_EI_IF_INSIDE
2428 self.vapi.nat44_ei_interface_add_del_feature(
2429 sw_if_index=self.pg0.sw_if_index,
2430 flags=flags, is_add=1)
2431 self.vapi.nat44_ei_interface_add_del_feature(
2432 sw_if_index=self.pg1.sw_if_index,
2435 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2436 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2437 TCP(sport=self.tcp_port_in, dport=20))
2438 self.pg0.add_stream(p)
2439 self.pg_enable_capture(self.pg_interfaces)
2441 capture = self.pg1.get_capture(1)
2442 self.tcp_port_out = capture[0][TCP].sport
2443 capture = self.pg3.get_capture(1)
2444 self.verify_syslog_apmap(capture[0][Raw].load)
2446 self.pg_enable_capture(self.pg_interfaces)
2448 self.nat44_add_address(self.nat_addr, is_add=0)
2449 capture = self.pg3.get_capture(1)
2450 self.verify_syslog_apmap(capture[0][Raw].load, False)
2452 def test_pool_addr_fib(self):
2453 """ NAT44EI add pool addresses to FIB """
2454 static_addr = '10.0.0.10'
2455 self.nat44_add_address(self.nat_addr)
2456 flags = self.config_flags.NAT44_EI_IF_INSIDE
2457 self.vapi.nat44_ei_interface_add_del_feature(
2458 sw_if_index=self.pg0.sw_if_index,
2459 flags=flags, is_add=1)
2460 self.vapi.nat44_ei_interface_add_del_feature(
2461 sw_if_index=self.pg1.sw_if_index,
2463 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2466 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2467 ARP(op=ARP.who_has, pdst=self.nat_addr,
2468 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2469 self.pg1.add_stream(p)
2470 self.pg_enable_capture(self.pg_interfaces)
2472 capture = self.pg1.get_capture(1)
2473 self.assertTrue(capture[0].haslayer(ARP))
2474 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2477 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2478 ARP(op=ARP.who_has, pdst=static_addr,
2479 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2480 self.pg1.add_stream(p)
2481 self.pg_enable_capture(self.pg_interfaces)
2483 capture = self.pg1.get_capture(1)
2484 self.assertTrue(capture[0].haslayer(ARP))
2485 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2487 # send ARP to non-NAT44EI interface
2488 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2489 ARP(op=ARP.who_has, pdst=self.nat_addr,
2490 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2491 self.pg2.add_stream(p)
2492 self.pg_enable_capture(self.pg_interfaces)
2494 self.pg1.assert_nothing_captured()
2496 # remove addresses and verify
2497 self.nat44_add_address(self.nat_addr, is_add=0)
2498 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2501 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2502 ARP(op=ARP.who_has, pdst=self.nat_addr,
2503 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2504 self.pg1.add_stream(p)
2505 self.pg_enable_capture(self.pg_interfaces)
2507 self.pg1.assert_nothing_captured()
2509 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2510 ARP(op=ARP.who_has, pdst=static_addr,
2511 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2512 self.pg1.add_stream(p)
2513 self.pg_enable_capture(self.pg_interfaces)
2515 self.pg1.assert_nothing_captured()
2517 def test_vrf_mode(self):
2518 """ NAT44EI tenant VRF aware address pool mode """
2522 nat_ip1 = "10.0.0.10"
2523 nat_ip2 = "10.0.0.11"
2525 self.pg0.unconfig_ip4()
2526 self.pg1.unconfig_ip4()
2527 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2528 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2529 self.pg0.set_table_ip4(vrf_id1)
2530 self.pg1.set_table_ip4(vrf_id2)
2531 self.pg0.config_ip4()
2532 self.pg1.config_ip4()
2533 self.pg0.resolve_arp()
2534 self.pg1.resolve_arp()
2536 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2537 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2538 flags = self.config_flags.NAT44_EI_IF_INSIDE
2539 self.vapi.nat44_ei_interface_add_del_feature(
2540 sw_if_index=self.pg0.sw_if_index,
2541 flags=flags, is_add=1)
2542 self.vapi.nat44_ei_interface_add_del_feature(
2543 sw_if_index=self.pg1.sw_if_index,
2544 flags=flags, is_add=1)
2545 self.vapi.nat44_ei_interface_add_del_feature(
2546 sw_if_index=self.pg2.sw_if_index,
2551 pkts = self.create_stream_in(self.pg0, self.pg2)
2552 self.pg0.add_stream(pkts)
2553 self.pg_enable_capture(self.pg_interfaces)
2555 capture = self.pg2.get_capture(len(pkts))
2556 self.verify_capture_out(capture, nat_ip1)
2559 pkts = self.create_stream_in(self.pg1, self.pg2)
2560 self.pg1.add_stream(pkts)
2561 self.pg_enable_capture(self.pg_interfaces)
2563 capture = self.pg2.get_capture(len(pkts))
2564 self.verify_capture_out(capture, nat_ip2)
2567 self.pg0.unconfig_ip4()
2568 self.pg1.unconfig_ip4()
2569 self.pg0.set_table_ip4(0)
2570 self.pg1.set_table_ip4(0)
2571 self.pg0.config_ip4()
2572 self.pg1.config_ip4()
2573 self.pg0.resolve_arp()
2574 self.pg1.resolve_arp()
2575 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2576 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2578 def test_vrf_feature_independent(self):
2579 """ NAT44EI tenant VRF independent address pool mode """
2581 nat_ip1 = "10.0.0.10"
2582 nat_ip2 = "10.0.0.11"
2584 self.nat44_add_address(nat_ip1)
2585 self.nat44_add_address(nat_ip2, vrf_id=99)
2586 flags = self.config_flags.NAT44_EI_IF_INSIDE
2587 self.vapi.nat44_ei_interface_add_del_feature(
2588 sw_if_index=self.pg0.sw_if_index,
2589 flags=flags, is_add=1)
2590 self.vapi.nat44_ei_interface_add_del_feature(
2591 sw_if_index=self.pg1.sw_if_index,
2592 flags=flags, is_add=1)
2593 self.vapi.nat44_ei_interface_add_del_feature(
2594 sw_if_index=self.pg2.sw_if_index,
2598 pkts = self.create_stream_in(self.pg0, self.pg2)
2599 self.pg0.add_stream(pkts)
2600 self.pg_enable_capture(self.pg_interfaces)
2602 capture = self.pg2.get_capture(len(pkts))
2603 self.verify_capture_out(capture, nat_ip1)
2606 pkts = self.create_stream_in(self.pg1, self.pg2)
2607 self.pg1.add_stream(pkts)
2608 self.pg_enable_capture(self.pg_interfaces)
2610 capture = self.pg2.get_capture(len(pkts))
2611 self.verify_capture_out(capture, nat_ip1)
2613 def test_dynamic_ipless_interfaces(self):
2614 """ NAT44EI interfaces without configured IP address """
2615 self.create_routes_and_neigbors()
2616 self.nat44_add_address(self.nat_addr)
2617 flags = self.config_flags.NAT44_EI_IF_INSIDE
2618 self.vapi.nat44_ei_interface_add_del_feature(
2619 sw_if_index=self.pg7.sw_if_index,
2620 flags=flags, is_add=1)
2621 self.vapi.nat44_ei_interface_add_del_feature(
2622 sw_if_index=self.pg8.sw_if_index,
2626 pkts = self.create_stream_in(self.pg7, self.pg8)
2627 self.pg7.add_stream(pkts)
2628 self.pg_enable_capture(self.pg_interfaces)
2630 capture = self.pg8.get_capture(len(pkts))
2631 self.verify_capture_out(capture)
2634 pkts = self.create_stream_out(self.pg8, self.nat_addr)
2635 self.pg8.add_stream(pkts)
2636 self.pg_enable_capture(self.pg_interfaces)
2638 capture = self.pg7.get_capture(len(pkts))
2639 self.verify_capture_in(capture, self.pg7)
2641 def test_static_ipless_interfaces(self):
2642 """ NAT44EI interfaces without configured IP address - 1:1 NAT """
2644 self.create_routes_and_neigbors()
2645 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2646 flags = self.config_flags.NAT44_EI_IF_INSIDE
2647 self.vapi.nat44_ei_interface_add_del_feature(
2648 sw_if_index=self.pg7.sw_if_index,
2649 flags=flags, is_add=1)
2650 self.vapi.nat44_ei_interface_add_del_feature(
2651 sw_if_index=self.pg8.sw_if_index,
2655 pkts = self.create_stream_out(self.pg8)
2656 self.pg8.add_stream(pkts)
2657 self.pg_enable_capture(self.pg_interfaces)
2659 capture = self.pg7.get_capture(len(pkts))
2660 self.verify_capture_in(capture, self.pg7)
2663 pkts = self.create_stream_in(self.pg7, self.pg8)
2664 self.pg7.add_stream(pkts)
2665 self.pg_enable_capture(self.pg_interfaces)
2667 capture = self.pg8.get_capture(len(pkts))
2668 self.verify_capture_out(capture, self.nat_addr, True)
2670 def test_static_with_port_ipless_interfaces(self):
2671 """ NAT44EI interfaces without configured IP address - 1:1 NAPT """
2673 self.tcp_port_out = 30606
2674 self.udp_port_out = 30607
2675 self.icmp_id_out = 30608
2677 self.create_routes_and_neigbors()
2678 self.nat44_add_address(self.nat_addr)
2679 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2680 self.tcp_port_in, self.tcp_port_out,
2681 proto=IP_PROTOS.tcp)
2682 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2683 self.udp_port_in, self.udp_port_out,
2684 proto=IP_PROTOS.udp)
2685 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2686 self.icmp_id_in, self.icmp_id_out,
2687 proto=IP_PROTOS.icmp)
2688 flags = self.config_flags.NAT44_EI_IF_INSIDE
2689 self.vapi.nat44_ei_interface_add_del_feature(
2690 sw_if_index=self.pg7.sw_if_index,
2691 flags=flags, is_add=1)
2692 self.vapi.nat44_ei_interface_add_del_feature(
2693 sw_if_index=self.pg8.sw_if_index,
2697 pkts = self.create_stream_out(self.pg8)
2698 self.pg8.add_stream(pkts)
2699 self.pg_enable_capture(self.pg_interfaces)
2701 capture = self.pg7.get_capture(len(pkts))
2702 self.verify_capture_in(capture, self.pg7)
2705 pkts = self.create_stream_in(self.pg7, self.pg8)
2706 self.pg7.add_stream(pkts)
2707 self.pg_enable_capture(self.pg_interfaces)
2709 capture = self.pg8.get_capture(len(pkts))
2710 self.verify_capture_out(capture)
2712 def test_static_unknown_proto(self):
2713 """ NAT44EI 1:1 translate packet with unknown protocol """
2714 nat_ip = "10.0.0.10"
2715 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2716 flags = self.config_flags.NAT44_EI_IF_INSIDE
2717 self.vapi.nat44_ei_interface_add_del_feature(
2718 sw_if_index=self.pg0.sw_if_index,
2719 flags=flags, is_add=1)
2720 self.vapi.nat44_ei_interface_add_del_feature(
2721 sw_if_index=self.pg1.sw_if_index,
2725 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2726 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2728 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2729 TCP(sport=1234, dport=1234))
2730 self.pg0.add_stream(p)
2731 self.pg_enable_capture(self.pg_interfaces)
2733 p = self.pg1.get_capture(1)
2736 self.assertEqual(packet[IP].src, nat_ip)
2737 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2738 self.assertEqual(packet.haslayer(GRE), 1)
2739 self.assert_packet_checksums_valid(packet)
2741 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2745 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2746 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2748 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2749 TCP(sport=1234, dport=1234))
2750 self.pg1.add_stream(p)
2751 self.pg_enable_capture(self.pg_interfaces)
2753 p = self.pg0.get_capture(1)
2756 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2757 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2758 self.assertEqual(packet.haslayer(GRE), 1)
2759 self.assert_packet_checksums_valid(packet)
2761 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2764 def test_hairpinning_static_unknown_proto(self):
2765 """ NAT44EI 1:1 translate packet with unknown protocol - hairpinning
2768 host = self.pg0.remote_hosts[0]
2769 server = self.pg0.remote_hosts[1]
2771 host_nat_ip = "10.0.0.10"
2772 server_nat_ip = "10.0.0.11"
2774 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2775 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2776 flags = self.config_flags.NAT44_EI_IF_INSIDE
2777 self.vapi.nat44_ei_interface_add_del_feature(
2778 sw_if_index=self.pg0.sw_if_index,
2779 flags=flags, is_add=1)
2780 self.vapi.nat44_ei_interface_add_del_feature(
2781 sw_if_index=self.pg1.sw_if_index,
2785 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2786 IP(src=host.ip4, dst=server_nat_ip) /
2788 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2789 TCP(sport=1234, dport=1234))
2790 self.pg0.add_stream(p)
2791 self.pg_enable_capture(self.pg_interfaces)
2793 p = self.pg0.get_capture(1)
2796 self.assertEqual(packet[IP].src, host_nat_ip)
2797 self.assertEqual(packet[IP].dst, server.ip4)
2798 self.assertEqual(packet.haslayer(GRE), 1)
2799 self.assert_packet_checksums_valid(packet)
2801 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2805 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2806 IP(src=server.ip4, dst=host_nat_ip) /
2808 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2809 TCP(sport=1234, dport=1234))
2810 self.pg0.add_stream(p)
2811 self.pg_enable_capture(self.pg_interfaces)
2813 p = self.pg0.get_capture(1)
2816 self.assertEqual(packet[IP].src, server_nat_ip)
2817 self.assertEqual(packet[IP].dst, host.ip4)
2818 self.assertEqual(packet.haslayer(GRE), 1)
2819 self.assert_packet_checksums_valid(packet)
2821 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2824 def test_output_feature(self):
2825 """ NAT44EI output feature (in2out postrouting) """
2826 self.nat44_add_address(self.nat_addr)
2827 flags = self.config_flags.NAT44_EI_IF_INSIDE
2828 self.vapi.nat44_ei_interface_add_del_output_feature(
2829 is_add=1, flags=flags,
2830 sw_if_index=self.pg0.sw_if_index)
2831 self.vapi.nat44_ei_interface_add_del_output_feature(
2832 is_add=1, flags=flags,
2833 sw_if_index=self.pg1.sw_if_index)
2834 self.vapi.nat44_ei_interface_add_del_output_feature(
2836 sw_if_index=self.pg3.sw_if_index)
2839 pkts = self.create_stream_in(self.pg0, self.pg3)
2840 self.pg0.add_stream(pkts)
2841 self.pg_enable_capture(self.pg_interfaces)
2843 capture = self.pg3.get_capture(len(pkts))
2844 self.verify_capture_out(capture)
2847 pkts = self.create_stream_out(self.pg3)
2848 self.pg3.add_stream(pkts)
2849 self.pg_enable_capture(self.pg_interfaces)
2851 capture = self.pg0.get_capture(len(pkts))
2852 self.verify_capture_in(capture, self.pg0)
2854 # from non-NAT interface to NAT inside interface
2855 pkts = self.create_stream_in(self.pg2, self.pg0)
2856 self.pg2.add_stream(pkts)
2857 self.pg_enable_capture(self.pg_interfaces)
2859 capture = self.pg0.get_capture(len(pkts))
2860 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2862 def test_output_feature_vrf_aware(self):
2863 """ NAT44EI output feature VRF aware (in2out postrouting) """
2864 nat_ip_vrf10 = "10.0.0.10"
2865 nat_ip_vrf20 = "10.0.0.20"
2867 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2868 [VppRoutePath(self.pg3.remote_ip4,
2869 self.pg3.sw_if_index)],
2871 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2872 [VppRoutePath(self.pg3.remote_ip4,
2873 self.pg3.sw_if_index)],
2878 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2879 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2880 flags = self.config_flags.NAT44_EI_IF_INSIDE
2881 self.vapi.nat44_ei_interface_add_del_output_feature(
2882 is_add=1, flags=flags,
2883 sw_if_index=self.pg4.sw_if_index)
2884 self.vapi.nat44_ei_interface_add_del_output_feature(
2885 is_add=1, flags=flags,
2886 sw_if_index=self.pg6.sw_if_index)
2887 self.vapi.nat44_ei_interface_add_del_output_feature(
2889 sw_if_index=self.pg3.sw_if_index)
2892 pkts = self.create_stream_in(self.pg4, self.pg3)
2893 self.pg4.add_stream(pkts)
2894 self.pg_enable_capture(self.pg_interfaces)
2896 capture = self.pg3.get_capture(len(pkts))
2897 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2900 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2901 self.pg3.add_stream(pkts)
2902 self.pg_enable_capture(self.pg_interfaces)
2904 capture = self.pg4.get_capture(len(pkts))
2905 self.verify_capture_in(capture, self.pg4)
2908 pkts = self.create_stream_in(self.pg6, self.pg3)
2909 self.pg6.add_stream(pkts)
2910 self.pg_enable_capture(self.pg_interfaces)
2912 capture = self.pg3.get_capture(len(pkts))
2913 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2916 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2917 self.pg3.add_stream(pkts)
2918 self.pg_enable_capture(self.pg_interfaces)
2920 capture = self.pg6.get_capture(len(pkts))
2921 self.verify_capture_in(capture, self.pg6)
2923 def test_output_feature_hairpinning(self):
2924 """ NAT44EI output feature hairpinning (in2out postrouting) """
2925 host = self.pg0.remote_hosts[0]
2926 server = self.pg0.remote_hosts[1]
2929 server_in_port = 5678
2930 server_out_port = 8765
2932 self.nat44_add_address(self.nat_addr)
2933 flags = self.config_flags.NAT44_EI_IF_INSIDE
2934 self.vapi.nat44_ei_interface_add_del_output_feature(
2935 is_add=1, flags=flags,
2936 sw_if_index=self.pg0.sw_if_index)
2937 self.vapi.nat44_ei_interface_add_del_output_feature(
2939 sw_if_index=self.pg1.sw_if_index)
2941 # add static mapping for server
2942 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2943 server_in_port, server_out_port,
2944 proto=IP_PROTOS.tcp)
2946 # send packet from host to server
2947 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2948 IP(src=host.ip4, dst=self.nat_addr) /
2949 TCP(sport=host_in_port, dport=server_out_port))
2950 self.pg0.add_stream(p)
2951 self.pg_enable_capture(self.pg_interfaces)
2953 capture = self.pg0.get_capture(1)
2958 self.assertEqual(ip.src, self.nat_addr)
2959 self.assertEqual(ip.dst, server.ip4)
2960 self.assertNotEqual(tcp.sport, host_in_port)
2961 self.assertEqual(tcp.dport, server_in_port)
2962 self.assert_packet_checksums_valid(p)
2963 host_out_port = tcp.sport
2965 self.logger.error(ppp("Unexpected or invalid packet:", p))
2968 # send reply from server to host
2969 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2970 IP(src=server.ip4, dst=self.nat_addr) /
2971 TCP(sport=server_in_port, dport=host_out_port))
2972 self.pg0.add_stream(p)
2973 self.pg_enable_capture(self.pg_interfaces)
2975 capture = self.pg0.get_capture(1)
2980 self.assertEqual(ip.src, self.nat_addr)
2981 self.assertEqual(ip.dst, host.ip4)
2982 self.assertEqual(tcp.sport, server_out_port)
2983 self.assertEqual(tcp.dport, host_in_port)
2984 self.assert_packet_checksums_valid(p)
2986 self.logger.error(ppp("Unexpected or invalid packet:", p))
2989 def test_one_armed_nat44(self):
2990 """ NAT44EI One armed NAT """
2991 remote_host = self.pg9.remote_hosts[0]
2992 local_host = self.pg9.remote_hosts[1]
2995 self.nat44_add_address(self.nat_addr)
2996 flags = self.config_flags.NAT44_EI_IF_INSIDE
2997 self.vapi.nat44_ei_interface_add_del_feature(
2998 sw_if_index=self.pg9.sw_if_index,
3000 self.vapi.nat44_ei_interface_add_del_feature(
3001 sw_if_index=self.pg9.sw_if_index,
3002 flags=flags, is_add=1)
3005 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3006 IP(src=local_host.ip4, dst=remote_host.ip4) /
3007 TCP(sport=12345, dport=80))
3008 self.pg9.add_stream(p)
3009 self.pg_enable_capture(self.pg_interfaces)
3011 capture = self.pg9.get_capture(1)
3016 self.assertEqual(ip.src, self.nat_addr)
3017 self.assertEqual(ip.dst, remote_host.ip4)
3018 self.assertNotEqual(tcp.sport, 12345)
3019 external_port = tcp.sport
3020 self.assertEqual(tcp.dport, 80)
3021 self.assert_packet_checksums_valid(p)
3023 self.logger.error(ppp("Unexpected or invalid packet:", p))
3027 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3028 IP(src=remote_host.ip4, dst=self.nat_addr) /
3029 TCP(sport=80, dport=external_port))
3030 self.pg9.add_stream(p)
3031 self.pg_enable_capture(self.pg_interfaces)
3033 capture = self.pg9.get_capture(1)
3038 self.assertEqual(ip.src, remote_host.ip4)
3039 self.assertEqual(ip.dst, local_host.ip4)
3040 self.assertEqual(tcp.sport, 80)
3041 self.assertEqual(tcp.dport, 12345)
3042 self.assert_packet_checksums_valid(p)
3044 self.logger.error(ppp("Unexpected or invalid packet:", p))
3047 if self.vpp_worker_count > 1:
3048 node = "nat44-ei-handoff-classify"
3050 node = "nat44-ei-classify"
3052 err = self.statistics.get_err_counter('/err/%s/next in2out' % node)
3053 self.assertEqual(err, 1)
3054 err = self.statistics.get_err_counter('/err/%s/next out2in' % node)
3055 self.assertEqual(err, 1)
3057 def test_del_session(self):
3058 """ NAT44EI delete session """
3059 self.nat44_add_address(self.nat_addr)
3060 flags = self.config_flags.NAT44_EI_IF_INSIDE
3061 self.vapi.nat44_ei_interface_add_del_feature(
3062 sw_if_index=self.pg0.sw_if_index,
3063 flags=flags, is_add=1)
3064 self.vapi.nat44_ei_interface_add_del_feature(
3065 sw_if_index=self.pg1.sw_if_index,
3068 pkts = self.create_stream_in(self.pg0, self.pg1)
3069 self.pg0.add_stream(pkts)
3070 self.pg_enable_capture(self.pg_interfaces)
3072 self.pg1.get_capture(len(pkts))
3074 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
3075 nsessions = len(sessions)
3077 self.vapi.nat44_ei_del_session(
3078 address=sessions[0].inside_ip_address,
3079 port=sessions[0].inside_port,
3080 protocol=sessions[0].protocol,
3081 flags=self.config_flags.NAT44_EI_IF_INSIDE)
3083 self.vapi.nat44_ei_del_session(
3084 address=sessions[1].outside_ip_address,
3085 port=sessions[1].outside_port,
3086 protocol=sessions[1].protocol)
3088 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
3089 self.assertEqual(nsessions - len(sessions), 2)
3091 self.vapi.nat44_ei_del_session(
3092 address=sessions[0].inside_ip_address,
3093 port=sessions[0].inside_port,
3094 protocol=sessions[0].protocol,
3095 flags=self.config_flags.NAT44_EI_IF_INSIDE)
3097 self.verify_no_nat44_user()
3099 def test_frag_in_order(self):
3100 """ NAT44EI translate fragments arriving in order """
3102 self.nat44_add_address(self.nat_addr)
3103 flags = self.config_flags.NAT44_EI_IF_INSIDE
3104 self.vapi.nat44_ei_interface_add_del_feature(
3105 sw_if_index=self.pg0.sw_if_index,
3106 flags=flags, is_add=1)
3107 self.vapi.nat44_ei_interface_add_del_feature(
3108 sw_if_index=self.pg1.sw_if_index,
3111 self.frag_in_order(proto=IP_PROTOS.tcp)
3112 self.frag_in_order(proto=IP_PROTOS.udp)
3113 self.frag_in_order(proto=IP_PROTOS.icmp)
3115 def test_frag_forwarding(self):
3116 """ NAT44EI forwarding fragment test """
3117 self.vapi.nat44_ei_add_del_interface_addr(
3119 sw_if_index=self.pg1.sw_if_index)
3120 flags = self.config_flags.NAT44_EI_IF_INSIDE
3121 self.vapi.nat44_ei_interface_add_del_feature(
3122 sw_if_index=self.pg0.sw_if_index,
3123 flags=flags, is_add=1)
3124 self.vapi.nat44_ei_interface_add_del_feature(
3125 sw_if_index=self.pg1.sw_if_index,
3127 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
3129 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3130 pkts = self.create_stream_frag(self.pg1,
3131 self.pg0.remote_ip4,
3135 proto=IP_PROTOS.udp)
3136 self.pg1.add_stream(pkts)
3137 self.pg_enable_capture(self.pg_interfaces)
3139 frags = self.pg0.get_capture(len(pkts))
3140 p = self.reass_frags_and_verify(frags,
3141 self.pg1.remote_ip4,
3142 self.pg0.remote_ip4)
3143 self.assertEqual(p[UDP].sport, 4789)
3144 self.assertEqual(p[UDP].dport, 4789)
3145 self.assertEqual(data, p[Raw].load)
3147 def test_reass_hairpinning(self):
3148 """ NAT44EI fragments hairpinning """
3150 server_addr = self.pg0.remote_hosts[1].ip4
3151 host_in_port = random.randint(1025, 65535)
3152 server_in_port = random.randint(1025, 65535)
3153 server_out_port = random.randint(1025, 65535)
3155 self.nat44_add_address(self.nat_addr)
3156 flags = self.config_flags.NAT44_EI_IF_INSIDE
3157 self.vapi.nat44_ei_interface_add_del_feature(
3158 sw_if_index=self.pg0.sw_if_index,
3159 flags=flags, is_add=1)
3160 self.vapi.nat44_ei_interface_add_del_feature(
3161 sw_if_index=self.pg1.sw_if_index,
3163 # add static mapping for server
3164 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3167 proto=IP_PROTOS.tcp)
3168 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3171 proto=IP_PROTOS.udp)
3172 self.nat44_add_static_mapping(server_addr, self.nat_addr)
3174 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3175 host_in_port, proto=IP_PROTOS.tcp)
3176 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3177 host_in_port, proto=IP_PROTOS.udp)
3178 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3179 host_in_port, proto=IP_PROTOS.icmp)
3181 def test_frag_out_of_order(self):
3182 """ NAT44EI translate fragments arriving out of order """
3184 self.nat44_add_address(self.nat_addr)
3185 flags = self.config_flags.NAT44_EI_IF_INSIDE
3186 self.vapi.nat44_ei_interface_add_del_feature(
3187 sw_if_index=self.pg0.sw_if_index,
3188 flags=flags, is_add=1)
3189 self.vapi.nat44_ei_interface_add_del_feature(
3190 sw_if_index=self.pg1.sw_if_index,
3193 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3194 self.frag_out_of_order(proto=IP_PROTOS.udp)
3195 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3197 def test_port_restricted(self):
3198 """ NAT44EI Port restricted NAT44EI (MAP-E CE) """
3199 self.nat44_add_address(self.nat_addr)
3200 flags = self.config_flags.NAT44_EI_IF_INSIDE
3201 self.vapi.nat44_ei_interface_add_del_feature(
3202 sw_if_index=self.pg0.sw_if_index,
3203 flags=flags, is_add=1)
3204 self.vapi.nat44_ei_interface_add_del_feature(
3205 sw_if_index=self.pg1.sw_if_index,
3207 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=1,
3212 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3213 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3214 TCP(sport=4567, dport=22))
3215 self.pg0.add_stream(p)
3216 self.pg_enable_capture(self.pg_interfaces)
3218 capture = self.pg1.get_capture(1)
3223 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3224 self.assertEqual(ip.src, self.nat_addr)
3225 self.assertEqual(tcp.dport, 22)
3226 self.assertNotEqual(tcp.sport, 4567)
3227 self.assertEqual((tcp.sport >> 6) & 63, 10)
3228 self.assert_packet_checksums_valid(p)
3230 self.logger.error(ppp("Unexpected or invalid packet:", p))
3233 def test_port_range(self):
3234 """ NAT44EI External address port range """
3235 self.nat44_add_address(self.nat_addr)
3236 flags = self.config_flags.NAT44_EI_IF_INSIDE
3237 self.vapi.nat44_ei_interface_add_del_feature(
3238 sw_if_index=self.pg0.sw_if_index,
3239 flags=flags, is_add=1)
3240 self.vapi.nat44_ei_interface_add_del_feature(
3241 sw_if_index=self.pg1.sw_if_index,
3243 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=2,
3248 for port in range(0, 5):
3249 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3250 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3251 TCP(sport=1125 + port))
3253 self.pg0.add_stream(pkts)
3254 self.pg_enable_capture(self.pg_interfaces)
3256 capture = self.pg1.get_capture(3)
3259 self.assertGreaterEqual(tcp.sport, 1025)
3260 self.assertLessEqual(tcp.sport, 1027)
3262 def test_multiple_outside_vrf(self):
3263 """ NAT44EI Multiple outside VRF """
3267 self.pg1.unconfig_ip4()
3268 self.pg2.unconfig_ip4()
3269 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3270 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3271 self.pg1.set_table_ip4(vrf_id1)
3272 self.pg2.set_table_ip4(vrf_id2)
3273 self.pg1.config_ip4()
3274 self.pg2.config_ip4()
3275 self.pg1.resolve_arp()
3276 self.pg2.resolve_arp()
3278 self.nat44_add_address(self.nat_addr)
3279 flags = self.config_flags.NAT44_EI_IF_INSIDE
3280 self.vapi.nat44_ei_interface_add_del_feature(
3281 sw_if_index=self.pg0.sw_if_index,
3282 flags=flags, is_add=1)
3283 self.vapi.nat44_ei_interface_add_del_feature(
3284 sw_if_index=self.pg1.sw_if_index,
3286 self.vapi.nat44_ei_interface_add_del_feature(
3287 sw_if_index=self.pg2.sw_if_index,
3292 pkts = self.create_stream_in(self.pg0, self.pg1)
3293 self.pg0.add_stream(pkts)
3294 self.pg_enable_capture(self.pg_interfaces)
3296 capture = self.pg1.get_capture(len(pkts))
3297 self.verify_capture_out(capture, self.nat_addr)
3299 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3300 self.pg1.add_stream(pkts)
3301 self.pg_enable_capture(self.pg_interfaces)
3303 capture = self.pg0.get_capture(len(pkts))
3304 self.verify_capture_in(capture, self.pg0)
3306 self.tcp_port_in = 60303
3307 self.udp_port_in = 60304
3308 self.icmp_id_in = 60305
3311 pkts = self.create_stream_in(self.pg0, self.pg2)
3312 self.pg0.add_stream(pkts)
3313 self.pg_enable_capture(self.pg_interfaces)
3315 capture = self.pg2.get_capture(len(pkts))
3316 self.verify_capture_out(capture, self.nat_addr)
3318 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3319 self.pg2.add_stream(pkts)
3320 self.pg_enable_capture(self.pg_interfaces)
3322 capture = self.pg0.get_capture(len(pkts))
3323 self.verify_capture_in(capture, self.pg0)
3326 self.nat44_add_address(self.nat_addr, is_add=0)
3327 self.pg1.unconfig_ip4()
3328 self.pg2.unconfig_ip4()
3329 self.pg1.set_table_ip4(0)
3330 self.pg2.set_table_ip4(0)
3331 self.pg1.config_ip4()
3332 self.pg2.config_ip4()
3333 self.pg1.resolve_arp()
3334 self.pg2.resolve_arp()
3336 def test_mss_clamping(self):
3337 """ NAT44EI TCP MSS clamping """
3338 self.nat44_add_address(self.nat_addr)
3339 flags = self.config_flags.NAT44_EI_IF_INSIDE
3340 self.vapi.nat44_ei_interface_add_del_feature(
3341 sw_if_index=self.pg0.sw_if_index,
3342 flags=flags, is_add=1)
3343 self.vapi.nat44_ei_interface_add_del_feature(
3344 sw_if_index=self.pg1.sw_if_index,
3347 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3348 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3349 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3350 flags="S", options=[('MSS', 1400)]))
3352 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1000)
3353 self.pg0.add_stream(p)
3354 self.pg_enable_capture(self.pg_interfaces)
3356 capture = self.pg1.get_capture(1)
3357 # Negotiated MSS value greater than configured - changed
3358 self.verify_mss_value(capture[0], 1000)
3360 self.vapi.nat44_ei_set_mss_clamping(enable=0, mss_value=1500)
3361 self.pg0.add_stream(p)
3362 self.pg_enable_capture(self.pg_interfaces)
3364 capture = self.pg1.get_capture(1)
3365 # MSS clamping disabled - negotiated MSS unchanged
3366 self.verify_mss_value(capture[0], 1400)
3368 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1500)
3369 self.pg0.add_stream(p)
3370 self.pg_enable_capture(self.pg_interfaces)
3372 capture = self.pg1.get_capture(1)
3373 # Negotiated MSS value smaller than configured - unchanged
3374 self.verify_mss_value(capture[0], 1400)
3376 def test_ha_send(self):
3377 """ NAT44EI Send HA session synchronization events (active) """
3378 flags = self.config_flags.NAT44_EI_IF_INSIDE
3379 self.vapi.nat44_ei_interface_add_del_feature(
3380 sw_if_index=self.pg0.sw_if_index,
3381 flags=flags, is_add=1)
3382 self.vapi.nat44_ei_interface_add_del_feature(
3383 sw_if_index=self.pg1.sw_if_index,
3385 self.nat44_add_address(self.nat_addr)
3387 self.vapi.nat44_ei_ha_set_listener(
3388 ip_address=self.pg3.local_ip4, port=12345, path_mtu=512)
3389 self.vapi.nat44_ei_ha_set_failover(
3390 ip_address=self.pg3.remote_ip4, port=12346,
3391 session_refresh_interval=10)
3392 bind_layers(UDP, HANATStateSync, sport=12345)
3395 pkts = self.create_stream_in(self.pg0, self.pg1)
3396 self.pg0.add_stream(pkts)
3397 self.pg_enable_capture(self.pg_interfaces)
3399 capture = self.pg1.get_capture(len(pkts))
3400 self.verify_capture_out(capture)
3401 # active send HA events
3402 self.vapi.nat44_ei_ha_flush()
3403 stats = self.statistics.get_counter('/nat44-ei/ha/add-event-send')
3404 self.assertEqual(stats[0][0], 3)
3405 capture = self.pg3.get_capture(1)
3407 self.assert_packet_checksums_valid(p)
3411 hanat = p[HANATStateSync]
3413 self.logger.error(ppp("Invalid packet:", p))
3416 self.assertEqual(ip.src, self.pg3.local_ip4)
3417 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3418 self.assertEqual(udp.sport, 12345)
3419 self.assertEqual(udp.dport, 12346)
3420 self.assertEqual(hanat.version, 1)
3421 self.assertEqual(hanat.thread_index, 0)
3422 self.assertEqual(hanat.count, 3)
3423 seq = hanat.sequence_number
3424 for event in hanat.events:
3425 self.assertEqual(event.event_type, 1)
3426 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3427 self.assertEqual(event.out_addr, self.nat_addr)
3428 self.assertEqual(event.fib_index, 0)
3430 # ACK received events
3431 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3432 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3433 UDP(sport=12346, dport=12345) /
3434 HANATStateSync(sequence_number=seq, flags='ACK'))
3435 self.pg3.add_stream(ack)
3437 stats = self.statistics.get_counter('/nat44-ei/ha/ack-recv')
3438 self.assertEqual(stats[0][0], 1)
3440 # delete one session
3441 self.pg_enable_capture(self.pg_interfaces)
3442 self.vapi.nat44_ei_del_session(
3443 address=self.pg0.remote_ip4, port=self.tcp_port_in,
3444 protocol=IP_PROTOS.tcp, flags=self.config_flags.NAT44_EI_IF_INSIDE)
3445 self.vapi.nat44_ei_ha_flush()
3446 stats = self.statistics.get_counter('/nat44-ei/ha/del-event-send')
3447 self.assertEqual(stats[0][0], 1)
3448 capture = self.pg3.get_capture(1)
3451 hanat = p[HANATStateSync]
3453 self.logger.error(ppp("Invalid packet:", p))
3456 self.assertGreater(hanat.sequence_number, seq)
3458 # do not send ACK, active retry send HA event again
3459 self.pg_enable_capture(self.pg_interfaces)
3461 stats = self.statistics.get_counter('/nat44-ei/ha/retry-count')
3462 self.assertEqual(stats[0][0], 3)
3463 stats = self.statistics.get_counter('/nat44-ei/ha/missed-count')
3464 self.assertEqual(stats[0][0], 1)
3465 capture = self.pg3.get_capture(3)
3466 for packet in capture:
3467 self.assertEqual(packet, p)
3469 # session counters refresh
3470 pkts = self.create_stream_out(self.pg1)
3471 self.pg1.add_stream(pkts)
3472 self.pg_enable_capture(self.pg_interfaces)
3474 self.pg0.get_capture(2)
3475 self.vapi.nat44_ei_ha_flush()
3476 stats = self.statistics.get_counter('/nat44-ei/ha/refresh-event-send')
3477 self.assertEqual(stats[0][0], 2)
3478 capture = self.pg3.get_capture(1)
3480 self.assert_packet_checksums_valid(p)
3484 hanat = p[HANATStateSync]
3486 self.logger.error(ppp("Invalid packet:", p))
3489 self.assertEqual(ip.src, self.pg3.local_ip4)
3490 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3491 self.assertEqual(udp.sport, 12345)
3492 self.assertEqual(udp.dport, 12346)
3493 self.assertEqual(hanat.version, 1)
3494 self.assertEqual(hanat.count, 2)
3495 seq = hanat.sequence_number
3496 for event in hanat.events:
3497 self.assertEqual(event.event_type, 3)
3498 self.assertEqual(event.out_addr, self.nat_addr)
3499 self.assertEqual(event.fib_index, 0)
3500 self.assertEqual(event.total_pkts, 2)
3501 self.assertGreater(event.total_bytes, 0)
3503 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3504 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3505 UDP(sport=12346, dport=12345) /
3506 HANATStateSync(sequence_number=seq, flags='ACK'))
3507 self.pg3.add_stream(ack)
3509 stats = self.statistics.get_counter('/nat44-ei/ha/ack-recv')
3510 self.assertEqual(stats[0][0], 2)
3512 def test_ha_recv(self):
3513 """ NAT44EI Receive HA session synchronization events (passive) """
3514 self.nat44_add_address(self.nat_addr)
3515 flags = self.config_flags.NAT44_EI_IF_INSIDE
3516 self.vapi.nat44_ei_interface_add_del_feature(
3517 sw_if_index=self.pg0.sw_if_index,
3518 flags=flags, is_add=1)
3519 self.vapi.nat44_ei_interface_add_del_feature(
3520 sw_if_index=self.pg1.sw_if_index,
3522 self.vapi.nat44_ei_ha_set_listener(ip_address=self.pg3.local_ip4,
3523 port=12345, path_mtu=512)
3524 bind_layers(UDP, HANATStateSync, sport=12345)
3526 self.tcp_port_out = random.randint(1025, 65535)
3527 self.udp_port_out = random.randint(1025, 65535)
3529 # send HA session add events to failover/passive
3530 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3531 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3532 UDP(sport=12346, dport=12345) /
3533 HANATStateSync(sequence_number=1, events=[
3534 Event(event_type='add', protocol='tcp',
3535 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3536 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3537 eh_addr=self.pg1.remote_ip4,
3538 ehn_addr=self.pg1.remote_ip4,
3539 eh_port=self.tcp_external_port,
3540 ehn_port=self.tcp_external_port, fib_index=0),
3541 Event(event_type='add', protocol='udp',
3542 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3543 in_port=self.udp_port_in, out_port=self.udp_port_out,
3544 eh_addr=self.pg1.remote_ip4,
3545 ehn_addr=self.pg1.remote_ip4,
3546 eh_port=self.udp_external_port,
3547 ehn_port=self.udp_external_port, fib_index=0)]))
3549 self.pg3.add_stream(p)
3550 self.pg_enable_capture(self.pg_interfaces)
3553 capture = self.pg3.get_capture(1)
3556 hanat = p[HANATStateSync]
3558 self.logger.error(ppp("Invalid packet:", p))
3561 self.assertEqual(hanat.sequence_number, 1)
3562 self.assertEqual(hanat.flags, 'ACK')
3563 self.assertEqual(hanat.version, 1)
3564 self.assertEqual(hanat.thread_index, 0)
3565 stats = self.statistics.get_counter('/nat44-ei/ha/ack-send')
3566 self.assertEqual(stats[0][0], 1)
3567 stats = self.statistics.get_counter('/nat44-ei/ha/add-event-recv')
3568 self.assertEqual(stats[0][0], 2)
3569 users = self.statistics.get_counter('/nat44-ei/total-users')
3570 self.assertEqual(users[0][0], 1)
3571 sessions = self.statistics.get_counter('/nat44-ei/total-sessions')
3572 self.assertEqual(sessions[0][0], 2)
3573 users = self.vapi.nat44_ei_user_dump()
3574 self.assertEqual(len(users), 1)
3575 self.assertEqual(str(users[0].ip_address),
3576 self.pg0.remote_ip4)
3577 # there should be 2 sessions created by HA
3578 sessions = self.vapi.nat44_ei_user_session_dump(
3579 users[0].ip_address, users[0].vrf_id)
3580 self.assertEqual(len(sessions), 2)
3581 for session in sessions:
3582 self.assertEqual(str(session.inside_ip_address),
3583 self.pg0.remote_ip4)
3584 self.assertEqual(str(session.outside_ip_address),
3586 self.assertIn(session.inside_port,
3587 [self.tcp_port_in, self.udp_port_in])
3588 self.assertIn(session.outside_port,
3589 [self.tcp_port_out, self.udp_port_out])
3590 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3592 # send HA session delete event to failover/passive
3593 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3594 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3595 UDP(sport=12346, dport=12345) /
3596 HANATStateSync(sequence_number=2, events=[
3597 Event(event_type='del', protocol='udp',
3598 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3599 in_port=self.udp_port_in, out_port=self.udp_port_out,
3600 eh_addr=self.pg1.remote_ip4,
3601 ehn_addr=self.pg1.remote_ip4,
3602 eh_port=self.udp_external_port,
3603 ehn_port=self.udp_external_port, fib_index=0)]))
3605 self.pg3.add_stream(p)
3606 self.pg_enable_capture(self.pg_interfaces)
3609 capture = self.pg3.get_capture(1)
3612 hanat = p[HANATStateSync]
3614 self.logger.error(ppp("Invalid packet:", p))
3617 self.assertEqual(hanat.sequence_number, 2)
3618 self.assertEqual(hanat.flags, 'ACK')
3619 self.assertEqual(hanat.version, 1)
3620 users = self.vapi.nat44_ei_user_dump()
3621 self.assertEqual(len(users), 1)
3622 self.assertEqual(str(users[0].ip_address),
3623 self.pg0.remote_ip4)
3624 # now we should have only 1 session, 1 deleted by HA
3625 sessions = self.vapi.nat44_ei_user_session_dump(users[0].ip_address,
3627 self.assertEqual(len(sessions), 1)
3628 stats = self.statistics.get_counter('/nat44-ei/ha/del-event-recv')
3629 self.assertEqual(stats[0][0], 1)
3631 stats = self.statistics.get_err_counter(
3632 '/err/nat44-ei-ha/pkts-processed')
3633 self.assertEqual(stats, 2)
3635 # send HA session refresh event to failover/passive
3636 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3637 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3638 UDP(sport=12346, dport=12345) /
3639 HANATStateSync(sequence_number=3, events=[
3640 Event(event_type='refresh', protocol='tcp',
3641 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3642 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3643 eh_addr=self.pg1.remote_ip4,
3644 ehn_addr=self.pg1.remote_ip4,
3645 eh_port=self.tcp_external_port,
3646 ehn_port=self.tcp_external_port, fib_index=0,
3647 total_bytes=1024, total_pkts=2)]))
3648 self.pg3.add_stream(p)
3649 self.pg_enable_capture(self.pg_interfaces)
3652 capture = self.pg3.get_capture(1)
3655 hanat = p[HANATStateSync]
3657 self.logger.error(ppp("Invalid packet:", p))
3660 self.assertEqual(hanat.sequence_number, 3)
3661 self.assertEqual(hanat.flags, 'ACK')
3662 self.assertEqual(hanat.version, 1)
3663 users = self.vapi.nat44_ei_user_dump()
3664 self.assertEqual(len(users), 1)
3665 self.assertEqual(str(users[0].ip_address),
3666 self.pg0.remote_ip4)
3667 sessions = self.vapi.nat44_ei_user_session_dump(
3668 users[0].ip_address, users[0].vrf_id)
3669 self.assertEqual(len(sessions), 1)
3670 session = sessions[0]
3671 self.assertEqual(session.total_bytes, 1024)
3672 self.assertEqual(session.total_pkts, 2)
3673 stats = self.statistics.get_counter(
3674 '/nat44-ei/ha/refresh-event-recv')
3675 self.assertEqual(stats[0][0], 1)
3677 stats = self.statistics.get_err_counter(
3678 '/err/nat44-ei-ha/pkts-processed')
3679 self.assertEqual(stats, 3)
3681 # send packet to test session created by HA
3682 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3683 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3684 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3685 self.pg1.add_stream(p)
3686 self.pg_enable_capture(self.pg_interfaces)
3688 capture = self.pg0.get_capture(1)
3694 self.logger.error(ppp("Invalid packet:", p))
3697 self.assertEqual(ip.src, self.pg1.remote_ip4)
3698 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3699 self.assertEqual(tcp.sport, self.tcp_external_port)
3700 self.assertEqual(tcp.dport, self.tcp_port_in)
3702 def reconfigure_frame_queue_nelts(self, frame_queue_nelts):
3703 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3704 self.vapi.nat44_ei_set_fq_options(frame_queue_nelts=frame_queue_nelts)
3705 # keep plugin configuration persistent
3706 self.plugin_enable()
3707 return self.vapi.nat44_ei_show_fq_options().frame_queue_nelts
3709 def test_set_frame_queue_nelts(self):
3710 """ NAT44 EI API test - worker handoff frame queue elements """
3711 self.assertEqual(self.reconfigure_frame_queue_nelts(512), 512)
3713 def show_commands_at_teardown(self):
3714 self.logger.info(self.vapi.cli("show nat44 ei timeouts"))
3715 self.logger.info(self.vapi.cli("show nat44 ei addresses"))
3716 self.logger.info(self.vapi.cli("show nat44 ei interfaces"))
3717 self.logger.info(self.vapi.cli("show nat44 ei static mappings"))
3718 self.logger.info(self.vapi.cli("show nat44 ei interface address"))
3719 self.logger.info(self.vapi.cli("show nat44 ei sessions detail"))
3720 self.logger.info(self.vapi.cli("show nat44 ei hash tables detail"))
3721 self.logger.info(self.vapi.cli("show nat44 ei ha"))
3723 self.vapi.cli("show nat44 ei addr-port-assignment-alg"))
3725 def test_outside_address_distribution(self):
3726 """ Outside address distribution based on source address """
3731 for i in range(1, x):
3733 nat_addresses.append(a)
3735 flags = self.config_flags.NAT44_EI_IF_INSIDE
3736 self.vapi.nat44_ei_interface_add_del_feature(
3737 sw_if_index=self.pg0.sw_if_index,
3738 flags=flags, is_add=1)
3739 self.vapi.nat44_ei_interface_add_del_feature(
3740 sw_if_index=self.pg1.sw_if_index,
3743 self.vapi.nat44_ei_add_del_address_range(
3744 first_ip_address=nat_addresses[0],
3745 last_ip_address=nat_addresses[-1],
3746 vrf_id=0xFFFFFFFF, is_add=1)
3748 self.pg0.generate_remote_hosts(x)
3752 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3753 IP(src=self.pg0.remote_hosts[i].ip4,
3754 dst=self.pg1.remote_ip4) /
3755 UDP(sport=7000+i, dport=80+i))
3758 self.pg0.add_stream(pkts)
3759 self.pg_enable_capture(self.pg_interfaces)
3761 recvd = self.pg1.get_capture(len(pkts))
3762 for (p_sent, p_recvd) in zip(pkts, recvd):
3763 packed = socket.inet_aton(p_sent[IP].src)
3764 numeric = struct.unpack("!L", packed)[0]
3765 numeric = socket.htonl(numeric)
3766 a = nat_addresses[(numeric-1) % len(nat_addresses)]
3767 self.assertEqual(a, p_recvd[IP].src, "Packet not translated")
3770 class TestNAT44Out2InDPO(MethodHolder):
3771 """ NAT44EI Test Cases using out2in DPO """
3774 def setUpClass(cls):
3775 super(TestNAT44Out2InDPO, cls).setUpClass()
3776 cls.vapi.cli("set log class nat44-ei level debug")
3778 cls.tcp_port_in = 6303
3779 cls.tcp_port_out = 6303
3780 cls.udp_port_in = 6304
3781 cls.udp_port_out = 6304
3782 cls.icmp_id_in = 6305
3783 cls.icmp_id_out = 6305
3784 cls.nat_addr = '10.0.0.3'
3785 cls.dst_ip4 = '192.168.70.1'
3787 cls.create_pg_interfaces(range(2))
3790 cls.pg0.config_ip4()
3791 cls.pg0.resolve_arp()
3794 cls.pg1.config_ip6()
3795 cls.pg1.resolve_ndp()
3797 r1 = VppIpRoute(cls, "::", 0,
3798 [VppRoutePath(cls.pg1.remote_ip6,
3799 cls.pg1.sw_if_index)],
3804 super(TestNAT44Out2InDPO, self).setUp()
3805 flags = self.config_flags.NAT44_EI_OUT2IN_DPO
3806 self.vapi.nat44_ei_plugin_enable_disable(enable=1, flags=flags)
3809 super(TestNAT44Out2InDPO, self).tearDown()
3810 if not self.vpp_dead:
3811 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3812 self.vapi.cli("clear logging")
3814 def configure_xlat(self):
3815 self.dst_ip6_pfx = '1:2:3::'
3816 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3818 self.dst_ip6_pfx_len = 96
3819 self.src_ip6_pfx = '4:5:6::'
3820 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3822 self.src_ip6_pfx_len = 96
3823 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
3824 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
3825 '\x00\x00\x00\x00', 0)
3827 @unittest.skip('Temporary disabled')
3828 def test_464xlat_ce(self):
3829 """ Test 464XLAT CE with NAT44EI """
3831 self.configure_xlat()
3833 flags = self.config_flags.NAT44_EI_IF_INSIDE
3834 self.vapi.nat44_ei_interface_add_del_feature(
3835 sw_if_index=self.pg0.sw_if_index,
3836 flags=flags, is_add=1)
3837 self.vapi.nat44_ei_add_del_address_range(
3838 first_ip_address=self.nat_addr_n,
3839 last_ip_address=self.nat_addr_n,
3840 vrf_id=0xFFFFFFFF, is_add=1)
3842 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3843 self.dst_ip6_pfx_len)
3844 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
3845 self.src_ip6_pfx_len)
3848 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3849 self.pg0.add_stream(pkts)
3850 self.pg_enable_capture(self.pg_interfaces)
3852 capture = self.pg1.get_capture(len(pkts))
3853 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
3856 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
3858 self.pg1.add_stream(pkts)
3859 self.pg_enable_capture(self.pg_interfaces)
3861 capture = self.pg0.get_capture(len(pkts))
3862 self.verify_capture_in(capture, self.pg0)
3864 self.vapi.nat44_ei_interface_add_del_feature(
3865 sw_if_index=self.pg0.sw_if_index,
3867 self.vapi.nat44_ei_add_del_address_range(
3868 first_ip_address=self.nat_addr_n,
3869 last_ip_address=self.nat_addr_n,
3872 @unittest.skip('Temporary disabled')
3873 def test_464xlat_ce_no_nat(self):
3874 """ Test 464XLAT CE without NAT44EI """
3876 self.configure_xlat()
3878 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3879 self.dst_ip6_pfx_len)
3880 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
3881 self.src_ip6_pfx_len)
3883 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3884 self.pg0.add_stream(pkts)
3885 self.pg_enable_capture(self.pg_interfaces)
3887 capture = self.pg1.get_capture(len(pkts))
3888 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
3889 nat_ip=out_dst_ip6, same_port=True)
3891 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
3892 self.pg1.add_stream(pkts)
3893 self.pg_enable_capture(self.pg_interfaces)
3895 capture = self.pg0.get_capture(len(pkts))
3896 self.verify_capture_in(capture, self.pg0)
3899 class TestNAT44EIMW(MethodHolder):
3900 """ NAT44EI Test Cases (multiple workers) """
3902 vpp_worker_count = 2
3904 max_translations = 10240
3908 def setUpClass(cls):
3909 super(TestNAT44EIMW, cls).setUpClass()
3910 cls.vapi.cli("set log class nat level debug")
3912 cls.tcp_port_in = 6303
3913 cls.tcp_port_out = 6303
3914 cls.udp_port_in = 6304
3915 cls.udp_port_out = 6304
3916 cls.icmp_id_in = 6305
3917 cls.icmp_id_out = 6305
3918 cls.nat_addr = '10.0.0.3'
3919 cls.ipfix_src_port = 4739
3920 cls.ipfix_domain_id = 1
3921 cls.tcp_external_port = 80
3922 cls.udp_external_port = 69
3924 cls.create_pg_interfaces(range(10))
3925 cls.interfaces = list(cls.pg_interfaces[0:4])
3927 for i in cls.interfaces:
3932 cls.pg0.generate_remote_hosts(3)
3933 cls.pg0.configure_ipv4_neighbors()
3935 cls.pg1.generate_remote_hosts(1)
3936 cls.pg1.configure_ipv4_neighbors()
3938 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
3939 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
3940 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
3942 cls.pg4._local_ip4 = "172.16.255.1"
3943 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
3944 cls.pg4.set_table_ip4(10)
3945 cls.pg5._local_ip4 = "172.17.255.3"
3946 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
3947 cls.pg5.set_table_ip4(10)
3948 cls.pg6._local_ip4 = "172.16.255.1"
3949 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
3950 cls.pg6.set_table_ip4(20)
3951 for i in cls.overlapping_interfaces:
3959 cls.pg9.generate_remote_hosts(2)
3960 cls.pg9.config_ip4()
3961 cls.vapi.sw_interface_add_del_address(
3962 sw_if_index=cls.pg9.sw_if_index,
3963 prefix="10.0.0.1/24")
3966 cls.pg9.resolve_arp()
3967 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
3968 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
3969 cls.pg9.resolve_arp()
3972 super(TestNAT44EIMW, self).setUp()
3973 self.vapi.nat44_ei_plugin_enable_disable(
3974 sessions=self.max_translations,
3975 users=self.max_users, enable=1)
3978 super(TestNAT44EIMW, self).tearDown()
3979 if not self.vpp_dead:
3980 self.vapi.nat44_ei_ipfix_enable_disable(
3981 domain_id=self.ipfix_domain_id,
3982 src_port=self.ipfix_src_port,
3984 self.ipfix_src_port = 4739
3985 self.ipfix_domain_id = 1
3987 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3988 self.vapi.cli("clear logging")
3990 def test_hairpinning(self):
3991 """ NAT44EI hairpinning - 1:1 NAPT """
3993 host = self.pg0.remote_hosts[0]
3994 server = self.pg0.remote_hosts[1]
3997 server_in_port = 5678
3998 server_out_port = 8765
4002 self.nat44_add_address(self.nat_addr)
4003 flags = self.config_flags.NAT44_EI_IF_INSIDE
4004 self.vapi.nat44_ei_interface_add_del_feature(
4005 sw_if_index=self.pg0.sw_if_index,
4006 flags=flags, is_add=1)
4007 self.vapi.nat44_ei_interface_add_del_feature(
4008 sw_if_index=self.pg1.sw_if_index,
4011 # add static mapping for server
4012 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
4013 server_in_port, server_out_port,
4014 proto=IP_PROTOS.tcp)
4016 cnt = self.statistics.get_counter('/nat44-ei/hairpinning')
4017 # send packet from host to server
4018 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4019 IP(src=host.ip4, dst=self.nat_addr) /
4020 TCP(sport=host_in_port, dport=server_out_port))
4021 self.pg0.add_stream(p)
4022 self.pg_enable_capture(self.pg_interfaces)
4024 capture = self.pg0.get_capture(1)
4029 self.assertEqual(ip.src, self.nat_addr)
4030 self.assertEqual(ip.dst, server.ip4)
4031 self.assertNotEqual(tcp.sport, host_in_port)
4032 self.assertEqual(tcp.dport, server_in_port)
4033 self.assert_packet_checksums_valid(p)
4034 host_out_port = tcp.sport
4036 self.logger.error(ppp("Unexpected or invalid packet:", p))
4039 after = self.statistics.get_counter('/nat44-ei/hairpinning')
4041 if_idx = self.pg0.sw_if_index
4042 self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1)
4044 # send reply from server to host
4045 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4046 IP(src=server.ip4, dst=self.nat_addr) /
4047 TCP(sport=server_in_port, dport=host_out_port))
4048 self.pg0.add_stream(p)
4049 self.pg_enable_capture(self.pg_interfaces)
4051 capture = self.pg0.get_capture(1)
4056 self.assertEqual(ip.src, self.nat_addr)
4057 self.assertEqual(ip.dst, host.ip4)
4058 self.assertEqual(tcp.sport, server_out_port)
4059 self.assertEqual(tcp.dport, host_in_port)
4060 self.assert_packet_checksums_valid(p)
4062 self.logger.error(ppp("Unexpected or invalid packet:", p))
4065 after = self.statistics.get_counter('/nat44-ei/hairpinning')
4066 if_idx = self.pg0.sw_if_index
4067 self.assertEqual(after[worker_1][if_idx] - cnt[worker_1][if_idx], 1)
4068 self.assertEqual(after[worker_2][if_idx] - cnt[worker_2][if_idx], 2)
4070 def test_hairpinning2(self):
4071 """ NAT44EI hairpinning - 1:1 NAT"""
4073 server1_nat_ip = "10.0.0.10"
4074 server2_nat_ip = "10.0.0.11"
4075 host = self.pg0.remote_hosts[0]
4076 server1 = self.pg0.remote_hosts[1]
4077 server2 = self.pg0.remote_hosts[2]
4078 server_tcp_port = 22
4079 server_udp_port = 20
4081 self.nat44_add_address(self.nat_addr)
4082 flags = self.config_flags.NAT44_EI_IF_INSIDE
4083 self.vapi.nat44_ei_interface_add_del_feature(
4084 sw_if_index=self.pg0.sw_if_index,
4085 flags=flags, is_add=1)
4086 self.vapi.nat44_ei_interface_add_del_feature(
4087 sw_if_index=self.pg1.sw_if_index,
4090 # add static mapping for servers
4091 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
4092 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
4096 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4097 IP(src=host.ip4, dst=server1_nat_ip) /
4098 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4100 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4101 IP(src=host.ip4, dst=server1_nat_ip) /
4102 UDP(sport=self.udp_port_in, dport=server_udp_port))
4104 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4105 IP(src=host.ip4, dst=server1_nat_ip) /
4106 ICMP(id=self.icmp_id_in, type='echo-request'))
4108 self.pg0.add_stream(pkts)
4109 self.pg_enable_capture(self.pg_interfaces)
4111 capture = self.pg0.get_capture(len(pkts))
4112 for packet in capture:
4114 self.assertEqual(packet[IP].src, self.nat_addr)
4115 self.assertEqual(packet[IP].dst, server1.ip4)
4116 if packet.haslayer(TCP):
4117 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
4118 self.assertEqual(packet[TCP].dport, server_tcp_port)
4119 self.tcp_port_out = packet[TCP].sport
4120 self.assert_packet_checksums_valid(packet)
4121 elif packet.haslayer(UDP):
4122 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
4123 self.assertEqual(packet[UDP].dport, server_udp_port)
4124 self.udp_port_out = packet[UDP].sport
4126 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
4127 self.icmp_id_out = packet[ICMP].id
4129 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4134 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4135 IP(src=server1.ip4, dst=self.nat_addr) /
4136 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4138 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4139 IP(src=server1.ip4, dst=self.nat_addr) /
4140 UDP(sport=server_udp_port, dport=self.udp_port_out))
4142 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4143 IP(src=server1.ip4, dst=self.nat_addr) /
4144 ICMP(id=self.icmp_id_out, type='echo-reply'))
4146 self.pg0.add_stream(pkts)
4147 self.pg_enable_capture(self.pg_interfaces)
4149 capture = self.pg0.get_capture(len(pkts))
4150 for packet in capture:
4152 self.assertEqual(packet[IP].src, server1_nat_ip)
4153 self.assertEqual(packet[IP].dst, host.ip4)
4154 if packet.haslayer(TCP):
4155 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4156 self.assertEqual(packet[TCP].sport, server_tcp_port)
4157 self.assert_packet_checksums_valid(packet)
4158 elif packet.haslayer(UDP):
4159 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4160 self.assertEqual(packet[UDP].sport, server_udp_port)
4162 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4164 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4167 # server2 to server1
4169 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4170 IP(src=server2.ip4, dst=server1_nat_ip) /
4171 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4173 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4174 IP(src=server2.ip4, dst=server1_nat_ip) /
4175 UDP(sport=self.udp_port_in, dport=server_udp_port))
4177 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4178 IP(src=server2.ip4, dst=server1_nat_ip) /
4179 ICMP(id=self.icmp_id_in, type='echo-request'))
4181 self.pg0.add_stream(pkts)
4182 self.pg_enable_capture(self.pg_interfaces)
4184 capture = self.pg0.get_capture(len(pkts))
4185 for packet in capture:
4187 self.assertEqual(packet[IP].src, server2_nat_ip)
4188 self.assertEqual(packet[IP].dst, server1.ip4)
4189 if packet.haslayer(TCP):
4190 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
4191 self.assertEqual(packet[TCP].dport, server_tcp_port)
4192 self.tcp_port_out = packet[TCP].sport
4193 self.assert_packet_checksums_valid(packet)
4194 elif packet.haslayer(UDP):
4195 self.assertEqual(packet[UDP].sport, self.udp_port_in)
4196 self.assertEqual(packet[UDP].dport, server_udp_port)
4197 self.udp_port_out = packet[UDP].sport
4199 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4200 self.icmp_id_out = packet[ICMP].id
4202 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4205 # server1 to server2
4207 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4208 IP(src=server1.ip4, dst=server2_nat_ip) /
4209 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4211 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4212 IP(src=server1.ip4, dst=server2_nat_ip) /
4213 UDP(sport=server_udp_port, dport=self.udp_port_out))
4215 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4216 IP(src=server1.ip4, dst=server2_nat_ip) /
4217 ICMP(id=self.icmp_id_out, type='echo-reply'))
4219 self.pg0.add_stream(pkts)
4220 self.pg_enable_capture(self.pg_interfaces)
4222 capture = self.pg0.get_capture(len(pkts))
4223 for packet in capture:
4225 self.assertEqual(packet[IP].src, server1_nat_ip)
4226 self.assertEqual(packet[IP].dst, server2.ip4)
4227 if packet.haslayer(TCP):
4228 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4229 self.assertEqual(packet[TCP].sport, server_tcp_port)
4230 self.assert_packet_checksums_valid(packet)
4231 elif packet.haslayer(UDP):
4232 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4233 self.assertEqual(packet[UDP].sport, server_udp_port)
4235 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4237 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4241 if __name__ == '__main__':
4242 unittest.main(testRunner=VppTestRunner)