blob: a6786218bd3517f84285748c5bdbbfcd469a9008 [file] [log] [blame]
Matus Fabiande886752016-12-07 03:38:19 -08001#!/usr/bin/env python
2
3import socket
4import unittest
Matus Fabianeea28d72017-01-13 04:15:54 -08005import struct
Matus Fabianefcd1e92017-08-15 06:59:19 -07006import random
Matus Fabiande886752016-12-07 03:38:19 -08007
Martin Gálik977c1cb2017-03-30 23:21:51 -07008from framework import VppTestCase, VppTestRunner, running_extended_tests
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07009
10import scapy.compat
Matus Fabiande886752016-12-07 03:38:19 -080011from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080012from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Juraj Slobodac746a152018-07-09 02:36:37 +020013from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
Paul Vinciguerra978aa642018-11-24 22:19:12 -080014 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
Matus Fabianefcd1e92017-08-15 06:59:19 -070015from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070016from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080017from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070018from scapy.packet import bind_layers, Raw
Klement Sekera9225dee2016-12-12 08:36:58 +010019from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080020from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070021from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070022from util import ip4_range
Ole Troan8006c6a2018-12-17 12:02:26 +010023from vpp_papi import mac_pton
Matus Fabianad1f3e12018-11-28 21:26:34 -080024from syslog_rfc5424_parser import SyslogMessage, ParseError
25from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
Ole Troan7f991832018-12-06 17:35:12 +010026from io import BytesIO
Neale Ranns37029302018-08-10 05:30:06 -070027from vpp_papi import VppEnum
Neale Ranns097fa662018-05-01 05:17:55 -070028from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType
29from vpp_neighbor import VppNeighbor
Matus Fabian34931eb2019-02-26 09:05:23 -080030from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
31 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
32 PacketListField
Filip Vargadd1e3e72019-04-15 18:52:43 +020033from ipaddress import IPv6Network
Matus Fabian34931eb2019-02-26 09:05:23 -080034
35
36# NAT HA protocol event data
37class Event(Packet):
38 name = "Event"
39 fields_desc = [ByteEnumField("event_type", None,
40 {1: "add", 2: "del", 3: "refresh"}),
41 ByteEnumField("protocol", None,
42 {0: "udp", 1: "tcp", 2: "icmp"}),
43 ShortField("flags", 0),
44 IPField("in_addr", None),
45 IPField("out_addr", None),
46 ShortField("in_port", None),
47 ShortField("out_port", None),
48 IPField("eh_addr", None),
49 IPField("ehn_addr", None),
50 ShortField("eh_port", None),
51 ShortField("ehn_port", None),
52 IntField("fib_index", None),
53 IntField("total_pkts", 0),
54 LongField("total_bytes", 0)]
55
56 def extract_padding(self, s):
57 return "", s
58
59
60# NAT HA protocol header
61class HANATStateSync(Packet):
62 name = "HA NAT state sync"
63 fields_desc = [XByteField("version", 1),
64 FlagsField("flags", 0, 8, ['ACK']),
65 FieldLenField("count", None, count_of="events"),
66 IntField("sequence_number", 1),
67 IntField("thread_index", 0),
68 PacketListField("events", [], Event,
Ole Troan9a475372019-03-05 16:58:24 +010069 count_from=lambda pkt: pkt.count)]
Matus Fabiande886752016-12-07 03:38:19 -080070
71
Martin Gálikd7f75cd2017-03-27 06:02:47 -070072class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070073 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080074
Filip Vargadd1e3e72019-04-15 18:52:43 +020075 @property
76 def config_flags(self):
77 return VppEnum.vl_api_nat_config_flags_t
78
Paul Vinciguerrab7658202019-05-17 09:48:15 -040079 @property
80 def SYSLOG_SEVERITY(self):
81 return VppEnum.vl_api_syslog_severity_t
82
Matus Fabiana6110b62018-06-13 05:39:07 -070083 def clear_nat44(self):
84 """
85 Clear NAT44 configuration.
86 """
87 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
Matus Fabiana6110b62018-06-13 05:39:07 -070088 if self.pg7.has_ip4_config:
89 self.pg7.unconfig_ip4()
90
Filip Vargaf4749ca2019-04-25 14:55:32 +020091 self.vapi.nat44_forwarding_enable_disable(enable=0)
Matus Fabiana6110b62018-06-13 05:39:07 -070092
93 interfaces = self.vapi.nat44_interface_addr_dump()
94 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +020095 self.vapi.nat44_add_del_interface_addr(
96 is_add=0,
97 sw_if_index=intf.sw_if_index,
98 flags=intf.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -070099
Filip Vargaf4749ca2019-04-25 14:55:32 +0200100 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Ole Troane1ade682019-03-04 23:55:43 +0100101 src_port=self.ipfix_src_port,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200102 enable=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700103 self.ipfix_src_port = 4739
104 self.ipfix_domain_id = 1
105
Paul Vinciguerrab7658202019-05-17 09:48:15 -0400106 self.vapi.syslog_set_filter(
107 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
Matus Fabianad1f3e12018-11-28 21:26:34 -0800108
Filip Vargaf4749ca2019-04-25 14:55:32 +0200109 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
110 path_mtu=512)
111 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
112 session_refresh_interval=10)
Matus Fabian34931eb2019-02-26 09:05:23 -0800113
Matus Fabiana6110b62018-06-13 05:39:07 -0700114 interfaces = self.vapi.nat44_interface_dump()
115 for intf in interfaces:
Filip Vargadd1e3e72019-04-15 18:52:43 +0200116 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
Filip Vargaf4749ca2019-04-25 14:55:32 +0200117 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
118 self.vapi.nat44_interface_add_del_feature(
119 sw_if_index=intf.sw_if_index)
120 self.vapi.nat44_interface_add_del_feature(
121 sw_if_index=intf.sw_if_index,
122 flags=intf.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700123
124 interfaces = self.vapi.nat44_interface_output_feature_dump()
125 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +0200126 self.vapi.nat44_interface_add_del_output_feature(
127 is_add=0,
128 flags=intf.flags,
129 sw_if_index=intf.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -0700130 static_mappings = self.vapi.nat44_static_mapping_dump()
131 for sm in static_mappings:
132 self.vapi.nat44_add_del_static_mapping(
Filip Vargadd1e3e72019-04-15 18:52:43 +0200133 is_add=0,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200134 local_ip_address=sm.local_ip_address,
135 external_ip_address=sm.external_ip_address,
136 external_sw_if_index=sm.external_sw_if_index,
137 local_port=sm.local_port,
138 external_port=sm.external_port,
139 vrf_id=sm.vrf_id,
140 protocol=sm.protocol,
141 flags=sm.flags, tag=sm.tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700142
143 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
144 for lb_sm in lb_static_mappings:
145 self.vapi.nat44_add_del_lb_static_mapping(
Matus Fabiana6110b62018-06-13 05:39:07 -0700146 is_add=0,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200147 flags=lb_sm.flags,
148 external_addr=lb_sm.external_addr,
149 external_port=lb_sm.external_port,
150 protocol=lb_sm.protocol,
151 local_num=0, locals=[],
152 tag=lb_sm.tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700153
154 identity_mappings = self.vapi.nat44_identity_mapping_dump()
155 for id_m in identity_mappings:
156 self.vapi.nat44_add_del_identity_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +0200157 ip_address=id_m.ip_address,
Matus Fabiana6110b62018-06-13 05:39:07 -0700158 sw_if_index=id_m.sw_if_index,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200159 port=id_m.port,
160 flags=id_m.flags,
Matus Fabiana6110b62018-06-13 05:39:07 -0700161 vrf_id=id_m.vrf_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200162 protocol=id_m.protocol)
Matus Fabiana6110b62018-06-13 05:39:07 -0700163
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700164 addresses = self.vapi.nat44_address_dump()
165 for addr in addresses:
Filip Vargaf4749ca2019-04-25 14:55:32 +0200166 self.vapi.nat44_add_del_address_range(
167 first_ip_address=addr.ip_address,
168 last_ip_address=addr.ip_address,
169 vrf_id=0xFFFFFFFF, flags=addr.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700170
Filip Vargaf4749ca2019-04-25 14:55:32 +0200171 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
172 drop_frag=0)
173 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
174 drop_frag=0, is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700175 self.verify_no_nat44_user()
Filip Vargaf4749ca2019-04-25 14:55:32 +0200176 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
177 tcp_transitory=240, icmp=60)
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700178 self.vapi.nat_set_addr_and_port_alloc_alg()
Filip Vargaf4749ca2019-04-25 14:55:32 +0200179 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
Matus Fabiana6110b62018-06-13 05:39:07 -0700180
181 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
182 local_port=0, external_port=0, vrf_id=0,
183 is_add=1, external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200184 proto=0, tag="", flags=0):
Matus Fabiana6110b62018-06-13 05:39:07 -0700185 """
186 Add/delete NAT44 static mapping
187
188 :param local_ip: Local IP address
189 :param external_ip: External IP address
190 :param local_port: Local port number (Optional)
191 :param external_port: External port number (Optional)
192 :param vrf_id: VRF ID (Default 0)
193 :param is_add: 1 if add, 0 if delete (Default add)
194 :param external_sw_if_index: External interface instead of IP address
195 :param proto: IP protocol (Mandatory if port specified)
Matus Fabiana6110b62018-06-13 05:39:07 -0700196 :param tag: Opaque string tag
Filip Vargadd1e3e72019-04-15 18:52:43 +0200197 :param flags: NAT configuration flags
Matus Fabiana6110b62018-06-13 05:39:07 -0700198 """
Filip Vargadd1e3e72019-04-15 18:52:43 +0200199
200 if not (local_port and external_port):
201 flags |= self.config_flags.NAT_IS_ADDR_ONLY
202
Matus Fabiana6110b62018-06-13 05:39:07 -0700203 self.vapi.nat44_add_del_static_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +0200204 is_add=is_add,
205 local_ip_address=local_ip,
206 external_ip_address=external_ip,
207 external_sw_if_index=external_sw_if_index,
208 local_port=local_port,
209 external_port=external_port,
210 vrf_id=vrf_id, protocol=proto,
211 flags=flags,
212 tag=tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700213
214 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
215 """
216 Add/delete NAT44 address
217
218 :param ip: IP address
219 :param is_add: 1 if add, 0 if delete (Default add)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700220 :param twice_nat: twice NAT address for external hosts
Matus Fabiana6110b62018-06-13 05:39:07 -0700221 """
Filip Vargadd1e3e72019-04-15 18:52:43 +0200222 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
Filip Vargaf4749ca2019-04-25 14:55:32 +0200223 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
224 last_ip_address=ip,
Matus Fabiana6110b62018-06-13 05:39:07 -0700225 vrf_id=vrf_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200226 is_add=is_add,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200227 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700228
Juraj Slobodacba69362017-12-19 02:09:32 +0100229 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800230 """
231 Create packet stream for inside network
232
233 :param in_if: Inside interface
234 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100235 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800236 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800237 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100238 if dst_ip is None:
239 dst_ip = out_if.remote_ip4
240
Matus Fabiande886752016-12-07 03:38:19 -0800241 pkts = []
242 # TCP
243 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100244 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700245 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800246 pkts.append(p)
247
248 # UDP
249 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100250 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700251 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800252 pkts.append(p)
253
254 # ICMP
255 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100256 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800257 ICMP(id=self.icmp_id_in, type='echo-request'))
258 pkts.append(p)
259
260 return pkts
261
Matus Fabian428dc912017-06-21 06:15:18 -0700262 def compose_ip6(self, ip4, pref, plen):
263 """
264 Compose IPv4-embedded IPv6 addresses
265
266 :param ip4: IPv4 address
267 :param pref: IPv6 prefix
268 :param plen: IPv6 prefix length
269 :returns: IPv4-embedded IPv6 addresses
270 """
271 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
272 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
273 if plen == 32:
274 pref_n[4] = ip4_n[0]
275 pref_n[5] = ip4_n[1]
276 pref_n[6] = ip4_n[2]
277 pref_n[7] = ip4_n[3]
278 elif plen == 40:
279 pref_n[5] = ip4_n[0]
280 pref_n[6] = ip4_n[1]
281 pref_n[7] = ip4_n[2]
282 pref_n[9] = ip4_n[3]
283 elif plen == 48:
284 pref_n[6] = ip4_n[0]
285 pref_n[7] = ip4_n[1]
286 pref_n[9] = ip4_n[2]
287 pref_n[10] = ip4_n[3]
288 elif plen == 56:
289 pref_n[7] = ip4_n[0]
290 pref_n[9] = ip4_n[1]
291 pref_n[10] = ip4_n[2]
292 pref_n[11] = ip4_n[3]
293 elif plen == 64:
294 pref_n[9] = ip4_n[0]
295 pref_n[10] = ip4_n[1]
296 pref_n[11] = ip4_n[2]
297 pref_n[12] = ip4_n[3]
298 elif plen == 96:
299 pref_n[12] = ip4_n[0]
300 pref_n[13] = ip4_n[1]
301 pref_n[14] = ip4_n[2]
302 pref_n[15] = ip4_n[3]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700303 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
304 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
Matus Fabian428dc912017-06-21 06:15:18 -0700305
Juraj Slobodacba69362017-12-19 02:09:32 +0100306 def extract_ip4(self, ip6, plen):
307 """
308 Extract IPv4 address embedded in IPv6 addresses
309
310 :param ip6: IPv6 address
311 :param plen: IPv6 prefix length
312 :returns: extracted IPv4 address
313 """
314 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
315 ip4_n = [None] * 4
316 if plen == 32:
317 ip4_n[0] = ip6_n[4]
318 ip4_n[1] = ip6_n[5]
319 ip4_n[2] = ip6_n[6]
320 ip4_n[3] = ip6_n[7]
321 elif plen == 40:
322 ip4_n[0] = ip6_n[5]
323 ip4_n[1] = ip6_n[6]
324 ip4_n[2] = ip6_n[7]
325 ip4_n[3] = ip6_n[9]
326 elif plen == 48:
327 ip4_n[0] = ip6_n[6]
328 ip4_n[1] = ip6_n[7]
329 ip4_n[2] = ip6_n[9]
330 ip4_n[3] = ip6_n[10]
331 elif plen == 56:
332 ip4_n[0] = ip6_n[7]
333 ip4_n[1] = ip6_n[9]
334 ip4_n[2] = ip6_n[10]
335 ip4_n[3] = ip6_n[11]
336 elif plen == 64:
337 ip4_n[0] = ip6_n[9]
338 ip4_n[1] = ip6_n[10]
339 ip4_n[2] = ip6_n[11]
340 ip4_n[3] = ip6_n[12]
341 elif plen == 96:
342 ip4_n[0] = ip6_n[12]
343 ip4_n[1] = ip6_n[13]
344 ip4_n[2] = ip6_n[14]
345 ip4_n[3] = ip6_n[15]
346 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
347
Matus Fabian428dc912017-06-21 06:15:18 -0700348 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700349 """
350 Create IPv6 packet stream for inside network
351
352 :param in_if: Inside interface
353 :param out_if: Outside interface
354 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700355 :param pref: NAT64 prefix
356 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700357 """
358 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700359 if pref is None:
360 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
361 else:
362 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
363
Matus Fabian06596c52017-06-06 04:53:28 -0700364 # TCP
365 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
366 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
367 TCP(sport=self.tcp_port_in, dport=20))
368 pkts.append(p)
369
370 # UDP
371 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
372 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
373 UDP(sport=self.udp_port_in, dport=20))
374 pkts.append(p)
375
376 # ICMP
377 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
378 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
379 ICMPv6EchoRequest(id=self.icmp_id_in))
380 pkts.append(p)
381
382 return pkts
383
Juraj Sloboda7b929792017-11-23 13:20:48 +0100384 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
385 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800386 """
387 Create packet stream for outside network
388
389 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700390 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800391 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100392 :param use_inside_ports: Use inside NAT ports as destination ports
393 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800394 """
395 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700396 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100397 if not use_inside_ports:
398 tcp_port = self.tcp_port_out
399 udp_port = self.udp_port_out
400 icmp_id = self.icmp_id_out
401 else:
402 tcp_port = self.tcp_port_in
403 udp_port = self.udp_port_in
404 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800405 pkts = []
406 # TCP
407 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800408 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100409 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800410 pkts.append(p)
411
412 # UDP
413 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800414 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100415 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800416 pkts.append(p)
417
418 # ICMP
419 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800420 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100421 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800422 pkts.append(p)
423
424 return pkts
425
Juraj Slobodacba69362017-12-19 02:09:32 +0100426 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
427 """
428 Create packet stream for outside network
429
430 :param out_if: Outside interface
431 :param dst_ip: Destination IP address (Default use global NAT address)
432 :param hl: HL of generated packets
433 """
434 pkts = []
435 # TCP
436 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
437 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
438 TCP(dport=self.tcp_port_out, sport=20))
439 pkts.append(p)
440
441 # UDP
442 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
443 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
444 UDP(dport=self.udp_port_out, sport=20))
445 pkts.append(p)
446
447 # ICMP
448 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
449 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
450 ICMPv6EchoReply(id=self.icmp_id_out))
451 pkts.append(p)
452
453 return pkts
454
Matus Fabiande886752016-12-07 03:38:19 -0800455 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700456 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800457 """
458 Verify captured packets on outside network
459
460 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700461 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700462 :param same_port: Source port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700463 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100464 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800465 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100466 if is_ip6:
467 IP46 = IPv6
468 ICMP46 = ICMPv6EchoRequest
469 else:
470 IP46 = IP
471 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800472 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700473 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800474 for packet in capture:
475 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100476 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200477 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100478 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700479 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100480 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800481 if packet.haslayer(TCP):
482 if same_port:
483 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
484 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100485 self.assertNotEqual(
486 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800487 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200488 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800489 elif packet.haslayer(UDP):
490 if same_port:
491 self.assertEqual(packet[UDP].sport, self.udp_port_in)
492 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100493 self.assertNotEqual(
494 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800495 self.udp_port_out = packet[UDP].sport
496 else:
497 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100498 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800499 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100500 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
501 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200502 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800503 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100504 self.logger.error(ppp("Unexpected or invalid packet "
505 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800506 raise
507
Juraj Slobodacba69362017-12-19 02:09:32 +0100508 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700509 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100510 """
511 Verify captured packets on outside network
512
513 :param capture: Captured packets
514 :param nat_ip: Translated IP address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700515 :param same_port: Source port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100516 :param dst_ip: Destination IP address (Default do not verify)
517 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700518 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
519 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100520
Matus Fabian05ca4a32018-09-04 23:45:13 -0700521 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800522 """
523 Verify captured packets on inside network
524
525 :param capture: Captured packets
526 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800527 """
Matus Fabiande886752016-12-07 03:38:19 -0800528 for packet in capture:
529 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200530 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800531 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
532 if packet.haslayer(TCP):
533 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
534 elif packet.haslayer(UDP):
535 self.assertEqual(packet[UDP].dport, self.udp_port_in)
536 else:
537 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
538 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100539 self.logger.error(ppp("Unexpected or invalid packet "
540 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800541 raise
542
Matus Fabian05ca4a32018-09-04 23:45:13 -0700543 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700544 """
545 Verify captured IPv6 packets on inside network
546
547 :param capture: Captured packets
548 :param src_ip: Source IP
549 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700550 """
Matus Fabian06596c52017-06-06 04:53:28 -0700551 for packet in capture:
552 try:
553 self.assertEqual(packet[IPv6].src, src_ip)
554 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200555 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700556 if packet.haslayer(TCP):
557 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
558 elif packet.haslayer(UDP):
559 self.assertEqual(packet[UDP].dport, self.udp_port_in)
560 else:
561 self.assertEqual(packet[ICMPv6EchoReply].id,
562 self.icmp_id_in)
563 except:
564 self.logger.error(ppp("Unexpected or invalid packet "
565 "(inside network):", packet))
566 raise
567
Matus Fabian675a69c2017-01-18 01:46:01 -0800568 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
569 """
570 Verify captured packet that don't have to be translated
571
572 :param capture: Captured packets
573 :param ingress_if: Ingress interface
574 :param egress_if: Egress interface
575 """
576 for packet in capture:
577 try:
578 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
579 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
580 if packet.haslayer(TCP):
581 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
582 elif packet.haslayer(UDP):
583 self.assertEqual(packet[UDP].sport, self.udp_port_in)
584 else:
585 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
586 except:
587 self.logger.error(ppp("Unexpected or invalid packet "
588 "(inside network):", packet))
589 raise
590
Juraj Slobodab33f4132017-02-08 23:54:21 -0800591 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700592 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800593 """
594 Verify captured packets with ICMP errors on outside network
595
596 :param capture: Captured packets
597 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700598 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800599 :param icmp_type: Type of error ICMP packet
600 we are expecting (Default 11)
601 """
602 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700603 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800604 for packet in capture:
605 try:
606 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800607 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800608 icmp = packet[ICMP]
609 self.assertEqual(icmp.type, icmp_type)
610 self.assertTrue(icmp.haslayer(IPerror))
611 inner_ip = icmp[IPerror]
612 if inner_ip.haslayer(TCPerror):
613 self.assertEqual(inner_ip[TCPerror].dport,
614 self.tcp_port_out)
615 elif inner_ip.haslayer(UDPerror):
616 self.assertEqual(inner_ip[UDPerror].dport,
617 self.udp_port_out)
618 else:
619 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
620 except:
621 self.logger.error(ppp("Unexpected or invalid packet "
622 "(outside network):", packet))
623 raise
624
Matus Fabian05ca4a32018-09-04 23:45:13 -0700625 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800626 """
627 Verify captured packets with ICMP errors on inside network
628
629 :param capture: Captured packets
630 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800631 :param icmp_type: Type of error ICMP packet
632 we are expecting (Default 11)
633 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800634 for packet in capture:
635 try:
636 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800637 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800638 icmp = packet[ICMP]
639 self.assertEqual(icmp.type, icmp_type)
640 self.assertTrue(icmp.haslayer(IPerror))
641 inner_ip = icmp[IPerror]
642 if inner_ip.haslayer(TCPerror):
643 self.assertEqual(inner_ip[TCPerror].sport,
644 self.tcp_port_in)
645 elif inner_ip.haslayer(UDPerror):
646 self.assertEqual(inner_ip[UDPerror].sport,
647 self.udp_port_in)
648 else:
649 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
650 except:
651 self.logger.error(ppp("Unexpected or invalid packet "
652 "(inside network):", packet))
653 raise
654
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200655 def create_stream_frag(self, src_if, dst, sport, dport, data,
656 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700657 """
658 Create fragmented packet stream
659
660 :param src_if: Source interface
661 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200662 :param sport: Source port
663 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700664 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200665 :param proto: protocol (TCP, UDP, ICMP)
666 :param echo_reply: use echo_reply if protocol is ICMP
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700667 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700668 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200669 if proto == IP_PROTOS.tcp:
670 p = (IP(src=src_if.remote_ip4, dst=dst) /
671 TCP(sport=sport, dport=dport) /
672 Raw(data))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700673 p = p.__class__(scapy.compat.raw(p))
674 chksum = p[TCP].chksum
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200675 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
676 elif proto == IP_PROTOS.udp:
677 proto_header = UDP(sport=sport, dport=dport)
678 elif proto == IP_PROTOS.icmp:
679 if not echo_reply:
680 proto_header = ICMP(id=sport, type='echo-request')
681 else:
682 proto_header = ICMP(id=sport, type='echo-reply')
683 else:
684 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700685 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700686 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200687 if proto == IP_PROTOS.tcp:
688 raw = Raw(data[0:4])
689 else:
690 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700691 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
692 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200693 proto_header /
694 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700695 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200696 if proto == IP_PROTOS.tcp:
697 raw = Raw(data[4:20])
698 else:
699 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700700 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
701 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200702 proto=proto) /
703 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700704 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200705 if proto == IP_PROTOS.tcp:
706 raw = Raw(data[20:])
707 else:
708 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700709 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200710 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700711 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200712 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700713 pkts.append(p)
714 return pkts
715
716 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
717 pref=None, plen=0, frag_size=128):
718 """
719 Create fragmented packet stream
720
721 :param src_if: Source interface
722 :param dst: Destination IPv4 address
723 :param sport: Source TCP port
724 :param dport: Destination TCP port
725 :param data: Payload data
726 :param pref: NAT64 prefix
727 :param plen: NAT64 prefix length
728 :param fragsize: size of fragments
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700729 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700730 """
731 if pref is None:
732 dst_ip6 = ''.join(['64:ff9b::', dst])
733 else:
734 dst_ip6 = self.compose_ip6(dst, pref, plen)
735
736 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
737 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
738 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
739 TCP(sport=sport, dport=dport) /
740 Raw(data))
741
742 return fragment6(p, frag_size)
743
744 def reass_frags_and_verify(self, frags, src, dst):
745 """
746 Reassemble and verify fragmented packet
747
748 :param frags: Captured fragments
749 :param src: Source IPv4 address to verify
750 :param dst: Destination IPv4 address to verify
751
752 :returns: Reassembled IPv4 packet
753 """
Ole Troan7f991832018-12-06 17:35:12 +0100754 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700755 for p in frags:
756 self.assertEqual(p[IP].src, src)
757 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200758 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700759 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100760 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700761 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
762 proto=frags[0][IP].proto)
763 if ip.proto == IP_PROTOS.tcp:
764 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200765 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700766 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200767 p = (ip / UDP(buffer.getvalue()[:8]) /
768 Raw(buffer.getvalue()[8:]))
769 elif ip.proto == IP_PROTOS.icmp:
770 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700771 return p
772
773 def reass_frags_and_verify_ip6(self, frags, src, dst):
774 """
775 Reassemble and verify fragmented packet
776
777 :param frags: Captured fragments
778 :param src: Source IPv6 address to verify
779 :param dst: Destination IPv6 address to verify
780
781 :returns: Reassembled IPv6 packet
782 """
Ole Troan7f991832018-12-06 17:35:12 +0100783 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700784 for p in frags:
785 self.assertEqual(p[IPv6].src, src)
786 self.assertEqual(p[IPv6].dst, dst)
787 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100788 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700789 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
790 nh=frags[0][IPv6ExtHdrFragment].nh)
791 if ip.nh == IP_PROTOS.tcp:
792 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700793 elif ip.nh == IP_PROTOS.udp:
794 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200795 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700796 return p
797
Matus Fabianebdf1902018-05-04 03:57:42 -0700798 def initiate_tcp_session(self, in_if, out_if):
799 """
800 Initiates TCP session
801
802 :param in_if: Inside interface
803 :param out_if: Outside interface
804 """
805 try:
806 # SYN packet in->out
807 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
808 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
809 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
810 flags="S"))
811 in_if.add_stream(p)
812 self.pg_enable_capture(self.pg_interfaces)
813 self.pg_start()
814 capture = out_if.get_capture(1)
815 p = capture[0]
816 self.tcp_port_out = p[TCP].sport
817
818 # SYN + ACK packet out->in
819 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
820 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
821 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
822 flags="SA"))
823 out_if.add_stream(p)
824 self.pg_enable_capture(self.pg_interfaces)
825 self.pg_start()
826 in_if.get_capture(1)
827
828 # ACK packet in->out
829 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
830 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
831 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
832 flags="A"))
833 in_if.add_stream(p)
834 self.pg_enable_capture(self.pg_interfaces)
835 self.pg_start()
836 out_if.get_capture(1)
837
838 except:
839 self.logger.error("TCP 3 way handshake failed")
840 raise
841
Matus Fabianeea28d72017-01-13 04:15:54 -0800842 def verify_ipfix_nat44_ses(self, data):
843 """
844 Verify IPFIX NAT44 session create/delete event
845
846 :param data: Decoded IPFIX data records
847 """
848 nat44_ses_create_num = 0
849 nat44_ses_delete_num = 0
850 self.assertEqual(6, len(data))
851 for record in data:
852 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700853 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
854 if scapy.compat.orb(record[230]) == 4:
Matus Fabianeea28d72017-01-13 04:15:54 -0800855 nat44_ses_create_num += 1
856 else:
857 nat44_ses_delete_num += 1
858 # sourceIPv4Address
859 self.assertEqual(self.pg0.remote_ip4n, record[8])
860 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700861 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800862 record[225])
863 # ingressVRFID
864 self.assertEqual(struct.pack("!I", 0), record[234])
Filip Vargaf4749ca2019-04-25 14:55:32 +0200865 # protocolIdentifier/sourceTransportPort
866 # /postNAPTSourceTransportPort
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700867 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800868 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
869 self.assertEqual(struct.pack("!H", self.icmp_id_out),
870 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700871 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800872 self.assertEqual(struct.pack("!H", self.tcp_port_in),
873 record[7])
874 self.assertEqual(struct.pack("!H", self.tcp_port_out),
875 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700876 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800877 self.assertEqual(struct.pack("!H", self.udp_port_in),
878 record[7])
879 self.assertEqual(struct.pack("!H", self.udp_port_out),
880 record[227])
881 else:
882 self.fail("Invalid protocol")
883 self.assertEqual(3, nat44_ses_create_num)
884 self.assertEqual(3, nat44_ses_delete_num)
885
886 def verify_ipfix_addr_exhausted(self, data):
887 """
888 Verify IPFIX NAT addresses event
889
890 :param data: Decoded IPFIX data records
891 """
892 self.assertEqual(1, len(data))
893 record = data[0]
894 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700895 self.assertEqual(scapy.compat.orb(record[230]), 3)
Matus Fabianeea28d72017-01-13 04:15:54 -0800896 # natPoolID
897 self.assertEqual(struct.pack("!I", 0), record[283])
898
Matus Fabiana431ad12018-01-04 04:03:14 -0800899 def verify_ipfix_max_sessions(self, data, limit):
900 """
901 Verify IPFIX maximum session entries exceeded event
902
903 :param data: Decoded IPFIX data records
904 :param limit: Number of maximum session entries that can be created.
905 """
906 self.assertEqual(1, len(data))
907 record = data[0]
908 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700909 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800910 # natQuotaExceededEvent
911 self.assertEqual(struct.pack("I", 1), record[466])
912 # maxSessionEntries
913 self.assertEqual(struct.pack("I", limit), record[471])
914
915 def verify_ipfix_max_bibs(self, data, limit):
916 """
917 Verify IPFIX maximum BIB entries exceeded event
918
919 :param data: Decoded IPFIX data records
920 :param limit: Number of maximum BIB entries that can be created.
921 """
922 self.assertEqual(1, len(data))
923 record = data[0]
924 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700925 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800926 # natQuotaExceededEvent
927 self.assertEqual(struct.pack("I", 2), record[466])
928 # maxBIBEntries
929 self.assertEqual(struct.pack("I", limit), record[472])
930
931 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
932 """
933 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
934
935 :param data: Decoded IPFIX data records
936 :param limit: Number of maximum fragments pending reassembly
937 :param src_addr: IPv6 source address
938 """
939 self.assertEqual(1, len(data))
940 record = data[0]
941 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700942 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800943 # natQuotaExceededEvent
944 self.assertEqual(struct.pack("I", 5), record[466])
945 # maxFragmentsPendingReassembly
946 self.assertEqual(struct.pack("I", limit), record[475])
947 # sourceIPv6Address
948 self.assertEqual(src_addr, record[27])
949
950 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
951 """
952 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
953
954 :param data: Decoded IPFIX data records
955 :param limit: Number of maximum fragments pending reassembly
956 :param src_addr: IPv4 source address
957 """
958 self.assertEqual(1, len(data))
959 record = data[0]
960 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700961 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800962 # natQuotaExceededEvent
963 self.assertEqual(struct.pack("I", 5), record[466])
964 # maxFragmentsPendingReassembly
965 self.assertEqual(struct.pack("I", limit), record[475])
966 # sourceIPv4Address
967 self.assertEqual(src_addr, record[8])
968
969 def verify_ipfix_bib(self, data, is_create, src_addr):
970 """
971 Verify IPFIX NAT64 BIB create and delete events
972
973 :param data: Decoded IPFIX data records
974 :param is_create: Create event if nonzero value otherwise delete event
975 :param src_addr: IPv6 source address
976 """
977 self.assertEqual(1, len(data))
978 record = data[0]
979 # natEvent
980 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700981 self.assertEqual(scapy.compat.orb(record[230]), 10)
Matus Fabiana431ad12018-01-04 04:03:14 -0800982 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700983 self.assertEqual(scapy.compat.orb(record[230]), 11)
Matus Fabiana431ad12018-01-04 04:03:14 -0800984 # sourceIPv6Address
985 self.assertEqual(src_addr, record[27])
986 # postNATSourceIPv4Address
987 self.assertEqual(self.nat_addr_n, record[225])
988 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700989 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -0800990 # ingressVRFID
991 self.assertEqual(struct.pack("!I", 0), record[234])
992 # sourceTransportPort
993 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
994 # postNAPTSourceTransportPort
995 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
996
997 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
998 dst_port):
999 """
1000 Verify IPFIX NAT64 session create and delete events
1001
1002 :param data: Decoded IPFIX data records
1003 :param is_create: Create event if nonzero value otherwise delete event
1004 :param src_addr: IPv6 source address
1005 :param dst_addr: IPv4 destination address
1006 :param dst_port: destination TCP port
1007 """
1008 self.assertEqual(1, len(data))
1009 record = data[0]
1010 # natEvent
1011 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001012 self.assertEqual(scapy.compat.orb(record[230]), 6)
Matus Fabiana431ad12018-01-04 04:03:14 -08001013 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001014 self.assertEqual(scapy.compat.orb(record[230]), 7)
Matus Fabiana431ad12018-01-04 04:03:14 -08001015 # sourceIPv6Address
1016 self.assertEqual(src_addr, record[27])
1017 # destinationIPv6Address
1018 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1019 self.compose_ip6(dst_addr,
1020 '64:ff9b::',
1021 96)),
1022 record[28])
1023 # postNATSourceIPv4Address
1024 self.assertEqual(self.nat_addr_n, record[225])
1025 # postNATDestinationIPv4Address
1026 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1027 record[226])
1028 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001029 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001030 # ingressVRFID
1031 self.assertEqual(struct.pack("!I", 0), record[234])
1032 # sourceTransportPort
1033 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1034 # postNAPTSourceTransportPort
1035 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1036 # destinationTransportPort
1037 self.assertEqual(struct.pack("!H", dst_port), record[11])
1038 # postNAPTDestinationTransportPort
1039 self.assertEqual(struct.pack("!H", dst_port), record[228])
1040
Matus Fabian68ba8802018-08-08 05:52:47 -07001041 def verify_no_nat44_user(self):
1042 """ Verify that there is no NAT44 user """
1043 users = self.vapi.nat44_user_dump()
1044 self.assertEqual(len(users), 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08001045 users = self.statistics.get_counter('/nat44/total-users')
1046 self.assertEqual(users[0][0], 0)
1047 sessions = self.statistics.get_counter('/nat44/total-sessions')
1048 self.assertEqual(sessions[0][0], 0)
Matus Fabian68ba8802018-08-08 05:52:47 -07001049
Matus Fabian878c6462018-08-23 00:33:35 -07001050 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1051 """
1052 Verify IPFIX maximum entries per user exceeded event
1053
1054 :param data: Decoded IPFIX data records
1055 :param limit: Number of maximum entries per user
1056 :param src_addr: IPv4 source address
1057 """
1058 self.assertEqual(1, len(data))
1059 record = data[0]
1060 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001061 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabian878c6462018-08-23 00:33:35 -07001062 # natQuotaExceededEvent
1063 self.assertEqual(struct.pack("I", 3), record[466])
1064 # maxEntriesPerUser
1065 self.assertEqual(struct.pack("I", limit), record[473])
1066 # sourceIPv4Address
1067 self.assertEqual(src_addr, record[8])
1068
Matus Fabianad1f3e12018-11-28 21:26:34 -08001069 def verify_syslog_apmap(self, data, is_add=True):
1070 message = data.decode('utf-8')
1071 try:
1072 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001073 except ParseError as e:
1074 self.logger.error(e)
1075 raise
1076 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001077 self.assertEqual(message.severity, SyslogSeverity.info)
1078 self.assertEqual(message.appname, 'NAT')
1079 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1080 sd_params = message.sd.get('napmap')
1081 self.assertTrue(sd_params is not None)
1082 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1083 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1084 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1085 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1086 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1087 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1088 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1089 self.assertTrue(sd_params.get('SSUBIX') is not None)
1090 self.assertEqual(sd_params.get('SVLAN'), '0')
Matus Fabianad1f3e12018-11-28 21:26:34 -08001091
1092 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1093 message = data.decode('utf-8')
1094 try:
1095 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001096 except ParseError as e:
1097 self.logger.error(e)
1098 raise
1099 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001100 self.assertEqual(message.severity, SyslogSeverity.info)
1101 self.assertEqual(message.appname, 'NAT')
1102 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1103 sd_params = message.sd.get('nsess')
1104 self.assertTrue(sd_params is not None)
1105 if is_ip6:
1106 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1107 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1108 else:
1109 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1110 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1111 self.assertTrue(sd_params.get('SSUBIX') is not None)
1112 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1113 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1114 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1115 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1116 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1117 self.assertEqual(sd_params.get('SVLAN'), '0')
1118 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1119 self.assertEqual(sd_params.get('XDPORT'),
1120 "%d" % self.tcp_external_port)
Matus Fabianad1f3e12018-11-28 21:26:34 -08001121
Matus Fabianbb4e0222018-09-13 02:36:25 -07001122 def verify_mss_value(self, pkt, mss):
1123 """
1124 Verify TCP MSS value
1125
1126 :param pkt:
1127 :param mss:
1128 """
1129 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1130 raise TypeError("Not a TCP/IP packet")
1131
1132 for option in pkt[TCP].options:
1133 if option[0] == 'MSS':
1134 self.assertEqual(option[1], mss)
1135 self.assert_tcp_checksum_valid(pkt)
1136
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001137 @staticmethod
1138 def proto2layer(proto):
1139 if proto == IP_PROTOS.tcp:
1140 return TCP
1141 elif proto == IP_PROTOS.udp:
1142 return UDP
1143 elif proto == IP_PROTOS.icmp:
1144 return ICMP
1145 else:
1146 raise Exception("Unsupported protocol")
1147
1148 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1149 layer = self.proto2layer(proto)
1150
1151 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001152 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001153 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001154 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001155 self.port_in = random.randint(1025, 65535)
1156
1157 reass = self.vapi.nat_reass_dump()
1158 reass_n_start = len(reass)
1159
1160 # in2out
1161 pkts = self.create_stream_frag(self.pg0,
1162 self.pg1.remote_ip4,
1163 self.port_in,
1164 20,
1165 data,
1166 proto)
1167 self.pg0.add_stream(pkts)
1168 self.pg_enable_capture(self.pg_interfaces)
1169 self.pg_start()
1170 frags = self.pg1.get_capture(len(pkts))
1171 if not dont_translate:
1172 p = self.reass_frags_and_verify(frags,
1173 self.nat_addr,
1174 self.pg1.remote_ip4)
1175 else:
1176 p = self.reass_frags_and_verify(frags,
1177 self.pg0.remote_ip4,
1178 self.pg1.remote_ip4)
1179 if proto != IP_PROTOS.icmp:
1180 if not dont_translate:
1181 self.assertEqual(p[layer].dport, 20)
1182 self.assertNotEqual(p[layer].sport, self.port_in)
1183 else:
1184 self.assertEqual(p[layer].sport, self.port_in)
1185 else:
1186 if not dont_translate:
1187 self.assertNotEqual(p[layer].id, self.port_in)
1188 else:
1189 self.assertEqual(p[layer].id, self.port_in)
1190 self.assertEqual(data, p[Raw].load)
1191
1192 # out2in
1193 if not dont_translate:
1194 dst_addr = self.nat_addr
1195 else:
1196 dst_addr = self.pg0.remote_ip4
1197 if proto != IP_PROTOS.icmp:
1198 sport = 20
1199 dport = p[layer].sport
1200 else:
1201 sport = p[layer].id
1202 dport = 0
1203 pkts = self.create_stream_frag(self.pg1,
1204 dst_addr,
1205 sport,
1206 dport,
1207 data,
1208 proto,
1209 echo_reply=True)
1210 self.pg1.add_stream(pkts)
1211 self.pg_enable_capture(self.pg_interfaces)
1212 self.pg_start()
1213 frags = self.pg0.get_capture(len(pkts))
1214 p = self.reass_frags_and_verify(frags,
1215 self.pg1.remote_ip4,
1216 self.pg0.remote_ip4)
1217 if proto != IP_PROTOS.icmp:
1218 self.assertEqual(p[layer].sport, 20)
1219 self.assertEqual(p[layer].dport, self.port_in)
1220 else:
1221 self.assertEqual(p[layer].id, self.port_in)
1222 self.assertEqual(data, p[Raw].load)
1223
1224 reass = self.vapi.nat_reass_dump()
1225 reass_n_end = len(reass)
1226
1227 self.assertEqual(reass_n_end - reass_n_start, 2)
1228
1229 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1230 layer = self.proto2layer(proto)
1231
1232 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001233 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001234 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001235 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001236 self.port_in = random.randint(1025, 65535)
1237
1238 for i in range(2):
1239 reass = self.vapi.nat_reass_dump()
1240 reass_n_start = len(reass)
1241
1242 # out2in
1243 pkts = self.create_stream_frag(self.pg0,
1244 self.server_out_addr,
1245 self.port_in,
1246 self.server_out_port,
1247 data,
1248 proto)
1249 self.pg0.add_stream(pkts)
1250 self.pg_enable_capture(self.pg_interfaces)
1251 self.pg_start()
1252 frags = self.pg1.get_capture(len(pkts))
1253 p = self.reass_frags_and_verify(frags,
1254 self.pg0.remote_ip4,
1255 self.server_in_addr)
1256 if proto != IP_PROTOS.icmp:
1257 self.assertEqual(p[layer].sport, self.port_in)
1258 self.assertEqual(p[layer].dport, self.server_in_port)
1259 else:
1260 self.assertEqual(p[layer].id, self.port_in)
1261 self.assertEqual(data, p[Raw].load)
1262
1263 # in2out
1264 if proto != IP_PROTOS.icmp:
1265 pkts = self.create_stream_frag(self.pg1,
1266 self.pg0.remote_ip4,
1267 self.server_in_port,
1268 p[layer].sport,
1269 data,
1270 proto)
1271 else:
1272 pkts = self.create_stream_frag(self.pg1,
1273 self.pg0.remote_ip4,
1274 p[layer].id,
1275 0,
1276 data,
1277 proto,
1278 echo_reply=True)
1279 self.pg1.add_stream(pkts)
1280 self.pg_enable_capture(self.pg_interfaces)
1281 self.pg_start()
1282 frags = self.pg0.get_capture(len(pkts))
1283 p = self.reass_frags_and_verify(frags,
1284 self.server_out_addr,
1285 self.pg0.remote_ip4)
1286 if proto != IP_PROTOS.icmp:
1287 self.assertEqual(p[layer].sport, self.server_out_port)
1288 self.assertEqual(p[layer].dport, self.port_in)
1289 else:
1290 self.assertEqual(p[layer].id, self.port_in)
1291 self.assertEqual(data, p[Raw].load)
1292
1293 reass = self.vapi.nat_reass_dump()
1294 reass_n_end = len(reass)
1295
1296 self.assertEqual(reass_n_end - reass_n_start, 2)
1297
1298 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1299 layer = self.proto2layer(proto)
1300
1301 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001302 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001303 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001304 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001305
1306 # send packet from host to server
1307 pkts = self.create_stream_frag(self.pg0,
1308 self.nat_addr,
1309 self.host_in_port,
1310 self.server_out_port,
1311 data,
1312 proto)
1313 self.pg0.add_stream(pkts)
1314 self.pg_enable_capture(self.pg_interfaces)
1315 self.pg_start()
1316 frags = self.pg0.get_capture(len(pkts))
1317 p = self.reass_frags_and_verify(frags,
1318 self.nat_addr,
1319 self.server.ip4)
1320 if proto != IP_PROTOS.icmp:
1321 self.assertNotEqual(p[layer].sport, self.host_in_port)
1322 self.assertEqual(p[layer].dport, self.server_in_port)
1323 else:
1324 self.assertNotEqual(p[layer].id, self.host_in_port)
1325 self.assertEqual(data, p[Raw].load)
1326
1327 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1328 layer = self.proto2layer(proto)
1329
1330 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001331 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001332 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001333 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001334 self.port_in = random.randint(1025, 65535)
1335
1336 for i in range(2):
1337 # in2out
1338 pkts = self.create_stream_frag(self.pg0,
1339 self.pg1.remote_ip4,
1340 self.port_in,
1341 20,
1342 data,
1343 proto)
1344 pkts.reverse()
1345 self.pg0.add_stream(pkts)
1346 self.pg_enable_capture(self.pg_interfaces)
1347 self.pg_start()
1348 frags = self.pg1.get_capture(len(pkts))
1349 if not dont_translate:
1350 p = self.reass_frags_and_verify(frags,
1351 self.nat_addr,
1352 self.pg1.remote_ip4)
1353 else:
1354 p = self.reass_frags_and_verify(frags,
1355 self.pg0.remote_ip4,
1356 self.pg1.remote_ip4)
1357 if proto != IP_PROTOS.icmp:
1358 if not dont_translate:
1359 self.assertEqual(p[layer].dport, 20)
1360 self.assertNotEqual(p[layer].sport, self.port_in)
1361 else:
1362 self.assertEqual(p[layer].sport, self.port_in)
1363 else:
1364 if not dont_translate:
1365 self.assertNotEqual(p[layer].id, self.port_in)
1366 else:
1367 self.assertEqual(p[layer].id, self.port_in)
1368 self.assertEqual(data, p[Raw].load)
1369
1370 # out2in
1371 if not dont_translate:
1372 dst_addr = self.nat_addr
1373 else:
1374 dst_addr = self.pg0.remote_ip4
1375 if proto != IP_PROTOS.icmp:
1376 sport = 20
1377 dport = p[layer].sport
1378 else:
1379 sport = p[layer].id
1380 dport = 0
1381 pkts = self.create_stream_frag(self.pg1,
1382 dst_addr,
1383 sport,
1384 dport,
1385 data,
1386 proto,
1387 echo_reply=True)
1388 pkts.reverse()
1389 self.pg1.add_stream(pkts)
1390 self.pg_enable_capture(self.pg_interfaces)
1391 self.pg_start()
1392 frags = self.pg0.get_capture(len(pkts))
1393 p = self.reass_frags_and_verify(frags,
1394 self.pg1.remote_ip4,
1395 self.pg0.remote_ip4)
1396 if proto != IP_PROTOS.icmp:
1397 self.assertEqual(p[layer].sport, 20)
1398 self.assertEqual(p[layer].dport, self.port_in)
1399 else:
1400 self.assertEqual(p[layer].id, self.port_in)
1401 self.assertEqual(data, p[Raw].load)
1402
1403 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1404 layer = self.proto2layer(proto)
1405
1406 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001407 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001408 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001409 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001410 self.port_in = random.randint(1025, 65535)
1411
1412 for i in range(2):
1413 # out2in
1414 pkts = self.create_stream_frag(self.pg0,
1415 self.server_out_addr,
1416 self.port_in,
1417 self.server_out_port,
1418 data,
1419 proto)
1420 pkts.reverse()
1421 self.pg0.add_stream(pkts)
1422 self.pg_enable_capture(self.pg_interfaces)
1423 self.pg_start()
1424 frags = self.pg1.get_capture(len(pkts))
1425 p = self.reass_frags_and_verify(frags,
1426 self.pg0.remote_ip4,
1427 self.server_in_addr)
1428 if proto != IP_PROTOS.icmp:
1429 self.assertEqual(p[layer].dport, self.server_in_port)
1430 self.assertEqual(p[layer].sport, self.port_in)
1431 self.assertEqual(p[layer].dport, self.server_in_port)
1432 else:
1433 self.assertEqual(p[layer].id, self.port_in)
1434 self.assertEqual(data, p[Raw].load)
1435
1436 # in2out
1437 if proto != IP_PROTOS.icmp:
1438 pkts = self.create_stream_frag(self.pg1,
1439 self.pg0.remote_ip4,
1440 self.server_in_port,
1441 p[layer].sport,
1442 data,
1443 proto)
1444 else:
1445 pkts = self.create_stream_frag(self.pg1,
1446 self.pg0.remote_ip4,
1447 p[layer].id,
1448 0,
1449 data,
1450 proto,
1451 echo_reply=True)
1452 pkts.reverse()
1453 self.pg1.add_stream(pkts)
1454 self.pg_enable_capture(self.pg_interfaces)
1455 self.pg_start()
1456 frags = self.pg0.get_capture(len(pkts))
1457 p = self.reass_frags_and_verify(frags,
1458 self.server_out_addr,
1459 self.pg0.remote_ip4)
1460 if proto != IP_PROTOS.icmp:
1461 self.assertEqual(p[layer].sport, self.server_out_port)
1462 self.assertEqual(p[layer].dport, self.port_in)
1463 else:
1464 self.assertEqual(p[layer].id, self.port_in)
1465 self.assertEqual(data, p[Raw].load)
1466
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001467
Matus Fabian2ba92e32017-08-21 07:05:03 -07001468class TestNAT44(MethodHolder):
1469 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001470
1471 @classmethod
1472 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001473 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001474 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001475
1476 try:
1477 cls.tcp_port_in = 6303
1478 cls.tcp_port_out = 6303
1479 cls.udp_port_in = 6304
1480 cls.udp_port_out = 6304
1481 cls.icmp_id_in = 6305
1482 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001483 cls.nat_addr = '10.0.0.3'
Matus Fabian6631e9c2017-05-24 01:52:20 -07001484 cls.ipfix_src_port = 4739
1485 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001486 cls.tcp_external_port = 80
Matus Fabian34931eb2019-02-26 09:05:23 -08001487 cls.udp_external_port = 69
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001488
Matus Fabian36ea2d62017-10-24 04:13:49 -07001489 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001490 cls.interfaces = list(cls.pg_interfaces[0:4])
1491
1492 for i in cls.interfaces:
1493 i.admin_up()
1494 i.config_ip4()
1495 i.resolve_arp()
1496
Matus Fabian6fa74c62017-06-05 05:55:48 -07001497 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001498 cls.pg0.configure_ipv4_neighbors()
1499
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001500 cls.pg1.generate_remote_hosts(1)
1501 cls.pg1.configure_ipv4_neighbors()
1502
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001503 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Ole Troan9a475372019-03-05 16:58:24 +01001504 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1505 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001506
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001507 cls.pg4._local_ip4 = "172.16.255.1"
1508 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001509 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1510 cls.pg4.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001511 cls.pg5._local_ip4 = "172.17.255.3"
1512 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001513 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001514 cls.pg5.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001515 cls.pg6._local_ip4 = "172.16.255.1"
1516 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001517 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1518 cls.pg6.set_table_ip4(20)
1519 for i in cls.overlapping_interfaces:
1520 i.config_ip4()
1521 i.admin_up()
1522 i.resolve_arp()
1523
1524 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001525 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001526
Matus Fabian36ea2d62017-10-24 04:13:49 -07001527 cls.pg9.generate_remote_hosts(2)
1528 cls.pg9.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001529 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01001530 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001531 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1532 address_length=24)
Matus Fabian36ea2d62017-10-24 04:13:49 -07001533 cls.pg9.admin_up()
1534 cls.pg9.resolve_arp()
1535 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1536 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1537 cls.pg9.resolve_arp()
1538
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001539 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001540 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001541 raise
1542
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001543 @classmethod
1544 def tearDownClass(cls):
1545 super(TestNAT44, cls).tearDownClass()
1546
Matus Fabiande886752016-12-07 03:38:19 -08001547 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001548 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001549 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001550 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001551 self.vapi.nat44_interface_add_del_feature(
1552 sw_if_index=self.pg0.sw_if_index,
1553 flags=flags, is_add=1)
1554 self.vapi.nat44_interface_add_del_feature(
1555 sw_if_index=self.pg1.sw_if_index,
1556 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08001557
1558 # in2out
Ole Troan233e4682019-05-16 15:01:34 +02001559 tcpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001560 '/err/nat44-in2out-slowpath/TCP packets')
Ole Troan233e4682019-05-16 15:01:34 +02001561 udpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001562 '/err/nat44-in2out-slowpath/UDP packets')
Ole Troan233e4682019-05-16 15:01:34 +02001563 icmpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001564 '/err/nat44-in2out-slowpath/ICMP packets')
Ole Troan233e4682019-05-16 15:01:34 +02001565 totaln = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001566 '/err/nat44-in2out-slowpath/good in2out packets processed')
1567
Matus Fabiande886752016-12-07 03:38:19 -08001568 pkts = self.create_stream_in(self.pg0, self.pg1)
1569 self.pg0.add_stream(pkts)
1570 self.pg_enable_capture(self.pg_interfaces)
1571 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001572 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001573 self.verify_capture_out(capture)
1574
Ole Troan233e4682019-05-16 15:01:34 +02001575 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001576 '/err/nat44-in2out-slowpath/TCP packets')
1577 self.assertEqual(err - tcpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02001578 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001579 '/err/nat44-in2out-slowpath/UDP packets')
1580 self.assertEqual(err - udpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02001581 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001582 '/err/nat44-in2out-slowpath/ICMP packets')
1583 self.assertEqual(err - icmpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02001584 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001585 '/err/nat44-in2out-slowpath/good in2out packets processed')
1586 self.assertEqual(err - totaln, 3)
1587
Matus Fabiande886752016-12-07 03:38:19 -08001588 # out2in
Ole Troan233e4682019-05-16 15:01:34 +02001589 tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1590 udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1591 icmpn = self.statistics.get_err_counter(
1592 '/err/nat44-out2in/ICMP packets')
1593 totaln = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001594 '/err/nat44-out2in/good out2in packets processed')
1595
Matus Fabiande886752016-12-07 03:38:19 -08001596 pkts = self.create_stream_out(self.pg1)
1597 self.pg1.add_stream(pkts)
1598 self.pg_enable_capture(self.pg_interfaces)
1599 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001600 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001601 self.verify_capture_in(capture, self.pg0)
1602
Ole Troan233e4682019-05-16 15:01:34 +02001603 err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08001604 self.assertEqual(err - tcpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02001605 err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08001606 self.assertEqual(err - udpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02001607 err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08001608 self.assertEqual(err - icmpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02001609 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08001610 '/err/nat44-out2in/good out2in packets processed')
1611 self.assertEqual(err - totaln, 3)
1612
Matus Fabianfd0d5082018-12-18 01:08:51 -08001613 users = self.statistics.get_counter('/nat44/total-users')
1614 self.assertEqual(users[0][0], 1)
1615 sessions = self.statistics.get_counter('/nat44/total-sessions')
1616 self.assertEqual(sessions[0][0], 3)
1617
Juraj Slobodab33f4132017-02-08 23:54:21 -08001618 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001619 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001620
Matus Fabian2ba92e32017-08-21 07:05:03 -07001621 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001622 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001623 self.vapi.nat44_interface_add_del_feature(
1624 sw_if_index=self.pg0.sw_if_index,
1625 flags=flags, is_add=1)
1626 self.vapi.nat44_interface_add_del_feature(
1627 sw_if_index=self.pg1.sw_if_index,
1628 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001629
1630 # Client side - generate traffic
1631 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1632 self.pg0.add_stream(pkts)
1633 self.pg_enable_capture(self.pg_interfaces)
1634 self.pg_start()
1635
1636 # Client side - verify ICMP type 11 packets
1637 capture = self.pg0.get_capture(len(pkts))
1638 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1639
1640 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001641 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001642
Matus Fabian2ba92e32017-08-21 07:05:03 -07001643 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001644 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001645 self.vapi.nat44_interface_add_del_feature(
1646 sw_if_index=self.pg0.sw_if_index,
1647 flags=flags, is_add=1)
1648 self.vapi.nat44_interface_add_del_feature(
1649 sw_if_index=self.pg1.sw_if_index,
1650 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001651
1652 # Client side - create sessions
1653 pkts = self.create_stream_in(self.pg0, self.pg1)
1654 self.pg0.add_stream(pkts)
1655 self.pg_enable_capture(self.pg_interfaces)
1656 self.pg_start()
1657
1658 # Server side - generate traffic
1659 capture = self.pg1.get_capture(len(pkts))
1660 self.verify_capture_out(capture)
1661 pkts = self.create_stream_out(self.pg1, ttl=1)
1662 self.pg1.add_stream(pkts)
1663 self.pg_enable_capture(self.pg_interfaces)
1664 self.pg_start()
1665
1666 # Server side - verify ICMP type 11 packets
1667 capture = self.pg1.get_capture(len(pkts))
1668 self.verify_capture_out_with_icmp_errors(capture,
1669 src_ip=self.pg1.local_ip4)
1670
1671 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001672 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001673
Matus Fabian2ba92e32017-08-21 07:05:03 -07001674 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001675 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001676 self.vapi.nat44_interface_add_del_feature(
1677 sw_if_index=self.pg0.sw_if_index,
1678 flags=flags, is_add=1)
1679 self.vapi.nat44_interface_add_del_feature(
1680 sw_if_index=self.pg1.sw_if_index,
1681 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001682
1683 # Client side - generate traffic
1684 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1685 self.pg0.add_stream(pkts)
1686 self.pg_enable_capture(self.pg_interfaces)
1687 self.pg_start()
1688
1689 # Server side - simulate ICMP type 11 response
1690 capture = self.pg1.get_capture(len(pkts))
1691 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001692 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001693 ICMP(type=11) / packet[IP] for packet in capture]
1694 self.pg1.add_stream(pkts)
1695 self.pg_enable_capture(self.pg_interfaces)
1696 self.pg_start()
1697
1698 # Client side - verify ICMP type 11 packets
1699 capture = self.pg0.get_capture(len(pkts))
1700 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1701
1702 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001703 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001704
Matus Fabian2ba92e32017-08-21 07:05:03 -07001705 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001706 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001707 self.vapi.nat44_interface_add_del_feature(
1708 sw_if_index=self.pg0.sw_if_index,
1709 flags=flags, is_add=1)
1710 self.vapi.nat44_interface_add_del_feature(
1711 sw_if_index=self.pg1.sw_if_index,
1712 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001713
1714 # Client side - create sessions
1715 pkts = self.create_stream_in(self.pg0, self.pg1)
1716 self.pg0.add_stream(pkts)
1717 self.pg_enable_capture(self.pg_interfaces)
1718 self.pg_start()
1719
1720 # Server side - generate traffic
1721 capture = self.pg1.get_capture(len(pkts))
1722 self.verify_capture_out(capture)
1723 pkts = self.create_stream_out(self.pg1, ttl=2)
1724 self.pg1.add_stream(pkts)
1725 self.pg_enable_capture(self.pg_interfaces)
1726 self.pg_start()
1727
1728 # Client side - simulate ICMP type 11 response
1729 capture = self.pg0.get_capture(len(pkts))
1730 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1731 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1732 ICMP(type=11) / packet[IP] for packet in capture]
1733 self.pg0.add_stream(pkts)
1734 self.pg_enable_capture(self.pg_interfaces)
1735 self.pg_start()
1736
1737 # Server side - verify ICMP type 11 packets
1738 capture = self.pg1.get_capture(len(pkts))
1739 self.verify_capture_out_with_icmp_errors(capture)
1740
Juraj Sloboda665e4822017-02-16 17:17:19 -08001741 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001742 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001743
Matus Fabian2ba92e32017-08-21 07:05:03 -07001744 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001745 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001746 self.vapi.nat44_interface_add_del_feature(
1747 sw_if_index=self.pg0.sw_if_index,
1748 flags=flags, is_add=1)
1749 self.vapi.nat44_interface_add_del_feature(
1750 sw_if_index=self.pg1.sw_if_index,
1751 is_add=1)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001752
1753 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1754 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1755 ICMP(id=self.icmp_id_out, type='echo-request'))
1756 pkts = [p]
1757 self.pg1.add_stream(pkts)
1758 self.pg_enable_capture(self.pg_interfaces)
1759 self.pg_start()
1760 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001761 packet = capture[0]
1762 try:
1763 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1764 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1765 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1766 self.assertEqual(packet[ICMP].type, 0) # echo reply
1767 except:
1768 self.logger.error(ppp("Unexpected or invalid packet "
1769 "(outside network):", packet))
1770 raise
1771
Juraj Slobodad3677682017-04-14 03:24:45 +02001772 def test_ping_internal_host_from_outside(self):
1773 """ Ping internal host from outside network """
1774
Matus Fabian2ba92e32017-08-21 07:05:03 -07001775 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001776 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001777 self.vapi.nat44_interface_add_del_feature(
1778 sw_if_index=self.pg0.sw_if_index,
1779 flags=flags, is_add=1)
1780 self.vapi.nat44_interface_add_del_feature(
1781 sw_if_index=self.pg1.sw_if_index,
1782 is_add=1)
Juraj Slobodad3677682017-04-14 03:24:45 +02001783
1784 # out2in
1785 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001786 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001787 ICMP(id=self.icmp_id_out, type='echo-request'))
1788 self.pg1.add_stream(pkt)
1789 self.pg_enable_capture(self.pg_interfaces)
1790 self.pg_start()
1791 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001792 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001793 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1794
1795 # in2out
1796 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1797 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1798 ICMP(id=self.icmp_id_in, type='echo-reply'))
1799 self.pg0.add_stream(pkt)
1800 self.pg_enable_capture(self.pg_interfaces)
1801 self.pg_start()
1802 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001803 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001804 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1805
Matus Fabianc79396e2018-07-23 00:05:22 -07001806 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001807 """ NAT44 forwarding test """
1808
Filip Vargadd1e3e72019-04-15 18:52:43 +02001809 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001810 self.vapi.nat44_interface_add_del_feature(
1811 sw_if_index=self.pg0.sw_if_index,
1812 flags=flags, is_add=1)
1813 self.vapi.nat44_interface_add_del_feature(
1814 sw_if_index=self.pg1.sw_if_index,
1815 is_add=1)
1816 self.vapi.nat44_forwarding_enable_disable(enable=1)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001817
1818 real_ip = self.pg0.remote_ip4n
Filip Vargadd1e3e72019-04-15 18:52:43 +02001819 alias_ip = self.nat_addr
1820 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02001821 self.vapi.nat44_add_del_static_mapping(is_add=1,
1822 local_ip_address=real_ip,
1823 external_ip_address=alias_ip,
1824 external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +02001825 flags=flags)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001826
1827 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001828 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001829
1830 pkts = self.create_stream_out(self.pg1)
1831 self.pg1.add_stream(pkts)
1832 self.pg_enable_capture(self.pg_interfaces)
1833 self.pg_start()
1834 capture = self.pg0.get_capture(len(pkts))
1835 self.verify_capture_in(capture, self.pg0)
1836
1837 pkts = self.create_stream_in(self.pg0, self.pg1)
1838 self.pg0.add_stream(pkts)
1839 self.pg_enable_capture(self.pg_interfaces)
1840 self.pg_start()
1841 capture = self.pg1.get_capture(len(pkts))
1842 self.verify_capture_out(capture, same_port=True)
1843
Matus Fabianc79396e2018-07-23 00:05:22 -07001844 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001845
1846 host0 = self.pg0.remote_hosts[0]
1847 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1848 try:
1849 pkts = self.create_stream_out(self.pg1,
1850 dst_ip=self.pg0.remote_ip4,
1851 use_inside_ports=True)
1852 self.pg1.add_stream(pkts)
1853 self.pg_enable_capture(self.pg_interfaces)
1854 self.pg_start()
1855 capture = self.pg0.get_capture(len(pkts))
1856 self.verify_capture_in(capture, self.pg0)
1857
1858 pkts = self.create_stream_in(self.pg0, self.pg1)
1859 self.pg0.add_stream(pkts)
1860 self.pg_enable_capture(self.pg_interfaces)
1861 self.pg_start()
1862 capture = self.pg1.get_capture(len(pkts))
1863 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1864 same_port=True)
1865 finally:
1866 self.pg0.remote_hosts[0] = host0
1867
1868 finally:
Filip Vargaf4749ca2019-04-25 14:55:32 +02001869 self.vapi.nat44_forwarding_enable_disable(enable=0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001870 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02001871 self.vapi.nat44_add_del_static_mapping(
1872 is_add=0,
1873 local_ip_address=real_ip,
1874 external_ip_address=alias_ip,
1875 external_sw_if_index=0xFFFFFFFF,
1876 flags=flags)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001877
Matus Fabiande886752016-12-07 03:38:19 -08001878 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001879 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001880
1881 nat_ip = "10.0.0.10"
1882 self.tcp_port_out = 6303
1883 self.udp_port_out = 6304
1884 self.icmp_id_out = 6305
1885
Matus Fabian2ba92e32017-08-21 07:05:03 -07001886 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001887 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001888 self.vapi.nat44_interface_add_del_feature(
1889 sw_if_index=self.pg0.sw_if_index,
1890 flags=flags, is_add=1)
1891 self.vapi.nat44_interface_add_del_feature(
1892 sw_if_index=self.pg1.sw_if_index,
1893 is_add=1)
Matus Fabian5f224992018-01-25 21:59:16 -08001894 sm = self.vapi.nat44_static_mapping_dump()
1895 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001896 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
Matus Fabian9dba7812018-01-31 01:13:23 -08001897 self.assertEqual(sm[0].protocol, 0)
1898 self.assertEqual(sm[0].local_port, 0)
1899 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001900
1901 # in2out
1902 pkts = self.create_stream_in(self.pg0, self.pg1)
1903 self.pg0.add_stream(pkts)
1904 self.pg_enable_capture(self.pg_interfaces)
1905 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001906 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001907 self.verify_capture_out(capture, nat_ip, True)
1908
1909 # out2in
1910 pkts = self.create_stream_out(self.pg1, nat_ip)
1911 self.pg1.add_stream(pkts)
1912 self.pg_enable_capture(self.pg_interfaces)
1913 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001914 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001915 self.verify_capture_in(capture, self.pg0)
1916
1917 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001918 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001919
1920 nat_ip = "10.0.0.20"
1921 self.tcp_port_out = 6303
1922 self.udp_port_out = 6304
1923 self.icmp_id_out = 6305
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001924 tag = b"testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001925
Matus Fabian5f224992018-01-25 21:59:16 -08001926 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001927 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001928 self.vapi.nat44_interface_add_del_feature(
1929 sw_if_index=self.pg0.sw_if_index,
1930 flags=flags, is_add=1)
1931 self.vapi.nat44_interface_add_del_feature(
1932 sw_if_index=self.pg1.sw_if_index,
1933 is_add=1)
Matus Fabian5f224992018-01-25 21:59:16 -08001934 sm = self.vapi.nat44_static_mapping_dump()
1935 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001936 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001937
1938 # out2in
1939 pkts = self.create_stream_out(self.pg1, nat_ip)
1940 self.pg1.add_stream(pkts)
1941 self.pg_enable_capture(self.pg_interfaces)
1942 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001943 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001944 self.verify_capture_in(capture, self.pg0)
1945
1946 # in2out
1947 pkts = self.create_stream_in(self.pg0, self.pg1)
1948 self.pg0.add_stream(pkts)
1949 self.pg_enable_capture(self.pg_interfaces)
1950 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001951 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001952 self.verify_capture_out(capture, nat_ip, True)
1953
1954 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001955 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001956
1957 self.tcp_port_out = 3606
1958 self.udp_port_out = 3607
1959 self.icmp_id_out = 3608
1960
Matus Fabian2ba92e32017-08-21 07:05:03 -07001961 self.nat44_add_address(self.nat_addr)
1962 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1963 self.tcp_port_in, self.tcp_port_out,
1964 proto=IP_PROTOS.tcp)
1965 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1966 self.udp_port_in, self.udp_port_out,
1967 proto=IP_PROTOS.udp)
1968 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1969 self.icmp_id_in, self.icmp_id_out,
1970 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001971 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001972 self.vapi.nat44_interface_add_del_feature(
1973 sw_if_index=self.pg0.sw_if_index,
1974 flags=flags, is_add=1)
1975 self.vapi.nat44_interface_add_del_feature(
1976 sw_if_index=self.pg1.sw_if_index,
1977 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08001978
1979 # in2out
1980 pkts = self.create_stream_in(self.pg0, self.pg1)
1981 self.pg0.add_stream(pkts)
1982 self.pg_enable_capture(self.pg_interfaces)
1983 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001984 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001985 self.verify_capture_out(capture)
1986
1987 # out2in
1988 pkts = self.create_stream_out(self.pg1)
1989 self.pg1.add_stream(pkts)
1990 self.pg_enable_capture(self.pg_interfaces)
1991 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001992 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001993 self.verify_capture_in(capture, self.pg0)
1994
1995 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001996 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001997
1998 self.tcp_port_out = 30606
1999 self.udp_port_out = 30607
2000 self.icmp_id_out = 30608
2001
Matus Fabian2ba92e32017-08-21 07:05:03 -07002002 self.nat44_add_address(self.nat_addr)
2003 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2004 self.tcp_port_in, self.tcp_port_out,
2005 proto=IP_PROTOS.tcp)
2006 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2007 self.udp_port_in, self.udp_port_out,
2008 proto=IP_PROTOS.udp)
2009 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2010 self.icmp_id_in, self.icmp_id_out,
2011 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002012 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002013 self.vapi.nat44_interface_add_del_feature(
2014 sw_if_index=self.pg0.sw_if_index,
2015 flags=flags, is_add=1)
2016 self.vapi.nat44_interface_add_del_feature(
2017 sw_if_index=self.pg1.sw_if_index,
2018 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08002019
2020 # out2in
2021 pkts = self.create_stream_out(self.pg1)
2022 self.pg1.add_stream(pkts)
2023 self.pg_enable_capture(self.pg_interfaces)
2024 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002025 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002026 self.verify_capture_in(capture, self.pg0)
2027
2028 # in2out
2029 pkts = self.create_stream_in(self.pg0, self.pg1)
2030 self.pg0.add_stream(pkts)
2031 self.pg_enable_capture(self.pg_interfaces)
2032 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002033 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002034 self.verify_capture_out(capture)
2035
2036 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002037 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08002038
2039 nat_ip1 = "10.0.0.30"
2040 nat_ip2 = "10.0.0.40"
2041 self.tcp_port_out = 6303
2042 self.udp_port_out = 6304
2043 self.icmp_id_out = 6305
2044
Matus Fabian2ba92e32017-08-21 07:05:03 -07002045 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2046 vrf_id=10)
2047 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2048 vrf_id=10)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002049 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002050 self.vapi.nat44_interface_add_del_feature(
2051 sw_if_index=self.pg3.sw_if_index,
2052 is_add=1)
2053 self.vapi.nat44_interface_add_del_feature(
2054 sw_if_index=self.pg0.sw_if_index,
2055 flags=flags, is_add=1)
2056 self.vapi.nat44_interface_add_del_feature(
2057 sw_if_index=self.pg4.sw_if_index,
2058 flags=flags, is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08002059
Matus Fabian2ba92e32017-08-21 07:05:03 -07002060 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002061 pkts = self.create_stream_in(self.pg4, self.pg3)
2062 self.pg4.add_stream(pkts)
2063 self.pg_enable_capture(self.pg_interfaces)
2064 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002065 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002066 self.verify_capture_out(capture, nat_ip1, True)
2067
Matus Fabian2ba92e32017-08-21 07:05:03 -07002068 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002069 # are dropped)
2070 pkts = self.create_stream_in(self.pg0, self.pg3)
2071 self.pg0.add_stream(pkts)
2072 self.pg_enable_capture(self.pg_interfaces)
2073 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002074 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002075
Matus Fabianb793d092018-01-31 05:50:21 -08002076 def test_dynamic_to_static(self):
2077 """ Switch from dynamic translation to 1:1NAT """
2078 nat_ip = "10.0.0.10"
2079 self.tcp_port_out = 6303
2080 self.udp_port_out = 6304
2081 self.icmp_id_out = 6305
2082
2083 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002084 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002085 self.vapi.nat44_interface_add_del_feature(
2086 sw_if_index=self.pg0.sw_if_index,
2087 flags=flags, is_add=1)
2088 self.vapi.nat44_interface_add_del_feature(
2089 sw_if_index=self.pg1.sw_if_index,
2090 is_add=1)
Matus Fabianb793d092018-01-31 05:50:21 -08002091
2092 # dynamic
2093 pkts = self.create_stream_in(self.pg0, self.pg1)
2094 self.pg0.add_stream(pkts)
2095 self.pg_enable_capture(self.pg_interfaces)
2096 self.pg_start()
2097 capture = self.pg1.get_capture(len(pkts))
2098 self.verify_capture_out(capture)
2099
2100 # 1:1NAT
2101 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2102 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2103 self.assertEqual(len(sessions), 0)
2104 pkts = self.create_stream_in(self.pg0, self.pg1)
2105 self.pg0.add_stream(pkts)
2106 self.pg_enable_capture(self.pg_interfaces)
2107 self.pg_start()
2108 capture = self.pg1.get_capture(len(pkts))
2109 self.verify_capture_out(capture, nat_ip, True)
2110
Matus Fabianab7a8052017-11-28 04:29:41 -08002111 def test_identity_nat(self):
2112 """ Identity NAT """
Filip Vargadd1e3e72019-04-15 18:52:43 +02002113 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02002114 self.vapi.nat44_add_del_identity_mapping(
2115 ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
2116 flags=flags, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002117 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002118 self.vapi.nat44_interface_add_del_feature(
2119 sw_if_index=self.pg0.sw_if_index,
2120 flags=flags, is_add=1)
2121 self.vapi.nat44_interface_add_del_feature(
2122 sw_if_index=self.pg1.sw_if_index,
2123 is_add=1)
Matus Fabianab7a8052017-11-28 04:29:41 -08002124
2125 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2126 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2127 TCP(sport=12345, dport=56789))
2128 self.pg1.add_stream(p)
2129 self.pg_enable_capture(self.pg_interfaces)
2130 self.pg_start()
2131 capture = self.pg0.get_capture(1)
2132 p = capture[0]
2133 try:
2134 ip = p[IP]
2135 tcp = p[TCP]
2136 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2137 self.assertEqual(ip.src, self.pg1.remote_ip4)
2138 self.assertEqual(tcp.dport, 56789)
2139 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002140 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002141 except:
2142 self.logger.error(ppp("Unexpected or invalid packet:", p))
2143 raise
2144
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002145 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2146 self.assertEqual(len(sessions), 0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002147 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02002148 self.vapi.nat44_add_del_identity_mapping(
2149 ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
2150 flags=flags, vrf_id=1, is_add=1)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002151 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2152 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002153
Matus Fabiande886752016-12-07 03:38:19 -08002154 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002155 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002156
Matus Fabian2ba92e32017-08-21 07:05:03 -07002157 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002158 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002159 self.vapi.nat44_interface_add_del_feature(
2160 sw_if_index=self.pg0.sw_if_index,
2161 flags=flags, is_add=1)
2162 self.vapi.nat44_interface_add_del_feature(
2163 sw_if_index=self.pg1.sw_if_index,
2164 flags=flags, is_add=1)
2165 self.vapi.nat44_interface_add_del_feature(
2166 sw_if_index=self.pg3.sw_if_index,
2167 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08002168
Matus Fabian2ba92e32017-08-21 07:05:03 -07002169 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002170 pkts = self.create_stream_in(self.pg0, self.pg1)
2171 self.pg0.add_stream(pkts)
2172 self.pg_enable_capture(self.pg_interfaces)
2173 self.pg_start()
2174 capture = self.pg1.get_capture(len(pkts))
2175 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2176
Matus Fabian2ba92e32017-08-21 07:05:03 -07002177 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002178 pkts = self.create_stream_in(self.pg0, self.pg2)
2179 self.pg0.add_stream(pkts)
2180 self.pg_enable_capture(self.pg_interfaces)
2181 self.pg_start()
2182 capture = self.pg2.get_capture(len(pkts))
2183 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2184
Matus Fabiande886752016-12-07 03:38:19 -08002185 # in2out 1st interface
2186 pkts = self.create_stream_in(self.pg0, self.pg3)
2187 self.pg0.add_stream(pkts)
2188 self.pg_enable_capture(self.pg_interfaces)
2189 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002190 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002191 self.verify_capture_out(capture)
2192
2193 # out2in 1st interface
2194 pkts = self.create_stream_out(self.pg3)
2195 self.pg3.add_stream(pkts)
2196 self.pg_enable_capture(self.pg_interfaces)
2197 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002198 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002199 self.verify_capture_in(capture, self.pg0)
2200
2201 # in2out 2nd interface
2202 pkts = self.create_stream_in(self.pg1, self.pg3)
2203 self.pg1.add_stream(pkts)
2204 self.pg_enable_capture(self.pg_interfaces)
2205 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002206 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002207 self.verify_capture_out(capture)
2208
2209 # out2in 2nd interface
2210 pkts = self.create_stream_out(self.pg3)
2211 self.pg3.add_stream(pkts)
2212 self.pg_enable_capture(self.pg_interfaces)
2213 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002214 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002215 self.verify_capture_in(capture, self.pg1)
2216
Matus Fabiande886752016-12-07 03:38:19 -08002217 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002218 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002219
Matus Fabian675a69c2017-01-18 01:46:01 -08002220 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002221 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002222 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002223 self.vapi.nat44_interface_add_del_feature(
2224 sw_if_index=self.pg3.sw_if_index,
2225 is_add=1)
2226 self.vapi.nat44_interface_add_del_feature(
2227 sw_if_index=self.pg4.sw_if_index,
2228 flags=flags, is_add=1)
2229 self.vapi.nat44_interface_add_del_feature(
2230 sw_if_index=self.pg5.sw_if_index,
2231 flags=flags, is_add=1)
2232 self.vapi.nat44_interface_add_del_feature(
2233 sw_if_index=self.pg6.sw_if_index,
2234 flags=flags, is_add=1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002235 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2236 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002237
Matus Fabian2ba92e32017-08-21 07:05:03 -07002238 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002239 pkts = self.create_stream_in(self.pg4, self.pg5)
2240 self.pg4.add_stream(pkts)
2241 self.pg_enable_capture(self.pg_interfaces)
2242 self.pg_start()
2243 capture = self.pg5.get_capture(len(pkts))
2244 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2245
Matus Fabian2ba92e32017-08-21 07:05:03 -07002246 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002247 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2248 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2249 TCP(sport=1234, dport=5678))
2250 self.pg4.add_stream(p)
2251 self.pg_enable_capture(self.pg_interfaces)
2252 self.pg_start()
2253 capture = self.pg6.get_capture(1)
2254 p = capture[0]
2255 try:
2256 ip = p[IP]
2257 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002258 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002259 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2260 self.assertNotEqual(tcp.sport, 1234)
2261 self.assertEqual(tcp.dport, 5678)
2262 except:
2263 self.logger.error(ppp("Unexpected or invalid packet:", p))
2264 raise
Matus Fabiande886752016-12-07 03:38:19 -08002265
2266 # in2out 1st interface
2267 pkts = self.create_stream_in(self.pg4, self.pg3)
2268 self.pg4.add_stream(pkts)
2269 self.pg_enable_capture(self.pg_interfaces)
2270 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002271 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002272 self.verify_capture_out(capture)
2273
2274 # out2in 1st interface
2275 pkts = self.create_stream_out(self.pg3)
2276 self.pg3.add_stream(pkts)
2277 self.pg_enable_capture(self.pg_interfaces)
2278 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002279 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002280 self.verify_capture_in(capture, self.pg4)
2281
2282 # in2out 2nd interface
2283 pkts = self.create_stream_in(self.pg5, self.pg3)
2284 self.pg5.add_stream(pkts)
2285 self.pg_enable_capture(self.pg_interfaces)
2286 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002287 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002288 self.verify_capture_out(capture)
2289
2290 # out2in 2nd interface
2291 pkts = self.create_stream_out(self.pg3)
2292 self.pg3.add_stream(pkts)
2293 self.pg_enable_capture(self.pg_interfaces)
2294 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002295 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002296 self.verify_capture_in(capture, self.pg5)
2297
magalik23caa882017-02-08 23:25:45 -08002298 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002299 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002300 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002301 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002302 self.assertEqual(len(sessions), 3)
2303 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002304 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2305 self.assertEqual(str(session.inside_ip_address),
2306 self.pg5.remote_ip4)
magalik23caa882017-02-08 23:25:45 -08002307 self.assertEqual(session.outside_ip_address,
2308 addresses[0].ip_address)
2309 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2310 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2311 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2312 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2313 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2314 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2315 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2316 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2317 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2318
Matus Fabiande886752016-12-07 03:38:19 -08002319 # in2out 3rd interface
2320 pkts = self.create_stream_in(self.pg6, self.pg3)
2321 self.pg6.add_stream(pkts)
2322 self.pg_enable_capture(self.pg_interfaces)
2323 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002324 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002325 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002326
2327 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002328 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002329 self.pg3.add_stream(pkts)
2330 self.pg_enable_capture(self.pg_interfaces)
2331 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002332 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002333 self.verify_capture_in(capture, self.pg6)
2334
magalik23caa882017-02-08 23:25:45 -08002335 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002336 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002337 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002338 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002339 self.assertEqual(len(addresses), 1)
2340 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002341 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2342 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002343 for session in sessions:
2344 self.assertEqual(user.ip_address, session.inside_ip_address)
2345 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2346 self.assertTrue(session.protocol in
2347 [IP_PROTOS.tcp, IP_PROTOS.udp,
2348 IP_PROTOS.icmp])
Filip Vargadd1e3e72019-04-15 18:52:43 +02002349 self.assertFalse(session.flags &
2350 self.config_flags.NAT_IS_EXT_HOST_VALID)
magalik23caa882017-02-08 23:25:45 -08002351
2352 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002353 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002354 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002355 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002356 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2357 self.assertEqual(str(session.inside_ip_address),
2358 self.pg4.remote_ip4)
magalik23caa882017-02-08 23:25:45 -08002359 self.assertEqual(session.outside_ip_address,
2360 addresses[0].ip_address)
2361
2362 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002363 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002364 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002365 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002366 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2367 self.assertEqual(str(session.inside_ip_address),
2368 self.pg6.remote_ip4)
2369 self.assertEqual(str(session.outside_ip_address),
2370 static_nat_ip)
magalik23caa882017-02-08 23:25:45 -08002371 self.assertTrue(session.inside_port in
2372 [self.tcp_port_in, self.udp_port_in,
2373 self.icmp_id_in])
2374
Matus Fabianf78a70d2016-12-12 04:30:39 -08002375 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002376 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002377
2378 host = self.pg0.remote_hosts[0]
2379 server = self.pg0.remote_hosts[1]
2380 host_in_port = 1234
2381 host_out_port = 0
2382 server_in_port = 5678
2383 server_out_port = 8765
2384
Matus Fabian2ba92e32017-08-21 07:05:03 -07002385 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002386 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002387 self.vapi.nat44_interface_add_del_feature(
2388 sw_if_index=self.pg0.sw_if_index,
2389 flags=flags, is_add=1)
2390 self.vapi.nat44_interface_add_del_feature(
2391 sw_if_index=self.pg1.sw_if_index,
2392 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002393
Matus Fabianf78a70d2016-12-12 04:30:39 -08002394 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002395 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2396 server_in_port, server_out_port,
2397 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002398
2399 # send packet from host to server
2400 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002401 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002402 TCP(sport=host_in_port, dport=server_out_port))
2403 self.pg0.add_stream(p)
2404 self.pg_enable_capture(self.pg_interfaces)
2405 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002406 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002407 p = capture[0]
2408 try:
2409 ip = p[IP]
2410 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002411 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002412 self.assertEqual(ip.dst, server.ip4)
2413 self.assertNotEqual(tcp.sport, host_in_port)
2414 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002415 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002416 host_out_port = tcp.sport
2417 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002418 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002419 raise
2420
2421 # send reply from server to host
2422 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002423 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002424 TCP(sport=server_in_port, dport=host_out_port))
2425 self.pg0.add_stream(p)
2426 self.pg_enable_capture(self.pg_interfaces)
2427 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002428 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002429 p = capture[0]
2430 try:
2431 ip = p[IP]
2432 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002433 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002434 self.assertEqual(ip.dst, host.ip4)
2435 self.assertEqual(tcp.sport, server_out_port)
2436 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002437 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002438 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002439 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002440 raise
2441
Matus Fabian6fa74c62017-06-05 05:55:48 -07002442 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002443 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002444
2445 server1_nat_ip = "10.0.0.10"
2446 server2_nat_ip = "10.0.0.11"
2447 host = self.pg0.remote_hosts[0]
2448 server1 = self.pg0.remote_hosts[1]
2449 server2 = self.pg0.remote_hosts[2]
2450 server_tcp_port = 22
2451 server_udp_port = 20
2452
Matus Fabian2ba92e32017-08-21 07:05:03 -07002453 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002454 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002455 self.vapi.nat44_interface_add_del_feature(
2456 sw_if_index=self.pg0.sw_if_index,
2457 flags=flags, is_add=1)
2458 self.vapi.nat44_interface_add_del_feature(
2459 sw_if_index=self.pg1.sw_if_index,
2460 is_add=1)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002461
2462 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002463 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2464 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002465
2466 # host to server1
2467 pkts = []
2468 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2469 IP(src=host.ip4, dst=server1_nat_ip) /
2470 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2471 pkts.append(p)
2472 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2473 IP(src=host.ip4, dst=server1_nat_ip) /
2474 UDP(sport=self.udp_port_in, dport=server_udp_port))
2475 pkts.append(p)
2476 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2477 IP(src=host.ip4, dst=server1_nat_ip) /
2478 ICMP(id=self.icmp_id_in, type='echo-request'))
2479 pkts.append(p)
2480 self.pg0.add_stream(pkts)
2481 self.pg_enable_capture(self.pg_interfaces)
2482 self.pg_start()
2483 capture = self.pg0.get_capture(len(pkts))
2484 for packet in capture:
2485 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002486 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002487 self.assertEqual(packet[IP].dst, server1.ip4)
2488 if packet.haslayer(TCP):
2489 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2490 self.assertEqual(packet[TCP].dport, server_tcp_port)
2491 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002492 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002493 elif packet.haslayer(UDP):
2494 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2495 self.assertEqual(packet[UDP].dport, server_udp_port)
2496 self.udp_port_out = packet[UDP].sport
2497 else:
2498 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2499 self.icmp_id_out = packet[ICMP].id
2500 except:
2501 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2502 raise
2503
2504 # server1 to host
2505 pkts = []
2506 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002507 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002508 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2509 pkts.append(p)
2510 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002511 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002512 UDP(sport=server_udp_port, dport=self.udp_port_out))
2513 pkts.append(p)
2514 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002515 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002516 ICMP(id=self.icmp_id_out, type='echo-reply'))
2517 pkts.append(p)
2518 self.pg0.add_stream(pkts)
2519 self.pg_enable_capture(self.pg_interfaces)
2520 self.pg_start()
2521 capture = self.pg0.get_capture(len(pkts))
2522 for packet in capture:
2523 try:
2524 self.assertEqual(packet[IP].src, server1_nat_ip)
2525 self.assertEqual(packet[IP].dst, host.ip4)
2526 if packet.haslayer(TCP):
2527 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2528 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002529 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002530 elif packet.haslayer(UDP):
2531 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2532 self.assertEqual(packet[UDP].sport, server_udp_port)
2533 else:
2534 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2535 except:
2536 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2537 raise
2538
2539 # server2 to server1
2540 pkts = []
2541 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2542 IP(src=server2.ip4, dst=server1_nat_ip) /
2543 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2544 pkts.append(p)
2545 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2546 IP(src=server2.ip4, dst=server1_nat_ip) /
2547 UDP(sport=self.udp_port_in, dport=server_udp_port))
2548 pkts.append(p)
2549 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2550 IP(src=server2.ip4, dst=server1_nat_ip) /
2551 ICMP(id=self.icmp_id_in, type='echo-request'))
2552 pkts.append(p)
2553 self.pg0.add_stream(pkts)
2554 self.pg_enable_capture(self.pg_interfaces)
2555 self.pg_start()
2556 capture = self.pg0.get_capture(len(pkts))
2557 for packet in capture:
2558 try:
2559 self.assertEqual(packet[IP].src, server2_nat_ip)
2560 self.assertEqual(packet[IP].dst, server1.ip4)
2561 if packet.haslayer(TCP):
2562 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2563 self.assertEqual(packet[TCP].dport, server_tcp_port)
2564 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002565 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002566 elif packet.haslayer(UDP):
2567 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2568 self.assertEqual(packet[UDP].dport, server_udp_port)
2569 self.udp_port_out = packet[UDP].sport
2570 else:
2571 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2572 self.icmp_id_out = packet[ICMP].id
2573 except:
2574 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2575 raise
2576
2577 # server1 to server2
2578 pkts = []
2579 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2580 IP(src=server1.ip4, dst=server2_nat_ip) /
2581 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2582 pkts.append(p)
2583 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2584 IP(src=server1.ip4, dst=server2_nat_ip) /
2585 UDP(sport=server_udp_port, dport=self.udp_port_out))
2586 pkts.append(p)
2587 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2588 IP(src=server1.ip4, dst=server2_nat_ip) /
2589 ICMP(id=self.icmp_id_out, type='echo-reply'))
2590 pkts.append(p)
2591 self.pg0.add_stream(pkts)
2592 self.pg_enable_capture(self.pg_interfaces)
2593 self.pg_start()
2594 capture = self.pg0.get_capture(len(pkts))
2595 for packet in capture:
2596 try:
2597 self.assertEqual(packet[IP].src, server1_nat_ip)
2598 self.assertEqual(packet[IP].dst, server2.ip4)
2599 if packet.haslayer(TCP):
2600 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2601 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002602 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002603 elif packet.haslayer(UDP):
2604 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2605 self.assertEqual(packet[UDP].sport, server_udp_port)
2606 else:
2607 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2608 except:
2609 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2610 raise
2611
Matus Fabian9902fcd2016-12-21 23:58:46 -08002612 def test_max_translations_per_user(self):
2613 """ MAX translations per user - recycle the least recently used """
2614
Matus Fabian2ba92e32017-08-21 07:05:03 -07002615 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002616 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002617 self.vapi.nat44_interface_add_del_feature(
2618 sw_if_index=self.pg0.sw_if_index,
2619 flags=flags, is_add=1)
2620 self.vapi.nat44_interface_add_del_feature(
2621 sw_if_index=self.pg1.sw_if_index,
2622 is_add=1)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002623
2624 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002625 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002626
2627 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002628 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002629 pkts = []
2630 for port in range(0, pkts_num):
2631 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2632 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2633 TCP(sport=1025 + port))
2634 pkts.append(p)
2635 self.pg0.add_stream(pkts)
2636 self.pg_enable_capture(self.pg_interfaces)
2637 self.pg_start()
2638
2639 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002640 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002641
Matus Fabian132dc492018-05-09 04:51:03 -07002642 users = self.vapi.nat44_user_dump()
2643 for user in users:
2644 if user.ip_address == self.pg0.remote_ip4n:
2645 self.assertEqual(user.nsessions,
2646 nat44_config.max_translations_per_user)
2647 self.assertEqual(user.nstaticsessions, 0)
2648
2649 tcp_port = 22
2650 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2651 tcp_port, tcp_port,
2652 proto=IP_PROTOS.tcp)
2653 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2654 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2655 TCP(sport=tcp_port))
2656 self.pg0.add_stream(p)
2657 self.pg_enable_capture(self.pg_interfaces)
2658 self.pg_start()
2659 self.pg1.get_capture(1)
2660 users = self.vapi.nat44_user_dump()
2661 for user in users:
2662 if user.ip_address == self.pg0.remote_ip4n:
2663 self.assertEqual(user.nsessions,
2664 nat44_config.max_translations_per_user - 1)
2665 self.assertEqual(user.nstaticsessions, 1)
2666
Matus Fabian8bf68e82017-01-12 04:24:35 -08002667 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002668 """ Acquire NAT44 addresses from interface """
Filip Vargaf4749ca2019-04-25 14:55:32 +02002669 self.vapi.nat44_add_del_interface_addr(
2670 is_add=1,
2671 sw_if_index=self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002672
2673 # no address in NAT pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002674 addresses = self.vapi.nat44_address_dump()
2675 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002676
2677 # configure interface address and check NAT address pool
2678 self.pg7.config_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002679 addresses = self.vapi.nat44_address_dump()
2680 self.assertEqual(1, len(addresses))
Filip Vargadd1e3e72019-04-15 18:52:43 +02002681 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002682
2683 # remove interface address and check NAT address pool
2684 self.pg7.unconfig_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002685 addresses = self.vapi.nat44_address_dump()
2686 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002687
Matus Fabian36532bd2017-01-23 23:42:28 -08002688 def test_interface_addr_static_mapping(self):
2689 """ Static mapping with addresses from interface """
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002690 tag = b"testTAG"
Matus Fabian5f224992018-01-25 21:59:16 -08002691
Filip Vargaf4749ca2019-04-25 14:55:32 +02002692 self.vapi.nat44_add_del_interface_addr(
2693 is_add=1,
2694 sw_if_index=self.pg7.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002695 self.nat44_add_static_mapping(
2696 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002697 external_sw_if_index=self.pg7.sw_if_index,
2698 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002699
Matus Fabiane22e5462017-02-14 23:33:43 -08002700 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002701 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002702 self.assertEqual(1, len(static_mappings))
2703 self.assertEqual(self.pg7.sw_if_index,
2704 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002705 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002706
2707 # configure interface address and check static mappings
2708 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002709 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002710 self.assertEqual(2, len(static_mappings))
2711 resolved = False
2712 for sm in static_mappings:
2713 if sm.external_sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002714 self.assertEqual(str(sm.external_ip_address),
2715 self.pg7.local_ip4)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002716 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002717 resolved = True
2718 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002719
2720 # remove interface address and check static mappings
2721 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002722 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002723 self.assertEqual(1, len(static_mappings))
2724 self.assertEqual(self.pg7.sw_if_index,
2725 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002726 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002727
2728 # configure interface address again and check static mappings
2729 self.pg7.config_ip4()
2730 static_mappings = self.vapi.nat44_static_mapping_dump()
2731 self.assertEqual(2, len(static_mappings))
2732 resolved = False
2733 for sm in static_mappings:
2734 if sm.external_sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002735 self.assertEqual(str(sm.external_ip_address),
2736 self.pg7.local_ip4)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002737 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002738 resolved = True
2739 self.assertTrue(resolved)
2740
2741 # remove static mapping
2742 self.nat44_add_static_mapping(
2743 '1.2.3.4',
2744 external_sw_if_index=self.pg7.sw_if_index,
2745 tag=tag,
2746 is_add=0)
2747 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002748 self.assertEqual(0, len(static_mappings))
2749
Matus Fabianab7a8052017-11-28 04:29:41 -08002750 def test_interface_addr_identity_nat(self):
2751 """ Identity NAT with addresses from interface """
2752
2753 port = 53053
Filip Vargaf4749ca2019-04-25 14:55:32 +02002754 self.vapi.nat44_add_del_interface_addr(
2755 is_add=1,
2756 sw_if_index=self.pg7.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002757 self.vapi.nat44_add_del_identity_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +02002758 ip_address=b'0',
Matus Fabianab7a8052017-11-28 04:29:41 -08002759 sw_if_index=self.pg7.sw_if_index,
2760 port=port,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002761 protocol=IP_PROTOS.tcp,
2762 is_add=1)
Matus Fabianab7a8052017-11-28 04:29:41 -08002763
2764 # identity mappings with external interface
2765 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2766 self.assertEqual(1, len(identity_mappings))
2767 self.assertEqual(self.pg7.sw_if_index,
2768 identity_mappings[0].sw_if_index)
2769
2770 # configure interface address and check identity mappings
2771 self.pg7.config_ip4()
2772 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002773 resolved = False
2774 self.assertEqual(2, len(identity_mappings))
2775 for sm in identity_mappings:
2776 if sm.sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002777 self.assertEqual(str(identity_mappings[0].ip_address),
2778 self.pg7.local_ip4)
Matus Fabianea2600a2018-03-28 04:06:26 -07002779 self.assertEqual(port, identity_mappings[0].port)
2780 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2781 resolved = True
2782 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002783
2784 # remove interface address and check identity mappings
2785 self.pg7.unconfig_ip4()
2786 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002787 self.assertEqual(1, len(identity_mappings))
2788 self.assertEqual(self.pg7.sw_if_index,
2789 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002790
Matus Fabianeea28d72017-01-13 04:15:54 -08002791 def test_ipfix_nat44_sess(self):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002792 """ IPFIX logging NAT44 session created/deleted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002793 self.ipfix_domain_id = 10
2794 self.ipfix_src_port = 20202
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002795 collector_port = 30303
Matus Fabian6631e9c2017-05-24 01:52:20 -07002796 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002797 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002798 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002799 self.vapi.nat44_interface_add_del_feature(
2800 sw_if_index=self.pg0.sw_if_index,
2801 flags=flags, is_add=1)
2802 self.vapi.nat44_interface_add_del_feature(
2803 sw_if_index=self.pg1.sw_if_index,
2804 is_add=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002805 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2806 src_address=self.pg3.local_ip4n,
2807 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002808 template_interval=10,
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002809 collector_port=collector_port)
Ole Troane1ade682019-03-04 23:55:43 +01002810 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002811 src_port=self.ipfix_src_port,
2812 enable=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002813
2814 pkts = self.create_stream_in(self.pg0, self.pg1)
2815 self.pg0.add_stream(pkts)
2816 self.pg_enable_capture(self.pg_interfaces)
2817 self.pg_start()
2818 capture = self.pg1.get_capture(len(pkts))
2819 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002820 self.nat44_add_address(self.nat_addr, is_add=0)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04002821 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08002822 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002823 ipfix = IPFIXDecoder()
2824 # first load template
2825 for p in capture:
2826 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002827 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2828 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2829 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002830 self.assertEqual(p[UDP].dport, collector_port)
Matus Fabian6631e9c2017-05-24 01:52:20 -07002831 self.assertEqual(p[IPFIX].observationDomainID,
2832 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002833 if p.haslayer(Template):
2834 ipfix.add_template(p.getlayer(Template))
2835 # verify events in data set
2836 for p in capture:
2837 if p.haslayer(Data):
2838 data = ipfix.decode_data_set(p.getlayer(Set))
2839 self.verify_ipfix_nat44_ses(data)
2840
2841 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002842 """ IPFIX logging NAT addresses exhausted """
Filip Vargadd1e3e72019-04-15 18:52:43 +02002843 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002844 self.vapi.nat44_interface_add_del_feature(
2845 sw_if_index=self.pg0.sw_if_index,
2846 flags=flags, is_add=1)
2847 self.vapi.nat44_interface_add_del_feature(
2848 sw_if_index=self.pg1.sw_if_index,
2849 is_add=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002850 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2851 src_address=self.pg3.local_ip4n,
2852 path_mtu=512,
2853 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002854 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002855 src_port=self.ipfix_src_port,
2856 enable=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002857
2858 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2859 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2860 TCP(sport=3025))
2861 self.pg0.add_stream(p)
2862 self.pg_enable_capture(self.pg_interfaces)
2863 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002864 self.pg1.assert_nothing_captured()
2865 sleep(1)
Vratko Polak9f1b3ff2019-06-25 19:01:34 +02002866 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08002867 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002868 ipfix = IPFIXDecoder()
2869 # first load template
2870 for p in capture:
2871 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002872 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2873 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2874 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2875 self.assertEqual(p[UDP].dport, 4739)
2876 self.assertEqual(p[IPFIX].observationDomainID,
2877 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002878 if p.haslayer(Template):
2879 ipfix.add_template(p.getlayer(Template))
2880 # verify events in data set
2881 for p in capture:
2882 if p.haslayer(Data):
2883 data = ipfix.decode_data_set(p.getlayer(Set))
2884 self.verify_ipfix_addr_exhausted(data)
2885
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002886 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002887 def test_ipfix_max_sessions(self):
2888 """ IPFIX logging maximum session entries exceeded """
2889 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002890 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002891 self.vapi.nat44_interface_add_del_feature(
2892 sw_if_index=self.pg0.sw_if_index,
2893 flags=flags, is_add=1)
2894 self.vapi.nat44_interface_add_del_feature(
2895 sw_if_index=self.pg1.sw_if_index,
2896 is_add=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002897
2898 nat44_config = self.vapi.nat_show_config()
2899 max_sessions = 10 * nat44_config.translation_buckets
2900
2901 pkts = []
2902 for i in range(0, max_sessions):
2903 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2904 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2905 IP(src=src, dst=self.pg1.remote_ip4) /
2906 TCP(sport=1025))
2907 pkts.append(p)
2908 self.pg0.add_stream(pkts)
2909 self.pg_enable_capture(self.pg_interfaces)
2910 self.pg_start()
2911
2912 self.pg1.get_capture(max_sessions)
2913 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2914 src_address=self.pg3.local_ip4n,
2915 path_mtu=512,
2916 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002917 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002918 src_port=self.ipfix_src_port,
2919 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002920
2921 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2922 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2923 TCP(sport=1025))
2924 self.pg0.add_stream(p)
2925 self.pg_enable_capture(self.pg_interfaces)
2926 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002927 self.pg1.assert_nothing_captured()
2928 sleep(1)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04002929 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08002930 capture = self.pg3.get_capture(9)
2931 ipfix = IPFIXDecoder()
2932 # first load template
2933 for p in capture:
2934 self.assertTrue(p.haslayer(IPFIX))
2935 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2936 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2937 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2938 self.assertEqual(p[UDP].dport, 4739)
2939 self.assertEqual(p[IPFIX].observationDomainID,
2940 self.ipfix_domain_id)
2941 if p.haslayer(Template):
2942 ipfix.add_template(p.getlayer(Template))
2943 # verify events in data set
2944 for p in capture:
2945 if p.haslayer(Data):
2946 data = ipfix.decode_data_set(p.getlayer(Set))
2947 self.verify_ipfix_max_sessions(data, max_sessions)
2948
Matus Fabianad1f3e12018-11-28 21:26:34 -08002949 def test_syslog_apmap(self):
2950 """ Test syslog address and port mapping creation and deletion """
Paul Vinciguerrab7658202019-05-17 09:48:15 -04002951 self.vapi.syslog_set_filter(
2952 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
Ole Troanf159f582019-02-28 20:20:47 +01002953 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002954 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002955 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002956 self.vapi.nat44_interface_add_del_feature(
2957 sw_if_index=self.pg0.sw_if_index,
2958 flags=flags, is_add=1)
2959 self.vapi.nat44_interface_add_del_feature(
2960 sw_if_index=self.pg1.sw_if_index,
2961 is_add=1)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002962
2963 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2964 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2965 TCP(sport=self.tcp_port_in, dport=20))
2966 self.pg0.add_stream(p)
2967 self.pg_enable_capture(self.pg_interfaces)
2968 self.pg_start()
2969 capture = self.pg1.get_capture(1)
2970 self.tcp_port_out = capture[0][TCP].sport
2971 capture = self.pg3.get_capture(1)
2972 self.verify_syslog_apmap(capture[0][Raw].load)
2973
2974 self.pg_enable_capture(self.pg_interfaces)
2975 self.pg_start()
2976 self.nat44_add_address(self.nat_addr, is_add=0)
2977 capture = self.pg3.get_capture(1)
2978 self.verify_syslog_apmap(capture[0][Raw].load, False)
2979
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002980 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002981 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002982 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002983 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002984 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002985 self.vapi.nat44_interface_add_del_feature(
2986 sw_if_index=self.pg0.sw_if_index,
2987 flags=flags, is_add=1)
2988 self.vapi.nat44_interface_add_del_feature(
2989 sw_if_index=self.pg1.sw_if_index,
2990 is_add=1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002991 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002992
Matus Fabian2ba92e32017-08-21 07:05:03 -07002993 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002994 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002995 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002996 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2997 self.pg1.add_stream(p)
2998 self.pg_enable_capture(self.pg_interfaces)
2999 self.pg_start()
3000 capture = self.pg1.get_capture(1)
3001 self.assertTrue(capture[0].haslayer(ARP))
3002 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3003
3004 # 1:1 NAT address
3005 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3006 ARP(op=ARP.who_has, pdst=static_addr,
3007 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3008 self.pg1.add_stream(p)
3009 self.pg_enable_capture(self.pg_interfaces)
3010 self.pg_start()
3011 capture = self.pg1.get_capture(1)
3012 self.assertTrue(capture[0].haslayer(ARP))
3013 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3014
Matus Fabian2ba92e32017-08-21 07:05:03 -07003015 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003016 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003017 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003018 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
3019 self.pg2.add_stream(p)
3020 self.pg_enable_capture(self.pg_interfaces)
3021 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003022 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003023
3024 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07003025 self.nat44_add_address(self.nat_addr, is_add=0)
3026 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
3027 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003028
3029 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003030 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003031 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3032 self.pg1.add_stream(p)
3033 self.pg_enable_capture(self.pg_interfaces)
3034 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003035 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003036
3037 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3038 ARP(op=ARP.who_has, pdst=static_addr,
3039 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3040 self.pg1.add_stream(p)
3041 self.pg_enable_capture(self.pg_interfaces)
3042 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003043 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003044
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003045 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003046 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003047
3048 vrf_id1 = 1
3049 vrf_id2 = 2
3050 nat_ip1 = "10.0.0.10"
3051 nat_ip2 = "10.0.0.11"
3052
3053 self.pg0.unconfig_ip4()
3054 self.pg1.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003055 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3056 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003057 self.pg0.set_table_ip4(vrf_id1)
3058 self.pg1.set_table_ip4(vrf_id2)
3059 self.pg0.config_ip4()
3060 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07003061 self.pg0.resolve_arp()
3062 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003063
Matus Fabian2ba92e32017-08-21 07:05:03 -07003064 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
3065 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003066 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003067 self.vapi.nat44_interface_add_del_feature(
3068 sw_if_index=self.pg0.sw_if_index,
3069 flags=flags, is_add=1)
3070 self.vapi.nat44_interface_add_del_feature(
3071 sw_if_index=self.pg1.sw_if_index,
3072 flags=flags, is_add=1)
3073 self.vapi.nat44_interface_add_del_feature(
3074 sw_if_index=self.pg2.sw_if_index,
3075 is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003076
Matus Fabian8008d7c2018-07-09 01:34:20 -07003077 try:
3078 # first VRF
3079 pkts = self.create_stream_in(self.pg0, self.pg2)
3080 self.pg0.add_stream(pkts)
3081 self.pg_enable_capture(self.pg_interfaces)
3082 self.pg_start()
3083 capture = self.pg2.get_capture(len(pkts))
3084 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003085
Matus Fabian8008d7c2018-07-09 01:34:20 -07003086 # second VRF
3087 pkts = self.create_stream_in(self.pg1, self.pg2)
3088 self.pg1.add_stream(pkts)
3089 self.pg_enable_capture(self.pg_interfaces)
3090 self.pg_start()
3091 capture = self.pg2.get_capture(len(pkts))
3092 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003093
Matus Fabian8008d7c2018-07-09 01:34:20 -07003094 finally:
3095 self.pg0.unconfig_ip4()
3096 self.pg1.unconfig_ip4()
3097 self.pg0.set_table_ip4(0)
3098 self.pg1.set_table_ip4(0)
3099 self.pg0.config_ip4()
3100 self.pg1.config_ip4()
3101 self.pg0.resolve_arp()
3102 self.pg1.resolve_arp()
Ole Troan9a475372019-03-05 16:58:24 +01003103 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
3104 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
Neale Ranns15002542017-09-10 04:39:11 -07003105
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003106 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003107 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003108
3109 nat_ip1 = "10.0.0.10"
3110 nat_ip2 = "10.0.0.11"
3111
Matus Fabian2ba92e32017-08-21 07:05:03 -07003112 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08003113 self.nat44_add_address(nat_ip2, vrf_id=99)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003114 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003115 self.vapi.nat44_interface_add_del_feature(
3116 sw_if_index=self.pg0.sw_if_index,
3117 flags=flags, is_add=1)
3118 self.vapi.nat44_interface_add_del_feature(
3119 sw_if_index=self.pg1.sw_if_index,
3120 flags=flags, is_add=1)
3121 self.vapi.nat44_interface_add_del_feature(
3122 sw_if_index=self.pg2.sw_if_index,
3123 is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003124
3125 # first VRF
3126 pkts = self.create_stream_in(self.pg0, self.pg2)
3127 self.pg0.add_stream(pkts)
3128 self.pg_enable_capture(self.pg_interfaces)
3129 self.pg_start()
3130 capture = self.pg2.get_capture(len(pkts))
3131 self.verify_capture_out(capture, nat_ip1)
3132
3133 # second VRF
3134 pkts = self.create_stream_in(self.pg1, self.pg2)
3135 self.pg1.add_stream(pkts)
3136 self.pg_enable_capture(self.pg_interfaces)
3137 self.pg_start()
3138 capture = self.pg2.get_capture(len(pkts))
3139 self.verify_capture_out(capture, nat_ip1)
3140
Neale Ranns097fa662018-05-01 05:17:55 -07003141 def create_routes_and_neigbors(self):
3142 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
3143 [VppRoutePath(self.pg7.remote_ip4,
3144 self.pg7.sw_if_index)])
3145 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
3146 [VppRoutePath(self.pg8.remote_ip4,
3147 self.pg8.sw_if_index)])
3148 r1.add_vpp_config()
3149 r2.add_vpp_config()
3150
3151 n1 = VppNeighbor(self,
3152 self.pg7.sw_if_index,
3153 self.pg7.remote_mac,
3154 self.pg7.remote_ip4,
3155 is_static=1)
3156 n2 = VppNeighbor(self,
3157 self.pg8.sw_if_index,
3158 self.pg8.remote_mac,
3159 self.pg8.remote_ip4,
3160 is_static=1)
3161 n1.add_vpp_config()
3162 n2.add_vpp_config()
3163
Martin Gálik406eb1d2017-05-04 04:35:04 -07003164 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003165 """ NAT44 interfaces without configured IP address """
Neale Ranns097fa662018-05-01 05:17:55 -07003166 self.create_routes_and_neigbors()
Matus Fabian2ba92e32017-08-21 07:05:03 -07003167 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003168 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003169 self.vapi.nat44_interface_add_del_feature(
3170 sw_if_index=self.pg7.sw_if_index,
3171 flags=flags, is_add=1)
3172 self.vapi.nat44_interface_add_del_feature(
3173 sw_if_index=self.pg8.sw_if_index,
3174 is_add=1)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003175
3176 # in2out
3177 pkts = self.create_stream_in(self.pg7, self.pg8)
3178 self.pg7.add_stream(pkts)
3179 self.pg_enable_capture(self.pg_interfaces)
3180 self.pg_start()
3181 capture = self.pg8.get_capture(len(pkts))
3182 self.verify_capture_out(capture)
3183
3184 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003185 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003186 self.pg8.add_stream(pkts)
3187 self.pg_enable_capture(self.pg_interfaces)
3188 self.pg_start()
3189 capture = self.pg7.get_capture(len(pkts))
3190 self.verify_capture_in(capture, self.pg7)
3191
3192 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003193 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003194
Neale Ranns097fa662018-05-01 05:17:55 -07003195 self.create_routes_and_neigbors()
Matus Fabian2ba92e32017-08-21 07:05:03 -07003196 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003197 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003198 self.vapi.nat44_interface_add_del_feature(
3199 sw_if_index=self.pg7.sw_if_index,
3200 flags=flags, is_add=1)
3201 self.vapi.nat44_interface_add_del_feature(
3202 sw_if_index=self.pg8.sw_if_index,
3203 is_add=1)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003204
3205 # out2in
3206 pkts = self.create_stream_out(self.pg8)
3207 self.pg8.add_stream(pkts)
3208 self.pg_enable_capture(self.pg_interfaces)
3209 self.pg_start()
3210 capture = self.pg7.get_capture(len(pkts))
3211 self.verify_capture_in(capture, self.pg7)
3212
3213 # in2out
3214 pkts = self.create_stream_in(self.pg7, self.pg8)
3215 self.pg7.add_stream(pkts)
3216 self.pg_enable_capture(self.pg_interfaces)
3217 self.pg_start()
3218 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003219 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003220
3221 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003222 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003223
3224 self.tcp_port_out = 30606
3225 self.udp_port_out = 30607
3226 self.icmp_id_out = 30608
3227
Neale Ranns097fa662018-05-01 05:17:55 -07003228 self.create_routes_and_neigbors()
Matus Fabian2ba92e32017-08-21 07:05:03 -07003229 self.nat44_add_address(self.nat_addr)
3230 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3231 self.tcp_port_in, self.tcp_port_out,
3232 proto=IP_PROTOS.tcp)
3233 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3234 self.udp_port_in, self.udp_port_out,
3235 proto=IP_PROTOS.udp)
3236 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3237 self.icmp_id_in, self.icmp_id_out,
3238 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003239 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003240 self.vapi.nat44_interface_add_del_feature(
3241 sw_if_index=self.pg7.sw_if_index,
3242 flags=flags, is_add=1)
3243 self.vapi.nat44_interface_add_del_feature(
3244 sw_if_index=self.pg8.sw_if_index,
3245 is_add=1)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003246
3247 # out2in
3248 pkts = self.create_stream_out(self.pg8)
3249 self.pg8.add_stream(pkts)
3250 self.pg_enable_capture(self.pg_interfaces)
3251 self.pg_start()
3252 capture = self.pg7.get_capture(len(pkts))
3253 self.verify_capture_in(capture, self.pg7)
3254
3255 # in2out
3256 pkts = self.create_stream_in(self.pg7, self.pg8)
3257 self.pg7.add_stream(pkts)
3258 self.pg_enable_capture(self.pg_interfaces)
3259 self.pg_start()
3260 capture = self.pg8.get_capture(len(pkts))
3261 self.verify_capture_out(capture)
3262
Matus Fabian328dbc82017-06-19 04:28:04 -07003263 def test_static_unknown_proto(self):
3264 """ 1:1 NAT translate packet with unknown protocol """
3265 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003266 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003267 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003268 self.vapi.nat44_interface_add_del_feature(
3269 sw_if_index=self.pg0.sw_if_index,
3270 flags=flags, is_add=1)
3271 self.vapi.nat44_interface_add_del_feature(
3272 sw_if_index=self.pg1.sw_if_index,
3273 is_add=1)
Matus Fabian328dbc82017-06-19 04:28:04 -07003274
3275 # in2out
3276 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3277 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3278 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003279 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003280 TCP(sport=1234, dport=1234))
3281 self.pg0.add_stream(p)
3282 self.pg_enable_capture(self.pg_interfaces)
3283 self.pg_start()
3284 p = self.pg1.get_capture(1)
3285 packet = p[0]
3286 try:
3287 self.assertEqual(packet[IP].src, nat_ip)
3288 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003289 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003290 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003291 except:
3292 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3293 raise
3294
3295 # out2in
3296 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3297 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3298 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003299 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003300 TCP(sport=1234, dport=1234))
3301 self.pg1.add_stream(p)
3302 self.pg_enable_capture(self.pg_interfaces)
3303 self.pg_start()
3304 p = self.pg0.get_capture(1)
3305 packet = p[0]
3306 try:
3307 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3308 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003309 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003310 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003311 except:
3312 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3313 raise
3314
Matus Fabian7968e6c2017-07-06 05:37:49 -07003315 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003316 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3317
3318 host = self.pg0.remote_hosts[0]
3319 server = self.pg0.remote_hosts[1]
3320
3321 host_nat_ip = "10.0.0.10"
3322 server_nat_ip = "10.0.0.11"
3323
Matus Fabian2ba92e32017-08-21 07:05:03 -07003324 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3325 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003326 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003327 self.vapi.nat44_interface_add_del_feature(
3328 sw_if_index=self.pg0.sw_if_index,
3329 flags=flags, is_add=1)
3330 self.vapi.nat44_interface_add_del_feature(
3331 sw_if_index=self.pg1.sw_if_index,
3332 is_add=1)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003333
3334 # host to server
3335 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3336 IP(src=host.ip4, dst=server_nat_ip) /
3337 GRE() /
3338 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3339 TCP(sport=1234, dport=1234))
3340 self.pg0.add_stream(p)
3341 self.pg_enable_capture(self.pg_interfaces)
3342 self.pg_start()
3343 p = self.pg0.get_capture(1)
3344 packet = p[0]
3345 try:
3346 self.assertEqual(packet[IP].src, host_nat_ip)
3347 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003348 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003349 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003350 except:
3351 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3352 raise
3353
3354 # server to host
3355 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3356 IP(src=server.ip4, dst=host_nat_ip) /
3357 GRE() /
3358 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3359 TCP(sport=1234, dport=1234))
3360 self.pg0.add_stream(p)
3361 self.pg_enable_capture(self.pg_interfaces)
3362 self.pg_start()
3363 p = self.pg0.get_capture(1)
3364 packet = p[0]
3365 try:
3366 self.assertEqual(packet[IP].src, server_nat_ip)
3367 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003368 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003369 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003370 except:
3371 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3372 raise
3373
Matus Fabian93d84c92017-07-19 08:06:01 -07003374 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003375 """ NAT44 interface output feature (in2out postrouting) """
3376 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003377 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003378 self.vapi.nat44_interface_add_del_output_feature(
3379 is_add=1, flags=flags,
3380 sw_if_index=self.pg0.sw_if_index)
3381 self.vapi.nat44_interface_add_del_output_feature(
3382 is_add=1, flags=flags,
3383 sw_if_index=self.pg1.sw_if_index)
3384 self.vapi.nat44_interface_add_del_output_feature(
3385 is_add=1,
3386 sw_if_index=self.pg3.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003387
3388 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003389 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003390 self.pg0.add_stream(pkts)
3391 self.pg_enable_capture(self.pg_interfaces)
3392 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003393 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003394 self.verify_capture_out(capture)
3395
3396 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003397 pkts = self.create_stream_out(self.pg3)
3398 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003399 self.pg_enable_capture(self.pg_interfaces)
3400 self.pg_start()
3401 capture = self.pg0.get_capture(len(pkts))
3402 self.verify_capture_in(capture, self.pg0)
3403
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003404 # from non-NAT interface to NAT inside interface
3405 pkts = self.create_stream_in(self.pg2, self.pg0)
3406 self.pg2.add_stream(pkts)
3407 self.pg_enable_capture(self.pg_interfaces)
3408 self.pg_start()
3409 capture = self.pg0.get_capture(len(pkts))
3410 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3411
Matus Fabian93d84c92017-07-19 08:06:01 -07003412 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003413 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003414 nat_ip_vrf10 = "10.0.0.10"
3415 nat_ip_vrf20 = "10.0.0.20"
3416
Neale Ranns097fa662018-05-01 05:17:55 -07003417 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3418 [VppRoutePath(self.pg3.remote_ip4,
3419 self.pg3.sw_if_index)],
3420 table_id=10)
3421 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3422 [VppRoutePath(self.pg3.remote_ip4,
3423 self.pg3.sw_if_index)],
3424 table_id=20)
3425 r1.add_vpp_config()
3426 r2.add_vpp_config()
Matus Fabian93d84c92017-07-19 08:06:01 -07003427
Matus Fabian2ba92e32017-08-21 07:05:03 -07003428 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3429 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003430 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003431 self.vapi.nat44_interface_add_del_output_feature(
3432 is_add=1, flags=flags,
3433 sw_if_index=self.pg4.sw_if_index)
3434 self.vapi.nat44_interface_add_del_output_feature(
3435 is_add=1, flags=flags,
3436 sw_if_index=self.pg6.sw_if_index)
3437 self.vapi.nat44_interface_add_del_output_feature(
3438 is_add=1,
3439 sw_if_index=self.pg3.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003440
3441 # in2out VRF 10
3442 pkts = self.create_stream_in(self.pg4, self.pg3)
3443 self.pg4.add_stream(pkts)
3444 self.pg_enable_capture(self.pg_interfaces)
3445 self.pg_start()
3446 capture = self.pg3.get_capture(len(pkts))
3447 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3448
3449 # out2in VRF 10
3450 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3451 self.pg3.add_stream(pkts)
3452 self.pg_enable_capture(self.pg_interfaces)
3453 self.pg_start()
3454 capture = self.pg4.get_capture(len(pkts))
3455 self.verify_capture_in(capture, self.pg4)
3456
3457 # in2out VRF 20
3458 pkts = self.create_stream_in(self.pg6, self.pg3)
3459 self.pg6.add_stream(pkts)
3460 self.pg_enable_capture(self.pg_interfaces)
3461 self.pg_start()
3462 capture = self.pg3.get_capture(len(pkts))
3463 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3464
3465 # out2in VRF 20
3466 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3467 self.pg3.add_stream(pkts)
3468 self.pg_enable_capture(self.pg_interfaces)
3469 self.pg_start()
3470 capture = self.pg6.get_capture(len(pkts))
3471 self.verify_capture_in(capture, self.pg6)
3472
Matus Fabian161c59c2017-07-21 03:46:03 -07003473 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003474 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003475 host = self.pg0.remote_hosts[0]
3476 server = self.pg0.remote_hosts[1]
3477 host_in_port = 1234
3478 host_out_port = 0
3479 server_in_port = 5678
3480 server_out_port = 8765
3481
Matus Fabian2ba92e32017-08-21 07:05:03 -07003482 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003483 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003484 self.vapi.nat44_interface_add_del_output_feature(
3485 is_add=1, flags=flags,
3486 sw_if_index=self.pg0.sw_if_index)
3487 self.vapi.nat44_interface_add_del_output_feature(
3488 is_add=1,
3489 sw_if_index=self.pg1.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003490
3491 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003492 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3493 server_in_port, server_out_port,
3494 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003495
3496 # send packet from host to server
3497 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003498 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003499 TCP(sport=host_in_port, dport=server_out_port))
3500 self.pg0.add_stream(p)
3501 self.pg_enable_capture(self.pg_interfaces)
3502 self.pg_start()
3503 capture = self.pg0.get_capture(1)
3504 p = capture[0]
3505 try:
3506 ip = p[IP]
3507 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003508 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003509 self.assertEqual(ip.dst, server.ip4)
3510 self.assertNotEqual(tcp.sport, host_in_port)
3511 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003512 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003513 host_out_port = tcp.sport
3514 except:
3515 self.logger.error(ppp("Unexpected or invalid packet:", p))
3516 raise
3517
3518 # send reply from server to host
3519 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003520 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003521 TCP(sport=server_in_port, dport=host_out_port))
3522 self.pg0.add_stream(p)
3523 self.pg_enable_capture(self.pg_interfaces)
3524 self.pg_start()
3525 capture = self.pg0.get_capture(1)
3526 p = capture[0]
3527 try:
3528 ip = p[IP]
3529 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003530 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003531 self.assertEqual(ip.dst, host.ip4)
3532 self.assertEqual(tcp.sport, server_out_port)
3533 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003534 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003535 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003536 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003537 raise
3538
Matus Fabian36ea2d62017-10-24 04:13:49 -07003539 def test_one_armed_nat44(self):
3540 """ One armed NAT44 """
3541 remote_host = self.pg9.remote_hosts[0]
3542 local_host = self.pg9.remote_hosts[1]
3543 external_port = 0
3544
3545 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003546 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003547 self.vapi.nat44_interface_add_del_feature(
3548 sw_if_index=self.pg9.sw_if_index,
3549 is_add=1)
3550 self.vapi.nat44_interface_add_del_feature(
3551 sw_if_index=self.pg9.sw_if_index,
3552 flags=flags, is_add=1)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003553
3554 # in2out
3555 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3556 IP(src=local_host.ip4, dst=remote_host.ip4) /
3557 TCP(sport=12345, dport=80))
3558 self.pg9.add_stream(p)
3559 self.pg_enable_capture(self.pg_interfaces)
3560 self.pg_start()
3561 capture = self.pg9.get_capture(1)
3562 p = capture[0]
3563 try:
3564 ip = p[IP]
3565 tcp = p[TCP]
3566 self.assertEqual(ip.src, self.nat_addr)
3567 self.assertEqual(ip.dst, remote_host.ip4)
3568 self.assertNotEqual(tcp.sport, 12345)
3569 external_port = tcp.sport
3570 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003571 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003572 except:
3573 self.logger.error(ppp("Unexpected or invalid packet:", p))
3574 raise
3575
3576 # out2in
3577 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3578 IP(src=remote_host.ip4, dst=self.nat_addr) /
3579 TCP(sport=80, dport=external_port))
3580 self.pg9.add_stream(p)
3581 self.pg_enable_capture(self.pg_interfaces)
3582 self.pg_start()
3583 capture = self.pg9.get_capture(1)
3584 p = capture[0]
3585 try:
3586 ip = p[IP]
3587 tcp = p[TCP]
3588 self.assertEqual(ip.src, remote_host.ip4)
3589 self.assertEqual(ip.dst, local_host.ip4)
3590 self.assertEqual(tcp.sport, 80)
3591 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003592 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003593 except:
3594 self.logger.error(ppp("Unexpected or invalid packet:", p))
3595 raise
3596
Ole Troan233e4682019-05-16 15:01:34 +02003597 err = self.statistics.get_err_counter(
3598 '/err/nat44-classify/next in2out')
Matus Fabiana5e73762018-12-14 01:55:16 -08003599 self.assertEqual(err, 1)
Ole Troan233e4682019-05-16 15:01:34 +02003600 err = self.statistics.get_err_counter(
3601 '/err/nat44-classify/next out2in')
Matus Fabiana5e73762018-12-14 01:55:16 -08003602 self.assertEqual(err, 1)
3603
Matus Fabian5ba86f72017-10-26 03:37:38 -07003604 def test_del_session(self):
3605 """ Delete NAT44 session """
3606 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003607 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003608 self.vapi.nat44_interface_add_del_feature(
3609 sw_if_index=self.pg0.sw_if_index,
3610 flags=flags, is_add=1)
3611 self.vapi.nat44_interface_add_del_feature(
3612 sw_if_index=self.pg1.sw_if_index,
3613 is_add=1)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003614
3615 pkts = self.create_stream_in(self.pg0, self.pg1)
3616 self.pg0.add_stream(pkts)
3617 self.pg_enable_capture(self.pg_interfaces)
3618 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003619 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003620
3621 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3622 nsessions = len(sessions)
3623
Filip Vargaf4749ca2019-04-25 14:55:32 +02003624 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3625 port=sessions[0].inside_port,
3626 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003627 flags=self.config_flags.NAT_IS_INSIDE)
Filip Vargaf4749ca2019-04-25 14:55:32 +02003628 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3629 port=sessions[1].outside_port,
3630 protocol=sessions[1].protocol)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003631
3632 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3633 self.assertEqual(nsessions - len(sessions), 2)
3634
Filip Vargaf4749ca2019-04-25 14:55:32 +02003635 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3636 port=sessions[0].inside_port,
3637 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003638 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian68ba8802018-08-08 05:52:47 -07003639
3640 self.verify_no_nat44_user()
3641
Matus Fabianefcd1e92017-08-15 06:59:19 -07003642 def test_set_get_reass(self):
3643 """ NAT44 set/get virtual fragmentation reassembly """
3644 reas_cfg1 = self.vapi.nat_get_reass()
3645
3646 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3647 max_reass=reas_cfg1.ip4_max_reass * 2,
Filip Vargaf4749ca2019-04-25 14:55:32 +02003648 max_frag=reas_cfg1.ip4_max_frag * 2,
3649 drop_frag=0)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003650
3651 reas_cfg2 = self.vapi.nat_get_reass()
3652
3653 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3654 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3655 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3656
Filip Vargaf4749ca2019-04-25 14:55:32 +02003657 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
3658 drop_frag=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003659 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3660
3661 def test_frag_in_order(self):
3662 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003663
Matus Fabianefcd1e92017-08-15 06:59:19 -07003664 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003665 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003666 self.vapi.nat44_interface_add_del_feature(
3667 sw_if_index=self.pg0.sw_if_index,
3668 flags=flags, is_add=1)
3669 self.vapi.nat44_interface_add_del_feature(
3670 sw_if_index=self.pg1.sw_if_index,
3671 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003672
Matus Fabianda41d722018-10-19 04:01:19 -07003673 self.frag_in_order(proto=IP_PROTOS.tcp)
3674 self.frag_in_order(proto=IP_PROTOS.udp)
3675 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003676
Matus Fabian111add72018-11-20 02:19:05 -08003677 def test_frag_forwarding(self):
3678 """ NAT44 forwarding fragment test """
Filip Vargaf4749ca2019-04-25 14:55:32 +02003679 self.vapi.nat44_add_del_interface_addr(
3680 is_add=1,
3681 sw_if_index=self.pg1.sw_if_index)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003682 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003683 self.vapi.nat44_interface_add_del_feature(
3684 sw_if_index=self.pg0.sw_if_index,
3685 flags=flags, is_add=1)
3686 self.vapi.nat44_interface_add_del_feature(
3687 sw_if_index=self.pg1.sw_if_index,
3688 is_add=1)
3689 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian111add72018-11-20 02:19:05 -08003690
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003691 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Matus Fabian111add72018-11-20 02:19:05 -08003692 pkts = self.create_stream_frag(self.pg1,
3693 self.pg0.remote_ip4,
3694 4789,
3695 4789,
3696 data,
3697 proto=IP_PROTOS.udp)
3698 self.pg1.add_stream(pkts)
3699 self.pg_enable_capture(self.pg_interfaces)
3700 self.pg_start()
3701 frags = self.pg0.get_capture(len(pkts))
3702 p = self.reass_frags_and_verify(frags,
3703 self.pg1.remote_ip4,
3704 self.pg0.remote_ip4)
3705 self.assertEqual(p[UDP].sport, 4789)
3706 self.assertEqual(p[UDP].dport, 4789)
3707 self.assertEqual(data, p[Raw].load)
3708
Matus Fabianefcd1e92017-08-15 06:59:19 -07003709 def test_reass_hairpinning(self):
3710 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003711
Matus Fabianda41d722018-10-19 04:01:19 -07003712 self.server = self.pg0.remote_hosts[1]
3713 self.host_in_port = random.randint(1025, 65535)
3714 self.server_in_port = random.randint(1025, 65535)
3715 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003716
3717 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003718 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003719 self.vapi.nat44_interface_add_del_feature(
3720 sw_if_index=self.pg0.sw_if_index,
3721 flags=flags, is_add=1)
3722 self.vapi.nat44_interface_add_del_feature(
3723 sw_if_index=self.pg1.sw_if_index,
3724 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003725 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003726 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3727 self.server_in_port,
3728 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003729 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003730 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3731 self.server_in_port,
3732 self.server_out_port,
3733 proto=IP_PROTOS.udp)
3734 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003735
Matus Fabianda41d722018-10-19 04:01:19 -07003736 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3737 self.reass_hairpinning(proto=IP_PROTOS.udp)
3738 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003739
3740 def test_frag_out_of_order(self):
3741 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003742
Matus Fabianefcd1e92017-08-15 06:59:19 -07003743 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003744 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003745 self.vapi.nat44_interface_add_del_feature(
3746 sw_if_index=self.pg0.sw_if_index,
3747 flags=flags, is_add=1)
3748 self.vapi.nat44_interface_add_del_feature(
3749 sw_if_index=self.pg1.sw_if_index,
3750 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003751
Matus Fabianda41d722018-10-19 04:01:19 -07003752 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3753 self.frag_out_of_order(proto=IP_PROTOS.udp)
3754 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003755
Matus Fabian27697102017-11-09 01:43:47 -08003756 def test_port_restricted(self):
3757 """ Port restricted NAT44 (MAP-E CE) """
3758 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003759 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003760 self.vapi.nat44_interface_add_del_feature(
3761 sw_if_index=self.pg0.sw_if_index,
3762 flags=flags, is_add=1)
3763 self.vapi.nat44_interface_add_del_feature(
3764 sw_if_index=self.pg1.sw_if_index,
3765 is_add=1)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003766 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3767 psid_offset=6,
3768 psid_length=6,
3769 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003770
3771 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3772 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3773 TCP(sport=4567, dport=22))
3774 self.pg0.add_stream(p)
3775 self.pg_enable_capture(self.pg_interfaces)
3776 self.pg_start()
3777 capture = self.pg1.get_capture(1)
3778 p = capture[0]
3779 try:
3780 ip = p[IP]
3781 tcp = p[TCP]
3782 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3783 self.assertEqual(ip.src, self.nat_addr)
3784 self.assertEqual(tcp.dport, 22)
3785 self.assertNotEqual(tcp.sport, 4567)
3786 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003787 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003788 except:
3789 self.logger.error(ppp("Unexpected or invalid packet:", p))
3790 raise
3791
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003792 def test_port_range(self):
3793 """ External address port range """
3794 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003795 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003796 self.vapi.nat44_interface_add_del_feature(
3797 sw_if_index=self.pg0.sw_if_index,
3798 flags=flags, is_add=1)
3799 self.vapi.nat44_interface_add_del_feature(
3800 sw_if_index=self.pg1.sw_if_index,
3801 is_add=1)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003802 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3803 start_port=1025,
3804 end_port=1027)
3805
3806 pkts = []
3807 for port in range(0, 5):
3808 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3809 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3810 TCP(sport=1125 + port))
3811 pkts.append(p)
3812 self.pg0.add_stream(pkts)
3813 self.pg_enable_capture(self.pg_interfaces)
3814 self.pg_start()
3815 capture = self.pg1.get_capture(3)
3816 for p in capture:
3817 tcp = p[TCP]
3818 self.assertGreaterEqual(tcp.sport, 1025)
3819 self.assertLessEqual(tcp.sport, 1027)
3820
Matus Fabiana6110b62018-06-13 05:39:07 -07003821 def test_ipfix_max_frags(self):
3822 """ IPFIX logging maximum fragments pending reassembly exceeded """
3823 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003824 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003825 self.vapi.nat44_interface_add_del_feature(
3826 sw_if_index=self.pg0.sw_if_index,
3827 flags=flags, is_add=1)
3828 self.vapi.nat44_interface_add_del_feature(
3829 sw_if_index=self.pg1.sw_if_index,
3830 is_add=1)
3831 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
3832 drop_frag=0)
Matus Fabiana6110b62018-06-13 05:39:07 -07003833 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3834 src_address=self.pg3.local_ip4n,
3835 path_mtu=512,
3836 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01003837 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02003838 src_port=self.ipfix_src_port,
3839 enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003840
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003841 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabiana6110b62018-06-13 05:39:07 -07003842 self.tcp_port_in = random.randint(1025, 65535)
3843 pkts = self.create_stream_frag(self.pg0,
3844 self.pg1.remote_ip4,
3845 self.tcp_port_in,
3846 20,
3847 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003848 pkts.reverse()
3849 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003850 self.pg_enable_capture(self.pg_interfaces)
3851 self.pg_start()
3852 self.pg1.assert_nothing_captured()
3853 sleep(1)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04003854 self.vapi.ipfix_flush()
Matus Fabiana6110b62018-06-13 05:39:07 -07003855 capture = self.pg3.get_capture(9)
3856 ipfix = IPFIXDecoder()
3857 # first load template
3858 for p in capture:
3859 self.assertTrue(p.haslayer(IPFIX))
3860 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3861 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3862 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3863 self.assertEqual(p[UDP].dport, 4739)
3864 self.assertEqual(p[IPFIX].observationDomainID,
3865 self.ipfix_domain_id)
3866 if p.haslayer(Template):
3867 ipfix.add_template(p.getlayer(Template))
3868 # verify events in data set
3869 for p in capture:
3870 if p.haslayer(Data):
3871 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003872 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003873 self.pg0.remote_ip4n)
3874
Matus Fabian8008d7c2018-07-09 01:34:20 -07003875 def test_multiple_outside_vrf(self):
3876 """ Multiple outside VRF """
3877 vrf_id1 = 1
3878 vrf_id2 = 2
3879
3880 self.pg1.unconfig_ip4()
3881 self.pg2.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003882 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3883 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003884 self.pg1.set_table_ip4(vrf_id1)
3885 self.pg2.set_table_ip4(vrf_id2)
3886 self.pg1.config_ip4()
3887 self.pg2.config_ip4()
3888 self.pg1.resolve_arp()
3889 self.pg2.resolve_arp()
3890
3891 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003892 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003893 self.vapi.nat44_interface_add_del_feature(
3894 sw_if_index=self.pg0.sw_if_index,
3895 flags=flags, is_add=1)
3896 self.vapi.nat44_interface_add_del_feature(
3897 sw_if_index=self.pg1.sw_if_index,
3898 is_add=1)
3899 self.vapi.nat44_interface_add_del_feature(
3900 sw_if_index=self.pg2.sw_if_index,
3901 is_add=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003902
3903 try:
3904 # first VRF
3905 pkts = self.create_stream_in(self.pg0, self.pg1)
3906 self.pg0.add_stream(pkts)
3907 self.pg_enable_capture(self.pg_interfaces)
3908 self.pg_start()
3909 capture = self.pg1.get_capture(len(pkts))
3910 self.verify_capture_out(capture, self.nat_addr)
3911
3912 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3913 self.pg1.add_stream(pkts)
3914 self.pg_enable_capture(self.pg_interfaces)
3915 self.pg_start()
3916 capture = self.pg0.get_capture(len(pkts))
3917 self.verify_capture_in(capture, self.pg0)
3918
3919 self.tcp_port_in = 60303
3920 self.udp_port_in = 60304
3921 self.icmp_id_in = 60305
3922
3923 # second VRF
3924 pkts = self.create_stream_in(self.pg0, self.pg2)
3925 self.pg0.add_stream(pkts)
3926 self.pg_enable_capture(self.pg_interfaces)
3927 self.pg_start()
3928 capture = self.pg2.get_capture(len(pkts))
3929 self.verify_capture_out(capture, self.nat_addr)
3930
3931 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3932 self.pg2.add_stream(pkts)
3933 self.pg_enable_capture(self.pg_interfaces)
3934 self.pg_start()
3935 capture = self.pg0.get_capture(len(pkts))
3936 self.verify_capture_in(capture, self.pg0)
3937
3938 finally:
Filip Varga04bb6422019-05-04 16:02:53 +02003939 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003940 self.pg1.unconfig_ip4()
3941 self.pg2.unconfig_ip4()
3942 self.pg1.set_table_ip4(0)
3943 self.pg2.set_table_ip4(0)
3944 self.pg1.config_ip4()
3945 self.pg2.config_ip4()
3946 self.pg1.resolve_arp()
3947 self.pg2.resolve_arp()
3948
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08003949 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07003950 def test_session_timeout(self):
3951 """ NAT44 session timeouts """
3952 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003953 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003954 self.vapi.nat44_interface_add_del_feature(
3955 sw_if_index=self.pg0.sw_if_index,
3956 flags=flags, is_add=1)
3957 self.vapi.nat44_interface_add_del_feature(
3958 sw_if_index=self.pg1.sw_if_index,
3959 is_add=1)
3960 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3961 tcp_transitory=240, icmp=60)
Matus Fabian878c6462018-08-23 00:33:35 -07003962
3963 max_sessions = 1000
3964 pkts = []
3965 for i in range(0, max_sessions):
3966 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3967 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3968 IP(src=src, dst=self.pg1.remote_ip4) /
3969 UDP(sport=1025, dport=53))
3970 pkts.append(p)
3971 self.pg0.add_stream(pkts)
3972 self.pg_enable_capture(self.pg_interfaces)
3973 self.pg_start()
3974 self.pg1.get_capture(max_sessions)
3975
3976 sleep(6)
3977
3978 pkts = []
3979 for i in range(0, max_sessions):
3980 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3981 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3982 IP(src=src, dst=self.pg1.remote_ip4) /
3983 UDP(sport=1026, dport=53))
3984 pkts.append(p)
3985 self.pg0.add_stream(pkts)
3986 self.pg_enable_capture(self.pg_interfaces)
3987 self.pg_start()
3988 self.pg1.get_capture(max_sessions)
3989
3990 nsessions = 0
3991 users = self.vapi.nat44_user_dump()
3992 for user in users:
3993 nsessions = nsessions + user.nsessions
3994 self.assertLess(nsessions, 2 * max_sessions)
3995
Matus Fabianbb4e0222018-09-13 02:36:25 -07003996 def test_mss_clamping(self):
3997 """ TCP MSS clamping """
3998 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003999 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004000 self.vapi.nat44_interface_add_del_feature(
4001 sw_if_index=self.pg0.sw_if_index,
4002 flags=flags, is_add=1)
4003 self.vapi.nat44_interface_add_del_feature(
4004 sw_if_index=self.pg1.sw_if_index,
4005 is_add=1)
Matus Fabianbb4e0222018-09-13 02:36:25 -07004006
4007 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4008 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4009 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4010 flags="S", options=[('MSS', 1400)]))
4011
4012 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
4013 self.pg0.add_stream(p)
4014 self.pg_enable_capture(self.pg_interfaces)
4015 self.pg_start()
4016 capture = self.pg1.get_capture(1)
4017 # Negotiated MSS value greater than configured - changed
4018 self.verify_mss_value(capture[0], 1000)
4019
Filip Vargaf4749ca2019-04-25 14:55:32 +02004020 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
Matus Fabianbb4e0222018-09-13 02:36:25 -07004021 self.pg0.add_stream(p)
4022 self.pg_enable_capture(self.pg_interfaces)
4023 self.pg_start()
4024 capture = self.pg1.get_capture(1)
4025 # MSS clamping disabled - negotiated MSS unchanged
4026 self.verify_mss_value(capture[0], 1400)
4027
4028 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
4029 self.pg0.add_stream(p)
4030 self.pg_enable_capture(self.pg_interfaces)
4031 self.pg_start()
4032 capture = self.pg1.get_capture(1)
4033 # Negotiated MSS value smaller than configured - unchanged
4034 self.verify_mss_value(capture[0], 1400)
4035
Matus Fabian34931eb2019-02-26 09:05:23 -08004036 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4037 def test_ha_send(self):
4038 """ Send HA session synchronization events (active) """
4039 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004040 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004041 self.vapi.nat44_interface_add_del_feature(
4042 sw_if_index=self.pg0.sw_if_index,
4043 flags=flags, is_add=1)
4044 self.vapi.nat44_interface_add_del_feature(
4045 sw_if_index=self.pg1.sw_if_index,
4046 is_add=1)
4047 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4048 port=12345,
4049 path_mtu=512)
4050 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
4051 port=12346, session_refresh_interval=10)
Matus Fabian34931eb2019-02-26 09:05:23 -08004052 bind_layers(UDP, HANATStateSync, sport=12345)
4053
4054 # create sessions
4055 pkts = self.create_stream_in(self.pg0, self.pg1)
4056 self.pg0.add_stream(pkts)
4057 self.pg_enable_capture(self.pg_interfaces)
4058 self.pg_start()
4059 capture = self.pg1.get_capture(len(pkts))
4060 self.verify_capture_out(capture)
4061 # active send HA events
4062 self.vapi.nat_ha_flush()
4063 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
4064 self.assertEqual(stats[0][0], 3)
4065 capture = self.pg3.get_capture(1)
4066 p = capture[0]
4067 self.assert_packet_checksums_valid(p)
4068 try:
4069 ip = p[IP]
4070 udp = p[UDP]
4071 hanat = p[HANATStateSync]
4072 except IndexError:
4073 self.logger.error(ppp("Invalid packet:", p))
4074 raise
4075 else:
4076 self.assertEqual(ip.src, self.pg3.local_ip4)
4077 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4078 self.assertEqual(udp.sport, 12345)
4079 self.assertEqual(udp.dport, 12346)
4080 self.assertEqual(hanat.version, 1)
4081 self.assertEqual(hanat.thread_index, 0)
4082 self.assertEqual(hanat.count, 3)
4083 seq = hanat.sequence_number
4084 for event in hanat.events:
4085 self.assertEqual(event.event_type, 1)
4086 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
4087 self.assertEqual(event.out_addr, self.nat_addr)
4088 self.assertEqual(event.fib_index, 0)
4089
4090 # ACK received events
4091 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4092 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4093 UDP(sport=12346, dport=12345) /
4094 HANATStateSync(sequence_number=seq, flags='ACK'))
4095 self.pg3.add_stream(ack)
4096 self.pg_start()
4097 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4098 self.assertEqual(stats[0][0], 1)
4099
4100 # delete one session
4101 self.pg_enable_capture(self.pg_interfaces)
Filip Vargaf4749ca2019-04-25 14:55:32 +02004102 self.vapi.nat44_del_session(address=self.pg0.remote_ip4n,
4103 port=self.tcp_port_in,
4104 protocol=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004105 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian34931eb2019-02-26 09:05:23 -08004106 self.vapi.nat_ha_flush()
4107 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
4108 self.assertEqual(stats[0][0], 1)
4109 capture = self.pg3.get_capture(1)
4110 p = capture[0]
4111 try:
4112 hanat = p[HANATStateSync]
4113 except IndexError:
4114 self.logger.error(ppp("Invalid packet:", p))
4115 raise
4116 else:
4117 self.assertGreater(hanat.sequence_number, seq)
4118
4119 # do not send ACK, active retry send HA event again
4120 self.pg_enable_capture(self.pg_interfaces)
4121 sleep(12)
4122 stats = self.statistics.get_counter('/nat44/ha/retry-count')
4123 self.assertEqual(stats[0][0], 3)
4124 stats = self.statistics.get_counter('/nat44/ha/missed-count')
4125 self.assertEqual(stats[0][0], 1)
4126 capture = self.pg3.get_capture(3)
4127 for packet in capture:
4128 self.assertEqual(packet, p)
4129
4130 # session counters refresh
4131 pkts = self.create_stream_out(self.pg1)
4132 self.pg1.add_stream(pkts)
4133 self.pg_enable_capture(self.pg_interfaces)
4134 self.pg_start()
4135 self.pg0.get_capture(2)
4136 self.vapi.nat_ha_flush()
4137 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
4138 self.assertEqual(stats[0][0], 2)
4139 capture = self.pg3.get_capture(1)
4140 p = capture[0]
4141 self.assert_packet_checksums_valid(p)
4142 try:
4143 ip = p[IP]
4144 udp = p[UDP]
4145 hanat = p[HANATStateSync]
4146 except IndexError:
4147 self.logger.error(ppp("Invalid packet:", p))
4148 raise
4149 else:
4150 self.assertEqual(ip.src, self.pg3.local_ip4)
4151 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4152 self.assertEqual(udp.sport, 12345)
4153 self.assertEqual(udp.dport, 12346)
4154 self.assertEqual(hanat.version, 1)
4155 self.assertEqual(hanat.count, 2)
4156 seq = hanat.sequence_number
4157 for event in hanat.events:
4158 self.assertEqual(event.event_type, 3)
4159 self.assertEqual(event.out_addr, self.nat_addr)
4160 self.assertEqual(event.fib_index, 0)
4161 self.assertEqual(event.total_pkts, 2)
4162 self.assertGreater(event.total_bytes, 0)
4163
4164 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4165 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4166 UDP(sport=12346, dport=12345) /
4167 HANATStateSync(sequence_number=seq, flags='ACK'))
4168 self.pg3.add_stream(ack)
4169 self.pg_start()
4170 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4171 self.assertEqual(stats[0][0], 2)
4172
4173 def test_ha_recv(self):
4174 """ Receive HA session synchronization events (passive) """
4175 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004176 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004177 self.vapi.nat44_interface_add_del_feature(
4178 sw_if_index=self.pg0.sw_if_index,
4179 flags=flags, is_add=1)
4180 self.vapi.nat44_interface_add_del_feature(
4181 sw_if_index=self.pg1.sw_if_index,
4182 is_add=1)
4183 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4184 port=12345,
4185 path_mtu=512)
Matus Fabian34931eb2019-02-26 09:05:23 -08004186 bind_layers(UDP, HANATStateSync, sport=12345)
4187
4188 self.tcp_port_out = random.randint(1025, 65535)
4189 self.udp_port_out = random.randint(1025, 65535)
4190
4191 # send HA session add events to failover/passive
4192 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4193 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4194 UDP(sport=12346, dport=12345) /
4195 HANATStateSync(sequence_number=1, events=[
4196 Event(event_type='add', protocol='tcp',
4197 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4198 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4199 eh_addr=self.pg1.remote_ip4,
4200 ehn_addr=self.pg1.remote_ip4,
4201 eh_port=self.tcp_external_port,
4202 ehn_port=self.tcp_external_port, fib_index=0),
4203 Event(event_type='add', protocol='udp',
4204 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4205 in_port=self.udp_port_in, out_port=self.udp_port_out,
4206 eh_addr=self.pg1.remote_ip4,
4207 ehn_addr=self.pg1.remote_ip4,
4208 eh_port=self.udp_external_port,
4209 ehn_port=self.udp_external_port, fib_index=0)]))
4210
4211 self.pg3.add_stream(p)
4212 self.pg_enable_capture(self.pg_interfaces)
4213 self.pg_start()
4214 # receive ACK
4215 capture = self.pg3.get_capture(1)
4216 p = capture[0]
4217 try:
4218 hanat = p[HANATStateSync]
4219 except IndexError:
4220 self.logger.error(ppp("Invalid packet:", p))
4221 raise
4222 else:
4223 self.assertEqual(hanat.sequence_number, 1)
4224 self.assertEqual(hanat.flags, 'ACK')
4225 self.assertEqual(hanat.version, 1)
4226 self.assertEqual(hanat.thread_index, 0)
4227 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4228 self.assertEqual(stats[0][0], 1)
4229 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4230 self.assertEqual(stats[0][0], 2)
4231 users = self.statistics.get_counter('/nat44/total-users')
4232 self.assertEqual(users[0][0], 1)
4233 sessions = self.statistics.get_counter('/nat44/total-sessions')
4234 self.assertEqual(sessions[0][0], 2)
4235 users = self.vapi.nat44_user_dump()
4236 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004237 self.assertEqual(str(users[0].ip_address),
4238 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004239 # there should be 2 sessions created by HA
4240 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4241 users[0].vrf_id)
4242 self.assertEqual(len(sessions), 2)
4243 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02004244 self.assertEqual(str(session.inside_ip_address),
4245 self.pg0.remote_ip4)
4246 self.assertEqual(str(session.outside_ip_address),
4247 self.nat_addr)
Matus Fabian34931eb2019-02-26 09:05:23 -08004248 self.assertIn(session.inside_port,
4249 [self.tcp_port_in, self.udp_port_in])
4250 self.assertIn(session.outside_port,
4251 [self.tcp_port_out, self.udp_port_out])
4252 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4253
4254 # send HA session delete event to failover/passive
4255 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4256 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4257 UDP(sport=12346, dport=12345) /
4258 HANATStateSync(sequence_number=2, events=[
4259 Event(event_type='del', protocol='udp',
4260 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4261 in_port=self.udp_port_in, out_port=self.udp_port_out,
4262 eh_addr=self.pg1.remote_ip4,
4263 ehn_addr=self.pg1.remote_ip4,
4264 eh_port=self.udp_external_port,
4265 ehn_port=self.udp_external_port, fib_index=0)]))
4266
4267 self.pg3.add_stream(p)
4268 self.pg_enable_capture(self.pg_interfaces)
4269 self.pg_start()
4270 # receive ACK
4271 capture = self.pg3.get_capture(1)
4272 p = capture[0]
4273 try:
4274 hanat = p[HANATStateSync]
4275 except IndexError:
4276 self.logger.error(ppp("Invalid packet:", p))
4277 raise
4278 else:
4279 self.assertEqual(hanat.sequence_number, 2)
4280 self.assertEqual(hanat.flags, 'ACK')
4281 self.assertEqual(hanat.version, 1)
4282 users = self.vapi.nat44_user_dump()
4283 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004284 self.assertEqual(str(users[0].ip_address),
4285 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004286 # now we should have only 1 session, 1 deleted by HA
4287 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4288 users[0].vrf_id)
4289 self.assertEqual(len(sessions), 1)
4290 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4291 self.assertEqual(stats[0][0], 1)
4292
Ole Troan233e4682019-05-16 15:01:34 +02004293 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
Matus Fabian34931eb2019-02-26 09:05:23 -08004294 self.assertEqual(stats, 2)
4295
4296 # send HA session refresh event to failover/passive
4297 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4298 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4299 UDP(sport=12346, dport=12345) /
4300 HANATStateSync(sequence_number=3, events=[
4301 Event(event_type='refresh', protocol='tcp',
4302 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4303 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4304 eh_addr=self.pg1.remote_ip4,
4305 ehn_addr=self.pg1.remote_ip4,
4306 eh_port=self.tcp_external_port,
4307 ehn_port=self.tcp_external_port, fib_index=0,
4308 total_bytes=1024, total_pkts=2)]))
4309 self.pg3.add_stream(p)
4310 self.pg_enable_capture(self.pg_interfaces)
4311 self.pg_start()
4312 # receive ACK
4313 capture = self.pg3.get_capture(1)
4314 p = capture[0]
4315 try:
4316 hanat = p[HANATStateSync]
4317 except IndexError:
4318 self.logger.error(ppp("Invalid packet:", p))
4319 raise
4320 else:
4321 self.assertEqual(hanat.sequence_number, 3)
4322 self.assertEqual(hanat.flags, 'ACK')
4323 self.assertEqual(hanat.version, 1)
4324 users = self.vapi.nat44_user_dump()
4325 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004326 self.assertEqual(str(users[0].ip_address),
4327 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004328 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4329 users[0].vrf_id)
4330 self.assertEqual(len(sessions), 1)
4331 session = sessions[0]
4332 self.assertEqual(session.total_bytes, 1024)
4333 self.assertEqual(session.total_pkts, 2)
4334 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4335 self.assertEqual(stats[0][0], 1)
4336
Ole Troan233e4682019-05-16 15:01:34 +02004337 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
Matus Fabian34931eb2019-02-26 09:05:23 -08004338 self.assertEqual(stats, 3)
4339
4340 # send packet to test session created by HA
4341 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4342 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4343 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4344 self.pg1.add_stream(p)
4345 self.pg_enable_capture(self.pg_interfaces)
4346 self.pg_start()
4347 capture = self.pg0.get_capture(1)
4348 p = capture[0]
4349 try:
4350 ip = p[IP]
4351 tcp = p[TCP]
4352 except IndexError:
4353 self.logger.error(ppp("Invalid packet:", p))
4354 raise
4355 else:
4356 self.assertEqual(ip.src, self.pg1.remote_ip4)
4357 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4358 self.assertEqual(tcp.sport, self.tcp_external_port)
4359 self.assertEqual(tcp.dport, self.tcp_port_in)
4360
Matus Fabiana6110b62018-06-13 05:39:07 -07004361 def tearDown(self):
4362 super(TestNAT44, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07004363 self.clear_nat44()
4364 self.vapi.cli("clear logging")
4365
4366 def show_commands_at_teardown(self):
4367 self.logger.info(self.vapi.cli("show nat44 addresses"))
4368 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4369 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4370 self.logger.info(self.vapi.cli("show nat44 interface address"))
4371 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4372 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4373 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4374 self.logger.info(self.vapi.cli("show nat timeouts"))
4375 self.logger.info(
4376 self.vapi.cli("show nat addr-port-assignment-alg"))
4377 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004378
4379
4380class TestNAT44EndpointDependent(MethodHolder):
4381 """ Endpoint-Dependent mapping and filtering test cases """
4382
4383 @classmethod
4384 def setUpConstants(cls):
4385 super(TestNAT44EndpointDependent, cls).setUpConstants()
4386 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4387
4388 @classmethod
4389 def setUpClass(cls):
4390 super(TestNAT44EndpointDependent, cls).setUpClass()
4391 cls.vapi.cli("set log class nat level debug")
4392 try:
4393 cls.tcp_port_in = 6303
4394 cls.tcp_port_out = 6303
4395 cls.udp_port_in = 6304
4396 cls.udp_port_out = 6304
4397 cls.icmp_id_in = 6305
4398 cls.icmp_id_out = 6305
4399 cls.nat_addr = '10.0.0.3'
Matus Fabiana6110b62018-06-13 05:39:07 -07004400 cls.ipfix_src_port = 4739
4401 cls.ipfix_domain_id = 1
4402 cls.tcp_external_port = 80
4403
Matus Fabian8008d7c2018-07-09 01:34:20 -07004404 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004405 cls.interfaces = list(cls.pg_interfaces[0:3])
4406
4407 for i in cls.interfaces:
4408 i.admin_up()
4409 i.config_ip4()
4410 i.resolve_arp()
4411
4412 cls.pg0.generate_remote_hosts(3)
4413 cls.pg0.configure_ipv4_neighbors()
4414
4415 cls.pg3.admin_up()
4416
4417 cls.pg4.generate_remote_hosts(2)
4418 cls.pg4.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004419 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01004420 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004421 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4422 address_length=24)
Matus Fabiana6110b62018-06-13 05:39:07 -07004423 cls.pg4.admin_up()
4424 cls.pg4.resolve_arp()
4425 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4426 cls.pg4.resolve_arp()
4427
Matus Fabian8008d7c2018-07-09 01:34:20 -07004428 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004429 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004430
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004431 cls.pg5._local_ip4 = "10.1.1.1"
4432 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4433 cls.pg5.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004434 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4435 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4436 socket.AF_INET, cls.pg5.remote_ip4)
4437 cls.pg5.set_table_ip4(1)
4438 cls.pg5.config_ip4()
4439 cls.pg5.admin_up()
Neale Ranns097fa662018-05-01 05:17:55 -07004440 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4441 [VppRoutePath("0.0.0.0",
4442 cls.pg5.sw_if_index)],
4443 table_id=1,
4444 register=False)
4445 r1.add_vpp_config()
Matus Fabian8008d7c2018-07-09 01:34:20 -07004446
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004447 cls.pg6._local_ip4 = "10.1.2.1"
4448 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4449 cls.pg6.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004450 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4451 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4452 socket.AF_INET, cls.pg6.remote_ip4)
4453 cls.pg6.set_table_ip4(1)
4454 cls.pg6.config_ip4()
4455 cls.pg6.admin_up()
Matus Fabian8008d7c2018-07-09 01:34:20 -07004456
Neale Ranns097fa662018-05-01 05:17:55 -07004457 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4458 [VppRoutePath("0.0.0.0",
4459 cls.pg6.sw_if_index)],
4460 table_id=1,
4461 register=False)
4462 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4463 [VppRoutePath("0.0.0.0",
4464 0xffffffff,
4465 nh_table_id=1)],
4466 table_id=0,
4467 register=False)
4468 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4469 [VppRoutePath("0.0.0.0", 0xffffffff,
4470 nh_table_id=0)],
4471 table_id=1,
4472 register=False)
4473 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4474 [VppRoutePath(cls.pg1.local_ip4,
4475 cls.pg1.sw_if_index)],
4476 register=False)
4477 r2.add_vpp_config()
4478 r3.add_vpp_config()
4479 r4.add_vpp_config()
4480 r5.add_vpp_config()
Matus Fabian8008d7c2018-07-09 01:34:20 -07004481
4482 cls.pg5.resolve_arp()
4483 cls.pg6.resolve_arp()
4484
Matus Fabiana6110b62018-06-13 05:39:07 -07004485 except Exception:
4486 super(TestNAT44EndpointDependent, cls).tearDownClass()
4487 raise
4488
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07004489 @classmethod
4490 def tearDownClass(cls):
4491 super(TestNAT44EndpointDependent, cls).tearDownClass()
4492
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004493 def test_frag_in_order(self):
4494 """ NAT44 translate fragments arriving in order """
4495 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004496 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004497 self.vapi.nat44_interface_add_del_feature(
4498 sw_if_index=self.pg0.sw_if_index,
4499 flags=flags, is_add=1)
4500 self.vapi.nat44_interface_add_del_feature(
4501 sw_if_index=self.pg1.sw_if_index,
4502 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004503 self.frag_in_order(proto=IP_PROTOS.tcp)
4504 self.frag_in_order(proto=IP_PROTOS.udp)
4505 self.frag_in_order(proto=IP_PROTOS.icmp)
4506
4507 def test_frag_in_order_dont_translate(self):
4508 """ NAT44 don't translate fragments arriving in order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004509 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004510 self.vapi.nat44_interface_add_del_feature(
4511 sw_if_index=self.pg0.sw_if_index,
4512 flags=flags, is_add=1)
4513 self.vapi.nat44_interface_add_del_feature(
4514 sw_if_index=self.pg1.sw_if_index,
4515 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004516 self.vapi.nat44_forwarding_enable_disable(enable=True)
4517 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4518
4519 def test_frag_out_of_order(self):
4520 """ NAT44 translate fragments arriving out of order """
4521 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004522 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004523 self.vapi.nat44_interface_add_del_feature(
4524 sw_if_index=self.pg0.sw_if_index,
4525 flags=flags, is_add=1)
4526 self.vapi.nat44_interface_add_del_feature(
4527 sw_if_index=self.pg1.sw_if_index,
4528 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004529 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4530 self.frag_out_of_order(proto=IP_PROTOS.udp)
4531 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4532
4533 def test_frag_out_of_order_dont_translate(self):
4534 """ NAT44 don't translate fragments arriving out of order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004535 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004536 self.vapi.nat44_interface_add_del_feature(
4537 sw_if_index=self.pg0.sw_if_index,
4538 flags=flags, is_add=1)
4539 self.vapi.nat44_interface_add_del_feature(
4540 sw_if_index=self.pg1.sw_if_index,
4541 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004542 self.vapi.nat44_forwarding_enable_disable(enable=True)
4543 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4544
4545 def test_frag_in_order_in_plus_out(self):
4546 """ in+out interface fragments in order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004547 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004548 self.vapi.nat44_interface_add_del_feature(
4549 sw_if_index=self.pg0.sw_if_index,
4550 is_add=1)
4551 self.vapi.nat44_interface_add_del_feature(
4552 sw_if_index=self.pg0.sw_if_index,
4553 flags=flags, is_add=1)
4554 self.vapi.nat44_interface_add_del_feature(
4555 sw_if_index=self.pg1.sw_if_index,
4556 is_add=1)
4557 self.vapi.nat44_interface_add_del_feature(
4558 sw_if_index=self.pg1.sw_if_index,
4559 flags=flags, is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004560
4561 self.server = self.pg1.remote_hosts[0]
4562
4563 self.server_in_addr = self.server.ip4
4564 self.server_out_addr = '11.11.11.11'
4565 self.server_in_port = random.randint(1025, 65535)
4566 self.server_out_port = random.randint(1025, 65535)
4567
4568 self.nat44_add_address(self.server_out_addr)
4569
4570 # add static mappings for server
4571 self.nat44_add_static_mapping(self.server_in_addr,
4572 self.server_out_addr,
4573 self.server_in_port,
4574 self.server_out_port,
4575 proto=IP_PROTOS.tcp)
4576 self.nat44_add_static_mapping(self.server_in_addr,
4577 self.server_out_addr,
4578 self.server_in_port,
4579 self.server_out_port,
4580 proto=IP_PROTOS.udp)
4581 self.nat44_add_static_mapping(self.server_in_addr,
4582 self.server_out_addr,
4583 proto=IP_PROTOS.icmp)
4584
Filip Vargaf4749ca2019-04-25 14:55:32 +02004585 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4586 drop_frag=0)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004587
4588 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4589 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4590 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4591
4592 def test_frag_out_of_order_in_plus_out(self):
4593 """ in+out interface fragments out of order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004594 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004595 self.vapi.nat44_interface_add_del_feature(
4596 sw_if_index=self.pg0.sw_if_index,
4597 is_add=1)
4598 self.vapi.nat44_interface_add_del_feature(
4599 sw_if_index=self.pg0.sw_if_index,
4600 flags=flags, is_add=1)
4601 self.vapi.nat44_interface_add_del_feature(
4602 sw_if_index=self.pg1.sw_if_index,
4603 is_add=1)
4604 self.vapi.nat44_interface_add_del_feature(
4605 sw_if_index=self.pg1.sw_if_index,
4606 flags=flags, is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004607
4608 self.server = self.pg1.remote_hosts[0]
4609
4610 self.server_in_addr = self.server.ip4
4611 self.server_out_addr = '11.11.11.11'
4612 self.server_in_port = random.randint(1025, 65535)
4613 self.server_out_port = random.randint(1025, 65535)
4614
4615 self.nat44_add_address(self.server_out_addr)
4616
4617 # add static mappings for server
4618 self.nat44_add_static_mapping(self.server_in_addr,
4619 self.server_out_addr,
4620 self.server_in_port,
4621 self.server_out_port,
4622 proto=IP_PROTOS.tcp)
4623 self.nat44_add_static_mapping(self.server_in_addr,
4624 self.server_out_addr,
4625 self.server_in_port,
4626 self.server_out_port,
4627 proto=IP_PROTOS.udp)
4628 self.nat44_add_static_mapping(self.server_in_addr,
4629 self.server_out_addr,
4630 proto=IP_PROTOS.icmp)
4631
Filip Vargaf4749ca2019-04-25 14:55:32 +02004632 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4633 drop_frag=0)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004634
4635 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4636 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4637 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4638
4639 def test_reass_hairpinning(self):
4640 """ NAT44 fragments hairpinning """
4641 self.server = self.pg0.remote_hosts[1]
4642 self.host_in_port = random.randint(1025, 65535)
4643 self.server_in_port = random.randint(1025, 65535)
4644 self.server_out_port = random.randint(1025, 65535)
4645
4646 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004647 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004648 self.vapi.nat44_interface_add_del_feature(
4649 sw_if_index=self.pg0.sw_if_index,
4650 flags=flags, is_add=1)
4651 self.vapi.nat44_interface_add_del_feature(
4652 sw_if_index=self.pg1.sw_if_index,
4653 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004654 # add static mapping for server
4655 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4656 self.server_in_port,
4657 self.server_out_port,
4658 proto=IP_PROTOS.tcp)
4659 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4660 self.server_in_port,
4661 self.server_out_port,
4662 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004663 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004664
4665 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4666 self.reass_hairpinning(proto=IP_PROTOS.udp)
4667 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4668
Matus Fabiana6110b62018-06-13 05:39:07 -07004669 def test_dynamic(self):
4670 """ NAT44 dynamic translation test """
4671
4672 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004673 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004674 self.vapi.nat44_interface_add_del_feature(
4675 sw_if_index=self.pg0.sw_if_index,
4676 flags=flags, is_add=1)
4677 self.vapi.nat44_interface_add_del_feature(
4678 sw_if_index=self.pg1.sw_if_index,
4679 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004680
Matus Fabian69ce30d2018-08-22 01:27:10 -07004681 nat_config = self.vapi.nat_show_config()
4682 self.assertEqual(1, nat_config.endpoint_dependent)
4683
Matus Fabiana6110b62018-06-13 05:39:07 -07004684 # in2out
Ole Troan233e4682019-05-16 15:01:34 +02004685 tcpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004686 '/err/nat44-ed-in2out-slowpath/TCP packets')
Ole Troan233e4682019-05-16 15:01:34 +02004687 udpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004688 '/err/nat44-ed-in2out-slowpath/UDP packets')
Ole Troan233e4682019-05-16 15:01:34 +02004689 icmpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004690 '/err/nat44-ed-in2out-slowpath/ICMP packets')
Ole Troan233e4682019-05-16 15:01:34 +02004691 totaln = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004692 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4693
Matus Fabiana6110b62018-06-13 05:39:07 -07004694 pkts = self.create_stream_in(self.pg0, self.pg1)
4695 self.pg0.add_stream(pkts)
4696 self.pg_enable_capture(self.pg_interfaces)
4697 self.pg_start()
4698 capture = self.pg1.get_capture(len(pkts))
4699 self.verify_capture_out(capture)
4700
Ole Troan233e4682019-05-16 15:01:34 +02004701 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004702 '/err/nat44-ed-in2out-slowpath/TCP packets')
4703 self.assertEqual(err - tcpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02004704 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004705 '/err/nat44-ed-in2out-slowpath/UDP packets')
4706 self.assertEqual(err - udpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02004707 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004708 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4709 self.assertEqual(err - icmpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02004710 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004711 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4712 self.assertEqual(err - totaln, 3)
4713
Matus Fabiana6110b62018-06-13 05:39:07 -07004714 # out2in
Ole Troan233e4682019-05-16 15:01:34 +02004715 tcpn = self.statistics.get_err_counter(
4716 '/err/nat44-ed-out2in/TCP packets')
4717 udpn = self.statistics.get_err_counter(
4718 '/err/nat44-ed-out2in/UDP packets')
4719 icmpn = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004720 '/err/nat44-ed-out2in-slowpath/ICMP packets')
Ole Troan233e4682019-05-16 15:01:34 +02004721 totaln = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004722 '/err/nat44-ed-out2in/good out2in packets processed')
4723
Matus Fabiana6110b62018-06-13 05:39:07 -07004724 pkts = self.create_stream_out(self.pg1)
4725 self.pg1.add_stream(pkts)
4726 self.pg_enable_capture(self.pg_interfaces)
4727 self.pg_start()
4728 capture = self.pg0.get_capture(len(pkts))
4729 self.verify_capture_in(capture, self.pg0)
4730
Ole Troan233e4682019-05-16 15:01:34 +02004731 err = self.statistics.get_err_counter(
4732 '/err/nat44-ed-out2in/TCP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08004733 self.assertEqual(err - tcpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02004734 err = self.statistics.get_err_counter(
4735 '/err/nat44-ed-out2in/UDP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08004736 self.assertEqual(err - udpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02004737 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004738 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4739 self.assertEqual(err - icmpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02004740 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08004741 '/err/nat44-ed-out2in/good out2in packets processed')
4742 self.assertEqual(err - totaln, 2)
4743
Matus Fabianfd0d5082018-12-18 01:08:51 -08004744 users = self.statistics.get_counter('/nat44/total-users')
4745 self.assertEqual(users[0][0], 1)
4746 sessions = self.statistics.get_counter('/nat44/total-sessions')
4747 self.assertEqual(sessions[0][0], 3)
4748
Matus Fabiana6110b62018-06-13 05:39:07 -07004749 def test_forwarding(self):
4750 """ NAT44 forwarding test """
4751
Filip Vargadd1e3e72019-04-15 18:52:43 +02004752 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004753 self.vapi.nat44_interface_add_del_feature(
4754 sw_if_index=self.pg0.sw_if_index,
4755 flags=flags, is_add=1)
4756 self.vapi.nat44_interface_add_del_feature(
4757 sw_if_index=self.pg1.sw_if_index,
4758 is_add=1)
4759 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004760
Filip Vargadd1e3e72019-04-15 18:52:43 +02004761 real_ip = self.pg0.remote_ip4
4762 alias_ip = self.nat_addr
4763 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02004764 self.vapi.nat44_add_del_static_mapping(is_add=1,
4765 local_ip_address=real_ip,
4766 external_ip_address=alias_ip,
4767 external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004768 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07004769
4770 try:
4771 # in2out - static mapping match
4772
4773 pkts = self.create_stream_out(self.pg1)
4774 self.pg1.add_stream(pkts)
4775 self.pg_enable_capture(self.pg_interfaces)
4776 self.pg_start()
4777 capture = self.pg0.get_capture(len(pkts))
4778 self.verify_capture_in(capture, self.pg0)
4779
4780 pkts = self.create_stream_in(self.pg0, self.pg1)
4781 self.pg0.add_stream(pkts)
4782 self.pg_enable_capture(self.pg_interfaces)
4783 self.pg_start()
4784 capture = self.pg1.get_capture(len(pkts))
4785 self.verify_capture_out(capture, same_port=True)
4786
4787 # in2out - no static mapping match
4788
4789 host0 = self.pg0.remote_hosts[0]
4790 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4791 try:
4792 pkts = self.create_stream_out(self.pg1,
4793 dst_ip=self.pg0.remote_ip4,
4794 use_inside_ports=True)
4795 self.pg1.add_stream(pkts)
4796 self.pg_enable_capture(self.pg_interfaces)
4797 self.pg_start()
4798 capture = self.pg0.get_capture(len(pkts))
4799 self.verify_capture_in(capture, self.pg0)
4800
4801 pkts = self.create_stream_in(self.pg0, self.pg1)
4802 self.pg0.add_stream(pkts)
4803 self.pg_enable_capture(self.pg_interfaces)
4804 self.pg_start()
4805 capture = self.pg1.get_capture(len(pkts))
4806 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4807 same_port=True)
4808 finally:
4809 self.pg0.remote_hosts[0] = host0
4810
4811 user = self.pg0.remote_hosts[1]
4812 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4813 self.assertEqual(len(sessions), 3)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004814 self.assertTrue(sessions[0].flags &
4815 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabiana6110b62018-06-13 05:39:07 -07004816 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02004817 address=sessions[0].inside_ip_address,
4818 port=sessions[0].inside_port,
4819 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004820 flags=(self.config_flags.NAT_IS_INSIDE |
4821 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabiana6110b62018-06-13 05:39:07 -07004822 ext_host_address=sessions[0].ext_host_address,
4823 ext_host_port=sessions[0].ext_host_port)
4824 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4825 self.assertEqual(len(sessions), 2)
4826
4827 finally:
Filip Vargaf4749ca2019-04-25 14:55:32 +02004828 self.vapi.nat44_forwarding_enable_disable(enable=0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004829 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02004830 self.vapi.nat44_add_del_static_mapping(
4831 is_add=0,
4832 local_ip_address=real_ip,
4833 external_ip_address=alias_ip,
4834 external_sw_if_index=0xFFFFFFFF,
4835 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07004836
4837 def test_static_lb(self):
4838 """ NAT44 local service load balancing """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004839 external_addr_n = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004840 external_port = 80
4841 local_port = 8080
4842 server1 = self.pg0.remote_hosts[0]
4843 server2 = self.pg0.remote_hosts[1]
4844
4845 locals = [{'addr': server1.ip4n,
4846 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004847 'probability': 70,
4848 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004849 {'addr': server2.ip4n,
4850 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004851 'probability': 30,
4852 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004853
4854 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02004855 self.vapi.nat44_add_del_lb_static_mapping(
4856 is_add=1,
4857 external_addr=external_addr_n,
4858 external_port=external_port,
4859 protocol=IP_PROTOS.tcp,
4860 local_num=len(locals),
4861 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004862 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004863 self.vapi.nat44_interface_add_del_feature(
4864 sw_if_index=self.pg0.sw_if_index,
4865 flags=flags, is_add=1)
4866 self.vapi.nat44_interface_add_del_feature(
4867 sw_if_index=self.pg1.sw_if_index,
4868 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004869
4870 # from client to service
4871 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4872 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4873 TCP(sport=12345, dport=external_port))
4874 self.pg1.add_stream(p)
4875 self.pg_enable_capture(self.pg_interfaces)
4876 self.pg_start()
4877 capture = self.pg0.get_capture(1)
4878 p = capture[0]
4879 server = None
4880 try:
4881 ip = p[IP]
4882 tcp = p[TCP]
4883 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4884 if ip.dst == server1.ip4:
4885 server = server1
4886 else:
4887 server = server2
4888 self.assertEqual(tcp.dport, local_port)
4889 self.assert_packet_checksums_valid(p)
4890 except:
4891 self.logger.error(ppp("Unexpected or invalid packet:", p))
4892 raise
4893
4894 # from service back to client
4895 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4896 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4897 TCP(sport=local_port, dport=12345))
4898 self.pg0.add_stream(p)
4899 self.pg_enable_capture(self.pg_interfaces)
4900 self.pg_start()
4901 capture = self.pg1.get_capture(1)
4902 p = capture[0]
4903 try:
4904 ip = p[IP]
4905 tcp = p[TCP]
4906 self.assertEqual(ip.src, self.nat_addr)
4907 self.assertEqual(tcp.sport, external_port)
4908 self.assert_packet_checksums_valid(p)
4909 except:
4910 self.logger.error(ppp("Unexpected or invalid packet:", p))
4911 raise
4912
4913 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4914 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004915 self.assertTrue(sessions[0].flags &
4916 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabiana6110b62018-06-13 05:39:07 -07004917 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02004918 address=sessions[0].inside_ip_address,
4919 port=sessions[0].inside_port,
4920 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004921 flags=(self.config_flags.NAT_IS_INSIDE |
4922 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabiana6110b62018-06-13 05:39:07 -07004923 ext_host_address=sessions[0].ext_host_address,
4924 ext_host_port=sessions[0].ext_host_port)
4925 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4926 self.assertEqual(len(sessions), 0)
4927
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004928 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004929 def test_static_lb_multi_clients(self):
4930 """ NAT44 local service load balancing - multiple clients"""
4931
Filip Vargadd1e3e72019-04-15 18:52:43 +02004932 external_addr = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004933 external_port = 80
4934 local_port = 8080
4935 server1 = self.pg0.remote_hosts[0]
4936 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004937 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004938
4939 locals = [{'addr': server1.ip4n,
4940 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004941 'probability': 90,
4942 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004943 {'addr': server2.ip4n,
4944 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004945 'probability': 10,
4946 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004947
4948 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02004949 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4950 external_addr=external_addr,
4951 external_port=external_port,
4952 protocol=IP_PROTOS.tcp,
Matus Fabiana6110b62018-06-13 05:39:07 -07004953 local_num=len(locals),
4954 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004955 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004956 self.vapi.nat44_interface_add_del_feature(
4957 sw_if_index=self.pg0.sw_if_index,
4958 flags=flags, is_add=1)
4959 self.vapi.nat44_interface_add_del_feature(
4960 sw_if_index=self.pg1.sw_if_index,
4961 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004962
4963 server1_n = 0
4964 server2_n = 0
4965 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4966 pkts = []
4967 for client in clients:
4968 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4969 IP(src=client, dst=self.nat_addr) /
4970 TCP(sport=12345, dport=external_port))
4971 pkts.append(p)
4972 self.pg1.add_stream(pkts)
4973 self.pg_enable_capture(self.pg_interfaces)
4974 self.pg_start()
4975 capture = self.pg0.get_capture(len(pkts))
4976 for p in capture:
4977 if p[IP].dst == server1.ip4:
4978 server1_n += 1
4979 else:
4980 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004981 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004982
Filip Vargaf4749ca2019-04-25 14:55:32 +02004983 local = {
4984 'addr': server3.ip4n,
4985 'port': local_port,
4986 'probability': 20,
4987 'vrf_id': 0
4988 }
4989
Matus Fabianb6865082018-12-06 03:11:09 -08004990 # add new back-end
Filip Vargaf4749ca2019-04-25 14:55:32 +02004991 self.vapi.nat44_lb_static_mapping_add_del_local(
4992 is_add=1,
4993 external_addr=external_addr,
4994 external_port=external_port,
4995 local=local,
4996 protocol=IP_PROTOS.tcp)
Matus Fabianb6865082018-12-06 03:11:09 -08004997 server1_n = 0
4998 server2_n = 0
4999 server3_n = 0
5000 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5001 pkts = []
5002 for client in clients:
5003 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5004 IP(src=client, dst=self.nat_addr) /
5005 TCP(sport=12346, dport=external_port))
5006 pkts.append(p)
5007 self.assertGreater(len(pkts), 0)
5008 self.pg1.add_stream(pkts)
5009 self.pg_enable_capture(self.pg_interfaces)
5010 self.pg_start()
5011 capture = self.pg0.get_capture(len(pkts))
5012 for p in capture:
5013 if p[IP].dst == server1.ip4:
5014 server1_n += 1
5015 elif p[IP].dst == server2.ip4:
5016 server2_n += 1
5017 else:
5018 server3_n += 1
5019 self.assertGreater(server1_n, 0)
5020 self.assertGreater(server2_n, 0)
5021 self.assertGreater(server3_n, 0)
5022
Filip Vargaf4749ca2019-04-25 14:55:32 +02005023 local = {
5024 'addr': server2.ip4n,
5025 'port': local_port,
5026 'probability': 10,
5027 'vrf_id': 0
5028 }
5029
Matus Fabianb6865082018-12-06 03:11:09 -08005030 # remove one back-end
Filip Vargaf4749ca2019-04-25 14:55:32 +02005031 self.vapi.nat44_lb_static_mapping_add_del_local(
5032 is_add=0,
5033 external_addr=external_addr,
5034 external_port=external_port,
5035 local=local,
5036 protocol=IP_PROTOS.tcp)
Matus Fabianb6865082018-12-06 03:11:09 -08005037 server1_n = 0
5038 server2_n = 0
5039 server3_n = 0
5040 self.pg1.add_stream(pkts)
5041 self.pg_enable_capture(self.pg_interfaces)
5042 self.pg_start()
5043 capture = self.pg0.get_capture(len(pkts))
5044 for p in capture:
5045 if p[IP].dst == server1.ip4:
5046 server1_n += 1
5047 elif p[IP].dst == server2.ip4:
5048 server2_n += 1
5049 else:
5050 server3_n += 1
5051 self.assertGreater(server1_n, 0)
5052 self.assertEqual(server2_n, 0)
5053 self.assertGreater(server3_n, 0)
5054
Matus Fabiana6110b62018-06-13 05:39:07 -07005055 def test_static_lb_2(self):
5056 """ NAT44 local service load balancing (asymmetrical rule) """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005057 external_addr = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07005058 external_port = 80
5059 local_port = 8080
5060 server1 = self.pg0.remote_hosts[0]
5061 server2 = self.pg0.remote_hosts[1]
5062
5063 locals = [{'addr': server1.ip4n,
5064 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005065 'probability': 70,
5066 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07005067 {'addr': server2.ip4n,
5068 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005069 'probability': 30,
5070 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07005071
Filip Vargaf4749ca2019-04-25 14:55:32 +02005072 self.vapi.nat44_forwarding_enable_disable(enable=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005073 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02005074 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5075 external_addr=external_addr,
5076 external_port=external_port,
5077 protocol=IP_PROTOS.tcp,
Matus Fabiana6110b62018-06-13 05:39:07 -07005078 local_num=len(locals),
Filip Vargaf4749ca2019-04-25 14:55:32 +02005079 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005080 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005081 self.vapi.nat44_interface_add_del_feature(
5082 sw_if_index=self.pg0.sw_if_index,
5083 flags=flags, is_add=1)
5084 self.vapi.nat44_interface_add_del_feature(
5085 sw_if_index=self.pg1.sw_if_index,
5086 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005087
5088 # from client to service
5089 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5090 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5091 TCP(sport=12345, dport=external_port))
5092 self.pg1.add_stream(p)
5093 self.pg_enable_capture(self.pg_interfaces)
5094 self.pg_start()
5095 capture = self.pg0.get_capture(1)
5096 p = capture[0]
5097 server = None
5098 try:
5099 ip = p[IP]
5100 tcp = p[TCP]
5101 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5102 if ip.dst == server1.ip4:
5103 server = server1
5104 else:
5105 server = server2
5106 self.assertEqual(tcp.dport, local_port)
5107 self.assert_packet_checksums_valid(p)
5108 except:
5109 self.logger.error(ppp("Unexpected or invalid packet:", p))
5110 raise
5111
5112 # from service back to client
5113 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5114 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5115 TCP(sport=local_port, dport=12345))
5116 self.pg0.add_stream(p)
5117 self.pg_enable_capture(self.pg_interfaces)
5118 self.pg_start()
5119 capture = self.pg1.get_capture(1)
5120 p = capture[0]
5121 try:
5122 ip = p[IP]
5123 tcp = p[TCP]
5124 self.assertEqual(ip.src, self.nat_addr)
5125 self.assertEqual(tcp.sport, external_port)
5126 self.assert_packet_checksums_valid(p)
5127 except:
5128 self.logger.error(ppp("Unexpected or invalid packet:", p))
5129 raise
5130
5131 # from client to server (no translation)
5132 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5133 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5134 TCP(sport=12346, dport=local_port))
5135 self.pg1.add_stream(p)
5136 self.pg_enable_capture(self.pg_interfaces)
5137 self.pg_start()
5138 capture = self.pg0.get_capture(1)
5139 p = capture[0]
5140 server = None
5141 try:
5142 ip = p[IP]
5143 tcp = p[TCP]
5144 self.assertEqual(ip.dst, server1.ip4)
5145 self.assertEqual(tcp.dport, local_port)
5146 self.assert_packet_checksums_valid(p)
5147 except:
5148 self.logger.error(ppp("Unexpected or invalid packet:", p))
5149 raise
5150
5151 # from service back to client (no translation)
5152 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5153 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5154 TCP(sport=local_port, dport=12346))
5155 self.pg0.add_stream(p)
5156 self.pg_enable_capture(self.pg_interfaces)
5157 self.pg_start()
5158 capture = self.pg1.get_capture(1)
5159 p = capture[0]
5160 try:
5161 ip = p[IP]
5162 tcp = p[TCP]
5163 self.assertEqual(ip.src, server1.ip4)
5164 self.assertEqual(tcp.sport, local_port)
5165 self.assert_packet_checksums_valid(p)
5166 except:
5167 self.logger.error(ppp("Unexpected or invalid packet:", p))
5168 raise
5169
Matus Fabianea5b5be2018-09-03 05:02:23 -07005170 def test_lb_affinity(self):
5171 """ NAT44 local service load balancing affinity """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005172 external_addr = self.nat_addr
Matus Fabianea5b5be2018-09-03 05:02:23 -07005173 external_port = 80
5174 local_port = 8080
5175 server1 = self.pg0.remote_hosts[0]
5176 server2 = self.pg0.remote_hosts[1]
5177
5178 locals = [{'addr': server1.ip4n,
5179 'port': local_port,
5180 'probability': 50,
5181 'vrf_id': 0},
5182 {'addr': server2.ip4n,
5183 'port': local_port,
5184 'probability': 50,
5185 'vrf_id': 0}]
5186
5187 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02005188 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5189 external_addr=external_addr,
5190 external_port=external_port,
5191 protocol=IP_PROTOS.tcp,
Matus Fabianea5b5be2018-09-03 05:02:23 -07005192 affinity=10800,
5193 local_num=len(locals),
5194 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005195 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005196 self.vapi.nat44_interface_add_del_feature(
5197 sw_if_index=self.pg0.sw_if_index,
5198 flags=flags, is_add=1)
5199 self.vapi.nat44_interface_add_del_feature(
5200 sw_if_index=self.pg1.sw_if_index,
5201 is_add=1)
Matus Fabianea5b5be2018-09-03 05:02:23 -07005202
5203 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5204 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5205 TCP(sport=1025, dport=external_port))
5206 self.pg1.add_stream(p)
5207 self.pg_enable_capture(self.pg_interfaces)
5208 self.pg_start()
5209 capture = self.pg0.get_capture(1)
5210 backend = capture[0][IP].dst
5211
Filip Vargadd1e3e72019-04-15 18:52:43 +02005212 sessions = self.vapi.nat44_user_session_dump(backend, 0)
Matus Fabianea5b5be2018-09-03 05:02:23 -07005213 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005214 self.assertTrue(sessions[0].flags &
5215 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabianea5b5be2018-09-03 05:02:23 -07005216 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02005217 address=sessions[0].inside_ip_address,
5218 port=sessions[0].inside_port,
5219 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005220 flags=(self.config_flags.NAT_IS_INSIDE |
5221 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabianea5b5be2018-09-03 05:02:23 -07005222 ext_host_address=sessions[0].ext_host_address,
5223 ext_host_port=sessions[0].ext_host_port)
5224
5225 pkts = []
5226 for port in range(1030, 1100):
5227 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5228 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5229 TCP(sport=port, dport=external_port))
5230 pkts.append(p)
5231 self.pg1.add_stream(pkts)
5232 self.pg_enable_capture(self.pg_interfaces)
5233 self.pg_start()
5234 capture = self.pg0.get_capture(len(pkts))
5235 for p in capture:
5236 self.assertEqual(p[IP].dst, backend)
5237
Matus Fabiana6110b62018-06-13 05:39:07 -07005238 def test_unknown_proto(self):
5239 """ NAT44 translate packet with unknown protocol """
5240 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005241 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005242 self.vapi.nat44_interface_add_del_feature(
5243 sw_if_index=self.pg0.sw_if_index,
5244 flags=flags, is_add=1)
5245 self.vapi.nat44_interface_add_del_feature(
5246 sw_if_index=self.pg1.sw_if_index,
5247 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005248
5249 # in2out
5250 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5251 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5252 TCP(sport=self.tcp_port_in, dport=20))
5253 self.pg0.add_stream(p)
5254 self.pg_enable_capture(self.pg_interfaces)
5255 self.pg_start()
5256 p = self.pg1.get_capture(1)
5257
5258 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5259 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5260 GRE() /
5261 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5262 TCP(sport=1234, dport=1234))
5263 self.pg0.add_stream(p)
5264 self.pg_enable_capture(self.pg_interfaces)
5265 self.pg_start()
5266 p = self.pg1.get_capture(1)
5267 packet = p[0]
5268 try:
5269 self.assertEqual(packet[IP].src, self.nat_addr)
5270 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005271 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005272 self.assert_packet_checksums_valid(packet)
5273 except:
5274 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5275 raise
5276
5277 # out2in
5278 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5279 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5280 GRE() /
5281 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5282 TCP(sport=1234, dport=1234))
5283 self.pg1.add_stream(p)
5284 self.pg_enable_capture(self.pg_interfaces)
5285 self.pg_start()
5286 p = self.pg0.get_capture(1)
5287 packet = p[0]
5288 try:
5289 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5290 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005291 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005292 self.assert_packet_checksums_valid(packet)
5293 except:
5294 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5295 raise
5296
5297 def test_hairpinning_unknown_proto(self):
5298 """ NAT44 translate packet with unknown protocol - hairpinning """
5299 host = self.pg0.remote_hosts[0]
5300 server = self.pg0.remote_hosts[1]
5301 host_in_port = 1234
5302 server_out_port = 8765
5303 server_nat_ip = "10.0.0.11"
5304
5305 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005306 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005307 self.vapi.nat44_interface_add_del_feature(
5308 sw_if_index=self.pg0.sw_if_index,
5309 flags=flags, is_add=1)
5310 self.vapi.nat44_interface_add_del_feature(
5311 sw_if_index=self.pg1.sw_if_index,
5312 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005313
5314 # add static mapping for server
5315 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5316
5317 # host to server
5318 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5319 IP(src=host.ip4, dst=server_nat_ip) /
5320 TCP(sport=host_in_port, dport=server_out_port))
5321 self.pg0.add_stream(p)
5322 self.pg_enable_capture(self.pg_interfaces)
5323 self.pg_start()
5324 self.pg0.get_capture(1)
5325
5326 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5327 IP(src=host.ip4, dst=server_nat_ip) /
5328 GRE() /
5329 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5330 TCP(sport=1234, dport=1234))
5331 self.pg0.add_stream(p)
5332 self.pg_enable_capture(self.pg_interfaces)
5333 self.pg_start()
5334 p = self.pg0.get_capture(1)
5335 packet = p[0]
5336 try:
5337 self.assertEqual(packet[IP].src, self.nat_addr)
5338 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005339 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005340 self.assert_packet_checksums_valid(packet)
5341 except:
5342 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5343 raise
5344
5345 # server to host
5346 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5347 IP(src=server.ip4, dst=self.nat_addr) /
5348 GRE() /
5349 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5350 TCP(sport=1234, dport=1234))
5351 self.pg0.add_stream(p)
5352 self.pg_enable_capture(self.pg_interfaces)
5353 self.pg_start()
5354 p = self.pg0.get_capture(1)
5355 packet = p[0]
5356 try:
5357 self.assertEqual(packet[IP].src, server_nat_ip)
5358 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005359 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005360 self.assert_packet_checksums_valid(packet)
5361 except:
5362 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5363 raise
5364
5365 def test_output_feature_and_service(self):
5366 """ NAT44 interface output feature and services """
5367 external_addr = '1.2.3.4'
5368 external_port = 80
5369 local_port = 8080
5370
Filip Vargaf4749ca2019-04-25 14:55:32 +02005371 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005372 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005373 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02005374 self.vapi.nat44_add_del_identity_mapping(
5375 ip_address=self.pg1.remote_ip4n, sw_if_index=0xFFFFFFFF,
5376 flags=flags, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005377 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005378 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5379 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005380 proto=IP_PROTOS.tcp, flags=flags)
5381 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005382 self.vapi.nat44_interface_add_del_feature(
5383 sw_if_index=self.pg0.sw_if_index,
5384 is_add=1)
5385 self.vapi.nat44_interface_add_del_feature(
5386 sw_if_index=self.pg0.sw_if_index,
5387 flags=flags, is_add=1)
5388 self.vapi.nat44_interface_add_del_output_feature(
5389 is_add=1,
5390 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005391
5392 # from client to service
5393 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5394 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5395 TCP(sport=12345, dport=external_port))
5396 self.pg1.add_stream(p)
5397 self.pg_enable_capture(self.pg_interfaces)
5398 self.pg_start()
5399 capture = self.pg0.get_capture(1)
5400 p = capture[0]
5401 try:
5402 ip = p[IP]
5403 tcp = p[TCP]
5404 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5405 self.assertEqual(tcp.dport, local_port)
5406 self.assert_packet_checksums_valid(p)
5407 except:
5408 self.logger.error(ppp("Unexpected or invalid packet:", p))
5409 raise
5410
5411 # from service back to client
5412 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5413 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5414 TCP(sport=local_port, dport=12345))
5415 self.pg0.add_stream(p)
5416 self.pg_enable_capture(self.pg_interfaces)
5417 self.pg_start()
5418 capture = self.pg1.get_capture(1)
5419 p = capture[0]
5420 try:
5421 ip = p[IP]
5422 tcp = p[TCP]
5423 self.assertEqual(ip.src, external_addr)
5424 self.assertEqual(tcp.sport, external_port)
5425 self.assert_packet_checksums_valid(p)
5426 except:
5427 self.logger.error(ppp("Unexpected or invalid packet:", p))
5428 raise
5429
5430 # from local network host to external network
5431 pkts = self.create_stream_in(self.pg0, self.pg1)
5432 self.pg0.add_stream(pkts)
5433 self.pg_enable_capture(self.pg_interfaces)
5434 self.pg_start()
5435 capture = self.pg1.get_capture(len(pkts))
5436 self.verify_capture_out(capture)
5437 pkts = self.create_stream_in(self.pg0, self.pg1)
5438 self.pg0.add_stream(pkts)
5439 self.pg_enable_capture(self.pg_interfaces)
5440 self.pg_start()
5441 capture = self.pg1.get_capture(len(pkts))
5442 self.verify_capture_out(capture)
5443
5444 # from external network back to local network host
5445 pkts = self.create_stream_out(self.pg1)
5446 self.pg1.add_stream(pkts)
5447 self.pg_enable_capture(self.pg_interfaces)
5448 self.pg_start()
5449 capture = self.pg0.get_capture(len(pkts))
5450 self.verify_capture_in(capture, self.pg0)
5451
5452 def test_output_feature_and_service2(self):
5453 """ NAT44 interface output feature and service host direct access """
Filip Vargaf4749ca2019-04-25 14:55:32 +02005454 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005455 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02005456 self.vapi.nat44_interface_add_del_output_feature(
5457 is_add=1,
5458 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005459
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005460 # session initiated from service host - translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005461 pkts = self.create_stream_in(self.pg0, self.pg1)
5462 self.pg0.add_stream(pkts)
5463 self.pg_enable_capture(self.pg_interfaces)
5464 self.pg_start()
5465 capture = self.pg1.get_capture(len(pkts))
5466 self.verify_capture_out(capture)
5467
5468 pkts = self.create_stream_out(self.pg1)
5469 self.pg1.add_stream(pkts)
5470 self.pg_enable_capture(self.pg_interfaces)
5471 self.pg_start()
5472 capture = self.pg0.get_capture(len(pkts))
5473 self.verify_capture_in(capture, self.pg0)
5474
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005475 # session initiated from remote host - do not translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005476 self.tcp_port_in = 60303
5477 self.udp_port_in = 60304
5478 self.icmp_id_in = 60305
5479 pkts = self.create_stream_out(self.pg1,
5480 self.pg0.remote_ip4,
5481 use_inside_ports=True)
5482 self.pg1.add_stream(pkts)
5483 self.pg_enable_capture(self.pg_interfaces)
5484 self.pg_start()
5485 capture = self.pg0.get_capture(len(pkts))
5486 self.verify_capture_in(capture, self.pg0)
5487
5488 pkts = self.create_stream_in(self.pg0, self.pg1)
5489 self.pg0.add_stream(pkts)
5490 self.pg_enable_capture(self.pg_interfaces)
5491 self.pg_start()
5492 capture = self.pg1.get_capture(len(pkts))
5493 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5494 same_port=True)
5495
5496 def test_output_feature_and_service3(self):
5497 """ NAT44 interface output feature and DST NAT """
5498 external_addr = '1.2.3.4'
5499 external_port = 80
5500 local_port = 8080
5501
Filip Vargaf4749ca2019-04-25 14:55:32 +02005502 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005503 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005504 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005505 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5506 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005507 proto=IP_PROTOS.tcp, flags=flags)
5508 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005509 self.vapi.nat44_interface_add_del_feature(
5510 sw_if_index=self.pg0.sw_if_index,
5511 is_add=1)
5512 self.vapi.nat44_interface_add_del_feature(
5513 sw_if_index=self.pg0.sw_if_index,
5514 flags=flags, is_add=1)
5515 self.vapi.nat44_interface_add_del_output_feature(
5516 is_add=1,
5517 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005518
5519 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5520 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5521 TCP(sport=12345, dport=external_port))
5522 self.pg0.add_stream(p)
5523 self.pg_enable_capture(self.pg_interfaces)
5524 self.pg_start()
5525 capture = self.pg1.get_capture(1)
5526 p = capture[0]
5527 try:
5528 ip = p[IP]
5529 tcp = p[TCP]
5530 self.assertEqual(ip.src, self.pg0.remote_ip4)
5531 self.assertEqual(tcp.sport, 12345)
5532 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5533 self.assertEqual(tcp.dport, local_port)
5534 self.assert_packet_checksums_valid(p)
5535 except:
5536 self.logger.error(ppp("Unexpected or invalid packet:", p))
5537 raise
5538
5539 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5540 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5541 TCP(sport=local_port, dport=12345))
5542 self.pg1.add_stream(p)
5543 self.pg_enable_capture(self.pg_interfaces)
5544 self.pg_start()
5545 capture = self.pg0.get_capture(1)
5546 p = capture[0]
5547 try:
5548 ip = p[IP]
5549 tcp = p[TCP]
5550 self.assertEqual(ip.src, external_addr)
5551 self.assertEqual(tcp.sport, external_port)
5552 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5553 self.assertEqual(tcp.dport, 12345)
5554 self.assert_packet_checksums_valid(p)
5555 except:
5556 self.logger.error(ppp("Unexpected or invalid packet:", p))
5557 raise
5558
Matus Fabian182e37e2018-08-14 04:21:26 -07005559 def test_next_src_nat(self):
5560 """ On way back forward packet to nat44-in2out node. """
5561 twice_nat_addr = '10.0.1.3'
5562 external_port = 80
5563 local_port = 8080
5564 post_twice_nat_port = 0
5565
Filip Vargaf4749ca2019-04-25 14:55:32 +02005566 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian182e37e2018-08-14 04:21:26 -07005567 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005568 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5569 self.config_flags.NAT_IS_SELF_TWICE_NAT)
Matus Fabian182e37e2018-08-14 04:21:26 -07005570 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5571 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005572 proto=IP_PROTOS.tcp, vrf_id=1,
5573 flags=flags)
Filip Vargaf4749ca2019-04-25 14:55:32 +02005574 self.vapi.nat44_interface_add_del_feature(
5575 sw_if_index=self.pg6.sw_if_index,
5576 is_add=1)
Matus Fabian182e37e2018-08-14 04:21:26 -07005577
5578 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5579 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5580 TCP(sport=12345, dport=external_port))
5581 self.pg6.add_stream(p)
5582 self.pg_enable_capture(self.pg_interfaces)
5583 self.pg_start()
5584 capture = self.pg6.get_capture(1)
5585 p = capture[0]
5586 try:
5587 ip = p[IP]
5588 tcp = p[TCP]
5589 self.assertEqual(ip.src, twice_nat_addr)
5590 self.assertNotEqual(tcp.sport, 12345)
5591 post_twice_nat_port = tcp.sport
5592 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5593 self.assertEqual(tcp.dport, local_port)
5594 self.assert_packet_checksums_valid(p)
5595 except:
5596 self.logger.error(ppp("Unexpected or invalid packet:", p))
5597 raise
5598
5599 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5600 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5601 TCP(sport=local_port, dport=post_twice_nat_port))
5602 self.pg6.add_stream(p)
5603 self.pg_enable_capture(self.pg_interfaces)
5604 self.pg_start()
5605 capture = self.pg6.get_capture(1)
5606 p = capture[0]
5607 try:
5608 ip = p[IP]
5609 tcp = p[TCP]
5610 self.assertEqual(ip.src, self.pg1.remote_ip4)
5611 self.assertEqual(tcp.sport, external_port)
5612 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5613 self.assertEqual(tcp.dport, 12345)
5614 self.assert_packet_checksums_valid(p)
5615 except:
5616 self.logger.error(ppp("Unexpected or invalid packet:", p))
5617 raise
5618
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005619 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5620 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005621 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005622
Matus Fabianb932d262017-12-18 05:38:24 -08005623 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005624 if lb:
5625 if not same_pg:
5626 port_in1 = port_in
5627 port_in2 = port_in
5628 else:
Ole Troan9a475372019-03-05 16:58:24 +01005629 port_in1 = port_in + 1
5630 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005631
Matus Fabianb932d262017-12-18 05:38:24 -08005632 port_out = 80
5633 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005634
5635 server1 = self.pg0.remote_hosts[0]
5636 server2 = self.pg0.remote_hosts[1]
5637 if lb and same_pg:
5638 server2 = server1
5639 if not lb:
5640 server = server1
5641
5642 pg0 = self.pg0
5643 if same_pg:
5644 pg1 = self.pg0
5645 else:
5646 pg1 = self.pg1
5647
5648 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5649 client_id == 1)
5650
Matus Fabianb932d262017-12-18 05:38:24 -08005651 self.nat44_add_address(self.nat_addr)
5652 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005653
5654 flags = 0
5655 if self_twice_nat:
5656 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5657 else:
5658 flags |= self.config_flags.NAT_IS_TWICE_NAT
5659
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005660 if not lb:
5661 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5662 port_in, port_out,
5663 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005664 flags=flags)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005665 else:
5666 locals = [{'addr': server1.ip4n,
5667 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005668 'probability': 50,
5669 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005670 {'addr': server2.ip4n,
5671 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005672 'probability': 50,
5673 'vrf_id': 0}]
Filip Vargadd1e3e72019-04-15 18:52:43 +02005674 out_addr = self.nat_addr
5675
Filip Vargaf4749ca2019-04-25 14:55:32 +02005676 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5677 external_addr=out_addr,
5678 external_port=port_out,
5679 protocol=IP_PROTOS.tcp,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005680 local_num=len(locals),
Filip Vargaf4749ca2019-04-25 14:55:32 +02005681 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005682 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005683 self.vapi.nat44_interface_add_del_feature(
5684 sw_if_index=pg0.sw_if_index,
5685 flags=flags, is_add=1)
5686 self.vapi.nat44_interface_add_del_feature(
5687 sw_if_index=pg1.sw_if_index,
5688 is_add=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005689
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005690 if same_pg:
5691 if not lb:
5692 client = server
5693 else:
5694 assert client_id is not None
5695 if client_id == 1:
5696 client = self.pg0.remote_hosts[0]
5697 elif client_id == 2:
5698 client = self.pg0.remote_hosts[1]
5699 else:
5700 client = pg1.remote_hosts[0]
5701 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5702 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005703 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005704 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005705 self.pg_enable_capture(self.pg_interfaces)
5706 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005707 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005708 p = capture[0]
5709 try:
5710 ip = p[IP]
5711 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005712 if lb:
5713 if ip.dst == server1.ip4:
5714 server = server1
5715 port_in = port_in1
5716 else:
5717 server = server2
5718 port_in = port_in2
5719 self.assertEqual(ip.dst, server.ip4)
5720 if lb and same_pg:
5721 self.assertIn(tcp.dport, [port_in1, port_in2])
5722 else:
5723 self.assertEqual(tcp.dport, port_in)
5724 if eh_translate:
5725 self.assertEqual(ip.src, twice_nat_addr)
5726 self.assertNotEqual(tcp.sport, eh_port_out)
5727 else:
5728 self.assertEqual(ip.src, client.ip4)
5729 self.assertEqual(tcp.sport, eh_port_out)
5730 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005731 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005732 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005733 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005734 except:
5735 self.logger.error(ppp("Unexpected or invalid packet:", p))
5736 raise
5737
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005738 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5739 IP(src=server.ip4, dst=eh_addr_in) /
5740 TCP(sport=saved_port_in, dport=eh_port_in))
5741 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005742 self.pg_enable_capture(self.pg_interfaces)
5743 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005744 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005745 p = capture[0]
5746 try:
5747 ip = p[IP]
5748 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005749 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005750 self.assertEqual(ip.src, self.nat_addr)
5751 self.assertEqual(tcp.dport, eh_port_out)
5752 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005753 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005754 except:
5755 self.logger.error(ppp("Unexpected or invalid packet:", p))
5756 raise
5757
Matus Fabian70a26ac2018-05-14 06:20:28 -07005758 if eh_translate:
5759 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5760 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005761 self.assertTrue(sessions[0].flags &
5762 self.config_flags.NAT_IS_EXT_HOST_VALID)
5763 self.assertTrue(sessions[0].flags &
5764 self.config_flags.NAT_IS_TWICE_NAT)
Paul Vinciguerra2f5fd362019-06-19 21:21:13 -04005765 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian70a26ac2018-05-14 06:20:28 -07005766 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02005767 address=sessions[0].inside_ip_address,
5768 port=sessions[0].inside_port,
5769 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005770 flags=(self.config_flags.NAT_IS_INSIDE |
5771 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabian70a26ac2018-05-14 06:20:28 -07005772 ext_host_address=sessions[0].ext_host_nat_address,
5773 ext_host_port=sessions[0].ext_host_nat_port)
5774 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5775 self.assertEqual(len(sessions), 0)
5776
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005777 def test_twice_nat(self):
5778 """ Twice NAT44 """
5779 self.twice_nat_common()
5780
5781 def test_self_twice_nat_positive(self):
5782 """ Self Twice NAT44 (positive test) """
5783 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5784
5785 def test_self_twice_nat_negative(self):
5786 """ Self Twice NAT44 (negative test) """
5787 self.twice_nat_common(self_twice_nat=True)
5788
Matus Fabianb932d262017-12-18 05:38:24 -08005789 def test_twice_nat_lb(self):
5790 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005791 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005792
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005793 def test_self_twice_nat_lb_positive(self):
5794 """ Self Twice NAT44 local service load balancing (positive test) """
5795 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5796 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005797
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005798 def test_self_twice_nat_lb_negative(self):
5799 """ Self Twice NAT44 local service load balancing (negative test) """
5800 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5801 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005802
5803 def test_twice_nat_interface_addr(self):
5804 """ Acquire twice NAT44 addresses from interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005805 flags = self.config_flags.NAT_IS_TWICE_NAT
Filip Vargaf4749ca2019-04-25 14:55:32 +02005806 self.vapi.nat44_add_del_interface_addr(
5807 is_add=1,
5808 sw_if_index=self.pg3.sw_if_index,
5809 flags=flags)
Matus Fabianb932d262017-12-18 05:38:24 -08005810
5811 # no address in NAT pool
5812 adresses = self.vapi.nat44_address_dump()
5813 self.assertEqual(0, len(adresses))
5814
5815 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005816 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005817 adresses = self.vapi.nat44_address_dump()
5818 self.assertEqual(1, len(adresses))
Filip Vargadd1e3e72019-04-15 18:52:43 +02005819 self.assertEqual(str(adresses[0].ip_address),
5820 self.pg3.local_ip4)
5821 self.assertEqual(adresses[0].flags, flags)
Matus Fabianb932d262017-12-18 05:38:24 -08005822
5823 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005824 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005825 adresses = self.vapi.nat44_address_dump()
5826 self.assertEqual(0, len(adresses))
5827
Matus Fabian6c01dce2018-11-16 04:41:31 -08005828 def test_tcp_close(self):
5829 """ Close TCP session from inside network - output feature """
Filip Vargaf4749ca2019-04-25 14:55:32 +02005830 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005831 self.nat44_add_address(self.pg1.local_ip4)
5832 twice_nat_addr = '10.0.1.3'
5833 service_ip = '192.168.16.150'
5834 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005835 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005836 self.vapi.nat44_interface_add_del_feature(
5837 sw_if_index=self.pg0.sw_if_index,
5838 is_add=1)
5839 self.vapi.nat44_interface_add_del_feature(
5840 sw_if_index=self.pg0.sw_if_index,
5841 flags=flags, is_add=1)
5842 self.vapi.nat44_interface_add_del_output_feature(
5843 is_add=1,
5844 sw_if_index=self.pg1.sw_if_index)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005845 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5846 self.config_flags.NAT_IS_TWICE_NAT)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005847 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5848 service_ip,
5849 80,
5850 80,
5851 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005852 flags=flags)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005853 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5854 start_sessnum = len(sessions)
5855
5856 # SYN packet out->in
5857 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5858 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5859 TCP(sport=33898, dport=80, flags="S"))
5860 self.pg1.add_stream(p)
5861 self.pg_enable_capture(self.pg_interfaces)
5862 self.pg_start()
5863 capture = self.pg0.get_capture(1)
5864 p = capture[0]
5865 tcp_port = p[TCP].sport
5866
5867 # SYN + ACK packet in->out
5868 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5869 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5870 TCP(sport=80, dport=tcp_port, flags="SA"))
5871 self.pg0.add_stream(p)
5872 self.pg_enable_capture(self.pg_interfaces)
5873 self.pg_start()
5874 self.pg1.get_capture(1)
5875
5876 # ACK packet out->in
5877 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5878 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5879 TCP(sport=33898, dport=80, flags="A"))
5880 self.pg1.add_stream(p)
5881 self.pg_enable_capture(self.pg_interfaces)
5882 self.pg_start()
5883 self.pg0.get_capture(1)
5884
5885 # FIN packet in -> out
5886 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5887 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5888 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5889 self.pg0.add_stream(p)
5890 self.pg_enable_capture(self.pg_interfaces)
5891 self.pg_start()
5892 self.pg1.get_capture(1)
5893
5894 # FIN+ACK packet out -> in
5895 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5896 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5897 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5898 self.pg1.add_stream(p)
5899 self.pg_enable_capture(self.pg_interfaces)
5900 self.pg_start()
5901 self.pg0.get_capture(1)
5902
5903 # ACK packet in -> out
5904 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5905 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5906 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5907 self.pg0.add_stream(p)
5908 self.pg_enable_capture(self.pg_interfaces)
5909 self.pg_start()
5910 self.pg1.get_capture(1)
5911
5912 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5913 0)
5914 self.assertEqual(len(sessions) - start_sessnum, 0)
5915
Matus Fabianebdf1902018-05-04 03:57:42 -07005916 def test_tcp_session_close_in(self):
5917 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005918 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005919 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005920 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07005921 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5922 self.nat_addr,
5923 self.tcp_port_in,
5924 self.tcp_port_out,
5925 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005926 flags=flags)
5927 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005928 self.vapi.nat44_interface_add_del_feature(
5929 sw_if_index=self.pg0.sw_if_index,
5930 flags=flags, is_add=1)
5931 self.vapi.nat44_interface_add_del_feature(
5932 sw_if_index=self.pg1.sw_if_index,
5933 is_add=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005934
5935 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5936 start_sessnum = len(sessions)
5937
5938 self.initiate_tcp_session(self.pg0, self.pg1)
5939
Matus Fabian229c1aa2018-05-28 04:09:52 -07005940 # FIN packet in -> out
5941 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5942 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5943 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5944 flags="FA", seq=100, ack=300))
5945 self.pg0.add_stream(p)
5946 self.pg_enable_capture(self.pg_interfaces)
5947 self.pg_start()
5948 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005949
Matus Fabian229c1aa2018-05-28 04:09:52 -07005950 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005951
Matus Fabian229c1aa2018-05-28 04:09:52 -07005952 # ACK packet out -> in
5953 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5954 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5955 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5956 flags="A", seq=300, ack=101))
5957 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005958
Matus Fabian229c1aa2018-05-28 04:09:52 -07005959 # FIN packet out -> in
5960 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5961 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5962 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5963 flags="FA", seq=300, ack=101))
5964 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005965
Matus Fabian229c1aa2018-05-28 04:09:52 -07005966 self.pg1.add_stream(pkts)
5967 self.pg_enable_capture(self.pg_interfaces)
5968 self.pg_start()
5969 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005970
Matus Fabian229c1aa2018-05-28 04:09:52 -07005971 # ACK packet in -> out
5972 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5973 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5974 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5975 flags="A", seq=101, ack=301))
5976 self.pg0.add_stream(p)
5977 self.pg_enable_capture(self.pg_interfaces)
5978 self.pg_start()
5979 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005980
Matus Fabian229c1aa2018-05-28 04:09:52 -07005981 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5982 0)
5983 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005984
5985 def test_tcp_session_close_out(self):
5986 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005987 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005988 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005989 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07005990 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5991 self.nat_addr,
5992 self.tcp_port_in,
5993 self.tcp_port_out,
5994 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005995 flags=flags)
5996 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005997 self.vapi.nat44_interface_add_del_feature(
5998 sw_if_index=self.pg0.sw_if_index,
5999 flags=flags, is_add=1)
6000 self.vapi.nat44_interface_add_del_feature(
6001 sw_if_index=self.pg1.sw_if_index,
6002 is_add=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006003
6004 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
6005 start_sessnum = len(sessions)
6006
6007 self.initiate_tcp_session(self.pg0, self.pg1)
6008
Matus Fabian229c1aa2018-05-28 04:09:52 -07006009 # FIN packet out -> in
6010 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6011 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6012 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6013 flags="FA", seq=100, ack=300))
6014 self.pg1.add_stream(p)
6015 self.pg_enable_capture(self.pg_interfaces)
6016 self.pg_start()
6017 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006018
Matus Fabian229c1aa2018-05-28 04:09:52 -07006019 # FIN+ACK packet in -> out
6020 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6021 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6022 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6023 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07006024
Matus Fabian229c1aa2018-05-28 04:09:52 -07006025 self.pg0.add_stream(p)
6026 self.pg_enable_capture(self.pg_interfaces)
6027 self.pg_start()
6028 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006029
Matus Fabian229c1aa2018-05-28 04:09:52 -07006030 # ACK packet out -> in
6031 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6032 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6033 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6034 flags="A", seq=101, ack=301))
6035 self.pg1.add_stream(p)
6036 self.pg_enable_capture(self.pg_interfaces)
6037 self.pg_start()
6038 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006039
Matus Fabian229c1aa2018-05-28 04:09:52 -07006040 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6041 0)
6042 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07006043
6044 def test_tcp_session_close_simultaneous(self):
6045 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07006046 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07006047 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006048 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07006049 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6050 self.nat_addr,
6051 self.tcp_port_in,
6052 self.tcp_port_out,
6053 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006054 flags=flags)
6055 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006056 self.vapi.nat44_interface_add_del_feature(
6057 sw_if_index=self.pg0.sw_if_index,
6058 flags=flags, is_add=1)
6059 self.vapi.nat44_interface_add_del_feature(
6060 sw_if_index=self.pg1.sw_if_index,
6061 is_add=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006062
6063 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
6064 start_sessnum = len(sessions)
6065
6066 self.initiate_tcp_session(self.pg0, self.pg1)
6067
Matus Fabian229c1aa2018-05-28 04:09:52 -07006068 # FIN packet in -> out
6069 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6070 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6071 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6072 flags="FA", seq=100, ack=300))
6073 self.pg0.add_stream(p)
6074 self.pg_enable_capture(self.pg_interfaces)
6075 self.pg_start()
6076 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006077
Matus Fabian229c1aa2018-05-28 04:09:52 -07006078 # FIN packet out -> in
6079 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6080 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6081 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6082 flags="FA", seq=300, ack=100))
6083 self.pg1.add_stream(p)
6084 self.pg_enable_capture(self.pg_interfaces)
6085 self.pg_start()
6086 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006087
Matus Fabian229c1aa2018-05-28 04:09:52 -07006088 # ACK packet in -> out
6089 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6090 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6091 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6092 flags="A", seq=101, ack=301))
6093 self.pg0.add_stream(p)
6094 self.pg_enable_capture(self.pg_interfaces)
6095 self.pg_start()
6096 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006097
Matus Fabian229c1aa2018-05-28 04:09:52 -07006098 # ACK packet out -> in
6099 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6100 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6101 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6102 flags="A", seq=301, ack=101))
6103 self.pg1.add_stream(p)
6104 self.pg_enable_capture(self.pg_interfaces)
6105 self.pg_start()
6106 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006107
Matus Fabian229c1aa2018-05-28 04:09:52 -07006108 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6109 0)
6110 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07006111
Matus Fabiana6110b62018-06-13 05:39:07 -07006112 def test_one_armed_nat44_static(self):
6113 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6114 remote_host = self.pg4.remote_hosts[0]
6115 local_host = self.pg4.remote_hosts[1]
6116 external_port = 80
6117 local_port = 8080
6118 eh_port_in = 0
6119
Filip Vargaf4749ca2019-04-25 14:55:32 +02006120 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07006121 self.nat44_add_address(self.nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006122 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6123 self.config_flags.NAT_IS_TWICE_NAT)
Matus Fabiana6110b62018-06-13 05:39:07 -07006124 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6125 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006126 proto=IP_PROTOS.tcp, flags=flags)
6127 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006128 self.vapi.nat44_interface_add_del_feature(
6129 sw_if_index=self.pg4.sw_if_index,
6130 is_add=1)
6131 self.vapi.nat44_interface_add_del_feature(
6132 sw_if_index=self.pg4.sw_if_index,
6133 flags=flags, is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07006134
6135 # from client to service
6136 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6137 IP(src=remote_host.ip4, dst=self.nat_addr) /
6138 TCP(sport=12345, dport=external_port))
6139 self.pg4.add_stream(p)
6140 self.pg_enable_capture(self.pg_interfaces)
6141 self.pg_start()
6142 capture = self.pg4.get_capture(1)
6143 p = capture[0]
6144 try:
6145 ip = p[IP]
6146 tcp = p[TCP]
6147 self.assertEqual(ip.dst, local_host.ip4)
6148 self.assertEqual(ip.src, self.nat_addr)
6149 self.assertEqual(tcp.dport, local_port)
6150 self.assertNotEqual(tcp.sport, 12345)
6151 eh_port_in = tcp.sport
6152 self.assert_packet_checksums_valid(p)
6153 except:
6154 self.logger.error(ppp("Unexpected or invalid packet:", p))
6155 raise
6156
6157 # from service back to client
6158 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6159 IP(src=local_host.ip4, dst=self.nat_addr) /
6160 TCP(sport=local_port, dport=eh_port_in))
6161 self.pg4.add_stream(p)
6162 self.pg_enable_capture(self.pg_interfaces)
6163 self.pg_start()
6164 capture = self.pg4.get_capture(1)
6165 p = capture[0]
6166 try:
6167 ip = p[IP]
6168 tcp = p[TCP]
6169 self.assertEqual(ip.src, self.nat_addr)
6170 self.assertEqual(ip.dst, remote_host.ip4)
6171 self.assertEqual(tcp.sport, external_port)
6172 self.assertEqual(tcp.dport, 12345)
6173 self.assert_packet_checksums_valid(p)
6174 except:
6175 self.logger.error(ppp("Unexpected or invalid packet:", p))
6176 raise
6177
6178 def test_static_with_port_out2(self):
6179 """ 1:1 NAPT asymmetrical rule """
6180
6181 external_port = 80
6182 local_port = 8080
6183
Filip Vargaf4749ca2019-04-25 14:55:32 +02006184 self.vapi.nat44_forwarding_enable_disable(enable=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006185 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07006186 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6187 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006188 proto=IP_PROTOS.tcp, flags=flags)
6189 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006190 self.vapi.nat44_interface_add_del_feature(
6191 sw_if_index=self.pg0.sw_if_index,
6192 flags=flags, is_add=1)
6193 self.vapi.nat44_interface_add_del_feature(
6194 sw_if_index=self.pg1.sw_if_index,
6195 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07006196
6197 # from client to service
6198 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6199 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6200 TCP(sport=12345, dport=external_port))
6201 self.pg1.add_stream(p)
6202 self.pg_enable_capture(self.pg_interfaces)
6203 self.pg_start()
6204 capture = self.pg0.get_capture(1)
6205 p = capture[0]
6206 try:
6207 ip = p[IP]
6208 tcp = p[TCP]
6209 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6210 self.assertEqual(tcp.dport, local_port)
6211 self.assert_packet_checksums_valid(p)
6212 except:
6213 self.logger.error(ppp("Unexpected or invalid packet:", p))
6214 raise
6215
6216 # ICMP error
6217 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6218 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6219 ICMP(type=11) / capture[0][IP])
6220 self.pg0.add_stream(p)
6221 self.pg_enable_capture(self.pg_interfaces)
6222 self.pg_start()
6223 capture = self.pg1.get_capture(1)
6224 p = capture[0]
6225 try:
6226 self.assertEqual(p[IP].src, self.nat_addr)
6227 inner = p[IPerror]
6228 self.assertEqual(inner.dst, self.nat_addr)
6229 self.assertEqual(inner[TCPerror].dport, external_port)
6230 except:
6231 self.logger.error(ppp("Unexpected or invalid packet:", p))
6232 raise
6233
6234 # from service back to client
6235 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6236 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6237 TCP(sport=local_port, dport=12345))
6238 self.pg0.add_stream(p)
6239 self.pg_enable_capture(self.pg_interfaces)
6240 self.pg_start()
6241 capture = self.pg1.get_capture(1)
6242 p = capture[0]
6243 try:
6244 ip = p[IP]
6245 tcp = p[TCP]
6246 self.assertEqual(ip.src, self.nat_addr)
6247 self.assertEqual(tcp.sport, external_port)
6248 self.assert_packet_checksums_valid(p)
6249 except:
6250 self.logger.error(ppp("Unexpected or invalid packet:", p))
6251 raise
6252
6253 # ICMP error
6254 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6255 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6256 ICMP(type=11) / capture[0][IP])
6257 self.pg1.add_stream(p)
6258 self.pg_enable_capture(self.pg_interfaces)
6259 self.pg_start()
6260 capture = self.pg0.get_capture(1)
6261 p = capture[0]
6262 try:
6263 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6264 inner = p[IPerror]
6265 self.assertEqual(inner.src, self.pg0.remote_ip4)
6266 self.assertEqual(inner[TCPerror].sport, local_port)
6267 except:
6268 self.logger.error(ppp("Unexpected or invalid packet:", p))
6269 raise
6270
6271 # from client to server (no translation)
6272 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6273 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6274 TCP(sport=12346, dport=local_port))
6275 self.pg1.add_stream(p)
6276 self.pg_enable_capture(self.pg_interfaces)
6277 self.pg_start()
6278 capture = self.pg0.get_capture(1)
6279 p = capture[0]
6280 try:
6281 ip = p[IP]
6282 tcp = p[TCP]
6283 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6284 self.assertEqual(tcp.dport, local_port)
6285 self.assert_packet_checksums_valid(p)
6286 except:
6287 self.logger.error(ppp("Unexpected or invalid packet:", p))
6288 raise
6289
6290 # from service back to client (no translation)
6291 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6292 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6293 TCP(sport=local_port, dport=12346))
6294 self.pg0.add_stream(p)
6295 self.pg_enable_capture(self.pg_interfaces)
6296 self.pg_start()
6297 capture = self.pg1.get_capture(1)
6298 p = capture[0]
6299 try:
6300 ip = p[IP]
6301 tcp = p[TCP]
6302 self.assertEqual(ip.src, self.pg0.remote_ip4)
6303 self.assertEqual(tcp.sport, local_port)
6304 self.assert_packet_checksums_valid(p)
6305 except:
6306 self.logger.error(ppp("Unexpected or invalid packet:", p))
6307 raise
6308
Matus Fabian235a47e2018-06-25 16:42:36 -07006309 def test_output_feature(self):
6310 """ NAT44 interface output feature (in2out postrouting) """
Filip Vargaf4749ca2019-04-25 14:55:32 +02006311 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian235a47e2018-06-25 16:42:36 -07006312 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02006313 self.vapi.nat44_interface_add_del_feature(
6314 sw_if_index=self.pg0.sw_if_index,
6315 is_add=1)
6316 self.vapi.nat44_interface_add_del_output_feature(
6317 is_add=1,
6318 sw_if_index=self.pg1.sw_if_index)
Matus Fabian235a47e2018-06-25 16:42:36 -07006319
6320 # in2out
6321 pkts = self.create_stream_in(self.pg0, self.pg1)
6322 self.pg0.add_stream(pkts)
6323 self.pg_enable_capture(self.pg_interfaces)
6324 self.pg_start()
6325 capture = self.pg1.get_capture(len(pkts))
6326 self.verify_capture_out(capture)
6327
6328 # out2in
6329 pkts = self.create_stream_out(self.pg1)
6330 self.pg1.add_stream(pkts)
6331 self.pg_enable_capture(self.pg_interfaces)
6332 self.pg_start()
6333 capture = self.pg0.get_capture(len(pkts))
6334 self.verify_capture_in(capture, self.pg0)
6335
Matus Fabian8008d7c2018-07-09 01:34:20 -07006336 def test_multiple_vrf(self):
6337 """ Multiple VRF setup """
6338 external_addr = '1.2.3.4'
6339 external_port = 80
6340 local_port = 8080
6341 port = 0
6342
Filip Vargaf4749ca2019-04-25 14:55:32 +02006343 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07006344 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006345 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006346 self.vapi.nat44_interface_add_del_feature(
6347 sw_if_index=self.pg0.sw_if_index,
6348 is_add=1)
6349 self.vapi.nat44_interface_add_del_feature(
6350 sw_if_index=self.pg0.sw_if_index,
6351 flags=flags, is_add=1)
6352 self.vapi.nat44_interface_add_del_output_feature(
6353 is_add=1,
6354 sw_if_index=self.pg1.sw_if_index)
6355 self.vapi.nat44_interface_add_del_feature(
6356 sw_if_index=self.pg5.sw_if_index,
6357 is_add=1)
6358 self.vapi.nat44_interface_add_del_feature(
6359 sw_if_index=self.pg5.sw_if_index,
6360 flags=flags, is_add=1)
6361 self.vapi.nat44_interface_add_del_feature(
6362 sw_if_index=self.pg6.sw_if_index,
6363 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006364 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabian8008d7c2018-07-09 01:34:20 -07006365 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6366 local_port, external_port, vrf_id=1,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006367 proto=IP_PROTOS.tcp, flags=flags)
Matus Fabian8008d7c2018-07-09 01:34:20 -07006368 self.nat44_add_static_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +02006369 self.pg0.remote_ip4,
6370 external_sw_if_index=self.pg0.sw_if_index,
6371 local_port=local_port,
6372 vrf_id=0,
6373 external_port=external_port,
6374 proto=IP_PROTOS.tcp,
6375 flags=flags
Filip Vargadd1e3e72019-04-15 18:52:43 +02006376 )
Matus Fabian8008d7c2018-07-09 01:34:20 -07006377
6378 # from client to service (both VRF1)
6379 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6380 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6381 TCP(sport=12345, dport=external_port))
6382 self.pg6.add_stream(p)
6383 self.pg_enable_capture(self.pg_interfaces)
6384 self.pg_start()
6385 capture = self.pg5.get_capture(1)
6386 p = capture[0]
6387 try:
6388 ip = p[IP]
6389 tcp = p[TCP]
6390 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6391 self.assertEqual(tcp.dport, local_port)
6392 self.assert_packet_checksums_valid(p)
6393 except:
6394 self.logger.error(ppp("Unexpected or invalid packet:", p))
6395 raise
6396
6397 # from service back to client (both VRF1)
6398 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6399 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6400 TCP(sport=local_port, dport=12345))
6401 self.pg5.add_stream(p)
6402 self.pg_enable_capture(self.pg_interfaces)
6403 self.pg_start()
6404 capture = self.pg6.get_capture(1)
6405 p = capture[0]
6406 try:
6407 ip = p[IP]
6408 tcp = p[TCP]
6409 self.assertEqual(ip.src, external_addr)
6410 self.assertEqual(tcp.sport, external_port)
6411 self.assert_packet_checksums_valid(p)
6412 except:
6413 self.logger.error(ppp("Unexpected or invalid packet:", p))
6414 raise
6415
6416 # dynamic NAT from VRF1 to VRF0 (output-feature)
6417 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6418 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6419 TCP(sport=2345, dport=22))
6420 self.pg5.add_stream(p)
6421 self.pg_enable_capture(self.pg_interfaces)
6422 self.pg_start()
6423 capture = self.pg1.get_capture(1)
6424 p = capture[0]
6425 try:
6426 ip = p[IP]
6427 tcp = p[TCP]
6428 self.assertEqual(ip.src, self.nat_addr)
6429 self.assertNotEqual(tcp.sport, 2345)
6430 self.assert_packet_checksums_valid(p)
6431 port = tcp.sport
6432 except:
6433 self.logger.error(ppp("Unexpected or invalid packet:", p))
6434 raise
6435
6436 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6437 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6438 TCP(sport=22, dport=port))
6439 self.pg1.add_stream(p)
6440 self.pg_enable_capture(self.pg_interfaces)
6441 self.pg_start()
6442 capture = self.pg5.get_capture(1)
6443 p = capture[0]
6444 try:
6445 ip = p[IP]
6446 tcp = p[TCP]
6447 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6448 self.assertEqual(tcp.dport, 2345)
6449 self.assert_packet_checksums_valid(p)
6450 except:
6451 self.logger.error(ppp("Unexpected or invalid packet:", p))
6452 raise
6453
6454 # from client VRF1 to service VRF0
6455 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6456 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6457 TCP(sport=12346, dport=external_port))
6458 self.pg6.add_stream(p)
6459 self.pg_enable_capture(self.pg_interfaces)
6460 self.pg_start()
6461 capture = self.pg0.get_capture(1)
6462 p = capture[0]
6463 try:
6464 ip = p[IP]
6465 tcp = p[TCP]
6466 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6467 self.assertEqual(tcp.dport, local_port)
6468 self.assert_packet_checksums_valid(p)
6469 except:
6470 self.logger.error(ppp("Unexpected or invalid packet:", p))
6471 raise
6472
6473 # from service VRF0 back to client VRF1
6474 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6475 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6476 TCP(sport=local_port, dport=12346))
6477 self.pg0.add_stream(p)
6478 self.pg_enable_capture(self.pg_interfaces)
6479 self.pg_start()
6480 capture = self.pg6.get_capture(1)
6481 p = capture[0]
6482 try:
6483 ip = p[IP]
6484 tcp = p[TCP]
6485 self.assertEqual(ip.src, self.pg0.local_ip4)
6486 self.assertEqual(tcp.sport, external_port)
6487 self.assert_packet_checksums_valid(p)
6488 except:
6489 self.logger.error(ppp("Unexpected or invalid packet:", p))
6490 raise
6491
6492 # from client VRF0 to service VRF1
6493 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6494 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6495 TCP(sport=12347, dport=external_port))
6496 self.pg0.add_stream(p)
6497 self.pg_enable_capture(self.pg_interfaces)
6498 self.pg_start()
6499 capture = self.pg5.get_capture(1)
6500 p = capture[0]
6501 try:
6502 ip = p[IP]
6503 tcp = p[TCP]
6504 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6505 self.assertEqual(tcp.dport, local_port)
6506 self.assert_packet_checksums_valid(p)
6507 except:
6508 self.logger.error(ppp("Unexpected or invalid packet:", p))
6509 raise
6510
6511 # from service VRF1 back to client VRF0
6512 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6513 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6514 TCP(sport=local_port, dport=12347))
6515 self.pg5.add_stream(p)
6516 self.pg_enable_capture(self.pg_interfaces)
6517 self.pg_start()
6518 capture = self.pg0.get_capture(1)
6519 p = capture[0]
6520 try:
6521 ip = p[IP]
6522 tcp = p[TCP]
6523 self.assertEqual(ip.src, external_addr)
6524 self.assertEqual(tcp.sport, external_port)
6525 self.assert_packet_checksums_valid(p)
6526 except:
6527 self.logger.error(ppp("Unexpected or invalid packet:", p))
6528 raise
6529
6530 # from client to server (both VRF1, no translation)
6531 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6532 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6533 TCP(sport=12348, dport=local_port))
6534 self.pg6.add_stream(p)
6535 self.pg_enable_capture(self.pg_interfaces)
6536 self.pg_start()
6537 capture = self.pg5.get_capture(1)
6538 p = capture[0]
6539 try:
6540 ip = p[IP]
6541 tcp = p[TCP]
6542 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6543 self.assertEqual(tcp.dport, local_port)
6544 self.assert_packet_checksums_valid(p)
6545 except:
6546 self.logger.error(ppp("Unexpected or invalid packet:", p))
6547 raise
6548
6549 # from server back to client (both VRF1, no translation)
6550 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6551 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6552 TCP(sport=local_port, dport=12348))
6553 self.pg5.add_stream(p)
6554 self.pg_enable_capture(self.pg_interfaces)
6555 self.pg_start()
6556 capture = self.pg6.get_capture(1)
6557 p = capture[0]
6558 try:
6559 ip = p[IP]
6560 tcp = p[TCP]
6561 self.assertEqual(ip.src, self.pg5.remote_ip4)
6562 self.assertEqual(tcp.sport, local_port)
6563 self.assert_packet_checksums_valid(p)
6564 except:
6565 self.logger.error(ppp("Unexpected or invalid packet:", p))
6566 raise
6567
6568 # from client VRF1 to server VRF0 (no translation)
6569 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6570 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6571 TCP(sport=local_port, dport=12349))
6572 self.pg0.add_stream(p)
6573 self.pg_enable_capture(self.pg_interfaces)
6574 self.pg_start()
6575 capture = self.pg6.get_capture(1)
6576 p = capture[0]
6577 try:
6578 ip = p[IP]
6579 tcp = p[TCP]
6580 self.assertEqual(ip.src, self.pg0.remote_ip4)
6581 self.assertEqual(tcp.sport, local_port)
6582 self.assert_packet_checksums_valid(p)
6583 except:
6584 self.logger.error(ppp("Unexpected or invalid packet:", p))
6585 raise
6586
6587 # from server VRF0 back to client VRF1 (no translation)
6588 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6589 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6590 TCP(sport=local_port, dport=12349))
6591 self.pg0.add_stream(p)
6592 self.pg_enable_capture(self.pg_interfaces)
6593 self.pg_start()
6594 capture = self.pg6.get_capture(1)
6595 p = capture[0]
6596 try:
6597 ip = p[IP]
6598 tcp = p[TCP]
6599 self.assertEqual(ip.src, self.pg0.remote_ip4)
6600 self.assertEqual(tcp.sport, local_port)
6601 self.assert_packet_checksums_valid(p)
6602 except:
6603 self.logger.error(ppp("Unexpected or invalid packet:", p))
6604 raise
6605
6606 # from client VRF0 to server VRF1 (no translation)
6607 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6608 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6609 TCP(sport=12344, dport=local_port))
6610 self.pg0.add_stream(p)
6611 self.pg_enable_capture(self.pg_interfaces)
6612 self.pg_start()
6613 capture = self.pg5.get_capture(1)
6614 p = capture[0]
6615 try:
6616 ip = p[IP]
6617 tcp = p[TCP]
6618 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6619 self.assertEqual(tcp.dport, local_port)
6620 self.assert_packet_checksums_valid(p)
6621 except:
6622 self.logger.error(ppp("Unexpected or invalid packet:", p))
6623 raise
6624
6625 # from server VRF1 back to client VRF0 (no translation)
6626 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6627 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6628 TCP(sport=local_port, dport=12344))
6629 self.pg5.add_stream(p)
6630 self.pg_enable_capture(self.pg_interfaces)
6631 self.pg_start()
6632 capture = self.pg0.get_capture(1)
6633 p = capture[0]
6634 try:
6635 ip = p[IP]
6636 tcp = p[TCP]
6637 self.assertEqual(ip.src, self.pg5.remote_ip4)
6638 self.assertEqual(tcp.sport, local_port)
6639 self.assert_packet_checksums_valid(p)
6640 except:
6641 self.logger.error(ppp("Unexpected or invalid packet:", p))
6642 raise
6643
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006644 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006645 def test_session_timeout(self):
6646 """ NAT44 session timeouts """
6647 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006648 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006649 self.vapi.nat44_interface_add_del_feature(
6650 sw_if_index=self.pg0.sw_if_index,
6651 flags=flags, is_add=1)
6652 self.vapi.nat44_interface_add_del_feature(
6653 sw_if_index=self.pg1.sw_if_index,
6654 is_add=1)
6655 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6656 tcp_transitory=240, icmp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006657
6658 max_sessions = 1000
6659 pkts = []
6660 for i in range(0, max_sessions):
6661 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6662 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6663 IP(src=src, dst=self.pg1.remote_ip4) /
6664 ICMP(id=1025, type='echo-request'))
6665 pkts.append(p)
6666 self.pg0.add_stream(pkts)
6667 self.pg_enable_capture(self.pg_interfaces)
6668 self.pg_start()
6669 self.pg1.get_capture(max_sessions)
6670
6671 sleep(10)
6672
6673 pkts = []
6674 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006675 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006676 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6677 IP(src=src, dst=self.pg1.remote_ip4) /
6678 ICMP(id=1026, type='echo-request'))
6679 pkts.append(p)
6680 self.pg0.add_stream(pkts)
6681 self.pg_enable_capture(self.pg_interfaces)
6682 self.pg_start()
6683 self.pg1.get_capture(max_sessions)
6684
6685 nsessions = 0
6686 users = self.vapi.nat44_user_dump()
6687 for user in users:
6688 nsessions = nsessions + user.nsessions
6689 self.assertLess(nsessions, 2 * max_sessions)
6690
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006691 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006692 def test_session_rst_timeout(self):
6693 """ NAT44 session RST timeouts """
6694 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006695 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006696 self.vapi.nat44_interface_add_del_feature(
6697 sw_if_index=self.pg0.sw_if_index,
6698 flags=flags, is_add=1)
6699 self.vapi.nat44_interface_add_del_feature(
6700 sw_if_index=self.pg1.sw_if_index,
6701 is_add=1)
6702 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6703 tcp_transitory=5, icmp=60)
Matus Fabian15e8e682018-11-21 04:53:10 -08006704
Matus Fabian15e8e682018-11-21 04:53:10 -08006705 self.initiate_tcp_session(self.pg0, self.pg1)
6706 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6707 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6708 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6709 flags="R"))
6710 self.pg0.add_stream(p)
6711 self.pg_enable_capture(self.pg_interfaces)
6712 self.pg_start()
6713 self.pg1.get_capture(1)
6714
Matus Fabian15e8e682018-11-21 04:53:10 -08006715 sleep(6)
6716
6717 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6718 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6719 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6720 flags="S"))
6721 self.pg0.add_stream(p)
6722 self.pg_enable_capture(self.pg_interfaces)
6723 self.pg_start()
6724 self.pg1.get_capture(1)
6725
6726 nsessions = 0
6727 users = self.vapi.nat44_user_dump()
6728 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006729 self.assertEqual(str(users[0].ip_address),
6730 self.pg0.remote_ip4)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006731 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006732
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006733 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006734 def test_session_limit_per_user(self):
6735 """ Maximum sessions per user limit """
6736 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006737 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006738 self.vapi.nat44_interface_add_del_feature(
6739 sw_if_index=self.pg0.sw_if_index,
6740 flags=flags, is_add=1)
6741 self.vapi.nat44_interface_add_del_feature(
6742 sw_if_index=self.pg1.sw_if_index,
6743 is_add=1)
Matus Fabian878c6462018-08-23 00:33:35 -07006744 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6745 src_address=self.pg2.local_ip4n,
6746 path_mtu=512,
6747 template_interval=10)
Filip Vargaf4749ca2019-04-25 14:55:32 +02006748 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
6749 tcp_transitory=240, icmp=60)
Matus Fabian878c6462018-08-23 00:33:35 -07006750
6751 # get maximum number of translations per user
6752 nat44_config = self.vapi.nat_show_config()
6753
6754 pkts = []
6755 for port in range(0, nat44_config.max_translations_per_user):
6756 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6757 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6758 UDP(sport=1025 + port, dport=1025 + port))
6759 pkts.append(p)
6760
6761 self.pg0.add_stream(pkts)
6762 self.pg_enable_capture(self.pg_interfaces)
6763 self.pg_start()
6764 capture = self.pg1.get_capture(len(pkts))
6765
Ole Troane1ade682019-03-04 23:55:43 +01006766 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02006767 src_port=self.ipfix_src_port,
6768 enable=1)
Matus Fabian878c6462018-08-23 00:33:35 -07006769
6770 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6771 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6772 UDP(sport=3001, dport=3002))
6773 self.pg0.add_stream(p)
6774 self.pg_enable_capture(self.pg_interfaces)
6775 self.pg_start()
6776 capture = self.pg1.assert_nothing_captured()
6777
6778 # verify IPFIX logging
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04006779 self.vapi.ipfix_flush()
Matus Fabian878c6462018-08-23 00:33:35 -07006780 sleep(1)
6781 capture = self.pg2.get_capture(10)
6782 ipfix = IPFIXDecoder()
6783 # first load template
6784 for p in capture:
6785 self.assertTrue(p.haslayer(IPFIX))
6786 if p.haslayer(Template):
6787 ipfix.add_template(p.getlayer(Template))
6788 # verify events in data set
6789 for p in capture:
6790 if p.haslayer(Data):
6791 data = ipfix.decode_data_set(p.getlayer(Set))
6792 self.verify_ipfix_max_entries_per_user(
6793 data,
6794 nat44_config.max_translations_per_user,
6795 self.pg0.remote_ip4n)
6796
Matus Fabian8fdc0152018-09-24 04:41:28 -07006797 sleep(6)
6798 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6799 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6800 UDP(sport=3001, dport=3002))
6801 self.pg0.add_stream(p)
6802 self.pg_enable_capture(self.pg_interfaces)
6803 self.pg_start()
6804 self.pg1.get_capture(1)
6805
Matus Fabianad1f3e12018-11-28 21:26:34 -08006806 def test_syslog_sess(self):
6807 """ Test syslog session creation and deletion """
Paul Vinciguerrab7658202019-05-17 09:48:15 -04006808 self.vapi.syslog_set_filter(
6809 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006810 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006811 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006812 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006813 self.vapi.nat44_interface_add_del_feature(
6814 sw_if_index=self.pg0.sw_if_index,
6815 flags=flags, is_add=1)
6816 self.vapi.nat44_interface_add_del_feature(
6817 sw_if_index=self.pg1.sw_if_index,
6818 is_add=1)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006819
6820 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6821 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6822 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6823 self.pg0.add_stream(p)
6824 self.pg_enable_capture(self.pg_interfaces)
6825 self.pg_start()
6826 capture = self.pg1.get_capture(1)
6827 self.tcp_port_out = capture[0][TCP].sport
6828 capture = self.pg2.get_capture(1)
6829 self.verify_syslog_sess(capture[0][Raw].load)
6830
6831 self.pg_enable_capture(self.pg_interfaces)
6832 self.pg_start()
6833 self.nat44_add_address(self.nat_addr, is_add=0)
6834 capture = self.pg2.get_capture(1)
6835 self.verify_syslog_sess(capture[0][Raw].load, False)
6836
Matus Fabiande886752016-12-07 03:38:19 -08006837 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006838 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006839 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006840 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006841 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006842
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07006843 def show_commands_at_teardown(self):
6844 self.logger.info(self.vapi.cli("show nat44 addresses"))
6845 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6846 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6847 self.logger.info(self.vapi.cli("show nat44 interface address"))
6848 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6849 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6850 self.logger.info(self.vapi.cli("show nat timeouts"))
6851
Matus Fabianeea28d72017-01-13 04:15:54 -08006852
Juraj Slobodacba69362017-12-19 02:09:32 +01006853class TestNAT44Out2InDPO(MethodHolder):
6854 """ NAT44 Test Cases using out2in DPO """
6855
6856 @classmethod
6857 def setUpConstants(cls):
6858 super(TestNAT44Out2InDPO, cls).setUpConstants()
6859 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6860
6861 @classmethod
6862 def setUpClass(cls):
6863 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006864 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006865
6866 try:
6867 cls.tcp_port_in = 6303
6868 cls.tcp_port_out = 6303
6869 cls.udp_port_in = 6304
6870 cls.udp_port_out = 6304
6871 cls.icmp_id_in = 6305
6872 cls.icmp_id_out = 6305
6873 cls.nat_addr = '10.0.0.3'
Juraj Slobodacba69362017-12-19 02:09:32 +01006874 cls.dst_ip4 = '192.168.70.1'
6875
6876 cls.create_pg_interfaces(range(2))
6877
6878 cls.pg0.admin_up()
6879 cls.pg0.config_ip4()
6880 cls.pg0.resolve_arp()
6881
6882 cls.pg1.admin_up()
6883 cls.pg1.config_ip6()
6884 cls.pg1.resolve_ndp()
6885
Neale Ranns097fa662018-05-01 05:17:55 -07006886 r1 = VppIpRoute(cls, "::", 0,
6887 [VppRoutePath(cls.pg1.remote_ip6,
6888 cls.pg1.sw_if_index)],
6889 register=False)
6890 r1.add_vpp_config()
Juraj Slobodacba69362017-12-19 02:09:32 +01006891
6892 except Exception:
6893 super(TestNAT44Out2InDPO, cls).tearDownClass()
6894 raise
6895
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006896 @classmethod
6897 def tearDownClass(cls):
6898 super(TestNAT44Out2InDPO, cls).tearDownClass()
6899
Juraj Slobodacba69362017-12-19 02:09:32 +01006900 def configure_xlat(self):
6901 self.dst_ip6_pfx = '1:2:3::'
6902 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6903 self.dst_ip6_pfx)
6904 self.dst_ip6_pfx_len = 96
6905 self.src_ip6_pfx = '4:5:6::'
6906 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6907 self.src_ip6_pfx)
6908 self.src_ip6_pfx_len = 96
6909 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6910 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006911 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006912
Ole Troanffba3c32018-11-22 12:53:00 +01006913 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006914 def test_464xlat_ce(self):
6915 """ Test 464XLAT CE with NAT44 """
6916
Matus Fabian69ce30d2018-08-22 01:27:10 -07006917 nat_config = self.vapi.nat_show_config()
6918 self.assertEqual(1, nat_config.out2in_dpo)
6919
Juraj Slobodacba69362017-12-19 02:09:32 +01006920 self.configure_xlat()
6921
Filip Vargadd1e3e72019-04-15 18:52:43 +02006922 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006923 self.vapi.nat44_interface_add_del_feature(
6924 sw_if_index=self.pg0.sw_if_index,
6925 flags=flags, is_add=1)
6926 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
6927 last_ip_address=self.nat_addr_n,
6928 vrf_id=0xFFFFFFFF, is_add=1)
Juraj Slobodacba69362017-12-19 02:09:32 +01006929
6930 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6931 self.dst_ip6_pfx_len)
6932 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6933 self.src_ip6_pfx_len)
6934
6935 try:
6936 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6937 self.pg0.add_stream(pkts)
6938 self.pg_enable_capture(self.pg_interfaces)
6939 self.pg_start()
6940 capture = self.pg1.get_capture(len(pkts))
6941 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6942 dst_ip=out_src_ip6)
6943
6944 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6945 out_dst_ip6)
6946 self.pg1.add_stream(pkts)
6947 self.pg_enable_capture(self.pg_interfaces)
6948 self.pg_start()
6949 capture = self.pg0.get_capture(len(pkts))
6950 self.verify_capture_in(capture, self.pg0)
6951 finally:
Filip Vargaf4749ca2019-04-25 14:55:32 +02006952 self.vapi.nat44_interface_add_del_feature(
6953 sw_if_index=self.pg0.sw_if_index,
6954 flags=flags)
6955 self.vapi.nat44_add_del_address_range(
6956 first_ip_address=self.nat_addr_n,
6957 last_ip_address=self.nat_addr_n,
6958 vrf_id=0xFFFFFFFF)
Juraj Slobodacba69362017-12-19 02:09:32 +01006959
Ole Troanffba3c32018-11-22 12:53:00 +01006960 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006961 def test_464xlat_ce_no_nat(self):
6962 """ Test 464XLAT CE without NAT44 """
6963
6964 self.configure_xlat()
6965
6966 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6967 self.dst_ip6_pfx_len)
6968 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6969 self.src_ip6_pfx_len)
6970
6971 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6972 self.pg0.add_stream(pkts)
6973 self.pg_enable_capture(self.pg_interfaces)
6974 self.pg_start()
6975 capture = self.pg1.get_capture(len(pkts))
6976 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6977 nat_ip=out_dst_ip6, same_port=True)
6978
6979 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6980 self.pg1.add_stream(pkts)
6981 self.pg_enable_capture(self.pg_interfaces)
6982 self.pg_start()
6983 capture = self.pg0.get_capture(len(pkts))
6984 self.verify_capture_in(capture, self.pg0)
6985
6986
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006987class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006988 """ Deterministic NAT Test Cases """
6989
6990 @classmethod
6991 def setUpConstants(cls):
6992 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006993 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006994
6995 @classmethod
6996 def setUpClass(cls):
6997 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006998 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006999
7000 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07007001 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07007002 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07007003 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07007004 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07007005 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07007006 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07007007
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007008 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08007009 cls.interfaces = list(cls.pg_interfaces)
7010
7011 for i in cls.interfaces:
7012 i.admin_up()
7013 i.config_ip4()
7014 i.resolve_arp()
7015
Martin Gálik977c1cb2017-03-30 23:21:51 -07007016 cls.pg0.generate_remote_hosts(2)
7017 cls.pg0.configure_ipv4_neighbors()
7018
Matus Fabian066f0342017-02-10 03:48:01 -08007019 except Exception:
7020 super(TestDeterministicNAT, cls).tearDownClass()
7021 raise
7022
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007023 @classmethod
7024 def tearDownClass(cls):
7025 super(TestDeterministicNAT, cls).tearDownClass()
7026
Martin Gálik977c1cb2017-03-30 23:21:51 -07007027 def create_stream_in(self, in_if, out_if, ttl=64):
7028 """
7029 Create packet stream for inside network
7030
7031 :param in_if: Inside interface
7032 :param out_if: Outside interface
7033 :param ttl: TTL of generated packets
7034 """
7035 pkts = []
7036 # TCP
7037 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7038 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007039 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007040 pkts.append(p)
7041
7042 # UDP
7043 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7044 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007045 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007046 pkts.append(p)
7047
7048 # ICMP
7049 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7050 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7051 ICMP(id=self.icmp_id_in, type='echo-request'))
7052 pkts.append(p)
7053
7054 return pkts
7055
7056 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7057 """
7058 Create packet stream for outside network
7059
7060 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07007061 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007062 :param ttl: TTL of generated packets
7063 """
7064 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007065 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07007066 pkts = []
7067 # TCP
7068 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7069 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007070 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007071 pkts.append(p)
7072
7073 # UDP
7074 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7075 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007076 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007077 pkts.append(p)
7078
7079 # ICMP
7080 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7081 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7082 ICMP(id=self.icmp_external_id, type='echo-reply'))
7083 pkts.append(p)
7084
7085 return pkts
7086
Matus Fabian05ca4a32018-09-04 23:45:13 -07007087 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07007088 """
7089 Verify captured packets on outside network
7090
7091 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07007092 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07007093 :param same_port: Source port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007094 """
7095 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007096 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07007097 for packet in capture:
7098 try:
7099 self.assertEqual(packet[IP].src, nat_ip)
7100 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07007101 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007102 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07007103 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007104 else:
7105 self.icmp_external_id = packet[ICMP].id
7106 except:
7107 self.logger.error(ppp("Unexpected or invalid packet "
7108 "(outside network):", packet))
7109 raise
7110
Matus Fabian066f0342017-02-10 03:48:01 -08007111 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007112 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08007113 in_addr = '172.16.255.0'
7114 out_addr = '172.17.255.50'
7115 in_addr_t = '172.16.255.20'
Matus Fabian066f0342017-02-10 03:48:01 -08007116 in_plen = 24
7117 out_plen = 32
7118
Matus Fabian2ba92e32017-08-21 07:05:03 -07007119 nat_config = self.vapi.nat_show_config()
7120 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08007121
Filip Vargaf4749ca2019-04-25 14:55:32 +02007122 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7123 in_plen=in_plen, out_addr=out_addr,
7124 out_plen=out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08007125
Filip Vargadd1e3e72019-04-15 18:52:43 +02007126 rep1 = self.vapi.nat_det_forward(in_addr_t)
7127 self.assertEqual(str(rep1.out_addr), out_addr)
7128 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7129
7130 self.assertEqual(str(rep2.in_addr), in_addr_t)
Matus Fabian066f0342017-02-10 03:48:01 -08007131
Matus Fabian2ba92e32017-08-21 07:05:03 -07007132 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007133 self.assertEqual(len(deterministic_mappings), 1)
7134 dsm = deterministic_mappings[0]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007135 self.assertEqual(in_addr, str(dsm.in_addr))
Martin17a75cb2017-03-08 05:53:20 -08007136 self.assertEqual(in_plen, dsm.in_plen)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007137 self.assertEqual(out_addr, str(dsm.out_addr))
Martin17a75cb2017-03-08 05:53:20 -08007138 self.assertEqual(out_plen, dsm.out_plen)
7139
Matus Fabian2ba92e32017-08-21 07:05:03 -07007140 self.clear_nat_det()
7141 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07007142 self.assertEqual(len(deterministic_mappings), 0)
7143
Matus Fabian6a0946f2017-04-12 03:36:13 -07007144 def test_set_timeouts(self):
7145 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07007146 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07007147
Filip Vargaf4749ca2019-04-25 14:55:32 +02007148 self.vapi.nat_set_timeouts(
7149 udp=timeouts_before.udp + 10,
7150 tcp_established=timeouts_before.tcp_established + 10,
7151 tcp_transitory=timeouts_before.tcp_transitory + 10,
7152 icmp=timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07007153
Matus Fabian878c6462018-08-23 00:33:35 -07007154 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07007155
7156 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7157 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7158 self.assertNotEqual(timeouts_before.tcp_established,
7159 timeouts_after.tcp_established)
7160 self.assertNotEqual(timeouts_before.tcp_transitory,
7161 timeouts_after.tcp_transitory)
7162
Martin Gálik977c1cb2017-03-30 23:21:51 -07007163 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007164 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07007165
7166 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07007167
Filip Vargaf4749ca2019-04-25 14:55:32 +02007168 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7169 in_plen=32,
7170 out_addr=socket.inet_aton(nat_ip),
7171 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007172
7173 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007174 self.vapi.nat44_interface_add_del_feature(
7175 sw_if_index=self.pg0.sw_if_index,
7176 flags=flags, is_add=1)
7177 self.vapi.nat44_interface_add_del_feature(
7178 sw_if_index=self.pg1.sw_if_index,
7179 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007180
7181 # in2out
7182 pkts = self.create_stream_in(self.pg0, self.pg1)
7183 self.pg0.add_stream(pkts)
7184 self.pg_enable_capture(self.pg_interfaces)
7185 self.pg_start()
7186 capture = self.pg1.get_capture(len(pkts))
7187 self.verify_capture_out(capture, nat_ip)
7188
7189 # out2in
7190 pkts = self.create_stream_out(self.pg1, nat_ip)
7191 self.pg1.add_stream(pkts)
7192 self.pg_enable_capture(self.pg_interfaces)
7193 self.pg_start()
7194 capture = self.pg0.get_capture(len(pkts))
7195 self.verify_capture_in(capture, self.pg0)
7196
Martin Gálik9806eae2017-04-25 01:25:08 -07007197 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07007198 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07007199 self.assertEqual(len(sessions), 3)
7200
7201 # TCP session
7202 s = sessions[0]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007203 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007204 self.assertEqual(s.in_port, self.tcp_port_in)
7205 self.assertEqual(s.out_port, self.tcp_port_out)
7206 self.assertEqual(s.ext_port, self.tcp_external_port)
7207
7208 # UDP session
7209 s = sessions[1]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007210 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007211 self.assertEqual(s.in_port, self.udp_port_in)
7212 self.assertEqual(s.out_port, self.udp_port_out)
7213 self.assertEqual(s.ext_port, self.udp_external_port)
7214
7215 # ICMP session
7216 s = sessions[2]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007217 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007218 self.assertEqual(s.in_port, self.icmp_id_in)
7219 self.assertEqual(s.out_port, self.icmp_external_id)
7220
Martin Gálik977c1cb2017-03-30 23:21:51 -07007221 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007222 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07007223
7224 nat_ip = "10.0.0.10"
7225 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07007226 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07007227
7228 host0 = self.pg0.remote_hosts[0]
7229 host1 = self.pg0.remote_hosts[1]
7230
Filip Vargaf4749ca2019-04-25 14:55:32 +02007231 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4n, in_plen=24,
7232 out_addr=socket.inet_aton(nat_ip),
7233 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007234 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007235 self.vapi.nat44_interface_add_del_feature(
7236 sw_if_index=self.pg0.sw_if_index,
7237 flags=flags, is_add=1)
7238 self.vapi.nat44_interface_add_del_feature(
7239 sw_if_index=self.pg1.sw_if_index,
7240 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007241
7242 # host0 to out
7243 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7244 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007245 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007246 self.pg0.add_stream(p)
7247 self.pg_enable_capture(self.pg_interfaces)
7248 self.pg_start()
7249 capture = self.pg1.get_capture(1)
7250 p = capture[0]
7251 try:
7252 ip = p[IP]
7253 tcp = p[TCP]
7254 self.assertEqual(ip.src, nat_ip)
7255 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007256 self.assertEqual(tcp.dport, external_port)
7257 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007258 except:
7259 self.logger.error(ppp("Unexpected or invalid packet:", p))
7260 raise
7261
7262 # host1 to out
7263 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7264 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007265 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007266 self.pg0.add_stream(p)
7267 self.pg_enable_capture(self.pg_interfaces)
7268 self.pg_start()
7269 capture = self.pg1.get_capture(1)
7270 p = capture[0]
7271 try:
7272 ip = p[IP]
7273 tcp = p[TCP]
7274 self.assertEqual(ip.src, nat_ip)
7275 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007276 self.assertEqual(tcp.dport, external_port)
7277 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007278 except:
7279 self.logger.error(ppp("Unexpected or invalid packet:", p))
7280 raise
7281
Matus Fabian2ba92e32017-08-21 07:05:03 -07007282 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007283 self.assertEqual(1, len(dms))
7284 self.assertEqual(2, dms[0].ses_num)
7285
7286 # out to host0
7287 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7288 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007289 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007290 self.pg1.add_stream(p)
7291 self.pg_enable_capture(self.pg_interfaces)
7292 self.pg_start()
7293 capture = self.pg0.get_capture(1)
7294 p = capture[0]
7295 try:
7296 ip = p[IP]
7297 tcp = p[TCP]
7298 self.assertEqual(ip.src, self.pg1.remote_ip4)
7299 self.assertEqual(ip.dst, host0.ip4)
7300 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07007301 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007302 except:
7303 self.logger.error(ppp("Unexpected or invalid packet:", p))
7304 raise
7305
7306 # out to host1
7307 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7308 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007309 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007310 self.pg1.add_stream(p)
7311 self.pg_enable_capture(self.pg_interfaces)
7312 self.pg_start()
7313 capture = self.pg0.get_capture(1)
7314 p = capture[0]
7315 try:
7316 ip = p[IP]
7317 tcp = p[TCP]
7318 self.assertEqual(ip.src, self.pg1.remote_ip4)
7319 self.assertEqual(ip.dst, host1.ip4)
7320 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07007321 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007322 except:
7323 self.logger.error(ppp("Unexpected or invalid packet", p))
7324 raise
7325
Martin Gálik6bc8c642017-04-19 01:12:27 -07007326 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07007327 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7328 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07007329 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07007330 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07007331 dms = self.vapi.nat_det_map_dump()
7332 self.assertEqual(dms[0].ses_num, 1)
7333
7334 self.vapi.nat_det_close_session_in(host0.ip4n,
7335 port_in,
7336 self.pg1.remote_ip4n,
7337 external_port)
7338 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07007339 self.assertEqual(dms[0].ses_num, 0)
7340
Martin Gálik977c1cb2017-03-30 23:21:51 -07007341 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007342 """ Deterministic NAT TCP session close from inside network """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007343 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7344 in_plen=32,
7345 out_addr=socket.inet_aton(self.nat_addr),
7346 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007347 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007348 self.vapi.nat44_interface_add_del_feature(
7349 sw_if_index=self.pg0.sw_if_index,
7350 flags=flags, is_add=1)
7351 self.vapi.nat44_interface_add_del_feature(
7352 sw_if_index=self.pg1.sw_if_index,
7353 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007354
7355 self.initiate_tcp_session(self.pg0, self.pg1)
7356
7357 # close the session from inside
7358 try:
7359 # FIN packet in -> out
7360 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7361 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007362 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007363 flags="F"))
7364 self.pg0.add_stream(p)
7365 self.pg_enable_capture(self.pg_interfaces)
7366 self.pg_start()
7367 self.pg1.get_capture(1)
7368
7369 pkts = []
7370
7371 # ACK packet out -> in
7372 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007373 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007374 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007375 flags="A"))
7376 pkts.append(p)
7377
7378 # FIN packet out -> in
7379 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007380 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007381 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007382 flags="F"))
7383 pkts.append(p)
7384
7385 self.pg1.add_stream(pkts)
7386 self.pg_enable_capture(self.pg_interfaces)
7387 self.pg_start()
7388 self.pg0.get_capture(2)
7389
7390 # ACK packet in -> out
7391 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7392 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007393 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007394 flags="A"))
7395 self.pg0.add_stream(p)
7396 self.pg_enable_capture(self.pg_interfaces)
7397 self.pg_start()
7398 self.pg1.get_capture(1)
7399
Matus Fabian2ba92e32017-08-21 07:05:03 -07007400 # Check if deterministic NAT44 closed the session
7401 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007402 self.assertEqual(0, dms[0].ses_num)
7403 except:
7404 self.logger.error("TCP session termination failed")
7405 raise
7406
7407 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007408 """ Deterministic NAT TCP session close from outside network """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007409 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7410 in_plen=32,
7411 out_addr=socket.inet_aton(self.nat_addr),
7412 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007413 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007414 self.vapi.nat44_interface_add_del_feature(
7415 sw_if_index=self.pg0.sw_if_index,
7416 flags=flags, is_add=1)
7417 self.vapi.nat44_interface_add_del_feature(
7418 sw_if_index=self.pg1.sw_if_index,
7419 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007420
7421 self.initiate_tcp_session(self.pg0, self.pg1)
7422
7423 # close the session from outside
7424 try:
7425 # FIN packet out -> in
7426 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007427 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007428 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007429 flags="F"))
7430 self.pg1.add_stream(p)
7431 self.pg_enable_capture(self.pg_interfaces)
7432 self.pg_start()
7433 self.pg0.get_capture(1)
7434
7435 pkts = []
7436
7437 # ACK packet in -> out
7438 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7439 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007440 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007441 flags="A"))
7442 pkts.append(p)
7443
7444 # ACK packet in -> out
7445 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7446 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007447 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007448 flags="F"))
7449 pkts.append(p)
7450
7451 self.pg0.add_stream(pkts)
7452 self.pg_enable_capture(self.pg_interfaces)
7453 self.pg_start()
7454 self.pg1.get_capture(2)
7455
7456 # ACK packet out -> in
7457 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007458 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007459 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007460 flags="A"))
7461 self.pg1.add_stream(p)
7462 self.pg_enable_capture(self.pg_interfaces)
7463 self.pg_start()
7464 self.pg0.get_capture(1)
7465
Matus Fabian2ba92e32017-08-21 07:05:03 -07007466 # Check if deterministic NAT44 closed the session
7467 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007468 self.assertEqual(0, dms[0].ses_num)
7469 except:
7470 self.logger.error("TCP session termination failed")
7471 raise
7472
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007473 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007474 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007475 """ Deterministic NAT session timeouts """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007476 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7477 in_plen=32,
7478 out_addr=socket.inet_aton(self.nat_addr),
7479 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007480 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007481 self.vapi.nat44_interface_add_del_feature(
7482 sw_if_index=self.pg0.sw_if_index,
7483 flags=flags, is_add=1)
7484 self.vapi.nat44_interface_add_del_feature(
7485 sw_if_index=self.pg1.sw_if_index,
7486 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007487
7488 self.initiate_tcp_session(self.pg0, self.pg1)
Filip Vargaf4749ca2019-04-25 14:55:32 +02007489 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7490 icmp=5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007491 pkts = self.create_stream_in(self.pg0, self.pg1)
7492 self.pg0.add_stream(pkts)
7493 self.pg_enable_capture(self.pg_interfaces)
7494 self.pg_start()
7495 capture = self.pg1.get_capture(len(pkts))
7496 sleep(15)
7497
Matus Fabian2ba92e32017-08-21 07:05:03 -07007498 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007499 self.assertEqual(0, dms[0].ses_num)
7500
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007501 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007502 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007503 """ Deterministic NAT maximum sessions per user limit """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007504 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7505 in_plen=32,
7506 out_addr=socket.inet_aton(self.nat_addr),
7507 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007508 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007509 self.vapi.nat44_interface_add_del_feature(
7510 sw_if_index=self.pg0.sw_if_index,
7511 flags=flags, is_add=1)
7512 self.vapi.nat44_interface_add_del_feature(
7513 sw_if_index=self.pg1.sw_if_index,
7514 is_add=1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007515 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7516 src_address=self.pg2.local_ip4n,
7517 path_mtu=512,
7518 template_interval=10)
Filip Vargaf4749ca2019-04-25 14:55:32 +02007519 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7520 enable=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007521
7522 pkts = []
7523 for port in range(1025, 2025):
7524 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7525 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7526 UDP(sport=port, dport=port))
7527 pkts.append(p)
7528
7529 self.pg0.add_stream(pkts)
7530 self.pg_enable_capture(self.pg_interfaces)
7531 self.pg_start()
7532 capture = self.pg1.get_capture(len(pkts))
7533
7534 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7535 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007536 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007537 self.pg0.add_stream(p)
7538 self.pg_enable_capture(self.pg_interfaces)
7539 self.pg_start()
7540 capture = self.pg1.assert_nothing_captured()
7541
Martin Gálikf7e655d2017-04-27 02:13:26 -07007542 # verify ICMP error packet
7543 capture = self.pg0.get_capture(1)
7544 p = capture[0]
7545 self.assertTrue(p.haslayer(ICMP))
7546 icmp = p[ICMP]
7547 self.assertEqual(icmp.type, 3)
7548 self.assertEqual(icmp.code, 1)
7549 self.assertTrue(icmp.haslayer(IPerror))
7550 inner_ip = icmp[IPerror]
7551 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7552 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7553
Matus Fabian2ba92e32017-08-21 07:05:03 -07007554 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007555
7556 self.assertEqual(1000, dms[0].ses_num)
7557
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007558 # verify IPFIX logging
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04007559 self.vapi.ipfix_flush()
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007560 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007561 capture = self.pg2.get_capture(2)
7562 ipfix = IPFIXDecoder()
7563 # first load template
7564 for p in capture:
7565 self.assertTrue(p.haslayer(IPFIX))
7566 if p.haslayer(Template):
7567 ipfix.add_template(p.getlayer(Template))
7568 # verify events in data set
7569 for p in capture:
7570 if p.haslayer(Data):
7571 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007572 self.verify_ipfix_max_entries_per_user(data,
7573 1000,
7574 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007575
Matus Fabian2ba92e32017-08-21 07:05:03 -07007576 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007577 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007578 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007579 """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007580 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7581 enable=0)
7582 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7583 tcp_transitory=240, icmp=60)
Matus Fabian2ba92e32017-08-21 07:05:03 -07007584 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007585 for dsm in deterministic_mappings:
Filip Vargaf4749ca2019-04-25 14:55:32 +02007586 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7587 in_plen=dsm.in_plen,
7588 out_addr=dsm.out_addr,
7589 out_plen=dsm.out_plen)
Martin17a75cb2017-03-08 05:53:20 -08007590
Matus Fabian2ba92e32017-08-21 07:05:03 -07007591 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007592 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +02007593 self.vapi.nat44_interface_add_del_feature(
7594 sw_if_index=intf.sw_if_index,
7595 flags=intf.flags)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007596
Matus Fabian066f0342017-02-10 03:48:01 -08007597 def tearDown(self):
7598 super(TestDeterministicNAT, self).tearDown()
7599 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007600 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007601
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07007602 def show_commands_at_teardown(self):
7603 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7604 self.logger.info(self.vapi.cli("show nat timeouts"))
7605 self.logger.info(
7606 self.vapi.cli("show nat44 deterministic mappings"))
7607 self.logger.info(
7608 self.vapi.cli("show nat44 deterministic sessions"))
7609
Matus Fabian06596c52017-06-06 04:53:28 -07007610
7611class TestNAT64(MethodHolder):
7612 """ NAT64 Test Cases """
7613
7614 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007615 def setUpConstants(cls):
7616 super(TestNAT64, cls).setUpConstants()
7617 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7618 "nat64 st hash buckets 256", "}"])
7619
7620 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007621 def setUpClass(cls):
7622 super(TestNAT64, cls).setUpClass()
7623
7624 try:
7625 cls.tcp_port_in = 6303
7626 cls.tcp_port_out = 6303
7627 cls.udp_port_in = 6304
7628 cls.udp_port_out = 6304
7629 cls.icmp_id_in = 6305
7630 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007631 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007632 cls.nat_addr = '10.0.0.3'
7633 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007634 cls.vrf1_id = 10
7635 cls.vrf1_nat_addr = '10.0.10.3'
Matus Fabiana431ad12018-01-04 04:03:14 -08007636 cls.ipfix_src_port = 4739
7637 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007638
Juraj Slobodac746a152018-07-09 02:36:37 +02007639 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007640 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007641 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007642 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7643
Ole Troan9a475372019-03-05 16:58:24 +01007644 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7645 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007646
Matus Fabian029f3d22017-06-15 02:28:50 -07007647 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7648
7649 cls.pg0.generate_remote_hosts(2)
7650
Matus Fabian06596c52017-06-06 04:53:28 -07007651 for i in cls.ip6_interfaces:
7652 i.admin_up()
7653 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007654 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007655
7656 for i in cls.ip4_interfaces:
7657 i.admin_up()
7658 i.config_ip4()
7659 i.resolve_arp()
7660
Matus Fabian36ea2d62017-10-24 04:13:49 -07007661 cls.pg3.admin_up()
7662 cls.pg3.config_ip4()
7663 cls.pg3.resolve_arp()
7664 cls.pg3.config_ip6()
7665 cls.pg3.configure_ipv6_neighbors()
7666
Juraj Slobodac746a152018-07-09 02:36:37 +02007667 cls.pg5.admin_up()
7668 cls.pg5.config_ip6()
7669
Matus Fabian06596c52017-06-06 04:53:28 -07007670 except Exception:
7671 super(TestNAT64, cls).tearDownClass()
7672 raise
7673
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007674 @classmethod
7675 def tearDownClass(cls):
7676 super(TestNAT64, cls).tearDownClass()
7677
Juraj Slobodac746a152018-07-09 02:36:37 +02007678 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7679 """ NAT64 inside interface handles Neighbor Advertisement """
7680
Filip Vargadd1e3e72019-04-15 18:52:43 +02007681 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007682 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7683 sw_if_index=self.pg5.sw_if_index)
Juraj Slobodac746a152018-07-09 02:36:37 +02007684
7685 # Try to send ping
7686 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7687 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7688 ICMPv6EchoRequest())
7689 pkts = [ping]
7690 self.pg5.add_stream(pkts)
7691 self.pg_enable_capture(self.pg_interfaces)
7692 self.pg_start()
7693
7694 # Wait for Neighbor Solicitation
7695 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007696 packet = capture[0]
7697 try:
7698 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007699 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007700 tgt = packet[ICMPv6ND_NS].tgt
7701 except:
7702 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7703 raise
7704
7705 # Send Neighbor Advertisement
7706 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7707 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7708 ICMPv6ND_NA(tgt=tgt) /
7709 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7710 pkts = [p]
7711 self.pg5.add_stream(pkts)
7712 self.pg_enable_capture(self.pg_interfaces)
7713 self.pg_start()
7714
7715 # Try to send ping again
7716 pkts = [ping]
7717 self.pg5.add_stream(pkts)
7718 self.pg_enable_capture(self.pg_interfaces)
7719 self.pg_start()
7720
7721 # Wait for ping reply
7722 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007723 packet = capture[0]
7724 try:
7725 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7726 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007727 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007728 except:
7729 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7730 raise
7731
Matus Fabian06596c52017-06-06 04:53:28 -07007732 def test_pool(self):
7733 """ Add/delete address to NAT64 pool """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007734 nat_addr = '1.2.3.4'
Matus Fabian06596c52017-06-06 04:53:28 -07007735
Filip Vargaf4749ca2019-04-25 14:55:32 +02007736 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7737 end_addr=nat_addr,
7738 vrf_id=0xFFFFFFFF, is_add=1)
Matus Fabian06596c52017-06-06 04:53:28 -07007739
7740 addresses = self.vapi.nat64_pool_addr_dump()
7741 self.assertEqual(len(addresses), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007742 self.assertEqual(str(addresses[0].address), nat_addr)
Matus Fabian06596c52017-06-06 04:53:28 -07007743
Filip Vargaf4749ca2019-04-25 14:55:32 +02007744 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7745 end_addr=nat_addr,
7746 vrf_id=0xFFFFFFFF, is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007747
7748 addresses = self.vapi.nat64_pool_addr_dump()
7749 self.assertEqual(len(addresses), 0)
7750
7751 def test_interface(self):
7752 """ Enable/disable NAT64 feature on the interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007753 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007754 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7755 sw_if_index=self.pg0.sw_if_index)
7756 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7757 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007758
7759 interfaces = self.vapi.nat64_interface_dump()
7760 self.assertEqual(len(interfaces), 2)
7761 pg0_found = False
7762 pg1_found = False
7763 for intf in interfaces:
7764 if intf.sw_if_index == self.pg0.sw_if_index:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007765 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
Matus Fabian06596c52017-06-06 04:53:28 -07007766 pg0_found = True
7767 elif intf.sw_if_index == self.pg1.sw_if_index:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007768 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
Matus Fabian06596c52017-06-06 04:53:28 -07007769 pg1_found = True
7770 self.assertTrue(pg0_found)
7771 self.assertTrue(pg1_found)
7772
7773 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007774 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007775 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007776 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007777
Filip Vargaf4749ca2019-04-25 14:55:32 +02007778 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7779 sw_if_index=self.pg0.sw_if_index)
7780 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7781 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007782
7783 interfaces = self.vapi.nat64_interface_dump()
7784 self.assertEqual(len(interfaces), 0)
7785
7786 def test_static_bib(self):
7787 """ Add/delete static BIB entry """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007788 in_addr = '2001:db8:85a3::8a2e:370:7334'
7789 out_addr = '10.1.1.3'
Matus Fabian06596c52017-06-06 04:53:28 -07007790 in_port = 1234
7791 out_port = 5678
7792 proto = IP_PROTOS.tcp
7793
Filip Vargaf4749ca2019-04-25 14:55:32 +02007794 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7795 i_port=in_port, o_port=out_port,
7796 proto=proto, vrf_id=0, is_add=1)
7797 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
Matus Fabian06596c52017-06-06 04:53:28 -07007798 static_bib_num = 0
7799 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007800 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07007801 static_bib_num += 1
Filip Vargadd1e3e72019-04-15 18:52:43 +02007802 self.assertEqual(str(bibe.i_addr), in_addr)
7803 self.assertEqual(str(bibe.o_addr), out_addr)
Matus Fabian06596c52017-06-06 04:53:28 -07007804 self.assertEqual(bibe.i_port, in_port)
7805 self.assertEqual(bibe.o_port, out_port)
7806 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007807 bibs = self.statistics.get_counter('/nat64/total-bibs')
7808 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007809
Filip Vargaf4749ca2019-04-25 14:55:32 +02007810 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7811 i_port=in_port, o_port=out_port,
7812 proto=proto, vrf_id=0, is_add=0)
7813 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
Matus Fabian06596c52017-06-06 04:53:28 -07007814 static_bib_num = 0
7815 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007816 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07007817 static_bib_num += 1
7818 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007819 bibs = self.statistics.get_counter('/nat64/total-bibs')
7820 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007821
7822 def test_set_timeouts(self):
7823 """ Set NAT64 timeouts """
7824 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007825 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007826 self.assertEqual(timeouts.udp, 300)
7827 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007828 self.assertEqual(timeouts.tcp_transitory, 240)
7829 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007830
7831 # set and verify custom values
Filip Vargaf4749ca2019-04-25 14:55:32 +02007832 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7833 tcp_transitory=250, icmp=30)
Matus Fabian878c6462018-08-23 00:33:35 -07007834 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007835 self.assertEqual(timeouts.udp, 200)
7836 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007837 self.assertEqual(timeouts.tcp_transitory, 250)
7838 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007839
7840 def test_dynamic(self):
7841 """ NAT64 dynamic translation test """
7842 self.tcp_port_in = 6303
7843 self.udp_port_in = 6304
7844 self.icmp_id_in = 6305
7845
7846 ses_num_start = self.nat64_get_ses_num()
7847
Filip Vargaf4749ca2019-04-25 14:55:32 +02007848 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7849 end_addr=self.nat_addr,
7850 vrf_id=0xFFFFFFFF,
7851 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007852 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007853 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7854 sw_if_index=self.pg0.sw_if_index)
7855 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7856 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007857
7858 # in2out
Ole Troan233e4682019-05-16 15:01:34 +02007859 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7860 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7861 icmpn = self.statistics.get_err_counter(
7862 '/err/nat64-in2out/ICMP packets')
7863 totaln = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08007864 '/err/nat64-in2out/good in2out packets processed')
7865
Matus Fabian06596c52017-06-06 04:53:28 -07007866 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7867 self.pg0.add_stream(pkts)
7868 self.pg_enable_capture(self.pg_interfaces)
7869 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007870 capture = self.pg1.get_capture(len(pkts))
7871 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007872 dst_ip=self.pg1.remote_ip4)
7873
Ole Troan233e4682019-05-16 15:01:34 +02007874 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08007875 self.assertEqual(err - tcpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02007876 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08007877 self.assertEqual(err - udpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02007878 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08007879 self.assertEqual(err - icmpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02007880 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08007881 '/err/nat64-in2out/good in2out packets processed')
7882 self.assertEqual(err - totaln, 3)
7883
Matus Fabian06596c52017-06-06 04:53:28 -07007884 # out2in
Ole Troan233e4682019-05-16 15:01:34 +02007885 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
7886 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
7887 icmpn = self.statistics.get_err_counter(
7888 '/err/nat64-out2in/ICMP packets')
7889 totaln = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08007890 '/err/nat64-out2in/good out2in packets processed')
7891
Matus Fabian06596c52017-06-06 04:53:28 -07007892 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7893 self.pg1.add_stream(pkts)
7894 self.pg_enable_capture(self.pg_interfaces)
7895 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007896 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007897 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7898 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7899
Ole Troan233e4682019-05-16 15:01:34 +02007900 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08007901 self.assertEqual(err - tcpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02007902 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08007903 self.assertEqual(err - udpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02007904 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
Matus Fabiana5e73762018-12-14 01:55:16 -08007905 self.assertEqual(err - icmpn, 1)
Ole Troan233e4682019-05-16 15:01:34 +02007906 err = self.statistics.get_err_counter(
Matus Fabiana5e73762018-12-14 01:55:16 -08007907 '/err/nat64-out2in/good out2in packets processed')
7908 self.assertEqual(err - totaln, 3)
7909
Matus Fabianfd0d5082018-12-18 01:08:51 -08007910 bibs = self.statistics.get_counter('/nat64/total-bibs')
7911 self.assertEqual(bibs[0][0], 3)
7912 sessions = self.statistics.get_counter('/nat64/total-sessions')
7913 self.assertEqual(sessions[0][0], 3)
7914
Matus Fabian06596c52017-06-06 04:53:28 -07007915 # in2out
7916 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7917 self.pg0.add_stream(pkts)
7918 self.pg_enable_capture(self.pg_interfaces)
7919 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007920 capture = self.pg1.get_capture(len(pkts))
7921 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007922 dst_ip=self.pg1.remote_ip4)
7923
7924 # out2in
7925 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7926 self.pg1.add_stream(pkts)
7927 self.pg_enable_capture(self.pg_interfaces)
7928 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007929 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007930 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7931
7932 ses_num_end = self.nat64_get_ses_num()
7933
7934 self.assertEqual(ses_num_end - ses_num_start, 3)
7935
Matus Fabian029f3d22017-06-15 02:28:50 -07007936 # tenant with specific VRF
Filip Vargaf4749ca2019-04-25 14:55:32 +02007937 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
7938 end_addr=self.vrf1_nat_addr,
7939 vrf_id=self.vrf1_id, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007940 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007941 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7942 sw_if_index=self.pg2.sw_if_index)
Matus Fabian029f3d22017-06-15 02:28:50 -07007943
7944 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7945 self.pg2.add_stream(pkts)
7946 self.pg_enable_capture(self.pg_interfaces)
7947 self.pg_start()
7948 capture = self.pg1.get_capture(len(pkts))
7949 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7950 dst_ip=self.pg1.remote_ip4)
7951
7952 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7953 self.pg1.add_stream(pkts)
7954 self.pg_enable_capture(self.pg_interfaces)
7955 self.pg_start()
7956 capture = self.pg2.get_capture(len(pkts))
7957 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7958
Matus Fabian06596c52017-06-06 04:53:28 -07007959 def test_static(self):
7960 """ NAT64 static translation test """
7961 self.tcp_port_in = 60303
7962 self.udp_port_in = 60304
7963 self.icmp_id_in = 60305
7964 self.tcp_port_out = 60303
7965 self.udp_port_out = 60304
7966 self.icmp_id_out = 60305
7967
7968 ses_num_start = self.nat64_get_ses_num()
7969
Filip Vargaf4749ca2019-04-25 14:55:32 +02007970 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7971 end_addr=self.nat_addr,
7972 vrf_id=0xFFFFFFFF,
7973 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007974 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007975 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7976 sw_if_index=self.pg0.sw_if_index)
7977 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7978 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007979
Filip Vargaf4749ca2019-04-25 14:55:32 +02007980 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
7981 o_addr=self.nat_addr,
7982 i_port=self.tcp_port_in,
7983 o_port=self.tcp_port_out,
7984 proto=IP_PROTOS.tcp, vrf_id=0,
7985 is_add=1)
7986 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
7987 o_addr=self.nat_addr,
7988 i_port=self.udp_port_in,
7989 o_port=self.udp_port_out,
7990 proto=IP_PROTOS.udp, vrf_id=0,
7991 is_add=1)
7992 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
7993 o_addr=self.nat_addr,
7994 i_port=self.icmp_id_in,
7995 o_port=self.icmp_id_out,
7996 proto=IP_PROTOS.icmp, vrf_id=0,
7997 is_add=1)
Matus Fabian06596c52017-06-06 04:53:28 -07007998
7999 # in2out
8000 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8001 self.pg0.add_stream(pkts)
8002 self.pg_enable_capture(self.pg_interfaces)
8003 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07008004 capture = self.pg1.get_capture(len(pkts))
8005 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07008006 dst_ip=self.pg1.remote_ip4, same_port=True)
8007
8008 # out2in
8009 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8010 self.pg1.add_stream(pkts)
8011 self.pg_enable_capture(self.pg_interfaces)
8012 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07008013 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07008014 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8015 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8016
8017 ses_num_end = self.nat64_get_ses_num()
8018
8019 self.assertEqual(ses_num_end - ses_num_start, 3)
8020
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008021 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07008022 def test_session_timeout(self):
8023 """ NAT64 session timeout """
8024 self.icmp_id_in = 1234
Filip Vargaf4749ca2019-04-25 14:55:32 +02008025 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8026 end_addr=self.nat_addr,
8027 vrf_id=0xFFFFFFFF,
8028 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008029 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008030 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8031 sw_if_index=self.pg0.sw_if_index)
8032 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8033 sw_if_index=self.pg1.sw_if_index)
8034 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8035 tcp_transitory=5,
8036 icmp=5)
Matus Fabian06596c52017-06-06 04:53:28 -07008037
8038 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8039 self.pg0.add_stream(pkts)
8040 self.pg_enable_capture(self.pg_interfaces)
8041 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07008042 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07008043
8044 ses_num_before_timeout = self.nat64_get_ses_num()
8045
8046 sleep(15)
8047
Matus Fabian8fed4242018-08-14 05:14:55 -07008048 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07008049 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07008050 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07008051
Matus Fabian732036d2017-06-08 05:24:28 -07008052 def test_icmp_error(self):
8053 """ NAT64 ICMP Error message translation """
8054 self.tcp_port_in = 6303
8055 self.udp_port_in = 6304
8056 self.icmp_id_in = 6305
8057
Filip Vargaf4749ca2019-04-25 14:55:32 +02008058 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8059 end_addr=self.nat_addr,
8060 vrf_id=0xFFFFFFFF,
8061 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008062 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008063 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8064 sw_if_index=self.pg0.sw_if_index)
8065 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8066 sw_if_index=self.pg1.sw_if_index)
Matus Fabian732036d2017-06-08 05:24:28 -07008067
8068 # send some packets to create sessions
8069 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8070 self.pg0.add_stream(pkts)
8071 self.pg_enable_capture(self.pg_interfaces)
8072 self.pg_start()
8073 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07008074 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07008075 nat_ip=self.nat_addr,
8076 dst_ip=self.pg1.remote_ip4)
8077
8078 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8079 self.pg1.add_stream(pkts)
8080 self.pg_enable_capture(self.pg_interfaces)
8081 self.pg_start()
8082 capture_ip6 = self.pg0.get_capture(len(pkts))
8083 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8084 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8085 self.pg0.remote_ip6)
8086
8087 # in2out
8088 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8089 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8090 ICMPv6DestUnreach(code=1) /
8091 packet[IPv6] for packet in capture_ip6]
8092 self.pg0.add_stream(pkts)
8093 self.pg_enable_capture(self.pg_interfaces)
8094 self.pg_start()
8095 capture = self.pg1.get_capture(len(pkts))
8096 for packet in capture:
8097 try:
8098 self.assertEqual(packet[IP].src, self.nat_addr)
8099 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8100 self.assertEqual(packet[ICMP].type, 3)
8101 self.assertEqual(packet[ICMP].code, 13)
8102 inner = packet[IPerror]
8103 self.assertEqual(inner.src, self.pg1.remote_ip4)
8104 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02008105 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07008106 if inner.haslayer(TCPerror):
8107 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8108 elif inner.haslayer(UDPerror):
8109 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8110 else:
8111 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8112 except:
8113 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8114 raise
8115
8116 # out2in
8117 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8118 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8119 ICMP(type=3, code=13) /
8120 packet[IP] for packet in capture_ip4]
8121 self.pg1.add_stream(pkts)
8122 self.pg_enable_capture(self.pg_interfaces)
8123 self.pg_start()
8124 capture = self.pg0.get_capture(len(pkts))
8125 for packet in capture:
8126 try:
8127 self.assertEqual(packet[IPv6].src, ip.src)
8128 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8129 icmp = packet[ICMPv6DestUnreach]
8130 self.assertEqual(icmp.code, 1)
8131 inner = icmp[IPerror6]
8132 self.assertEqual(inner.src, self.pg0.remote_ip6)
8133 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02008134 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07008135 if inner.haslayer(TCPerror):
8136 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8137 elif inner.haslayer(UDPerror):
8138 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8139 else:
8140 self.assertEqual(inner[ICMPv6EchoRequest].id,
8141 self.icmp_id_in)
8142 except:
8143 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8144 raise
8145
Matus Fabian029f3d22017-06-15 02:28:50 -07008146 def test_hairpinning(self):
8147 """ NAT64 hairpinning """
8148
8149 client = self.pg0.remote_hosts[0]
8150 server = self.pg0.remote_hosts[1]
8151 server_tcp_in_port = 22
8152 server_tcp_out_port = 4022
8153 server_udp_in_port = 23
8154 server_udp_out_port = 4023
8155 client_tcp_in_port = 1234
8156 client_udp_in_port = 1235
8157 client_tcp_out_port = 0
8158 client_udp_out_port = 0
8159 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8160 nat_addr_ip6 = ip.src
8161
Filip Vargaf4749ca2019-04-25 14:55:32 +02008162 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8163 end_addr=self.nat_addr,
8164 vrf_id=0xFFFFFFFF,
8165 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008166 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008167 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8168 sw_if_index=self.pg0.sw_if_index)
8169 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8170 sw_if_index=self.pg1.sw_if_index)
Matus Fabian029f3d22017-06-15 02:28:50 -07008171
Filip Vargaf4749ca2019-04-25 14:55:32 +02008172 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8173 o_addr=self.nat_addr,
8174 i_port=server_tcp_in_port,
8175 o_port=server_tcp_out_port,
8176 proto=IP_PROTOS.tcp, vrf_id=0,
8177 is_add=1)
8178 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8179 o_addr=self.nat_addr,
8180 i_port=server_udp_in_port,
8181 o_port=server_udp_out_port,
8182 proto=IP_PROTOS.udp, vrf_id=0,
8183 is_add=1)
Matus Fabian029f3d22017-06-15 02:28:50 -07008184
8185 # client to server
8186 pkts = []
8187 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8188 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8189 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8190 pkts.append(p)
8191 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8192 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8193 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8194 pkts.append(p)
8195 self.pg0.add_stream(pkts)
8196 self.pg_enable_capture(self.pg_interfaces)
8197 self.pg_start()
8198 capture = self.pg0.get_capture(len(pkts))
8199 for packet in capture:
8200 try:
8201 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8202 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008203 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07008204 if packet.haslayer(TCP):
8205 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8206 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008207 client_tcp_out_port = packet[TCP].sport
8208 else:
8209 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8210 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008211 client_udp_out_port = packet[UDP].sport
8212 except:
8213 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8214 raise
8215
8216 # server to client
8217 pkts = []
8218 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8219 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8220 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8221 pkts.append(p)
8222 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8223 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8224 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8225 pkts.append(p)
8226 self.pg0.add_stream(pkts)
8227 self.pg_enable_capture(self.pg_interfaces)
8228 self.pg_start()
8229 capture = self.pg0.get_capture(len(pkts))
8230 for packet in capture:
8231 try:
8232 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8233 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008234 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07008235 if packet.haslayer(TCP):
8236 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8237 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008238 else:
8239 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8240 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008241 except:
8242 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8243 raise
8244
8245 # ICMP error
8246 pkts = []
8247 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8248 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8249 ICMPv6DestUnreach(code=1) /
8250 packet[IPv6] for packet in capture]
8251 self.pg0.add_stream(pkts)
8252 self.pg_enable_capture(self.pg_interfaces)
8253 self.pg_start()
8254 capture = self.pg0.get_capture(len(pkts))
8255 for packet in capture:
8256 try:
8257 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8258 self.assertEqual(packet[IPv6].dst, server.ip6)
8259 icmp = packet[ICMPv6DestUnreach]
8260 self.assertEqual(icmp.code, 1)
8261 inner = icmp[IPerror6]
8262 self.assertEqual(inner.src, server.ip6)
8263 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008264 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07008265 if inner.haslayer(TCPerror):
8266 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8267 self.assertEqual(inner[TCPerror].dport,
8268 client_tcp_out_port)
8269 else:
8270 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8271 self.assertEqual(inner[UDPerror].dport,
8272 client_udp_out_port)
8273 except:
8274 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8275 raise
8276
Matus Fabian428dc912017-06-21 06:15:18 -07008277 def test_prefix(self):
8278 """ NAT64 Network-Specific Prefix """
8279
Filip Vargaf4749ca2019-04-25 14:55:32 +02008280 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8281 end_addr=self.nat_addr,
8282 vrf_id=0xFFFFFFFF,
8283 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008284 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008285 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8286 sw_if_index=self.pg0.sw_if_index)
8287 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8288 sw_if_index=self.pg1.sw_if_index)
8289 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8290 end_addr=self.vrf1_nat_addr,
8291 vrf_id=self.vrf1_id, is_add=1)
8292 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8293 sw_if_index=self.pg2.sw_if_index)
Matus Fabian428dc912017-06-21 06:15:18 -07008294
8295 # Add global prefix
8296 global_pref64 = "2001:db8::"
Matus Fabian428dc912017-06-21 06:15:18 -07008297 global_pref64_len = 32
Filip Vargadd1e3e72019-04-15 18:52:43 +02008298 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
Filip Vargaf4749ca2019-04-25 14:55:32 +02008299 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8300 is_add=1)
Matus Fabian428dc912017-06-21 06:15:18 -07008301
8302 prefix = self.vapi.nat64_prefix_dump()
8303 self.assertEqual(len(prefix), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008304 self.assertEqual(prefix[0].prefix,
8305 IPv6Network(unicode(global_pref64_str)))
Matus Fabian428dc912017-06-21 06:15:18 -07008306 self.assertEqual(prefix[0].vrf_id, 0)
8307
8308 # Add tenant specific prefix
8309 vrf1_pref64 = "2001:db8:122:300::"
Matus Fabian428dc912017-06-21 06:15:18 -07008310 vrf1_pref64_len = 56
Filip Vargadd1e3e72019-04-15 18:52:43 +02008311 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
Filip Vargaf4749ca2019-04-25 14:55:32 +02008312 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8313 vrf_id=self.vrf1_id, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008314
Matus Fabian428dc912017-06-21 06:15:18 -07008315 prefix = self.vapi.nat64_prefix_dump()
8316 self.assertEqual(len(prefix), 2)
8317
8318 # Global prefix
8319 pkts = self.create_stream_in_ip6(self.pg0,
8320 self.pg1,
8321 pref=global_pref64,
8322 plen=global_pref64_len)
8323 self.pg0.add_stream(pkts)
8324 self.pg_enable_capture(self.pg_interfaces)
8325 self.pg_start()
8326 capture = self.pg1.get_capture(len(pkts))
8327 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8328 dst_ip=self.pg1.remote_ip4)
8329
8330 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8331 self.pg1.add_stream(pkts)
8332 self.pg_enable_capture(self.pg_interfaces)
8333 self.pg_start()
8334 capture = self.pg0.get_capture(len(pkts))
8335 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8336 global_pref64,
8337 global_pref64_len)
8338 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8339
8340 # Tenant specific prefix
8341 pkts = self.create_stream_in_ip6(self.pg2,
8342 self.pg1,
8343 pref=vrf1_pref64,
8344 plen=vrf1_pref64_len)
8345 self.pg2.add_stream(pkts)
8346 self.pg_enable_capture(self.pg_interfaces)
8347 self.pg_start()
8348 capture = self.pg1.get_capture(len(pkts))
8349 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8350 dst_ip=self.pg1.remote_ip4)
8351
8352 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8353 self.pg1.add_stream(pkts)
8354 self.pg_enable_capture(self.pg_interfaces)
8355 self.pg_start()
8356 capture = self.pg2.get_capture(len(pkts))
8357 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8358 vrf1_pref64,
8359 vrf1_pref64_len)
8360 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8361
Matus Fabianf8cd5812017-07-11 03:55:02 -07008362 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07008363 """ NAT64 translate packet with unknown protocol """
8364
Filip Vargaf4749ca2019-04-25 14:55:32 +02008365 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8366 end_addr=self.nat_addr,
8367 vrf_id=0xFFFFFFFF,
8368 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008369 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008370 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8371 sw_if_index=self.pg0.sw_if_index)
8372 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8373 sw_if_index=self.pg1.sw_if_index)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008374 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8375
8376 # in2out
8377 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8378 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8379 TCP(sport=self.tcp_port_in, dport=20))
8380 self.pg0.add_stream(p)
8381 self.pg_enable_capture(self.pg_interfaces)
8382 self.pg_start()
8383 p = self.pg1.get_capture(1)
8384
8385 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008386 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008387 GRE() /
8388 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8389 TCP(sport=1234, dport=1234))
8390 self.pg0.add_stream(p)
8391 self.pg_enable_capture(self.pg_interfaces)
8392 self.pg_start()
8393 p = self.pg1.get_capture(1)
8394 packet = p[0]
8395 try:
8396 self.assertEqual(packet[IP].src, self.nat_addr)
8397 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08008398 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02008399 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008400 except:
8401 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8402 raise
8403
8404 # out2in
8405 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8406 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8407 GRE() /
8408 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8409 TCP(sport=1234, dport=1234))
8410 self.pg1.add_stream(p)
8411 self.pg_enable_capture(self.pg_interfaces)
8412 self.pg_start()
8413 p = self.pg0.get_capture(1)
8414 packet = p[0]
8415 try:
8416 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008417 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8418 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008419 except:
8420 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8421 raise
8422
Matus Fabianf8cd5812017-07-11 03:55:02 -07008423 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07008424 """ NAT64 translate packet with unknown protocol - hairpinning """
8425
8426 client = self.pg0.remote_hosts[0]
8427 server = self.pg0.remote_hosts[1]
8428 server_tcp_in_port = 22
8429 server_tcp_out_port = 4022
8430 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07008431 client_tcp_out_port = 1235
8432 server_nat_ip = "10.0.0.100"
8433 client_nat_ip = "10.0.0.110"
Matus Fabianf8cd5812017-07-11 03:55:02 -07008434 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8435 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008436
Filip Vargaf4749ca2019-04-25 14:55:32 +02008437 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8438 end_addr=client_nat_ip,
8439 vrf_id=0xFFFFFFFF,
8440 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008441 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008442 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8443 sw_if_index=self.pg0.sw_if_index)
8444 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8445 sw_if_index=self.pg1.sw_if_index)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008446
Filip Vargaf4749ca2019-04-25 14:55:32 +02008447 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8448 o_addr=server_nat_ip,
8449 i_port=server_tcp_in_port,
8450 o_port=server_tcp_out_port,
8451 proto=IP_PROTOS.tcp, vrf_id=0,
8452 is_add=1)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008453
Filip Vargaf4749ca2019-04-25 14:55:32 +02008454 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8455 o_addr=server_nat_ip, i_port=0,
8456 o_port=0,
8457 proto=IP_PROTOS.gre, vrf_id=0,
8458 is_add=1)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008459
Filip Vargaf4749ca2019-04-25 14:55:32 +02008460 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8461 o_addr=client_nat_ip,
8462 i_port=client_tcp_in_port,
8463 o_port=client_tcp_out_port,
8464 proto=IP_PROTOS.tcp, vrf_id=0,
8465 is_add=1)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008466
Matus Fabian7968e6c2017-07-06 05:37:49 -07008467 # client to server
8468 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008469 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008470 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8471 self.pg0.add_stream(p)
8472 self.pg_enable_capture(self.pg_interfaces)
8473 self.pg_start()
8474 p = self.pg0.get_capture(1)
8475
8476 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008477 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008478 GRE() /
8479 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8480 TCP(sport=1234, dport=1234))
8481 self.pg0.add_stream(p)
8482 self.pg_enable_capture(self.pg_interfaces)
8483 self.pg_start()
8484 p = self.pg0.get_capture(1)
8485 packet = p[0]
8486 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07008487 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008488 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008489 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008490 except:
8491 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8492 raise
8493
8494 # server to client
8495 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008496 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008497 GRE() /
8498 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8499 TCP(sport=1234, dport=1234))
8500 self.pg0.add_stream(p)
8501 self.pg_enable_capture(self.pg_interfaces)
8502 self.pg_start()
8503 p = self.pg0.get_capture(1)
8504 packet = p[0]
8505 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07008506 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008507 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008508 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008509 except:
8510 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8511 raise
8512
Matus Fabian36ea2d62017-10-24 04:13:49 -07008513 def test_one_armed_nat64(self):
8514 """ One armed NAT64 """
8515 external_port = 0
8516 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8517 '64:ff9b::',
8518 96)
8519
Filip Vargaf4749ca2019-04-25 14:55:32 +02008520 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8521 end_addr=self.nat_addr,
8522 vrf_id=0xFFFFFFFF,
8523 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008524 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008525 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8526 sw_if_index=self.pg3.sw_if_index)
8527 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8528 sw_if_index=self.pg3.sw_if_index)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008529
8530 # in2out
8531 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8532 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8533 TCP(sport=12345, dport=80))
8534 self.pg3.add_stream(p)
8535 self.pg_enable_capture(self.pg_interfaces)
8536 self.pg_start()
8537 capture = self.pg3.get_capture(1)
8538 p = capture[0]
8539 try:
8540 ip = p[IP]
8541 tcp = p[TCP]
8542 self.assertEqual(ip.src, self.nat_addr)
8543 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8544 self.assertNotEqual(tcp.sport, 12345)
8545 external_port = tcp.sport
8546 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008547 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008548 except:
8549 self.logger.error(ppp("Unexpected or invalid packet:", p))
8550 raise
8551
8552 # out2in
8553 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8554 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8555 TCP(sport=80, dport=external_port))
8556 self.pg3.add_stream(p)
8557 self.pg_enable_capture(self.pg_interfaces)
8558 self.pg_start()
8559 capture = self.pg3.get_capture(1)
8560 p = capture[0]
8561 try:
8562 ip = p[IPv6]
8563 tcp = p[TCP]
8564 self.assertEqual(ip.src, remote_host_ip6)
8565 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8566 self.assertEqual(tcp.sport, 80)
8567 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008568 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008569 except:
8570 self.logger.error(ppp("Unexpected or invalid packet:", p))
8571 raise
8572
Matus Fabianefcd1e92017-08-15 06:59:19 -07008573 def test_frag_in_order(self):
8574 """ NAT64 translate fragments arriving in order """
8575 self.tcp_port_in = random.randint(1025, 65535)
8576
Filip Vargaf4749ca2019-04-25 14:55:32 +02008577 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8578 end_addr=self.nat_addr,
8579 vrf_id=0xFFFFFFFF,
8580 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008581 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008582 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8583 sw_if_index=self.pg0.sw_if_index)
8584 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8585 sw_if_index=self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008586
8587 reass = self.vapi.nat_reass_dump()
8588 reass_n_start = len(reass)
8589
8590 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008591 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008592 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8593 self.tcp_port_in, 20, data)
8594 self.pg0.add_stream(pkts)
8595 self.pg_enable_capture(self.pg_interfaces)
8596 self.pg_start()
8597 frags = self.pg1.get_capture(len(pkts))
8598 p = self.reass_frags_and_verify(frags,
8599 self.nat_addr,
8600 self.pg1.remote_ip4)
8601 self.assertEqual(p[TCP].dport, 20)
8602 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8603 self.tcp_port_out = p[TCP].sport
8604 self.assertEqual(data, p[Raw].load)
8605
8606 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008607 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008608 pkts = self.create_stream_frag(self.pg1,
8609 self.nat_addr,
8610 20,
8611 self.tcp_port_out,
8612 data)
8613 self.pg1.add_stream(pkts)
8614 self.pg_enable_capture(self.pg_interfaces)
8615 self.pg_start()
8616 frags = self.pg0.get_capture(len(pkts))
8617 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8618 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8619 self.assertEqual(p[TCP].sport, 20)
8620 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8621 self.assertEqual(data, p[Raw].load)
8622
8623 reass = self.vapi.nat_reass_dump()
8624 reass_n_end = len(reass)
8625
8626 self.assertEqual(reass_n_end - reass_n_start, 2)
8627
8628 def test_reass_hairpinning(self):
8629 """ NAT64 fragments hairpinning """
8630 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008631 server = self.pg0.remote_hosts[1]
8632 server_in_port = random.randint(1025, 65535)
8633 server_out_port = random.randint(1025, 65535)
8634 client_in_port = random.randint(1025, 65535)
8635 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8636 nat_addr_ip6 = ip.src
8637
Filip Vargaf4749ca2019-04-25 14:55:32 +02008638 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8639 end_addr=self.nat_addr,
8640 vrf_id=0xFFFFFFFF,
8641 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008642 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008643 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8644 sw_if_index=self.pg0.sw_if_index)
8645 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8646 sw_if_index=self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008647
8648 # add static BIB entry for server
Filip Vargaf4749ca2019-04-25 14:55:32 +02008649 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8650 o_addr=self.nat_addr,
8651 i_port=server_in_port,
8652 o_port=server_out_port,
8653 proto=IP_PROTOS.tcp, vrf_id=0,
8654 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008655
8656 # send packet from host to server
8657 pkts = self.create_stream_frag_ip6(self.pg0,
8658 self.nat_addr,
8659 client_in_port,
8660 server_out_port,
8661 data)
8662 self.pg0.add_stream(pkts)
8663 self.pg_enable_capture(self.pg_interfaces)
8664 self.pg_start()
8665 frags = self.pg0.get_capture(len(pkts))
8666 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8667 self.assertNotEqual(p[TCP].sport, client_in_port)
8668 self.assertEqual(p[TCP].dport, server_in_port)
8669 self.assertEqual(data, p[Raw].load)
8670
8671 def test_frag_out_of_order(self):
8672 """ NAT64 translate fragments arriving out of order """
8673 self.tcp_port_in = random.randint(1025, 65535)
8674
Filip Vargaf4749ca2019-04-25 14:55:32 +02008675 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8676 end_addr=self.nat_addr,
8677 vrf_id=0xFFFFFFFF,
8678 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008679 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008680 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8681 sw_if_index=self.pg0.sw_if_index)
8682 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8683 sw_if_index=self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008684
8685 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008686 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008687 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8688 self.tcp_port_in, 20, data)
8689 pkts.reverse()
8690 self.pg0.add_stream(pkts)
8691 self.pg_enable_capture(self.pg_interfaces)
8692 self.pg_start()
8693 frags = self.pg1.get_capture(len(pkts))
8694 p = self.reass_frags_and_verify(frags,
8695 self.nat_addr,
8696 self.pg1.remote_ip4)
8697 self.assertEqual(p[TCP].dport, 20)
8698 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8699 self.tcp_port_out = p[TCP].sport
8700 self.assertEqual(data, p[Raw].load)
8701
8702 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008703 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008704 pkts = self.create_stream_frag(self.pg1,
8705 self.nat_addr,
8706 20,
8707 self.tcp_port_out,
8708 data)
8709 pkts.reverse()
8710 self.pg1.add_stream(pkts)
8711 self.pg_enable_capture(self.pg_interfaces)
8712 self.pg_start()
8713 frags = self.pg0.get_capture(len(pkts))
8714 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8715 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8716 self.assertEqual(p[TCP].sport, 20)
8717 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8718 self.assertEqual(data, p[Raw].load)
8719
Matus Fabian0938dcf2017-11-08 01:59:38 -08008720 def test_interface_addr(self):
8721 """ Acquire NAT64 pool addresses from interface """
Filip Vargaf4749ca2019-04-25 14:55:32 +02008722 self.vapi.nat64_add_del_interface_addr(
8723 is_add=1,
8724 sw_if_index=self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008725
8726 # no address in NAT64 pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008727 addresses = self.vapi.nat44_address_dump()
8728 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008729
8730 # configure interface address and check NAT64 address pool
8731 self.pg4.config_ip4()
8732 addresses = self.vapi.nat64_pool_addr_dump()
8733 self.assertEqual(len(addresses), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008734
8735 self.assertEqual(str(addresses[0].address),
8736 self.pg4.local_ip4)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008737
8738 # remove interface address and check NAT64 address pool
8739 self.pg4.unconfig_ip4()
8740 addresses = self.vapi.nat64_pool_addr_dump()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008741 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008742
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008743 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008744 def test_ipfix_max_bibs_sessions(self):
8745 """ IPFIX logging maximum session and BIB entries exceeded """
8746 max_bibs = 1280
8747 max_sessions = 2560
8748 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8749 '64:ff9b::',
8750 96)
8751
Filip Vargaf4749ca2019-04-25 14:55:32 +02008752 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8753 end_addr=self.nat_addr,
8754 vrf_id=0xFFFFFFFF,
8755 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008756 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008757 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8758 sw_if_index=self.pg0.sw_if_index)
8759 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8760 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08008761
8762 pkts = []
8763 src = ""
8764 for i in range(0, max_bibs):
8765 src = "fd01:aa::%x" % (i)
8766 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8767 IPv6(src=src, dst=remote_host_ip6) /
8768 TCP(sport=12345, dport=80))
8769 pkts.append(p)
8770 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8771 IPv6(src=src, dst=remote_host_ip6) /
8772 TCP(sport=12345, dport=22))
8773 pkts.append(p)
8774 self.pg0.add_stream(pkts)
8775 self.pg_enable_capture(self.pg_interfaces)
8776 self.pg_start()
8777 self.pg1.get_capture(max_sessions)
8778
8779 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8780 src_address=self.pg3.local_ip4n,
8781 path_mtu=512,
8782 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008783 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02008784 src_port=self.ipfix_src_port,
8785 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008786
8787 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8788 IPv6(src=src, dst=remote_host_ip6) /
8789 TCP(sport=12345, dport=25))
8790 self.pg0.add_stream(p)
8791 self.pg_enable_capture(self.pg_interfaces)
8792 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008793 self.pg1.assert_nothing_captured()
8794 sleep(1)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04008795 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08008796 capture = self.pg3.get_capture(9)
8797 ipfix = IPFIXDecoder()
8798 # first load template
8799 for p in capture:
8800 self.assertTrue(p.haslayer(IPFIX))
8801 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8802 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8803 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8804 self.assertEqual(p[UDP].dport, 4739)
8805 self.assertEqual(p[IPFIX].observationDomainID,
8806 self.ipfix_domain_id)
8807 if p.haslayer(Template):
8808 ipfix.add_template(p.getlayer(Template))
8809 # verify events in data set
8810 for p in capture:
8811 if p.haslayer(Data):
8812 data = ipfix.decode_data_set(p.getlayer(Set))
8813 self.verify_ipfix_max_sessions(data, max_sessions)
8814
8815 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8816 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8817 TCP(sport=12345, dport=80))
8818 self.pg0.add_stream(p)
8819 self.pg_enable_capture(self.pg_interfaces)
8820 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008821 self.pg1.assert_nothing_captured()
8822 sleep(1)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04008823 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08008824 capture = self.pg3.get_capture(1)
8825 # verify events in data set
8826 for p in capture:
8827 self.assertTrue(p.haslayer(IPFIX))
8828 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8829 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8830 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8831 self.assertEqual(p[UDP].dport, 4739)
8832 self.assertEqual(p[IPFIX].observationDomainID,
8833 self.ipfix_domain_id)
8834 if p.haslayer(Data):
8835 data = ipfix.decode_data_set(p.getlayer(Set))
8836 self.verify_ipfix_max_bibs(data, max_bibs)
8837
8838 def test_ipfix_max_frags(self):
8839 """ IPFIX logging maximum fragments pending reassembly exceeded """
Filip Vargaf4749ca2019-04-25 14:55:32 +02008840 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8841 end_addr=self.nat_addr,
8842 vrf_id=0xFFFFFFFF,
8843 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008844 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008845 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8846 sw_if_index=self.pg0.sw_if_index)
8847 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8848 sw_if_index=self.pg1.sw_if_index)
8849 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
8850 drop_frag=0, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008851 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8852 src_address=self.pg3.local_ip4n,
8853 path_mtu=512,
8854 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008855 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02008856 src_port=self.ipfix_src_port,
8857 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008858
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008859 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008860 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8861 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008862 pkts.reverse()
8863 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008864 self.pg_enable_capture(self.pg_interfaces)
8865 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008866 self.pg1.assert_nothing_captured()
8867 sleep(1)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04008868 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08008869 capture = self.pg3.get_capture(9)
8870 ipfix = IPFIXDecoder()
8871 # first load template
8872 for p in capture:
8873 self.assertTrue(p.haslayer(IPFIX))
8874 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8875 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8876 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8877 self.assertEqual(p[UDP].dport, 4739)
8878 self.assertEqual(p[IPFIX].observationDomainID,
8879 self.ipfix_domain_id)
8880 if p.haslayer(Template):
8881 ipfix.add_template(p.getlayer(Template))
8882 # verify events in data set
8883 for p in capture:
8884 if p.haslayer(Data):
8885 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008886 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008887 self.pg0.remote_ip6n)
8888
8889 def test_ipfix_bib_ses(self):
8890 """ IPFIX logging NAT64 BIB/session create and delete events """
8891 self.tcp_port_in = random.randint(1025, 65535)
8892 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8893 '64:ff9b::',
8894 96)
8895
Filip Vargaf4749ca2019-04-25 14:55:32 +02008896 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8897 end_addr=self.nat_addr,
8898 vrf_id=0xFFFFFFFF,
8899 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008900 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008901 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8902 sw_if_index=self.pg0.sw_if_index)
8903 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8904 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08008905 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8906 src_address=self.pg3.local_ip4n,
8907 path_mtu=512,
8908 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008909 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02008910 src_port=self.ipfix_src_port,
8911 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008912
8913 # Create
8914 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8915 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8916 TCP(sport=self.tcp_port_in, dport=25))
8917 self.pg0.add_stream(p)
8918 self.pg_enable_capture(self.pg_interfaces)
8919 self.pg_start()
8920 p = self.pg1.get_capture(1)
8921 self.tcp_port_out = p[0][TCP].sport
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04008922 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08008923 capture = self.pg3.get_capture(10)
8924 ipfix = IPFIXDecoder()
8925 # first load template
8926 for p in capture:
8927 self.assertTrue(p.haslayer(IPFIX))
8928 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8929 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8930 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8931 self.assertEqual(p[UDP].dport, 4739)
8932 self.assertEqual(p[IPFIX].observationDomainID,
8933 self.ipfix_domain_id)
8934 if p.haslayer(Template):
8935 ipfix.add_template(p.getlayer(Template))
8936 # verify events in data set
8937 for p in capture:
8938 if p.haslayer(Data):
8939 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008940 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008941 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008942 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008943 self.verify_ipfix_nat64_ses(data,
8944 1,
8945 self.pg0.remote_ip6n,
8946 self.pg1.remote_ip4,
8947 25)
8948 else:
8949 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8950
8951 # Delete
8952 self.pg_enable_capture(self.pg_interfaces)
Filip Vargaf4749ca2019-04-25 14:55:32 +02008953 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8954 end_addr=self.nat_addr,
8955 vrf_id=0xFFFFFFFF,
Matus Fabiana431ad12018-01-04 04:03:14 -08008956 is_add=0)
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04008957 self.vapi.ipfix_flush()
Matus Fabiana431ad12018-01-04 04:03:14 -08008958 capture = self.pg3.get_capture(2)
8959 # verify events in data set
8960 for p in capture:
8961 self.assertTrue(p.haslayer(IPFIX))
8962 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8963 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8964 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8965 self.assertEqual(p[UDP].dport, 4739)
8966 self.assertEqual(p[IPFIX].observationDomainID,
8967 self.ipfix_domain_id)
8968 if p.haslayer(Data):
8969 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008970 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08008971 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008972 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08008973 self.verify_ipfix_nat64_ses(data,
8974 0,
8975 self.pg0.remote_ip6n,
8976 self.pg1.remote_ip4,
8977 25)
8978 else:
8979 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8980
Matus Fabianad1f3e12018-11-28 21:26:34 -08008981 def test_syslog_sess(self):
8982 """ Test syslog session creation and deletion """
8983 self.tcp_port_in = random.randint(1025, 65535)
8984 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8985 '64:ff9b::',
8986 96)
8987
Filip Vargaf4749ca2019-04-25 14:55:32 +02008988 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8989 end_addr=self.nat_addr,
8990 vrf_id=0xFFFFFFFF,
8991 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008992 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008993 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8994 sw_if_index=self.pg0.sw_if_index)
8995 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8996 sw_if_index=self.pg1.sw_if_index)
Paul Vinciguerrab7658202019-05-17 09:48:15 -04008997 self.vapi.syslog_set_filter(
8998 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
Ole Troanf159f582019-02-28 20:20:47 +01008999 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08009000
9001 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9002 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9003 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9004 self.pg0.add_stream(p)
9005 self.pg_enable_capture(self.pg_interfaces)
9006 self.pg_start()
9007 p = self.pg1.get_capture(1)
9008 self.tcp_port_out = p[0][TCP].sport
9009 capture = self.pg3.get_capture(1)
9010 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9011
9012 self.pg_enable_capture(self.pg_interfaces)
9013 self.pg_start()
Filip Vargaf4749ca2019-04-25 14:55:32 +02009014 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9015 end_addr=self.nat_addr,
9016 vrf_id=0xFFFFFFFF,
Matus Fabianad1f3e12018-11-28 21:26:34 -08009017 is_add=0)
9018 capture = self.pg3.get_capture(1)
9019 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9020
Matus Fabian06596c52017-06-06 04:53:28 -07009021 def nat64_get_ses_num(self):
9022 """
9023 Return number of active NAT64 sessions.
9024 """
Filip Vargaf4749ca2019-04-25 14:55:32 +02009025 st = self.vapi.nat64_st_dump(proto=255)
Matus Fabianab9a59c2017-08-16 05:37:36 -07009026 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07009027
9028 def clear_nat64(self):
9029 """
9030 Clear NAT64 configuration.
9031 """
Filip Vargaf4749ca2019-04-25 14:55:32 +02009032 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Ole Troane1ade682019-03-04 23:55:43 +01009033 src_port=self.ipfix_src_port,
Filip Vargaf4749ca2019-04-25 14:55:32 +02009034 enable=0)
Matus Fabiana431ad12018-01-04 04:03:14 -08009035 self.ipfix_src_port = 4739
9036 self.ipfix_domain_id = 1
9037
Paul Vinciguerrab7658202019-05-17 09:48:15 -04009038 self.vapi.syslog_set_filter(
9039 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
Matus Fabianad1f3e12018-11-28 21:26:34 -08009040
Filip Vargaf4749ca2019-04-25 14:55:32 +02009041 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9042 tcp_transitory=240, icmp=60)
Matus Fabian06596c52017-06-06 04:53:28 -07009043
9044 interfaces = self.vapi.nat64_interface_dump()
9045 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009046 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9047 sw_if_index=intf.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07009048
Filip Vargaf4749ca2019-04-25 14:55:32 +02009049 bib = self.vapi.nat64_bib_dump(proto=255)
Matus Fabian06596c52017-06-06 04:53:28 -07009050 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02009051 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009052 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9053 o_addr=bibe.o_addr,
9054 i_port=bibe.i_port,
9055 o_port=bibe.o_port,
9056 proto=bibe.proto,
9057 vrf_id=bibe.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07009058 is_add=0)
9059
9060 adresses = self.vapi.nat64_pool_addr_dump()
9061 for addr in adresses:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009062 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9063 end_addr=addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07009064 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07009065 is_add=0)
9066
Matus Fabian428dc912017-06-21 06:15:18 -07009067 prefixes = self.vapi.nat64_prefix_dump()
9068 for prefix in prefixes:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009069 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9070 vrf_id=prefix.vrf_id, is_add=0)
Matus Fabian428dc912017-06-21 06:15:18 -07009071
Matus Fabianfd0d5082018-12-18 01:08:51 -08009072 bibs = self.statistics.get_counter('/nat64/total-bibs')
9073 self.assertEqual(bibs[0][0], 0)
9074 sessions = self.statistics.get_counter('/nat64/total-sessions')
9075 self.assertEqual(sessions[0][0], 0)
9076
Matus Fabian06596c52017-06-06 04:53:28 -07009077 def tearDown(self):
9078 super(TestNAT64, self).tearDown()
9079 if not self.vpp_dead:
Matus Fabian06596c52017-06-06 04:53:28 -07009080 self.clear_nat64()
9081
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009082 def show_commands_at_teardown(self):
9083 self.logger.info(self.vapi.cli("show nat64 pool"))
9084 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9085 self.logger.info(self.vapi.cli("show nat64 prefix"))
9086 self.logger.info(self.vapi.cli("show nat64 bib all"))
9087 self.logger.info(self.vapi.cli("show nat64 session table all"))
9088 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
9089
Matus Fabian8ebe6252017-11-06 05:04:53 -08009090
9091class TestDSlite(MethodHolder):
9092 """ DS-Lite Test Cases """
9093
9094 @classmethod
9095 def setUpClass(cls):
9096 super(TestDSlite, cls).setUpClass()
9097
9098 try:
9099 cls.nat_addr = '10.0.0.3'
Matus Fabian8ebe6252017-11-06 05:04:53 -08009100
Matus Fabianad1f3e12018-11-28 21:26:34 -08009101 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08009102 cls.pg0.admin_up()
9103 cls.pg0.config_ip4()
9104 cls.pg0.resolve_arp()
9105 cls.pg1.admin_up()
9106 cls.pg1.config_ip6()
9107 cls.pg1.generate_remote_hosts(2)
9108 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08009109 cls.pg2.admin_up()
9110 cls.pg2.config_ip4()
9111 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08009112
9113 except Exception:
9114 super(TestDSlite, cls).tearDownClass()
9115 raise
9116
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009117 @classmethod
9118 def tearDownClass(cls):
9119 super(TestDSlite, cls).tearDownClass()
9120
Matus Fabianad1f3e12018-11-28 21:26:34 -08009121 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
9122 sv6enc, proto):
9123 message = data.decode('utf-8')
9124 try:
9125 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08009126 except ParseError as e:
9127 self.logger.error(e)
9128 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08009129 self.assertEqual(message.severity, SyslogSeverity.info)
9130 self.assertEqual(message.appname, 'NAT')
9131 self.assertEqual(message.msgid, 'APMADD')
9132 sd_params = message.sd.get('napmap')
9133 self.assertTrue(sd_params is not None)
9134 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
9135 self.assertEqual(sd_params.get('ISADDR'), isaddr)
9136 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
9137 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
9138 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
9139 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
9140 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
9141 self.assertTrue(sd_params.get('SSUBIX') is not None)
9142 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08009143
Matus Fabian8ebe6252017-11-06 05:04:53 -08009144 def test_dslite(self):
9145 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07009146 nat_config = self.vapi.nat_show_config()
9147 self.assertEqual(0, nat_config.dslite_ce)
9148
Filip Vargaf4749ca2019-04-25 14:55:32 +02009149 self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr,
9150 end_addr=self.nat_addr,
9151 is_add=1)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009152 aftr_ip4 = '192.0.0.1'
Matus Fabian8ebe6252017-11-06 05:04:53 -08009153 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
Filip Vargaf4749ca2019-04-25 14:55:32 +02009154 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
Ole Troanf159f582019-02-28 20:20:47 +01009155 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009156
9157 # UDP
9158 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9159 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
9160 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9161 UDP(sport=20000, dport=10000))
9162 self.pg1.add_stream(p)
9163 self.pg_enable_capture(self.pg_interfaces)
9164 self.pg_start()
9165 capture = self.pg0.get_capture(1)
9166 capture = capture[0]
9167 self.assertFalse(capture.haslayer(IPv6))
9168 self.assertEqual(capture[IP].src, self.nat_addr)
9169 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9170 self.assertNotEqual(capture[UDP].sport, 20000)
9171 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009172 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009173 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08009174 capture = self.pg2.get_capture(1)
9175 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
9176 20000, self.nat_addr, out_port,
9177 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009178
9179 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9180 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9181 UDP(sport=10000, dport=out_port))
9182 self.pg0.add_stream(p)
9183 self.pg_enable_capture(self.pg_interfaces)
9184 self.pg_start()
9185 capture = self.pg1.get_capture(1)
9186 capture = capture[0]
9187 self.assertEqual(capture[IPv6].src, aftr_ip6)
9188 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9189 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9190 self.assertEqual(capture[IP].dst, '192.168.1.1')
9191 self.assertEqual(capture[UDP].sport, 10000)
9192 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009193 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009194
9195 # TCP
9196 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9197 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9198 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9199 TCP(sport=20001, dport=10001))
9200 self.pg1.add_stream(p)
9201 self.pg_enable_capture(self.pg_interfaces)
9202 self.pg_start()
9203 capture = self.pg0.get_capture(1)
9204 capture = capture[0]
9205 self.assertFalse(capture.haslayer(IPv6))
9206 self.assertEqual(capture[IP].src, self.nat_addr)
9207 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9208 self.assertNotEqual(capture[TCP].sport, 20001)
9209 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02009210 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009211 out_port = capture[TCP].sport
9212
9213 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9214 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9215 TCP(sport=10001, dport=out_port))
9216 self.pg0.add_stream(p)
9217 self.pg_enable_capture(self.pg_interfaces)
9218 self.pg_start()
9219 capture = self.pg1.get_capture(1)
9220 capture = capture[0]
9221 self.assertEqual(capture[IPv6].src, aftr_ip6)
9222 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9223 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9224 self.assertEqual(capture[IP].dst, '192.168.1.1')
9225 self.assertEqual(capture[TCP].sport, 10001)
9226 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02009227 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009228
9229 # ICMP
9230 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9231 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9232 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9233 ICMP(id=4000, type='echo-request'))
9234 self.pg1.add_stream(p)
9235 self.pg_enable_capture(self.pg_interfaces)
9236 self.pg_start()
9237 capture = self.pg0.get_capture(1)
9238 capture = capture[0]
9239 self.assertFalse(capture.haslayer(IPv6))
9240 self.assertEqual(capture[IP].src, self.nat_addr)
9241 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9242 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009243 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009244 out_id = capture[ICMP].id
9245
9246 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9247 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9248 ICMP(id=out_id, type='echo-reply'))
9249 self.pg0.add_stream(p)
9250 self.pg_enable_capture(self.pg_interfaces)
9251 self.pg_start()
9252 capture = self.pg1.get_capture(1)
9253 capture = capture[0]
9254 self.assertEqual(capture[IPv6].src, aftr_ip6)
9255 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9256 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9257 self.assertEqual(capture[IP].dst, '192.168.1.1')
9258 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009259 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009260
Matus Fabian331acc62017-12-08 03:38:51 -08009261 # ping DS-Lite AFTR tunnel endpoint address
9262 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9263 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
9264 ICMPv6EchoRequest())
9265 self.pg1.add_stream(p)
9266 self.pg_enable_capture(self.pg_interfaces)
9267 self.pg_start()
9268 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08009269 capture = capture[0]
9270 self.assertEqual(capture[IPv6].src, aftr_ip6)
9271 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9272 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9273
Matus Fabianfd0d5082018-12-18 01:08:51 -08009274 b4s = self.statistics.get_counter('/dslite/total-b4s')
9275 self.assertEqual(b4s[0][0], 2)
9276 sessions = self.statistics.get_counter('/dslite/total-sessions')
9277 self.assertEqual(sessions[0][0], 3)
9278
Matus Fabian8ebe6252017-11-06 05:04:53 -08009279 def tearDown(self):
9280 super(TestDSlite, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009281
9282 def show_commands_at_teardown(self):
9283 self.logger.info(self.vapi.cli("show dslite pool"))
9284 self.logger.info(
9285 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9286 self.logger.info(self.vapi.cli("show dslite sessions"))
Matus Fabian8ebe6252017-11-06 05:04:53 -08009287
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009288
9289class TestDSliteCE(MethodHolder):
9290 """ DS-Lite CE Test Cases """
9291
9292 @classmethod
9293 def setUpConstants(cls):
9294 super(TestDSliteCE, cls).setUpConstants()
9295 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
9296
9297 @classmethod
9298 def setUpClass(cls):
9299 super(TestDSliteCE, cls).setUpClass()
9300
9301 try:
9302 cls.create_pg_interfaces(range(2))
9303 cls.pg0.admin_up()
9304 cls.pg0.config_ip4()
9305 cls.pg0.resolve_arp()
9306 cls.pg1.admin_up()
9307 cls.pg1.config_ip6()
9308 cls.pg1.generate_remote_hosts(1)
9309 cls.pg1.configure_ipv6_neighbors()
9310
9311 except Exception:
9312 super(TestDSliteCE, cls).tearDownClass()
9313 raise
9314
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009315 @classmethod
9316 def tearDownClass(cls):
9317 super(TestDSliteCE, cls).tearDownClass()
9318
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009319 def test_dslite_ce(self):
9320 """ Test DS-Lite CE """
9321
Matus Fabian69ce30d2018-08-22 01:27:10 -07009322 nat_config = self.vapi.nat_show_config()
9323 self.assertEqual(1, nat_config.dslite_ce)
9324
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009325 b4_ip4 = '192.0.0.2'
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009326 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
Filip Vargaf4749ca2019-04-25 14:55:32 +02009327 self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009328
9329 aftr_ip4 = '192.0.0.1'
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009330 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
9331 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
Filip Vargaf4749ca2019-04-25 14:55:32 +02009332 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009333
Neale Ranns097fa662018-05-01 05:17:55 -07009334 r1 = VppIpRoute(self, aftr_ip6, 128,
9335 [VppRoutePath(self.pg1.remote_ip6,
9336 self.pg1.sw_if_index)])
9337 r1.add_vpp_config()
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009338
9339 # UDP encapsulation
9340 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9341 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
9342 UDP(sport=10000, dport=20000))
9343 self.pg0.add_stream(p)
9344 self.pg_enable_capture(self.pg_interfaces)
9345 self.pg_start()
9346 capture = self.pg1.get_capture(1)
9347 capture = capture[0]
9348 self.assertEqual(capture[IPv6].src, b4_ip6)
9349 self.assertEqual(capture[IPv6].dst, aftr_ip6)
9350 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9351 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
9352 self.assertEqual(capture[UDP].sport, 10000)
9353 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009354 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009355
9356 # UDP decapsulation
9357 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9358 IPv6(dst=b4_ip6, src=aftr_ip6) /
9359 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
9360 UDP(sport=20000, dport=10000))
9361 self.pg1.add_stream(p)
9362 self.pg_enable_capture(self.pg_interfaces)
9363 self.pg_start()
9364 capture = self.pg0.get_capture(1)
9365 capture = capture[0]
9366 self.assertFalse(capture.haslayer(IPv6))
9367 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
9368 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9369 self.assertEqual(capture[UDP].sport, 20000)
9370 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009371 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009372
9373 # ping DS-Lite B4 tunnel endpoint address
9374 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9375 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
9376 ICMPv6EchoRequest())
9377 self.pg1.add_stream(p)
9378 self.pg_enable_capture(self.pg_interfaces)
9379 self.pg_start()
9380 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009381 capture = capture[0]
9382 self.assertEqual(capture[IPv6].src, b4_ip6)
9383 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9384 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9385
9386 def tearDown(self):
9387 super(TestDSliteCE, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009388
9389 def show_commands_at_teardown(self):
9390 self.logger.info(
9391 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9392 self.logger.info(
9393 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009394
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009395
9396class TestNAT66(MethodHolder):
9397 """ NAT66 Test Cases """
9398
9399 @classmethod
9400 def setUpClass(cls):
9401 super(TestNAT66, cls).setUpClass()
9402
9403 try:
9404 cls.nat_addr = 'fd01:ff::2'
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009405
9406 cls.create_pg_interfaces(range(2))
9407 cls.interfaces = list(cls.pg_interfaces)
9408
9409 for i in cls.interfaces:
9410 i.admin_up()
9411 i.config_ip6()
9412 i.configure_ipv6_neighbors()
9413
9414 except Exception:
9415 super(TestNAT66, cls).tearDownClass()
9416 raise
9417
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009418 @classmethod
9419 def tearDownClass(cls):
9420 super(TestNAT66, cls).tearDownClass()
9421
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009422 def test_static(self):
9423 """ 1:1 NAT66 test """
Filip Vargadd1e3e72019-04-15 18:52:43 +02009424 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02009425 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9426 sw_if_index=self.pg0.sw_if_index)
9427 self.vapi.nat66_add_del_interface(is_add=1,
9428 sw_if_index=self.pg1.sw_if_index)
9429 self.vapi.nat66_add_del_static_mapping(
9430 local_ip_address=self.pg0.remote_ip6n,
9431 external_ip_address=self.nat_addr,
9432 is_add=1)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009433
9434 # in2out
9435 pkts = []
9436 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9437 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9438 TCP())
9439 pkts.append(p)
9440 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9441 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9442 UDP())
9443 pkts.append(p)
9444 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9445 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9446 ICMPv6EchoRequest())
9447 pkts.append(p)
9448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9449 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9450 GRE() / IP() / TCP())
9451 pkts.append(p)
9452 self.pg0.add_stream(pkts)
9453 self.pg_enable_capture(self.pg_interfaces)
9454 self.pg_start()
9455 capture = self.pg1.get_capture(len(pkts))
9456 for packet in capture:
9457 try:
9458 self.assertEqual(packet[IPv6].src, self.nat_addr)
9459 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02009460 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009461 except:
9462 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9463 raise
9464
9465 # out2in
9466 pkts = []
9467 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9468 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9469 TCP())
9470 pkts.append(p)
9471 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9472 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9473 UDP())
9474 pkts.append(p)
9475 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9476 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9477 ICMPv6EchoReply())
9478 pkts.append(p)
9479 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9480 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9481 GRE() / IP() / TCP())
9482 pkts.append(p)
9483 self.pg1.add_stream(pkts)
9484 self.pg_enable_capture(self.pg_interfaces)
9485 self.pg_start()
9486 capture = self.pg0.get_capture(len(pkts))
9487 for packet in capture:
9488 try:
9489 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9490 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02009491 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009492 except:
9493 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9494 raise
9495
9496 sm = self.vapi.nat66_static_mapping_dump()
9497 self.assertEqual(len(sm), 1)
9498 self.assertEqual(sm[0].total_pkts, 8)
9499
Juraj Sloboda9341e342018-04-13 12:00:46 +02009500 def test_check_no_translate(self):
9501 """ NAT66 translate only when egress interface is outside interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02009502 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02009503 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9504 sw_if_index=self.pg0.sw_if_index)
9505 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9506 sw_if_index=self.pg1.sw_if_index)
9507 self.vapi.nat66_add_del_static_mapping(
9508 local_ip_address=self.pg0.remote_ip6n,
9509 external_ip_address=self.nat_addr,
9510 is_add=1)
Juraj Sloboda9341e342018-04-13 12:00:46 +02009511
9512 # in2out
9513 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9514 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9515 UDP())
9516 self.pg0.add_stream([p])
9517 self.pg_enable_capture(self.pg_interfaces)
9518 self.pg_start()
9519 capture = self.pg1.get_capture(1)
9520 packet = capture[0]
9521 try:
9522 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9523 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9524 except:
9525 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9526 raise
9527
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009528 def clear_nat66(self):
9529 """
9530 Clear NAT66 configuration.
9531 """
9532 interfaces = self.vapi.nat66_interface_dump()
9533 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009534 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9535 sw_if_index=intf.sw_if_index)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009536
9537 static_mappings = self.vapi.nat66_static_mapping_dump()
9538 for sm in static_mappings:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009539 self.vapi.nat66_add_del_static_mapping(
9540 local_ip_address=sm.local_ip_address,
9541 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9542 is_add=0)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009543
9544 def tearDown(self):
9545 super(TestNAT66, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009546 self.clear_nat66()
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009547
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009548 def show_commands_at_teardown(self):
9549 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9550 self.logger.info(self.vapi.cli("show nat66 static mappings"))
Klement Sekerad81ae412018-05-16 10:52:54 +02009551
Filip Vargaf4749ca2019-04-25 14:55:32 +02009552
Matus Fabiande886752016-12-07 03:38:19 -08009553if __name__ == '__main__':
9554 unittest.main(testRunner=VppTestRunner)