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['/nat44-ei/total-users']
636 self.assertEqual(users[0][0], 0)
637 sessions = self.statistics['/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 def get_nat44_ei_in2out_worker_index(ip, vpp_worker_count):
856 if 0 == vpp_worker_count:
858 numeric = socket.inet_aton(ip)
859 numeric = struct.unpack("!L", numeric)[0]
860 numeric = socket.htonl(numeric)
861 h = numeric + (numeric >> 8) + (numeric >> 16) + (numeric >> 24)
862 return 1 + h % vpp_worker_count
865 @tag_fixme_vpp_workers
866 class TestNAT44EI(MethodHolder):
867 """ NAT44EI Test Cases """
869 max_translations = 10240
874 super(TestNAT44EI, cls).setUpClass()
875 cls.vapi.cli("set log class nat44-ei level debug")
877 cls.tcp_port_in = 6303
878 cls.tcp_port_out = 6303
879 cls.udp_port_in = 6304
880 cls.udp_port_out = 6304
881 cls.icmp_id_in = 6305
882 cls.icmp_id_out = 6305
883 cls.nat_addr = '10.0.0.3'
884 cls.ipfix_src_port = 4739
885 cls.ipfix_domain_id = 1
886 cls.tcp_external_port = 80
887 cls.udp_external_port = 69
889 cls.create_pg_interfaces(range(10))
890 cls.interfaces = list(cls.pg_interfaces[0:4])
892 for i in cls.interfaces:
897 cls.pg0.generate_remote_hosts(3)
898 cls.pg0.configure_ipv4_neighbors()
900 cls.pg1.generate_remote_hosts(1)
901 cls.pg1.configure_ipv4_neighbors()
903 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
904 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
905 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
907 cls.pg4._local_ip4 = "172.16.255.1"
908 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
909 cls.pg4.set_table_ip4(10)
910 cls.pg5._local_ip4 = "172.17.255.3"
911 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
912 cls.pg5.set_table_ip4(10)
913 cls.pg6._local_ip4 = "172.16.255.1"
914 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
915 cls.pg6.set_table_ip4(20)
916 for i in cls.overlapping_interfaces:
924 cls.pg9.generate_remote_hosts(2)
926 cls.vapi.sw_interface_add_del_address(
927 sw_if_index=cls.pg9.sw_if_index,
928 prefix="10.0.0.1/24")
931 cls.pg9.resolve_arp()
932 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
933 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
934 cls.pg9.resolve_arp()
936 def plugin_enable(self):
937 self.vapi.nat44_ei_plugin_enable_disable(
938 sessions=self.max_translations,
939 users=self.max_users, enable=1)
942 super(TestNAT44EI, self).setUp()
946 super(TestNAT44EI, self).tearDown()
947 if not self.vpp_dead:
948 self.vapi.nat44_ei_ipfix_enable_disable(
949 domain_id=self.ipfix_domain_id, src_port=self.ipfix_src_port,
951 self.ipfix_src_port = 4739
952 self.ipfix_domain_id = 1
954 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
955 self.vapi.cli("clear logging")
957 def test_clear_sessions(self):
958 """ NAT44EI session clearing test """
960 self.nat44_add_address(self.nat_addr)
961 flags = self.config_flags.NAT44_EI_IF_INSIDE
962 self.vapi.nat44_ei_interface_add_del_feature(
963 sw_if_index=self.pg0.sw_if_index,
964 flags=flags, is_add=1)
965 self.vapi.nat44_ei_interface_add_del_feature(
966 sw_if_index=self.pg1.sw_if_index,
969 pkts = self.create_stream_in(self.pg0, self.pg1)
970 self.pg0.add_stream(pkts)
971 self.pg_enable_capture(self.pg_interfaces)
973 capture = self.pg1.get_capture(len(pkts))
974 self.verify_capture_out(capture)
976 sessions = self.statistics['/nat44-ei/total-sessions']
977 self.assertGreater(sessions[:, 0].sum(), 0, "Session count invalid")
978 self.logger.info("sessions before clearing: %s" % sessions[0][0])
980 self.vapi.cli("clear nat44 ei sessions")
982 sessions = self.statistics['/nat44-ei/total-sessions']
983 self.assertEqual(sessions[:, 0].sum(), 0, "Session count invalid")
984 self.logger.info("sessions after clearing: %s" % sessions[0][0])
986 def test_dynamic(self):
987 """ NAT44EI dynamic translation test """
988 self.nat44_add_address(self.nat_addr)
989 flags = self.config_flags.NAT44_EI_IF_INSIDE
990 self.vapi.nat44_ei_interface_add_del_feature(
991 sw_if_index=self.pg0.sw_if_index,
992 flags=flags, is_add=1)
993 self.vapi.nat44_ei_interface_add_del_feature(
994 sw_if_index=self.pg1.sw_if_index,
998 tcpn = self.statistics['/nat44-ei/in2out/slowpath/tcp']
999 udpn = self.statistics['/nat44-ei/in2out/slowpath/udp']
1000 icmpn = self.statistics['/nat44-ei/in2out/slowpath/icmp']
1001 drops = self.statistics['/nat44-ei/in2out/slowpath/drops']
1003 pkts = self.create_stream_in(self.pg0, self.pg1)
1004 self.pg0.add_stream(pkts)
1005 self.pg_enable_capture(self.pg_interfaces)
1007 capture = self.pg1.get_capture(len(pkts))
1008 self.verify_capture_out(capture)
1010 if_idx = self.pg0.sw_if_index
1011 cnt = self.statistics['/nat44-ei/in2out/slowpath/tcp']
1012 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
1013 cnt = self.statistics['/nat44-ei/in2out/slowpath/udp']
1014 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
1015 cnt = self.statistics['/nat44-ei/in2out/slowpath/icmp']
1016 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
1017 cnt = self.statistics['/nat44-ei/in2out/slowpath/drops']
1018 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
1021 tcpn = self.statistics['/nat44-ei/out2in/slowpath/tcp']
1022 udpn = self.statistics['/nat44-ei/out2in/slowpath/udp']
1023 icmpn = self.statistics['/nat44-ei/out2in/slowpath/icmp']
1024 drops = self.statistics['/nat44-ei/out2in/slowpath/drops']
1026 pkts = self.create_stream_out(self.pg1)
1027 self.pg1.add_stream(pkts)
1028 self.pg_enable_capture(self.pg_interfaces)
1030 capture = self.pg0.get_capture(len(pkts))
1031 self.verify_capture_in(capture, self.pg0)
1033 if_idx = self.pg1.sw_if_index
1034 cnt = self.statistics['/nat44-ei/out2in/slowpath/tcp']
1035 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
1036 cnt = self.statistics['/nat44-ei/out2in/slowpath/udp']
1037 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
1038 cnt = self.statistics['/nat44-ei/out2in/slowpath/icmp']
1039 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
1040 cnt = self.statistics['/nat44-ei/out2in/slowpath/drops']
1041 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
1043 users = self.statistics['/nat44-ei/total-users']
1044 self.assertEqual(users[:, 0].sum(), 1)
1045 sessions = self.statistics['/nat44-ei/total-sessions']
1046 self.assertEqual(sessions[:, 0].sum(), 3)
1048 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1049 """ NAT44EI handling of client packets with TTL=1 """
1051 self.nat44_add_address(self.nat_addr)
1052 flags = self.config_flags.NAT44_EI_IF_INSIDE
1053 self.vapi.nat44_ei_interface_add_del_feature(
1054 sw_if_index=self.pg0.sw_if_index,
1055 flags=flags, is_add=1)
1056 self.vapi.nat44_ei_interface_add_del_feature(
1057 sw_if_index=self.pg1.sw_if_index,
1060 # Client side - generate traffic
1061 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1062 self.pg0.add_stream(pkts)
1063 self.pg_enable_capture(self.pg_interfaces)
1066 # Client side - verify ICMP type 11 packets
1067 capture = self.pg0.get_capture(len(pkts))
1068 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1070 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1071 """ NAT44EI handling of server packets with TTL=1 """
1073 self.nat44_add_address(self.nat_addr)
1074 flags = self.config_flags.NAT44_EI_IF_INSIDE
1075 self.vapi.nat44_ei_interface_add_del_feature(
1076 sw_if_index=self.pg0.sw_if_index,
1077 flags=flags, is_add=1)
1078 self.vapi.nat44_ei_interface_add_del_feature(
1079 sw_if_index=self.pg1.sw_if_index,
1082 # Client side - create sessions
1083 pkts = self.create_stream_in(self.pg0, self.pg1)
1084 self.pg0.add_stream(pkts)
1085 self.pg_enable_capture(self.pg_interfaces)
1088 # Server side - generate traffic
1089 capture = self.pg1.get_capture(len(pkts))
1090 self.verify_capture_out(capture)
1091 pkts = self.create_stream_out(self.pg1, ttl=1)
1092 self.pg1.add_stream(pkts)
1093 self.pg_enable_capture(self.pg_interfaces)
1096 # Server side - verify ICMP type 11 packets
1097 capture = self.pg1.get_capture(len(pkts))
1098 self.verify_capture_out_with_icmp_errors(capture,
1099 src_ip=self.pg1.local_ip4)
1101 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1102 """ NAT44EI handling of error responses to client packets with TTL=2
1105 self.nat44_add_address(self.nat_addr)
1106 flags = self.config_flags.NAT44_EI_IF_INSIDE
1107 self.vapi.nat44_ei_interface_add_del_feature(
1108 sw_if_index=self.pg0.sw_if_index,
1109 flags=flags, is_add=1)
1110 self.vapi.nat44_ei_interface_add_del_feature(
1111 sw_if_index=self.pg1.sw_if_index,
1114 # Client side - generate traffic
1115 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1116 self.pg0.add_stream(pkts)
1117 self.pg_enable_capture(self.pg_interfaces)
1120 # Server side - simulate ICMP type 11 response
1121 capture = self.pg1.get_capture(len(pkts))
1122 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1123 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1124 ICMP(type=11) / packet[IP] for packet in capture]
1125 self.pg1.add_stream(pkts)
1126 self.pg_enable_capture(self.pg_interfaces)
1129 # Client side - verify ICMP type 11 packets
1130 capture = self.pg0.get_capture(len(pkts))
1131 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1133 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1134 """ NAT44EI handling of error responses to server packets with TTL=2
1137 self.nat44_add_address(self.nat_addr)
1138 flags = self.config_flags.NAT44_EI_IF_INSIDE
1139 self.vapi.nat44_ei_interface_add_del_feature(
1140 sw_if_index=self.pg0.sw_if_index,
1141 flags=flags, is_add=1)
1142 self.vapi.nat44_ei_interface_add_del_feature(
1143 sw_if_index=self.pg1.sw_if_index,
1146 # Client side - create sessions
1147 pkts = self.create_stream_in(self.pg0, self.pg1)
1148 self.pg0.add_stream(pkts)
1149 self.pg_enable_capture(self.pg_interfaces)
1152 # Server side - generate traffic
1153 capture = self.pg1.get_capture(len(pkts))
1154 self.verify_capture_out(capture)
1155 pkts = self.create_stream_out(self.pg1, ttl=2)
1156 self.pg1.add_stream(pkts)
1157 self.pg_enable_capture(self.pg_interfaces)
1160 # Client side - simulate ICMP type 11 response
1161 capture = self.pg0.get_capture(len(pkts))
1162 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1163 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1164 ICMP(type=11) / packet[IP] for packet in capture]
1165 self.pg0.add_stream(pkts)
1166 self.pg_enable_capture(self.pg_interfaces)
1169 # Server side - verify ICMP type 11 packets
1170 capture = self.pg1.get_capture(len(pkts))
1171 self.verify_capture_out_with_icmp_errors(capture)
1173 def test_ping_out_interface_from_outside(self):
1174 """ NAT44EI ping out interface from outside network """
1176 self.nat44_add_address(self.nat_addr)
1177 flags = self.config_flags.NAT44_EI_IF_INSIDE
1178 self.vapi.nat44_ei_interface_add_del_feature(
1179 sw_if_index=self.pg0.sw_if_index,
1180 flags=flags, is_add=1)
1181 self.vapi.nat44_ei_interface_add_del_feature(
1182 sw_if_index=self.pg1.sw_if_index,
1185 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1186 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1187 ICMP(id=self.icmp_id_out, type='echo-request'))
1189 self.pg1.add_stream(pkts)
1190 self.pg_enable_capture(self.pg_interfaces)
1192 capture = self.pg1.get_capture(len(pkts))
1195 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1196 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1197 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1198 self.assertEqual(packet[ICMP].type, 0) # echo reply
1200 self.logger.error(ppp("Unexpected or invalid packet "
1201 "(outside network):", packet))
1204 def test_ping_internal_host_from_outside(self):
1205 """ NAT44EI ping internal host from outside network """
1207 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1208 flags = self.config_flags.NAT44_EI_IF_INSIDE
1209 self.vapi.nat44_ei_interface_add_del_feature(
1210 sw_if_index=self.pg0.sw_if_index,
1211 flags=flags, is_add=1)
1212 self.vapi.nat44_ei_interface_add_del_feature(
1213 sw_if_index=self.pg1.sw_if_index,
1217 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1218 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1219 ICMP(id=self.icmp_id_out, type='echo-request'))
1220 self.pg1.add_stream(pkt)
1221 self.pg_enable_capture(self.pg_interfaces)
1223 capture = self.pg0.get_capture(1)
1224 self.verify_capture_in(capture, self.pg0)
1225 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1228 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1229 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1230 ICMP(id=self.icmp_id_in, type='echo-reply'))
1231 self.pg0.add_stream(pkt)
1232 self.pg_enable_capture(self.pg_interfaces)
1234 capture = self.pg1.get_capture(1)
1235 self.verify_capture_out(capture, same_port=True)
1236 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1238 def test_forwarding(self):
1239 """ NAT44EI forwarding test """
1241 flags = self.config_flags.NAT44_EI_IF_INSIDE
1242 self.vapi.nat44_ei_interface_add_del_feature(
1243 sw_if_index=self.pg0.sw_if_index,
1244 flags=flags, is_add=1)
1245 self.vapi.nat44_ei_interface_add_del_feature(
1246 sw_if_index=self.pg1.sw_if_index,
1248 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
1250 real_ip = self.pg0.remote_ip4
1251 alias_ip = self.nat_addr
1252 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1253 self.vapi.nat44_ei_add_del_static_mapping(
1254 is_add=1, local_ip_address=real_ip,
1255 external_ip_address=alias_ip,
1256 external_sw_if_index=0xFFFFFFFF,
1260 # static mapping match
1262 pkts = self.create_stream_out(self.pg1)
1263 self.pg1.add_stream(pkts)
1264 self.pg_enable_capture(self.pg_interfaces)
1266 capture = self.pg0.get_capture(len(pkts))
1267 self.verify_capture_in(capture, self.pg0)
1269 pkts = self.create_stream_in(self.pg0, self.pg1)
1270 self.pg0.add_stream(pkts)
1271 self.pg_enable_capture(self.pg_interfaces)
1273 capture = self.pg1.get_capture(len(pkts))
1274 self.verify_capture_out(capture, same_port=True)
1276 # no static mapping match
1278 host0 = self.pg0.remote_hosts[0]
1279 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1281 pkts = self.create_stream_out(self.pg1,
1282 dst_ip=self.pg0.remote_ip4,
1283 use_inside_ports=True)
1284 self.pg1.add_stream(pkts)
1285 self.pg_enable_capture(self.pg_interfaces)
1287 capture = self.pg0.get_capture(len(pkts))
1288 self.verify_capture_in(capture, self.pg0)
1290 pkts = self.create_stream_in(self.pg0, self.pg1)
1291 self.pg0.add_stream(pkts)
1292 self.pg_enable_capture(self.pg_interfaces)
1294 capture = self.pg1.get_capture(len(pkts))
1295 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1298 self.pg0.remote_hosts[0] = host0
1301 self.vapi.nat44_ei_forwarding_enable_disable(enable=0)
1302 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1303 self.vapi.nat44_ei_add_del_static_mapping(
1305 local_ip_address=real_ip,
1306 external_ip_address=alias_ip,
1307 external_sw_if_index=0xFFFFFFFF,
1310 def test_static_in(self):
1311 """ NAT44EI 1:1 NAT initialized from inside network """
1313 nat_ip = "10.0.0.10"
1314 self.tcp_port_out = 6303
1315 self.udp_port_out = 6304
1316 self.icmp_id_out = 6305
1318 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1319 flags = self.config_flags.NAT44_EI_IF_INSIDE
1320 self.vapi.nat44_ei_interface_add_del_feature(
1321 sw_if_index=self.pg0.sw_if_index,
1322 flags=flags, is_add=1)
1323 self.vapi.nat44_ei_interface_add_del_feature(
1324 sw_if_index=self.pg1.sw_if_index,
1326 sm = self.vapi.nat44_ei_static_mapping_dump()
1327 self.assertEqual(len(sm), 1)
1328 self.assertEqual(sm[0].tag, '')
1329 self.assertEqual(sm[0].protocol, 0)
1330 self.assertEqual(sm[0].local_port, 0)
1331 self.assertEqual(sm[0].external_port, 0)
1334 pkts = self.create_stream_in(self.pg0, self.pg1)
1335 self.pg0.add_stream(pkts)
1336 self.pg_enable_capture(self.pg_interfaces)
1338 capture = self.pg1.get_capture(len(pkts))
1339 self.verify_capture_out(capture, nat_ip, True)
1342 pkts = self.create_stream_out(self.pg1, nat_ip)
1343 self.pg1.add_stream(pkts)
1344 self.pg_enable_capture(self.pg_interfaces)
1346 capture = self.pg0.get_capture(len(pkts))
1347 self.verify_capture_in(capture, self.pg0)
1349 def test_static_out(self):
1350 """ NAT44EI 1:1 NAT initialized from outside network """
1352 nat_ip = "10.0.0.20"
1353 self.tcp_port_out = 6303
1354 self.udp_port_out = 6304
1355 self.icmp_id_out = 6305
1358 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1359 flags = self.config_flags.NAT44_EI_IF_INSIDE
1360 self.vapi.nat44_ei_interface_add_del_feature(
1361 sw_if_index=self.pg0.sw_if_index,
1362 flags=flags, is_add=1)
1363 self.vapi.nat44_ei_interface_add_del_feature(
1364 sw_if_index=self.pg1.sw_if_index,
1366 sm = self.vapi.nat44_ei_static_mapping_dump()
1367 self.assertEqual(len(sm), 1)
1368 self.assertEqual(sm[0].tag, tag)
1371 pkts = self.create_stream_out(self.pg1, nat_ip)
1372 self.pg1.add_stream(pkts)
1373 self.pg_enable_capture(self.pg_interfaces)
1375 capture = self.pg0.get_capture(len(pkts))
1376 self.verify_capture_in(capture, self.pg0)
1379 pkts = self.create_stream_in(self.pg0, self.pg1)
1380 self.pg0.add_stream(pkts)
1381 self.pg_enable_capture(self.pg_interfaces)
1383 capture = self.pg1.get_capture(len(pkts))
1384 self.verify_capture_out(capture, nat_ip, True)
1386 def test_static_with_port_in(self):
1387 """ NAT44EI 1:1 NAPT initialized from inside network """
1389 self.tcp_port_out = 3606
1390 self.udp_port_out = 3607
1391 self.icmp_id_out = 3608
1393 self.nat44_add_address(self.nat_addr)
1394 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1395 self.tcp_port_in, self.tcp_port_out,
1396 proto=IP_PROTOS.tcp)
1397 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1398 self.udp_port_in, self.udp_port_out,
1399 proto=IP_PROTOS.udp)
1400 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1401 self.icmp_id_in, self.icmp_id_out,
1402 proto=IP_PROTOS.icmp)
1403 flags = self.config_flags.NAT44_EI_IF_INSIDE
1404 self.vapi.nat44_ei_interface_add_del_feature(
1405 sw_if_index=self.pg0.sw_if_index,
1406 flags=flags, is_add=1)
1407 self.vapi.nat44_ei_interface_add_del_feature(
1408 sw_if_index=self.pg1.sw_if_index,
1412 pkts = self.create_stream_in(self.pg0, self.pg1)
1413 self.pg0.add_stream(pkts)
1414 self.pg_enable_capture(self.pg_interfaces)
1416 capture = self.pg1.get_capture(len(pkts))
1417 self.verify_capture_out(capture)
1420 pkts = self.create_stream_out(self.pg1)
1421 self.pg1.add_stream(pkts)
1422 self.pg_enable_capture(self.pg_interfaces)
1424 capture = self.pg0.get_capture(len(pkts))
1425 self.verify_capture_in(capture, self.pg0)
1427 def test_static_with_port_out(self):
1428 """ NAT44EI 1:1 NAPT initialized from outside network """
1430 self.tcp_port_out = 30606
1431 self.udp_port_out = 30607
1432 self.icmp_id_out = 30608
1434 self.nat44_add_address(self.nat_addr)
1435 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1436 self.tcp_port_in, self.tcp_port_out,
1437 proto=IP_PROTOS.tcp)
1438 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1439 self.udp_port_in, self.udp_port_out,
1440 proto=IP_PROTOS.udp)
1441 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1442 self.icmp_id_in, self.icmp_id_out,
1443 proto=IP_PROTOS.icmp)
1444 flags = self.config_flags.NAT44_EI_IF_INSIDE
1445 self.vapi.nat44_ei_interface_add_del_feature(
1446 sw_if_index=self.pg0.sw_if_index,
1447 flags=flags, is_add=1)
1448 self.vapi.nat44_ei_interface_add_del_feature(
1449 sw_if_index=self.pg1.sw_if_index,
1453 pkts = self.create_stream_out(self.pg1)
1454 self.pg1.add_stream(pkts)
1455 self.pg_enable_capture(self.pg_interfaces)
1457 capture = self.pg0.get_capture(len(pkts))
1458 self.verify_capture_in(capture, self.pg0)
1461 pkts = self.create_stream_in(self.pg0, self.pg1)
1462 self.pg0.add_stream(pkts)
1463 self.pg_enable_capture(self.pg_interfaces)
1465 capture = self.pg1.get_capture(len(pkts))
1466 self.verify_capture_out(capture)
1468 def test_static_vrf_aware(self):
1469 """ NAT44EI 1:1 NAT VRF awareness """
1471 nat_ip1 = "10.0.0.30"
1472 nat_ip2 = "10.0.0.40"
1473 self.tcp_port_out = 6303
1474 self.udp_port_out = 6304
1475 self.icmp_id_out = 6305
1477 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1479 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1481 flags = self.config_flags.NAT44_EI_IF_INSIDE
1482 self.vapi.nat44_ei_interface_add_del_feature(
1483 sw_if_index=self.pg3.sw_if_index,
1485 self.vapi.nat44_ei_interface_add_del_feature(
1486 sw_if_index=self.pg0.sw_if_index,
1487 flags=flags, is_add=1)
1488 self.vapi.nat44_ei_interface_add_del_feature(
1489 sw_if_index=self.pg4.sw_if_index,
1490 flags=flags, is_add=1)
1492 # inside interface VRF match NAT44EI static mapping VRF
1493 pkts = self.create_stream_in(self.pg4, self.pg3)
1494 self.pg4.add_stream(pkts)
1495 self.pg_enable_capture(self.pg_interfaces)
1497 capture = self.pg3.get_capture(len(pkts))
1498 self.verify_capture_out(capture, nat_ip1, True)
1500 # inside interface VRF don't match NAT44EI static mapping VRF (packets
1502 pkts = self.create_stream_in(self.pg0, self.pg3)
1503 self.pg0.add_stream(pkts)
1504 self.pg_enable_capture(self.pg_interfaces)
1506 self.pg3.assert_nothing_captured()
1508 def test_dynamic_to_static(self):
1509 """ NAT44EI Switch from dynamic translation to 1:1NAT """
1510 nat_ip = "10.0.0.10"
1511 self.tcp_port_out = 6303
1512 self.udp_port_out = 6304
1513 self.icmp_id_out = 6305
1515 self.nat44_add_address(self.nat_addr)
1516 flags = self.config_flags.NAT44_EI_IF_INSIDE
1517 self.vapi.nat44_ei_interface_add_del_feature(
1518 sw_if_index=self.pg0.sw_if_index,
1519 flags=flags, is_add=1)
1520 self.vapi.nat44_ei_interface_add_del_feature(
1521 sw_if_index=self.pg1.sw_if_index,
1525 pkts = self.create_stream_in(self.pg0, self.pg1)
1526 self.pg0.add_stream(pkts)
1527 self.pg_enable_capture(self.pg_interfaces)
1529 capture = self.pg1.get_capture(len(pkts))
1530 self.verify_capture_out(capture)
1533 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1534 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
1535 self.assertEqual(len(sessions), 0)
1536 pkts = self.create_stream_in(self.pg0, self.pg1)
1537 self.pg0.add_stream(pkts)
1538 self.pg_enable_capture(self.pg_interfaces)
1540 capture = self.pg1.get_capture(len(pkts))
1541 self.verify_capture_out(capture, nat_ip, True)
1543 def test_identity_nat(self):
1544 """ NAT44EI Identity NAT """
1545 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1546 self.vapi.nat44_ei_add_del_identity_mapping(
1547 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1548 flags=flags, is_add=1)
1549 flags = self.config_flags.NAT44_EI_IF_INSIDE
1550 self.vapi.nat44_ei_interface_add_del_feature(
1551 sw_if_index=self.pg0.sw_if_index,
1552 flags=flags, is_add=1)
1553 self.vapi.nat44_ei_interface_add_del_feature(
1554 sw_if_index=self.pg1.sw_if_index,
1557 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1558 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1559 TCP(sport=12345, dport=56789))
1560 self.pg1.add_stream(p)
1561 self.pg_enable_capture(self.pg_interfaces)
1563 capture = self.pg0.get_capture(1)
1568 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1569 self.assertEqual(ip.src, self.pg1.remote_ip4)
1570 self.assertEqual(tcp.dport, 56789)
1571 self.assertEqual(tcp.sport, 12345)
1572 self.assert_packet_checksums_valid(p)
1574 self.logger.error(ppp("Unexpected or invalid packet:", p))
1577 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
1578 self.assertEqual(len(sessions), 0)
1579 flags = self.config_flags.NAT44_EI_ADDR_ONLY_MAPPING
1580 self.vapi.nat44_ei_add_del_identity_mapping(
1581 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1582 flags=flags, vrf_id=1, is_add=1)
1583 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
1584 self.assertEqual(len(identity_mappings), 2)
1586 def test_multiple_inside_interfaces(self):
1587 """ NAT44EI multiple non-overlapping address space inside interfaces
1590 self.nat44_add_address(self.nat_addr)
1591 flags = self.config_flags.NAT44_EI_IF_INSIDE
1592 self.vapi.nat44_ei_interface_add_del_feature(
1593 sw_if_index=self.pg0.sw_if_index,
1594 flags=flags, is_add=1)
1595 self.vapi.nat44_ei_interface_add_del_feature(
1596 sw_if_index=self.pg1.sw_if_index,
1597 flags=flags, is_add=1)
1598 self.vapi.nat44_ei_interface_add_del_feature(
1599 sw_if_index=self.pg3.sw_if_index,
1602 # between two NAT44EI inside interfaces (no translation)
1603 pkts = self.create_stream_in(self.pg0, self.pg1)
1604 self.pg0.add_stream(pkts)
1605 self.pg_enable_capture(self.pg_interfaces)
1607 capture = self.pg1.get_capture(len(pkts))
1608 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1610 # from inside to interface without translation
1611 pkts = self.create_stream_in(self.pg0, self.pg2)
1612 self.pg0.add_stream(pkts)
1613 self.pg_enable_capture(self.pg_interfaces)
1615 capture = self.pg2.get_capture(len(pkts))
1616 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1618 # in2out 1st interface
1619 pkts = self.create_stream_in(self.pg0, self.pg3)
1620 self.pg0.add_stream(pkts)
1621 self.pg_enable_capture(self.pg_interfaces)
1623 capture = self.pg3.get_capture(len(pkts))
1624 self.verify_capture_out(capture)
1626 # out2in 1st interface
1627 pkts = self.create_stream_out(self.pg3)
1628 self.pg3.add_stream(pkts)
1629 self.pg_enable_capture(self.pg_interfaces)
1631 capture = self.pg0.get_capture(len(pkts))
1632 self.verify_capture_in(capture, self.pg0)
1634 # in2out 2nd interface
1635 pkts = self.create_stream_in(self.pg1, self.pg3)
1636 self.pg1.add_stream(pkts)
1637 self.pg_enable_capture(self.pg_interfaces)
1639 capture = self.pg3.get_capture(len(pkts))
1640 self.verify_capture_out(capture)
1642 # out2in 2nd interface
1643 pkts = self.create_stream_out(self.pg3)
1644 self.pg3.add_stream(pkts)
1645 self.pg_enable_capture(self.pg_interfaces)
1647 capture = self.pg1.get_capture(len(pkts))
1648 self.verify_capture_in(capture, self.pg1)
1650 def test_inside_overlapping_interfaces(self):
1651 """ NAT44EI multiple inside interfaces with overlapping address space
1654 static_nat_ip = "10.0.0.10"
1655 self.nat44_add_address(self.nat_addr)
1656 flags = self.config_flags.NAT44_EI_IF_INSIDE
1657 self.vapi.nat44_ei_interface_add_del_feature(
1658 sw_if_index=self.pg3.sw_if_index,
1660 self.vapi.nat44_ei_interface_add_del_feature(
1661 sw_if_index=self.pg4.sw_if_index,
1662 flags=flags, is_add=1)
1663 self.vapi.nat44_ei_interface_add_del_feature(
1664 sw_if_index=self.pg5.sw_if_index,
1665 flags=flags, is_add=1)
1666 self.vapi.nat44_ei_interface_add_del_feature(
1667 sw_if_index=self.pg6.sw_if_index,
1668 flags=flags, is_add=1)
1669 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1672 # between NAT44EI inside interfaces with same VRF (no translation)
1673 pkts = self.create_stream_in(self.pg4, self.pg5)
1674 self.pg4.add_stream(pkts)
1675 self.pg_enable_capture(self.pg_interfaces)
1677 capture = self.pg5.get_capture(len(pkts))
1678 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1680 # between NAT44EI inside interfaces with different VRF (hairpinning)
1681 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1682 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1683 TCP(sport=1234, dport=5678))
1684 self.pg4.add_stream(p)
1685 self.pg_enable_capture(self.pg_interfaces)
1687 capture = self.pg6.get_capture(1)
1692 self.assertEqual(ip.src, self.nat_addr)
1693 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1694 self.assertNotEqual(tcp.sport, 1234)
1695 self.assertEqual(tcp.dport, 5678)
1697 self.logger.error(ppp("Unexpected or invalid packet:", p))
1700 # in2out 1st interface
1701 pkts = self.create_stream_in(self.pg4, self.pg3)
1702 self.pg4.add_stream(pkts)
1703 self.pg_enable_capture(self.pg_interfaces)
1705 capture = self.pg3.get_capture(len(pkts))
1706 self.verify_capture_out(capture)
1708 # out2in 1st interface
1709 pkts = self.create_stream_out(self.pg3)
1710 self.pg3.add_stream(pkts)
1711 self.pg_enable_capture(self.pg_interfaces)
1713 capture = self.pg4.get_capture(len(pkts))
1714 self.verify_capture_in(capture, self.pg4)
1716 # in2out 2nd interface
1717 pkts = self.create_stream_in(self.pg5, self.pg3)
1718 self.pg5.add_stream(pkts)
1719 self.pg_enable_capture(self.pg_interfaces)
1721 capture = self.pg3.get_capture(len(pkts))
1722 self.verify_capture_out(capture)
1724 # out2in 2nd interface
1725 pkts = self.create_stream_out(self.pg3)
1726 self.pg3.add_stream(pkts)
1727 self.pg_enable_capture(self.pg_interfaces)
1729 capture = self.pg5.get_capture(len(pkts))
1730 self.verify_capture_in(capture, self.pg5)
1733 addresses = self.vapi.nat44_ei_address_dump()
1734 self.assertEqual(len(addresses), 1)
1735 sessions = self.vapi.nat44_ei_user_session_dump(
1736 self.pg5.remote_ip4, 10)
1737 self.assertEqual(len(sessions), 3)
1738 for session in sessions:
1739 self.assertFalse(session.flags &
1740 self.config_flags.NAT44_EI_STATIC_MAPPING)
1741 self.assertEqual(str(session.inside_ip_address),
1742 self.pg5.remote_ip4)
1743 self.assertEqual(session.outside_ip_address,
1744 addresses[0].ip_address)
1745 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1746 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1747 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1748 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1749 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1750 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1751 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1752 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1753 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1755 # in2out 3rd interface
1756 pkts = self.create_stream_in(self.pg6, self.pg3)
1757 self.pg6.add_stream(pkts)
1758 self.pg_enable_capture(self.pg_interfaces)
1760 capture = self.pg3.get_capture(len(pkts))
1761 self.verify_capture_out(capture, static_nat_ip, True)
1763 # out2in 3rd interface
1764 pkts = self.create_stream_out(self.pg3, static_nat_ip)
1765 self.pg3.add_stream(pkts)
1766 self.pg_enable_capture(self.pg_interfaces)
1768 capture = self.pg6.get_capture(len(pkts))
1769 self.verify_capture_in(capture, self.pg6)
1771 # general user and session dump verifications
1772 users = self.vapi.nat44_ei_user_dump()
1773 self.assertGreaterEqual(len(users), 3)
1774 addresses = self.vapi.nat44_ei_address_dump()
1775 self.assertEqual(len(addresses), 1)
1777 sessions = self.vapi.nat44_ei_user_session_dump(user.ip_address,
1779 for session in sessions:
1780 self.assertEqual(user.ip_address, session.inside_ip_address)
1781 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1782 self.assertTrue(session.protocol in
1783 [IP_PROTOS.tcp, IP_PROTOS.udp,
1787 sessions = self.vapi.nat44_ei_user_session_dump(
1788 self.pg4.remote_ip4, 10)
1789 self.assertGreaterEqual(len(sessions), 4)
1790 for session in sessions:
1792 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1793 self.assertEqual(str(session.inside_ip_address),
1794 self.pg4.remote_ip4)
1795 self.assertEqual(session.outside_ip_address,
1796 addresses[0].ip_address)
1799 sessions = self.vapi.nat44_ei_user_session_dump(
1800 self.pg6.remote_ip4, 20)
1801 self.assertGreaterEqual(len(sessions), 3)
1802 for session in sessions:
1804 session.flags & self.config_flags.NAT44_EI_STATIC_MAPPING)
1805 self.assertEqual(str(session.inside_ip_address),
1806 self.pg6.remote_ip4)
1807 self.assertEqual(str(session.outside_ip_address),
1809 self.assertTrue(session.inside_port in
1810 [self.tcp_port_in, self.udp_port_in,
1813 def test_hairpinning(self):
1814 """ NAT44EI hairpinning - 1:1 NAPT """
1816 host = self.pg0.remote_hosts[0]
1817 server = self.pg0.remote_hosts[1]
1820 server_in_port = 5678
1821 server_out_port = 8765
1823 self.nat44_add_address(self.nat_addr)
1824 flags = self.config_flags.NAT44_EI_IF_INSIDE
1825 self.vapi.nat44_ei_interface_add_del_feature(
1826 sw_if_index=self.pg0.sw_if_index,
1827 flags=flags, is_add=1)
1828 self.vapi.nat44_ei_interface_add_del_feature(
1829 sw_if_index=self.pg1.sw_if_index,
1832 # add static mapping for server
1833 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1834 server_in_port, server_out_port,
1835 proto=IP_PROTOS.tcp)
1837 cnt = self.statistics['/nat44-ei/hairpinning']
1838 # send packet from host to server
1839 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
1840 IP(src=host.ip4, dst=self.nat_addr) /
1841 TCP(sport=host_in_port, dport=server_out_port))
1842 self.pg0.add_stream(p)
1843 self.pg_enable_capture(self.pg_interfaces)
1845 capture = self.pg0.get_capture(1)
1850 self.assertEqual(ip.src, self.nat_addr)
1851 self.assertEqual(ip.dst, server.ip4)
1852 self.assertNotEqual(tcp.sport, host_in_port)
1853 self.assertEqual(tcp.dport, server_in_port)
1854 self.assert_packet_checksums_valid(p)
1855 host_out_port = tcp.sport
1857 self.logger.error(ppp("Unexpected or invalid packet:", p))
1860 after = self.statistics['/nat44-ei/hairpinning']
1861 if_idx = self.pg0.sw_if_index
1862 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
1864 # send reply from server to host
1865 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1866 IP(src=server.ip4, dst=self.nat_addr) /
1867 TCP(sport=server_in_port, dport=host_out_port))
1868 self.pg0.add_stream(p)
1869 self.pg_enable_capture(self.pg_interfaces)
1871 capture = self.pg0.get_capture(1)
1876 self.assertEqual(ip.src, self.nat_addr)
1877 self.assertEqual(ip.dst, host.ip4)
1878 self.assertEqual(tcp.sport, server_out_port)
1879 self.assertEqual(tcp.dport, host_in_port)
1880 self.assert_packet_checksums_valid(p)
1882 self.logger.error(ppp("Unexpected or invalid packet:", p))
1885 after = self.statistics['/nat44-ei/hairpinning']
1886 if_idx = self.pg0.sw_if_index
1887 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(),
1888 2+(1 if self.vpp_worker_count > 0 else 0))
1890 def test_hairpinning2(self):
1891 """ NAT44EI hairpinning - 1:1 NAT"""
1893 server1_nat_ip = "10.0.0.10"
1894 server2_nat_ip = "10.0.0.11"
1895 host = self.pg0.remote_hosts[0]
1896 server1 = self.pg0.remote_hosts[1]
1897 server2 = self.pg0.remote_hosts[2]
1898 server_tcp_port = 22
1899 server_udp_port = 20
1901 self.nat44_add_address(self.nat_addr)
1902 flags = self.config_flags.NAT44_EI_IF_INSIDE
1903 self.vapi.nat44_ei_interface_add_del_feature(
1904 sw_if_index=self.pg0.sw_if_index,
1905 flags=flags, is_add=1)
1906 self.vapi.nat44_ei_interface_add_del_feature(
1907 sw_if_index=self.pg1.sw_if_index,
1910 # add static mapping for servers
1911 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1912 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
1916 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1917 IP(src=host.ip4, dst=server1_nat_ip) /
1918 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1920 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1921 IP(src=host.ip4, dst=server1_nat_ip) /
1922 UDP(sport=self.udp_port_in, dport=server_udp_port))
1924 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1925 IP(src=host.ip4, dst=server1_nat_ip) /
1926 ICMP(id=self.icmp_id_in, type='echo-request'))
1928 self.pg0.add_stream(pkts)
1929 self.pg_enable_capture(self.pg_interfaces)
1931 capture = self.pg0.get_capture(len(pkts))
1932 for packet in capture:
1934 self.assertEqual(packet[IP].src, self.nat_addr)
1935 self.assertEqual(packet[IP].dst, server1.ip4)
1936 if packet.haslayer(TCP):
1937 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1938 self.assertEqual(packet[TCP].dport, server_tcp_port)
1939 self.tcp_port_out = packet[TCP].sport
1940 self.assert_packet_checksums_valid(packet)
1941 elif packet.haslayer(UDP):
1942 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1943 self.assertEqual(packet[UDP].dport, server_udp_port)
1944 self.udp_port_out = packet[UDP].sport
1946 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1947 self.icmp_id_out = packet[ICMP].id
1949 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1954 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1955 IP(src=server1.ip4, dst=self.nat_addr) /
1956 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1958 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1959 IP(src=server1.ip4, dst=self.nat_addr) /
1960 UDP(sport=server_udp_port, dport=self.udp_port_out))
1962 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1963 IP(src=server1.ip4, dst=self.nat_addr) /
1964 ICMP(id=self.icmp_id_out, type='echo-reply'))
1966 self.pg0.add_stream(pkts)
1967 self.pg_enable_capture(self.pg_interfaces)
1969 capture = self.pg0.get_capture(len(pkts))
1970 for packet in capture:
1972 self.assertEqual(packet[IP].src, server1_nat_ip)
1973 self.assertEqual(packet[IP].dst, host.ip4)
1974 if packet.haslayer(TCP):
1975 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1976 self.assertEqual(packet[TCP].sport, server_tcp_port)
1977 self.assert_packet_checksums_valid(packet)
1978 elif packet.haslayer(UDP):
1979 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1980 self.assertEqual(packet[UDP].sport, server_udp_port)
1982 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1984 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1987 # server2 to server1
1989 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1990 IP(src=server2.ip4, dst=server1_nat_ip) /
1991 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1993 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1994 IP(src=server2.ip4, dst=server1_nat_ip) /
1995 UDP(sport=self.udp_port_in, dport=server_udp_port))
1997 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1998 IP(src=server2.ip4, dst=server1_nat_ip) /
1999 ICMP(id=self.icmp_id_in, type='echo-request'))
2001 self.pg0.add_stream(pkts)
2002 self.pg_enable_capture(self.pg_interfaces)
2004 capture = self.pg0.get_capture(len(pkts))
2005 for packet in capture:
2007 self.assertEqual(packet[IP].src, server2_nat_ip)
2008 self.assertEqual(packet[IP].dst, server1.ip4)
2009 if packet.haslayer(TCP):
2010 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2011 self.assertEqual(packet[TCP].dport, server_tcp_port)
2012 self.tcp_port_out = packet[TCP].sport
2013 self.assert_packet_checksums_valid(packet)
2014 elif packet.haslayer(UDP):
2015 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2016 self.assertEqual(packet[UDP].dport, server_udp_port)
2017 self.udp_port_out = packet[UDP].sport
2019 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2020 self.icmp_id_out = packet[ICMP].id
2022 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2025 # server1 to server2
2027 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2028 IP(src=server1.ip4, dst=server2_nat_ip) /
2029 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2031 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2032 IP(src=server1.ip4, dst=server2_nat_ip) /
2033 UDP(sport=server_udp_port, dport=self.udp_port_out))
2035 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2036 IP(src=server1.ip4, dst=server2_nat_ip) /
2037 ICMP(id=self.icmp_id_out, type='echo-reply'))
2039 self.pg0.add_stream(pkts)
2040 self.pg_enable_capture(self.pg_interfaces)
2042 capture = self.pg0.get_capture(len(pkts))
2043 for packet in capture:
2045 self.assertEqual(packet[IP].src, server1_nat_ip)
2046 self.assertEqual(packet[IP].dst, server2.ip4)
2047 if packet.haslayer(TCP):
2048 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2049 self.assertEqual(packet[TCP].sport, server_tcp_port)
2050 self.assert_packet_checksums_valid(packet)
2051 elif packet.haslayer(UDP):
2052 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2053 self.assertEqual(packet[UDP].sport, server_udp_port)
2055 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2057 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2060 def test_hairpinning_avoid_inf_loop(self):
2061 """ NAT44EI hairpinning - 1:1 NAPT avoid infinite loop """
2063 host = self.pg0.remote_hosts[0]
2064 server = self.pg0.remote_hosts[1]
2067 server_in_port = 5678
2068 server_out_port = 8765
2070 self.nat44_add_address(self.nat_addr)
2071 flags = self.config_flags.NAT44_EI_IF_INSIDE
2072 self.vapi.nat44_ei_interface_add_del_feature(
2073 sw_if_index=self.pg0.sw_if_index,
2074 flags=flags, is_add=1)
2075 self.vapi.nat44_ei_interface_add_del_feature(
2076 sw_if_index=self.pg1.sw_if_index,
2079 # add static mapping for server
2080 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2081 server_in_port, server_out_port,
2082 proto=IP_PROTOS.tcp)
2084 # add another static mapping that maps pg0.local_ip4 address to itself
2085 self.nat44_add_static_mapping(self.pg0.local_ip4, self.pg0.local_ip4)
2087 # send packet from host to VPP (the packet should get dropped)
2088 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2089 IP(src=host.ip4, dst=self.pg0.local_ip4) /
2090 TCP(sport=host_in_port, dport=server_out_port))
2091 self.pg0.add_stream(p)
2092 self.pg_enable_capture(self.pg_interfaces)
2094 # Here VPP used to crash due to an infinite loop
2096 cnt = self.statistics['/nat44-ei/hairpinning']
2097 # send packet from host to server
2098 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2099 IP(src=host.ip4, dst=self.nat_addr) /
2100 TCP(sport=host_in_port, dport=server_out_port))
2101 self.pg0.add_stream(p)
2102 self.pg_enable_capture(self.pg_interfaces)
2104 capture = self.pg0.get_capture(1)
2109 self.assertEqual(ip.src, self.nat_addr)
2110 self.assertEqual(ip.dst, server.ip4)
2111 self.assertNotEqual(tcp.sport, host_in_port)
2112 self.assertEqual(tcp.dport, server_in_port)
2113 self.assert_packet_checksums_valid(p)
2114 host_out_port = tcp.sport
2116 self.logger.error(ppp("Unexpected or invalid packet:", p))
2119 after = self.statistics['/nat44-ei/hairpinning']
2120 if_idx = self.pg0.sw_if_index
2121 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1)
2123 # send reply from server to host
2124 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2125 IP(src=server.ip4, dst=self.nat_addr) /
2126 TCP(sport=server_in_port, dport=host_out_port))
2127 self.pg0.add_stream(p)
2128 self.pg_enable_capture(self.pg_interfaces)
2130 capture = self.pg0.get_capture(1)
2135 self.assertEqual(ip.src, self.nat_addr)
2136 self.assertEqual(ip.dst, host.ip4)
2137 self.assertEqual(tcp.sport, server_out_port)
2138 self.assertEqual(tcp.dport, host_in_port)
2139 self.assert_packet_checksums_valid(p)
2141 self.logger.error(ppp("Unexpected or invalid packet:", p))
2144 after = self.statistics['/nat44-ei/hairpinning']
2145 if_idx = self.pg0.sw_if_index
2146 self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(),
2147 2+(1 if self.vpp_worker_count > 0 else 0))
2149 def test_interface_addr(self):
2150 """ NAT44EI acquire addresses from interface """
2151 self.vapi.nat44_ei_add_del_interface_addr(
2153 sw_if_index=self.pg7.sw_if_index)
2155 # no address in NAT pool
2156 addresses = self.vapi.nat44_ei_address_dump()
2157 self.assertEqual(0, len(addresses))
2159 # configure interface address and check NAT address pool
2160 self.pg7.config_ip4()
2161 addresses = self.vapi.nat44_ei_address_dump()
2162 self.assertEqual(1, len(addresses))
2163 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2165 # remove interface address and check NAT address pool
2166 self.pg7.unconfig_ip4()
2167 addresses = self.vapi.nat44_ei_address_dump()
2168 self.assertEqual(0, len(addresses))
2170 def test_interface_addr_static_mapping(self):
2171 """ NAT44EI Static mapping with addresses from interface """
2174 self.vapi.nat44_ei_add_del_interface_addr(
2176 sw_if_index=self.pg7.sw_if_index)
2177 self.nat44_add_static_mapping(
2179 external_sw_if_index=self.pg7.sw_if_index,
2182 # static mappings with external interface
2183 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2184 self.assertEqual(1, len(static_mappings))
2185 self.assertEqual(self.pg7.sw_if_index,
2186 static_mappings[0].external_sw_if_index)
2187 self.assertEqual(static_mappings[0].tag, tag)
2189 # configure interface address and check static mappings
2190 self.pg7.config_ip4()
2191 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2192 self.assertEqual(2, len(static_mappings))
2194 for sm in static_mappings:
2195 if sm.external_sw_if_index == 0xFFFFFFFF:
2196 self.assertEqual(str(sm.external_ip_address),
2198 self.assertEqual(sm.tag, tag)
2200 self.assertTrue(resolved)
2202 # remove interface address and check static mappings
2203 self.pg7.unconfig_ip4()
2204 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2205 self.assertEqual(1, len(static_mappings))
2206 self.assertEqual(self.pg7.sw_if_index,
2207 static_mappings[0].external_sw_if_index)
2208 self.assertEqual(static_mappings[0].tag, tag)
2210 # configure interface address again and check static mappings
2211 self.pg7.config_ip4()
2212 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2213 self.assertEqual(2, len(static_mappings))
2215 for sm in static_mappings:
2216 if sm.external_sw_if_index == 0xFFFFFFFF:
2217 self.assertEqual(str(sm.external_ip_address),
2219 self.assertEqual(sm.tag, tag)
2221 self.assertTrue(resolved)
2223 # remove static mapping
2224 self.nat44_add_static_mapping(
2226 external_sw_if_index=self.pg7.sw_if_index,
2229 static_mappings = self.vapi.nat44_ei_static_mapping_dump()
2230 self.assertEqual(0, len(static_mappings))
2232 def test_interface_addr_identity_nat(self):
2233 """ NAT44EI Identity NAT with addresses from interface """
2236 self.vapi.nat44_ei_add_del_interface_addr(
2238 sw_if_index=self.pg7.sw_if_index)
2239 self.vapi.nat44_ei_add_del_identity_mapping(
2241 sw_if_index=self.pg7.sw_if_index,
2243 protocol=IP_PROTOS.tcp,
2246 # identity mappings with external interface
2247 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2248 self.assertEqual(1, len(identity_mappings))
2249 self.assertEqual(self.pg7.sw_if_index,
2250 identity_mappings[0].sw_if_index)
2252 # configure interface address and check identity mappings
2253 self.pg7.config_ip4()
2254 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2256 self.assertEqual(2, len(identity_mappings))
2257 for sm in identity_mappings:
2258 if sm.sw_if_index == 0xFFFFFFFF:
2259 self.assertEqual(str(identity_mappings[0].ip_address),
2261 self.assertEqual(port, identity_mappings[0].port)
2262 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2264 self.assertTrue(resolved)
2266 # remove interface address and check identity mappings
2267 self.pg7.unconfig_ip4()
2268 identity_mappings = self.vapi.nat44_ei_identity_mapping_dump()
2269 self.assertEqual(1, len(identity_mappings))
2270 self.assertEqual(self.pg7.sw_if_index,
2271 identity_mappings[0].sw_if_index)
2273 def test_ipfix_nat44_sess(self):
2274 """ NAT44EI IPFIX logging NAT44EI session created/deleted """
2275 self.ipfix_domain_id = 10
2276 self.ipfix_src_port = 20202
2277 collector_port = 30303
2278 bind_layers(UDP, IPFIX, dport=30303)
2279 self.nat44_add_address(self.nat_addr)
2280 flags = self.config_flags.NAT44_EI_IF_INSIDE
2281 self.vapi.nat44_ei_interface_add_del_feature(
2282 sw_if_index=self.pg0.sw_if_index,
2283 flags=flags, is_add=1)
2284 self.vapi.nat44_ei_interface_add_del_feature(
2285 sw_if_index=self.pg1.sw_if_index,
2287 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2288 src_address=self.pg3.local_ip4,
2290 template_interval=10,
2291 collector_port=collector_port)
2292 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2293 src_port=self.ipfix_src_port,
2296 pkts = self.create_stream_in(self.pg0, self.pg1)
2297 self.pg0.add_stream(pkts)
2298 self.pg_enable_capture(self.pg_interfaces)
2300 capture = self.pg1.get_capture(len(pkts))
2301 self.verify_capture_out(capture)
2302 self.nat44_add_address(self.nat_addr, is_add=0)
2303 self.vapi.ipfix_flush()
2304 capture = self.pg3.get_capture(7)
2305 ipfix = IPFIXDecoder()
2306 # first load template
2308 self.assertTrue(p.haslayer(IPFIX))
2309 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2310 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2311 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2312 self.assertEqual(p[UDP].dport, collector_port)
2313 self.assertEqual(p[IPFIX].observationDomainID,
2314 self.ipfix_domain_id)
2315 if p.haslayer(Template):
2316 ipfix.add_template(p.getlayer(Template))
2317 # verify events in data set
2319 if p.haslayer(Data):
2320 data = ipfix.decode_data_set(p.getlayer(Set))
2321 self.verify_ipfix_nat44_ses(data)
2323 def test_ipfix_addr_exhausted(self):
2324 """ NAT44EI IPFIX logging NAT addresses exhausted """
2325 flags = self.config_flags.NAT44_EI_IF_INSIDE
2326 self.vapi.nat44_ei_interface_add_del_feature(
2327 sw_if_index=self.pg0.sw_if_index,
2328 flags=flags, is_add=1)
2329 self.vapi.nat44_ei_interface_add_del_feature(
2330 sw_if_index=self.pg1.sw_if_index,
2332 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2333 src_address=self.pg3.local_ip4,
2335 template_interval=10)
2336 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2337 src_port=self.ipfix_src_port,
2340 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2341 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2343 self.pg0.add_stream(p)
2344 self.pg_enable_capture(self.pg_interfaces)
2346 self.pg1.assert_nothing_captured()
2348 self.vapi.ipfix_flush()
2349 capture = self.pg3.get_capture(7)
2350 ipfix = IPFIXDecoder()
2351 # first load template
2353 self.assertTrue(p.haslayer(IPFIX))
2354 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2355 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2356 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2357 self.assertEqual(p[UDP].dport, 4739)
2358 self.assertEqual(p[IPFIX].observationDomainID,
2359 self.ipfix_domain_id)
2360 if p.haslayer(Template):
2361 ipfix.add_template(p.getlayer(Template))
2362 # verify events in data set
2364 if p.haslayer(Data):
2365 data = ipfix.decode_data_set(p.getlayer(Set))
2366 self.verify_ipfix_addr_exhausted(data)
2368 def test_ipfix_max_sessions(self):
2369 """ NAT44EI IPFIX logging maximum session entries exceeded """
2370 self.nat44_add_address(self.nat_addr)
2371 flags = self.config_flags.NAT44_EI_IF_INSIDE
2372 self.vapi.nat44_ei_interface_add_del_feature(
2373 sw_if_index=self.pg0.sw_if_index,
2374 flags=flags, is_add=1)
2375 self.vapi.nat44_ei_interface_add_del_feature(
2376 sw_if_index=self.pg1.sw_if_index,
2379 max_sessions_per_thread = self.max_translations
2380 max_sessions = max(1, self.vpp_worker_count) * max_sessions_per_thread
2383 for i in range(0, max_sessions):
2384 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2385 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2386 IP(src=src, dst=self.pg1.remote_ip4) /
2389 self.pg0.add_stream(pkts)
2390 self.pg_enable_capture(self.pg_interfaces)
2393 self.pg1.get_capture(max_sessions)
2394 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2395 src_address=self.pg3.local_ip4,
2397 template_interval=10)
2398 self.vapi.nat44_ei_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2399 src_port=self.ipfix_src_port,
2402 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2403 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2405 self.pg0.add_stream(p)
2406 self.pg_enable_capture(self.pg_interfaces)
2408 self.pg1.assert_nothing_captured()
2410 self.vapi.ipfix_flush()
2411 capture = self.pg3.get_capture(7)
2412 ipfix = IPFIXDecoder()
2413 # first load template
2415 self.assertTrue(p.haslayer(IPFIX))
2416 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2417 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2418 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2419 self.assertEqual(p[UDP].dport, 4739)
2420 self.assertEqual(p[IPFIX].observationDomainID,
2421 self.ipfix_domain_id)
2422 if p.haslayer(Template):
2423 ipfix.add_template(p.getlayer(Template))
2424 # verify events in data set
2426 if p.haslayer(Data):
2427 data = ipfix.decode_data_set(p.getlayer(Set))
2428 self.verify_ipfix_max_sessions(data, max_sessions_per_thread)
2430 def test_syslog_apmap(self):
2431 """ NAT44EI syslog address and port mapping creation and deletion """
2432 self.vapi.syslog_set_filter(
2433 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2434 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2435 self.nat44_add_address(self.nat_addr)
2436 flags = self.config_flags.NAT44_EI_IF_INSIDE
2437 self.vapi.nat44_ei_interface_add_del_feature(
2438 sw_if_index=self.pg0.sw_if_index,
2439 flags=flags, is_add=1)
2440 self.vapi.nat44_ei_interface_add_del_feature(
2441 sw_if_index=self.pg1.sw_if_index,
2444 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2445 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2446 TCP(sport=self.tcp_port_in, dport=20))
2447 self.pg0.add_stream(p)
2448 self.pg_enable_capture(self.pg_interfaces)
2450 capture = self.pg1.get_capture(1)
2451 self.tcp_port_out = capture[0][TCP].sport
2452 capture = self.pg3.get_capture(1)
2453 self.verify_syslog_apmap(capture[0][Raw].load)
2455 self.pg_enable_capture(self.pg_interfaces)
2457 self.nat44_add_address(self.nat_addr, is_add=0)
2458 capture = self.pg3.get_capture(1)
2459 self.verify_syslog_apmap(capture[0][Raw].load, False)
2461 def test_pool_addr_fib(self):
2462 """ NAT44EI add pool addresses to FIB """
2463 static_addr = '10.0.0.10'
2464 self.nat44_add_address(self.nat_addr)
2465 flags = self.config_flags.NAT44_EI_IF_INSIDE
2466 self.vapi.nat44_ei_interface_add_del_feature(
2467 sw_if_index=self.pg0.sw_if_index,
2468 flags=flags, is_add=1)
2469 self.vapi.nat44_ei_interface_add_del_feature(
2470 sw_if_index=self.pg1.sw_if_index,
2472 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2475 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2476 ARP(op=ARP.who_has, pdst=self.nat_addr,
2477 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2478 self.pg1.add_stream(p)
2479 self.pg_enable_capture(self.pg_interfaces)
2481 capture = self.pg1.get_capture(1)
2482 self.assertTrue(capture[0].haslayer(ARP))
2483 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2486 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2487 ARP(op=ARP.who_has, pdst=static_addr,
2488 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2489 self.pg1.add_stream(p)
2490 self.pg_enable_capture(self.pg_interfaces)
2492 capture = self.pg1.get_capture(1)
2493 self.assertTrue(capture[0].haslayer(ARP))
2494 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2496 # send ARP to non-NAT44EI interface
2497 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2498 ARP(op=ARP.who_has, pdst=self.nat_addr,
2499 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2500 self.pg2.add_stream(p)
2501 self.pg_enable_capture(self.pg_interfaces)
2503 self.pg1.assert_nothing_captured()
2505 # remove addresses and verify
2506 self.nat44_add_address(self.nat_addr, is_add=0)
2507 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2510 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2511 ARP(op=ARP.who_has, pdst=self.nat_addr,
2512 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2513 self.pg1.add_stream(p)
2514 self.pg_enable_capture(self.pg_interfaces)
2516 self.pg1.assert_nothing_captured()
2518 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2519 ARP(op=ARP.who_has, pdst=static_addr,
2520 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2521 self.pg1.add_stream(p)
2522 self.pg_enable_capture(self.pg_interfaces)
2524 self.pg1.assert_nothing_captured()
2526 def test_vrf_mode(self):
2527 """ NAT44EI tenant VRF aware address pool mode """
2531 nat_ip1 = "10.0.0.10"
2532 nat_ip2 = "10.0.0.11"
2534 self.pg0.unconfig_ip4()
2535 self.pg1.unconfig_ip4()
2536 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2537 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2538 self.pg0.set_table_ip4(vrf_id1)
2539 self.pg1.set_table_ip4(vrf_id2)
2540 self.pg0.config_ip4()
2541 self.pg1.config_ip4()
2542 self.pg0.resolve_arp()
2543 self.pg1.resolve_arp()
2545 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2546 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2547 flags = self.config_flags.NAT44_EI_IF_INSIDE
2548 self.vapi.nat44_ei_interface_add_del_feature(
2549 sw_if_index=self.pg0.sw_if_index,
2550 flags=flags, is_add=1)
2551 self.vapi.nat44_ei_interface_add_del_feature(
2552 sw_if_index=self.pg1.sw_if_index,
2553 flags=flags, is_add=1)
2554 self.vapi.nat44_ei_interface_add_del_feature(
2555 sw_if_index=self.pg2.sw_if_index,
2560 pkts = self.create_stream_in(self.pg0, self.pg2)
2561 self.pg0.add_stream(pkts)
2562 self.pg_enable_capture(self.pg_interfaces)
2564 capture = self.pg2.get_capture(len(pkts))
2565 self.verify_capture_out(capture, nat_ip1)
2568 pkts = self.create_stream_in(self.pg1, self.pg2)
2569 self.pg1.add_stream(pkts)
2570 self.pg_enable_capture(self.pg_interfaces)
2572 capture = self.pg2.get_capture(len(pkts))
2573 self.verify_capture_out(capture, nat_ip2)
2576 self.pg0.unconfig_ip4()
2577 self.pg1.unconfig_ip4()
2578 self.pg0.set_table_ip4(0)
2579 self.pg1.set_table_ip4(0)
2580 self.pg0.config_ip4()
2581 self.pg1.config_ip4()
2582 self.pg0.resolve_arp()
2583 self.pg1.resolve_arp()
2584 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2585 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2587 def test_vrf_feature_independent(self):
2588 """ NAT44EI tenant VRF independent address pool mode """
2590 nat_ip1 = "10.0.0.10"
2591 nat_ip2 = "10.0.0.11"
2593 self.nat44_add_address(nat_ip1)
2594 self.nat44_add_address(nat_ip2, vrf_id=99)
2595 flags = self.config_flags.NAT44_EI_IF_INSIDE
2596 self.vapi.nat44_ei_interface_add_del_feature(
2597 sw_if_index=self.pg0.sw_if_index,
2598 flags=flags, is_add=1)
2599 self.vapi.nat44_ei_interface_add_del_feature(
2600 sw_if_index=self.pg1.sw_if_index,
2601 flags=flags, is_add=1)
2602 self.vapi.nat44_ei_interface_add_del_feature(
2603 sw_if_index=self.pg2.sw_if_index,
2607 pkts = self.create_stream_in(self.pg0, self.pg2)
2608 self.pg0.add_stream(pkts)
2609 self.pg_enable_capture(self.pg_interfaces)
2611 capture = self.pg2.get_capture(len(pkts))
2612 self.verify_capture_out(capture, nat_ip1)
2615 pkts = self.create_stream_in(self.pg1, self.pg2)
2616 self.pg1.add_stream(pkts)
2617 self.pg_enable_capture(self.pg_interfaces)
2619 capture = self.pg2.get_capture(len(pkts))
2620 self.verify_capture_out(capture, nat_ip1)
2622 def test_dynamic_ipless_interfaces(self):
2623 """ NAT44EI interfaces without configured IP address """
2624 self.create_routes_and_neigbors()
2625 self.nat44_add_address(self.nat_addr)
2626 flags = self.config_flags.NAT44_EI_IF_INSIDE
2627 self.vapi.nat44_ei_interface_add_del_feature(
2628 sw_if_index=self.pg7.sw_if_index,
2629 flags=flags, is_add=1)
2630 self.vapi.nat44_ei_interface_add_del_feature(
2631 sw_if_index=self.pg8.sw_if_index,
2635 pkts = self.create_stream_in(self.pg7, self.pg8)
2636 self.pg7.add_stream(pkts)
2637 self.pg_enable_capture(self.pg_interfaces)
2639 capture = self.pg8.get_capture(len(pkts))
2640 self.verify_capture_out(capture)
2643 pkts = self.create_stream_out(self.pg8, self.nat_addr)
2644 self.pg8.add_stream(pkts)
2645 self.pg_enable_capture(self.pg_interfaces)
2647 capture = self.pg7.get_capture(len(pkts))
2648 self.verify_capture_in(capture, self.pg7)
2650 def test_static_ipless_interfaces(self):
2651 """ NAT44EI interfaces without configured IP address - 1:1 NAT """
2653 self.create_routes_and_neigbors()
2654 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2655 flags = self.config_flags.NAT44_EI_IF_INSIDE
2656 self.vapi.nat44_ei_interface_add_del_feature(
2657 sw_if_index=self.pg7.sw_if_index,
2658 flags=flags, is_add=1)
2659 self.vapi.nat44_ei_interface_add_del_feature(
2660 sw_if_index=self.pg8.sw_if_index,
2664 pkts = self.create_stream_out(self.pg8)
2665 self.pg8.add_stream(pkts)
2666 self.pg_enable_capture(self.pg_interfaces)
2668 capture = self.pg7.get_capture(len(pkts))
2669 self.verify_capture_in(capture, self.pg7)
2672 pkts = self.create_stream_in(self.pg7, self.pg8)
2673 self.pg7.add_stream(pkts)
2674 self.pg_enable_capture(self.pg_interfaces)
2676 capture = self.pg8.get_capture(len(pkts))
2677 self.verify_capture_out(capture, self.nat_addr, True)
2679 def test_static_with_port_ipless_interfaces(self):
2680 """ NAT44EI interfaces without configured IP address - 1:1 NAPT """
2682 self.tcp_port_out = 30606
2683 self.udp_port_out = 30607
2684 self.icmp_id_out = 30608
2686 self.create_routes_and_neigbors()
2687 self.nat44_add_address(self.nat_addr)
2688 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2689 self.tcp_port_in, self.tcp_port_out,
2690 proto=IP_PROTOS.tcp)
2691 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2692 self.udp_port_in, self.udp_port_out,
2693 proto=IP_PROTOS.udp)
2694 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2695 self.icmp_id_in, self.icmp_id_out,
2696 proto=IP_PROTOS.icmp)
2697 flags = self.config_flags.NAT44_EI_IF_INSIDE
2698 self.vapi.nat44_ei_interface_add_del_feature(
2699 sw_if_index=self.pg7.sw_if_index,
2700 flags=flags, is_add=1)
2701 self.vapi.nat44_ei_interface_add_del_feature(
2702 sw_if_index=self.pg8.sw_if_index,
2706 pkts = self.create_stream_out(self.pg8)
2707 self.pg8.add_stream(pkts)
2708 self.pg_enable_capture(self.pg_interfaces)
2710 capture = self.pg7.get_capture(len(pkts))
2711 self.verify_capture_in(capture, self.pg7)
2714 pkts = self.create_stream_in(self.pg7, self.pg8)
2715 self.pg7.add_stream(pkts)
2716 self.pg_enable_capture(self.pg_interfaces)
2718 capture = self.pg8.get_capture(len(pkts))
2719 self.verify_capture_out(capture)
2721 def test_static_unknown_proto(self):
2722 """ NAT44EI 1:1 translate packet with unknown protocol """
2723 nat_ip = "10.0.0.10"
2724 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2725 flags = self.config_flags.NAT44_EI_IF_INSIDE
2726 self.vapi.nat44_ei_interface_add_del_feature(
2727 sw_if_index=self.pg0.sw_if_index,
2728 flags=flags, is_add=1)
2729 self.vapi.nat44_ei_interface_add_del_feature(
2730 sw_if_index=self.pg1.sw_if_index,
2734 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2735 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2737 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2738 TCP(sport=1234, dport=1234))
2739 self.pg0.add_stream(p)
2740 self.pg_enable_capture(self.pg_interfaces)
2742 p = self.pg1.get_capture(1)
2745 self.assertEqual(packet[IP].src, nat_ip)
2746 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2747 self.assertEqual(packet.haslayer(GRE), 1)
2748 self.assert_packet_checksums_valid(packet)
2750 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2754 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2755 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2757 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2758 TCP(sport=1234, dport=1234))
2759 self.pg1.add_stream(p)
2760 self.pg_enable_capture(self.pg_interfaces)
2762 p = self.pg0.get_capture(1)
2765 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2766 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2767 self.assertEqual(packet.haslayer(GRE), 1)
2768 self.assert_packet_checksums_valid(packet)
2770 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2773 def test_hairpinning_static_unknown_proto(self):
2774 """ NAT44EI 1:1 translate packet with unknown protocol - hairpinning
2777 host = self.pg0.remote_hosts[0]
2778 server = self.pg0.remote_hosts[1]
2780 host_nat_ip = "10.0.0.10"
2781 server_nat_ip = "10.0.0.11"
2783 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2784 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2785 flags = self.config_flags.NAT44_EI_IF_INSIDE
2786 self.vapi.nat44_ei_interface_add_del_feature(
2787 sw_if_index=self.pg0.sw_if_index,
2788 flags=flags, is_add=1)
2789 self.vapi.nat44_ei_interface_add_del_feature(
2790 sw_if_index=self.pg1.sw_if_index,
2794 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2795 IP(src=host.ip4, dst=server_nat_ip) /
2797 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2798 TCP(sport=1234, dport=1234))
2799 self.pg0.add_stream(p)
2800 self.pg_enable_capture(self.pg_interfaces)
2802 p = self.pg0.get_capture(1)
2805 self.assertEqual(packet[IP].src, host_nat_ip)
2806 self.assertEqual(packet[IP].dst, server.ip4)
2807 self.assertEqual(packet.haslayer(GRE), 1)
2808 self.assert_packet_checksums_valid(packet)
2810 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2814 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2815 IP(src=server.ip4, dst=host_nat_ip) /
2817 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2818 TCP(sport=1234, dport=1234))
2819 self.pg0.add_stream(p)
2820 self.pg_enable_capture(self.pg_interfaces)
2822 p = self.pg0.get_capture(1)
2825 self.assertEqual(packet[IP].src, server_nat_ip)
2826 self.assertEqual(packet[IP].dst, host.ip4)
2827 self.assertEqual(packet.haslayer(GRE), 1)
2828 self.assert_packet_checksums_valid(packet)
2830 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2833 def test_output_feature(self):
2834 """ NAT44EI output feature (in2out postrouting) """
2835 self.nat44_add_address(self.nat_addr)
2836 flags = self.config_flags.NAT44_EI_IF_INSIDE
2837 self.vapi.nat44_ei_interface_add_del_output_feature(
2838 is_add=1, flags=flags,
2839 sw_if_index=self.pg0.sw_if_index)
2840 self.vapi.nat44_ei_interface_add_del_output_feature(
2841 is_add=1, flags=flags,
2842 sw_if_index=self.pg1.sw_if_index)
2843 self.vapi.nat44_ei_interface_add_del_output_feature(
2845 sw_if_index=self.pg3.sw_if_index)
2848 pkts = self.create_stream_in(self.pg0, self.pg3)
2849 self.pg0.add_stream(pkts)
2850 self.pg_enable_capture(self.pg_interfaces)
2852 capture = self.pg3.get_capture(len(pkts))
2853 self.verify_capture_out(capture)
2856 pkts = self.create_stream_out(self.pg3)
2857 self.pg3.add_stream(pkts)
2858 self.pg_enable_capture(self.pg_interfaces)
2860 capture = self.pg0.get_capture(len(pkts))
2861 self.verify_capture_in(capture, self.pg0)
2863 # from non-NAT interface to NAT inside interface
2864 pkts = self.create_stream_in(self.pg2, self.pg0)
2865 self.pg2.add_stream(pkts)
2866 self.pg_enable_capture(self.pg_interfaces)
2868 capture = self.pg0.get_capture(len(pkts))
2869 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2871 def test_output_feature_vrf_aware(self):
2872 """ NAT44EI output feature VRF aware (in2out postrouting) """
2873 nat_ip_vrf10 = "10.0.0.10"
2874 nat_ip_vrf20 = "10.0.0.20"
2876 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2877 [VppRoutePath(self.pg3.remote_ip4,
2878 self.pg3.sw_if_index)],
2880 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
2881 [VppRoutePath(self.pg3.remote_ip4,
2882 self.pg3.sw_if_index)],
2887 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2888 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2889 flags = self.config_flags.NAT44_EI_IF_INSIDE
2890 self.vapi.nat44_ei_interface_add_del_output_feature(
2891 is_add=1, flags=flags,
2892 sw_if_index=self.pg4.sw_if_index)
2893 self.vapi.nat44_ei_interface_add_del_output_feature(
2894 is_add=1, flags=flags,
2895 sw_if_index=self.pg6.sw_if_index)
2896 self.vapi.nat44_ei_interface_add_del_output_feature(
2898 sw_if_index=self.pg3.sw_if_index)
2901 pkts = self.create_stream_in(self.pg4, self.pg3)
2902 self.pg4.add_stream(pkts)
2903 self.pg_enable_capture(self.pg_interfaces)
2905 capture = self.pg3.get_capture(len(pkts))
2906 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2909 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2910 self.pg3.add_stream(pkts)
2911 self.pg_enable_capture(self.pg_interfaces)
2913 capture = self.pg4.get_capture(len(pkts))
2914 self.verify_capture_in(capture, self.pg4)
2917 pkts = self.create_stream_in(self.pg6, self.pg3)
2918 self.pg6.add_stream(pkts)
2919 self.pg_enable_capture(self.pg_interfaces)
2921 capture = self.pg3.get_capture(len(pkts))
2922 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2925 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2926 self.pg3.add_stream(pkts)
2927 self.pg_enable_capture(self.pg_interfaces)
2929 capture = self.pg6.get_capture(len(pkts))
2930 self.verify_capture_in(capture, self.pg6)
2932 def test_output_feature_hairpinning(self):
2933 """ NAT44EI output feature hairpinning (in2out postrouting) """
2934 host = self.pg0.remote_hosts[0]
2935 server = self.pg0.remote_hosts[1]
2938 server_in_port = 5678
2939 server_out_port = 8765
2941 self.nat44_add_address(self.nat_addr)
2942 flags = self.config_flags.NAT44_EI_IF_INSIDE
2943 self.vapi.nat44_ei_interface_add_del_output_feature(
2944 is_add=1, flags=flags,
2945 sw_if_index=self.pg0.sw_if_index)
2946 self.vapi.nat44_ei_interface_add_del_output_feature(
2948 sw_if_index=self.pg1.sw_if_index)
2950 # add static mapping for server
2951 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2952 server_in_port, server_out_port,
2953 proto=IP_PROTOS.tcp)
2955 # send packet from host to server
2956 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2957 IP(src=host.ip4, dst=self.nat_addr) /
2958 TCP(sport=host_in_port, dport=server_out_port))
2959 self.pg0.add_stream(p)
2960 self.pg_enable_capture(self.pg_interfaces)
2962 capture = self.pg0.get_capture(1)
2967 self.assertEqual(ip.src, self.nat_addr)
2968 self.assertEqual(ip.dst, server.ip4)
2969 self.assertNotEqual(tcp.sport, host_in_port)
2970 self.assertEqual(tcp.dport, server_in_port)
2971 self.assert_packet_checksums_valid(p)
2972 host_out_port = tcp.sport
2974 self.logger.error(ppp("Unexpected or invalid packet:", p))
2977 # send reply from server to host
2978 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2979 IP(src=server.ip4, dst=self.nat_addr) /
2980 TCP(sport=server_in_port, dport=host_out_port))
2981 self.pg0.add_stream(p)
2982 self.pg_enable_capture(self.pg_interfaces)
2984 capture = self.pg0.get_capture(1)
2989 self.assertEqual(ip.src, self.nat_addr)
2990 self.assertEqual(ip.dst, host.ip4)
2991 self.assertEqual(tcp.sport, server_out_port)
2992 self.assertEqual(tcp.dport, host_in_port)
2993 self.assert_packet_checksums_valid(p)
2995 self.logger.error(ppp("Unexpected or invalid packet:", p))
2998 def test_one_armed_nat44(self):
2999 """ NAT44EI One armed NAT """
3000 remote_host = self.pg9.remote_hosts[0]
3001 local_host = self.pg9.remote_hosts[1]
3004 self.nat44_add_address(self.nat_addr)
3005 flags = self.config_flags.NAT44_EI_IF_INSIDE
3006 self.vapi.nat44_ei_interface_add_del_feature(
3007 sw_if_index=self.pg9.sw_if_index,
3009 self.vapi.nat44_ei_interface_add_del_feature(
3010 sw_if_index=self.pg9.sw_if_index,
3011 flags=flags, is_add=1)
3014 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3015 IP(src=local_host.ip4, dst=remote_host.ip4) /
3016 TCP(sport=12345, dport=80))
3017 self.pg9.add_stream(p)
3018 self.pg_enable_capture(self.pg_interfaces)
3020 capture = self.pg9.get_capture(1)
3025 self.assertEqual(ip.src, self.nat_addr)
3026 self.assertEqual(ip.dst, remote_host.ip4)
3027 self.assertNotEqual(tcp.sport, 12345)
3028 external_port = tcp.sport
3029 self.assertEqual(tcp.dport, 80)
3030 self.assert_packet_checksums_valid(p)
3032 self.logger.error(ppp("Unexpected or invalid packet:", p))
3036 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3037 IP(src=remote_host.ip4, dst=self.nat_addr) /
3038 TCP(sport=80, dport=external_port))
3039 self.pg9.add_stream(p)
3040 self.pg_enable_capture(self.pg_interfaces)
3042 capture = self.pg9.get_capture(1)
3047 self.assertEqual(ip.src, remote_host.ip4)
3048 self.assertEqual(ip.dst, local_host.ip4)
3049 self.assertEqual(tcp.sport, 80)
3050 self.assertEqual(tcp.dport, 12345)
3051 self.assert_packet_checksums_valid(p)
3053 self.logger.error(ppp("Unexpected or invalid packet:", p))
3056 if self.vpp_worker_count > 1:
3057 node = "nat44-ei-handoff-classify"
3059 node = "nat44-ei-classify"
3061 err = self.statistics.get_err_counter('/err/%s/next in2out' % node)
3062 self.assertEqual(err, 1)
3063 err = self.statistics.get_err_counter('/err/%s/next out2in' % node)
3064 self.assertEqual(err, 1)
3066 def test_del_session(self):
3067 """ NAT44EI delete session """
3068 self.nat44_add_address(self.nat_addr)
3069 flags = self.config_flags.NAT44_EI_IF_INSIDE
3070 self.vapi.nat44_ei_interface_add_del_feature(
3071 sw_if_index=self.pg0.sw_if_index,
3072 flags=flags, is_add=1)
3073 self.vapi.nat44_ei_interface_add_del_feature(
3074 sw_if_index=self.pg1.sw_if_index,
3077 pkts = self.create_stream_in(self.pg0, self.pg1)
3078 self.pg0.add_stream(pkts)
3079 self.pg_enable_capture(self.pg_interfaces)
3081 self.pg1.get_capture(len(pkts))
3083 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
3084 nsessions = len(sessions)
3086 self.vapi.nat44_ei_del_session(
3087 address=sessions[0].inside_ip_address,
3088 port=sessions[0].inside_port,
3089 protocol=sessions[0].protocol,
3090 flags=self.config_flags.NAT44_EI_IF_INSIDE)
3092 self.vapi.nat44_ei_del_session(
3093 address=sessions[1].outside_ip_address,
3094 port=sessions[1].outside_port,
3095 protocol=sessions[1].protocol)
3097 sessions = self.vapi.nat44_ei_user_session_dump(self.pg0.remote_ip4, 0)
3098 self.assertEqual(nsessions - len(sessions), 2)
3100 self.vapi.nat44_ei_del_session(
3101 address=sessions[0].inside_ip_address,
3102 port=sessions[0].inside_port,
3103 protocol=sessions[0].protocol,
3104 flags=self.config_flags.NAT44_EI_IF_INSIDE)
3106 self.verify_no_nat44_user()
3108 def test_frag_in_order(self):
3109 """ NAT44EI translate fragments arriving in order """
3111 self.nat44_add_address(self.nat_addr)
3112 flags = self.config_flags.NAT44_EI_IF_INSIDE
3113 self.vapi.nat44_ei_interface_add_del_feature(
3114 sw_if_index=self.pg0.sw_if_index,
3115 flags=flags, is_add=1)
3116 self.vapi.nat44_ei_interface_add_del_feature(
3117 sw_if_index=self.pg1.sw_if_index,
3120 self.frag_in_order(proto=IP_PROTOS.tcp)
3121 self.frag_in_order(proto=IP_PROTOS.udp)
3122 self.frag_in_order(proto=IP_PROTOS.icmp)
3124 def test_frag_forwarding(self):
3125 """ NAT44EI forwarding fragment test """
3126 self.vapi.nat44_ei_add_del_interface_addr(
3128 sw_if_index=self.pg1.sw_if_index)
3129 flags = self.config_flags.NAT44_EI_IF_INSIDE
3130 self.vapi.nat44_ei_interface_add_del_feature(
3131 sw_if_index=self.pg0.sw_if_index,
3132 flags=flags, is_add=1)
3133 self.vapi.nat44_ei_interface_add_del_feature(
3134 sw_if_index=self.pg1.sw_if_index,
3136 self.vapi.nat44_ei_forwarding_enable_disable(enable=1)
3138 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3139 pkts = self.create_stream_frag(self.pg1,
3140 self.pg0.remote_ip4,
3144 proto=IP_PROTOS.udp)
3145 self.pg1.add_stream(pkts)
3146 self.pg_enable_capture(self.pg_interfaces)
3148 frags = self.pg0.get_capture(len(pkts))
3149 p = self.reass_frags_and_verify(frags,
3150 self.pg1.remote_ip4,
3151 self.pg0.remote_ip4)
3152 self.assertEqual(p[UDP].sport, 4789)
3153 self.assertEqual(p[UDP].dport, 4789)
3154 self.assertEqual(data, p[Raw].load)
3156 def test_reass_hairpinning(self):
3157 """ NAT44EI fragments hairpinning """
3159 server_addr = self.pg0.remote_hosts[1].ip4
3160 host_in_port = random.randint(1025, 65535)
3161 server_in_port = random.randint(1025, 65535)
3162 server_out_port = random.randint(1025, 65535)
3164 self.nat44_add_address(self.nat_addr)
3165 flags = self.config_flags.NAT44_EI_IF_INSIDE
3166 self.vapi.nat44_ei_interface_add_del_feature(
3167 sw_if_index=self.pg0.sw_if_index,
3168 flags=flags, is_add=1)
3169 self.vapi.nat44_ei_interface_add_del_feature(
3170 sw_if_index=self.pg1.sw_if_index,
3172 # add static mapping for server
3173 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3176 proto=IP_PROTOS.tcp)
3177 self.nat44_add_static_mapping(server_addr, self.nat_addr,
3180 proto=IP_PROTOS.udp)
3181 self.nat44_add_static_mapping(server_addr, self.nat_addr)
3183 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3184 host_in_port, proto=IP_PROTOS.tcp)
3185 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3186 host_in_port, proto=IP_PROTOS.udp)
3187 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
3188 host_in_port, proto=IP_PROTOS.icmp)
3190 def test_frag_out_of_order(self):
3191 """ NAT44EI translate fragments arriving out of order """
3193 self.nat44_add_address(self.nat_addr)
3194 flags = self.config_flags.NAT44_EI_IF_INSIDE
3195 self.vapi.nat44_ei_interface_add_del_feature(
3196 sw_if_index=self.pg0.sw_if_index,
3197 flags=flags, is_add=1)
3198 self.vapi.nat44_ei_interface_add_del_feature(
3199 sw_if_index=self.pg1.sw_if_index,
3202 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3203 self.frag_out_of_order(proto=IP_PROTOS.udp)
3204 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3206 def test_port_restricted(self):
3207 """ NAT44EI Port restricted NAT44EI (MAP-E CE) """
3208 self.nat44_add_address(self.nat_addr)
3209 flags = self.config_flags.NAT44_EI_IF_INSIDE
3210 self.vapi.nat44_ei_interface_add_del_feature(
3211 sw_if_index=self.pg0.sw_if_index,
3212 flags=flags, is_add=1)
3213 self.vapi.nat44_ei_interface_add_del_feature(
3214 sw_if_index=self.pg1.sw_if_index,
3216 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=1,
3221 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3222 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3223 TCP(sport=4567, dport=22))
3224 self.pg0.add_stream(p)
3225 self.pg_enable_capture(self.pg_interfaces)
3227 capture = self.pg1.get_capture(1)
3232 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3233 self.assertEqual(ip.src, self.nat_addr)
3234 self.assertEqual(tcp.dport, 22)
3235 self.assertNotEqual(tcp.sport, 4567)
3236 self.assertEqual((tcp.sport >> 6) & 63, 10)
3237 self.assert_packet_checksums_valid(p)
3239 self.logger.error(ppp("Unexpected or invalid packet:", p))
3242 def test_port_range(self):
3243 """ NAT44EI External address port range """
3244 self.nat44_add_address(self.nat_addr)
3245 flags = self.config_flags.NAT44_EI_IF_INSIDE
3246 self.vapi.nat44_ei_interface_add_del_feature(
3247 sw_if_index=self.pg0.sw_if_index,
3248 flags=flags, is_add=1)
3249 self.vapi.nat44_ei_interface_add_del_feature(
3250 sw_if_index=self.pg1.sw_if_index,
3252 self.vapi.nat44_ei_set_addr_and_port_alloc_alg(alg=2,
3257 for port in range(0, 5):
3258 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3259 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3260 TCP(sport=1125 + port))
3262 self.pg0.add_stream(pkts)
3263 self.pg_enable_capture(self.pg_interfaces)
3265 capture = self.pg1.get_capture(3)
3268 self.assertGreaterEqual(tcp.sport, 1025)
3269 self.assertLessEqual(tcp.sport, 1027)
3271 def test_multiple_outside_vrf(self):
3272 """ NAT44EI Multiple outside VRF """
3276 self.pg1.unconfig_ip4()
3277 self.pg2.unconfig_ip4()
3278 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3279 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3280 self.pg1.set_table_ip4(vrf_id1)
3281 self.pg2.set_table_ip4(vrf_id2)
3282 self.pg1.config_ip4()
3283 self.pg2.config_ip4()
3284 self.pg1.resolve_arp()
3285 self.pg2.resolve_arp()
3287 self.nat44_add_address(self.nat_addr)
3288 flags = self.config_flags.NAT44_EI_IF_INSIDE
3289 self.vapi.nat44_ei_interface_add_del_feature(
3290 sw_if_index=self.pg0.sw_if_index,
3291 flags=flags, is_add=1)
3292 self.vapi.nat44_ei_interface_add_del_feature(
3293 sw_if_index=self.pg1.sw_if_index,
3295 self.vapi.nat44_ei_interface_add_del_feature(
3296 sw_if_index=self.pg2.sw_if_index,
3301 pkts = self.create_stream_in(self.pg0, self.pg1)
3302 self.pg0.add_stream(pkts)
3303 self.pg_enable_capture(self.pg_interfaces)
3305 capture = self.pg1.get_capture(len(pkts))
3306 self.verify_capture_out(capture, self.nat_addr)
3308 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3309 self.pg1.add_stream(pkts)
3310 self.pg_enable_capture(self.pg_interfaces)
3312 capture = self.pg0.get_capture(len(pkts))
3313 self.verify_capture_in(capture, self.pg0)
3315 self.tcp_port_in = 60303
3316 self.udp_port_in = 60304
3317 self.icmp_id_in = 60305
3320 pkts = self.create_stream_in(self.pg0, self.pg2)
3321 self.pg0.add_stream(pkts)
3322 self.pg_enable_capture(self.pg_interfaces)
3324 capture = self.pg2.get_capture(len(pkts))
3325 self.verify_capture_out(capture, self.nat_addr)
3327 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3328 self.pg2.add_stream(pkts)
3329 self.pg_enable_capture(self.pg_interfaces)
3331 capture = self.pg0.get_capture(len(pkts))
3332 self.verify_capture_in(capture, self.pg0)
3335 self.nat44_add_address(self.nat_addr, is_add=0)
3336 self.pg1.unconfig_ip4()
3337 self.pg2.unconfig_ip4()
3338 self.pg1.set_table_ip4(0)
3339 self.pg2.set_table_ip4(0)
3340 self.pg1.config_ip4()
3341 self.pg2.config_ip4()
3342 self.pg1.resolve_arp()
3343 self.pg2.resolve_arp()
3345 def test_mss_clamping(self):
3346 """ NAT44EI TCP MSS clamping """
3347 self.nat44_add_address(self.nat_addr)
3348 flags = self.config_flags.NAT44_EI_IF_INSIDE
3349 self.vapi.nat44_ei_interface_add_del_feature(
3350 sw_if_index=self.pg0.sw_if_index,
3351 flags=flags, is_add=1)
3352 self.vapi.nat44_ei_interface_add_del_feature(
3353 sw_if_index=self.pg1.sw_if_index,
3356 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3357 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3358 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3359 flags="S", options=[('MSS', 1400)]))
3361 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1000)
3362 self.pg0.add_stream(p)
3363 self.pg_enable_capture(self.pg_interfaces)
3365 capture = self.pg1.get_capture(1)
3366 # Negotiated MSS value greater than configured - changed
3367 self.verify_mss_value(capture[0], 1000)
3369 self.vapi.nat44_ei_set_mss_clamping(enable=0, mss_value=1500)
3370 self.pg0.add_stream(p)
3371 self.pg_enable_capture(self.pg_interfaces)
3373 capture = self.pg1.get_capture(1)
3374 # MSS clamping disabled - negotiated MSS unchanged
3375 self.verify_mss_value(capture[0], 1400)
3377 self.vapi.nat44_ei_set_mss_clamping(enable=1, mss_value=1500)
3378 self.pg0.add_stream(p)
3379 self.pg_enable_capture(self.pg_interfaces)
3381 capture = self.pg1.get_capture(1)
3382 # Negotiated MSS value smaller than configured - unchanged
3383 self.verify_mss_value(capture[0], 1400)
3385 def test_ha_send(self):
3386 """ NAT44EI Send HA session synchronization events (active) """
3387 flags = self.config_flags.NAT44_EI_IF_INSIDE
3388 self.vapi.nat44_ei_interface_add_del_feature(
3389 sw_if_index=self.pg0.sw_if_index,
3390 flags=flags, is_add=1)
3391 self.vapi.nat44_ei_interface_add_del_feature(
3392 sw_if_index=self.pg1.sw_if_index,
3394 self.nat44_add_address(self.nat_addr)
3396 self.vapi.nat44_ei_ha_set_listener(
3397 ip_address=self.pg3.local_ip4, port=12345, path_mtu=512)
3398 self.vapi.nat44_ei_ha_set_failover(
3399 ip_address=self.pg3.remote_ip4, port=12346,
3400 session_refresh_interval=10)
3401 bind_layers(UDP, HANATStateSync, sport=12345)
3404 pkts = self.create_stream_in(self.pg0, self.pg1)
3405 self.pg0.add_stream(pkts)
3406 self.pg_enable_capture(self.pg_interfaces)
3408 capture = self.pg1.get_capture(len(pkts))
3409 self.verify_capture_out(capture)
3410 # active send HA events
3411 self.vapi.nat44_ei_ha_flush()
3412 stats = self.statistics['/nat44-ei/ha/add-event-send']
3413 self.assertEqual(stats[:, 0].sum(), 3)
3414 capture = self.pg3.get_capture(1)
3416 self.assert_packet_checksums_valid(p)
3420 hanat = p[HANATStateSync]
3422 self.logger.error(ppp("Invalid packet:", p))
3425 self.assertEqual(ip.src, self.pg3.local_ip4)
3426 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3427 self.assertEqual(udp.sport, 12345)
3428 self.assertEqual(udp.dport, 12346)
3429 self.assertEqual(hanat.version, 1)
3430 # self.assertEqual(hanat.thread_index, 0)
3431 self.assertEqual(hanat.count, 3)
3432 seq = hanat.sequence_number
3433 for event in hanat.events:
3434 self.assertEqual(event.event_type, 1)
3435 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3436 self.assertEqual(event.out_addr, self.nat_addr)
3437 self.assertEqual(event.fib_index, 0)
3439 # ACK received events
3440 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3441 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3442 UDP(sport=12346, dport=12345) /
3443 HANATStateSync(sequence_number=seq, flags='ACK',
3444 thread_index=hanat.thread_index))
3445 self.pg3.add_stream(ack)
3447 stats = self.statistics['/nat44-ei/ha/ack-recv']
3448 self.assertEqual(stats[:, 0].sum(), 1)
3450 # delete one session
3451 self.pg_enable_capture(self.pg_interfaces)
3452 self.vapi.nat44_ei_del_session(
3453 address=self.pg0.remote_ip4, port=self.tcp_port_in,
3454 protocol=IP_PROTOS.tcp, flags=self.config_flags.NAT44_EI_IF_INSIDE)
3455 self.vapi.nat44_ei_ha_flush()
3456 stats = self.statistics['/nat44-ei/ha/del-event-send']
3457 self.assertEqual(stats[:, 0].sum(), 1)
3458 capture = self.pg3.get_capture(1)
3461 hanat = p[HANATStateSync]
3463 self.logger.error(ppp("Invalid packet:", p))
3466 self.assertGreater(hanat.sequence_number, seq)
3468 # do not send ACK, active retry send HA event again
3469 self.pg_enable_capture(self.pg_interfaces)
3471 stats = self.statistics['/nat44-ei/ha/retry-count']
3472 self.assertEqual(stats[:, 0].sum(), 3)
3473 stats = self.statistics['/nat44-ei/ha/missed-count']
3474 self.assertEqual(stats[:, 0].sum(), 1)
3475 capture = self.pg3.get_capture(3)
3476 for packet in capture:
3477 self.assertEqual(packet, p)
3479 # session counters refresh
3480 pkts = self.create_stream_out(self.pg1)
3481 self.pg1.add_stream(pkts)
3482 self.pg_enable_capture(self.pg_interfaces)
3484 self.pg0.get_capture(2)
3485 self.vapi.nat44_ei_ha_flush()
3486 stats = self.statistics['/nat44-ei/ha/refresh-event-send']
3487 self.assertEqual(stats[:, 0].sum(), 2)
3488 capture = self.pg3.get_capture(1)
3490 self.assert_packet_checksums_valid(p)
3494 hanat = p[HANATStateSync]
3496 self.logger.error(ppp("Invalid packet:", p))
3499 self.assertEqual(ip.src, self.pg3.local_ip4)
3500 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3501 self.assertEqual(udp.sport, 12345)
3502 self.assertEqual(udp.dport, 12346)
3503 self.assertEqual(hanat.version, 1)
3504 self.assertEqual(hanat.count, 2)
3505 seq = hanat.sequence_number
3506 for event in hanat.events:
3507 self.assertEqual(event.event_type, 3)
3508 self.assertEqual(event.out_addr, self.nat_addr)
3509 self.assertEqual(event.fib_index, 0)
3510 self.assertEqual(event.total_pkts, 2)
3511 self.assertGreater(event.total_bytes, 0)
3513 stats = self.statistics['/nat44-ei/ha/ack-recv']
3514 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3515 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3516 UDP(sport=12346, dport=12345) /
3517 HANATStateSync(sequence_number=seq, flags='ACK',
3518 thread_index=hanat.thread_index))
3519 self.pg3.add_stream(ack)
3521 stats = self.statistics['/nat44-ei/ha/ack-recv']
3522 self.assertEqual(stats[:, 0].sum(), 2)
3524 def test_ha_recv(self):
3525 """ NAT44EI Receive HA session synchronization events (passive) """
3526 self.nat44_add_address(self.nat_addr)
3527 flags = self.config_flags.NAT44_EI_IF_INSIDE
3528 self.vapi.nat44_ei_interface_add_del_feature(
3529 sw_if_index=self.pg0.sw_if_index,
3530 flags=flags, is_add=1)
3531 self.vapi.nat44_ei_interface_add_del_feature(
3532 sw_if_index=self.pg1.sw_if_index,
3534 self.vapi.nat44_ei_ha_set_listener(ip_address=self.pg3.local_ip4,
3535 port=12345, path_mtu=512)
3536 bind_layers(UDP, HANATStateSync, sport=12345)
3538 # this is a bit tricky - HA dictates thread index due to how it's
3539 # designed, but once we use HA to create a session, we also want
3540 # to pass a packet through said session. so the session must end
3541 # up on the correct thread from both directions - in2out (based on
3542 # IP address) and out2in (based on outside port)
3544 # first choose a thread index which is correct for IP
3545 thread_index = get_nat44_ei_in2out_worker_index(self.pg0.remote_ip4,
3546 self.vpp_worker_count)
3548 # now pick a port which is correct for given thread
3549 port_per_thread = int((0xffff-1024) / max(1, self.vpp_worker_count))
3550 self.tcp_port_out = 1024 + random.randint(1, port_per_thread)
3551 self.udp_port_out = 1024 + random.randint(1, port_per_thread)
3552 if self.vpp_worker_count > 0:
3553 self.tcp_port_out += port_per_thread * (thread_index - 1)
3554 self.udp_port_out += port_per_thread * (thread_index - 1)
3556 # send HA session add events to failover/passive
3557 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3558 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3559 UDP(sport=12346, dport=12345) /
3560 HANATStateSync(sequence_number=1, events=[
3561 Event(event_type='add', protocol='tcp',
3562 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3563 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3564 eh_addr=self.pg1.remote_ip4,
3565 ehn_addr=self.pg1.remote_ip4,
3566 eh_port=self.tcp_external_port,
3567 ehn_port=self.tcp_external_port, fib_index=0),
3568 Event(event_type='add', protocol='udp',
3569 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3570 in_port=self.udp_port_in, out_port=self.udp_port_out,
3571 eh_addr=self.pg1.remote_ip4,
3572 ehn_addr=self.pg1.remote_ip4,
3573 eh_port=self.udp_external_port,
3574 ehn_port=self.udp_external_port, fib_index=0)],
3575 thread_index=thread_index))
3577 self.pg3.add_stream(p)
3578 self.pg_enable_capture(self.pg_interfaces)
3581 capture = self.pg3.get_capture(1)
3584 hanat = p[HANATStateSync]
3586 self.logger.error(ppp("Invalid packet:", p))
3589 self.assertEqual(hanat.sequence_number, 1)
3590 self.assertEqual(hanat.flags, 'ACK')
3591 self.assertEqual(hanat.version, 1)
3592 self.assertEqual(hanat.thread_index, thread_index)
3593 stats = self.statistics['/nat44-ei/ha/ack-send']
3594 self.assertEqual(stats[:, 0].sum(), 1)
3595 stats = self.statistics['/nat44-ei/ha/add-event-recv']
3596 self.assertEqual(stats[:, 0].sum(), 2)
3597 users = self.statistics['/nat44-ei/total-users']
3598 self.assertEqual(users[:, 0].sum(), 1)
3599 sessions = self.statistics['/nat44-ei/total-sessions']
3600 self.assertEqual(sessions[:, 0].sum(), 2)
3601 users = self.vapi.nat44_ei_user_dump()
3602 self.assertEqual(len(users), 1)
3603 self.assertEqual(str(users[0].ip_address),
3604 self.pg0.remote_ip4)
3605 # there should be 2 sessions created by HA
3606 sessions = self.vapi.nat44_ei_user_session_dump(
3607 users[0].ip_address, users[0].vrf_id)
3608 self.assertEqual(len(sessions), 2)
3609 for session in sessions:
3610 self.assertEqual(str(session.inside_ip_address),
3611 self.pg0.remote_ip4)
3612 self.assertEqual(str(session.outside_ip_address),
3614 self.assertIn(session.inside_port,
3615 [self.tcp_port_in, self.udp_port_in])
3616 self.assertIn(session.outside_port,
3617 [self.tcp_port_out, self.udp_port_out])
3618 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3620 # send HA session delete event to failover/passive
3621 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3622 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3623 UDP(sport=12346, dport=12345) /
3624 HANATStateSync(sequence_number=2, events=[
3625 Event(event_type='del', protocol='udp',
3626 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3627 in_port=self.udp_port_in, out_port=self.udp_port_out,
3628 eh_addr=self.pg1.remote_ip4,
3629 ehn_addr=self.pg1.remote_ip4,
3630 eh_port=self.udp_external_port,
3631 ehn_port=self.udp_external_port, fib_index=0)],
3632 thread_index=thread_index))
3634 self.pg3.add_stream(p)
3635 self.pg_enable_capture(self.pg_interfaces)
3638 capture = self.pg3.get_capture(1)
3641 hanat = p[HANATStateSync]
3643 self.logger.error(ppp("Invalid packet:", p))
3646 self.assertEqual(hanat.sequence_number, 2)
3647 self.assertEqual(hanat.flags, 'ACK')
3648 self.assertEqual(hanat.version, 1)
3649 users = self.vapi.nat44_ei_user_dump()
3650 self.assertEqual(len(users), 1)
3651 self.assertEqual(str(users[0].ip_address),
3652 self.pg0.remote_ip4)
3653 # now we should have only 1 session, 1 deleted by HA
3654 sessions = self.vapi.nat44_ei_user_session_dump(users[0].ip_address,
3656 self.assertEqual(len(sessions), 1)
3657 stats = self.statistics['/nat44-ei/ha/del-event-recv']
3658 self.assertEqual(stats[:, 0].sum(), 1)
3660 stats = self.statistics.get_err_counter(
3661 '/err/nat44-ei-ha/pkts-processed')
3662 self.assertEqual(stats, 2)
3664 # send HA session refresh event to failover/passive
3665 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3666 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3667 UDP(sport=12346, dport=12345) /
3668 HANATStateSync(sequence_number=3, events=[
3669 Event(event_type='refresh', protocol='tcp',
3670 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3671 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3672 eh_addr=self.pg1.remote_ip4,
3673 ehn_addr=self.pg1.remote_ip4,
3674 eh_port=self.tcp_external_port,
3675 ehn_port=self.tcp_external_port, fib_index=0,
3676 total_bytes=1024, total_pkts=2)],
3677 thread_index=thread_index))
3678 self.pg3.add_stream(p)
3679 self.pg_enable_capture(self.pg_interfaces)
3682 capture = self.pg3.get_capture(1)
3685 hanat = p[HANATStateSync]
3687 self.logger.error(ppp("Invalid packet:", p))
3690 self.assertEqual(hanat.sequence_number, 3)
3691 self.assertEqual(hanat.flags, 'ACK')
3692 self.assertEqual(hanat.version, 1)
3693 users = self.vapi.nat44_ei_user_dump()
3694 self.assertEqual(len(users), 1)
3695 self.assertEqual(str(users[0].ip_address),
3696 self.pg0.remote_ip4)
3697 sessions = self.vapi.nat44_ei_user_session_dump(
3698 users[0].ip_address, users[0].vrf_id)
3699 self.assertEqual(len(sessions), 1)
3700 session = sessions[0]
3701 self.assertEqual(session.total_bytes, 1024)
3702 self.assertEqual(session.total_pkts, 2)
3703 stats = self.statistics['/nat44-ei/ha/refresh-event-recv']
3704 self.assertEqual(stats[:, 0].sum(), 1)
3706 stats = self.statistics.get_err_counter(
3707 '/err/nat44-ei-ha/pkts-processed')
3708 self.assertEqual(stats, 3)
3710 # send packet to test session created by HA
3711 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3712 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3713 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3714 self.pg1.add_stream(p)
3715 self.pg_enable_capture(self.pg_interfaces)
3717 capture = self.pg0.get_capture(1)
3723 self.logger.error(ppp("Invalid packet:", p))
3726 self.assertEqual(ip.src, self.pg1.remote_ip4)
3727 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3728 self.assertEqual(tcp.sport, self.tcp_external_port)
3729 self.assertEqual(tcp.dport, self.tcp_port_in)
3731 def reconfigure_frame_queue_nelts(self, frame_queue_nelts):
3732 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3733 self.vapi.nat44_ei_set_fq_options(frame_queue_nelts=frame_queue_nelts)
3734 # keep plugin configuration persistent
3735 self.plugin_enable()
3736 return self.vapi.nat44_ei_show_fq_options().frame_queue_nelts
3738 def test_set_frame_queue_nelts(self):
3739 """ NAT44 EI API test - worker handoff frame queue elements """
3740 self.assertEqual(self.reconfigure_frame_queue_nelts(512), 512)
3742 def show_commands_at_teardown(self):
3743 self.logger.info(self.vapi.cli("show nat44 ei timeouts"))
3744 self.logger.info(self.vapi.cli("show nat44 ei addresses"))
3745 self.logger.info(self.vapi.cli("show nat44 ei interfaces"))
3746 self.logger.info(self.vapi.cli("show nat44 ei static mappings"))
3747 self.logger.info(self.vapi.cli("show nat44 ei interface address"))
3748 self.logger.info(self.vapi.cli("show nat44 ei sessions detail"))
3749 self.logger.info(self.vapi.cli("show nat44 ei hash tables detail"))
3750 self.logger.info(self.vapi.cli("show nat44 ei ha"))
3752 self.vapi.cli("show nat44 ei addr-port-assignment-alg"))
3754 def test_outside_address_distribution(self):
3755 """ Outside address distribution based on source address """
3760 for i in range(1, x):
3762 nat_addresses.append(a)
3764 flags = self.config_flags.NAT44_EI_IF_INSIDE
3765 self.vapi.nat44_ei_interface_add_del_feature(
3766 sw_if_index=self.pg0.sw_if_index,
3767 flags=flags, is_add=1)
3768 self.vapi.nat44_ei_interface_add_del_feature(
3769 sw_if_index=self.pg1.sw_if_index,
3772 self.vapi.nat44_ei_add_del_address_range(
3773 first_ip_address=nat_addresses[0],
3774 last_ip_address=nat_addresses[-1],
3775 vrf_id=0xFFFFFFFF, is_add=1)
3777 self.pg0.generate_remote_hosts(x)
3781 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3782 IP(src=self.pg0.remote_hosts[i].ip4,
3783 dst=self.pg1.remote_ip4) /
3784 UDP(sport=7000+i, dport=80+i))
3787 self.pg0.add_stream(pkts)
3788 self.pg_enable_capture(self.pg_interfaces)
3790 recvd = self.pg1.get_capture(len(pkts))
3791 for (p_sent, p_recvd) in zip(pkts, recvd):
3792 packed = socket.inet_aton(p_sent[IP].src)
3793 numeric = struct.unpack("!L", packed)[0]
3794 numeric = socket.htonl(numeric)
3795 a = nat_addresses[(numeric-1) % len(nat_addresses)]
3796 self.assertEqual(a, p_recvd[IP].src, "Packet not translated")
3799 class TestNAT44Out2InDPO(MethodHolder):
3800 """ NAT44EI Test Cases using out2in DPO """
3803 def setUpClass(cls):
3804 super(TestNAT44Out2InDPO, cls).setUpClass()
3805 cls.vapi.cli("set log class nat44-ei level debug")
3807 cls.tcp_port_in = 6303
3808 cls.tcp_port_out = 6303
3809 cls.udp_port_in = 6304
3810 cls.udp_port_out = 6304
3811 cls.icmp_id_in = 6305
3812 cls.icmp_id_out = 6305
3813 cls.nat_addr = '10.0.0.3'
3814 cls.dst_ip4 = '192.168.70.1'
3816 cls.create_pg_interfaces(range(2))
3819 cls.pg0.config_ip4()
3820 cls.pg0.resolve_arp()
3823 cls.pg1.config_ip6()
3824 cls.pg1.resolve_ndp()
3826 r1 = VppIpRoute(cls, "::", 0,
3827 [VppRoutePath(cls.pg1.remote_ip6,
3828 cls.pg1.sw_if_index)],
3833 super(TestNAT44Out2InDPO, self).setUp()
3834 flags = self.config_flags.NAT44_EI_OUT2IN_DPO
3835 self.vapi.nat44_ei_plugin_enable_disable(enable=1, flags=flags)
3838 super(TestNAT44Out2InDPO, self).tearDown()
3839 if not self.vpp_dead:
3840 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
3841 self.vapi.cli("clear logging")
3843 def configure_xlat(self):
3844 self.dst_ip6_pfx = '1:2:3::'
3845 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3847 self.dst_ip6_pfx_len = 96
3848 self.src_ip6_pfx = '4:5:6::'
3849 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
3851 self.src_ip6_pfx_len = 96
3852 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
3853 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
3854 '\x00\x00\x00\x00', 0)
3856 @unittest.skip('Temporary disabled')
3857 def test_464xlat_ce(self):
3858 """ Test 464XLAT CE with NAT44EI """
3860 self.configure_xlat()
3862 flags = self.config_flags.NAT44_EI_IF_INSIDE
3863 self.vapi.nat44_ei_interface_add_del_feature(
3864 sw_if_index=self.pg0.sw_if_index,
3865 flags=flags, is_add=1)
3866 self.vapi.nat44_ei_add_del_address_range(
3867 first_ip_address=self.nat_addr_n,
3868 last_ip_address=self.nat_addr_n,
3869 vrf_id=0xFFFFFFFF, is_add=1)
3871 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3872 self.dst_ip6_pfx_len)
3873 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
3874 self.src_ip6_pfx_len)
3877 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3878 self.pg0.add_stream(pkts)
3879 self.pg_enable_capture(self.pg_interfaces)
3881 capture = self.pg1.get_capture(len(pkts))
3882 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
3885 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
3887 self.pg1.add_stream(pkts)
3888 self.pg_enable_capture(self.pg_interfaces)
3890 capture = self.pg0.get_capture(len(pkts))
3891 self.verify_capture_in(capture, self.pg0)
3893 self.vapi.nat44_ei_interface_add_del_feature(
3894 sw_if_index=self.pg0.sw_if_index,
3896 self.vapi.nat44_ei_add_del_address_range(
3897 first_ip_address=self.nat_addr_n,
3898 last_ip_address=self.nat_addr_n,
3901 @unittest.skip('Temporary disabled')
3902 def test_464xlat_ce_no_nat(self):
3903 """ Test 464XLAT CE without NAT44EI """
3905 self.configure_xlat()
3907 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
3908 self.dst_ip6_pfx_len)
3909 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
3910 self.src_ip6_pfx_len)
3912 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
3913 self.pg0.add_stream(pkts)
3914 self.pg_enable_capture(self.pg_interfaces)
3916 capture = self.pg1.get_capture(len(pkts))
3917 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
3918 nat_ip=out_dst_ip6, same_port=True)
3920 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
3921 self.pg1.add_stream(pkts)
3922 self.pg_enable_capture(self.pg_interfaces)
3924 capture = self.pg0.get_capture(len(pkts))
3925 self.verify_capture_in(capture, self.pg0)
3928 class TestNAT44EIMW(MethodHolder):
3929 """ NAT44EI Test Cases (multiple workers) """
3930 vpp_worker_count = 2
3931 max_translations = 10240
3935 def setUpClass(cls):
3936 super(TestNAT44EIMW, cls).setUpClass()
3937 cls.vapi.cli("set log class nat level debug")
3939 cls.tcp_port_in = 6303
3940 cls.tcp_port_out = 6303
3941 cls.udp_port_in = 6304
3942 cls.udp_port_out = 6304
3943 cls.icmp_id_in = 6305
3944 cls.icmp_id_out = 6305
3945 cls.nat_addr = '10.0.0.3'
3946 cls.ipfix_src_port = 4739
3947 cls.ipfix_domain_id = 1
3948 cls.tcp_external_port = 80
3949 cls.udp_external_port = 69
3951 cls.create_pg_interfaces(range(10))
3952 cls.interfaces = list(cls.pg_interfaces[0:4])
3954 for i in cls.interfaces:
3959 cls.pg0.generate_remote_hosts(3)
3960 cls.pg0.configure_ipv4_neighbors()
3962 cls.pg1.generate_remote_hosts(1)
3963 cls.pg1.configure_ipv4_neighbors()
3965 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
3966 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
3967 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
3969 cls.pg4._local_ip4 = "172.16.255.1"
3970 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
3971 cls.pg4.set_table_ip4(10)
3972 cls.pg5._local_ip4 = "172.17.255.3"
3973 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
3974 cls.pg5.set_table_ip4(10)
3975 cls.pg6._local_ip4 = "172.16.255.1"
3976 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
3977 cls.pg6.set_table_ip4(20)
3978 for i in cls.overlapping_interfaces:
3986 cls.pg9.generate_remote_hosts(2)
3987 cls.pg9.config_ip4()
3988 cls.vapi.sw_interface_add_del_address(
3989 sw_if_index=cls.pg9.sw_if_index,
3990 prefix="10.0.0.1/24")
3993 cls.pg9.resolve_arp()
3994 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
3995 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
3996 cls.pg9.resolve_arp()
3999 super(TestNAT44EIMW, self).setUp()
4000 self.vapi.nat44_ei_plugin_enable_disable(
4001 sessions=self.max_translations,
4002 users=self.max_users, enable=1)
4005 super(TestNAT44EIMW, self).tearDown()
4006 if not self.vpp_dead:
4007 self.vapi.nat44_ei_ipfix_enable_disable(
4008 domain_id=self.ipfix_domain_id,
4009 src_port=self.ipfix_src_port,
4011 self.ipfix_src_port = 4739
4012 self.ipfix_domain_id = 1
4014 self.vapi.nat44_ei_plugin_enable_disable(enable=0)
4015 self.vapi.cli("clear logging")
4017 def test_hairpinning(self):
4018 """ NAT44EI hairpinning - 1:1 NAPT """
4020 host = self.pg0.remote_hosts[0]
4021 server = self.pg0.remote_hosts[1]
4024 server_in_port = 5678
4025 server_out_port = 8765
4029 self.nat44_add_address(self.nat_addr)
4030 flags = self.config_flags.NAT44_EI_IF_INSIDE
4031 self.vapi.nat44_ei_interface_add_del_feature(
4032 sw_if_index=self.pg0.sw_if_index,
4033 flags=flags, is_add=1)
4034 self.vapi.nat44_ei_interface_add_del_feature(
4035 sw_if_index=self.pg1.sw_if_index,
4038 # add static mapping for server
4039 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
4040 server_in_port, server_out_port,
4041 proto=IP_PROTOS.tcp)
4043 cnt = self.statistics['/nat44-ei/hairpinning']
4044 # send packet from host to server
4045 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4046 IP(src=host.ip4, dst=self.nat_addr) /
4047 TCP(sport=host_in_port, dport=server_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, server.ip4)
4058 self.assertNotEqual(tcp.sport, host_in_port)
4059 self.assertEqual(tcp.dport, server_in_port)
4060 self.assert_packet_checksums_valid(p)
4061 host_out_port = tcp.sport
4063 self.logger.error(ppp("Unexpected or invalid packet:", p))
4066 after = self.statistics['/nat44-ei/hairpinning']
4068 if_idx = self.pg0.sw_if_index
4069 self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1)
4071 # send reply from server to host
4072 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4073 IP(src=server.ip4, dst=self.nat_addr) /
4074 TCP(sport=server_in_port, dport=host_out_port))
4075 self.pg0.add_stream(p)
4076 self.pg_enable_capture(self.pg_interfaces)
4078 capture = self.pg0.get_capture(1)
4083 self.assertEqual(ip.src, self.nat_addr)
4084 self.assertEqual(ip.dst, host.ip4)
4085 self.assertEqual(tcp.sport, server_out_port)
4086 self.assertEqual(tcp.dport, host_in_port)
4087 self.assert_packet_checksums_valid(p)
4089 self.logger.error(ppp("Unexpected or invalid packet:", p))
4092 after = self.statistics['/nat44-ei/hairpinning']
4093 if_idx = self.pg0.sw_if_index
4094 self.assertEqual(after[worker_1][if_idx] - cnt[worker_1][if_idx], 1)
4095 self.assertEqual(after[worker_2][if_idx] - cnt[worker_2][if_idx], 2)
4097 def test_hairpinning2(self):
4098 """ NAT44EI hairpinning - 1:1 NAT"""
4100 server1_nat_ip = "10.0.0.10"
4101 server2_nat_ip = "10.0.0.11"
4102 host = self.pg0.remote_hosts[0]
4103 server1 = self.pg0.remote_hosts[1]
4104 server2 = self.pg0.remote_hosts[2]
4105 server_tcp_port = 22
4106 server_udp_port = 20
4108 self.nat44_add_address(self.nat_addr)
4109 flags = self.config_flags.NAT44_EI_IF_INSIDE
4110 self.vapi.nat44_ei_interface_add_del_feature(
4111 sw_if_index=self.pg0.sw_if_index,
4112 flags=flags, is_add=1)
4113 self.vapi.nat44_ei_interface_add_del_feature(
4114 sw_if_index=self.pg1.sw_if_index,
4117 # add static mapping for servers
4118 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
4119 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
4123 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4124 IP(src=host.ip4, dst=server1_nat_ip) /
4125 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4127 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4128 IP(src=host.ip4, dst=server1_nat_ip) /
4129 UDP(sport=self.udp_port_in, dport=server_udp_port))
4131 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4132 IP(src=host.ip4, dst=server1_nat_ip) /
4133 ICMP(id=self.icmp_id_in, type='echo-request'))
4135 self.pg0.add_stream(pkts)
4136 self.pg_enable_capture(self.pg_interfaces)
4138 capture = self.pg0.get_capture(len(pkts))
4139 for packet in capture:
4141 self.assertEqual(packet[IP].src, self.nat_addr)
4142 self.assertEqual(packet[IP].dst, server1.ip4)
4143 if packet.haslayer(TCP):
4144 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
4145 self.assertEqual(packet[TCP].dport, server_tcp_port)
4146 self.tcp_port_out = packet[TCP].sport
4147 self.assert_packet_checksums_valid(packet)
4148 elif packet.haslayer(UDP):
4149 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
4150 self.assertEqual(packet[UDP].dport, server_udp_port)
4151 self.udp_port_out = packet[UDP].sport
4153 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
4154 self.icmp_id_out = packet[ICMP].id
4156 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4161 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4162 IP(src=server1.ip4, dst=self.nat_addr) /
4163 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4165 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4166 IP(src=server1.ip4, dst=self.nat_addr) /
4167 UDP(sport=server_udp_port, dport=self.udp_port_out))
4169 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4170 IP(src=server1.ip4, dst=self.nat_addr) /
4171 ICMP(id=self.icmp_id_out, type='echo-reply'))
4173 self.pg0.add_stream(pkts)
4174 self.pg_enable_capture(self.pg_interfaces)
4176 capture = self.pg0.get_capture(len(pkts))
4177 for packet in capture:
4179 self.assertEqual(packet[IP].src, server1_nat_ip)
4180 self.assertEqual(packet[IP].dst, host.ip4)
4181 if packet.haslayer(TCP):
4182 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4183 self.assertEqual(packet[TCP].sport, server_tcp_port)
4184 self.assert_packet_checksums_valid(packet)
4185 elif packet.haslayer(UDP):
4186 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4187 self.assertEqual(packet[UDP].sport, server_udp_port)
4189 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4191 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4194 # server2 to server1
4196 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4197 IP(src=server2.ip4, dst=server1_nat_ip) /
4198 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
4200 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4201 IP(src=server2.ip4, dst=server1_nat_ip) /
4202 UDP(sport=self.udp_port_in, dport=server_udp_port))
4204 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4205 IP(src=server2.ip4, dst=server1_nat_ip) /
4206 ICMP(id=self.icmp_id_in, type='echo-request'))
4208 self.pg0.add_stream(pkts)
4209 self.pg_enable_capture(self.pg_interfaces)
4211 capture = self.pg0.get_capture(len(pkts))
4212 for packet in capture:
4214 self.assertEqual(packet[IP].src, server2_nat_ip)
4215 self.assertEqual(packet[IP].dst, server1.ip4)
4216 if packet.haslayer(TCP):
4217 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
4218 self.assertEqual(packet[TCP].dport, server_tcp_port)
4219 self.tcp_port_out = packet[TCP].sport
4220 self.assert_packet_checksums_valid(packet)
4221 elif packet.haslayer(UDP):
4222 self.assertEqual(packet[UDP].sport, self.udp_port_in)
4223 self.assertEqual(packet[UDP].dport, server_udp_port)
4224 self.udp_port_out = packet[UDP].sport
4226 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4227 self.icmp_id_out = packet[ICMP].id
4229 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4232 # server1 to server2
4234 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4235 IP(src=server1.ip4, dst=server2_nat_ip) /
4236 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
4238 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4239 IP(src=server1.ip4, dst=server2_nat_ip) /
4240 UDP(sport=server_udp_port, dport=self.udp_port_out))
4242 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4243 IP(src=server1.ip4, dst=server2_nat_ip) /
4244 ICMP(id=self.icmp_id_out, type='echo-reply'))
4246 self.pg0.add_stream(pkts)
4247 self.pg_enable_capture(self.pg_interfaces)
4249 capture = self.pg0.get_capture(len(pkts))
4250 for packet in capture:
4252 self.assertEqual(packet[IP].src, server1_nat_ip)
4253 self.assertEqual(packet[IP].dst, server2.ip4)
4254 if packet.haslayer(TCP):
4255 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
4256 self.assertEqual(packet[TCP].sport, server_tcp_port)
4257 self.assert_packet_checksums_valid(packet)
4258 elif packet.haslayer(UDP):
4259 self.assertEqual(packet[UDP].dport, self.udp_port_in)
4260 self.assertEqual(packet[UDP].sport, server_udp_port)
4262 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
4264 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4268 if __name__ == '__main__':
4269 unittest.main(testRunner=VppTestRunner)