blob: c88981b48b458c6f6a566d1611dbdfeea54e91fe [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
26from vpp_papi_provider import SYSLOG_SEVERITY
Ole Troan7f991832018-12-06 17:35:12 +010027from io import BytesIO
Neale Ranns37029302018-08-10 05:30:06 -070028from vpp_papi import VppEnum
Matus Fabian34931eb2019-02-26 09:05:23 -080029from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
30 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
31 PacketListField
Filip Vargadd1e3e72019-04-15 18:52:43 +020032from ipaddress import IPv6Network
Matus Fabian34931eb2019-02-26 09:05:23 -080033
34
35# NAT HA protocol event data
36class Event(Packet):
37 name = "Event"
38 fields_desc = [ByteEnumField("event_type", None,
39 {1: "add", 2: "del", 3: "refresh"}),
40 ByteEnumField("protocol", None,
41 {0: "udp", 1: "tcp", 2: "icmp"}),
42 ShortField("flags", 0),
43 IPField("in_addr", None),
44 IPField("out_addr", None),
45 ShortField("in_port", None),
46 ShortField("out_port", None),
47 IPField("eh_addr", None),
48 IPField("ehn_addr", None),
49 ShortField("eh_port", None),
50 ShortField("ehn_port", None),
51 IntField("fib_index", None),
52 IntField("total_pkts", 0),
53 LongField("total_bytes", 0)]
54
55 def extract_padding(self, s):
56 return "", s
57
58
59# NAT HA protocol header
60class HANATStateSync(Packet):
61 name = "HA NAT state sync"
62 fields_desc = [XByteField("version", 1),
63 FlagsField("flags", 0, 8, ['ACK']),
64 FieldLenField("count", None, count_of="events"),
65 IntField("sequence_number", 1),
66 IntField("thread_index", 0),
67 PacketListField("events", [], Event,
Ole Troan9a475372019-03-05 16:58:24 +010068 count_from=lambda pkt: pkt.count)]
Matus Fabiande886752016-12-07 03:38:19 -080069
70
Martin Gálikd7f75cd2017-03-27 06:02:47 -070071class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070072 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080073
Filip Vargadd1e3e72019-04-15 18:52:43 +020074 @property
75 def config_flags(self):
76 return VppEnum.vl_api_nat_config_flags_t
77
Matus Fabiana6110b62018-06-13 05:39:07 -070078 def clear_nat44(self):
79 """
80 Clear NAT44 configuration.
81 """
82 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
83 # I found no elegant way to do this
84 self.vapi.ip_add_del_route(
85 dst_address=self.pg7.remote_ip4n,
86 dst_address_length=32,
87 next_hop_address=self.pg7.remote_ip4n,
88 next_hop_sw_if_index=self.pg7.sw_if_index,
89 is_add=0)
90 self.vapi.ip_add_del_route(
91 dst_address=self.pg8.remote_ip4n,
92 dst_address_length=32,
93 next_hop_address=self.pg8.remote_ip4n,
94 next_hop_sw_if_index=self.pg8.sw_if_index,
95 is_add=0)
96
97 for intf in [self.pg7, self.pg8]:
Neale Ranns37029302018-08-10 05:30:06 -070098 self.vapi.ip_neighbor_add_del(
99 intf.sw_if_index,
100 intf.remote_mac,
101 intf.remote_ip4,
102 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
103 IP_API_NEIGHBOR_FLAG_STATIC),
104 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700105
106 if self.pg7.has_ip4_config:
107 self.pg7.unconfig_ip4()
108
109 self.vapi.nat44_forwarding_enable_disable(0)
110
111 interfaces = self.vapi.nat44_interface_addr_dump()
112 for intf in interfaces:
Ole Troane1ade682019-03-04 23:55:43 +0100113 self.vapi.nat44_add_del_interface_addr(intf.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200114 flags=intf.flags,
Ole Troane1ade682019-03-04 23:55:43 +0100115 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700116
Ole Troane1ade682019-03-04 23:55:43 +0100117 self.vapi.nat_ipfix_enable_disable(enable=0,
118 src_port=self.ipfix_src_port,
119 domain_id=self.ipfix_domain_id)
Matus Fabiana6110b62018-06-13 05:39:07 -0700120 self.ipfix_src_port = 4739
121 self.ipfix_domain_id = 1
122
Matus Fabianad1f3e12018-11-28 21:26:34 -0800123 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
124
Matus Fabian34931eb2019-02-26 09:05:23 -0800125 self.vapi.nat_ha_set_listener('0.0.0.0', 0)
126 self.vapi.nat_ha_set_failover('0.0.0.0', 0)
127
Matus Fabiana6110b62018-06-13 05:39:07 -0700128 interfaces = self.vapi.nat44_interface_dump()
129 for intf in interfaces:
Filip Vargadd1e3e72019-04-15 18:52:43 +0200130 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
131 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
Matus Fabiana6110b62018-06-13 05:39:07 -0700132 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
Matus Fabiana6110b62018-06-13 05:39:07 -0700133 is_add=0)
134 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200135 is_add=0,
136 flags=intf.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700137
138 interfaces = self.vapi.nat44_interface_output_feature_dump()
139 for intf in interfaces:
140 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200141 is_add=0,
142 flags=intf.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700143 static_mappings = self.vapi.nat44_static_mapping_dump()
144 for sm in static_mappings:
145 self.vapi.nat44_add_del_static_mapping(
146 sm.local_ip_address,
147 sm.external_ip_address,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200148 sm.external_sw_if_index,
149 sm.local_port,
150 sm.external_port,
151 sm.vrf_id,
152 sm.protocol,
153 is_add=0,
154 flags=sm.flags,
155 tag=sm.tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700156
157 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
158 for lb_sm in lb_static_mappings:
159 self.vapi.nat44_add_del_lb_static_mapping(
160 lb_sm.external_addr,
161 lb_sm.external_port,
162 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700163 tag=lb_sm.tag,
164 is_add=0,
165 local_num=0,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200166 locals=[],
167 flags=lb_sm.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700168
169 identity_mappings = self.vapi.nat44_identity_mapping_dump()
170 for id_m in identity_mappings:
171 self.vapi.nat44_add_del_identity_mapping(
Filip Vargadd1e3e72019-04-15 18:52:43 +0200172 flags=id_m.flags,
Matus Fabiana6110b62018-06-13 05:39:07 -0700173 ip=id_m.ip_address,
174 port=id_m.port,
175 sw_if_index=id_m.sw_if_index,
176 vrf_id=id_m.vrf_id,
177 protocol=id_m.protocol,
178 is_add=0)
179
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700180 addresses = self.vapi.nat44_address_dump()
181 for addr in addresses:
Matus Fabiana6110b62018-06-13 05:39:07 -0700182 self.vapi.nat44_add_del_address_range(addr.ip_address,
183 addr.ip_address,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200184 is_add=0,
185 flags=addr.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700186
187 self.vapi.nat_set_reass()
188 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700189 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700190 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700191 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabianbb4e0222018-09-13 02:36:25 -0700192 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700193
194 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
195 local_port=0, external_port=0, vrf_id=0,
196 is_add=1, external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200197 proto=0, tag="", flags=0):
Matus Fabiana6110b62018-06-13 05:39:07 -0700198 """
199 Add/delete NAT44 static mapping
200
201 :param local_ip: Local IP address
202 :param external_ip: External IP address
203 :param local_port: Local port number (Optional)
204 :param external_port: External port number (Optional)
205 :param vrf_id: VRF ID (Default 0)
206 :param is_add: 1 if add, 0 if delete (Default add)
207 :param external_sw_if_index: External interface instead of IP address
208 :param proto: IP protocol (Mandatory if port specified)
Matus Fabiana6110b62018-06-13 05:39:07 -0700209 :param tag: Opaque string tag
Filip Vargadd1e3e72019-04-15 18:52:43 +0200210 :param flags: NAT configuration flags
Matus Fabiana6110b62018-06-13 05:39:07 -0700211 """
Filip Vargadd1e3e72019-04-15 18:52:43 +0200212
213 if not (local_port and external_port):
214 flags |= self.config_flags.NAT_IS_ADDR_ONLY
215
Matus Fabiana6110b62018-06-13 05:39:07 -0700216 self.vapi.nat44_add_del_static_mapping(
Filip Vargadd1e3e72019-04-15 18:52:43 +0200217 local_ip,
218 external_ip,
Matus Fabiana6110b62018-06-13 05:39:07 -0700219 external_sw_if_index,
220 local_port,
221 external_port,
Matus Fabiana6110b62018-06-13 05:39:07 -0700222 vrf_id,
223 proto,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200224 is_add,
225 flags,
226 tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700227
228 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
229 """
230 Add/delete NAT44 address
231
232 :param ip: IP address
233 :param is_add: 1 if add, 0 if delete (Default add)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700234 :param twice_nat: twice NAT address for external hosts
Matus Fabiana6110b62018-06-13 05:39:07 -0700235 """
Filip Vargadd1e3e72019-04-15 18:52:43 +0200236 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
237 self.vapi.nat44_add_del_address_range(ip, ip, is_add,
Matus Fabiana6110b62018-06-13 05:39:07 -0700238 vrf_id=vrf_id,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200239 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700240
Juraj Slobodacba69362017-12-19 02:09:32 +0100241 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800242 """
243 Create packet stream for inside network
244
245 :param in_if: Inside interface
246 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100247 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800248 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800249 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100250 if dst_ip is None:
251 dst_ip = out_if.remote_ip4
252
Matus Fabiande886752016-12-07 03:38:19 -0800253 pkts = []
254 # TCP
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 Fabian06596c52017-06-06 04:53:28 -0700257 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800258 pkts.append(p)
259
260 # UDP
261 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100262 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700263 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800264 pkts.append(p)
265
266 # ICMP
267 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100268 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800269 ICMP(id=self.icmp_id_in, type='echo-request'))
270 pkts.append(p)
271
272 return pkts
273
Matus Fabian428dc912017-06-21 06:15:18 -0700274 def compose_ip6(self, ip4, pref, plen):
275 """
276 Compose IPv4-embedded IPv6 addresses
277
278 :param ip4: IPv4 address
279 :param pref: IPv6 prefix
280 :param plen: IPv6 prefix length
281 :returns: IPv4-embedded IPv6 addresses
282 """
283 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
284 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
285 if plen == 32:
286 pref_n[4] = ip4_n[0]
287 pref_n[5] = ip4_n[1]
288 pref_n[6] = ip4_n[2]
289 pref_n[7] = ip4_n[3]
290 elif plen == 40:
291 pref_n[5] = ip4_n[0]
292 pref_n[6] = ip4_n[1]
293 pref_n[7] = ip4_n[2]
294 pref_n[9] = ip4_n[3]
295 elif plen == 48:
296 pref_n[6] = ip4_n[0]
297 pref_n[7] = ip4_n[1]
298 pref_n[9] = ip4_n[2]
299 pref_n[10] = ip4_n[3]
300 elif plen == 56:
301 pref_n[7] = ip4_n[0]
302 pref_n[9] = ip4_n[1]
303 pref_n[10] = ip4_n[2]
304 pref_n[11] = ip4_n[3]
305 elif plen == 64:
306 pref_n[9] = ip4_n[0]
307 pref_n[10] = ip4_n[1]
308 pref_n[11] = ip4_n[2]
309 pref_n[12] = ip4_n[3]
310 elif plen == 96:
311 pref_n[12] = ip4_n[0]
312 pref_n[13] = ip4_n[1]
313 pref_n[14] = ip4_n[2]
314 pref_n[15] = ip4_n[3]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700315 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
316 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
Matus Fabian428dc912017-06-21 06:15:18 -0700317
Juraj Slobodacba69362017-12-19 02:09:32 +0100318 def extract_ip4(self, ip6, plen):
319 """
320 Extract IPv4 address embedded in IPv6 addresses
321
322 :param ip6: IPv6 address
323 :param plen: IPv6 prefix length
324 :returns: extracted IPv4 address
325 """
326 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
327 ip4_n = [None] * 4
328 if plen == 32:
329 ip4_n[0] = ip6_n[4]
330 ip4_n[1] = ip6_n[5]
331 ip4_n[2] = ip6_n[6]
332 ip4_n[3] = ip6_n[7]
333 elif plen == 40:
334 ip4_n[0] = ip6_n[5]
335 ip4_n[1] = ip6_n[6]
336 ip4_n[2] = ip6_n[7]
337 ip4_n[3] = ip6_n[9]
338 elif plen == 48:
339 ip4_n[0] = ip6_n[6]
340 ip4_n[1] = ip6_n[7]
341 ip4_n[2] = ip6_n[9]
342 ip4_n[3] = ip6_n[10]
343 elif plen == 56:
344 ip4_n[0] = ip6_n[7]
345 ip4_n[1] = ip6_n[9]
346 ip4_n[2] = ip6_n[10]
347 ip4_n[3] = ip6_n[11]
348 elif plen == 64:
349 ip4_n[0] = ip6_n[9]
350 ip4_n[1] = ip6_n[10]
351 ip4_n[2] = ip6_n[11]
352 ip4_n[3] = ip6_n[12]
353 elif plen == 96:
354 ip4_n[0] = ip6_n[12]
355 ip4_n[1] = ip6_n[13]
356 ip4_n[2] = ip6_n[14]
357 ip4_n[3] = ip6_n[15]
358 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
359
Matus Fabian428dc912017-06-21 06:15:18 -0700360 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700361 """
362 Create IPv6 packet stream for inside network
363
364 :param in_if: Inside interface
365 :param out_if: Outside interface
366 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700367 :param pref: NAT64 prefix
368 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700369 """
370 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700371 if pref is None:
372 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
373 else:
374 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
375
Matus Fabian06596c52017-06-06 04:53:28 -0700376 # TCP
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 TCP(sport=self.tcp_port_in, dport=20))
380 pkts.append(p)
381
382 # UDP
383 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
384 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
385 UDP(sport=self.udp_port_in, dport=20))
386 pkts.append(p)
387
388 # ICMP
389 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
390 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
391 ICMPv6EchoRequest(id=self.icmp_id_in))
392 pkts.append(p)
393
394 return pkts
395
Juraj Sloboda7b929792017-11-23 13:20:48 +0100396 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
397 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800398 """
399 Create packet stream for outside network
400
401 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700402 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800403 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100404 :param use_inside_ports: Use inside NAT ports as destination ports
405 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800406 """
407 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700408 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100409 if not use_inside_ports:
410 tcp_port = self.tcp_port_out
411 udp_port = self.udp_port_out
412 icmp_id = self.icmp_id_out
413 else:
414 tcp_port = self.tcp_port_in
415 udp_port = self.udp_port_in
416 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800417 pkts = []
418 # TCP
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 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800422 pkts.append(p)
423
424 # UDP
425 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800426 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100427 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800428 pkts.append(p)
429
430 # ICMP
431 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800432 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100433 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800434 pkts.append(p)
435
436 return pkts
437
Juraj Slobodacba69362017-12-19 02:09:32 +0100438 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
439 """
440 Create packet stream for outside network
441
442 :param out_if: Outside interface
443 :param dst_ip: Destination IP address (Default use global NAT address)
444 :param hl: HL of generated packets
445 """
446 pkts = []
447 # TCP
448 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
449 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
450 TCP(dport=self.tcp_port_out, sport=20))
451 pkts.append(p)
452
453 # UDP
454 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
455 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
456 UDP(dport=self.udp_port_out, sport=20))
457 pkts.append(p)
458
459 # ICMP
460 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
461 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
462 ICMPv6EchoReply(id=self.icmp_id_out))
463 pkts.append(p)
464
465 return pkts
466
Matus Fabiande886752016-12-07 03:38:19 -0800467 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700468 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800469 """
470 Verify captured packets on outside network
471
472 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700473 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700474 :param same_port: Source port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700475 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100476 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800477 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100478 if is_ip6:
479 IP46 = IPv6
480 ICMP46 = ICMPv6EchoRequest
481 else:
482 IP46 = IP
483 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800484 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700485 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800486 for packet in capture:
487 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100488 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200489 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100490 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700491 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100492 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800493 if packet.haslayer(TCP):
494 if same_port:
495 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
496 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100497 self.assertNotEqual(
498 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800499 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200500 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800501 elif packet.haslayer(UDP):
502 if same_port:
503 self.assertEqual(packet[UDP].sport, self.udp_port_in)
504 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100505 self.assertNotEqual(
506 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800507 self.udp_port_out = packet[UDP].sport
508 else:
509 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100510 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800511 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100512 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
513 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200514 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800515 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100516 self.logger.error(ppp("Unexpected or invalid packet "
517 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800518 raise
519
Juraj Slobodacba69362017-12-19 02:09:32 +0100520 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700521 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100522 """
523 Verify captured packets on outside network
524
525 :param capture: Captured packets
526 :param nat_ip: Translated IP address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700527 :param same_port: Source port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100528 :param dst_ip: Destination IP address (Default do not verify)
529 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700530 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
531 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100532
Matus Fabian05ca4a32018-09-04 23:45:13 -0700533 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800534 """
535 Verify captured packets on inside network
536
537 :param capture: Captured packets
538 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800539 """
Matus Fabiande886752016-12-07 03:38:19 -0800540 for packet in capture:
541 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200542 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800543 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
544 if packet.haslayer(TCP):
545 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
546 elif packet.haslayer(UDP):
547 self.assertEqual(packet[UDP].dport, self.udp_port_in)
548 else:
549 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
550 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100551 self.logger.error(ppp("Unexpected or invalid packet "
552 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800553 raise
554
Matus Fabian05ca4a32018-09-04 23:45:13 -0700555 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700556 """
557 Verify captured IPv6 packets on inside network
558
559 :param capture: Captured packets
560 :param src_ip: Source IP
561 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700562 """
Matus Fabian06596c52017-06-06 04:53:28 -0700563 for packet in capture:
564 try:
565 self.assertEqual(packet[IPv6].src, src_ip)
566 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200567 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700568 if packet.haslayer(TCP):
569 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
570 elif packet.haslayer(UDP):
571 self.assertEqual(packet[UDP].dport, self.udp_port_in)
572 else:
573 self.assertEqual(packet[ICMPv6EchoReply].id,
574 self.icmp_id_in)
575 except:
576 self.logger.error(ppp("Unexpected or invalid packet "
577 "(inside network):", packet))
578 raise
579
Matus Fabian675a69c2017-01-18 01:46:01 -0800580 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
581 """
582 Verify captured packet that don't have to be translated
583
584 :param capture: Captured packets
585 :param ingress_if: Ingress interface
586 :param egress_if: Egress interface
587 """
588 for packet in capture:
589 try:
590 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
591 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
592 if packet.haslayer(TCP):
593 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
594 elif packet.haslayer(UDP):
595 self.assertEqual(packet[UDP].sport, self.udp_port_in)
596 else:
597 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
598 except:
599 self.logger.error(ppp("Unexpected or invalid packet "
600 "(inside network):", packet))
601 raise
602
Juraj Slobodab33f4132017-02-08 23:54:21 -0800603 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700604 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800605 """
606 Verify captured packets with ICMP errors on outside network
607
608 :param capture: Captured packets
609 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700610 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800611 :param icmp_type: Type of error ICMP packet
612 we are expecting (Default 11)
613 """
614 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700615 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800616 for packet in capture:
617 try:
618 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800619 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800620 icmp = packet[ICMP]
621 self.assertEqual(icmp.type, icmp_type)
622 self.assertTrue(icmp.haslayer(IPerror))
623 inner_ip = icmp[IPerror]
624 if inner_ip.haslayer(TCPerror):
625 self.assertEqual(inner_ip[TCPerror].dport,
626 self.tcp_port_out)
627 elif inner_ip.haslayer(UDPerror):
628 self.assertEqual(inner_ip[UDPerror].dport,
629 self.udp_port_out)
630 else:
631 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
632 except:
633 self.logger.error(ppp("Unexpected or invalid packet "
634 "(outside network):", packet))
635 raise
636
Matus Fabian05ca4a32018-09-04 23:45:13 -0700637 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800638 """
639 Verify captured packets with ICMP errors on inside network
640
641 :param capture: Captured packets
642 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800643 :param icmp_type: Type of error ICMP packet
644 we are expecting (Default 11)
645 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800646 for packet in capture:
647 try:
648 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800649 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800650 icmp = packet[ICMP]
651 self.assertEqual(icmp.type, icmp_type)
652 self.assertTrue(icmp.haslayer(IPerror))
653 inner_ip = icmp[IPerror]
654 if inner_ip.haslayer(TCPerror):
655 self.assertEqual(inner_ip[TCPerror].sport,
656 self.tcp_port_in)
657 elif inner_ip.haslayer(UDPerror):
658 self.assertEqual(inner_ip[UDPerror].sport,
659 self.udp_port_in)
660 else:
661 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
662 except:
663 self.logger.error(ppp("Unexpected or invalid packet "
664 "(inside network):", packet))
665 raise
666
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200667 def create_stream_frag(self, src_if, dst, sport, dport, data,
668 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700669 """
670 Create fragmented packet stream
671
672 :param src_if: Source interface
673 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200674 :param sport: Source port
675 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700676 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200677 :param proto: protocol (TCP, UDP, ICMP)
678 :param echo_reply: use echo_reply if protocol is ICMP
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700679 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700680 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200681 if proto == IP_PROTOS.tcp:
682 p = (IP(src=src_if.remote_ip4, dst=dst) /
683 TCP(sport=sport, dport=dport) /
684 Raw(data))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700685 p = p.__class__(scapy.compat.raw(p))
686 chksum = p[TCP].chksum
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200687 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
688 elif proto == IP_PROTOS.udp:
689 proto_header = UDP(sport=sport, dport=dport)
690 elif proto == IP_PROTOS.icmp:
691 if not echo_reply:
692 proto_header = ICMP(id=sport, type='echo-request')
693 else:
694 proto_header = ICMP(id=sport, type='echo-reply')
695 else:
696 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700697 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700698 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200699 if proto == IP_PROTOS.tcp:
700 raw = Raw(data[0:4])
701 else:
702 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700703 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
704 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200705 proto_header /
706 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700707 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200708 if proto == IP_PROTOS.tcp:
709 raw = Raw(data[4:20])
710 else:
711 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700712 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
713 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200714 proto=proto) /
715 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700716 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200717 if proto == IP_PROTOS.tcp:
718 raw = Raw(data[20:])
719 else:
720 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700721 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200722 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700723 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200724 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700725 pkts.append(p)
726 return pkts
727
728 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
729 pref=None, plen=0, frag_size=128):
730 """
731 Create fragmented packet stream
732
733 :param src_if: Source interface
734 :param dst: Destination IPv4 address
735 :param sport: Source TCP port
736 :param dport: Destination TCP port
737 :param data: Payload data
738 :param pref: NAT64 prefix
739 :param plen: NAT64 prefix length
740 :param fragsize: size of fragments
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700741 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700742 """
743 if pref is None:
744 dst_ip6 = ''.join(['64:ff9b::', dst])
745 else:
746 dst_ip6 = self.compose_ip6(dst, pref, plen)
747
748 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
749 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
750 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
751 TCP(sport=sport, dport=dport) /
752 Raw(data))
753
754 return fragment6(p, frag_size)
755
756 def reass_frags_and_verify(self, frags, src, dst):
757 """
758 Reassemble and verify fragmented packet
759
760 :param frags: Captured fragments
761 :param src: Source IPv4 address to verify
762 :param dst: Destination IPv4 address to verify
763
764 :returns: Reassembled IPv4 packet
765 """
Ole Troan7f991832018-12-06 17:35:12 +0100766 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700767 for p in frags:
768 self.assertEqual(p[IP].src, src)
769 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200770 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700771 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100772 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700773 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
774 proto=frags[0][IP].proto)
775 if ip.proto == IP_PROTOS.tcp:
776 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200777 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700778 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200779 p = (ip / UDP(buffer.getvalue()[:8]) /
780 Raw(buffer.getvalue()[8:]))
781 elif ip.proto == IP_PROTOS.icmp:
782 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700783 return p
784
785 def reass_frags_and_verify_ip6(self, frags, src, dst):
786 """
787 Reassemble and verify fragmented packet
788
789 :param frags: Captured fragments
790 :param src: Source IPv6 address to verify
791 :param dst: Destination IPv6 address to verify
792
793 :returns: Reassembled IPv6 packet
794 """
Ole Troan7f991832018-12-06 17:35:12 +0100795 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700796 for p in frags:
797 self.assertEqual(p[IPv6].src, src)
798 self.assertEqual(p[IPv6].dst, dst)
799 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100800 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700801 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
802 nh=frags[0][IPv6ExtHdrFragment].nh)
803 if ip.nh == IP_PROTOS.tcp:
804 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700805 elif ip.nh == IP_PROTOS.udp:
806 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200807 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700808 return p
809
Matus Fabianebdf1902018-05-04 03:57:42 -0700810 def initiate_tcp_session(self, in_if, out_if):
811 """
812 Initiates TCP session
813
814 :param in_if: Inside interface
815 :param out_if: Outside interface
816 """
817 try:
818 # SYN packet in->out
819 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
820 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
821 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
822 flags="S"))
823 in_if.add_stream(p)
824 self.pg_enable_capture(self.pg_interfaces)
825 self.pg_start()
826 capture = out_if.get_capture(1)
827 p = capture[0]
828 self.tcp_port_out = p[TCP].sport
829
830 # SYN + ACK packet out->in
831 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
832 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
833 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
834 flags="SA"))
835 out_if.add_stream(p)
836 self.pg_enable_capture(self.pg_interfaces)
837 self.pg_start()
838 in_if.get_capture(1)
839
840 # ACK packet in->out
841 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
842 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
843 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
844 flags="A"))
845 in_if.add_stream(p)
846 self.pg_enable_capture(self.pg_interfaces)
847 self.pg_start()
848 out_if.get_capture(1)
849
850 except:
851 self.logger.error("TCP 3 way handshake failed")
852 raise
853
Matus Fabianeea28d72017-01-13 04:15:54 -0800854 def verify_ipfix_nat44_ses(self, data):
855 """
856 Verify IPFIX NAT44 session create/delete event
857
858 :param data: Decoded IPFIX data records
859 """
860 nat44_ses_create_num = 0
861 nat44_ses_delete_num = 0
862 self.assertEqual(6, len(data))
863 for record in data:
864 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700865 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
866 if scapy.compat.orb(record[230]) == 4:
Matus Fabianeea28d72017-01-13 04:15:54 -0800867 nat44_ses_create_num += 1
868 else:
869 nat44_ses_delete_num += 1
870 # sourceIPv4Address
871 self.assertEqual(self.pg0.remote_ip4n, record[8])
872 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700873 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800874 record[225])
875 # ingressVRFID
876 self.assertEqual(struct.pack("!I", 0), record[234])
877 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700878 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800879 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
880 self.assertEqual(struct.pack("!H", self.icmp_id_out),
881 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700882 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800883 self.assertEqual(struct.pack("!H", self.tcp_port_in),
884 record[7])
885 self.assertEqual(struct.pack("!H", self.tcp_port_out),
886 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700887 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800888 self.assertEqual(struct.pack("!H", self.udp_port_in),
889 record[7])
890 self.assertEqual(struct.pack("!H", self.udp_port_out),
891 record[227])
892 else:
893 self.fail("Invalid protocol")
894 self.assertEqual(3, nat44_ses_create_num)
895 self.assertEqual(3, nat44_ses_delete_num)
896
897 def verify_ipfix_addr_exhausted(self, data):
898 """
899 Verify IPFIX NAT addresses event
900
901 :param data: Decoded IPFIX data records
902 """
903 self.assertEqual(1, len(data))
904 record = data[0]
905 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700906 self.assertEqual(scapy.compat.orb(record[230]), 3)
Matus Fabianeea28d72017-01-13 04:15:54 -0800907 # natPoolID
908 self.assertEqual(struct.pack("!I", 0), record[283])
909
Matus Fabiana431ad12018-01-04 04:03:14 -0800910 def verify_ipfix_max_sessions(self, data, limit):
911 """
912 Verify IPFIX maximum session entries exceeded event
913
914 :param data: Decoded IPFIX data records
915 :param limit: Number of maximum session entries that can be created.
916 """
917 self.assertEqual(1, len(data))
918 record = data[0]
919 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700920 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800921 # natQuotaExceededEvent
922 self.assertEqual(struct.pack("I", 1), record[466])
923 # maxSessionEntries
924 self.assertEqual(struct.pack("I", limit), record[471])
925
926 def verify_ipfix_max_bibs(self, data, limit):
927 """
928 Verify IPFIX maximum BIB entries exceeded event
929
930 :param data: Decoded IPFIX data records
931 :param limit: Number of maximum BIB entries that can be created.
932 """
933 self.assertEqual(1, len(data))
934 record = data[0]
935 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700936 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800937 # natQuotaExceededEvent
938 self.assertEqual(struct.pack("I", 2), record[466])
939 # maxBIBEntries
940 self.assertEqual(struct.pack("I", limit), record[472])
941
942 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
943 """
944 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
945
946 :param data: Decoded IPFIX data records
947 :param limit: Number of maximum fragments pending reassembly
948 :param src_addr: IPv6 source address
949 """
950 self.assertEqual(1, len(data))
951 record = data[0]
952 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700953 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800954 # natQuotaExceededEvent
955 self.assertEqual(struct.pack("I", 5), record[466])
956 # maxFragmentsPendingReassembly
957 self.assertEqual(struct.pack("I", limit), record[475])
958 # sourceIPv6Address
959 self.assertEqual(src_addr, record[27])
960
961 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
962 """
963 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
964
965 :param data: Decoded IPFIX data records
966 :param limit: Number of maximum fragments pending reassembly
967 :param src_addr: IPv4 source address
968 """
969 self.assertEqual(1, len(data))
970 record = data[0]
971 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700972 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800973 # natQuotaExceededEvent
974 self.assertEqual(struct.pack("I", 5), record[466])
975 # maxFragmentsPendingReassembly
976 self.assertEqual(struct.pack("I", limit), record[475])
977 # sourceIPv4Address
978 self.assertEqual(src_addr, record[8])
979
980 def verify_ipfix_bib(self, data, is_create, src_addr):
981 """
982 Verify IPFIX NAT64 BIB create and delete events
983
984 :param data: Decoded IPFIX data records
985 :param is_create: Create event if nonzero value otherwise delete event
986 :param src_addr: IPv6 source address
987 """
988 self.assertEqual(1, len(data))
989 record = data[0]
990 # natEvent
991 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700992 self.assertEqual(scapy.compat.orb(record[230]), 10)
Matus Fabiana431ad12018-01-04 04:03:14 -0800993 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700994 self.assertEqual(scapy.compat.orb(record[230]), 11)
Matus Fabiana431ad12018-01-04 04:03:14 -0800995 # sourceIPv6Address
996 self.assertEqual(src_addr, record[27])
997 # postNATSourceIPv4Address
998 self.assertEqual(self.nat_addr_n, record[225])
999 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001000 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001001 # ingressVRFID
1002 self.assertEqual(struct.pack("!I", 0), record[234])
1003 # sourceTransportPort
1004 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1005 # postNAPTSourceTransportPort
1006 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1007
1008 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1009 dst_port):
1010 """
1011 Verify IPFIX NAT64 session create and delete events
1012
1013 :param data: Decoded IPFIX data records
1014 :param is_create: Create event if nonzero value otherwise delete event
1015 :param src_addr: IPv6 source address
1016 :param dst_addr: IPv4 destination address
1017 :param dst_port: destination TCP port
1018 """
1019 self.assertEqual(1, len(data))
1020 record = data[0]
1021 # natEvent
1022 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001023 self.assertEqual(scapy.compat.orb(record[230]), 6)
Matus Fabiana431ad12018-01-04 04:03:14 -08001024 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001025 self.assertEqual(scapy.compat.orb(record[230]), 7)
Matus Fabiana431ad12018-01-04 04:03:14 -08001026 # sourceIPv6Address
1027 self.assertEqual(src_addr, record[27])
1028 # destinationIPv6Address
1029 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1030 self.compose_ip6(dst_addr,
1031 '64:ff9b::',
1032 96)),
1033 record[28])
1034 # postNATSourceIPv4Address
1035 self.assertEqual(self.nat_addr_n, record[225])
1036 # postNATDestinationIPv4Address
1037 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1038 record[226])
1039 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001040 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001041 # ingressVRFID
1042 self.assertEqual(struct.pack("!I", 0), record[234])
1043 # sourceTransportPort
1044 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1045 # postNAPTSourceTransportPort
1046 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1047 # destinationTransportPort
1048 self.assertEqual(struct.pack("!H", dst_port), record[11])
1049 # postNAPTDestinationTransportPort
1050 self.assertEqual(struct.pack("!H", dst_port), record[228])
1051
Matus Fabian68ba8802018-08-08 05:52:47 -07001052 def verify_no_nat44_user(self):
1053 """ Verify that there is no NAT44 user """
1054 users = self.vapi.nat44_user_dump()
1055 self.assertEqual(len(users), 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08001056 users = self.statistics.get_counter('/nat44/total-users')
1057 self.assertEqual(users[0][0], 0)
1058 sessions = self.statistics.get_counter('/nat44/total-sessions')
1059 self.assertEqual(sessions[0][0], 0)
Matus Fabian68ba8802018-08-08 05:52:47 -07001060
Matus Fabian878c6462018-08-23 00:33:35 -07001061 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1062 """
1063 Verify IPFIX maximum entries per user exceeded event
1064
1065 :param data: Decoded IPFIX data records
1066 :param limit: Number of maximum entries per user
1067 :param src_addr: IPv4 source address
1068 """
1069 self.assertEqual(1, len(data))
1070 record = data[0]
1071 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001072 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabian878c6462018-08-23 00:33:35 -07001073 # natQuotaExceededEvent
1074 self.assertEqual(struct.pack("I", 3), record[466])
1075 # maxEntriesPerUser
1076 self.assertEqual(struct.pack("I", limit), record[473])
1077 # sourceIPv4Address
1078 self.assertEqual(src_addr, record[8])
1079
Matus Fabianad1f3e12018-11-28 21:26:34 -08001080 def verify_syslog_apmap(self, data, is_add=True):
1081 message = data.decode('utf-8')
1082 try:
1083 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001084 except ParseError as e:
1085 self.logger.error(e)
1086 raise
1087 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001088 self.assertEqual(message.severity, SyslogSeverity.info)
1089 self.assertEqual(message.appname, 'NAT')
1090 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1091 sd_params = message.sd.get('napmap')
1092 self.assertTrue(sd_params is not None)
1093 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1094 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1095 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1096 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1097 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1098 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1099 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1100 self.assertTrue(sd_params.get('SSUBIX') is not None)
1101 self.assertEqual(sd_params.get('SVLAN'), '0')
Matus Fabianad1f3e12018-11-28 21:26:34 -08001102
1103 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1104 message = data.decode('utf-8')
1105 try:
1106 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001107 except ParseError as e:
1108 self.logger.error(e)
1109 raise
1110 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001111 self.assertEqual(message.severity, SyslogSeverity.info)
1112 self.assertEqual(message.appname, 'NAT')
1113 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1114 sd_params = message.sd.get('nsess')
1115 self.assertTrue(sd_params is not None)
1116 if is_ip6:
1117 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1118 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1119 else:
1120 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1121 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1122 self.assertTrue(sd_params.get('SSUBIX') is not None)
1123 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1124 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1125 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1126 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1127 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1128 self.assertEqual(sd_params.get('SVLAN'), '0')
1129 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1130 self.assertEqual(sd_params.get('XDPORT'),
1131 "%d" % self.tcp_external_port)
Matus Fabianad1f3e12018-11-28 21:26:34 -08001132
Matus Fabianbb4e0222018-09-13 02:36:25 -07001133 def verify_mss_value(self, pkt, mss):
1134 """
1135 Verify TCP MSS value
1136
1137 :param pkt:
1138 :param mss:
1139 """
1140 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1141 raise TypeError("Not a TCP/IP packet")
1142
1143 for option in pkt[TCP].options:
1144 if option[0] == 'MSS':
1145 self.assertEqual(option[1], mss)
1146 self.assert_tcp_checksum_valid(pkt)
1147
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001148 @staticmethod
1149 def proto2layer(proto):
1150 if proto == IP_PROTOS.tcp:
1151 return TCP
1152 elif proto == IP_PROTOS.udp:
1153 return UDP
1154 elif proto == IP_PROTOS.icmp:
1155 return ICMP
1156 else:
1157 raise Exception("Unsupported protocol")
1158
1159 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1160 layer = self.proto2layer(proto)
1161
1162 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001163 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001164 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001165 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001166 self.port_in = random.randint(1025, 65535)
1167
1168 reass = self.vapi.nat_reass_dump()
1169 reass_n_start = len(reass)
1170
1171 # in2out
1172 pkts = self.create_stream_frag(self.pg0,
1173 self.pg1.remote_ip4,
1174 self.port_in,
1175 20,
1176 data,
1177 proto)
1178 self.pg0.add_stream(pkts)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181 frags = self.pg1.get_capture(len(pkts))
1182 if not dont_translate:
1183 p = self.reass_frags_and_verify(frags,
1184 self.nat_addr,
1185 self.pg1.remote_ip4)
1186 else:
1187 p = self.reass_frags_and_verify(frags,
1188 self.pg0.remote_ip4,
1189 self.pg1.remote_ip4)
1190 if proto != IP_PROTOS.icmp:
1191 if not dont_translate:
1192 self.assertEqual(p[layer].dport, 20)
1193 self.assertNotEqual(p[layer].sport, self.port_in)
1194 else:
1195 self.assertEqual(p[layer].sport, self.port_in)
1196 else:
1197 if not dont_translate:
1198 self.assertNotEqual(p[layer].id, self.port_in)
1199 else:
1200 self.assertEqual(p[layer].id, self.port_in)
1201 self.assertEqual(data, p[Raw].load)
1202
1203 # out2in
1204 if not dont_translate:
1205 dst_addr = self.nat_addr
1206 else:
1207 dst_addr = self.pg0.remote_ip4
1208 if proto != IP_PROTOS.icmp:
1209 sport = 20
1210 dport = p[layer].sport
1211 else:
1212 sport = p[layer].id
1213 dport = 0
1214 pkts = self.create_stream_frag(self.pg1,
1215 dst_addr,
1216 sport,
1217 dport,
1218 data,
1219 proto,
1220 echo_reply=True)
1221 self.pg1.add_stream(pkts)
1222 self.pg_enable_capture(self.pg_interfaces)
1223 self.pg_start()
1224 frags = self.pg0.get_capture(len(pkts))
1225 p = self.reass_frags_and_verify(frags,
1226 self.pg1.remote_ip4,
1227 self.pg0.remote_ip4)
1228 if proto != IP_PROTOS.icmp:
1229 self.assertEqual(p[layer].sport, 20)
1230 self.assertEqual(p[layer].dport, self.port_in)
1231 else:
1232 self.assertEqual(p[layer].id, self.port_in)
1233 self.assertEqual(data, p[Raw].load)
1234
1235 reass = self.vapi.nat_reass_dump()
1236 reass_n_end = len(reass)
1237
1238 self.assertEqual(reass_n_end - reass_n_start, 2)
1239
1240 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1241 layer = self.proto2layer(proto)
1242
1243 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001244 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001245 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001246 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001247 self.port_in = random.randint(1025, 65535)
1248
1249 for i in range(2):
1250 reass = self.vapi.nat_reass_dump()
1251 reass_n_start = len(reass)
1252
1253 # out2in
1254 pkts = self.create_stream_frag(self.pg0,
1255 self.server_out_addr,
1256 self.port_in,
1257 self.server_out_port,
1258 data,
1259 proto)
1260 self.pg0.add_stream(pkts)
1261 self.pg_enable_capture(self.pg_interfaces)
1262 self.pg_start()
1263 frags = self.pg1.get_capture(len(pkts))
1264 p = self.reass_frags_and_verify(frags,
1265 self.pg0.remote_ip4,
1266 self.server_in_addr)
1267 if proto != IP_PROTOS.icmp:
1268 self.assertEqual(p[layer].sport, self.port_in)
1269 self.assertEqual(p[layer].dport, self.server_in_port)
1270 else:
1271 self.assertEqual(p[layer].id, self.port_in)
1272 self.assertEqual(data, p[Raw].load)
1273
1274 # in2out
1275 if proto != IP_PROTOS.icmp:
1276 pkts = self.create_stream_frag(self.pg1,
1277 self.pg0.remote_ip4,
1278 self.server_in_port,
1279 p[layer].sport,
1280 data,
1281 proto)
1282 else:
1283 pkts = self.create_stream_frag(self.pg1,
1284 self.pg0.remote_ip4,
1285 p[layer].id,
1286 0,
1287 data,
1288 proto,
1289 echo_reply=True)
1290 self.pg1.add_stream(pkts)
1291 self.pg_enable_capture(self.pg_interfaces)
1292 self.pg_start()
1293 frags = self.pg0.get_capture(len(pkts))
1294 p = self.reass_frags_and_verify(frags,
1295 self.server_out_addr,
1296 self.pg0.remote_ip4)
1297 if proto != IP_PROTOS.icmp:
1298 self.assertEqual(p[layer].sport, self.server_out_port)
1299 self.assertEqual(p[layer].dport, self.port_in)
1300 else:
1301 self.assertEqual(p[layer].id, self.port_in)
1302 self.assertEqual(data, p[Raw].load)
1303
1304 reass = self.vapi.nat_reass_dump()
1305 reass_n_end = len(reass)
1306
1307 self.assertEqual(reass_n_end - reass_n_start, 2)
1308
1309 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1310 layer = self.proto2layer(proto)
1311
1312 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001313 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001314 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001315 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001316
1317 # send packet from host to server
1318 pkts = self.create_stream_frag(self.pg0,
1319 self.nat_addr,
1320 self.host_in_port,
1321 self.server_out_port,
1322 data,
1323 proto)
1324 self.pg0.add_stream(pkts)
1325 self.pg_enable_capture(self.pg_interfaces)
1326 self.pg_start()
1327 frags = self.pg0.get_capture(len(pkts))
1328 p = self.reass_frags_and_verify(frags,
1329 self.nat_addr,
1330 self.server.ip4)
1331 if proto != IP_PROTOS.icmp:
1332 self.assertNotEqual(p[layer].sport, self.host_in_port)
1333 self.assertEqual(p[layer].dport, self.server_in_port)
1334 else:
1335 self.assertNotEqual(p[layer].id, self.host_in_port)
1336 self.assertEqual(data, p[Raw].load)
1337
1338 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1339 layer = self.proto2layer(proto)
1340
1341 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001342 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001343 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001344 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001345 self.port_in = random.randint(1025, 65535)
1346
1347 for i in range(2):
1348 # in2out
1349 pkts = self.create_stream_frag(self.pg0,
1350 self.pg1.remote_ip4,
1351 self.port_in,
1352 20,
1353 data,
1354 proto)
1355 pkts.reverse()
1356 self.pg0.add_stream(pkts)
1357 self.pg_enable_capture(self.pg_interfaces)
1358 self.pg_start()
1359 frags = self.pg1.get_capture(len(pkts))
1360 if not dont_translate:
1361 p = self.reass_frags_and_verify(frags,
1362 self.nat_addr,
1363 self.pg1.remote_ip4)
1364 else:
1365 p = self.reass_frags_and_verify(frags,
1366 self.pg0.remote_ip4,
1367 self.pg1.remote_ip4)
1368 if proto != IP_PROTOS.icmp:
1369 if not dont_translate:
1370 self.assertEqual(p[layer].dport, 20)
1371 self.assertNotEqual(p[layer].sport, self.port_in)
1372 else:
1373 self.assertEqual(p[layer].sport, self.port_in)
1374 else:
1375 if not dont_translate:
1376 self.assertNotEqual(p[layer].id, self.port_in)
1377 else:
1378 self.assertEqual(p[layer].id, self.port_in)
1379 self.assertEqual(data, p[Raw].load)
1380
1381 # out2in
1382 if not dont_translate:
1383 dst_addr = self.nat_addr
1384 else:
1385 dst_addr = self.pg0.remote_ip4
1386 if proto != IP_PROTOS.icmp:
1387 sport = 20
1388 dport = p[layer].sport
1389 else:
1390 sport = p[layer].id
1391 dport = 0
1392 pkts = self.create_stream_frag(self.pg1,
1393 dst_addr,
1394 sport,
1395 dport,
1396 data,
1397 proto,
1398 echo_reply=True)
1399 pkts.reverse()
1400 self.pg1.add_stream(pkts)
1401 self.pg_enable_capture(self.pg_interfaces)
1402 self.pg_start()
1403 frags = self.pg0.get_capture(len(pkts))
1404 p = self.reass_frags_and_verify(frags,
1405 self.pg1.remote_ip4,
1406 self.pg0.remote_ip4)
1407 if proto != IP_PROTOS.icmp:
1408 self.assertEqual(p[layer].sport, 20)
1409 self.assertEqual(p[layer].dport, self.port_in)
1410 else:
1411 self.assertEqual(p[layer].id, self.port_in)
1412 self.assertEqual(data, p[Raw].load)
1413
1414 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1415 layer = self.proto2layer(proto)
1416
1417 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001418 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001419 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001420 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001421 self.port_in = random.randint(1025, 65535)
1422
1423 for i in range(2):
1424 # out2in
1425 pkts = self.create_stream_frag(self.pg0,
1426 self.server_out_addr,
1427 self.port_in,
1428 self.server_out_port,
1429 data,
1430 proto)
1431 pkts.reverse()
1432 self.pg0.add_stream(pkts)
1433 self.pg_enable_capture(self.pg_interfaces)
1434 self.pg_start()
1435 frags = self.pg1.get_capture(len(pkts))
1436 p = self.reass_frags_and_verify(frags,
1437 self.pg0.remote_ip4,
1438 self.server_in_addr)
1439 if proto != IP_PROTOS.icmp:
1440 self.assertEqual(p[layer].dport, self.server_in_port)
1441 self.assertEqual(p[layer].sport, self.port_in)
1442 self.assertEqual(p[layer].dport, self.server_in_port)
1443 else:
1444 self.assertEqual(p[layer].id, self.port_in)
1445 self.assertEqual(data, p[Raw].load)
1446
1447 # in2out
1448 if proto != IP_PROTOS.icmp:
1449 pkts = self.create_stream_frag(self.pg1,
1450 self.pg0.remote_ip4,
1451 self.server_in_port,
1452 p[layer].sport,
1453 data,
1454 proto)
1455 else:
1456 pkts = self.create_stream_frag(self.pg1,
1457 self.pg0.remote_ip4,
1458 p[layer].id,
1459 0,
1460 data,
1461 proto,
1462 echo_reply=True)
1463 pkts.reverse()
1464 self.pg1.add_stream(pkts)
1465 self.pg_enable_capture(self.pg_interfaces)
1466 self.pg_start()
1467 frags = self.pg0.get_capture(len(pkts))
1468 p = self.reass_frags_and_verify(frags,
1469 self.server_out_addr,
1470 self.pg0.remote_ip4)
1471 if proto != IP_PROTOS.icmp:
1472 self.assertEqual(p[layer].sport, self.server_out_port)
1473 self.assertEqual(p[layer].dport, self.port_in)
1474 else:
1475 self.assertEqual(p[layer].id, self.port_in)
1476 self.assertEqual(data, p[Raw].load)
1477
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001478
Matus Fabian2ba92e32017-08-21 07:05:03 -07001479class TestNAT44(MethodHolder):
1480 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001481
1482 @classmethod
1483 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001484 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001485 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001486
1487 try:
1488 cls.tcp_port_in = 6303
1489 cls.tcp_port_out = 6303
1490 cls.udp_port_in = 6304
1491 cls.udp_port_out = 6304
1492 cls.icmp_id_in = 6305
1493 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001494 cls.nat_addr = '10.0.0.3'
Matus Fabian6631e9c2017-05-24 01:52:20 -07001495 cls.ipfix_src_port = 4739
1496 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001497 cls.tcp_external_port = 80
Matus Fabian34931eb2019-02-26 09:05:23 -08001498 cls.udp_external_port = 69
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001499
Matus Fabian36ea2d62017-10-24 04:13:49 -07001500 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001501 cls.interfaces = list(cls.pg_interfaces[0:4])
1502
1503 for i in cls.interfaces:
1504 i.admin_up()
1505 i.config_ip4()
1506 i.resolve_arp()
1507
Matus Fabian6fa74c62017-06-05 05:55:48 -07001508 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001509 cls.pg0.configure_ipv4_neighbors()
1510
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001511 cls.pg1.generate_remote_hosts(1)
1512 cls.pg1.configure_ipv4_neighbors()
1513
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001514 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Ole Troan9a475372019-03-05 16:58:24 +01001515 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1516 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001517
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001518 cls.pg4._local_ip4 = "172.16.255.1"
1519 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001520 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1521 cls.pg4.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001522 cls.pg5._local_ip4 = "172.17.255.3"
1523 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001524 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001525 cls.pg5.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001526 cls.pg6._local_ip4 = "172.16.255.1"
1527 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001528 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1529 cls.pg6.set_table_ip4(20)
1530 for i in cls.overlapping_interfaces:
1531 i.config_ip4()
1532 i.admin_up()
1533 i.resolve_arp()
1534
1535 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001536 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001537
Matus Fabian36ea2d62017-10-24 04:13:49 -07001538 cls.pg9.generate_remote_hosts(2)
1539 cls.pg9.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001540 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01001541 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001542 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1543 address_length=24)
Matus Fabian36ea2d62017-10-24 04:13:49 -07001544 cls.pg9.admin_up()
1545 cls.pg9.resolve_arp()
1546 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1547 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1548 cls.pg9.resolve_arp()
1549
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001550 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001551 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001552 raise
1553
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001554 @classmethod
1555 def tearDownClass(cls):
1556 super(TestNAT44, cls).tearDownClass()
1557
Matus Fabiande886752016-12-07 03:38:19 -08001558 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001559 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001560 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001561 flags = self.config_flags.NAT_IS_INSIDE
1562 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1563 flags=flags)
1564 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001565
1566 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08001567 tcpn = self.statistics.get_counter(
1568 '/err/nat44-in2out-slowpath/TCP packets')
1569 udpn = self.statistics.get_counter(
1570 '/err/nat44-in2out-slowpath/UDP packets')
1571 icmpn = self.statistics.get_counter(
1572 '/err/nat44-in2out-slowpath/ICMP packets')
1573 totaln = self.statistics.get_counter(
1574 '/err/nat44-in2out-slowpath/good in2out packets processed')
1575
Matus Fabiande886752016-12-07 03:38:19 -08001576 pkts = self.create_stream_in(self.pg0, self.pg1)
1577 self.pg0.add_stream(pkts)
1578 self.pg_enable_capture(self.pg_interfaces)
1579 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001580 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001581 self.verify_capture_out(capture)
1582
Matus Fabiana5e73762018-12-14 01:55:16 -08001583 err = self.statistics.get_counter(
1584 '/err/nat44-in2out-slowpath/TCP packets')
1585 self.assertEqual(err - tcpn, 1)
1586 err = self.statistics.get_counter(
1587 '/err/nat44-in2out-slowpath/UDP packets')
1588 self.assertEqual(err - udpn, 1)
1589 err = self.statistics.get_counter(
1590 '/err/nat44-in2out-slowpath/ICMP packets')
1591 self.assertEqual(err - icmpn, 1)
1592 err = self.statistics.get_counter(
1593 '/err/nat44-in2out-slowpath/good in2out packets processed')
1594 self.assertEqual(err - totaln, 3)
1595
Matus Fabiande886752016-12-07 03:38:19 -08001596 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08001597 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1598 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1599 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1600 totaln = self.statistics.get_counter(
1601 '/err/nat44-out2in/good out2in packets processed')
1602
Matus Fabiande886752016-12-07 03:38:19 -08001603 pkts = self.create_stream_out(self.pg1)
1604 self.pg1.add_stream(pkts)
1605 self.pg_enable_capture(self.pg_interfaces)
1606 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001607 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001608 self.verify_capture_in(capture, self.pg0)
1609
Matus Fabiana5e73762018-12-14 01:55:16 -08001610 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1611 self.assertEqual(err - tcpn, 1)
1612 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1613 self.assertEqual(err - udpn, 1)
1614 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1615 self.assertEqual(err - icmpn, 1)
1616 err = self.statistics.get_counter(
1617 '/err/nat44-out2in/good out2in packets processed')
1618 self.assertEqual(err - totaln, 3)
1619
Matus Fabianfd0d5082018-12-18 01:08:51 -08001620 users = self.statistics.get_counter('/nat44/total-users')
1621 self.assertEqual(users[0][0], 1)
1622 sessions = self.statistics.get_counter('/nat44/total-sessions')
1623 self.assertEqual(sessions[0][0], 3)
1624
Juraj Slobodab33f4132017-02-08 23:54:21 -08001625 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001626 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001627
Matus Fabian2ba92e32017-08-21 07:05:03 -07001628 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001629 flags = self.config_flags.NAT_IS_INSIDE
1630 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1631 flags=flags)
1632 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001633
1634 # Client side - generate traffic
1635 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1636 self.pg0.add_stream(pkts)
1637 self.pg_enable_capture(self.pg_interfaces)
1638 self.pg_start()
1639
1640 # Client side - verify ICMP type 11 packets
1641 capture = self.pg0.get_capture(len(pkts))
1642 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1643
1644 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001645 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001646
Matus Fabian2ba92e32017-08-21 07:05:03 -07001647 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001648 flags = self.config_flags.NAT_IS_INSIDE
1649 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1650 flags=flags)
1651 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001652
1653 # Client side - create sessions
1654 pkts = self.create_stream_in(self.pg0, self.pg1)
1655 self.pg0.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1657 self.pg_start()
1658
1659 # Server side - generate traffic
1660 capture = self.pg1.get_capture(len(pkts))
1661 self.verify_capture_out(capture)
1662 pkts = self.create_stream_out(self.pg1, ttl=1)
1663 self.pg1.add_stream(pkts)
1664 self.pg_enable_capture(self.pg_interfaces)
1665 self.pg_start()
1666
1667 # Server side - verify ICMP type 11 packets
1668 capture = self.pg1.get_capture(len(pkts))
1669 self.verify_capture_out_with_icmp_errors(capture,
1670 src_ip=self.pg1.local_ip4)
1671
1672 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001673 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001674
Matus Fabian2ba92e32017-08-21 07:05:03 -07001675 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001676 flags = self.config_flags.NAT_IS_INSIDE
1677 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1678 flags=flags)
1679 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001680
1681 # Client side - generate traffic
1682 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1683 self.pg0.add_stream(pkts)
1684 self.pg_enable_capture(self.pg_interfaces)
1685 self.pg_start()
1686
1687 # Server side - simulate ICMP type 11 response
1688 capture = self.pg1.get_capture(len(pkts))
1689 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001690 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001691 ICMP(type=11) / packet[IP] for packet in capture]
1692 self.pg1.add_stream(pkts)
1693 self.pg_enable_capture(self.pg_interfaces)
1694 self.pg_start()
1695
1696 # Client side - verify ICMP type 11 packets
1697 capture = self.pg0.get_capture(len(pkts))
1698 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1699
1700 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001701 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001702
Matus Fabian2ba92e32017-08-21 07:05:03 -07001703 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001704 flags = self.config_flags.NAT_IS_INSIDE
1705 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1706 flags=flags)
1707 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001708
1709 # Client side - create sessions
1710 pkts = self.create_stream_in(self.pg0, self.pg1)
1711 self.pg0.add_stream(pkts)
1712 self.pg_enable_capture(self.pg_interfaces)
1713 self.pg_start()
1714
1715 # Server side - generate traffic
1716 capture = self.pg1.get_capture(len(pkts))
1717 self.verify_capture_out(capture)
1718 pkts = self.create_stream_out(self.pg1, ttl=2)
1719 self.pg1.add_stream(pkts)
1720 self.pg_enable_capture(self.pg_interfaces)
1721 self.pg_start()
1722
1723 # Client side - simulate ICMP type 11 response
1724 capture = self.pg0.get_capture(len(pkts))
1725 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1726 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1727 ICMP(type=11) / packet[IP] for packet in capture]
1728 self.pg0.add_stream(pkts)
1729 self.pg_enable_capture(self.pg_interfaces)
1730 self.pg_start()
1731
1732 # Server side - verify ICMP type 11 packets
1733 capture = self.pg1.get_capture(len(pkts))
1734 self.verify_capture_out_with_icmp_errors(capture)
1735
Juraj Sloboda665e4822017-02-16 17:17:19 -08001736 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001737 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001738
Matus Fabian2ba92e32017-08-21 07:05:03 -07001739 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001740 flags = self.config_flags.NAT_IS_INSIDE
1741 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1742 flags=flags)
1743 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001744
1745 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1746 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1747 ICMP(id=self.icmp_id_out, type='echo-request'))
1748 pkts = [p]
1749 self.pg1.add_stream(pkts)
1750 self.pg_enable_capture(self.pg_interfaces)
1751 self.pg_start()
1752 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001753 packet = capture[0]
1754 try:
1755 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1756 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1757 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1758 self.assertEqual(packet[ICMP].type, 0) # echo reply
1759 except:
1760 self.logger.error(ppp("Unexpected or invalid packet "
1761 "(outside network):", packet))
1762 raise
1763
Juraj Slobodad3677682017-04-14 03:24:45 +02001764 def test_ping_internal_host_from_outside(self):
1765 """ Ping internal host from outside network """
1766
Matus Fabian2ba92e32017-08-21 07:05:03 -07001767 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001768 flags = self.config_flags.NAT_IS_INSIDE
1769 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1770 flags=flags)
1771 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodad3677682017-04-14 03:24:45 +02001772
1773 # out2in
1774 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001775 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001776 ICMP(id=self.icmp_id_out, type='echo-request'))
1777 self.pg1.add_stream(pkt)
1778 self.pg_enable_capture(self.pg_interfaces)
1779 self.pg_start()
1780 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001781 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001782 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1783
1784 # in2out
1785 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1786 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1787 ICMP(id=self.icmp_id_in, type='echo-reply'))
1788 self.pg0.add_stream(pkt)
1789 self.pg_enable_capture(self.pg_interfaces)
1790 self.pg_start()
1791 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001792 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001793 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1794
Matus Fabianc79396e2018-07-23 00:05:22 -07001795 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001796 """ NAT44 forwarding test """
1797
Filip Vargadd1e3e72019-04-15 18:52:43 +02001798 flags = self.config_flags.NAT_IS_INSIDE
1799 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1800 flags=flags)
1801 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001802 self.vapi.nat44_forwarding_enable_disable(1)
1803
1804 real_ip = self.pg0.remote_ip4n
Filip Vargadd1e3e72019-04-15 18:52:43 +02001805 alias_ip = self.nat_addr
1806 flags = self.config_flags.NAT_IS_ADDR_ONLY
Juraj Sloboda7b929792017-11-23 13:20:48 +01001807 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
Filip Vargadd1e3e72019-04-15 18:52:43 +02001808 external_ip=alias_ip,
1809 flags=flags)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001810
1811 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001812 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001813
1814 pkts = self.create_stream_out(self.pg1)
1815 self.pg1.add_stream(pkts)
1816 self.pg_enable_capture(self.pg_interfaces)
1817 self.pg_start()
1818 capture = self.pg0.get_capture(len(pkts))
1819 self.verify_capture_in(capture, self.pg0)
1820
1821 pkts = self.create_stream_in(self.pg0, self.pg1)
1822 self.pg0.add_stream(pkts)
1823 self.pg_enable_capture(self.pg_interfaces)
1824 self.pg_start()
1825 capture = self.pg1.get_capture(len(pkts))
1826 self.verify_capture_out(capture, same_port=True)
1827
Matus Fabianc79396e2018-07-23 00:05:22 -07001828 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001829
1830 host0 = self.pg0.remote_hosts[0]
1831 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1832 try:
1833 pkts = self.create_stream_out(self.pg1,
1834 dst_ip=self.pg0.remote_ip4,
1835 use_inside_ports=True)
1836 self.pg1.add_stream(pkts)
1837 self.pg_enable_capture(self.pg_interfaces)
1838 self.pg_start()
1839 capture = self.pg0.get_capture(len(pkts))
1840 self.verify_capture_in(capture, self.pg0)
1841
1842 pkts = self.create_stream_in(self.pg0, self.pg1)
1843 self.pg0.add_stream(pkts)
1844 self.pg_enable_capture(self.pg_interfaces)
1845 self.pg_start()
1846 capture = self.pg1.get_capture(len(pkts))
1847 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1848 same_port=True)
1849 finally:
1850 self.pg0.remote_hosts[0] = host0
1851
1852 finally:
1853 self.vapi.nat44_forwarding_enable_disable(0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001854 flags = self.config_flags.NAT_IS_ADDR_ONLY
Juraj Sloboda7b929792017-11-23 13:20:48 +01001855 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1856 external_ip=alias_ip,
Filip Vargadd1e3e72019-04-15 18:52:43 +02001857 is_add=0, flags=flags)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001858
Matus Fabiande886752016-12-07 03:38:19 -08001859 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001860 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001861
1862 nat_ip = "10.0.0.10"
1863 self.tcp_port_out = 6303
1864 self.udp_port_out = 6304
1865 self.icmp_id_out = 6305
1866
Matus Fabian2ba92e32017-08-21 07:05:03 -07001867 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001868 flags = self.config_flags.NAT_IS_INSIDE
1869 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1870 flags=flags)
1871 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08001872 sm = self.vapi.nat44_static_mapping_dump()
1873 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001874 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
Matus Fabian9dba7812018-01-31 01:13:23 -08001875 self.assertEqual(sm[0].protocol, 0)
1876 self.assertEqual(sm[0].local_port, 0)
1877 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001878
1879 # in2out
1880 pkts = self.create_stream_in(self.pg0, self.pg1)
1881 self.pg0.add_stream(pkts)
1882 self.pg_enable_capture(self.pg_interfaces)
1883 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001884 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001885 self.verify_capture_out(capture, nat_ip, True)
1886
1887 # out2in
1888 pkts = self.create_stream_out(self.pg1, nat_ip)
1889 self.pg1.add_stream(pkts)
1890 self.pg_enable_capture(self.pg_interfaces)
1891 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001892 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001893 self.verify_capture_in(capture, self.pg0)
1894
1895 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001896 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001897
1898 nat_ip = "10.0.0.20"
1899 self.tcp_port_out = 6303
1900 self.udp_port_out = 6304
1901 self.icmp_id_out = 6305
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001902 tag = b"testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001903
Matus Fabian5f224992018-01-25 21:59:16 -08001904 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001905 flags = self.config_flags.NAT_IS_INSIDE
1906 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1907 flags=flags)
1908 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08001909 sm = self.vapi.nat44_static_mapping_dump()
1910 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001911 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001912
1913 # out2in
1914 pkts = self.create_stream_out(self.pg1, nat_ip)
1915 self.pg1.add_stream(pkts)
1916 self.pg_enable_capture(self.pg_interfaces)
1917 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001918 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001919 self.verify_capture_in(capture, self.pg0)
1920
1921 # in2out
1922 pkts = self.create_stream_in(self.pg0, self.pg1)
1923 self.pg0.add_stream(pkts)
1924 self.pg_enable_capture(self.pg_interfaces)
1925 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001926 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001927 self.verify_capture_out(capture, nat_ip, True)
1928
1929 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001930 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001931
1932 self.tcp_port_out = 3606
1933 self.udp_port_out = 3607
1934 self.icmp_id_out = 3608
1935
Matus Fabian2ba92e32017-08-21 07:05:03 -07001936 self.nat44_add_address(self.nat_addr)
1937 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1938 self.tcp_port_in, self.tcp_port_out,
1939 proto=IP_PROTOS.tcp)
1940 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1941 self.udp_port_in, self.udp_port_out,
1942 proto=IP_PROTOS.udp)
1943 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1944 self.icmp_id_in, self.icmp_id_out,
1945 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001946 flags = self.config_flags.NAT_IS_INSIDE
1947 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1948 flags=flags)
1949 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001950
1951 # in2out
1952 pkts = self.create_stream_in(self.pg0, self.pg1)
1953 self.pg0.add_stream(pkts)
1954 self.pg_enable_capture(self.pg_interfaces)
1955 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001956 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001957 self.verify_capture_out(capture)
1958
1959 # out2in
1960 pkts = self.create_stream_out(self.pg1)
1961 self.pg1.add_stream(pkts)
1962 self.pg_enable_capture(self.pg_interfaces)
1963 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001964 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001965 self.verify_capture_in(capture, self.pg0)
1966
1967 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001968 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001969
1970 self.tcp_port_out = 30606
1971 self.udp_port_out = 30607
1972 self.icmp_id_out = 30608
1973
Matus Fabian2ba92e32017-08-21 07:05:03 -07001974 self.nat44_add_address(self.nat_addr)
1975 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1976 self.tcp_port_in, self.tcp_port_out,
1977 proto=IP_PROTOS.tcp)
1978 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1979 self.udp_port_in, self.udp_port_out,
1980 proto=IP_PROTOS.udp)
1981 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1982 self.icmp_id_in, self.icmp_id_out,
1983 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001984 flags = self.config_flags.NAT_IS_INSIDE
1985 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1986 flags=flags)
1987 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001988
1989 # out2in
1990 pkts = self.create_stream_out(self.pg1)
1991 self.pg1.add_stream(pkts)
1992 self.pg_enable_capture(self.pg_interfaces)
1993 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001994 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001995 self.verify_capture_in(capture, self.pg0)
1996
1997 # in2out
1998 pkts = self.create_stream_in(self.pg0, self.pg1)
1999 self.pg0.add_stream(pkts)
2000 self.pg_enable_capture(self.pg_interfaces)
2001 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002002 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002003 self.verify_capture_out(capture)
2004
2005 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002006 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08002007
2008 nat_ip1 = "10.0.0.30"
2009 nat_ip2 = "10.0.0.40"
2010 self.tcp_port_out = 6303
2011 self.udp_port_out = 6304
2012 self.icmp_id_out = 6305
2013
Matus Fabian2ba92e32017-08-21 07:05:03 -07002014 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2015 vrf_id=10)
2016 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2017 vrf_id=10)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002018 flags = self.config_flags.NAT_IS_INSIDE
2019 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index)
2020 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2021 flags=flags)
2022 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
2023 flags=flags)
Matus Fabiande886752016-12-07 03:38:19 -08002024
Matus Fabian2ba92e32017-08-21 07:05:03 -07002025 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002026 pkts = self.create_stream_in(self.pg4, self.pg3)
2027 self.pg4.add_stream(pkts)
2028 self.pg_enable_capture(self.pg_interfaces)
2029 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002030 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002031 self.verify_capture_out(capture, nat_ip1, True)
2032
Matus Fabian2ba92e32017-08-21 07:05:03 -07002033 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002034 # are dropped)
2035 pkts = self.create_stream_in(self.pg0, self.pg3)
2036 self.pg0.add_stream(pkts)
2037 self.pg_enable_capture(self.pg_interfaces)
2038 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002039 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002040
Matus Fabianb793d092018-01-31 05:50:21 -08002041 def test_dynamic_to_static(self):
2042 """ Switch from dynamic translation to 1:1NAT """
2043 nat_ip = "10.0.0.10"
2044 self.tcp_port_out = 6303
2045 self.udp_port_out = 6304
2046 self.icmp_id_out = 6305
2047
2048 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002049 flags = self.config_flags.NAT_IS_INSIDE
2050 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2051 flags=flags)
2052 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianb793d092018-01-31 05:50:21 -08002053
2054 # dynamic
2055 pkts = self.create_stream_in(self.pg0, self.pg1)
2056 self.pg0.add_stream(pkts)
2057 self.pg_enable_capture(self.pg_interfaces)
2058 self.pg_start()
2059 capture = self.pg1.get_capture(len(pkts))
2060 self.verify_capture_out(capture)
2061
2062 # 1:1NAT
2063 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2064 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2065 self.assertEqual(len(sessions), 0)
2066 pkts = self.create_stream_in(self.pg0, self.pg1)
2067 self.pg0.add_stream(pkts)
2068 self.pg_enable_capture(self.pg_interfaces)
2069 self.pg_start()
2070 capture = self.pg1.get_capture(len(pkts))
2071 self.verify_capture_out(capture, nat_ip, True)
2072
Matus Fabianab7a8052017-11-28 04:29:41 -08002073 def test_identity_nat(self):
2074 """ Identity NAT """
Filip Vargadd1e3e72019-04-15 18:52:43 +02002075 flags = self.config_flags.NAT_IS_ADDR_ONLY
2076 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2077 flags=flags)
2078 flags = self.config_flags.NAT_IS_INSIDE
2079 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2080 flags=flags)
2081 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002082
2083 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2084 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2085 TCP(sport=12345, dport=56789))
2086 self.pg1.add_stream(p)
2087 self.pg_enable_capture(self.pg_interfaces)
2088 self.pg_start()
2089 capture = self.pg0.get_capture(1)
2090 p = capture[0]
2091 try:
2092 ip = p[IP]
2093 tcp = p[TCP]
2094 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2095 self.assertEqual(ip.src, self.pg1.remote_ip4)
2096 self.assertEqual(tcp.dport, 56789)
2097 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002098 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002099 except:
2100 self.logger.error(ppp("Unexpected or invalid packet:", p))
2101 raise
2102
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002103 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2104 self.assertEqual(len(sessions), 0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002105 flags = self.config_flags.NAT_IS_ADDR_ONLY
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002106 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02002107 flags=flags, vrf_id=1)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002108 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2109 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002110
Matus Fabiande886752016-12-07 03:38:19 -08002111 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002112 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002113
Matus Fabian2ba92e32017-08-21 07:05:03 -07002114 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002115 flags = self.config_flags.NAT_IS_INSIDE
2116 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2117 flags=flags)
2118 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2119 flags=flags)
2120 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08002121
Matus Fabian2ba92e32017-08-21 07:05:03 -07002122 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002123 pkts = self.create_stream_in(self.pg0, self.pg1)
2124 self.pg0.add_stream(pkts)
2125 self.pg_enable_capture(self.pg_interfaces)
2126 self.pg_start()
2127 capture = self.pg1.get_capture(len(pkts))
2128 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2129
Matus Fabian2ba92e32017-08-21 07:05:03 -07002130 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002131 pkts = self.create_stream_in(self.pg0, self.pg2)
2132 self.pg0.add_stream(pkts)
2133 self.pg_enable_capture(self.pg_interfaces)
2134 self.pg_start()
2135 capture = self.pg2.get_capture(len(pkts))
2136 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2137
Matus Fabiande886752016-12-07 03:38:19 -08002138 # in2out 1st interface
2139 pkts = self.create_stream_in(self.pg0, self.pg3)
2140 self.pg0.add_stream(pkts)
2141 self.pg_enable_capture(self.pg_interfaces)
2142 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002143 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002144 self.verify_capture_out(capture)
2145
2146 # out2in 1st interface
2147 pkts = self.create_stream_out(self.pg3)
2148 self.pg3.add_stream(pkts)
2149 self.pg_enable_capture(self.pg_interfaces)
2150 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002151 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002152 self.verify_capture_in(capture, self.pg0)
2153
2154 # in2out 2nd interface
2155 pkts = self.create_stream_in(self.pg1, self.pg3)
2156 self.pg1.add_stream(pkts)
2157 self.pg_enable_capture(self.pg_interfaces)
2158 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002159 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002160 self.verify_capture_out(capture)
2161
2162 # out2in 2nd interface
2163 pkts = self.create_stream_out(self.pg3)
2164 self.pg3.add_stream(pkts)
2165 self.pg_enable_capture(self.pg_interfaces)
2166 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002167 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002168 self.verify_capture_in(capture, self.pg1)
2169
Matus Fabiande886752016-12-07 03:38:19 -08002170 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002171 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002172
Matus Fabian675a69c2017-01-18 01:46:01 -08002173 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002174 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002175 flags = self.config_flags.NAT_IS_INSIDE
2176 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index)
2177 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
2178 flags=flags)
2179 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
2180 flags=flags)
2181 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
2182 flags=flags)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002183 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2184 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002185
Matus Fabian2ba92e32017-08-21 07:05:03 -07002186 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002187 pkts = self.create_stream_in(self.pg4, self.pg5)
2188 self.pg4.add_stream(pkts)
2189 self.pg_enable_capture(self.pg_interfaces)
2190 self.pg_start()
2191 capture = self.pg5.get_capture(len(pkts))
2192 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2193
Matus Fabian2ba92e32017-08-21 07:05:03 -07002194 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002195 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2196 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2197 TCP(sport=1234, dport=5678))
2198 self.pg4.add_stream(p)
2199 self.pg_enable_capture(self.pg_interfaces)
2200 self.pg_start()
2201 capture = self.pg6.get_capture(1)
2202 p = capture[0]
2203 try:
2204 ip = p[IP]
2205 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002206 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002207 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2208 self.assertNotEqual(tcp.sport, 1234)
2209 self.assertEqual(tcp.dport, 5678)
2210 except:
2211 self.logger.error(ppp("Unexpected or invalid packet:", p))
2212 raise
Matus Fabiande886752016-12-07 03:38:19 -08002213
2214 # in2out 1st interface
2215 pkts = self.create_stream_in(self.pg4, self.pg3)
2216 self.pg4.add_stream(pkts)
2217 self.pg_enable_capture(self.pg_interfaces)
2218 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002219 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002220 self.verify_capture_out(capture)
2221
2222 # out2in 1st interface
2223 pkts = self.create_stream_out(self.pg3)
2224 self.pg3.add_stream(pkts)
2225 self.pg_enable_capture(self.pg_interfaces)
2226 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002227 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002228 self.verify_capture_in(capture, self.pg4)
2229
2230 # in2out 2nd interface
2231 pkts = self.create_stream_in(self.pg5, self.pg3)
2232 self.pg5.add_stream(pkts)
2233 self.pg_enable_capture(self.pg_interfaces)
2234 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002235 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002236 self.verify_capture_out(capture)
2237
2238 # out2in 2nd interface
2239 pkts = self.create_stream_out(self.pg3)
2240 self.pg3.add_stream(pkts)
2241 self.pg_enable_capture(self.pg_interfaces)
2242 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002243 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002244 self.verify_capture_in(capture, self.pg5)
2245
magalik23caa882017-02-08 23:25:45 -08002246 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002247 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002248 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002249 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002250 self.assertEqual(len(sessions), 3)
2251 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002252 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2253 self.assertEqual(str(session.inside_ip_address),
2254 self.pg5.remote_ip4)
magalik23caa882017-02-08 23:25:45 -08002255 self.assertEqual(session.outside_ip_address,
2256 addresses[0].ip_address)
2257 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2258 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2259 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2260 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2261 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2262 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2263 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2264 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2265 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2266
Matus Fabiande886752016-12-07 03:38:19 -08002267 # in2out 3rd interface
2268 pkts = self.create_stream_in(self.pg6, self.pg3)
2269 self.pg6.add_stream(pkts)
2270 self.pg_enable_capture(self.pg_interfaces)
2271 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002272 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002273 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002274
2275 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002276 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002277 self.pg3.add_stream(pkts)
2278 self.pg_enable_capture(self.pg_interfaces)
2279 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002280 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002281 self.verify_capture_in(capture, self.pg6)
2282
magalik23caa882017-02-08 23:25:45 -08002283 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002284 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002285 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002286 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002287 self.assertEqual(len(addresses), 1)
2288 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002289 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2290 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002291 for session in sessions:
2292 self.assertEqual(user.ip_address, session.inside_ip_address)
2293 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2294 self.assertTrue(session.protocol in
2295 [IP_PROTOS.tcp, IP_PROTOS.udp,
2296 IP_PROTOS.icmp])
Filip Vargadd1e3e72019-04-15 18:52:43 +02002297 self.assertFalse(session.flags &
2298 self.config_flags.NAT_IS_EXT_HOST_VALID)
magalik23caa882017-02-08 23:25:45 -08002299
2300 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002301 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002302 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002303 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.pg4.remote_ip4)
magalik23caa882017-02-08 23:25:45 -08002307 self.assertEqual(session.outside_ip_address,
2308 addresses[0].ip_address)
2309
2310 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002311 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002312 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002313 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002314 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2315 self.assertEqual(str(session.inside_ip_address),
2316 self.pg6.remote_ip4)
2317 self.assertEqual(str(session.outside_ip_address),
2318 static_nat_ip)
magalik23caa882017-02-08 23:25:45 -08002319 self.assertTrue(session.inside_port in
2320 [self.tcp_port_in, self.udp_port_in,
2321 self.icmp_id_in])
2322
Matus Fabianf78a70d2016-12-12 04:30:39 -08002323 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002324 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002325
2326 host = self.pg0.remote_hosts[0]
2327 server = self.pg0.remote_hosts[1]
2328 host_in_port = 1234
2329 host_out_port = 0
2330 server_in_port = 5678
2331 server_out_port = 8765
2332
Matus Fabian2ba92e32017-08-21 07:05:03 -07002333 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002334 flags = self.config_flags.NAT_IS_INSIDE
2335 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2336 flags=flags)
2337 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2338
Matus Fabianf78a70d2016-12-12 04:30:39 -08002339 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002340 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2341 server_in_port, server_out_port,
2342 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002343
2344 # send packet from host to server
2345 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002346 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002347 TCP(sport=host_in_port, dport=server_out_port))
2348 self.pg0.add_stream(p)
2349 self.pg_enable_capture(self.pg_interfaces)
2350 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002351 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002352 p = capture[0]
2353 try:
2354 ip = p[IP]
2355 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002356 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002357 self.assertEqual(ip.dst, server.ip4)
2358 self.assertNotEqual(tcp.sport, host_in_port)
2359 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002360 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002361 host_out_port = tcp.sport
2362 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002363 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002364 raise
2365
2366 # send reply from server to host
2367 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002368 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002369 TCP(sport=server_in_port, dport=host_out_port))
2370 self.pg0.add_stream(p)
2371 self.pg_enable_capture(self.pg_interfaces)
2372 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002373 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002374 p = capture[0]
2375 try:
2376 ip = p[IP]
2377 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002378 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002379 self.assertEqual(ip.dst, host.ip4)
2380 self.assertEqual(tcp.sport, server_out_port)
2381 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002382 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002383 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002384 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002385 raise
2386
Matus Fabian6fa74c62017-06-05 05:55:48 -07002387 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002388 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002389
2390 server1_nat_ip = "10.0.0.10"
2391 server2_nat_ip = "10.0.0.11"
2392 host = self.pg0.remote_hosts[0]
2393 server1 = self.pg0.remote_hosts[1]
2394 server2 = self.pg0.remote_hosts[2]
2395 server_tcp_port = 22
2396 server_udp_port = 20
2397
Matus Fabian2ba92e32017-08-21 07:05:03 -07002398 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002399 flags = self.config_flags.NAT_IS_INSIDE
2400 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2401 flags=flags)
2402 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002403
2404 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002405 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2406 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002407
2408 # host to server1
2409 pkts = []
2410 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2411 IP(src=host.ip4, dst=server1_nat_ip) /
2412 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2413 pkts.append(p)
2414 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2415 IP(src=host.ip4, dst=server1_nat_ip) /
2416 UDP(sport=self.udp_port_in, dport=server_udp_port))
2417 pkts.append(p)
2418 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2419 IP(src=host.ip4, dst=server1_nat_ip) /
2420 ICMP(id=self.icmp_id_in, type='echo-request'))
2421 pkts.append(p)
2422 self.pg0.add_stream(pkts)
2423 self.pg_enable_capture(self.pg_interfaces)
2424 self.pg_start()
2425 capture = self.pg0.get_capture(len(pkts))
2426 for packet in capture:
2427 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002428 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002429 self.assertEqual(packet[IP].dst, server1.ip4)
2430 if packet.haslayer(TCP):
2431 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2432 self.assertEqual(packet[TCP].dport, server_tcp_port)
2433 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002434 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002435 elif packet.haslayer(UDP):
2436 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2437 self.assertEqual(packet[UDP].dport, server_udp_port)
2438 self.udp_port_out = packet[UDP].sport
2439 else:
2440 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2441 self.icmp_id_out = packet[ICMP].id
2442 except:
2443 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2444 raise
2445
2446 # server1 to host
2447 pkts = []
2448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002449 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002450 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2451 pkts.append(p)
2452 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002453 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002454 UDP(sport=server_udp_port, dport=self.udp_port_out))
2455 pkts.append(p)
2456 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002457 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002458 ICMP(id=self.icmp_id_out, type='echo-reply'))
2459 pkts.append(p)
2460 self.pg0.add_stream(pkts)
2461 self.pg_enable_capture(self.pg_interfaces)
2462 self.pg_start()
2463 capture = self.pg0.get_capture(len(pkts))
2464 for packet in capture:
2465 try:
2466 self.assertEqual(packet[IP].src, server1_nat_ip)
2467 self.assertEqual(packet[IP].dst, host.ip4)
2468 if packet.haslayer(TCP):
2469 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2470 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002471 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002472 elif packet.haslayer(UDP):
2473 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2474 self.assertEqual(packet[UDP].sport, server_udp_port)
2475 else:
2476 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2477 except:
2478 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2479 raise
2480
2481 # server2 to server1
2482 pkts = []
2483 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2484 IP(src=server2.ip4, dst=server1_nat_ip) /
2485 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2486 pkts.append(p)
2487 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2488 IP(src=server2.ip4, dst=server1_nat_ip) /
2489 UDP(sport=self.udp_port_in, dport=server_udp_port))
2490 pkts.append(p)
2491 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2492 IP(src=server2.ip4, dst=server1_nat_ip) /
2493 ICMP(id=self.icmp_id_in, type='echo-request'))
2494 pkts.append(p)
2495 self.pg0.add_stream(pkts)
2496 self.pg_enable_capture(self.pg_interfaces)
2497 self.pg_start()
2498 capture = self.pg0.get_capture(len(pkts))
2499 for packet in capture:
2500 try:
2501 self.assertEqual(packet[IP].src, server2_nat_ip)
2502 self.assertEqual(packet[IP].dst, server1.ip4)
2503 if packet.haslayer(TCP):
2504 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2505 self.assertEqual(packet[TCP].dport, server_tcp_port)
2506 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002507 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002508 elif packet.haslayer(UDP):
2509 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2510 self.assertEqual(packet[UDP].dport, server_udp_port)
2511 self.udp_port_out = packet[UDP].sport
2512 else:
2513 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2514 self.icmp_id_out = packet[ICMP].id
2515 except:
2516 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2517 raise
2518
2519 # server1 to server2
2520 pkts = []
2521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2522 IP(src=server1.ip4, dst=server2_nat_ip) /
2523 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2524 pkts.append(p)
2525 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2526 IP(src=server1.ip4, dst=server2_nat_ip) /
2527 UDP(sport=server_udp_port, dport=self.udp_port_out))
2528 pkts.append(p)
2529 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2530 IP(src=server1.ip4, dst=server2_nat_ip) /
2531 ICMP(id=self.icmp_id_out, type='echo-reply'))
2532 pkts.append(p)
2533 self.pg0.add_stream(pkts)
2534 self.pg_enable_capture(self.pg_interfaces)
2535 self.pg_start()
2536 capture = self.pg0.get_capture(len(pkts))
2537 for packet in capture:
2538 try:
2539 self.assertEqual(packet[IP].src, server1_nat_ip)
2540 self.assertEqual(packet[IP].dst, server2.ip4)
2541 if packet.haslayer(TCP):
2542 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2543 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002544 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002545 elif packet.haslayer(UDP):
2546 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2547 self.assertEqual(packet[UDP].sport, server_udp_port)
2548 else:
2549 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2550 except:
2551 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2552 raise
2553
Matus Fabian9902fcd2016-12-21 23:58:46 -08002554 def test_max_translations_per_user(self):
2555 """ MAX translations per user - recycle the least recently used """
2556
Matus Fabian2ba92e32017-08-21 07:05:03 -07002557 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002558 flags = self.config_flags.NAT_IS_INSIDE
2559 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2560 flags=flags)
2561 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002562
2563 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002564 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002565
2566 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002567 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002568 pkts = []
2569 for port in range(0, pkts_num):
2570 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2571 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2572 TCP(sport=1025 + port))
2573 pkts.append(p)
2574 self.pg0.add_stream(pkts)
2575 self.pg_enable_capture(self.pg_interfaces)
2576 self.pg_start()
2577
2578 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002579 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002580
Matus Fabian132dc492018-05-09 04:51:03 -07002581 users = self.vapi.nat44_user_dump()
2582 for user in users:
2583 if user.ip_address == self.pg0.remote_ip4n:
2584 self.assertEqual(user.nsessions,
2585 nat44_config.max_translations_per_user)
2586 self.assertEqual(user.nstaticsessions, 0)
2587
2588 tcp_port = 22
2589 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2590 tcp_port, tcp_port,
2591 proto=IP_PROTOS.tcp)
2592 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2593 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2594 TCP(sport=tcp_port))
2595 self.pg0.add_stream(p)
2596 self.pg_enable_capture(self.pg_interfaces)
2597 self.pg_start()
2598 self.pg1.get_capture(1)
2599 users = self.vapi.nat44_user_dump()
2600 for user in users:
2601 if user.ip_address == self.pg0.remote_ip4n:
2602 self.assertEqual(user.nsessions,
2603 nat44_config.max_translations_per_user - 1)
2604 self.assertEqual(user.nstaticsessions, 1)
2605
Matus Fabian8bf68e82017-01-12 04:24:35 -08002606 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002607 """ Acquire NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01002608 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002609
2610 # no address in NAT pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002611 addresses = self.vapi.nat44_address_dump()
2612 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002613
2614 # configure interface address and check NAT address pool
2615 self.pg7.config_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002616 addresses = self.vapi.nat44_address_dump()
2617 self.assertEqual(1, len(addresses))
Filip Vargadd1e3e72019-04-15 18:52:43 +02002618 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002619
2620 # remove interface address and check NAT address pool
2621 self.pg7.unconfig_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002622 addresses = self.vapi.nat44_address_dump()
2623 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002624
Matus Fabian36532bd2017-01-23 23:42:28 -08002625 def test_interface_addr_static_mapping(self):
2626 """ Static mapping with addresses from interface """
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002627 tag = b"testTAG"
Matus Fabian5f224992018-01-25 21:59:16 -08002628
Ole Troane1ade682019-03-04 23:55:43 +01002629 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002630 self.nat44_add_static_mapping(
2631 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002632 external_sw_if_index=self.pg7.sw_if_index,
2633 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002634
Matus Fabiane22e5462017-02-14 23:33:43 -08002635 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002636 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002637 self.assertEqual(1, len(static_mappings))
2638 self.assertEqual(self.pg7.sw_if_index,
2639 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002640 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002641
2642 # configure interface address and check static mappings
2643 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002644 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002645 self.assertEqual(2, len(static_mappings))
2646 resolved = False
2647 for sm in static_mappings:
2648 if sm.external_sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002649 self.assertEqual(str(sm.external_ip_address),
2650 self.pg7.local_ip4)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002651 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002652 resolved = True
2653 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002654
2655 # remove interface address and check static mappings
2656 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002657 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002658 self.assertEqual(1, len(static_mappings))
2659 self.assertEqual(self.pg7.sw_if_index,
2660 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002661 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002662
2663 # configure interface address again and check static mappings
2664 self.pg7.config_ip4()
2665 static_mappings = self.vapi.nat44_static_mapping_dump()
2666 self.assertEqual(2, len(static_mappings))
2667 resolved = False
2668 for sm in static_mappings:
2669 if sm.external_sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002670 self.assertEqual(str(sm.external_ip_address),
2671 self.pg7.local_ip4)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002672 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002673 resolved = True
2674 self.assertTrue(resolved)
2675
2676 # remove static mapping
2677 self.nat44_add_static_mapping(
2678 '1.2.3.4',
2679 external_sw_if_index=self.pg7.sw_if_index,
2680 tag=tag,
2681 is_add=0)
2682 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002683 self.assertEqual(0, len(static_mappings))
2684
Matus Fabianab7a8052017-11-28 04:29:41 -08002685 def test_interface_addr_identity_nat(self):
2686 """ Identity NAT with addresses from interface """
2687
2688 port = 53053
Ole Troane1ade682019-03-04 23:55:43 +01002689 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002690 self.vapi.nat44_add_del_identity_mapping(
2691 sw_if_index=self.pg7.sw_if_index,
2692 port=port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02002693 protocol=IP_PROTOS.tcp)
Matus Fabianab7a8052017-11-28 04:29:41 -08002694
2695 # identity mappings with external interface
2696 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2697 self.assertEqual(1, len(identity_mappings))
2698 self.assertEqual(self.pg7.sw_if_index,
2699 identity_mappings[0].sw_if_index)
2700
2701 # configure interface address and check identity mappings
2702 self.pg7.config_ip4()
2703 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002704 resolved = False
2705 self.assertEqual(2, len(identity_mappings))
2706 for sm in identity_mappings:
2707 if sm.sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002708 self.assertEqual(str(identity_mappings[0].ip_address),
2709 self.pg7.local_ip4)
Matus Fabianea2600a2018-03-28 04:06:26 -07002710 self.assertEqual(port, identity_mappings[0].port)
2711 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2712 resolved = True
2713 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002714
2715 # remove interface address and check identity mappings
2716 self.pg7.unconfig_ip4()
2717 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002718 self.assertEqual(1, len(identity_mappings))
2719 self.assertEqual(self.pg7.sw_if_index,
2720 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002721
Matus Fabianeea28d72017-01-13 04:15:54 -08002722 def test_ipfix_nat44_sess(self):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002723 """ IPFIX logging NAT44 session created/deleted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002724 self.ipfix_domain_id = 10
2725 self.ipfix_src_port = 20202
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002726 collector_port = 30303
Matus Fabian6631e9c2017-05-24 01:52:20 -07002727 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002728 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002729 flags = self.config_flags.NAT_IS_INSIDE
2730 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2731 flags=flags)
2732 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianeea28d72017-01-13 04:15:54 -08002733 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2734 src_address=self.pg3.local_ip4n,
2735 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002736 template_interval=10,
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002737 collector_port=collector_port)
Ole Troane1ade682019-03-04 23:55:43 +01002738 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2739 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002740
2741 pkts = self.create_stream_in(self.pg0, self.pg1)
2742 self.pg0.add_stream(pkts)
2743 self.pg_enable_capture(self.pg_interfaces)
2744 self.pg_start()
2745 capture = self.pg1.get_capture(len(pkts))
2746 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002747 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002748 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002749 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002750 ipfix = IPFIXDecoder()
2751 # first load template
2752 for p in capture:
2753 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002754 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2755 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2756 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002757 self.assertEqual(p[UDP].dport, collector_port)
Matus Fabian6631e9c2017-05-24 01:52:20 -07002758 self.assertEqual(p[IPFIX].observationDomainID,
2759 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002760 if p.haslayer(Template):
2761 ipfix.add_template(p.getlayer(Template))
2762 # verify events in data set
2763 for p in capture:
2764 if p.haslayer(Data):
2765 data = ipfix.decode_data_set(p.getlayer(Set))
2766 self.verify_ipfix_nat44_ses(data)
2767
2768 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002769 """ IPFIX logging NAT addresses exhausted """
Filip Vargadd1e3e72019-04-15 18:52:43 +02002770 flags = self.config_flags.NAT_IS_INSIDE
2771 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2772 flags=flags)
2773 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianeea28d72017-01-13 04:15:54 -08002774 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2775 src_address=self.pg3.local_ip4n,
2776 path_mtu=512,
2777 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002778 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2779 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002780
2781 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2782 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2783 TCP(sport=3025))
2784 self.pg0.add_stream(p)
2785 self.pg_enable_capture(self.pg_interfaces)
2786 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002787 self.pg1.assert_nothing_captured()
2788 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002789 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002790 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002791 ipfix = IPFIXDecoder()
2792 # first load template
2793 for p in capture:
2794 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002795 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2796 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2797 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2798 self.assertEqual(p[UDP].dport, 4739)
2799 self.assertEqual(p[IPFIX].observationDomainID,
2800 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002801 if p.haslayer(Template):
2802 ipfix.add_template(p.getlayer(Template))
2803 # verify events in data set
2804 for p in capture:
2805 if p.haslayer(Data):
2806 data = ipfix.decode_data_set(p.getlayer(Set))
2807 self.verify_ipfix_addr_exhausted(data)
2808
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002809 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002810 def test_ipfix_max_sessions(self):
2811 """ IPFIX logging maximum session entries exceeded """
2812 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002813 flags = self.config_flags.NAT_IS_INSIDE
2814 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2815 flags=flags)
2816 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08002817
2818 nat44_config = self.vapi.nat_show_config()
2819 max_sessions = 10 * nat44_config.translation_buckets
2820
2821 pkts = []
2822 for i in range(0, max_sessions):
2823 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2824 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2825 IP(src=src, dst=self.pg1.remote_ip4) /
2826 TCP(sport=1025))
2827 pkts.append(p)
2828 self.pg0.add_stream(pkts)
2829 self.pg_enable_capture(self.pg_interfaces)
2830 self.pg_start()
2831
2832 self.pg1.get_capture(max_sessions)
2833 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2834 src_address=self.pg3.local_ip4n,
2835 path_mtu=512,
2836 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002837 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2838 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08002839
2840 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2841 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2842 TCP(sport=1025))
2843 self.pg0.add_stream(p)
2844 self.pg_enable_capture(self.pg_interfaces)
2845 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002846 self.pg1.assert_nothing_captured()
2847 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002848 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2849 capture = self.pg3.get_capture(9)
2850 ipfix = IPFIXDecoder()
2851 # first load template
2852 for p in capture:
2853 self.assertTrue(p.haslayer(IPFIX))
2854 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2855 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2856 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2857 self.assertEqual(p[UDP].dport, 4739)
2858 self.assertEqual(p[IPFIX].observationDomainID,
2859 self.ipfix_domain_id)
2860 if p.haslayer(Template):
2861 ipfix.add_template(p.getlayer(Template))
2862 # verify events in data set
2863 for p in capture:
2864 if p.haslayer(Data):
2865 data = ipfix.decode_data_set(p.getlayer(Set))
2866 self.verify_ipfix_max_sessions(data, max_sessions)
2867
Matus Fabianad1f3e12018-11-28 21:26:34 -08002868 def test_syslog_apmap(self):
2869 """ Test syslog address and port mapping creation and deletion """
2870 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01002871 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002872 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002873 flags = self.config_flags.NAT_IS_INSIDE
2874 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2875 flags=flags)
2876 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002877
2878 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2879 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2880 TCP(sport=self.tcp_port_in, dport=20))
2881 self.pg0.add_stream(p)
2882 self.pg_enable_capture(self.pg_interfaces)
2883 self.pg_start()
2884 capture = self.pg1.get_capture(1)
2885 self.tcp_port_out = capture[0][TCP].sport
2886 capture = self.pg3.get_capture(1)
2887 self.verify_syslog_apmap(capture[0][Raw].load)
2888
2889 self.pg_enable_capture(self.pg_interfaces)
2890 self.pg_start()
2891 self.nat44_add_address(self.nat_addr, is_add=0)
2892 capture = self.pg3.get_capture(1)
2893 self.verify_syslog_apmap(capture[0][Raw].load, False)
2894
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002895 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002896 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002897 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002898 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002899 flags = self.config_flags.NAT_IS_INSIDE
2900 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2901 flags=flags)
2902 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002903 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002904
Matus Fabian2ba92e32017-08-21 07:05:03 -07002905 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002906 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002907 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002908 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2909 self.pg1.add_stream(p)
2910 self.pg_enable_capture(self.pg_interfaces)
2911 self.pg_start()
2912 capture = self.pg1.get_capture(1)
2913 self.assertTrue(capture[0].haslayer(ARP))
2914 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2915
2916 # 1:1 NAT address
2917 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2918 ARP(op=ARP.who_has, pdst=static_addr,
2919 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2920 self.pg1.add_stream(p)
2921 self.pg_enable_capture(self.pg_interfaces)
2922 self.pg_start()
2923 capture = self.pg1.get_capture(1)
2924 self.assertTrue(capture[0].haslayer(ARP))
2925 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2926
Matus Fabian2ba92e32017-08-21 07:05:03 -07002927 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002928 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002929 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002930 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2931 self.pg2.add_stream(p)
2932 self.pg_enable_capture(self.pg_interfaces)
2933 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002934 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002935
2936 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002937 self.nat44_add_address(self.nat_addr, is_add=0)
2938 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2939 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002940
2941 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002942 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002943 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2944 self.pg1.add_stream(p)
2945 self.pg_enable_capture(self.pg_interfaces)
2946 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002947 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002948
2949 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2950 ARP(op=ARP.who_has, pdst=static_addr,
2951 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2952 self.pg1.add_stream(p)
2953 self.pg_enable_capture(self.pg_interfaces)
2954 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002955 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002956
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002957 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002958 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002959
2960 vrf_id1 = 1
2961 vrf_id2 = 2
2962 nat_ip1 = "10.0.0.10"
2963 nat_ip2 = "10.0.0.11"
2964
2965 self.pg0.unconfig_ip4()
2966 self.pg1.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01002967 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
2968 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002969 self.pg0.set_table_ip4(vrf_id1)
2970 self.pg1.set_table_ip4(vrf_id2)
2971 self.pg0.config_ip4()
2972 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002973 self.pg0.resolve_arp()
2974 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002975
Matus Fabian2ba92e32017-08-21 07:05:03 -07002976 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2977 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002978 flags = self.config_flags.NAT_IS_INSIDE
2979 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2980 flags=flags)
2981 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2982 flags=flags)
2983 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002984
Matus Fabian8008d7c2018-07-09 01:34:20 -07002985 try:
2986 # first VRF
2987 pkts = self.create_stream_in(self.pg0, self.pg2)
2988 self.pg0.add_stream(pkts)
2989 self.pg_enable_capture(self.pg_interfaces)
2990 self.pg_start()
2991 capture = self.pg2.get_capture(len(pkts))
2992 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002993
Matus Fabian8008d7c2018-07-09 01:34:20 -07002994 # second VRF
2995 pkts = self.create_stream_in(self.pg1, self.pg2)
2996 self.pg1.add_stream(pkts)
2997 self.pg_enable_capture(self.pg_interfaces)
2998 self.pg_start()
2999 capture = self.pg2.get_capture(len(pkts))
3000 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003001
Matus Fabian8008d7c2018-07-09 01:34:20 -07003002 finally:
3003 self.pg0.unconfig_ip4()
3004 self.pg1.unconfig_ip4()
3005 self.pg0.set_table_ip4(0)
3006 self.pg1.set_table_ip4(0)
3007 self.pg0.config_ip4()
3008 self.pg1.config_ip4()
3009 self.pg0.resolve_arp()
3010 self.pg1.resolve_arp()
Ole Troan9a475372019-03-05 16:58:24 +01003011 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
3012 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
Neale Ranns15002542017-09-10 04:39:11 -07003013
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003014 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003015 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003016
3017 nat_ip1 = "10.0.0.10"
3018 nat_ip2 = "10.0.0.11"
3019
Matus Fabian2ba92e32017-08-21 07:05:03 -07003020 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08003021 self.nat44_add_address(nat_ip2, vrf_id=99)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003022 flags = self.config_flags.NAT_IS_INSIDE
3023 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3024 flags=flags)
3025 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3026 flags=flags)
3027 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003028
3029 # first VRF
3030 pkts = self.create_stream_in(self.pg0, self.pg2)
3031 self.pg0.add_stream(pkts)
3032 self.pg_enable_capture(self.pg_interfaces)
3033 self.pg_start()
3034 capture = self.pg2.get_capture(len(pkts))
3035 self.verify_capture_out(capture, nat_ip1)
3036
3037 # second VRF
3038 pkts = self.create_stream_in(self.pg1, self.pg2)
3039 self.pg1.add_stream(pkts)
3040 self.pg_enable_capture(self.pg_interfaces)
3041 self.pg_start()
3042 capture = self.pg2.get_capture(len(pkts))
3043 self.verify_capture_out(capture, nat_ip1)
3044
Martin Gálik406eb1d2017-05-04 04:35:04 -07003045 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003046 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003047
Neale Ranns37029302018-08-10 05:30:06 -07003048 self.vapi.ip_neighbor_add_del(
3049 self.pg7.sw_if_index,
3050 self.pg7.remote_mac,
3051 self.pg7.remote_ip4,
3052 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3053 IP_API_NEIGHBOR_FLAG_STATIC))
3054 self.vapi.ip_neighbor_add_del(
3055 self.pg8.sw_if_index,
3056 self.pg8.remote_mac,
3057 self.pg8.remote_ip4,
3058 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3059 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003060
3061 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3062 dst_address_length=32,
3063 next_hop_address=self.pg7.remote_ip4n,
3064 next_hop_sw_if_index=self.pg7.sw_if_index)
3065 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3066 dst_address_length=32,
3067 next_hop_address=self.pg8.remote_ip4n,
3068 next_hop_sw_if_index=self.pg8.sw_if_index)
3069
Matus Fabian2ba92e32017-08-21 07:05:03 -07003070 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003071 flags = self.config_flags.NAT_IS_INSIDE
3072 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index,
3073 flags=flags)
3074 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003075
3076 # in2out
3077 pkts = self.create_stream_in(self.pg7, self.pg8)
3078 self.pg7.add_stream(pkts)
3079 self.pg_enable_capture(self.pg_interfaces)
3080 self.pg_start()
3081 capture = self.pg8.get_capture(len(pkts))
3082 self.verify_capture_out(capture)
3083
3084 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003085 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003086 self.pg8.add_stream(pkts)
3087 self.pg_enable_capture(self.pg_interfaces)
3088 self.pg_start()
3089 capture = self.pg7.get_capture(len(pkts))
3090 self.verify_capture_in(capture, self.pg7)
3091
3092 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003093 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003094
Neale Ranns37029302018-08-10 05:30:06 -07003095 self.vapi.ip_neighbor_add_del(
3096 self.pg7.sw_if_index,
3097 self.pg7.remote_mac,
3098 self.pg7.remote_ip4,
3099 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3100 IP_API_NEIGHBOR_FLAG_STATIC))
3101 self.vapi.ip_neighbor_add_del(
3102 self.pg8.sw_if_index,
3103 self.pg8.remote_mac,
3104 self.pg8.remote_ip4,
3105 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3106 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003107
3108 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3109 dst_address_length=32,
3110 next_hop_address=self.pg7.remote_ip4n,
3111 next_hop_sw_if_index=self.pg7.sw_if_index)
3112 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3113 dst_address_length=32,
3114 next_hop_address=self.pg8.remote_ip4n,
3115 next_hop_sw_if_index=self.pg8.sw_if_index)
3116
Matus Fabian2ba92e32017-08-21 07:05:03 -07003117 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003118 flags = self.config_flags.NAT_IS_INSIDE
3119 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index,
3120 flags=flags)
3121 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003122
3123 # out2in
3124 pkts = self.create_stream_out(self.pg8)
3125 self.pg8.add_stream(pkts)
3126 self.pg_enable_capture(self.pg_interfaces)
3127 self.pg_start()
3128 capture = self.pg7.get_capture(len(pkts))
3129 self.verify_capture_in(capture, self.pg7)
3130
3131 # in2out
3132 pkts = self.create_stream_in(self.pg7, self.pg8)
3133 self.pg7.add_stream(pkts)
3134 self.pg_enable_capture(self.pg_interfaces)
3135 self.pg_start()
3136 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003137 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003138
3139 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003140 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003141
3142 self.tcp_port_out = 30606
3143 self.udp_port_out = 30607
3144 self.icmp_id_out = 30608
3145
Neale Ranns37029302018-08-10 05:30:06 -07003146 self.vapi.ip_neighbor_add_del(
3147 self.pg7.sw_if_index,
3148 self.pg7.remote_mac,
3149 self.pg7.remote_ip4,
3150 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3151 IP_API_NEIGHBOR_FLAG_STATIC))
3152 self.vapi.ip_neighbor_add_del(
3153 self.pg8.sw_if_index,
3154 self.pg8.remote_mac,
3155 self.pg8.remote_ip4,
3156 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3157 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003158
3159 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3160 dst_address_length=32,
3161 next_hop_address=self.pg7.remote_ip4n,
3162 next_hop_sw_if_index=self.pg7.sw_if_index)
3163 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3164 dst_address_length=32,
3165 next_hop_address=self.pg8.remote_ip4n,
3166 next_hop_sw_if_index=self.pg8.sw_if_index)
3167
Matus Fabian2ba92e32017-08-21 07:05:03 -07003168 self.nat44_add_address(self.nat_addr)
3169 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3170 self.tcp_port_in, self.tcp_port_out,
3171 proto=IP_PROTOS.tcp)
3172 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3173 self.udp_port_in, self.udp_port_out,
3174 proto=IP_PROTOS.udp)
3175 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3176 self.icmp_id_in, self.icmp_id_out,
3177 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003178 flags = self.config_flags.NAT_IS_INSIDE
3179 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index,
3180 flags=flags)
3181 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003182
3183 # out2in
3184 pkts = self.create_stream_out(self.pg8)
3185 self.pg8.add_stream(pkts)
3186 self.pg_enable_capture(self.pg_interfaces)
3187 self.pg_start()
3188 capture = self.pg7.get_capture(len(pkts))
3189 self.verify_capture_in(capture, self.pg7)
3190
3191 # in2out
3192 pkts = self.create_stream_in(self.pg7, self.pg8)
3193 self.pg7.add_stream(pkts)
3194 self.pg_enable_capture(self.pg_interfaces)
3195 self.pg_start()
3196 capture = self.pg8.get_capture(len(pkts))
3197 self.verify_capture_out(capture)
3198
Matus Fabian328dbc82017-06-19 04:28:04 -07003199 def test_static_unknown_proto(self):
3200 """ 1:1 NAT translate packet with unknown protocol """
3201 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003202 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003203 flags = self.config_flags.NAT_IS_INSIDE
3204 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3205 flags=flags)
3206 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian328dbc82017-06-19 04:28:04 -07003207
3208 # in2out
3209 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3210 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3211 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003212 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003213 TCP(sport=1234, dport=1234))
3214 self.pg0.add_stream(p)
3215 self.pg_enable_capture(self.pg_interfaces)
3216 self.pg_start()
3217 p = self.pg1.get_capture(1)
3218 packet = p[0]
3219 try:
3220 self.assertEqual(packet[IP].src, nat_ip)
3221 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003222 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003223 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003224 except:
3225 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3226 raise
3227
3228 # out2in
3229 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3230 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3231 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003232 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003233 TCP(sport=1234, dport=1234))
3234 self.pg1.add_stream(p)
3235 self.pg_enable_capture(self.pg_interfaces)
3236 self.pg_start()
3237 p = self.pg0.get_capture(1)
3238 packet = p[0]
3239 try:
3240 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3241 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003242 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003243 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003244 except:
3245 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3246 raise
3247
Matus Fabian7968e6c2017-07-06 05:37:49 -07003248 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003249 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3250
3251 host = self.pg0.remote_hosts[0]
3252 server = self.pg0.remote_hosts[1]
3253
3254 host_nat_ip = "10.0.0.10"
3255 server_nat_ip = "10.0.0.11"
3256
Matus Fabian2ba92e32017-08-21 07:05:03 -07003257 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3258 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003259 flags = self.config_flags.NAT_IS_INSIDE
3260 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3261 flags=flags)
3262 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003263
3264 # host to server
3265 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3266 IP(src=host.ip4, dst=server_nat_ip) /
3267 GRE() /
3268 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3269 TCP(sport=1234, dport=1234))
3270 self.pg0.add_stream(p)
3271 self.pg_enable_capture(self.pg_interfaces)
3272 self.pg_start()
3273 p = self.pg0.get_capture(1)
3274 packet = p[0]
3275 try:
3276 self.assertEqual(packet[IP].src, host_nat_ip)
3277 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003278 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003279 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003280 except:
3281 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3282 raise
3283
3284 # server to host
3285 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3286 IP(src=server.ip4, dst=host_nat_ip) /
3287 GRE() /
3288 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3289 TCP(sport=1234, dport=1234))
3290 self.pg0.add_stream(p)
3291 self.pg_enable_capture(self.pg_interfaces)
3292 self.pg_start()
3293 p = self.pg0.get_capture(1)
3294 packet = p[0]
3295 try:
3296 self.assertEqual(packet[IP].src, server_nat_ip)
3297 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003298 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003299 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003300 except:
3301 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3302 raise
3303
Matus Fabian93d84c92017-07-19 08:06:01 -07003304 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003305 """ NAT44 interface output feature (in2out postrouting) """
3306 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003307 flags = self.config_flags.NAT_IS_INSIDE
3308 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index,
3309 flags=flags)
3310 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3311 flags=flags)
3312 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003313
3314 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003315 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003316 self.pg0.add_stream(pkts)
3317 self.pg_enable_capture(self.pg_interfaces)
3318 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003319 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003320 self.verify_capture_out(capture)
3321
3322 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003323 pkts = self.create_stream_out(self.pg3)
3324 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003325 self.pg_enable_capture(self.pg_interfaces)
3326 self.pg_start()
3327 capture = self.pg0.get_capture(len(pkts))
3328 self.verify_capture_in(capture, self.pg0)
3329
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003330 # from non-NAT interface to NAT inside interface
3331 pkts = self.create_stream_in(self.pg2, self.pg0)
3332 self.pg2.add_stream(pkts)
3333 self.pg_enable_capture(self.pg_interfaces)
3334 self.pg_start()
3335 capture = self.pg0.get_capture(len(pkts))
3336 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3337
Matus Fabian93d84c92017-07-19 08:06:01 -07003338 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003339 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003340 nat_ip_vrf10 = "10.0.0.10"
3341 nat_ip_vrf20 = "10.0.0.20"
3342
3343 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3344 dst_address_length=32,
3345 next_hop_address=self.pg3.remote_ip4n,
3346 next_hop_sw_if_index=self.pg3.sw_if_index,
3347 table_id=10)
3348 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3349 dst_address_length=32,
3350 next_hop_address=self.pg3.remote_ip4n,
3351 next_hop_sw_if_index=self.pg3.sw_if_index,
3352 table_id=20)
3353
Matus Fabian2ba92e32017-08-21 07:05:03 -07003354 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3355 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003356 flags = self.config_flags.NAT_IS_INSIDE
3357 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index,
3358 flags=flags)
3359 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index,
3360 flags=flags)
3361 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003362
3363 # in2out VRF 10
3364 pkts = self.create_stream_in(self.pg4, self.pg3)
3365 self.pg4.add_stream(pkts)
3366 self.pg_enable_capture(self.pg_interfaces)
3367 self.pg_start()
3368 capture = self.pg3.get_capture(len(pkts))
3369 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3370
3371 # out2in VRF 10
3372 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3373 self.pg3.add_stream(pkts)
3374 self.pg_enable_capture(self.pg_interfaces)
3375 self.pg_start()
3376 capture = self.pg4.get_capture(len(pkts))
3377 self.verify_capture_in(capture, self.pg4)
3378
3379 # in2out VRF 20
3380 pkts = self.create_stream_in(self.pg6, self.pg3)
3381 self.pg6.add_stream(pkts)
3382 self.pg_enable_capture(self.pg_interfaces)
3383 self.pg_start()
3384 capture = self.pg3.get_capture(len(pkts))
3385 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3386
3387 # out2in VRF 20
3388 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3389 self.pg3.add_stream(pkts)
3390 self.pg_enable_capture(self.pg_interfaces)
3391 self.pg_start()
3392 capture = self.pg6.get_capture(len(pkts))
3393 self.verify_capture_in(capture, self.pg6)
3394
Matus Fabian161c59c2017-07-21 03:46:03 -07003395 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003396 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003397 host = self.pg0.remote_hosts[0]
3398 server = self.pg0.remote_hosts[1]
3399 host_in_port = 1234
3400 host_out_port = 0
3401 server_in_port = 5678
3402 server_out_port = 8765
3403
Matus Fabian2ba92e32017-08-21 07:05:03 -07003404 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003405 flags = self.config_flags.NAT_IS_INSIDE
3406 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index,
3407 flags=flags)
3408 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003409
3410 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003411 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3412 server_in_port, server_out_port,
3413 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003414
3415 # send packet from host to server
3416 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003417 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003418 TCP(sport=host_in_port, dport=server_out_port))
3419 self.pg0.add_stream(p)
3420 self.pg_enable_capture(self.pg_interfaces)
3421 self.pg_start()
3422 capture = self.pg0.get_capture(1)
3423 p = capture[0]
3424 try:
3425 ip = p[IP]
3426 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003427 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003428 self.assertEqual(ip.dst, server.ip4)
3429 self.assertNotEqual(tcp.sport, host_in_port)
3430 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003431 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003432 host_out_port = tcp.sport
3433 except:
3434 self.logger.error(ppp("Unexpected or invalid packet:", p))
3435 raise
3436
3437 # send reply from server to host
3438 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003439 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003440 TCP(sport=server_in_port, dport=host_out_port))
3441 self.pg0.add_stream(p)
3442 self.pg_enable_capture(self.pg_interfaces)
3443 self.pg_start()
3444 capture = self.pg0.get_capture(1)
3445 p = capture[0]
3446 try:
3447 ip = p[IP]
3448 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003449 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003450 self.assertEqual(ip.dst, host.ip4)
3451 self.assertEqual(tcp.sport, server_out_port)
3452 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003453 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003454 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003455 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003456 raise
3457
Matus Fabian36ea2d62017-10-24 04:13:49 -07003458 def test_one_armed_nat44(self):
3459 """ One armed NAT44 """
3460 remote_host = self.pg9.remote_hosts[0]
3461 local_host = self.pg9.remote_hosts[1]
3462 external_port = 0
3463
3464 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003465 flags = self.config_flags.NAT_IS_INSIDE
Matus Fabian36ea2d62017-10-24 04:13:49 -07003466 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3467 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003468 flags=flags)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003469
3470 # in2out
3471 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3472 IP(src=local_host.ip4, dst=remote_host.ip4) /
3473 TCP(sport=12345, dport=80))
3474 self.pg9.add_stream(p)
3475 self.pg_enable_capture(self.pg_interfaces)
3476 self.pg_start()
3477 capture = self.pg9.get_capture(1)
3478 p = capture[0]
3479 try:
3480 ip = p[IP]
3481 tcp = p[TCP]
3482 self.assertEqual(ip.src, self.nat_addr)
3483 self.assertEqual(ip.dst, remote_host.ip4)
3484 self.assertNotEqual(tcp.sport, 12345)
3485 external_port = tcp.sport
3486 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003487 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003488 except:
3489 self.logger.error(ppp("Unexpected or invalid packet:", p))
3490 raise
3491
3492 # out2in
3493 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3494 IP(src=remote_host.ip4, dst=self.nat_addr) /
3495 TCP(sport=80, dport=external_port))
3496 self.pg9.add_stream(p)
3497 self.pg_enable_capture(self.pg_interfaces)
3498 self.pg_start()
3499 capture = self.pg9.get_capture(1)
3500 p = capture[0]
3501 try:
3502 ip = p[IP]
3503 tcp = p[TCP]
3504 self.assertEqual(ip.src, remote_host.ip4)
3505 self.assertEqual(ip.dst, local_host.ip4)
3506 self.assertEqual(tcp.sport, 80)
3507 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003508 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003509 except:
3510 self.logger.error(ppp("Unexpected or invalid packet:", p))
3511 raise
3512
Matus Fabiana5e73762018-12-14 01:55:16 -08003513 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3514 self.assertEqual(err, 1)
3515 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3516 self.assertEqual(err, 1)
3517
Matus Fabian5ba86f72017-10-26 03:37:38 -07003518 def test_del_session(self):
3519 """ Delete NAT44 session """
3520 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003521 flags = self.config_flags.NAT_IS_INSIDE
3522 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3523 flags=flags)
3524 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003525
3526 pkts = self.create_stream_in(self.pg0, self.pg1)
3527 self.pg0.add_stream(pkts)
3528 self.pg_enable_capture(self.pg_interfaces)
3529 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003530 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003531
3532 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3533 nsessions = len(sessions)
3534
3535 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3536 sessions[0].inside_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003537 sessions[0].protocol,
3538 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003539 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3540 sessions[1].outside_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003541 sessions[1].protocol)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003542
3543 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3544 self.assertEqual(nsessions - len(sessions), 2)
3545
Matus Fabian68ba8802018-08-08 05:52:47 -07003546 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3547 sessions[0].inside_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003548 sessions[0].protocol,
3549 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian68ba8802018-08-08 05:52:47 -07003550
3551 self.verify_no_nat44_user()
3552
Matus Fabianefcd1e92017-08-15 06:59:19 -07003553 def test_set_get_reass(self):
3554 """ NAT44 set/get virtual fragmentation reassembly """
3555 reas_cfg1 = self.vapi.nat_get_reass()
3556
3557 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3558 max_reass=reas_cfg1.ip4_max_reass * 2,
3559 max_frag=reas_cfg1.ip4_max_frag * 2)
3560
3561 reas_cfg2 = self.vapi.nat_get_reass()
3562
3563 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3564 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3565 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3566
3567 self.vapi.nat_set_reass(drop_frag=1)
3568 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3569
3570 def test_frag_in_order(self):
3571 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003572
Matus Fabianefcd1e92017-08-15 06:59:19 -07003573 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003574 flags = self.config_flags.NAT_IS_INSIDE
3575 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3576 flags=flags)
3577 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003578
Matus Fabianda41d722018-10-19 04:01:19 -07003579 self.frag_in_order(proto=IP_PROTOS.tcp)
3580 self.frag_in_order(proto=IP_PROTOS.udp)
3581 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003582
Matus Fabian111add72018-11-20 02:19:05 -08003583 def test_frag_forwarding(self):
3584 """ NAT44 forwarding fragment test """
Ole Troane1ade682019-03-04 23:55:43 +01003585 self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003586 flags = self.config_flags.NAT_IS_INSIDE
3587 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3588 flags=flags)
3589 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian111add72018-11-20 02:19:05 -08003590 self.vapi.nat44_forwarding_enable_disable(1)
3591
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003592 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Matus Fabian111add72018-11-20 02:19:05 -08003593 pkts = self.create_stream_frag(self.pg1,
3594 self.pg0.remote_ip4,
3595 4789,
3596 4789,
3597 data,
3598 proto=IP_PROTOS.udp)
3599 self.pg1.add_stream(pkts)
3600 self.pg_enable_capture(self.pg_interfaces)
3601 self.pg_start()
3602 frags = self.pg0.get_capture(len(pkts))
3603 p = self.reass_frags_and_verify(frags,
3604 self.pg1.remote_ip4,
3605 self.pg0.remote_ip4)
3606 self.assertEqual(p[UDP].sport, 4789)
3607 self.assertEqual(p[UDP].dport, 4789)
3608 self.assertEqual(data, p[Raw].load)
3609
Matus Fabianefcd1e92017-08-15 06:59:19 -07003610 def test_reass_hairpinning(self):
3611 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003612
Matus Fabianda41d722018-10-19 04:01:19 -07003613 self.server = self.pg0.remote_hosts[1]
3614 self.host_in_port = random.randint(1025, 65535)
3615 self.server_in_port = random.randint(1025, 65535)
3616 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003617
3618 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003619 flags = self.config_flags.NAT_IS_INSIDE
3620 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3621 flags=flags)
3622 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003623 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003624 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3625 self.server_in_port,
3626 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003627 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003628 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3629 self.server_in_port,
3630 self.server_out_port,
3631 proto=IP_PROTOS.udp)
3632 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003633
Matus Fabianda41d722018-10-19 04:01:19 -07003634 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3635 self.reass_hairpinning(proto=IP_PROTOS.udp)
3636 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003637
3638 def test_frag_out_of_order(self):
3639 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003640
Matus Fabianefcd1e92017-08-15 06:59:19 -07003641 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003642 flags = self.config_flags.NAT_IS_INSIDE
3643 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3644 flags=flags)
3645 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003646
Matus Fabianda41d722018-10-19 04:01:19 -07003647 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3648 self.frag_out_of_order(proto=IP_PROTOS.udp)
3649 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003650
Matus Fabian27697102017-11-09 01:43:47 -08003651 def test_port_restricted(self):
3652 """ Port restricted NAT44 (MAP-E CE) """
3653 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003654 flags = self.config_flags.NAT_IS_INSIDE
3655 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3656 flags=flags)
3657 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003658 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3659 psid_offset=6,
3660 psid_length=6,
3661 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003662
3663 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3664 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3665 TCP(sport=4567, dport=22))
3666 self.pg0.add_stream(p)
3667 self.pg_enable_capture(self.pg_interfaces)
3668 self.pg_start()
3669 capture = self.pg1.get_capture(1)
3670 p = capture[0]
3671 try:
3672 ip = p[IP]
3673 tcp = p[TCP]
3674 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3675 self.assertEqual(ip.src, self.nat_addr)
3676 self.assertEqual(tcp.dport, 22)
3677 self.assertNotEqual(tcp.sport, 4567)
3678 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003679 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003680 except:
3681 self.logger.error(ppp("Unexpected or invalid packet:", p))
3682 raise
3683
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003684 def test_port_range(self):
3685 """ External address port range """
3686 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003687 flags = self.config_flags.NAT_IS_INSIDE
3688 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3689 flags=flags)
3690 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003691 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3692 start_port=1025,
3693 end_port=1027)
3694
3695 pkts = []
3696 for port in range(0, 5):
3697 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3698 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3699 TCP(sport=1125 + port))
3700 pkts.append(p)
3701 self.pg0.add_stream(pkts)
3702 self.pg_enable_capture(self.pg_interfaces)
3703 self.pg_start()
3704 capture = self.pg1.get_capture(3)
3705 for p in capture:
3706 tcp = p[TCP]
3707 self.assertGreaterEqual(tcp.sport, 1025)
3708 self.assertLessEqual(tcp.sport, 1027)
3709
Matus Fabiana6110b62018-06-13 05:39:07 -07003710 def test_ipfix_max_frags(self):
3711 """ IPFIX logging maximum fragments pending reassembly exceeded """
3712 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003713 flags = self.config_flags.NAT_IS_INSIDE
3714 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3715 flags=flags)
3716 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003717 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003718 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3719 src_address=self.pg3.local_ip4n,
3720 path_mtu=512,
3721 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01003722 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3723 src_port=self.ipfix_src_port)
Matus Fabiana6110b62018-06-13 05:39:07 -07003724
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003725 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabiana6110b62018-06-13 05:39:07 -07003726 self.tcp_port_in = random.randint(1025, 65535)
3727 pkts = self.create_stream_frag(self.pg0,
3728 self.pg1.remote_ip4,
3729 self.tcp_port_in,
3730 20,
3731 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003732 pkts.reverse()
3733 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003734 self.pg_enable_capture(self.pg_interfaces)
3735 self.pg_start()
3736 self.pg1.assert_nothing_captured()
3737 sleep(1)
3738 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3739 capture = self.pg3.get_capture(9)
3740 ipfix = IPFIXDecoder()
3741 # first load template
3742 for p in capture:
3743 self.assertTrue(p.haslayer(IPFIX))
3744 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3745 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3746 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3747 self.assertEqual(p[UDP].dport, 4739)
3748 self.assertEqual(p[IPFIX].observationDomainID,
3749 self.ipfix_domain_id)
3750 if p.haslayer(Template):
3751 ipfix.add_template(p.getlayer(Template))
3752 # verify events in data set
3753 for p in capture:
3754 if p.haslayer(Data):
3755 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003756 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003757 self.pg0.remote_ip4n)
3758
Matus Fabian8008d7c2018-07-09 01:34:20 -07003759 def test_multiple_outside_vrf(self):
3760 """ Multiple outside VRF """
3761 vrf_id1 = 1
3762 vrf_id2 = 2
3763
3764 self.pg1.unconfig_ip4()
3765 self.pg2.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003766 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3767 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003768 self.pg1.set_table_ip4(vrf_id1)
3769 self.pg2.set_table_ip4(vrf_id2)
3770 self.pg1.config_ip4()
3771 self.pg2.config_ip4()
3772 self.pg1.resolve_arp()
3773 self.pg2.resolve_arp()
3774
3775 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003776 flags = self.config_flags.NAT_IS_INSIDE
3777 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3778 flags=flags)
3779 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3780 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003781
3782 try:
3783 # first VRF
3784 pkts = self.create_stream_in(self.pg0, self.pg1)
3785 self.pg0.add_stream(pkts)
3786 self.pg_enable_capture(self.pg_interfaces)
3787 self.pg_start()
3788 capture = self.pg1.get_capture(len(pkts))
3789 self.verify_capture_out(capture, self.nat_addr)
3790
3791 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3792 self.pg1.add_stream(pkts)
3793 self.pg_enable_capture(self.pg_interfaces)
3794 self.pg_start()
3795 capture = self.pg0.get_capture(len(pkts))
3796 self.verify_capture_in(capture, self.pg0)
3797
3798 self.tcp_port_in = 60303
3799 self.udp_port_in = 60304
3800 self.icmp_id_in = 60305
3801
3802 # second VRF
3803 pkts = self.create_stream_in(self.pg0, self.pg2)
3804 self.pg0.add_stream(pkts)
3805 self.pg_enable_capture(self.pg_interfaces)
3806 self.pg_start()
3807 capture = self.pg2.get_capture(len(pkts))
3808 self.verify_capture_out(capture, self.nat_addr)
3809
3810 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3811 self.pg2.add_stream(pkts)
3812 self.pg_enable_capture(self.pg_interfaces)
3813 self.pg_start()
3814 capture = self.pg0.get_capture(len(pkts))
3815 self.verify_capture_in(capture, self.pg0)
3816
3817 finally:
3818 self.pg1.unconfig_ip4()
3819 self.pg2.unconfig_ip4()
3820 self.pg1.set_table_ip4(0)
3821 self.pg2.set_table_ip4(0)
3822 self.pg1.config_ip4()
3823 self.pg2.config_ip4()
3824 self.pg1.resolve_arp()
3825 self.pg2.resolve_arp()
3826
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08003827 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07003828 def test_session_timeout(self):
3829 """ NAT44 session timeouts """
3830 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003831 flags = self.config_flags.NAT_IS_INSIDE
3832 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3833 flags=flags)
3834 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian878c6462018-08-23 00:33:35 -07003835 self.vapi.nat_set_timeouts(udp=5)
3836
3837 max_sessions = 1000
3838 pkts = []
3839 for i in range(0, max_sessions):
3840 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3841 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3842 IP(src=src, dst=self.pg1.remote_ip4) /
3843 UDP(sport=1025, dport=53))
3844 pkts.append(p)
3845 self.pg0.add_stream(pkts)
3846 self.pg_enable_capture(self.pg_interfaces)
3847 self.pg_start()
3848 self.pg1.get_capture(max_sessions)
3849
3850 sleep(6)
3851
3852 pkts = []
3853 for i in range(0, max_sessions):
3854 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3855 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3856 IP(src=src, dst=self.pg1.remote_ip4) /
3857 UDP(sport=1026, dport=53))
3858 pkts.append(p)
3859 self.pg0.add_stream(pkts)
3860 self.pg_enable_capture(self.pg_interfaces)
3861 self.pg_start()
3862 self.pg1.get_capture(max_sessions)
3863
3864 nsessions = 0
3865 users = self.vapi.nat44_user_dump()
3866 for user in users:
3867 nsessions = nsessions + user.nsessions
3868 self.assertLess(nsessions, 2 * max_sessions)
3869
Matus Fabianbb4e0222018-09-13 02:36:25 -07003870 def test_mss_clamping(self):
3871 """ TCP MSS clamping """
3872 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003873 flags = self.config_flags.NAT_IS_INSIDE
3874 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3875 flags=flags)
3876 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianbb4e0222018-09-13 02:36:25 -07003877
3878 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3879 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3880 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3881 flags="S", options=[('MSS', 1400)]))
3882
3883 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3884 self.pg0.add_stream(p)
3885 self.pg_enable_capture(self.pg_interfaces)
3886 self.pg_start()
3887 capture = self.pg1.get_capture(1)
3888 # Negotiated MSS value greater than configured - changed
3889 self.verify_mss_value(capture[0], 1000)
3890
3891 self.vapi.nat_set_mss_clamping(enable=0)
3892 self.pg0.add_stream(p)
3893 self.pg_enable_capture(self.pg_interfaces)
3894 self.pg_start()
3895 capture = self.pg1.get_capture(1)
3896 # MSS clamping disabled - negotiated MSS unchanged
3897 self.verify_mss_value(capture[0], 1400)
3898
3899 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3900 self.pg0.add_stream(p)
3901 self.pg_enable_capture(self.pg_interfaces)
3902 self.pg_start()
3903 capture = self.pg1.get_capture(1)
3904 # Negotiated MSS value smaller than configured - unchanged
3905 self.verify_mss_value(capture[0], 1400)
3906
Matus Fabian34931eb2019-02-26 09:05:23 -08003907 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3908 def test_ha_send(self):
3909 """ Send HA session synchronization events (active) """
3910 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003911 flags = self.config_flags.NAT_IS_INSIDE
3912 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3913 flags=flags)
3914 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian34931eb2019-02-26 09:05:23 -08003915 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3916 self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3917 bind_layers(UDP, HANATStateSync, sport=12345)
3918
3919 # create sessions
3920 pkts = self.create_stream_in(self.pg0, self.pg1)
3921 self.pg0.add_stream(pkts)
3922 self.pg_enable_capture(self.pg_interfaces)
3923 self.pg_start()
3924 capture = self.pg1.get_capture(len(pkts))
3925 self.verify_capture_out(capture)
3926 # active send HA events
3927 self.vapi.nat_ha_flush()
3928 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3929 self.assertEqual(stats[0][0], 3)
3930 capture = self.pg3.get_capture(1)
3931 p = capture[0]
3932 self.assert_packet_checksums_valid(p)
3933 try:
3934 ip = p[IP]
3935 udp = p[UDP]
3936 hanat = p[HANATStateSync]
3937 except IndexError:
3938 self.logger.error(ppp("Invalid packet:", p))
3939 raise
3940 else:
3941 self.assertEqual(ip.src, self.pg3.local_ip4)
3942 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3943 self.assertEqual(udp.sport, 12345)
3944 self.assertEqual(udp.dport, 12346)
3945 self.assertEqual(hanat.version, 1)
3946 self.assertEqual(hanat.thread_index, 0)
3947 self.assertEqual(hanat.count, 3)
3948 seq = hanat.sequence_number
3949 for event in hanat.events:
3950 self.assertEqual(event.event_type, 1)
3951 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3952 self.assertEqual(event.out_addr, self.nat_addr)
3953 self.assertEqual(event.fib_index, 0)
3954
3955 # ACK received events
3956 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3957 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3958 UDP(sport=12346, dport=12345) /
3959 HANATStateSync(sequence_number=seq, flags='ACK'))
3960 self.pg3.add_stream(ack)
3961 self.pg_start()
3962 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3963 self.assertEqual(stats[0][0], 1)
3964
3965 # delete one session
3966 self.pg_enable_capture(self.pg_interfaces)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003967 self.vapi.nat44_del_session(self.pg0.remote_ip4n,
3968 self.tcp_port_in,
3969 IP_PROTOS.tcp,
3970 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian34931eb2019-02-26 09:05:23 -08003971 self.vapi.nat_ha_flush()
3972 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3973 self.assertEqual(stats[0][0], 1)
3974 capture = self.pg3.get_capture(1)
3975 p = capture[0]
3976 try:
3977 hanat = p[HANATStateSync]
3978 except IndexError:
3979 self.logger.error(ppp("Invalid packet:", p))
3980 raise
3981 else:
3982 self.assertGreater(hanat.sequence_number, seq)
3983
3984 # do not send ACK, active retry send HA event again
3985 self.pg_enable_capture(self.pg_interfaces)
3986 sleep(12)
3987 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3988 self.assertEqual(stats[0][0], 3)
3989 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3990 self.assertEqual(stats[0][0], 1)
3991 capture = self.pg3.get_capture(3)
3992 for packet in capture:
3993 self.assertEqual(packet, p)
3994
3995 # session counters refresh
3996 pkts = self.create_stream_out(self.pg1)
3997 self.pg1.add_stream(pkts)
3998 self.pg_enable_capture(self.pg_interfaces)
3999 self.pg_start()
4000 self.pg0.get_capture(2)
4001 self.vapi.nat_ha_flush()
4002 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
4003 self.assertEqual(stats[0][0], 2)
4004 capture = self.pg3.get_capture(1)
4005 p = capture[0]
4006 self.assert_packet_checksums_valid(p)
4007 try:
4008 ip = p[IP]
4009 udp = p[UDP]
4010 hanat = p[HANATStateSync]
4011 except IndexError:
4012 self.logger.error(ppp("Invalid packet:", p))
4013 raise
4014 else:
4015 self.assertEqual(ip.src, self.pg3.local_ip4)
4016 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4017 self.assertEqual(udp.sport, 12345)
4018 self.assertEqual(udp.dport, 12346)
4019 self.assertEqual(hanat.version, 1)
4020 self.assertEqual(hanat.count, 2)
4021 seq = hanat.sequence_number
4022 for event in hanat.events:
4023 self.assertEqual(event.event_type, 3)
4024 self.assertEqual(event.out_addr, self.nat_addr)
4025 self.assertEqual(event.fib_index, 0)
4026 self.assertEqual(event.total_pkts, 2)
4027 self.assertGreater(event.total_bytes, 0)
4028
4029 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4030 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4031 UDP(sport=12346, dport=12345) /
4032 HANATStateSync(sequence_number=seq, flags='ACK'))
4033 self.pg3.add_stream(ack)
4034 self.pg_start()
4035 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4036 self.assertEqual(stats[0][0], 2)
4037
4038 def test_ha_recv(self):
4039 """ Receive HA session synchronization events (passive) """
4040 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004041 flags = self.config_flags.NAT_IS_INSIDE
4042 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4043 flags=flags)
4044 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian34931eb2019-02-26 09:05:23 -08004045 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
4046 bind_layers(UDP, HANATStateSync, sport=12345)
4047
4048 self.tcp_port_out = random.randint(1025, 65535)
4049 self.udp_port_out = random.randint(1025, 65535)
4050
4051 # send HA session add events to failover/passive
4052 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4053 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4054 UDP(sport=12346, dport=12345) /
4055 HANATStateSync(sequence_number=1, events=[
4056 Event(event_type='add', protocol='tcp',
4057 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4058 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4059 eh_addr=self.pg1.remote_ip4,
4060 ehn_addr=self.pg1.remote_ip4,
4061 eh_port=self.tcp_external_port,
4062 ehn_port=self.tcp_external_port, fib_index=0),
4063 Event(event_type='add', protocol='udp',
4064 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4065 in_port=self.udp_port_in, out_port=self.udp_port_out,
4066 eh_addr=self.pg1.remote_ip4,
4067 ehn_addr=self.pg1.remote_ip4,
4068 eh_port=self.udp_external_port,
4069 ehn_port=self.udp_external_port, fib_index=0)]))
4070
4071 self.pg3.add_stream(p)
4072 self.pg_enable_capture(self.pg_interfaces)
4073 self.pg_start()
4074 # receive ACK
4075 capture = self.pg3.get_capture(1)
4076 p = capture[0]
4077 try:
4078 hanat = p[HANATStateSync]
4079 except IndexError:
4080 self.logger.error(ppp("Invalid packet:", p))
4081 raise
4082 else:
4083 self.assertEqual(hanat.sequence_number, 1)
4084 self.assertEqual(hanat.flags, 'ACK')
4085 self.assertEqual(hanat.version, 1)
4086 self.assertEqual(hanat.thread_index, 0)
4087 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4088 self.assertEqual(stats[0][0], 1)
4089 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4090 self.assertEqual(stats[0][0], 2)
4091 users = self.statistics.get_counter('/nat44/total-users')
4092 self.assertEqual(users[0][0], 1)
4093 sessions = self.statistics.get_counter('/nat44/total-sessions')
4094 self.assertEqual(sessions[0][0], 2)
4095 users = self.vapi.nat44_user_dump()
4096 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004097 self.assertEqual(str(users[0].ip_address),
4098 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004099 # there should be 2 sessions created by HA
4100 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4101 users[0].vrf_id)
4102 self.assertEqual(len(sessions), 2)
4103 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02004104 self.assertEqual(str(session.inside_ip_address),
4105 self.pg0.remote_ip4)
4106 self.assertEqual(str(session.outside_ip_address),
4107 self.nat_addr)
Matus Fabian34931eb2019-02-26 09:05:23 -08004108 self.assertIn(session.inside_port,
4109 [self.tcp_port_in, self.udp_port_in])
4110 self.assertIn(session.outside_port,
4111 [self.tcp_port_out, self.udp_port_out])
4112 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4113
4114 # send HA session delete event to failover/passive
4115 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4116 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4117 UDP(sport=12346, dport=12345) /
4118 HANATStateSync(sequence_number=2, events=[
4119 Event(event_type='del', protocol='udp',
4120 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4121 in_port=self.udp_port_in, out_port=self.udp_port_out,
4122 eh_addr=self.pg1.remote_ip4,
4123 ehn_addr=self.pg1.remote_ip4,
4124 eh_port=self.udp_external_port,
4125 ehn_port=self.udp_external_port, fib_index=0)]))
4126
4127 self.pg3.add_stream(p)
4128 self.pg_enable_capture(self.pg_interfaces)
4129 self.pg_start()
4130 # receive ACK
4131 capture = self.pg3.get_capture(1)
4132 p = capture[0]
4133 try:
4134 hanat = p[HANATStateSync]
4135 except IndexError:
4136 self.logger.error(ppp("Invalid packet:", p))
4137 raise
4138 else:
4139 self.assertEqual(hanat.sequence_number, 2)
4140 self.assertEqual(hanat.flags, 'ACK')
4141 self.assertEqual(hanat.version, 1)
4142 users = self.vapi.nat44_user_dump()
4143 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004144 self.assertEqual(str(users[0].ip_address),
4145 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004146 # now we should have only 1 session, 1 deleted by HA
4147 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4148 users[0].vrf_id)
4149 self.assertEqual(len(sessions), 1)
4150 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4151 self.assertEqual(stats[0][0], 1)
4152
4153 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4154 self.assertEqual(stats, 2)
4155
4156 # send HA session refresh event to failover/passive
4157 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4158 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4159 UDP(sport=12346, dport=12345) /
4160 HANATStateSync(sequence_number=3, events=[
4161 Event(event_type='refresh', protocol='tcp',
4162 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4163 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4164 eh_addr=self.pg1.remote_ip4,
4165 ehn_addr=self.pg1.remote_ip4,
4166 eh_port=self.tcp_external_port,
4167 ehn_port=self.tcp_external_port, fib_index=0,
4168 total_bytes=1024, total_pkts=2)]))
4169 self.pg3.add_stream(p)
4170 self.pg_enable_capture(self.pg_interfaces)
4171 self.pg_start()
4172 # receive ACK
4173 capture = self.pg3.get_capture(1)
4174 p = capture[0]
4175 try:
4176 hanat = p[HANATStateSync]
4177 except IndexError:
4178 self.logger.error(ppp("Invalid packet:", p))
4179 raise
4180 else:
4181 self.assertEqual(hanat.sequence_number, 3)
4182 self.assertEqual(hanat.flags, 'ACK')
4183 self.assertEqual(hanat.version, 1)
4184 users = self.vapi.nat44_user_dump()
4185 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004186 self.assertEqual(str(users[0].ip_address),
4187 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004188 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4189 users[0].vrf_id)
4190 self.assertEqual(len(sessions), 1)
4191 session = sessions[0]
4192 self.assertEqual(session.total_bytes, 1024)
4193 self.assertEqual(session.total_pkts, 2)
4194 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4195 self.assertEqual(stats[0][0], 1)
4196
4197 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4198 self.assertEqual(stats, 3)
4199
4200 # send packet to test session created by HA
4201 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4202 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4203 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4204 self.pg1.add_stream(p)
4205 self.pg_enable_capture(self.pg_interfaces)
4206 self.pg_start()
4207 capture = self.pg0.get_capture(1)
4208 p = capture[0]
4209 try:
4210 ip = p[IP]
4211 tcp = p[TCP]
4212 except IndexError:
4213 self.logger.error(ppp("Invalid packet:", p))
4214 raise
4215 else:
4216 self.assertEqual(ip.src, self.pg1.remote_ip4)
4217 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4218 self.assertEqual(tcp.sport, self.tcp_external_port)
4219 self.assertEqual(tcp.dport, self.tcp_port_in)
4220
Matus Fabiana6110b62018-06-13 05:39:07 -07004221 def tearDown(self):
4222 super(TestNAT44, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07004223 self.clear_nat44()
4224 self.vapi.cli("clear logging")
4225
4226 def show_commands_at_teardown(self):
4227 self.logger.info(self.vapi.cli("show nat44 addresses"))
4228 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4229 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4230 self.logger.info(self.vapi.cli("show nat44 interface address"))
4231 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4232 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4233 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4234 self.logger.info(self.vapi.cli("show nat timeouts"))
4235 self.logger.info(
4236 self.vapi.cli("show nat addr-port-assignment-alg"))
4237 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004238
4239
4240class TestNAT44EndpointDependent(MethodHolder):
4241 """ Endpoint-Dependent mapping and filtering test cases """
4242
4243 @classmethod
4244 def setUpConstants(cls):
4245 super(TestNAT44EndpointDependent, cls).setUpConstants()
4246 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4247
4248 @classmethod
4249 def setUpClass(cls):
4250 super(TestNAT44EndpointDependent, cls).setUpClass()
4251 cls.vapi.cli("set log class nat level debug")
4252 try:
4253 cls.tcp_port_in = 6303
4254 cls.tcp_port_out = 6303
4255 cls.udp_port_in = 6304
4256 cls.udp_port_out = 6304
4257 cls.icmp_id_in = 6305
4258 cls.icmp_id_out = 6305
4259 cls.nat_addr = '10.0.0.3'
Matus Fabiana6110b62018-06-13 05:39:07 -07004260 cls.ipfix_src_port = 4739
4261 cls.ipfix_domain_id = 1
4262 cls.tcp_external_port = 80
4263
Matus Fabian8008d7c2018-07-09 01:34:20 -07004264 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004265 cls.interfaces = list(cls.pg_interfaces[0:3])
4266
4267 for i in cls.interfaces:
4268 i.admin_up()
4269 i.config_ip4()
4270 i.resolve_arp()
4271
4272 cls.pg0.generate_remote_hosts(3)
4273 cls.pg0.configure_ipv4_neighbors()
4274
4275 cls.pg3.admin_up()
4276
4277 cls.pg4.generate_remote_hosts(2)
4278 cls.pg4.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004279 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01004280 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004281 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4282 address_length=24)
Matus Fabiana6110b62018-06-13 05:39:07 -07004283 cls.pg4.admin_up()
4284 cls.pg4.resolve_arp()
4285 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4286 cls.pg4.resolve_arp()
4287
Matus Fabian8008d7c2018-07-09 01:34:20 -07004288 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004289 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004290
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004291 cls.pg5._local_ip4 = "10.1.1.1"
4292 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4293 cls.pg5.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004294 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4295 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4296 socket.AF_INET, cls.pg5.remote_ip4)
4297 cls.pg5.set_table_ip4(1)
4298 cls.pg5.config_ip4()
4299 cls.pg5.admin_up()
4300 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4301 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004302 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004303 next_hop_sw_if_index=cls.pg5.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004304 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004305
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004306 cls.pg6._local_ip4 = "10.1.2.1"
4307 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4308 cls.pg6.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004309 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4310 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4311 socket.AF_INET, cls.pg6.remote_ip4)
4312 cls.pg6.set_table_ip4(1)
4313 cls.pg6.config_ip4()
4314 cls.pg6.admin_up()
4315 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4316 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004317 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004318 next_hop_sw_if_index=cls.pg6.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004319 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004320
4321 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4322 dst_address_length=16,
Ole Troana5b2eec2019-03-11 19:23:25 +01004323 next_hop_address=zero_ip4n, table_id=0,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004324 next_hop_table_id=1)
4325 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4326 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004327 next_hop_address=zero_ip4n, table_id=1,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004328 next_hop_table_id=0)
4329 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4330 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004331 next_hop_address=cls.pg1.local_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004332 next_hop_sw_if_index=cls.pg1.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004333 table_id=0)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004334
4335 cls.pg5.resolve_arp()
4336 cls.pg6.resolve_arp()
4337
Matus Fabiana6110b62018-06-13 05:39:07 -07004338 except Exception:
4339 super(TestNAT44EndpointDependent, cls).tearDownClass()
4340 raise
4341
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07004342 @classmethod
4343 def tearDownClass(cls):
4344 super(TestNAT44EndpointDependent, cls).tearDownClass()
4345
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004346 def test_frag_in_order(self):
4347 """ NAT44 translate fragments arriving in order """
4348 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004349 flags = self.config_flags.NAT_IS_INSIDE
4350 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4351 flags=flags)
4352 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004353 self.frag_in_order(proto=IP_PROTOS.tcp)
4354 self.frag_in_order(proto=IP_PROTOS.udp)
4355 self.frag_in_order(proto=IP_PROTOS.icmp)
4356
4357 def test_frag_in_order_dont_translate(self):
4358 """ NAT44 don't translate fragments arriving in order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004359 flags = self.config_flags.NAT_IS_INSIDE
4360 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4361 flags=flags)
4362 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004363 self.vapi.nat44_forwarding_enable_disable(enable=True)
4364 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4365
4366 def test_frag_out_of_order(self):
4367 """ NAT44 translate fragments arriving out of order """
4368 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004369 flags = self.config_flags.NAT_IS_INSIDE
4370 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4371 flags=flags)
4372 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004373 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4374 self.frag_out_of_order(proto=IP_PROTOS.udp)
4375 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4376
4377 def test_frag_out_of_order_dont_translate(self):
4378 """ NAT44 don't translate fragments arriving out of order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004379 flags = self.config_flags.NAT_IS_INSIDE
4380 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4381 flags=flags)
4382 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004383 self.vapi.nat44_forwarding_enable_disable(enable=True)
4384 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4385
4386 def test_frag_in_order_in_plus_out(self):
4387 """ in+out interface fragments in order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004388 flags = self.config_flags.NAT_IS_INSIDE
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004389 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4390 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004391 flags=flags)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004392 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4393 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004394 flags=flags)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004395
4396 self.server = self.pg1.remote_hosts[0]
4397
4398 self.server_in_addr = self.server.ip4
4399 self.server_out_addr = '11.11.11.11'
4400 self.server_in_port = random.randint(1025, 65535)
4401 self.server_out_port = random.randint(1025, 65535)
4402
4403 self.nat44_add_address(self.server_out_addr)
4404
4405 # add static mappings for server
4406 self.nat44_add_static_mapping(self.server_in_addr,
4407 self.server_out_addr,
4408 self.server_in_port,
4409 self.server_out_port,
4410 proto=IP_PROTOS.tcp)
4411 self.nat44_add_static_mapping(self.server_in_addr,
4412 self.server_out_addr,
4413 self.server_in_port,
4414 self.server_out_port,
4415 proto=IP_PROTOS.udp)
4416 self.nat44_add_static_mapping(self.server_in_addr,
4417 self.server_out_addr,
4418 proto=IP_PROTOS.icmp)
4419
4420 self.vapi.nat_set_reass(timeout=10)
4421
4422 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4423 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4424 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4425
4426 def test_frag_out_of_order_in_plus_out(self):
4427 """ in+out interface fragments out of order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004428 flags = self.config_flags.NAT_IS_INSIDE
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004429 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4430 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004431 flags=flags)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004432 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4433 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004434 flags=flags)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004435
4436 self.server = self.pg1.remote_hosts[0]
4437
4438 self.server_in_addr = self.server.ip4
4439 self.server_out_addr = '11.11.11.11'
4440 self.server_in_port = random.randint(1025, 65535)
4441 self.server_out_port = random.randint(1025, 65535)
4442
4443 self.nat44_add_address(self.server_out_addr)
4444
4445 # add static mappings for server
4446 self.nat44_add_static_mapping(self.server_in_addr,
4447 self.server_out_addr,
4448 self.server_in_port,
4449 self.server_out_port,
4450 proto=IP_PROTOS.tcp)
4451 self.nat44_add_static_mapping(self.server_in_addr,
4452 self.server_out_addr,
4453 self.server_in_port,
4454 self.server_out_port,
4455 proto=IP_PROTOS.udp)
4456 self.nat44_add_static_mapping(self.server_in_addr,
4457 self.server_out_addr,
4458 proto=IP_PROTOS.icmp)
4459
4460 self.vapi.nat_set_reass(timeout=10)
4461
4462 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4463 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4464 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4465
4466 def test_reass_hairpinning(self):
4467 """ NAT44 fragments hairpinning """
4468 self.server = self.pg0.remote_hosts[1]
4469 self.host_in_port = random.randint(1025, 65535)
4470 self.server_in_port = random.randint(1025, 65535)
4471 self.server_out_port = random.randint(1025, 65535)
4472
4473 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004474 flags = self.config_flags.NAT_IS_INSIDE
4475 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4476 flags=flags)
4477 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004478 # add static mapping for server
4479 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4480 self.server_in_port,
4481 self.server_out_port,
4482 proto=IP_PROTOS.tcp)
4483 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4484 self.server_in_port,
4485 self.server_out_port,
4486 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004487 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004488
4489 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4490 self.reass_hairpinning(proto=IP_PROTOS.udp)
4491 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4492
Matus Fabiana6110b62018-06-13 05:39:07 -07004493 def test_dynamic(self):
4494 """ NAT44 dynamic translation test """
4495
4496 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004497 flags = self.config_flags.NAT_IS_INSIDE
4498 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4499 flags=flags)
4500 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07004501
Matus Fabian69ce30d2018-08-22 01:27:10 -07004502 nat_config = self.vapi.nat_show_config()
4503 self.assertEqual(1, nat_config.endpoint_dependent)
4504
Matus Fabiana6110b62018-06-13 05:39:07 -07004505 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004506 tcpn = self.statistics.get_counter(
4507 '/err/nat44-ed-in2out-slowpath/TCP packets')
4508 udpn = self.statistics.get_counter(
4509 '/err/nat44-ed-in2out-slowpath/UDP packets')
4510 icmpn = self.statistics.get_counter(
4511 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4512 totaln = self.statistics.get_counter(
4513 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4514
Matus Fabiana6110b62018-06-13 05:39:07 -07004515 pkts = self.create_stream_in(self.pg0, self.pg1)
4516 self.pg0.add_stream(pkts)
4517 self.pg_enable_capture(self.pg_interfaces)
4518 self.pg_start()
4519 capture = self.pg1.get_capture(len(pkts))
4520 self.verify_capture_out(capture)
4521
Matus Fabiana5e73762018-12-14 01:55:16 -08004522 err = self.statistics.get_counter(
4523 '/err/nat44-ed-in2out-slowpath/TCP packets')
4524 self.assertEqual(err - tcpn, 1)
4525 err = self.statistics.get_counter(
4526 '/err/nat44-ed-in2out-slowpath/UDP packets')
4527 self.assertEqual(err - udpn, 1)
4528 err = self.statistics.get_counter(
4529 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4530 self.assertEqual(err - icmpn, 1)
4531 err = self.statistics.get_counter(
4532 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4533 self.assertEqual(err - totaln, 3)
4534
Matus Fabiana6110b62018-06-13 05:39:07 -07004535 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004536 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4537 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4538 icmpn = self.statistics.get_counter(
4539 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4540 totaln = self.statistics.get_counter(
4541 '/err/nat44-ed-out2in/good out2in packets processed')
4542
Matus Fabiana6110b62018-06-13 05:39:07 -07004543 pkts = self.create_stream_out(self.pg1)
4544 self.pg1.add_stream(pkts)
4545 self.pg_enable_capture(self.pg_interfaces)
4546 self.pg_start()
4547 capture = self.pg0.get_capture(len(pkts))
4548 self.verify_capture_in(capture, self.pg0)
4549
Matus Fabiana5e73762018-12-14 01:55:16 -08004550 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4551 self.assertEqual(err - tcpn, 1)
4552 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4553 self.assertEqual(err - udpn, 1)
4554 err = self.statistics.get_counter(
4555 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4556 self.assertEqual(err - icmpn, 1)
4557 err = self.statistics.get_counter(
4558 '/err/nat44-ed-out2in/good out2in packets processed')
4559 self.assertEqual(err - totaln, 2)
4560
Matus Fabianfd0d5082018-12-18 01:08:51 -08004561 users = self.statistics.get_counter('/nat44/total-users')
4562 self.assertEqual(users[0][0], 1)
4563 sessions = self.statistics.get_counter('/nat44/total-sessions')
4564 self.assertEqual(sessions[0][0], 3)
4565
Matus Fabiana6110b62018-06-13 05:39:07 -07004566 def test_forwarding(self):
4567 """ NAT44 forwarding test """
4568
Filip Vargadd1e3e72019-04-15 18:52:43 +02004569 flags = self.config_flags.NAT_IS_INSIDE
4570 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4571 flags=flags)
4572 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07004573 self.vapi.nat44_forwarding_enable_disable(1)
4574
Filip Vargadd1e3e72019-04-15 18:52:43 +02004575 real_ip = self.pg0.remote_ip4
4576 alias_ip = self.nat_addr
4577 flags = self.config_flags.NAT_IS_ADDR_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07004578 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004579 external_ip=alias_ip,
4580 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07004581
4582 try:
4583 # in2out - static mapping match
4584
4585 pkts = self.create_stream_out(self.pg1)
4586 self.pg1.add_stream(pkts)
4587 self.pg_enable_capture(self.pg_interfaces)
4588 self.pg_start()
4589 capture = self.pg0.get_capture(len(pkts))
4590 self.verify_capture_in(capture, self.pg0)
4591
4592 pkts = self.create_stream_in(self.pg0, self.pg1)
4593 self.pg0.add_stream(pkts)
4594 self.pg_enable_capture(self.pg_interfaces)
4595 self.pg_start()
4596 capture = self.pg1.get_capture(len(pkts))
4597 self.verify_capture_out(capture, same_port=True)
4598
4599 # in2out - no static mapping match
4600
4601 host0 = self.pg0.remote_hosts[0]
4602 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4603 try:
4604 pkts = self.create_stream_out(self.pg1,
4605 dst_ip=self.pg0.remote_ip4,
4606 use_inside_ports=True)
4607 self.pg1.add_stream(pkts)
4608 self.pg_enable_capture(self.pg_interfaces)
4609 self.pg_start()
4610 capture = self.pg0.get_capture(len(pkts))
4611 self.verify_capture_in(capture, self.pg0)
4612
4613 pkts = self.create_stream_in(self.pg0, self.pg1)
4614 self.pg0.add_stream(pkts)
4615 self.pg_enable_capture(self.pg_interfaces)
4616 self.pg_start()
4617 capture = self.pg1.get_capture(len(pkts))
4618 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4619 same_port=True)
4620 finally:
4621 self.pg0.remote_hosts[0] = host0
4622
4623 user = self.pg0.remote_hosts[1]
4624 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4625 self.assertEqual(len(sessions), 3)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004626 self.assertTrue(sessions[0].flags &
4627 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabiana6110b62018-06-13 05:39:07 -07004628 self.vapi.nat44_del_session(
4629 sessions[0].inside_ip_address,
4630 sessions[0].inside_port,
4631 sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004632 flags=(self.config_flags.NAT_IS_INSIDE |
4633 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabiana6110b62018-06-13 05:39:07 -07004634 ext_host_address=sessions[0].ext_host_address,
4635 ext_host_port=sessions[0].ext_host_port)
4636 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4637 self.assertEqual(len(sessions), 2)
4638
4639 finally:
4640 self.vapi.nat44_forwarding_enable_disable(0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004641 flags = self.config_flags.NAT_IS_ADDR_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07004642 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4643 external_ip=alias_ip,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004644 is_add=0, flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07004645
4646 def test_static_lb(self):
4647 """ NAT44 local service load balancing """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004648 external_addr_n = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004649 external_port = 80
4650 local_port = 8080
4651 server1 = self.pg0.remote_hosts[0]
4652 server2 = self.pg0.remote_hosts[1]
4653
4654 locals = [{'addr': server1.ip4n,
4655 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004656 'probability': 70,
4657 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004658 {'addr': server2.ip4n,
4659 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004660 'probability': 30,
4661 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004662
4663 self.nat44_add_address(self.nat_addr)
4664 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4665 external_port,
4666 IP_PROTOS.tcp,
4667 local_num=len(locals),
4668 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004669 flags = self.config_flags.NAT_IS_INSIDE
4670 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4671 flags=flags)
4672 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07004673
4674 # from client to service
4675 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4676 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4677 TCP(sport=12345, dport=external_port))
4678 self.pg1.add_stream(p)
4679 self.pg_enable_capture(self.pg_interfaces)
4680 self.pg_start()
4681 capture = self.pg0.get_capture(1)
4682 p = capture[0]
4683 server = None
4684 try:
4685 ip = p[IP]
4686 tcp = p[TCP]
4687 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4688 if ip.dst == server1.ip4:
4689 server = server1
4690 else:
4691 server = server2
4692 self.assertEqual(tcp.dport, local_port)
4693 self.assert_packet_checksums_valid(p)
4694 except:
4695 self.logger.error(ppp("Unexpected or invalid packet:", p))
4696 raise
4697
4698 # from service back to client
4699 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4700 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4701 TCP(sport=local_port, dport=12345))
4702 self.pg0.add_stream(p)
4703 self.pg_enable_capture(self.pg_interfaces)
4704 self.pg_start()
4705 capture = self.pg1.get_capture(1)
4706 p = capture[0]
4707 try:
4708 ip = p[IP]
4709 tcp = p[TCP]
4710 self.assertEqual(ip.src, self.nat_addr)
4711 self.assertEqual(tcp.sport, external_port)
4712 self.assert_packet_checksums_valid(p)
4713 except:
4714 self.logger.error(ppp("Unexpected or invalid packet:", p))
4715 raise
4716
4717 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4718 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004719 self.assertTrue(sessions[0].flags &
4720 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabiana6110b62018-06-13 05:39:07 -07004721 self.vapi.nat44_del_session(
4722 sessions[0].inside_ip_address,
4723 sessions[0].inside_port,
4724 sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004725 flags=(self.config_flags.NAT_IS_INSIDE |
4726 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabiana6110b62018-06-13 05:39:07 -07004727 ext_host_address=sessions[0].ext_host_address,
4728 ext_host_port=sessions[0].ext_host_port)
4729 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4730 self.assertEqual(len(sessions), 0)
4731
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004732 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004733 def test_static_lb_multi_clients(self):
4734 """ NAT44 local service load balancing - multiple clients"""
4735
Filip Vargadd1e3e72019-04-15 18:52:43 +02004736 external_addr = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004737 external_port = 80
4738 local_port = 8080
4739 server1 = self.pg0.remote_hosts[0]
4740 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004741 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004742
4743 locals = [{'addr': server1.ip4n,
4744 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004745 'probability': 90,
4746 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004747 {'addr': server2.ip4n,
4748 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004749 'probability': 10,
4750 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004751
4752 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004753 self.vapi.nat44_add_del_lb_static_mapping(external_addr,
Matus Fabiana6110b62018-06-13 05:39:07 -07004754 external_port,
4755 IP_PROTOS.tcp,
4756 local_num=len(locals),
4757 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004758 flags = self.config_flags.NAT_IS_INSIDE
4759 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4760 flags=flags)
4761 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07004762
4763 server1_n = 0
4764 server2_n = 0
4765 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4766 pkts = []
4767 for client in clients:
4768 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4769 IP(src=client, dst=self.nat_addr) /
4770 TCP(sport=12345, dport=external_port))
4771 pkts.append(p)
4772 self.pg1.add_stream(pkts)
4773 self.pg_enable_capture(self.pg_interfaces)
4774 self.pg_start()
4775 capture = self.pg0.get_capture(len(pkts))
4776 for p in capture:
4777 if p[IP].dst == server1.ip4:
4778 server1_n += 1
4779 else:
4780 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004781 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004782
Matus Fabianb6865082018-12-06 03:11:09 -08004783 # add new back-end
Filip Vargadd1e3e72019-04-15 18:52:43 +02004784 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr,
Matus Fabianb6865082018-12-06 03:11:09 -08004785 external_port,
4786 server3.ip4n,
4787 local_port,
4788 IP_PROTOS.tcp,
4789 20)
4790 server1_n = 0
4791 server2_n = 0
4792 server3_n = 0
4793 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4794 pkts = []
4795 for client in clients:
4796 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4797 IP(src=client, dst=self.nat_addr) /
4798 TCP(sport=12346, dport=external_port))
4799 pkts.append(p)
4800 self.assertGreater(len(pkts), 0)
4801 self.pg1.add_stream(pkts)
4802 self.pg_enable_capture(self.pg_interfaces)
4803 self.pg_start()
4804 capture = self.pg0.get_capture(len(pkts))
4805 for p in capture:
4806 if p[IP].dst == server1.ip4:
4807 server1_n += 1
4808 elif p[IP].dst == server2.ip4:
4809 server2_n += 1
4810 else:
4811 server3_n += 1
4812 self.assertGreater(server1_n, 0)
4813 self.assertGreater(server2_n, 0)
4814 self.assertGreater(server3_n, 0)
4815
4816 # remove one back-end
Filip Vargadd1e3e72019-04-15 18:52:43 +02004817 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr,
Matus Fabianb6865082018-12-06 03:11:09 -08004818 external_port,
4819 server2.ip4n,
4820 local_port,
4821 IP_PROTOS.tcp,
4822 10,
4823 is_add=0)
4824 server1_n = 0
4825 server2_n = 0
4826 server3_n = 0
4827 self.pg1.add_stream(pkts)
4828 self.pg_enable_capture(self.pg_interfaces)
4829 self.pg_start()
4830 capture = self.pg0.get_capture(len(pkts))
4831 for p in capture:
4832 if p[IP].dst == server1.ip4:
4833 server1_n += 1
4834 elif p[IP].dst == server2.ip4:
4835 server2_n += 1
4836 else:
4837 server3_n += 1
4838 self.assertGreater(server1_n, 0)
4839 self.assertEqual(server2_n, 0)
4840 self.assertGreater(server3_n, 0)
4841
Matus Fabiana6110b62018-06-13 05:39:07 -07004842 def test_static_lb_2(self):
4843 """ NAT44 local service load balancing (asymmetrical rule) """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004844 external_addr = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004845 external_port = 80
4846 local_port = 8080
4847 server1 = self.pg0.remote_hosts[0]
4848 server2 = self.pg0.remote_hosts[1]
4849
4850 locals = [{'addr': server1.ip4n,
4851 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004852 'probability': 70,
4853 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004854 {'addr': server2.ip4n,
4855 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004856 'probability': 30,
4857 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004858
4859 self.vapi.nat44_forwarding_enable_disable(1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004860 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
4861 self.vapi.nat44_add_del_lb_static_mapping(external_addr,
Matus Fabiana6110b62018-06-13 05:39:07 -07004862 external_port,
4863 IP_PROTOS.tcp,
Matus Fabiana6110b62018-06-13 05:39:07 -07004864 local_num=len(locals),
Filip Vargadd1e3e72019-04-15 18:52:43 +02004865 locals=locals,
4866 flags=flags)
4867 flags = self.config_flags.NAT_IS_INSIDE
4868 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4869 flags=flags)
4870 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07004871
4872 # from client to service
4873 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4874 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4875 TCP(sport=12345, dport=external_port))
4876 self.pg1.add_stream(p)
4877 self.pg_enable_capture(self.pg_interfaces)
4878 self.pg_start()
4879 capture = self.pg0.get_capture(1)
4880 p = capture[0]
4881 server = None
4882 try:
4883 ip = p[IP]
4884 tcp = p[TCP]
4885 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4886 if ip.dst == server1.ip4:
4887 server = server1
4888 else:
4889 server = server2
4890 self.assertEqual(tcp.dport, local_port)
4891 self.assert_packet_checksums_valid(p)
4892 except:
4893 self.logger.error(ppp("Unexpected or invalid packet:", p))
4894 raise
4895
4896 # from service back to client
4897 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4898 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4899 TCP(sport=local_port, dport=12345))
4900 self.pg0.add_stream(p)
4901 self.pg_enable_capture(self.pg_interfaces)
4902 self.pg_start()
4903 capture = self.pg1.get_capture(1)
4904 p = capture[0]
4905 try:
4906 ip = p[IP]
4907 tcp = p[TCP]
4908 self.assertEqual(ip.src, self.nat_addr)
4909 self.assertEqual(tcp.sport, external_port)
4910 self.assert_packet_checksums_valid(p)
4911 except:
4912 self.logger.error(ppp("Unexpected or invalid packet:", p))
4913 raise
4914
4915 # from client to server (no translation)
4916 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4917 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4918 TCP(sport=12346, dport=local_port))
4919 self.pg1.add_stream(p)
4920 self.pg_enable_capture(self.pg_interfaces)
4921 self.pg_start()
4922 capture = self.pg0.get_capture(1)
4923 p = capture[0]
4924 server = None
4925 try:
4926 ip = p[IP]
4927 tcp = p[TCP]
4928 self.assertEqual(ip.dst, server1.ip4)
4929 self.assertEqual(tcp.dport, local_port)
4930 self.assert_packet_checksums_valid(p)
4931 except:
4932 self.logger.error(ppp("Unexpected or invalid packet:", p))
4933 raise
4934
4935 # from service back to client (no translation)
4936 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4937 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4938 TCP(sport=local_port, dport=12346))
4939 self.pg0.add_stream(p)
4940 self.pg_enable_capture(self.pg_interfaces)
4941 self.pg_start()
4942 capture = self.pg1.get_capture(1)
4943 p = capture[0]
4944 try:
4945 ip = p[IP]
4946 tcp = p[TCP]
4947 self.assertEqual(ip.src, server1.ip4)
4948 self.assertEqual(tcp.sport, local_port)
4949 self.assert_packet_checksums_valid(p)
4950 except:
4951 self.logger.error(ppp("Unexpected or invalid packet:", p))
4952 raise
4953
Matus Fabianea5b5be2018-09-03 05:02:23 -07004954 def test_lb_affinity(self):
4955 """ NAT44 local service load balancing affinity """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004956 external_addr = self.nat_addr
Matus Fabianea5b5be2018-09-03 05:02:23 -07004957 external_port = 80
4958 local_port = 8080
4959 server1 = self.pg0.remote_hosts[0]
4960 server2 = self.pg0.remote_hosts[1]
4961
4962 locals = [{'addr': server1.ip4n,
4963 'port': local_port,
4964 'probability': 50,
4965 'vrf_id': 0},
4966 {'addr': server2.ip4n,
4967 'port': local_port,
4968 'probability': 50,
4969 'vrf_id': 0}]
4970
4971 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004972 self.vapi.nat44_add_del_lb_static_mapping(external_addr,
Matus Fabianea5b5be2018-09-03 05:02:23 -07004973 external_port,
4974 IP_PROTOS.tcp,
4975 affinity=10800,
4976 local_num=len(locals),
4977 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004978 flags = self.config_flags.NAT_IS_INSIDE
4979 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4980 flags=flags)
4981 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianea5b5be2018-09-03 05:02:23 -07004982
4983 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4984 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4985 TCP(sport=1025, dport=external_port))
4986 self.pg1.add_stream(p)
4987 self.pg_enable_capture(self.pg_interfaces)
4988 self.pg_start()
4989 capture = self.pg0.get_capture(1)
4990 backend = capture[0][IP].dst
4991
Filip Vargadd1e3e72019-04-15 18:52:43 +02004992 sessions = self.vapi.nat44_user_session_dump(backend, 0)
Matus Fabianea5b5be2018-09-03 05:02:23 -07004993 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004994 self.assertTrue(sessions[0].flags &
4995 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabianea5b5be2018-09-03 05:02:23 -07004996 self.vapi.nat44_del_session(
4997 sessions[0].inside_ip_address,
4998 sessions[0].inside_port,
4999 sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005000 flags=(self.config_flags.NAT_IS_INSIDE |
5001 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabianea5b5be2018-09-03 05:02:23 -07005002 ext_host_address=sessions[0].ext_host_address,
5003 ext_host_port=sessions[0].ext_host_port)
5004
5005 pkts = []
5006 for port in range(1030, 1100):
5007 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5008 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5009 TCP(sport=port, dport=external_port))
5010 pkts.append(p)
5011 self.pg1.add_stream(pkts)
5012 self.pg_enable_capture(self.pg_interfaces)
5013 self.pg_start()
5014 capture = self.pg0.get_capture(len(pkts))
5015 for p in capture:
5016 self.assertEqual(p[IP].dst, backend)
5017
Matus Fabiana6110b62018-06-13 05:39:07 -07005018 def test_unknown_proto(self):
5019 """ NAT44 translate packet with unknown protocol """
5020 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005021 flags = self.config_flags.NAT_IS_INSIDE
5022 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5023 flags=flags)
5024 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005025
5026 # in2out
5027 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5028 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5029 TCP(sport=self.tcp_port_in, dport=20))
5030 self.pg0.add_stream(p)
5031 self.pg_enable_capture(self.pg_interfaces)
5032 self.pg_start()
5033 p = self.pg1.get_capture(1)
5034
5035 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5036 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5037 GRE() /
5038 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5039 TCP(sport=1234, dport=1234))
5040 self.pg0.add_stream(p)
5041 self.pg_enable_capture(self.pg_interfaces)
5042 self.pg_start()
5043 p = self.pg1.get_capture(1)
5044 packet = p[0]
5045 try:
5046 self.assertEqual(packet[IP].src, self.nat_addr)
5047 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005048 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005049 self.assert_packet_checksums_valid(packet)
5050 except:
5051 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5052 raise
5053
5054 # out2in
5055 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5056 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5057 GRE() /
5058 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5059 TCP(sport=1234, dport=1234))
5060 self.pg1.add_stream(p)
5061 self.pg_enable_capture(self.pg_interfaces)
5062 self.pg_start()
5063 p = self.pg0.get_capture(1)
5064 packet = p[0]
5065 try:
5066 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5067 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005068 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005069 self.assert_packet_checksums_valid(packet)
5070 except:
5071 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5072 raise
5073
5074 def test_hairpinning_unknown_proto(self):
5075 """ NAT44 translate packet with unknown protocol - hairpinning """
5076 host = self.pg0.remote_hosts[0]
5077 server = self.pg0.remote_hosts[1]
5078 host_in_port = 1234
5079 server_out_port = 8765
5080 server_nat_ip = "10.0.0.11"
5081
5082 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005083 flags = self.config_flags.NAT_IS_INSIDE
5084 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5085 flags=flags)
5086 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005087
5088 # add static mapping for server
5089 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5090
5091 # host to server
5092 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5093 IP(src=host.ip4, dst=server_nat_ip) /
5094 TCP(sport=host_in_port, dport=server_out_port))
5095 self.pg0.add_stream(p)
5096 self.pg_enable_capture(self.pg_interfaces)
5097 self.pg_start()
5098 self.pg0.get_capture(1)
5099
5100 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5101 IP(src=host.ip4, dst=server_nat_ip) /
5102 GRE() /
5103 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5104 TCP(sport=1234, dport=1234))
5105 self.pg0.add_stream(p)
5106 self.pg_enable_capture(self.pg_interfaces)
5107 self.pg_start()
5108 p = self.pg0.get_capture(1)
5109 packet = p[0]
5110 try:
5111 self.assertEqual(packet[IP].src, self.nat_addr)
5112 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005113 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005114 self.assert_packet_checksums_valid(packet)
5115 except:
5116 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5117 raise
5118
5119 # server to host
5120 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5121 IP(src=server.ip4, dst=self.nat_addr) /
5122 GRE() /
5123 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5124 TCP(sport=1234, dport=1234))
5125 self.pg0.add_stream(p)
5126 self.pg_enable_capture(self.pg_interfaces)
5127 self.pg_start()
5128 p = self.pg0.get_capture(1)
5129 packet = p[0]
5130 try:
5131 self.assertEqual(packet[IP].src, server_nat_ip)
5132 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005133 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005134 self.assert_packet_checksums_valid(packet)
5135 except:
5136 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5137 raise
5138
5139 def test_output_feature_and_service(self):
5140 """ NAT44 interface output feature and services """
5141 external_addr = '1.2.3.4'
5142 external_port = 80
5143 local_port = 8080
5144
5145 self.vapi.nat44_forwarding_enable_disable(1)
5146 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005147 flags = self.config_flags.NAT_IS_ADDR_ONLY
5148 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n,
5149 flags=flags)
5150 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005151 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5152 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005153 proto=IP_PROTOS.tcp, flags=flags)
5154 flags = self.config_flags.NAT_IS_INSIDE
Matus Fabiana6110b62018-06-13 05:39:07 -07005155 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5156 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005157 flags=flags)
5158 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005159
5160 # from client to service
5161 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5162 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5163 TCP(sport=12345, dport=external_port))
5164 self.pg1.add_stream(p)
5165 self.pg_enable_capture(self.pg_interfaces)
5166 self.pg_start()
5167 capture = self.pg0.get_capture(1)
5168 p = capture[0]
5169 try:
5170 ip = p[IP]
5171 tcp = p[TCP]
5172 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5173 self.assertEqual(tcp.dport, local_port)
5174 self.assert_packet_checksums_valid(p)
5175 except:
5176 self.logger.error(ppp("Unexpected or invalid packet:", p))
5177 raise
5178
5179 # from service back to client
5180 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5181 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5182 TCP(sport=local_port, dport=12345))
5183 self.pg0.add_stream(p)
5184 self.pg_enable_capture(self.pg_interfaces)
5185 self.pg_start()
5186 capture = self.pg1.get_capture(1)
5187 p = capture[0]
5188 try:
5189 ip = p[IP]
5190 tcp = p[TCP]
5191 self.assertEqual(ip.src, external_addr)
5192 self.assertEqual(tcp.sport, external_port)
5193 self.assert_packet_checksums_valid(p)
5194 except:
5195 self.logger.error(ppp("Unexpected or invalid packet:", p))
5196 raise
5197
5198 # from local network host to external network
5199 pkts = self.create_stream_in(self.pg0, self.pg1)
5200 self.pg0.add_stream(pkts)
5201 self.pg_enable_capture(self.pg_interfaces)
5202 self.pg_start()
5203 capture = self.pg1.get_capture(len(pkts))
5204 self.verify_capture_out(capture)
5205 pkts = self.create_stream_in(self.pg0, self.pg1)
5206 self.pg0.add_stream(pkts)
5207 self.pg_enable_capture(self.pg_interfaces)
5208 self.pg_start()
5209 capture = self.pg1.get_capture(len(pkts))
5210 self.verify_capture_out(capture)
5211
5212 # from external network back to local network host
5213 pkts = self.create_stream_out(self.pg1)
5214 self.pg1.add_stream(pkts)
5215 self.pg_enable_capture(self.pg_interfaces)
5216 self.pg_start()
5217 capture = self.pg0.get_capture(len(pkts))
5218 self.verify_capture_in(capture, self.pg0)
5219
5220 def test_output_feature_and_service2(self):
5221 """ NAT44 interface output feature and service host direct access """
5222 self.vapi.nat44_forwarding_enable_disable(1)
5223 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005224 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005225
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005226 # session initiated from service host - translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005227 pkts = self.create_stream_in(self.pg0, self.pg1)
5228 self.pg0.add_stream(pkts)
5229 self.pg_enable_capture(self.pg_interfaces)
5230 self.pg_start()
5231 capture = self.pg1.get_capture(len(pkts))
5232 self.verify_capture_out(capture)
5233
5234 pkts = self.create_stream_out(self.pg1)
5235 self.pg1.add_stream(pkts)
5236 self.pg_enable_capture(self.pg_interfaces)
5237 self.pg_start()
5238 capture = self.pg0.get_capture(len(pkts))
5239 self.verify_capture_in(capture, self.pg0)
5240
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005241 # session initiated from remote host - do not translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005242 self.tcp_port_in = 60303
5243 self.udp_port_in = 60304
5244 self.icmp_id_in = 60305
5245 pkts = self.create_stream_out(self.pg1,
5246 self.pg0.remote_ip4,
5247 use_inside_ports=True)
5248 self.pg1.add_stream(pkts)
5249 self.pg_enable_capture(self.pg_interfaces)
5250 self.pg_start()
5251 capture = self.pg0.get_capture(len(pkts))
5252 self.verify_capture_in(capture, self.pg0)
5253
5254 pkts = self.create_stream_in(self.pg0, self.pg1)
5255 self.pg0.add_stream(pkts)
5256 self.pg_enable_capture(self.pg_interfaces)
5257 self.pg_start()
5258 capture = self.pg1.get_capture(len(pkts))
5259 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5260 same_port=True)
5261
5262 def test_output_feature_and_service3(self):
5263 """ NAT44 interface output feature and DST NAT """
5264 external_addr = '1.2.3.4'
5265 external_port = 80
5266 local_port = 8080
5267
5268 self.vapi.nat44_forwarding_enable_disable(1)
5269 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005270 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005271 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5272 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005273 proto=IP_PROTOS.tcp, flags=flags)
5274 flags = self.config_flags.NAT_IS_INSIDE
Matus Fabiana6110b62018-06-13 05:39:07 -07005275 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5276 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005277 flags=flags)
5278 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005279
5280 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5281 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5282 TCP(sport=12345, dport=external_port))
5283 self.pg0.add_stream(p)
5284 self.pg_enable_capture(self.pg_interfaces)
5285 self.pg_start()
5286 capture = self.pg1.get_capture(1)
5287 p = capture[0]
5288 try:
5289 ip = p[IP]
5290 tcp = p[TCP]
5291 self.assertEqual(ip.src, self.pg0.remote_ip4)
5292 self.assertEqual(tcp.sport, 12345)
5293 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5294 self.assertEqual(tcp.dport, local_port)
5295 self.assert_packet_checksums_valid(p)
5296 except:
5297 self.logger.error(ppp("Unexpected or invalid packet:", p))
5298 raise
5299
5300 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5301 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5302 TCP(sport=local_port, dport=12345))
5303 self.pg1.add_stream(p)
5304 self.pg_enable_capture(self.pg_interfaces)
5305 self.pg_start()
5306 capture = self.pg0.get_capture(1)
5307 p = capture[0]
5308 try:
5309 ip = p[IP]
5310 tcp = p[TCP]
5311 self.assertEqual(ip.src, external_addr)
5312 self.assertEqual(tcp.sport, external_port)
5313 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5314 self.assertEqual(tcp.dport, 12345)
5315 self.assert_packet_checksums_valid(p)
5316 except:
5317 self.logger.error(ppp("Unexpected or invalid packet:", p))
5318 raise
5319
Matus Fabian182e37e2018-08-14 04:21:26 -07005320 def test_next_src_nat(self):
5321 """ On way back forward packet to nat44-in2out node. """
5322 twice_nat_addr = '10.0.1.3'
5323 external_port = 80
5324 local_port = 8080
5325 post_twice_nat_port = 0
5326
5327 self.vapi.nat44_forwarding_enable_disable(1)
5328 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005329 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5330 self.config_flags.NAT_IS_SELF_TWICE_NAT)
Matus Fabian182e37e2018-08-14 04:21:26 -07005331 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5332 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005333 proto=IP_PROTOS.tcp, vrf_id=1,
5334 flags=flags)
5335 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
Matus Fabian182e37e2018-08-14 04:21:26 -07005336
5337 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5338 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5339 TCP(sport=12345, dport=external_port))
5340 self.pg6.add_stream(p)
5341 self.pg_enable_capture(self.pg_interfaces)
5342 self.pg_start()
5343 capture = self.pg6.get_capture(1)
5344 p = capture[0]
5345 try:
5346 ip = p[IP]
5347 tcp = p[TCP]
5348 self.assertEqual(ip.src, twice_nat_addr)
5349 self.assertNotEqual(tcp.sport, 12345)
5350 post_twice_nat_port = tcp.sport
5351 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5352 self.assertEqual(tcp.dport, local_port)
5353 self.assert_packet_checksums_valid(p)
5354 except:
5355 self.logger.error(ppp("Unexpected or invalid packet:", p))
5356 raise
5357
5358 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5359 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5360 TCP(sport=local_port, dport=post_twice_nat_port))
5361 self.pg6.add_stream(p)
5362 self.pg_enable_capture(self.pg_interfaces)
5363 self.pg_start()
5364 capture = self.pg6.get_capture(1)
5365 p = capture[0]
5366 try:
5367 ip = p[IP]
5368 tcp = p[TCP]
5369 self.assertEqual(ip.src, self.pg1.remote_ip4)
5370 self.assertEqual(tcp.sport, external_port)
5371 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5372 self.assertEqual(tcp.dport, 12345)
5373 self.assert_packet_checksums_valid(p)
5374 except:
5375 self.logger.error(ppp("Unexpected or invalid packet:", p))
5376 raise
5377
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005378 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5379 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005380 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005381
Matus Fabianb932d262017-12-18 05:38:24 -08005382 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005383 if lb:
5384 if not same_pg:
5385 port_in1 = port_in
5386 port_in2 = port_in
5387 else:
Ole Troan9a475372019-03-05 16:58:24 +01005388 port_in1 = port_in + 1
5389 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005390
Matus Fabianb932d262017-12-18 05:38:24 -08005391 port_out = 80
5392 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005393
5394 server1 = self.pg0.remote_hosts[0]
5395 server2 = self.pg0.remote_hosts[1]
5396 if lb and same_pg:
5397 server2 = server1
5398 if not lb:
5399 server = server1
5400
5401 pg0 = self.pg0
5402 if same_pg:
5403 pg1 = self.pg0
5404 else:
5405 pg1 = self.pg1
5406
5407 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5408 client_id == 1)
5409
Matus Fabianb932d262017-12-18 05:38:24 -08005410 self.nat44_add_address(self.nat_addr)
5411 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005412
5413 flags = 0
5414 if self_twice_nat:
5415 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5416 else:
5417 flags |= self.config_flags.NAT_IS_TWICE_NAT
5418
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005419 if not lb:
5420 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5421 port_in, port_out,
5422 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005423 flags=flags)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005424 else:
5425 locals = [{'addr': server1.ip4n,
5426 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005427 'probability': 50,
5428 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005429 {'addr': server2.ip4n,
5430 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005431 'probability': 50,
5432 'vrf_id': 0}]
Filip Vargadd1e3e72019-04-15 18:52:43 +02005433 out_addr = self.nat_addr
5434
5435 self.vapi.nat44_add_del_lb_static_mapping(out_addr,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005436 port_out,
5437 IP_PROTOS.tcp,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005438 local_num=len(locals),
Filip Vargadd1e3e72019-04-15 18:52:43 +02005439 locals=locals,
5440 flags=flags)
5441 flags = self.config_flags.NAT_IS_INSIDE
5442 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index,
5443 flags=flags)
5444 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index)
Matus Fabianb932d262017-12-18 05:38:24 -08005445
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005446 if same_pg:
5447 if not lb:
5448 client = server
5449 else:
5450 assert client_id is not None
5451 if client_id == 1:
5452 client = self.pg0.remote_hosts[0]
5453 elif client_id == 2:
5454 client = self.pg0.remote_hosts[1]
5455 else:
5456 client = pg1.remote_hosts[0]
5457 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5458 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005459 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005460 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005461 self.pg_enable_capture(self.pg_interfaces)
5462 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005463 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005464 p = capture[0]
5465 try:
5466 ip = p[IP]
5467 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005468 if lb:
5469 if ip.dst == server1.ip4:
5470 server = server1
5471 port_in = port_in1
5472 else:
5473 server = server2
5474 port_in = port_in2
5475 self.assertEqual(ip.dst, server.ip4)
5476 if lb and same_pg:
5477 self.assertIn(tcp.dport, [port_in1, port_in2])
5478 else:
5479 self.assertEqual(tcp.dport, port_in)
5480 if eh_translate:
5481 self.assertEqual(ip.src, twice_nat_addr)
5482 self.assertNotEqual(tcp.sport, eh_port_out)
5483 else:
5484 self.assertEqual(ip.src, client.ip4)
5485 self.assertEqual(tcp.sport, eh_port_out)
5486 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005487 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005488 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005489 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005490 except:
5491 self.logger.error(ppp("Unexpected or invalid packet:", p))
5492 raise
5493
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005494 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5495 IP(src=server.ip4, dst=eh_addr_in) /
5496 TCP(sport=saved_port_in, dport=eh_port_in))
5497 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005498 self.pg_enable_capture(self.pg_interfaces)
5499 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005500 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005501 p = capture[0]
5502 try:
5503 ip = p[IP]
5504 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005505 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005506 self.assertEqual(ip.src, self.nat_addr)
5507 self.assertEqual(tcp.dport, eh_port_out)
5508 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005509 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005510 except:
5511 self.logger.error(ppp("Unexpected or invalid packet:", p))
5512 raise
5513
Matus Fabian70a26ac2018-05-14 06:20:28 -07005514 if eh_translate:
5515 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5516 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005517 self.assertTrue(sessions[0].flags &
5518 self.config_flags.NAT_IS_EXT_HOST_VALID)
5519 self.assertTrue(sessions[0].flags &
5520 self.config_flags.NAT_IS_TWICE_NAT)
5521 self.logger.error(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian70a26ac2018-05-14 06:20:28 -07005522 self.vapi.nat44_del_session(
5523 sessions[0].inside_ip_address,
5524 sessions[0].inside_port,
5525 sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005526 flags=(self.config_flags.NAT_IS_INSIDE |
5527 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabian70a26ac2018-05-14 06:20:28 -07005528 ext_host_address=sessions[0].ext_host_nat_address,
5529 ext_host_port=sessions[0].ext_host_nat_port)
5530 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5531 self.assertEqual(len(sessions), 0)
5532
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005533 def test_twice_nat(self):
5534 """ Twice NAT44 """
5535 self.twice_nat_common()
5536
5537 def test_self_twice_nat_positive(self):
5538 """ Self Twice NAT44 (positive test) """
5539 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5540
5541 def test_self_twice_nat_negative(self):
5542 """ Self Twice NAT44 (negative test) """
5543 self.twice_nat_common(self_twice_nat=True)
5544
Matus Fabianb932d262017-12-18 05:38:24 -08005545 def test_twice_nat_lb(self):
5546 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005547 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005548
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005549 def test_self_twice_nat_lb_positive(self):
5550 """ Self Twice NAT44 local service load balancing (positive test) """
5551 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5552 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005553
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005554 def test_self_twice_nat_lb_negative(self):
5555 """ Self Twice NAT44 local service load balancing (negative test) """
5556 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5557 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005558
5559 def test_twice_nat_interface_addr(self):
5560 """ Acquire twice NAT44 addresses from interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005561 flags = self.config_flags.NAT_IS_TWICE_NAT
Ole Troane1ade682019-03-04 23:55:43 +01005562 self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005563 flags=flags)
Matus Fabianb932d262017-12-18 05:38:24 -08005564
5565 # no address in NAT pool
5566 adresses = self.vapi.nat44_address_dump()
5567 self.assertEqual(0, len(adresses))
5568
5569 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005570 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005571 adresses = self.vapi.nat44_address_dump()
5572 self.assertEqual(1, len(adresses))
Filip Vargadd1e3e72019-04-15 18:52:43 +02005573 self.assertEqual(str(adresses[0].ip_address),
5574 self.pg3.local_ip4)
5575 self.assertEqual(adresses[0].flags, flags)
Matus Fabianb932d262017-12-18 05:38:24 -08005576
5577 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005578 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005579 adresses = self.vapi.nat44_address_dump()
5580 self.assertEqual(0, len(adresses))
5581
Matus Fabian6c01dce2018-11-16 04:41:31 -08005582 def test_tcp_close(self):
5583 """ Close TCP session from inside network - output feature """
5584 self.vapi.nat44_forwarding_enable_disable(1)
5585 self.nat44_add_address(self.pg1.local_ip4)
5586 twice_nat_addr = '10.0.1.3'
5587 service_ip = '192.168.16.150'
5588 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005589 flags = self.config_flags.NAT_IS_INSIDE
Matus Fabian6c01dce2018-11-16 04:41:31 -08005590 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5591 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005592 flags=flags)
5593 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
5594 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5595 self.config_flags.NAT_IS_TWICE_NAT)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005596 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5597 service_ip,
5598 80,
5599 80,
5600 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005601 flags=flags)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005602 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5603 start_sessnum = len(sessions)
5604
5605 # SYN packet out->in
5606 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5607 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5608 TCP(sport=33898, dport=80, flags="S"))
5609 self.pg1.add_stream(p)
5610 self.pg_enable_capture(self.pg_interfaces)
5611 self.pg_start()
5612 capture = self.pg0.get_capture(1)
5613 p = capture[0]
5614 tcp_port = p[TCP].sport
5615
5616 # SYN + ACK packet in->out
5617 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5618 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5619 TCP(sport=80, dport=tcp_port, flags="SA"))
5620 self.pg0.add_stream(p)
5621 self.pg_enable_capture(self.pg_interfaces)
5622 self.pg_start()
5623 self.pg1.get_capture(1)
5624
5625 # ACK packet out->in
5626 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5627 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5628 TCP(sport=33898, dport=80, flags="A"))
5629 self.pg1.add_stream(p)
5630 self.pg_enable_capture(self.pg_interfaces)
5631 self.pg_start()
5632 self.pg0.get_capture(1)
5633
5634 # FIN packet in -> out
5635 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5636 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5637 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5638 self.pg0.add_stream(p)
5639 self.pg_enable_capture(self.pg_interfaces)
5640 self.pg_start()
5641 self.pg1.get_capture(1)
5642
5643 # FIN+ACK packet out -> in
5644 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5645 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5646 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5647 self.pg1.add_stream(p)
5648 self.pg_enable_capture(self.pg_interfaces)
5649 self.pg_start()
5650 self.pg0.get_capture(1)
5651
5652 # ACK packet in -> out
5653 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5654 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5655 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5656 self.pg0.add_stream(p)
5657 self.pg_enable_capture(self.pg_interfaces)
5658 self.pg_start()
5659 self.pg1.get_capture(1)
5660
5661 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5662 0)
5663 self.assertEqual(len(sessions) - start_sessnum, 0)
5664
Matus Fabianebdf1902018-05-04 03:57:42 -07005665 def test_tcp_session_close_in(self):
5666 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005667 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005668 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005669 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07005670 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5671 self.nat_addr,
5672 self.tcp_port_in,
5673 self.tcp_port_out,
5674 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005675 flags=flags)
5676 flags = self.config_flags.NAT_IS_INSIDE
5677 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5678 flags=flags)
5679 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianebdf1902018-05-04 03:57:42 -07005680
5681 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5682 start_sessnum = len(sessions)
5683
5684 self.initiate_tcp_session(self.pg0, self.pg1)
5685
Matus Fabian229c1aa2018-05-28 04:09:52 -07005686 # FIN packet in -> out
5687 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5688 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5689 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5690 flags="FA", seq=100, ack=300))
5691 self.pg0.add_stream(p)
5692 self.pg_enable_capture(self.pg_interfaces)
5693 self.pg_start()
5694 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005695
Matus Fabian229c1aa2018-05-28 04:09:52 -07005696 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005697
Matus Fabian229c1aa2018-05-28 04:09:52 -07005698 # ACK packet out -> in
5699 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5700 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5701 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5702 flags="A", seq=300, ack=101))
5703 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005704
Matus Fabian229c1aa2018-05-28 04:09:52 -07005705 # FIN packet out -> in
5706 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5707 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5708 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5709 flags="FA", seq=300, ack=101))
5710 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005711
Matus Fabian229c1aa2018-05-28 04:09:52 -07005712 self.pg1.add_stream(pkts)
5713 self.pg_enable_capture(self.pg_interfaces)
5714 self.pg_start()
5715 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005716
Matus Fabian229c1aa2018-05-28 04:09:52 -07005717 # ACK packet in -> out
5718 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5719 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5720 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5721 flags="A", seq=101, ack=301))
5722 self.pg0.add_stream(p)
5723 self.pg_enable_capture(self.pg_interfaces)
5724 self.pg_start()
5725 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005726
Matus Fabian229c1aa2018-05-28 04:09:52 -07005727 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5728 0)
5729 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005730
5731 def test_tcp_session_close_out(self):
5732 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005733 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005734 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005735 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07005736 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5737 self.nat_addr,
5738 self.tcp_port_in,
5739 self.tcp_port_out,
5740 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005741 flags=flags)
5742 flags = self.config_flags.NAT_IS_INSIDE
5743 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5744 flags=flags)
5745 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianebdf1902018-05-04 03:57:42 -07005746
5747 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5748 start_sessnum = len(sessions)
5749
5750 self.initiate_tcp_session(self.pg0, self.pg1)
5751
Matus Fabian229c1aa2018-05-28 04:09:52 -07005752 # FIN packet out -> in
5753 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5754 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5755 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5756 flags="FA", seq=100, ack=300))
5757 self.pg1.add_stream(p)
5758 self.pg_enable_capture(self.pg_interfaces)
5759 self.pg_start()
5760 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005761
Matus Fabian229c1aa2018-05-28 04:09:52 -07005762 # FIN+ACK packet in -> out
5763 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5764 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5765 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5766 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005767
Matus Fabian229c1aa2018-05-28 04:09:52 -07005768 self.pg0.add_stream(p)
5769 self.pg_enable_capture(self.pg_interfaces)
5770 self.pg_start()
5771 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005772
Matus Fabian229c1aa2018-05-28 04:09:52 -07005773 # ACK packet out -> in
5774 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5775 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5776 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5777 flags="A", seq=101, ack=301))
5778 self.pg1.add_stream(p)
5779 self.pg_enable_capture(self.pg_interfaces)
5780 self.pg_start()
5781 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005782
Matus Fabian229c1aa2018-05-28 04:09:52 -07005783 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5784 0)
5785 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005786
5787 def test_tcp_session_close_simultaneous(self):
5788 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005789 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005790 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005791 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07005792 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5793 self.nat_addr,
5794 self.tcp_port_in,
5795 self.tcp_port_out,
5796 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005797 flags=flags)
5798 flags = self.config_flags.NAT_IS_INSIDE
5799 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5800 flags=flags)
5801 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianebdf1902018-05-04 03:57:42 -07005802
5803 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5804 start_sessnum = len(sessions)
5805
5806 self.initiate_tcp_session(self.pg0, self.pg1)
5807
Matus Fabian229c1aa2018-05-28 04:09:52 -07005808 # FIN packet in -> out
5809 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5810 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5811 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5812 flags="FA", seq=100, ack=300))
5813 self.pg0.add_stream(p)
5814 self.pg_enable_capture(self.pg_interfaces)
5815 self.pg_start()
5816 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005817
Matus Fabian229c1aa2018-05-28 04:09:52 -07005818 # FIN packet out -> in
5819 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5820 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5821 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5822 flags="FA", seq=300, ack=100))
5823 self.pg1.add_stream(p)
5824 self.pg_enable_capture(self.pg_interfaces)
5825 self.pg_start()
5826 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005827
Matus Fabian229c1aa2018-05-28 04:09:52 -07005828 # ACK packet in -> out
5829 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5830 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5831 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5832 flags="A", seq=101, ack=301))
5833 self.pg0.add_stream(p)
5834 self.pg_enable_capture(self.pg_interfaces)
5835 self.pg_start()
5836 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005837
Matus Fabian229c1aa2018-05-28 04:09:52 -07005838 # ACK packet out -> in
5839 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5840 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5841 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5842 flags="A", seq=301, ack=101))
5843 self.pg1.add_stream(p)
5844 self.pg_enable_capture(self.pg_interfaces)
5845 self.pg_start()
5846 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005847
Matus Fabian229c1aa2018-05-28 04:09:52 -07005848 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5849 0)
5850 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005851
Matus Fabiana6110b62018-06-13 05:39:07 -07005852 def test_one_armed_nat44_static(self):
5853 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5854 remote_host = self.pg4.remote_hosts[0]
5855 local_host = self.pg4.remote_hosts[1]
5856 external_port = 80
5857 local_port = 8080
5858 eh_port_in = 0
5859
5860 self.vapi.nat44_forwarding_enable_disable(1)
5861 self.nat44_add_address(self.nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005862 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5863 self.config_flags.NAT_IS_TWICE_NAT)
Matus Fabiana6110b62018-06-13 05:39:07 -07005864 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5865 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005866 proto=IP_PROTOS.tcp, flags=flags)
5867 flags = self.config_flags.NAT_IS_INSIDE
Matus Fabiana6110b62018-06-13 05:39:07 -07005868 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5869 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005870 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07005871
5872 # from client to service
5873 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5874 IP(src=remote_host.ip4, dst=self.nat_addr) /
5875 TCP(sport=12345, dport=external_port))
5876 self.pg4.add_stream(p)
5877 self.pg_enable_capture(self.pg_interfaces)
5878 self.pg_start()
5879 capture = self.pg4.get_capture(1)
5880 p = capture[0]
5881 try:
5882 ip = p[IP]
5883 tcp = p[TCP]
5884 self.assertEqual(ip.dst, local_host.ip4)
5885 self.assertEqual(ip.src, self.nat_addr)
5886 self.assertEqual(tcp.dport, local_port)
5887 self.assertNotEqual(tcp.sport, 12345)
5888 eh_port_in = tcp.sport
5889 self.assert_packet_checksums_valid(p)
5890 except:
5891 self.logger.error(ppp("Unexpected or invalid packet:", p))
5892 raise
5893
5894 # from service back to client
5895 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5896 IP(src=local_host.ip4, dst=self.nat_addr) /
5897 TCP(sport=local_port, dport=eh_port_in))
5898 self.pg4.add_stream(p)
5899 self.pg_enable_capture(self.pg_interfaces)
5900 self.pg_start()
5901 capture = self.pg4.get_capture(1)
5902 p = capture[0]
5903 try:
5904 ip = p[IP]
5905 tcp = p[TCP]
5906 self.assertEqual(ip.src, self.nat_addr)
5907 self.assertEqual(ip.dst, remote_host.ip4)
5908 self.assertEqual(tcp.sport, external_port)
5909 self.assertEqual(tcp.dport, 12345)
5910 self.assert_packet_checksums_valid(p)
5911 except:
5912 self.logger.error(ppp("Unexpected or invalid packet:", p))
5913 raise
5914
5915 def test_static_with_port_out2(self):
5916 """ 1:1 NAPT asymmetrical rule """
5917
5918 external_port = 80
5919 local_port = 8080
5920
5921 self.vapi.nat44_forwarding_enable_disable(1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005922 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005923 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5924 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005925 proto=IP_PROTOS.tcp, flags=flags)
5926 flags = self.config_flags.NAT_IS_INSIDE
5927 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5928 flags=flags)
5929 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005930
5931 # from client to service
5932 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5933 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5934 TCP(sport=12345, dport=external_port))
5935 self.pg1.add_stream(p)
5936 self.pg_enable_capture(self.pg_interfaces)
5937 self.pg_start()
5938 capture = self.pg0.get_capture(1)
5939 p = capture[0]
5940 try:
5941 ip = p[IP]
5942 tcp = p[TCP]
5943 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5944 self.assertEqual(tcp.dport, local_port)
5945 self.assert_packet_checksums_valid(p)
5946 except:
5947 self.logger.error(ppp("Unexpected or invalid packet:", p))
5948 raise
5949
5950 # ICMP error
5951 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5952 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5953 ICMP(type=11) / capture[0][IP])
5954 self.pg0.add_stream(p)
5955 self.pg_enable_capture(self.pg_interfaces)
5956 self.pg_start()
5957 capture = self.pg1.get_capture(1)
5958 p = capture[0]
5959 try:
5960 self.assertEqual(p[IP].src, self.nat_addr)
5961 inner = p[IPerror]
5962 self.assertEqual(inner.dst, self.nat_addr)
5963 self.assertEqual(inner[TCPerror].dport, external_port)
5964 except:
5965 self.logger.error(ppp("Unexpected or invalid packet:", p))
5966 raise
5967
5968 # from service back to client
5969 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5970 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5971 TCP(sport=local_port, dport=12345))
5972 self.pg0.add_stream(p)
5973 self.pg_enable_capture(self.pg_interfaces)
5974 self.pg_start()
5975 capture = self.pg1.get_capture(1)
5976 p = capture[0]
5977 try:
5978 ip = p[IP]
5979 tcp = p[TCP]
5980 self.assertEqual(ip.src, self.nat_addr)
5981 self.assertEqual(tcp.sport, external_port)
5982 self.assert_packet_checksums_valid(p)
5983 except:
5984 self.logger.error(ppp("Unexpected or invalid packet:", p))
5985 raise
5986
5987 # ICMP error
5988 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5989 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5990 ICMP(type=11) / capture[0][IP])
5991 self.pg1.add_stream(p)
5992 self.pg_enable_capture(self.pg_interfaces)
5993 self.pg_start()
5994 capture = self.pg0.get_capture(1)
5995 p = capture[0]
5996 try:
5997 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5998 inner = p[IPerror]
5999 self.assertEqual(inner.src, self.pg0.remote_ip4)
6000 self.assertEqual(inner[TCPerror].sport, local_port)
6001 except:
6002 self.logger.error(ppp("Unexpected or invalid packet:", p))
6003 raise
6004
6005 # from client to server (no translation)
6006 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6007 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6008 TCP(sport=12346, dport=local_port))
6009 self.pg1.add_stream(p)
6010 self.pg_enable_capture(self.pg_interfaces)
6011 self.pg_start()
6012 capture = self.pg0.get_capture(1)
6013 p = capture[0]
6014 try:
6015 ip = p[IP]
6016 tcp = p[TCP]
6017 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6018 self.assertEqual(tcp.dport, local_port)
6019 self.assert_packet_checksums_valid(p)
6020 except:
6021 self.logger.error(ppp("Unexpected or invalid packet:", p))
6022 raise
6023
6024 # from service back to client (no translation)
6025 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6026 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6027 TCP(sport=local_port, dport=12346))
6028 self.pg0.add_stream(p)
6029 self.pg_enable_capture(self.pg_interfaces)
6030 self.pg_start()
6031 capture = self.pg1.get_capture(1)
6032 p = capture[0]
6033 try:
6034 ip = p[IP]
6035 tcp = p[TCP]
6036 self.assertEqual(ip.src, self.pg0.remote_ip4)
6037 self.assertEqual(tcp.sport, local_port)
6038 self.assert_packet_checksums_valid(p)
6039 except:
6040 self.logger.error(ppp("Unexpected or invalid packet:", p))
6041 raise
6042
Matus Fabian235a47e2018-06-25 16:42:36 -07006043 def test_output_feature(self):
6044 """ NAT44 interface output feature (in2out postrouting) """
6045 self.vapi.nat44_forwarding_enable_disable(1)
6046 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006047 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6048 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
Matus Fabian235a47e2018-06-25 16:42:36 -07006049
6050 # in2out
6051 pkts = self.create_stream_in(self.pg0, self.pg1)
6052 self.pg0.add_stream(pkts)
6053 self.pg_enable_capture(self.pg_interfaces)
6054 self.pg_start()
6055 capture = self.pg1.get_capture(len(pkts))
6056 self.verify_capture_out(capture)
6057
6058 # out2in
6059 pkts = self.create_stream_out(self.pg1)
6060 self.pg1.add_stream(pkts)
6061 self.pg_enable_capture(self.pg_interfaces)
6062 self.pg_start()
6063 capture = self.pg0.get_capture(len(pkts))
6064 self.verify_capture_in(capture, self.pg0)
6065
Matus Fabian8008d7c2018-07-09 01:34:20 -07006066 def test_multiple_vrf(self):
6067 """ Multiple VRF setup """
6068 external_addr = '1.2.3.4'
6069 external_port = 80
6070 local_port = 8080
6071 port = 0
6072
6073 self.vapi.nat44_forwarding_enable_disable(1)
6074 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006075 flags = self.config_flags.NAT_IS_INSIDE
Matus Fabian8008d7c2018-07-09 01:34:20 -07006076 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6077 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006078 flags=flags)
6079 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
Matus Fabian8008d7c2018-07-09 01:34:20 -07006080 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
6081 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006082 flags=flags)
6083 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
6084 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabian8008d7c2018-07-09 01:34:20 -07006085 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6086 local_port, external_port, vrf_id=1,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006087 proto=IP_PROTOS.tcp, flags=flags)
Matus Fabian8008d7c2018-07-09 01:34:20 -07006088 self.nat44_add_static_mapping(
Filip Vargadd1e3e72019-04-15 18:52:43 +02006089 self.pg0.remote_ip4,
6090 external_sw_if_index=self.pg0.sw_if_index,
6091 local_port=local_port,
6092 vrf_id=0,
6093 external_port=external_port,
6094 proto=IP_PROTOS.tcp,
6095 flags=flags
6096 )
Matus Fabian8008d7c2018-07-09 01:34:20 -07006097
6098 # from client to service (both VRF1)
6099 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6100 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6101 TCP(sport=12345, dport=external_port))
6102 self.pg6.add_stream(p)
6103 self.pg_enable_capture(self.pg_interfaces)
6104 self.pg_start()
6105 capture = self.pg5.get_capture(1)
6106 p = capture[0]
6107 try:
6108 ip = p[IP]
6109 tcp = p[TCP]
6110 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6111 self.assertEqual(tcp.dport, local_port)
6112 self.assert_packet_checksums_valid(p)
6113 except:
6114 self.logger.error(ppp("Unexpected or invalid packet:", p))
6115 raise
6116
6117 # from service back to client (both VRF1)
6118 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6119 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6120 TCP(sport=local_port, dport=12345))
6121 self.pg5.add_stream(p)
6122 self.pg_enable_capture(self.pg_interfaces)
6123 self.pg_start()
6124 capture = self.pg6.get_capture(1)
6125 p = capture[0]
6126 try:
6127 ip = p[IP]
6128 tcp = p[TCP]
6129 self.assertEqual(ip.src, external_addr)
6130 self.assertEqual(tcp.sport, external_port)
6131 self.assert_packet_checksums_valid(p)
6132 except:
6133 self.logger.error(ppp("Unexpected or invalid packet:", p))
6134 raise
6135
6136 # dynamic NAT from VRF1 to VRF0 (output-feature)
6137 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6138 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6139 TCP(sport=2345, dport=22))
6140 self.pg5.add_stream(p)
6141 self.pg_enable_capture(self.pg_interfaces)
6142 self.pg_start()
6143 capture = self.pg1.get_capture(1)
6144 p = capture[0]
6145 try:
6146 ip = p[IP]
6147 tcp = p[TCP]
6148 self.assertEqual(ip.src, self.nat_addr)
6149 self.assertNotEqual(tcp.sport, 2345)
6150 self.assert_packet_checksums_valid(p)
6151 port = tcp.sport
6152 except:
6153 self.logger.error(ppp("Unexpected or invalid packet:", p))
6154 raise
6155
6156 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6157 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6158 TCP(sport=22, dport=port))
6159 self.pg1.add_stream(p)
6160 self.pg_enable_capture(self.pg_interfaces)
6161 self.pg_start()
6162 capture = self.pg5.get_capture(1)
6163 p = capture[0]
6164 try:
6165 ip = p[IP]
6166 tcp = p[TCP]
6167 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6168 self.assertEqual(tcp.dport, 2345)
6169 self.assert_packet_checksums_valid(p)
6170 except:
6171 self.logger.error(ppp("Unexpected or invalid packet:", p))
6172 raise
6173
6174 # from client VRF1 to service VRF0
6175 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6176 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6177 TCP(sport=12346, dport=external_port))
6178 self.pg6.add_stream(p)
6179 self.pg_enable_capture(self.pg_interfaces)
6180 self.pg_start()
6181 capture = self.pg0.get_capture(1)
6182 p = capture[0]
6183 try:
6184 ip = p[IP]
6185 tcp = p[TCP]
6186 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6187 self.assertEqual(tcp.dport, local_port)
6188 self.assert_packet_checksums_valid(p)
6189 except:
6190 self.logger.error(ppp("Unexpected or invalid packet:", p))
6191 raise
6192
6193 # from service VRF0 back to client VRF1
6194 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6195 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6196 TCP(sport=local_port, dport=12346))
6197 self.pg0.add_stream(p)
6198 self.pg_enable_capture(self.pg_interfaces)
6199 self.pg_start()
6200 capture = self.pg6.get_capture(1)
6201 p = capture[0]
6202 try:
6203 ip = p[IP]
6204 tcp = p[TCP]
6205 self.assertEqual(ip.src, self.pg0.local_ip4)
6206 self.assertEqual(tcp.sport, external_port)
6207 self.assert_packet_checksums_valid(p)
6208 except:
6209 self.logger.error(ppp("Unexpected or invalid packet:", p))
6210 raise
6211
6212 # from client VRF0 to service VRF1
6213 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6214 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6215 TCP(sport=12347, dport=external_port))
6216 self.pg0.add_stream(p)
6217 self.pg_enable_capture(self.pg_interfaces)
6218 self.pg_start()
6219 capture = self.pg5.get_capture(1)
6220 p = capture[0]
6221 try:
6222 ip = p[IP]
6223 tcp = p[TCP]
6224 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6225 self.assertEqual(tcp.dport, local_port)
6226 self.assert_packet_checksums_valid(p)
6227 except:
6228 self.logger.error(ppp("Unexpected or invalid packet:", p))
6229 raise
6230
6231 # from service VRF1 back to client VRF0
6232 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6233 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6234 TCP(sport=local_port, dport=12347))
6235 self.pg5.add_stream(p)
6236 self.pg_enable_capture(self.pg_interfaces)
6237 self.pg_start()
6238 capture = self.pg0.get_capture(1)
6239 p = capture[0]
6240 try:
6241 ip = p[IP]
6242 tcp = p[TCP]
6243 self.assertEqual(ip.src, external_addr)
6244 self.assertEqual(tcp.sport, external_port)
6245 self.assert_packet_checksums_valid(p)
6246 except:
6247 self.logger.error(ppp("Unexpected or invalid packet:", p))
6248 raise
6249
6250 # from client to server (both VRF1, no translation)
6251 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6252 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6253 TCP(sport=12348, dport=local_port))
6254 self.pg6.add_stream(p)
6255 self.pg_enable_capture(self.pg_interfaces)
6256 self.pg_start()
6257 capture = self.pg5.get_capture(1)
6258 p = capture[0]
6259 try:
6260 ip = p[IP]
6261 tcp = p[TCP]
6262 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6263 self.assertEqual(tcp.dport, local_port)
6264 self.assert_packet_checksums_valid(p)
6265 except:
6266 self.logger.error(ppp("Unexpected or invalid packet:", p))
6267 raise
6268
6269 # from server back to client (both VRF1, no translation)
6270 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6271 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6272 TCP(sport=local_port, dport=12348))
6273 self.pg5.add_stream(p)
6274 self.pg_enable_capture(self.pg_interfaces)
6275 self.pg_start()
6276 capture = self.pg6.get_capture(1)
6277 p = capture[0]
6278 try:
6279 ip = p[IP]
6280 tcp = p[TCP]
6281 self.assertEqual(ip.src, self.pg5.remote_ip4)
6282 self.assertEqual(tcp.sport, local_port)
6283 self.assert_packet_checksums_valid(p)
6284 except:
6285 self.logger.error(ppp("Unexpected or invalid packet:", p))
6286 raise
6287
6288 # from client VRF1 to server VRF0 (no translation)
6289 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6290 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6291 TCP(sport=local_port, dport=12349))
6292 self.pg0.add_stream(p)
6293 self.pg_enable_capture(self.pg_interfaces)
6294 self.pg_start()
6295 capture = self.pg6.get_capture(1)
6296 p = capture[0]
6297 try:
6298 ip = p[IP]
6299 tcp = p[TCP]
6300 self.assertEqual(ip.src, self.pg0.remote_ip4)
6301 self.assertEqual(tcp.sport, local_port)
6302 self.assert_packet_checksums_valid(p)
6303 except:
6304 self.logger.error(ppp("Unexpected or invalid packet:", p))
6305 raise
6306
6307 # from server VRF0 back to client VRF1 (no translation)
6308 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6309 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6310 TCP(sport=local_port, dport=12349))
6311 self.pg0.add_stream(p)
6312 self.pg_enable_capture(self.pg_interfaces)
6313 self.pg_start()
6314 capture = self.pg6.get_capture(1)
6315 p = capture[0]
6316 try:
6317 ip = p[IP]
6318 tcp = p[TCP]
6319 self.assertEqual(ip.src, self.pg0.remote_ip4)
6320 self.assertEqual(tcp.sport, local_port)
6321 self.assert_packet_checksums_valid(p)
6322 except:
6323 self.logger.error(ppp("Unexpected or invalid packet:", p))
6324 raise
6325
6326 # from client VRF0 to server VRF1 (no translation)
6327 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6328 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6329 TCP(sport=12344, dport=local_port))
6330 self.pg0.add_stream(p)
6331 self.pg_enable_capture(self.pg_interfaces)
6332 self.pg_start()
6333 capture = self.pg5.get_capture(1)
6334 p = capture[0]
6335 try:
6336 ip = p[IP]
6337 tcp = p[TCP]
6338 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6339 self.assertEqual(tcp.dport, local_port)
6340 self.assert_packet_checksums_valid(p)
6341 except:
6342 self.logger.error(ppp("Unexpected or invalid packet:", p))
6343 raise
6344
6345 # from server VRF1 back to client VRF0 (no translation)
6346 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6347 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6348 TCP(sport=local_port, dport=12344))
6349 self.pg5.add_stream(p)
6350 self.pg_enable_capture(self.pg_interfaces)
6351 self.pg_start()
6352 capture = self.pg0.get_capture(1)
6353 p = capture[0]
6354 try:
6355 ip = p[IP]
6356 tcp = p[TCP]
6357 self.assertEqual(ip.src, self.pg5.remote_ip4)
6358 self.assertEqual(tcp.sport, local_port)
6359 self.assert_packet_checksums_valid(p)
6360 except:
6361 self.logger.error(ppp("Unexpected or invalid packet:", p))
6362 raise
6363
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006364 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006365 def test_session_timeout(self):
6366 """ NAT44 session timeouts """
6367 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006368 flags = self.config_flags.NAT_IS_INSIDE
6369 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6370 flags=flags)
6371 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian878c6462018-08-23 00:33:35 -07006372 self.vapi.nat_set_timeouts(icmp=5)
6373
6374 max_sessions = 1000
6375 pkts = []
6376 for i in range(0, max_sessions):
6377 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6378 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6379 IP(src=src, dst=self.pg1.remote_ip4) /
6380 ICMP(id=1025, type='echo-request'))
6381 pkts.append(p)
6382 self.pg0.add_stream(pkts)
6383 self.pg_enable_capture(self.pg_interfaces)
6384 self.pg_start()
6385 self.pg1.get_capture(max_sessions)
6386
6387 sleep(10)
6388
6389 pkts = []
6390 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006391 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6393 IP(src=src, dst=self.pg1.remote_ip4) /
6394 ICMP(id=1026, type='echo-request'))
6395 pkts.append(p)
6396 self.pg0.add_stream(pkts)
6397 self.pg_enable_capture(self.pg_interfaces)
6398 self.pg_start()
6399 self.pg1.get_capture(max_sessions)
6400
6401 nsessions = 0
6402 users = self.vapi.nat44_user_dump()
6403 for user in users:
6404 nsessions = nsessions + user.nsessions
6405 self.assertLess(nsessions, 2 * max_sessions)
6406
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006407 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006408 def test_session_rst_timeout(self):
6409 """ NAT44 session RST timeouts """
6410 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006411 flags = self.config_flags.NAT_IS_INSIDE
6412 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6413 flags=flags)
6414 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian15e8e682018-11-21 04:53:10 -08006415 self.vapi.nat_set_timeouts(tcp_transitory=5)
6416
Matus Fabian15e8e682018-11-21 04:53:10 -08006417 self.initiate_tcp_session(self.pg0, self.pg1)
6418 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6419 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6420 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6421 flags="R"))
6422 self.pg0.add_stream(p)
6423 self.pg_enable_capture(self.pg_interfaces)
6424 self.pg_start()
6425 self.pg1.get_capture(1)
6426
Matus Fabian15e8e682018-11-21 04:53:10 -08006427 sleep(6)
6428
6429 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6430 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6431 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6432 flags="S"))
6433 self.pg0.add_stream(p)
6434 self.pg_enable_capture(self.pg_interfaces)
6435 self.pg_start()
6436 self.pg1.get_capture(1)
6437
6438 nsessions = 0
6439 users = self.vapi.nat44_user_dump()
6440 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006441 self.assertEqual(str(users[0].ip_address),
6442 self.pg0.remote_ip4)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006443 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006444
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006445 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006446 def test_session_limit_per_user(self):
6447 """ Maximum sessions per user limit """
6448 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006449 flags = self.config_flags.NAT_IS_INSIDE
6450 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6451 flags=flags)
6452 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian878c6462018-08-23 00:33:35 -07006453 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6454 src_address=self.pg2.local_ip4n,
6455 path_mtu=512,
6456 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07006457 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006458
6459 # get maximum number of translations per user
6460 nat44_config = self.vapi.nat_show_config()
6461
6462 pkts = []
6463 for port in range(0, nat44_config.max_translations_per_user):
6464 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6465 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6466 UDP(sport=1025 + port, dport=1025 + port))
6467 pkts.append(p)
6468
6469 self.pg0.add_stream(pkts)
6470 self.pg_enable_capture(self.pg_interfaces)
6471 self.pg_start()
6472 capture = self.pg1.get_capture(len(pkts))
6473
Ole Troane1ade682019-03-04 23:55:43 +01006474 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6475 src_port=self.ipfix_src_port)
Matus Fabian878c6462018-08-23 00:33:35 -07006476
6477 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6478 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6479 UDP(sport=3001, dport=3002))
6480 self.pg0.add_stream(p)
6481 self.pg_enable_capture(self.pg_interfaces)
6482 self.pg_start()
6483 capture = self.pg1.assert_nothing_captured()
6484
6485 # verify IPFIX logging
6486 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6487 sleep(1)
6488 capture = self.pg2.get_capture(10)
6489 ipfix = IPFIXDecoder()
6490 # first load template
6491 for p in capture:
6492 self.assertTrue(p.haslayer(IPFIX))
6493 if p.haslayer(Template):
6494 ipfix.add_template(p.getlayer(Template))
6495 # verify events in data set
6496 for p in capture:
6497 if p.haslayer(Data):
6498 data = ipfix.decode_data_set(p.getlayer(Set))
6499 self.verify_ipfix_max_entries_per_user(
6500 data,
6501 nat44_config.max_translations_per_user,
6502 self.pg0.remote_ip4n)
6503
Matus Fabian8fdc0152018-09-24 04:41:28 -07006504 sleep(6)
6505 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6506 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6507 UDP(sport=3001, dport=3002))
6508 self.pg0.add_stream(p)
6509 self.pg_enable_capture(self.pg_interfaces)
6510 self.pg_start()
6511 self.pg1.get_capture(1)
6512
Matus Fabianad1f3e12018-11-28 21:26:34 -08006513 def test_syslog_sess(self):
6514 """ Test syslog session creation and deletion """
6515 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006516 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006517 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006518 flags = self.config_flags.NAT_IS_INSIDE
6519 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6520 flags=flags)
6521 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006522
6523 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6524 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6525 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6526 self.pg0.add_stream(p)
6527 self.pg_enable_capture(self.pg_interfaces)
6528 self.pg_start()
6529 capture = self.pg1.get_capture(1)
6530 self.tcp_port_out = capture[0][TCP].sport
6531 capture = self.pg2.get_capture(1)
6532 self.verify_syslog_sess(capture[0][Raw].load)
6533
6534 self.pg_enable_capture(self.pg_interfaces)
6535 self.pg_start()
6536 self.nat44_add_address(self.nat_addr, is_add=0)
6537 capture = self.pg2.get_capture(1)
6538 self.verify_syslog_sess(capture[0][Raw].load, False)
6539
Matus Fabiande886752016-12-07 03:38:19 -08006540 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006541 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006542 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006543 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006544 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006545
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07006546 def show_commands_at_teardown(self):
6547 self.logger.info(self.vapi.cli("show nat44 addresses"))
6548 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6549 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6550 self.logger.info(self.vapi.cli("show nat44 interface address"))
6551 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6552 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6553 self.logger.info(self.vapi.cli("show nat timeouts"))
6554
Matus Fabianeea28d72017-01-13 04:15:54 -08006555
Juraj Slobodacba69362017-12-19 02:09:32 +01006556class TestNAT44Out2InDPO(MethodHolder):
6557 """ NAT44 Test Cases using out2in DPO """
6558
6559 @classmethod
6560 def setUpConstants(cls):
6561 super(TestNAT44Out2InDPO, cls).setUpConstants()
6562 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6563
6564 @classmethod
6565 def setUpClass(cls):
6566 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006567 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006568
6569 try:
6570 cls.tcp_port_in = 6303
6571 cls.tcp_port_out = 6303
6572 cls.udp_port_in = 6304
6573 cls.udp_port_out = 6304
6574 cls.icmp_id_in = 6305
6575 cls.icmp_id_out = 6305
6576 cls.nat_addr = '10.0.0.3'
Juraj Slobodacba69362017-12-19 02:09:32 +01006577 cls.dst_ip4 = '192.168.70.1'
6578
6579 cls.create_pg_interfaces(range(2))
6580
6581 cls.pg0.admin_up()
6582 cls.pg0.config_ip4()
6583 cls.pg0.resolve_arp()
6584
6585 cls.pg1.admin_up()
6586 cls.pg1.config_ip6()
6587 cls.pg1.resolve_ndp()
6588
Ole Troana5b2eec2019-03-11 19:23:25 +01006589 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
Juraj Slobodacba69362017-12-19 02:09:32 +01006590 dst_address_length=0,
6591 next_hop_address=cls.pg1.remote_ip6n,
Ole Troana5b2eec2019-03-11 19:23:25 +01006592 next_hop_sw_if_index=cls.pg1.sw_if_index,
6593 is_ipv6=True)
Juraj Slobodacba69362017-12-19 02:09:32 +01006594
6595 except Exception:
6596 super(TestNAT44Out2InDPO, cls).tearDownClass()
6597 raise
6598
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006599 @classmethod
6600 def tearDownClass(cls):
6601 super(TestNAT44Out2InDPO, cls).tearDownClass()
6602
Juraj Slobodacba69362017-12-19 02:09:32 +01006603 def configure_xlat(self):
6604 self.dst_ip6_pfx = '1:2:3::'
6605 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6606 self.dst_ip6_pfx)
6607 self.dst_ip6_pfx_len = 96
6608 self.src_ip6_pfx = '4:5:6::'
6609 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6610 self.src_ip6_pfx)
6611 self.src_ip6_pfx_len = 96
6612 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6613 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006614 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006615
Ole Troanffba3c32018-11-22 12:53:00 +01006616 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006617 def test_464xlat_ce(self):
6618 """ Test 464XLAT CE with NAT44 """
6619
Matus Fabian69ce30d2018-08-22 01:27:10 -07006620 nat_config = self.vapi.nat_show_config()
6621 self.assertEqual(1, nat_config.out2in_dpo)
6622
Juraj Slobodacba69362017-12-19 02:09:32 +01006623 self.configure_xlat()
6624
Filip Vargadd1e3e72019-04-15 18:52:43 +02006625 flags = self.config_flags.NAT_IS_INSIDE
6626 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6627 flags=flags)
Juraj Slobodacba69362017-12-19 02:09:32 +01006628 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6629
6630 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6631 self.dst_ip6_pfx_len)
6632 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6633 self.src_ip6_pfx_len)
6634
6635 try:
6636 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6637 self.pg0.add_stream(pkts)
6638 self.pg_enable_capture(self.pg_interfaces)
6639 self.pg_start()
6640 capture = self.pg1.get_capture(len(pkts))
6641 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6642 dst_ip=out_src_ip6)
6643
6644 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6645 out_dst_ip6)
6646 self.pg1.add_stream(pkts)
6647 self.pg_enable_capture(self.pg_interfaces)
6648 self.pg_start()
6649 capture = self.pg0.get_capture(len(pkts))
6650 self.verify_capture_in(capture, self.pg0)
6651 finally:
6652 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006653 is_add=0, flags=flags)
Juraj Slobodacba69362017-12-19 02:09:32 +01006654 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6655 self.nat_addr_n, is_add=0)
6656
Ole Troanffba3c32018-11-22 12:53:00 +01006657 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006658 def test_464xlat_ce_no_nat(self):
6659 """ Test 464XLAT CE without NAT44 """
6660
6661 self.configure_xlat()
6662
6663 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6664 self.dst_ip6_pfx_len)
6665 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6666 self.src_ip6_pfx_len)
6667
6668 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6669 self.pg0.add_stream(pkts)
6670 self.pg_enable_capture(self.pg_interfaces)
6671 self.pg_start()
6672 capture = self.pg1.get_capture(len(pkts))
6673 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6674 nat_ip=out_dst_ip6, same_port=True)
6675
6676 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6677 self.pg1.add_stream(pkts)
6678 self.pg_enable_capture(self.pg_interfaces)
6679 self.pg_start()
6680 capture = self.pg0.get_capture(len(pkts))
6681 self.verify_capture_in(capture, self.pg0)
6682
6683
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006684class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006685 """ Deterministic NAT Test Cases """
6686
6687 @classmethod
6688 def setUpConstants(cls):
6689 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006690 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006691
6692 @classmethod
6693 def setUpClass(cls):
6694 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006695 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006696
6697 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006698 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006699 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006700 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006701 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006702 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006703 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006704
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006705 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006706 cls.interfaces = list(cls.pg_interfaces)
6707
6708 for i in cls.interfaces:
6709 i.admin_up()
6710 i.config_ip4()
6711 i.resolve_arp()
6712
Martin Gálik977c1cb2017-03-30 23:21:51 -07006713 cls.pg0.generate_remote_hosts(2)
6714 cls.pg0.configure_ipv4_neighbors()
6715
Matus Fabian066f0342017-02-10 03:48:01 -08006716 except Exception:
6717 super(TestDeterministicNAT, cls).tearDownClass()
6718 raise
6719
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006720 @classmethod
6721 def tearDownClass(cls):
6722 super(TestDeterministicNAT, cls).tearDownClass()
6723
Martin Gálik977c1cb2017-03-30 23:21:51 -07006724 def create_stream_in(self, in_if, out_if, ttl=64):
6725 """
6726 Create packet stream for inside network
6727
6728 :param in_if: Inside interface
6729 :param out_if: Outside interface
6730 :param ttl: TTL of generated packets
6731 """
6732 pkts = []
6733 # TCP
6734 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6735 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006736 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006737 pkts.append(p)
6738
6739 # UDP
6740 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6741 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006742 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006743 pkts.append(p)
6744
6745 # ICMP
6746 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6747 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6748 ICMP(id=self.icmp_id_in, type='echo-request'))
6749 pkts.append(p)
6750
6751 return pkts
6752
6753 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6754 """
6755 Create packet stream for outside network
6756
6757 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006758 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006759 :param ttl: TTL of generated packets
6760 """
6761 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006762 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006763 pkts = []
6764 # TCP
6765 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6766 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006767 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006768 pkts.append(p)
6769
6770 # UDP
6771 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6772 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006773 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006774 pkts.append(p)
6775
6776 # ICMP
6777 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6778 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6779 ICMP(id=self.icmp_external_id, type='echo-reply'))
6780 pkts.append(p)
6781
6782 return pkts
6783
Matus Fabian05ca4a32018-09-04 23:45:13 -07006784 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006785 """
6786 Verify captured packets on outside network
6787
6788 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006789 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07006790 :param same_port: Source port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006791 """
6792 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006793 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006794 for packet in capture:
6795 try:
6796 self.assertEqual(packet[IP].src, nat_ip)
6797 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006798 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006799 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006800 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006801 else:
6802 self.icmp_external_id = packet[ICMP].id
6803 except:
6804 self.logger.error(ppp("Unexpected or invalid packet "
6805 "(outside network):", packet))
6806 raise
6807
Matus Fabian066f0342017-02-10 03:48:01 -08006808 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006809 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006810 in_addr = '172.16.255.0'
6811 out_addr = '172.17.255.50'
6812 in_addr_t = '172.16.255.20'
Matus Fabian066f0342017-02-10 03:48:01 -08006813 in_plen = 24
6814 out_plen = 32
6815
Matus Fabian2ba92e32017-08-21 07:05:03 -07006816 nat_config = self.vapi.nat_show_config()
6817 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006818
Filip Vargadd1e3e72019-04-15 18:52:43 +02006819 self.vapi.nat_det_add_del_map(1, in_addr, in_plen, out_addr, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006820
Filip Vargadd1e3e72019-04-15 18:52:43 +02006821 rep1 = self.vapi.nat_det_forward(in_addr_t)
6822 self.assertEqual(str(rep1.out_addr), out_addr)
6823 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
6824
6825 self.assertEqual(str(rep2.in_addr), in_addr_t)
Matus Fabian066f0342017-02-10 03:48:01 -08006826
Matus Fabian2ba92e32017-08-21 07:05:03 -07006827 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006828 self.assertEqual(len(deterministic_mappings), 1)
6829 dsm = deterministic_mappings[0]
Filip Vargadd1e3e72019-04-15 18:52:43 +02006830 self.assertEqual(in_addr, str(dsm.in_addr))
Martin17a75cb2017-03-08 05:53:20 -08006831 self.assertEqual(in_plen, dsm.in_plen)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006832 self.assertEqual(out_addr, str(dsm.out_addr))
Martin17a75cb2017-03-08 05:53:20 -08006833 self.assertEqual(out_plen, dsm.out_plen)
6834
Matus Fabian2ba92e32017-08-21 07:05:03 -07006835 self.clear_nat_det()
6836 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006837 self.assertEqual(len(deterministic_mappings), 0)
6838
Matus Fabian6a0946f2017-04-12 03:36:13 -07006839 def test_set_timeouts(self):
6840 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006841 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006842
Matus Fabian878c6462018-08-23 00:33:35 -07006843 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6844 timeouts_before.tcp_established + 10,
6845 timeouts_before.tcp_transitory + 10,
6846 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006847
Matus Fabian878c6462018-08-23 00:33:35 -07006848 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006849
6850 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6851 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6852 self.assertNotEqual(timeouts_before.tcp_established,
6853 timeouts_after.tcp_established)
6854 self.assertNotEqual(timeouts_before.tcp_transitory,
6855 timeouts_after.tcp_transitory)
6856
Martin Gálik977c1cb2017-03-30 23:21:51 -07006857 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006858 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006859
6860 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006861
Filip Vargadd1e3e72019-04-15 18:52:43 +02006862 self.vapi.nat_det_add_del_map(1,
6863 self.pg0.remote_ip4n,
Matus Fabian2ba92e32017-08-21 07:05:03 -07006864 32,
6865 socket.inet_aton(nat_ip),
6866 32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006867
6868 flags = self.config_flags.NAT_IS_INSIDE
6869 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6870 flags=flags)
6871 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006872
6873 # in2out
6874 pkts = self.create_stream_in(self.pg0, self.pg1)
6875 self.pg0.add_stream(pkts)
6876 self.pg_enable_capture(self.pg_interfaces)
6877 self.pg_start()
6878 capture = self.pg1.get_capture(len(pkts))
6879 self.verify_capture_out(capture, nat_ip)
6880
6881 # out2in
6882 pkts = self.create_stream_out(self.pg1, nat_ip)
6883 self.pg1.add_stream(pkts)
6884 self.pg_enable_capture(self.pg_interfaces)
6885 self.pg_start()
6886 capture = self.pg0.get_capture(len(pkts))
6887 self.verify_capture_in(capture, self.pg0)
6888
Martin Gálik9806eae2017-04-25 01:25:08 -07006889 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006890 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006891 self.assertEqual(len(sessions), 3)
6892
6893 # TCP session
6894 s = sessions[0]
Filip Vargadd1e3e72019-04-15 18:52:43 +02006895 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006896 self.assertEqual(s.in_port, self.tcp_port_in)
6897 self.assertEqual(s.out_port, self.tcp_port_out)
6898 self.assertEqual(s.ext_port, self.tcp_external_port)
6899
6900 # UDP session
6901 s = sessions[1]
Filip Vargadd1e3e72019-04-15 18:52:43 +02006902 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006903 self.assertEqual(s.in_port, self.udp_port_in)
6904 self.assertEqual(s.out_port, self.udp_port_out)
6905 self.assertEqual(s.ext_port, self.udp_external_port)
6906
6907 # ICMP session
6908 s = sessions[2]
Filip Vargadd1e3e72019-04-15 18:52:43 +02006909 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006910 self.assertEqual(s.in_port, self.icmp_id_in)
6911 self.assertEqual(s.out_port, self.icmp_external_id)
6912
Martin Gálik977c1cb2017-03-30 23:21:51 -07006913 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006914 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006915
6916 nat_ip = "10.0.0.10"
6917 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006918 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006919
6920 host0 = self.pg0.remote_hosts[0]
6921 host1 = self.pg0.remote_hosts[1]
6922
Filip Vargadd1e3e72019-04-15 18:52:43 +02006923 self.vapi.nat_det_add_del_map(1,
6924 host0.ip4n,
Matus Fabian2ba92e32017-08-21 07:05:03 -07006925 24,
6926 socket.inet_aton(nat_ip),
6927 32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006928 flags = self.config_flags.NAT_IS_INSIDE
6929 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6930 flags=flags)
6931 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006932
6933 # host0 to out
6934 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6935 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006936 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006937 self.pg0.add_stream(p)
6938 self.pg_enable_capture(self.pg_interfaces)
6939 self.pg_start()
6940 capture = self.pg1.get_capture(1)
6941 p = capture[0]
6942 try:
6943 ip = p[IP]
6944 tcp = p[TCP]
6945 self.assertEqual(ip.src, nat_ip)
6946 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006947 self.assertEqual(tcp.dport, external_port)
6948 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006949 except:
6950 self.logger.error(ppp("Unexpected or invalid packet:", p))
6951 raise
6952
6953 # host1 to out
6954 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6955 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006956 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006957 self.pg0.add_stream(p)
6958 self.pg_enable_capture(self.pg_interfaces)
6959 self.pg_start()
6960 capture = self.pg1.get_capture(1)
6961 p = capture[0]
6962 try:
6963 ip = p[IP]
6964 tcp = p[TCP]
6965 self.assertEqual(ip.src, nat_ip)
6966 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006967 self.assertEqual(tcp.dport, external_port)
6968 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006969 except:
6970 self.logger.error(ppp("Unexpected or invalid packet:", p))
6971 raise
6972
Matus Fabian2ba92e32017-08-21 07:05:03 -07006973 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006974 self.assertEqual(1, len(dms))
6975 self.assertEqual(2, dms[0].ses_num)
6976
6977 # out to host0
6978 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6979 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006980 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006981 self.pg1.add_stream(p)
6982 self.pg_enable_capture(self.pg_interfaces)
6983 self.pg_start()
6984 capture = self.pg0.get_capture(1)
6985 p = capture[0]
6986 try:
6987 ip = p[IP]
6988 tcp = p[TCP]
6989 self.assertEqual(ip.src, self.pg1.remote_ip4)
6990 self.assertEqual(ip.dst, host0.ip4)
6991 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006992 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006993 except:
6994 self.logger.error(ppp("Unexpected or invalid packet:", p))
6995 raise
6996
6997 # out to host1
6998 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6999 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007000 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007001 self.pg1.add_stream(p)
7002 self.pg_enable_capture(self.pg_interfaces)
7003 self.pg_start()
7004 capture = self.pg0.get_capture(1)
7005 p = capture[0]
7006 try:
7007 ip = p[IP]
7008 tcp = p[TCP]
7009 self.assertEqual(ip.src, self.pg1.remote_ip4)
7010 self.assertEqual(ip.dst, host1.ip4)
7011 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07007012 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007013 except:
7014 self.logger.error(ppp("Unexpected or invalid packet", p))
7015 raise
7016
Martin Gálik6bc8c642017-04-19 01:12:27 -07007017 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07007018 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7019 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07007020 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07007021 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07007022 dms = self.vapi.nat_det_map_dump()
7023 self.assertEqual(dms[0].ses_num, 1)
7024
7025 self.vapi.nat_det_close_session_in(host0.ip4n,
7026 port_in,
7027 self.pg1.remote_ip4n,
7028 external_port)
7029 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07007030 self.assertEqual(dms[0].ses_num, 0)
7031
Martin Gálik977c1cb2017-03-30 23:21:51 -07007032 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007033 """ Deterministic NAT TCP session close from inside network """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007034 self.vapi.nat_det_add_del_map(1,
7035 self.pg0.remote_ip4n,
Matus Fabian2ba92e32017-08-21 07:05:03 -07007036 32,
7037 socket.inet_aton(self.nat_addr),
7038 32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007039 flags = self.config_flags.NAT_IS_INSIDE
7040 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7041 flags=flags)
7042 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007043
7044 self.initiate_tcp_session(self.pg0, self.pg1)
7045
7046 # close the session from inside
7047 try:
7048 # FIN packet in -> out
7049 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7050 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007051 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007052 flags="F"))
7053 self.pg0.add_stream(p)
7054 self.pg_enable_capture(self.pg_interfaces)
7055 self.pg_start()
7056 self.pg1.get_capture(1)
7057
7058 pkts = []
7059
7060 # ACK packet out -> in
7061 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007062 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007063 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007064 flags="A"))
7065 pkts.append(p)
7066
7067 # FIN packet out -> in
7068 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007069 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007070 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007071 flags="F"))
7072 pkts.append(p)
7073
7074 self.pg1.add_stream(pkts)
7075 self.pg_enable_capture(self.pg_interfaces)
7076 self.pg_start()
7077 self.pg0.get_capture(2)
7078
7079 # ACK packet in -> out
7080 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7081 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007082 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007083 flags="A"))
7084 self.pg0.add_stream(p)
7085 self.pg_enable_capture(self.pg_interfaces)
7086 self.pg_start()
7087 self.pg1.get_capture(1)
7088
Matus Fabian2ba92e32017-08-21 07:05:03 -07007089 # Check if deterministic NAT44 closed the session
7090 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007091 self.assertEqual(0, dms[0].ses_num)
7092 except:
7093 self.logger.error("TCP session termination failed")
7094 raise
7095
7096 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007097 """ Deterministic NAT TCP session close from outside network """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007098 self.vapi.nat_det_add_del_map(1,
7099 self.pg0.remote_ip4n,
Matus Fabian2ba92e32017-08-21 07:05:03 -07007100 32,
7101 socket.inet_aton(self.nat_addr),
7102 32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007103 flags = self.config_flags.NAT_IS_INSIDE
7104 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7105 flags=flags)
7106 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007107
7108 self.initiate_tcp_session(self.pg0, self.pg1)
7109
7110 # close the session from outside
7111 try:
7112 # FIN packet out -> in
7113 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007114 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007115 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007116 flags="F"))
7117 self.pg1.add_stream(p)
7118 self.pg_enable_capture(self.pg_interfaces)
7119 self.pg_start()
7120 self.pg0.get_capture(1)
7121
7122 pkts = []
7123
7124 # ACK packet in -> out
7125 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7126 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007127 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007128 flags="A"))
7129 pkts.append(p)
7130
7131 # ACK packet in -> out
7132 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7133 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007134 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007135 flags="F"))
7136 pkts.append(p)
7137
7138 self.pg0.add_stream(pkts)
7139 self.pg_enable_capture(self.pg_interfaces)
7140 self.pg_start()
7141 self.pg1.get_capture(2)
7142
7143 # ACK packet out -> in
7144 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007145 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007146 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007147 flags="A"))
7148 self.pg1.add_stream(p)
7149 self.pg_enable_capture(self.pg_interfaces)
7150 self.pg_start()
7151 self.pg0.get_capture(1)
7152
Matus Fabian2ba92e32017-08-21 07:05:03 -07007153 # Check if deterministic NAT44 closed the session
7154 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007155 self.assertEqual(0, dms[0].ses_num)
7156 except:
7157 self.logger.error("TCP session termination failed")
7158 raise
7159
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007160 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007161 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007162 """ Deterministic NAT session timeouts """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007163 self.vapi.nat_det_add_del_map(1,
7164 self.pg0.remote_ip4n,
Matus Fabian2ba92e32017-08-21 07:05:03 -07007165 32,
7166 socket.inet_aton(self.nat_addr),
7167 32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007168 flags = self.config_flags.NAT_IS_INSIDE
7169 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7170 flags=flags)
7171 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007172
7173 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07007174 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007175 pkts = self.create_stream_in(self.pg0, self.pg1)
7176 self.pg0.add_stream(pkts)
7177 self.pg_enable_capture(self.pg_interfaces)
7178 self.pg_start()
7179 capture = self.pg1.get_capture(len(pkts))
7180 sleep(15)
7181
Matus Fabian2ba92e32017-08-21 07:05:03 -07007182 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007183 self.assertEqual(0, dms[0].ses_num)
7184
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007185 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007186 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007187 """ Deterministic NAT maximum sessions per user limit """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007188 self.vapi.nat_det_add_del_map(1,
7189 self.pg0.remote_ip4n,
Matus Fabian2ba92e32017-08-21 07:05:03 -07007190 32,
7191 socket.inet_aton(self.nat_addr),
7192 32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007193 flags = self.config_flags.NAT_IS_INSIDE
7194 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7195 flags=flags)
7196 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007197 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7198 src_address=self.pg2.local_ip4n,
7199 path_mtu=512,
7200 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01007201 self.vapi.nat_ipfix_enable_disable()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007202
7203 pkts = []
7204 for port in range(1025, 2025):
7205 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7206 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7207 UDP(sport=port, dport=port))
7208 pkts.append(p)
7209
7210 self.pg0.add_stream(pkts)
7211 self.pg_enable_capture(self.pg_interfaces)
7212 self.pg_start()
7213 capture = self.pg1.get_capture(len(pkts))
7214
7215 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7216 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007217 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007218 self.pg0.add_stream(p)
7219 self.pg_enable_capture(self.pg_interfaces)
7220 self.pg_start()
7221 capture = self.pg1.assert_nothing_captured()
7222
Martin Gálikf7e655d2017-04-27 02:13:26 -07007223 # verify ICMP error packet
7224 capture = self.pg0.get_capture(1)
7225 p = capture[0]
7226 self.assertTrue(p.haslayer(ICMP))
7227 icmp = p[ICMP]
7228 self.assertEqual(icmp.type, 3)
7229 self.assertEqual(icmp.code, 1)
7230 self.assertTrue(icmp.haslayer(IPerror))
7231 inner_ip = icmp[IPerror]
7232 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7233 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7234
Matus Fabian2ba92e32017-08-21 07:05:03 -07007235 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007236
7237 self.assertEqual(1000, dms[0].ses_num)
7238
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007239 # verify IPFIX logging
7240 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007241 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007242 capture = self.pg2.get_capture(2)
7243 ipfix = IPFIXDecoder()
7244 # first load template
7245 for p in capture:
7246 self.assertTrue(p.haslayer(IPFIX))
7247 if p.haslayer(Template):
7248 ipfix.add_template(p.getlayer(Template))
7249 # verify events in data set
7250 for p in capture:
7251 if p.haslayer(Data):
7252 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007253 self.verify_ipfix_max_entries_per_user(data,
7254 1000,
7255 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007256
Matus Fabian2ba92e32017-08-21 07:05:03 -07007257 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007258 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007259 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007260 """
Ole Troane1ade682019-03-04 23:55:43 +01007261 self.vapi.nat_ipfix_enable_disable(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007262 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007263 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007264 for dsm in deterministic_mappings:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007265 self.vapi.nat_det_add_del_map(0,
7266 dsm.in_addr,
Matus Fabian2ba92e32017-08-21 07:05:03 -07007267 dsm.in_plen,
7268 dsm.out_addr,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007269 dsm.out_plen)
Martin17a75cb2017-03-08 05:53:20 -08007270
Matus Fabian2ba92e32017-08-21 07:05:03 -07007271 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007272 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007273 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007274 is_add=0,
7275 flags=intf.flags)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007276
Matus Fabian066f0342017-02-10 03:48:01 -08007277 def tearDown(self):
7278 super(TestDeterministicNAT, self).tearDown()
7279 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007280 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007281
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07007282 def show_commands_at_teardown(self):
7283 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7284 self.logger.info(self.vapi.cli("show nat timeouts"))
7285 self.logger.info(
7286 self.vapi.cli("show nat44 deterministic mappings"))
7287 self.logger.info(
7288 self.vapi.cli("show nat44 deterministic sessions"))
7289
Matus Fabian06596c52017-06-06 04:53:28 -07007290
7291class TestNAT64(MethodHolder):
7292 """ NAT64 Test Cases """
7293
7294 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007295 def setUpConstants(cls):
7296 super(TestNAT64, cls).setUpConstants()
7297 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7298 "nat64 st hash buckets 256", "}"])
7299
7300 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007301 def setUpClass(cls):
7302 super(TestNAT64, cls).setUpClass()
7303
7304 try:
7305 cls.tcp_port_in = 6303
7306 cls.tcp_port_out = 6303
7307 cls.udp_port_in = 6304
7308 cls.udp_port_out = 6304
7309 cls.icmp_id_in = 6305
7310 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007311 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007312 cls.nat_addr = '10.0.0.3'
7313 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007314 cls.vrf1_id = 10
7315 cls.vrf1_nat_addr = '10.0.10.3'
Matus Fabiana431ad12018-01-04 04:03:14 -08007316 cls.ipfix_src_port = 4739
7317 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007318
Juraj Slobodac746a152018-07-09 02:36:37 +02007319 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007320 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007321 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007322 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7323
Ole Troan9a475372019-03-05 16:58:24 +01007324 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7325 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007326
Matus Fabian029f3d22017-06-15 02:28:50 -07007327 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7328
7329 cls.pg0.generate_remote_hosts(2)
7330
Matus Fabian06596c52017-06-06 04:53:28 -07007331 for i in cls.ip6_interfaces:
7332 i.admin_up()
7333 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007334 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007335
7336 for i in cls.ip4_interfaces:
7337 i.admin_up()
7338 i.config_ip4()
7339 i.resolve_arp()
7340
Matus Fabian36ea2d62017-10-24 04:13:49 -07007341 cls.pg3.admin_up()
7342 cls.pg3.config_ip4()
7343 cls.pg3.resolve_arp()
7344 cls.pg3.config_ip6()
7345 cls.pg3.configure_ipv6_neighbors()
7346
Juraj Slobodac746a152018-07-09 02:36:37 +02007347 cls.pg5.admin_up()
7348 cls.pg5.config_ip6()
7349
Matus Fabian06596c52017-06-06 04:53:28 -07007350 except Exception:
7351 super(TestNAT64, cls).tearDownClass()
7352 raise
7353
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007354 @classmethod
7355 def tearDownClass(cls):
7356 super(TestNAT64, cls).tearDownClass()
7357
Juraj Slobodac746a152018-07-09 02:36:37 +02007358 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7359 """ NAT64 inside interface handles Neighbor Advertisement """
7360
Filip Vargadd1e3e72019-04-15 18:52:43 +02007361 flags = self.config_flags.NAT_IS_INSIDE
7362 self.vapi.nat64_add_del_interface(1, flags, self.pg5.sw_if_index)
Juraj Slobodac746a152018-07-09 02:36:37 +02007363
7364 # Try to send ping
7365 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7366 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7367 ICMPv6EchoRequest())
7368 pkts = [ping]
7369 self.pg5.add_stream(pkts)
7370 self.pg_enable_capture(self.pg_interfaces)
7371 self.pg_start()
7372
7373 # Wait for Neighbor Solicitation
7374 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007375 packet = capture[0]
7376 try:
7377 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007378 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007379 tgt = packet[ICMPv6ND_NS].tgt
7380 except:
7381 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7382 raise
7383
7384 # Send Neighbor Advertisement
7385 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7386 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7387 ICMPv6ND_NA(tgt=tgt) /
7388 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7389 pkts = [p]
7390 self.pg5.add_stream(pkts)
7391 self.pg_enable_capture(self.pg_interfaces)
7392 self.pg_start()
7393
7394 # Try to send ping again
7395 pkts = [ping]
7396 self.pg5.add_stream(pkts)
7397 self.pg_enable_capture(self.pg_interfaces)
7398 self.pg_start()
7399
7400 # Wait for ping reply
7401 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007402 packet = capture[0]
7403 try:
7404 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7405 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007406 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007407 except:
7408 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7409 raise
7410
Matus Fabian06596c52017-06-06 04:53:28 -07007411 def test_pool(self):
7412 """ Add/delete address to NAT64 pool """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007413 nat_addr = '1.2.3.4'
Matus Fabian06596c52017-06-06 04:53:28 -07007414
7415 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7416
7417 addresses = self.vapi.nat64_pool_addr_dump()
7418 self.assertEqual(len(addresses), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007419 self.assertEqual(str(addresses[0].address), nat_addr)
Matus Fabian06596c52017-06-06 04:53:28 -07007420
7421 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7422
7423 addresses = self.vapi.nat64_pool_addr_dump()
7424 self.assertEqual(len(addresses), 0)
7425
7426 def test_interface(self):
7427 """ Enable/disable NAT64 feature on the interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007428 flags = self.config_flags.NAT_IS_INSIDE
7429 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7430 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007431
7432 interfaces = self.vapi.nat64_interface_dump()
7433 self.assertEqual(len(interfaces), 2)
7434 pg0_found = False
7435 pg1_found = False
7436 for intf in interfaces:
7437 if intf.sw_if_index == self.pg0.sw_if_index:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007438 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
Matus Fabian06596c52017-06-06 04:53:28 -07007439 pg0_found = True
7440 elif intf.sw_if_index == self.pg1.sw_if_index:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007441 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
Matus Fabian06596c52017-06-06 04:53:28 -07007442 pg1_found = True
7443 self.assertTrue(pg0_found)
7444 self.assertTrue(pg1_found)
7445
7446 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007447 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007448 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007449 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007450
Filip Vargadd1e3e72019-04-15 18:52:43 +02007451 self.vapi.nat64_add_del_interface(0, flags, self.pg0.sw_if_index)
7452 self.vapi.nat64_add_del_interface(0, flags, self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007453
7454 interfaces = self.vapi.nat64_interface_dump()
7455 self.assertEqual(len(interfaces), 0)
7456
7457 def test_static_bib(self):
7458 """ Add/delete static BIB entry """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007459 in_addr = '2001:db8:85a3::8a2e:370:7334'
7460 out_addr = '10.1.1.3'
Matus Fabian06596c52017-06-06 04:53:28 -07007461 in_port = 1234
7462 out_port = 5678
7463 proto = IP_PROTOS.tcp
7464
7465 self.vapi.nat64_add_del_static_bib(in_addr,
7466 out_addr,
7467 in_port,
7468 out_port,
7469 proto)
7470 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7471 static_bib_num = 0
7472 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007473 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07007474 static_bib_num += 1
Filip Vargadd1e3e72019-04-15 18:52:43 +02007475 self.assertEqual(str(bibe.i_addr), in_addr)
7476 self.assertEqual(str(bibe.o_addr), out_addr)
Matus Fabian06596c52017-06-06 04:53:28 -07007477 self.assertEqual(bibe.i_port, in_port)
7478 self.assertEqual(bibe.o_port, out_port)
7479 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007480 bibs = self.statistics.get_counter('/nat64/total-bibs')
7481 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007482
7483 self.vapi.nat64_add_del_static_bib(in_addr,
7484 out_addr,
7485 in_port,
7486 out_port,
7487 proto,
7488 is_add=0)
7489 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7490 static_bib_num = 0
7491 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007492 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07007493 static_bib_num += 1
7494 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007495 bibs = self.statistics.get_counter('/nat64/total-bibs')
7496 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007497
7498 def test_set_timeouts(self):
7499 """ Set NAT64 timeouts """
7500 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007501 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007502 self.assertEqual(timeouts.udp, 300)
7503 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007504 self.assertEqual(timeouts.tcp_transitory, 240)
7505 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007506
7507 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07007508 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7509 tcp_established=7450)
7510 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007511 self.assertEqual(timeouts.udp, 200)
7512 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007513 self.assertEqual(timeouts.tcp_transitory, 250)
7514 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007515
7516 def test_dynamic(self):
7517 """ NAT64 dynamic translation test """
7518 self.tcp_port_in = 6303
7519 self.udp_port_in = 6304
7520 self.icmp_id_in = 6305
7521
7522 ses_num_start = self.nat64_get_ses_num()
7523
Filip Vargadd1e3e72019-04-15 18:52:43 +02007524 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7525 self.nat_addr)
7526 flags = self.config_flags.NAT_IS_INSIDE
7527 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7528 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007529
7530 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007531 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7532 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7533 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7534 totaln = self.statistics.get_counter(
7535 '/err/nat64-in2out/good in2out packets processed')
7536
Matus Fabian06596c52017-06-06 04:53:28 -07007537 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7538 self.pg0.add_stream(pkts)
7539 self.pg_enable_capture(self.pg_interfaces)
7540 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007541 capture = self.pg1.get_capture(len(pkts))
7542 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007543 dst_ip=self.pg1.remote_ip4)
7544
Matus Fabiana5e73762018-12-14 01:55:16 -08007545 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7546 self.assertEqual(err - tcpn, 1)
7547 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7548 self.assertEqual(err - udpn, 1)
7549 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7550 self.assertEqual(err - icmpn, 1)
7551 err = self.statistics.get_counter(
7552 '/err/nat64-in2out/good in2out packets processed')
7553 self.assertEqual(err - totaln, 3)
7554
Matus Fabian06596c52017-06-06 04:53:28 -07007555 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007556 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7557 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7558 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7559 totaln = self.statistics.get_counter(
7560 '/err/nat64-out2in/good out2in packets processed')
7561
Matus Fabian06596c52017-06-06 04:53:28 -07007562 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7563 self.pg1.add_stream(pkts)
7564 self.pg_enable_capture(self.pg_interfaces)
7565 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007566 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007567 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7568 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7569
Matus Fabiana5e73762018-12-14 01:55:16 -08007570 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7571 self.assertEqual(err - tcpn, 1)
7572 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7573 self.assertEqual(err - udpn, 1)
7574 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7575 self.assertEqual(err - icmpn, 1)
7576 err = self.statistics.get_counter(
7577 '/err/nat64-out2in/good out2in packets processed')
7578 self.assertEqual(err - totaln, 3)
7579
Matus Fabianfd0d5082018-12-18 01:08:51 -08007580 bibs = self.statistics.get_counter('/nat64/total-bibs')
7581 self.assertEqual(bibs[0][0], 3)
7582 sessions = self.statistics.get_counter('/nat64/total-sessions')
7583 self.assertEqual(sessions[0][0], 3)
7584
Matus Fabian06596c52017-06-06 04:53:28 -07007585 # in2out
7586 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7587 self.pg0.add_stream(pkts)
7588 self.pg_enable_capture(self.pg_interfaces)
7589 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007590 capture = self.pg1.get_capture(len(pkts))
7591 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007592 dst_ip=self.pg1.remote_ip4)
7593
7594 # out2in
7595 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7596 self.pg1.add_stream(pkts)
7597 self.pg_enable_capture(self.pg_interfaces)
7598 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007599 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007600 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7601
7602 ses_num_end = self.nat64_get_ses_num()
7603
7604 self.assertEqual(ses_num_end - ses_num_start, 3)
7605
Matus Fabian029f3d22017-06-15 02:28:50 -07007606 # tenant with specific VRF
Filip Vargadd1e3e72019-04-15 18:52:43 +02007607 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr,
7608 self.vrf1_nat_addr,
Matus Fabian029f3d22017-06-15 02:28:50 -07007609 vrf_id=self.vrf1_id)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007610 flags = self.config_flags.NAT_IS_INSIDE
7611 self.vapi.nat64_add_del_interface(1, flags, self.pg2.sw_if_index)
Matus Fabian029f3d22017-06-15 02:28:50 -07007612
7613 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7614 self.pg2.add_stream(pkts)
7615 self.pg_enable_capture(self.pg_interfaces)
7616 self.pg_start()
7617 capture = self.pg1.get_capture(len(pkts))
7618 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7619 dst_ip=self.pg1.remote_ip4)
7620
7621 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7622 self.pg1.add_stream(pkts)
7623 self.pg_enable_capture(self.pg_interfaces)
7624 self.pg_start()
7625 capture = self.pg2.get_capture(len(pkts))
7626 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7627
Matus Fabian06596c52017-06-06 04:53:28 -07007628 def test_static(self):
7629 """ NAT64 static translation test """
7630 self.tcp_port_in = 60303
7631 self.udp_port_in = 60304
7632 self.icmp_id_in = 60305
7633 self.tcp_port_out = 60303
7634 self.udp_port_out = 60304
7635 self.icmp_id_out = 60305
7636
7637 ses_num_start = self.nat64_get_ses_num()
7638
Filip Vargadd1e3e72019-04-15 18:52:43 +02007639 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7640 self.nat_addr)
7641 flags = self.config_flags.NAT_IS_INSIDE
7642 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7643 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007644
7645 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007646 self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007647 self.tcp_port_in,
7648 self.tcp_port_out,
7649 IP_PROTOS.tcp)
7650 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007651 self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007652 self.udp_port_in,
7653 self.udp_port_out,
7654 IP_PROTOS.udp)
7655 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007656 self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007657 self.icmp_id_in,
7658 self.icmp_id_out,
7659 IP_PROTOS.icmp)
7660
7661 # in2out
7662 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7663 self.pg0.add_stream(pkts)
7664 self.pg_enable_capture(self.pg_interfaces)
7665 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007666 capture = self.pg1.get_capture(len(pkts))
7667 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007668 dst_ip=self.pg1.remote_ip4, same_port=True)
7669
7670 # out2in
7671 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7672 self.pg1.add_stream(pkts)
7673 self.pg_enable_capture(self.pg_interfaces)
7674 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007675 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007676 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7677 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7678
7679 ses_num_end = self.nat64_get_ses_num()
7680
7681 self.assertEqual(ses_num_end - ses_num_start, 3)
7682
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007683 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07007684 def test_session_timeout(self):
7685 """ NAT64 session timeout """
7686 self.icmp_id_in = 1234
Filip Vargadd1e3e72019-04-15 18:52:43 +02007687 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7688 self.nat_addr)
7689 flags = self.config_flags.NAT_IS_INSIDE
7690 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7691 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian878c6462018-08-23 00:33:35 -07007692 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07007693
7694 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7695 self.pg0.add_stream(pkts)
7696 self.pg_enable_capture(self.pg_interfaces)
7697 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007698 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007699
7700 ses_num_before_timeout = self.nat64_get_ses_num()
7701
7702 sleep(15)
7703
Matus Fabian8fed4242018-08-14 05:14:55 -07007704 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07007705 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07007706 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07007707
Matus Fabian732036d2017-06-08 05:24:28 -07007708 def test_icmp_error(self):
7709 """ NAT64 ICMP Error message translation """
7710 self.tcp_port_in = 6303
7711 self.udp_port_in = 6304
7712 self.icmp_id_in = 6305
7713
Filip Vargadd1e3e72019-04-15 18:52:43 +02007714 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7715 self.nat_addr)
7716 flags = self.config_flags.NAT_IS_INSIDE
7717 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7718 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian732036d2017-06-08 05:24:28 -07007719
7720 # send some packets to create sessions
7721 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7722 self.pg0.add_stream(pkts)
7723 self.pg_enable_capture(self.pg_interfaces)
7724 self.pg_start()
7725 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07007726 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07007727 nat_ip=self.nat_addr,
7728 dst_ip=self.pg1.remote_ip4)
7729
7730 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7731 self.pg1.add_stream(pkts)
7732 self.pg_enable_capture(self.pg_interfaces)
7733 self.pg_start()
7734 capture_ip6 = self.pg0.get_capture(len(pkts))
7735 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7736 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7737 self.pg0.remote_ip6)
7738
7739 # in2out
7740 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7741 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7742 ICMPv6DestUnreach(code=1) /
7743 packet[IPv6] for packet in capture_ip6]
7744 self.pg0.add_stream(pkts)
7745 self.pg_enable_capture(self.pg_interfaces)
7746 self.pg_start()
7747 capture = self.pg1.get_capture(len(pkts))
7748 for packet in capture:
7749 try:
7750 self.assertEqual(packet[IP].src, self.nat_addr)
7751 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7752 self.assertEqual(packet[ICMP].type, 3)
7753 self.assertEqual(packet[ICMP].code, 13)
7754 inner = packet[IPerror]
7755 self.assertEqual(inner.src, self.pg1.remote_ip4)
7756 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007757 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007758 if inner.haslayer(TCPerror):
7759 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7760 elif inner.haslayer(UDPerror):
7761 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7762 else:
7763 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7764 except:
7765 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7766 raise
7767
7768 # out2in
7769 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7770 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7771 ICMP(type=3, code=13) /
7772 packet[IP] for packet in capture_ip4]
7773 self.pg1.add_stream(pkts)
7774 self.pg_enable_capture(self.pg_interfaces)
7775 self.pg_start()
7776 capture = self.pg0.get_capture(len(pkts))
7777 for packet in capture:
7778 try:
7779 self.assertEqual(packet[IPv6].src, ip.src)
7780 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7781 icmp = packet[ICMPv6DestUnreach]
7782 self.assertEqual(icmp.code, 1)
7783 inner = icmp[IPerror6]
7784 self.assertEqual(inner.src, self.pg0.remote_ip6)
7785 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007786 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007787 if inner.haslayer(TCPerror):
7788 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7789 elif inner.haslayer(UDPerror):
7790 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7791 else:
7792 self.assertEqual(inner[ICMPv6EchoRequest].id,
7793 self.icmp_id_in)
7794 except:
7795 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7796 raise
7797
Matus Fabian029f3d22017-06-15 02:28:50 -07007798 def test_hairpinning(self):
7799 """ NAT64 hairpinning """
7800
7801 client = self.pg0.remote_hosts[0]
7802 server = self.pg0.remote_hosts[1]
7803 server_tcp_in_port = 22
7804 server_tcp_out_port = 4022
7805 server_udp_in_port = 23
7806 server_udp_out_port = 4023
7807 client_tcp_in_port = 1234
7808 client_udp_in_port = 1235
7809 client_tcp_out_port = 0
7810 client_udp_out_port = 0
7811 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7812 nat_addr_ip6 = ip.src
7813
Filip Vargadd1e3e72019-04-15 18:52:43 +02007814 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7815 self.nat_addr)
7816 flags = self.config_flags.NAT_IS_INSIDE
7817 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7818 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian029f3d22017-06-15 02:28:50 -07007819
7820 self.vapi.nat64_add_del_static_bib(server.ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007821 self.nat_addr,
Matus Fabian029f3d22017-06-15 02:28:50 -07007822 server_tcp_in_port,
7823 server_tcp_out_port,
7824 IP_PROTOS.tcp)
7825 self.vapi.nat64_add_del_static_bib(server.ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02007826 self.nat_addr,
Matus Fabian029f3d22017-06-15 02:28:50 -07007827 server_udp_in_port,
7828 server_udp_out_port,
7829 IP_PROTOS.udp)
7830
7831 # client to server
7832 pkts = []
7833 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7834 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7835 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7836 pkts.append(p)
7837 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7838 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7839 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7840 pkts.append(p)
7841 self.pg0.add_stream(pkts)
7842 self.pg_enable_capture(self.pg_interfaces)
7843 self.pg_start()
7844 capture = self.pg0.get_capture(len(pkts))
7845 for packet in capture:
7846 try:
7847 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7848 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007849 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007850 if packet.haslayer(TCP):
7851 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7852 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007853 client_tcp_out_port = packet[TCP].sport
7854 else:
7855 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7856 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007857 client_udp_out_port = packet[UDP].sport
7858 except:
7859 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7860 raise
7861
7862 # server to client
7863 pkts = []
7864 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7865 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7866 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7867 pkts.append(p)
7868 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7869 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7870 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7871 pkts.append(p)
7872 self.pg0.add_stream(pkts)
7873 self.pg_enable_capture(self.pg_interfaces)
7874 self.pg_start()
7875 capture = self.pg0.get_capture(len(pkts))
7876 for packet in capture:
7877 try:
7878 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7879 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007880 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007881 if packet.haslayer(TCP):
7882 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7883 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007884 else:
7885 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7886 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007887 except:
7888 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7889 raise
7890
7891 # ICMP error
7892 pkts = []
7893 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7894 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7895 ICMPv6DestUnreach(code=1) /
7896 packet[IPv6] for packet in capture]
7897 self.pg0.add_stream(pkts)
7898 self.pg_enable_capture(self.pg_interfaces)
7899 self.pg_start()
7900 capture = self.pg0.get_capture(len(pkts))
7901 for packet in capture:
7902 try:
7903 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7904 self.assertEqual(packet[IPv6].dst, server.ip6)
7905 icmp = packet[ICMPv6DestUnreach]
7906 self.assertEqual(icmp.code, 1)
7907 inner = icmp[IPerror6]
7908 self.assertEqual(inner.src, server.ip6)
7909 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007910 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007911 if inner.haslayer(TCPerror):
7912 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7913 self.assertEqual(inner[TCPerror].dport,
7914 client_tcp_out_port)
7915 else:
7916 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7917 self.assertEqual(inner[UDPerror].dport,
7918 client_udp_out_port)
7919 except:
7920 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7921 raise
7922
Matus Fabian428dc912017-06-21 06:15:18 -07007923 def test_prefix(self):
7924 """ NAT64 Network-Specific Prefix """
7925
Filip Vargadd1e3e72019-04-15 18:52:43 +02007926 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7927 self.nat_addr)
7928 flags = self.config_flags.NAT_IS_INSIDE
7929 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7930 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7931 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr,
7932 self.vrf1_nat_addr,
Matus Fabian428dc912017-06-21 06:15:18 -07007933 vrf_id=self.vrf1_id)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007934 self.vapi.nat64_add_del_interface(1, flags, self.pg2.sw_if_index)
Matus Fabian428dc912017-06-21 06:15:18 -07007935
7936 # Add global prefix
7937 global_pref64 = "2001:db8::"
Matus Fabian428dc912017-06-21 06:15:18 -07007938 global_pref64_len = 32
Filip Vargadd1e3e72019-04-15 18:52:43 +02007939 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
7940 self.vapi.nat64_add_del_prefix(global_pref64_str)
Matus Fabian428dc912017-06-21 06:15:18 -07007941
7942 prefix = self.vapi.nat64_prefix_dump()
7943 self.assertEqual(len(prefix), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007944 self.assertEqual(prefix[0].prefix,
7945 IPv6Network(unicode(global_pref64_str)))
Matus Fabian428dc912017-06-21 06:15:18 -07007946 self.assertEqual(prefix[0].vrf_id, 0)
7947
7948 # Add tenant specific prefix
7949 vrf1_pref64 = "2001:db8:122:300::"
Matus Fabian428dc912017-06-21 06:15:18 -07007950 vrf1_pref64_len = 56
Filip Vargadd1e3e72019-04-15 18:52:43 +02007951 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
7952 self.vapi.nat64_add_del_prefix(vrf1_pref64_str, vrf_id=self.vrf1_id)
7953
Matus Fabian428dc912017-06-21 06:15:18 -07007954 prefix = self.vapi.nat64_prefix_dump()
7955 self.assertEqual(len(prefix), 2)
7956
7957 # Global prefix
7958 pkts = self.create_stream_in_ip6(self.pg0,
7959 self.pg1,
7960 pref=global_pref64,
7961 plen=global_pref64_len)
7962 self.pg0.add_stream(pkts)
7963 self.pg_enable_capture(self.pg_interfaces)
7964 self.pg_start()
7965 capture = self.pg1.get_capture(len(pkts))
7966 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7967 dst_ip=self.pg1.remote_ip4)
7968
7969 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7970 self.pg1.add_stream(pkts)
7971 self.pg_enable_capture(self.pg_interfaces)
7972 self.pg_start()
7973 capture = self.pg0.get_capture(len(pkts))
7974 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7975 global_pref64,
7976 global_pref64_len)
7977 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7978
7979 # Tenant specific prefix
7980 pkts = self.create_stream_in_ip6(self.pg2,
7981 self.pg1,
7982 pref=vrf1_pref64,
7983 plen=vrf1_pref64_len)
7984 self.pg2.add_stream(pkts)
7985 self.pg_enable_capture(self.pg_interfaces)
7986 self.pg_start()
7987 capture = self.pg1.get_capture(len(pkts))
7988 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7989 dst_ip=self.pg1.remote_ip4)
7990
7991 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7992 self.pg1.add_stream(pkts)
7993 self.pg_enable_capture(self.pg_interfaces)
7994 self.pg_start()
7995 capture = self.pg2.get_capture(len(pkts))
7996 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7997 vrf1_pref64,
7998 vrf1_pref64_len)
7999 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8000
Matus Fabianf8cd5812017-07-11 03:55:02 -07008001 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07008002 """ NAT64 translate packet with unknown protocol """
8003
Filip Vargadd1e3e72019-04-15 18:52:43 +02008004 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8005 self.nat_addr)
8006 flags = self.config_flags.NAT_IS_INSIDE
8007 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8008 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008009 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8010
8011 # in2out
8012 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8013 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8014 TCP(sport=self.tcp_port_in, dport=20))
8015 self.pg0.add_stream(p)
8016 self.pg_enable_capture(self.pg_interfaces)
8017 self.pg_start()
8018 p = self.pg1.get_capture(1)
8019
8020 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008021 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008022 GRE() /
8023 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8024 TCP(sport=1234, dport=1234))
8025 self.pg0.add_stream(p)
8026 self.pg_enable_capture(self.pg_interfaces)
8027 self.pg_start()
8028 p = self.pg1.get_capture(1)
8029 packet = p[0]
8030 try:
8031 self.assertEqual(packet[IP].src, self.nat_addr)
8032 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08008033 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02008034 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008035 except:
8036 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8037 raise
8038
8039 # out2in
8040 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8041 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8042 GRE() /
8043 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8044 TCP(sport=1234, dport=1234))
8045 self.pg1.add_stream(p)
8046 self.pg_enable_capture(self.pg_interfaces)
8047 self.pg_start()
8048 p = self.pg0.get_capture(1)
8049 packet = p[0]
8050 try:
8051 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008052 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8053 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008054 except:
8055 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8056 raise
8057
Matus Fabianf8cd5812017-07-11 03:55:02 -07008058 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07008059 """ NAT64 translate packet with unknown protocol - hairpinning """
8060
8061 client = self.pg0.remote_hosts[0]
8062 server = self.pg0.remote_hosts[1]
8063 server_tcp_in_port = 22
8064 server_tcp_out_port = 4022
8065 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07008066 client_tcp_out_port = 1235
8067 server_nat_ip = "10.0.0.100"
8068 client_nat_ip = "10.0.0.110"
Matus Fabianf8cd5812017-07-11 03:55:02 -07008069 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8070 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008071
Filip Vargadd1e3e72019-04-15 18:52:43 +02008072 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip,
8073 client_nat_ip)
8074 flags = self.config_flags.NAT_IS_INSIDE
8075 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8076 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008077
8078 self.vapi.nat64_add_del_static_bib(server.ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02008079 server_nat_ip,
Matus Fabian7968e6c2017-07-06 05:37:49 -07008080 server_tcp_in_port,
8081 server_tcp_out_port,
8082 IP_PROTOS.tcp)
8083
Matus Fabianf8cd5812017-07-11 03:55:02 -07008084 self.vapi.nat64_add_del_static_bib(server.ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02008085 server_nat_ip,
Matus Fabianf8cd5812017-07-11 03:55:02 -07008086 0,
8087 0,
8088 IP_PROTOS.gre)
8089
8090 self.vapi.nat64_add_del_static_bib(client.ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02008091 client_nat_ip,
Matus Fabianf8cd5812017-07-11 03:55:02 -07008092 client_tcp_in_port,
8093 client_tcp_out_port,
8094 IP_PROTOS.tcp)
8095
Matus Fabian7968e6c2017-07-06 05:37:49 -07008096 # client to server
8097 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008098 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008099 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8100 self.pg0.add_stream(p)
8101 self.pg_enable_capture(self.pg_interfaces)
8102 self.pg_start()
8103 p = self.pg0.get_capture(1)
8104
8105 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008106 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008107 GRE() /
8108 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8109 TCP(sport=1234, dport=1234))
8110 self.pg0.add_stream(p)
8111 self.pg_enable_capture(self.pg_interfaces)
8112 self.pg_start()
8113 p = self.pg0.get_capture(1)
8114 packet = p[0]
8115 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07008116 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008117 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008118 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008119 except:
8120 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8121 raise
8122
8123 # server to client
8124 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008125 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008126 GRE() /
8127 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8128 TCP(sport=1234, dport=1234))
8129 self.pg0.add_stream(p)
8130 self.pg_enable_capture(self.pg_interfaces)
8131 self.pg_start()
8132 p = self.pg0.get_capture(1)
8133 packet = p[0]
8134 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07008135 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008136 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008137 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008138 except:
8139 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8140 raise
8141
Matus Fabian36ea2d62017-10-24 04:13:49 -07008142 def test_one_armed_nat64(self):
8143 """ One armed NAT64 """
8144 external_port = 0
8145 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8146 '64:ff9b::',
8147 96)
8148
Filip Vargadd1e3e72019-04-15 18:52:43 +02008149 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8150 self.nat_addr)
8151 flags = self.config_flags.NAT_IS_INSIDE
8152 self.vapi.nat64_add_del_interface(1, flags, self.pg3.sw_if_index)
8153 self.vapi.nat64_add_del_interface(1, 0, self.pg3.sw_if_index)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008154
8155 # in2out
8156 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8157 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8158 TCP(sport=12345, dport=80))
8159 self.pg3.add_stream(p)
8160 self.pg_enable_capture(self.pg_interfaces)
8161 self.pg_start()
8162 capture = self.pg3.get_capture(1)
8163 p = capture[0]
8164 try:
8165 ip = p[IP]
8166 tcp = p[TCP]
8167 self.assertEqual(ip.src, self.nat_addr)
8168 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8169 self.assertNotEqual(tcp.sport, 12345)
8170 external_port = tcp.sport
8171 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008172 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008173 except:
8174 self.logger.error(ppp("Unexpected or invalid packet:", p))
8175 raise
8176
8177 # out2in
8178 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8179 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8180 TCP(sport=80, dport=external_port))
8181 self.pg3.add_stream(p)
8182 self.pg_enable_capture(self.pg_interfaces)
8183 self.pg_start()
8184 capture = self.pg3.get_capture(1)
8185 p = capture[0]
8186 try:
8187 ip = p[IPv6]
8188 tcp = p[TCP]
8189 self.assertEqual(ip.src, remote_host_ip6)
8190 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8191 self.assertEqual(tcp.sport, 80)
8192 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008193 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008194 except:
8195 self.logger.error(ppp("Unexpected or invalid packet:", p))
8196 raise
8197
Matus Fabianefcd1e92017-08-15 06:59:19 -07008198 def test_frag_in_order(self):
8199 """ NAT64 translate fragments arriving in order """
8200 self.tcp_port_in = random.randint(1025, 65535)
8201
Filip Vargadd1e3e72019-04-15 18:52:43 +02008202 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8203 self.nat_addr)
8204 flags = self.config_flags.NAT_IS_INSIDE
8205 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8206 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008207
8208 reass = self.vapi.nat_reass_dump()
8209 reass_n_start = len(reass)
8210
8211 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008212 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008213 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8214 self.tcp_port_in, 20, data)
8215 self.pg0.add_stream(pkts)
8216 self.pg_enable_capture(self.pg_interfaces)
8217 self.pg_start()
8218 frags = self.pg1.get_capture(len(pkts))
8219 p = self.reass_frags_and_verify(frags,
8220 self.nat_addr,
8221 self.pg1.remote_ip4)
8222 self.assertEqual(p[TCP].dport, 20)
8223 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8224 self.tcp_port_out = p[TCP].sport
8225 self.assertEqual(data, p[Raw].load)
8226
8227 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008228 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008229 pkts = self.create_stream_frag(self.pg1,
8230 self.nat_addr,
8231 20,
8232 self.tcp_port_out,
8233 data)
8234 self.pg1.add_stream(pkts)
8235 self.pg_enable_capture(self.pg_interfaces)
8236 self.pg_start()
8237 frags = self.pg0.get_capture(len(pkts))
8238 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8239 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8240 self.assertEqual(p[TCP].sport, 20)
8241 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8242 self.assertEqual(data, p[Raw].load)
8243
8244 reass = self.vapi.nat_reass_dump()
8245 reass_n_end = len(reass)
8246
8247 self.assertEqual(reass_n_end - reass_n_start, 2)
8248
8249 def test_reass_hairpinning(self):
8250 """ NAT64 fragments hairpinning """
8251 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008252 server = self.pg0.remote_hosts[1]
8253 server_in_port = random.randint(1025, 65535)
8254 server_out_port = random.randint(1025, 65535)
8255 client_in_port = random.randint(1025, 65535)
8256 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8257 nat_addr_ip6 = ip.src
8258
Filip Vargadd1e3e72019-04-15 18:52:43 +02008259 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8260 self.nat_addr)
8261 flags = self.config_flags.NAT_IS_INSIDE
8262 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8263 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008264
8265 # add static BIB entry for server
8266 self.vapi.nat64_add_del_static_bib(server.ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02008267 self.nat_addr,
Matus Fabianefcd1e92017-08-15 06:59:19 -07008268 server_in_port,
8269 server_out_port,
8270 IP_PROTOS.tcp)
8271
8272 # send packet from host to server
8273 pkts = self.create_stream_frag_ip6(self.pg0,
8274 self.nat_addr,
8275 client_in_port,
8276 server_out_port,
8277 data)
8278 self.pg0.add_stream(pkts)
8279 self.pg_enable_capture(self.pg_interfaces)
8280 self.pg_start()
8281 frags = self.pg0.get_capture(len(pkts))
8282 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8283 self.assertNotEqual(p[TCP].sport, client_in_port)
8284 self.assertEqual(p[TCP].dport, server_in_port)
8285 self.assertEqual(data, p[Raw].load)
8286
8287 def test_frag_out_of_order(self):
8288 """ NAT64 translate fragments arriving out of order """
8289 self.tcp_port_in = random.randint(1025, 65535)
8290
Filip Vargadd1e3e72019-04-15 18:52:43 +02008291 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8292 self.nat_addr)
8293 flags = self.config_flags.NAT_IS_INSIDE
8294 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8295 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008296
8297 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008298 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008299 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8300 self.tcp_port_in, 20, data)
8301 pkts.reverse()
8302 self.pg0.add_stream(pkts)
8303 self.pg_enable_capture(self.pg_interfaces)
8304 self.pg_start()
8305 frags = self.pg1.get_capture(len(pkts))
8306 p = self.reass_frags_and_verify(frags,
8307 self.nat_addr,
8308 self.pg1.remote_ip4)
8309 self.assertEqual(p[TCP].dport, 20)
8310 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8311 self.tcp_port_out = p[TCP].sport
8312 self.assertEqual(data, p[Raw].load)
8313
8314 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008315 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008316 pkts = self.create_stream_frag(self.pg1,
8317 self.nat_addr,
8318 20,
8319 self.tcp_port_out,
8320 data)
8321 pkts.reverse()
8322 self.pg1.add_stream(pkts)
8323 self.pg_enable_capture(self.pg_interfaces)
8324 self.pg_start()
8325 frags = self.pg0.get_capture(len(pkts))
8326 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8327 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8328 self.assertEqual(p[TCP].sport, 20)
8329 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8330 self.assertEqual(data, p[Raw].load)
8331
Matus Fabian0938dcf2017-11-08 01:59:38 -08008332 def test_interface_addr(self):
8333 """ Acquire NAT64 pool addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01008334 self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008335
8336 # no address in NAT64 pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008337 addresses = self.vapi.nat44_address_dump()
8338 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008339
8340 # configure interface address and check NAT64 address pool
8341 self.pg4.config_ip4()
8342 addresses = self.vapi.nat64_pool_addr_dump()
8343 self.assertEqual(len(addresses), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008344
8345 self.assertEqual(str(addresses[0].address),
8346 self.pg4.local_ip4)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008347
8348 # remove interface address and check NAT64 address pool
8349 self.pg4.unconfig_ip4()
8350 addresses = self.vapi.nat64_pool_addr_dump()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008351 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008352
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008353 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008354 def test_ipfix_max_bibs_sessions(self):
8355 """ IPFIX logging maximum session and BIB entries exceeded """
8356 max_bibs = 1280
8357 max_sessions = 2560
8358 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8359 '64:ff9b::',
8360 96)
8361
Filip Vargadd1e3e72019-04-15 18:52:43 +02008362 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8363 self.nat_addr)
8364 flags = self.config_flags.NAT_IS_INSIDE
8365 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8366 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08008367
8368 pkts = []
8369 src = ""
8370 for i in range(0, max_bibs):
8371 src = "fd01:aa::%x" % (i)
8372 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8373 IPv6(src=src, dst=remote_host_ip6) /
8374 TCP(sport=12345, dport=80))
8375 pkts.append(p)
8376 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8377 IPv6(src=src, dst=remote_host_ip6) /
8378 TCP(sport=12345, dport=22))
8379 pkts.append(p)
8380 self.pg0.add_stream(pkts)
8381 self.pg_enable_capture(self.pg_interfaces)
8382 self.pg_start()
8383 self.pg1.get_capture(max_sessions)
8384
8385 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8386 src_address=self.pg3.local_ip4n,
8387 path_mtu=512,
8388 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008389 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8390 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008391
8392 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8393 IPv6(src=src, dst=remote_host_ip6) /
8394 TCP(sport=12345, dport=25))
8395 self.pg0.add_stream(p)
8396 self.pg_enable_capture(self.pg_interfaces)
8397 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008398 self.pg1.assert_nothing_captured()
8399 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008400 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8401 capture = self.pg3.get_capture(9)
8402 ipfix = IPFIXDecoder()
8403 # first load template
8404 for p in capture:
8405 self.assertTrue(p.haslayer(IPFIX))
8406 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8407 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8408 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8409 self.assertEqual(p[UDP].dport, 4739)
8410 self.assertEqual(p[IPFIX].observationDomainID,
8411 self.ipfix_domain_id)
8412 if p.haslayer(Template):
8413 ipfix.add_template(p.getlayer(Template))
8414 # verify events in data set
8415 for p in capture:
8416 if p.haslayer(Data):
8417 data = ipfix.decode_data_set(p.getlayer(Set))
8418 self.verify_ipfix_max_sessions(data, max_sessions)
8419
8420 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8421 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8422 TCP(sport=12345, dport=80))
8423 self.pg0.add_stream(p)
8424 self.pg_enable_capture(self.pg_interfaces)
8425 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008426 self.pg1.assert_nothing_captured()
8427 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008428 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8429 capture = self.pg3.get_capture(1)
8430 # verify events in data set
8431 for p in capture:
8432 self.assertTrue(p.haslayer(IPFIX))
8433 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8434 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8435 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8436 self.assertEqual(p[UDP].dport, 4739)
8437 self.assertEqual(p[IPFIX].observationDomainID,
8438 self.ipfix_domain_id)
8439 if p.haslayer(Data):
8440 data = ipfix.decode_data_set(p.getlayer(Set))
8441 self.verify_ipfix_max_bibs(data, max_bibs)
8442
8443 def test_ipfix_max_frags(self):
8444 """ IPFIX logging maximum fragments pending reassembly exceeded """
Filip Vargadd1e3e72019-04-15 18:52:43 +02008445 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8446 self.nat_addr)
8447 flags = self.config_flags.NAT_IS_INSIDE
8448 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8449 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008450 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008451 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8452 src_address=self.pg3.local_ip4n,
8453 path_mtu=512,
8454 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008455 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8456 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008457
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008458 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008459 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8460 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008461 pkts.reverse()
8462 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008463 self.pg_enable_capture(self.pg_interfaces)
8464 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008465 self.pg1.assert_nothing_captured()
8466 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008467 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8468 capture = self.pg3.get_capture(9)
8469 ipfix = IPFIXDecoder()
8470 # first load template
8471 for p in capture:
8472 self.assertTrue(p.haslayer(IPFIX))
8473 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8474 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8475 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8476 self.assertEqual(p[UDP].dport, 4739)
8477 self.assertEqual(p[IPFIX].observationDomainID,
8478 self.ipfix_domain_id)
8479 if p.haslayer(Template):
8480 ipfix.add_template(p.getlayer(Template))
8481 # verify events in data set
8482 for p in capture:
8483 if p.haslayer(Data):
8484 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008485 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008486 self.pg0.remote_ip6n)
8487
8488 def test_ipfix_bib_ses(self):
8489 """ IPFIX logging NAT64 BIB/session create and delete events """
8490 self.tcp_port_in = random.randint(1025, 65535)
8491 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8492 '64:ff9b::',
8493 96)
8494
Filip Vargadd1e3e72019-04-15 18:52:43 +02008495 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8496 self.nat_addr)
8497 flags = self.config_flags.NAT_IS_INSIDE
8498 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8499 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08008500 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8501 src_address=self.pg3.local_ip4n,
8502 path_mtu=512,
8503 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008504 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8505 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008506
8507 # Create
8508 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8509 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8510 TCP(sport=self.tcp_port_in, dport=25))
8511 self.pg0.add_stream(p)
8512 self.pg_enable_capture(self.pg_interfaces)
8513 self.pg_start()
8514 p = self.pg1.get_capture(1)
8515 self.tcp_port_out = p[0][TCP].sport
8516 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8517 capture = self.pg3.get_capture(10)
8518 ipfix = IPFIXDecoder()
8519 # first load template
8520 for p in capture:
8521 self.assertTrue(p.haslayer(IPFIX))
8522 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8523 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8524 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8525 self.assertEqual(p[UDP].dport, 4739)
8526 self.assertEqual(p[IPFIX].observationDomainID,
8527 self.ipfix_domain_id)
8528 if p.haslayer(Template):
8529 ipfix.add_template(p.getlayer(Template))
8530 # verify events in data set
8531 for p in capture:
8532 if p.haslayer(Data):
8533 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008534 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008535 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008536 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008537 self.verify_ipfix_nat64_ses(data,
8538 1,
8539 self.pg0.remote_ip6n,
8540 self.pg1.remote_ip4,
8541 25)
8542 else:
8543 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8544
8545 # Delete
8546 self.pg_enable_capture(self.pg_interfaces)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008547 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8548 self.nat_addr,
Matus Fabiana431ad12018-01-04 04:03:14 -08008549 is_add=0)
8550 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8551 capture = self.pg3.get_capture(2)
8552 # verify events in data set
8553 for p in capture:
8554 self.assertTrue(p.haslayer(IPFIX))
8555 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8556 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8557 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8558 self.assertEqual(p[UDP].dport, 4739)
8559 self.assertEqual(p[IPFIX].observationDomainID,
8560 self.ipfix_domain_id)
8561 if p.haslayer(Data):
8562 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008563 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08008564 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008565 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08008566 self.verify_ipfix_nat64_ses(data,
8567 0,
8568 self.pg0.remote_ip6n,
8569 self.pg1.remote_ip4,
8570 25)
8571 else:
8572 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8573
Matus Fabianad1f3e12018-11-28 21:26:34 -08008574 def test_syslog_sess(self):
8575 """ Test syslog session creation and deletion """
8576 self.tcp_port_in = random.randint(1025, 65535)
8577 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8578 '64:ff9b::',
8579 96)
8580
Filip Vargadd1e3e72019-04-15 18:52:43 +02008581 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8582 self.nat_addr)
8583 flags = self.config_flags.NAT_IS_INSIDE
8584 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8585 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008586 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01008587 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008588
8589 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8590 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8591 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8592 self.pg0.add_stream(p)
8593 self.pg_enable_capture(self.pg_interfaces)
8594 self.pg_start()
8595 p = self.pg1.get_capture(1)
8596 self.tcp_port_out = p[0][TCP].sport
8597 capture = self.pg3.get_capture(1)
8598 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8599
8600 self.pg_enable_capture(self.pg_interfaces)
8601 self.pg_start()
Filip Vargadd1e3e72019-04-15 18:52:43 +02008602 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8603 self.nat_addr,
Matus Fabianad1f3e12018-11-28 21:26:34 -08008604 is_add=0)
8605 capture = self.pg3.get_capture(1)
8606 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8607
Matus Fabian06596c52017-06-06 04:53:28 -07008608 def nat64_get_ses_num(self):
8609 """
8610 Return number of active NAT64 sessions.
8611 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07008612 st = self.vapi.nat64_st_dump()
8613 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07008614
8615 def clear_nat64(self):
8616 """
8617 Clear NAT64 configuration.
8618 """
Ole Troane1ade682019-03-04 23:55:43 +01008619 self.vapi.nat_ipfix_enable_disable(enable=0,
8620 src_port=self.ipfix_src_port,
8621 domain_id=self.ipfix_domain_id)
Matus Fabiana431ad12018-01-04 04:03:14 -08008622 self.ipfix_src_port = 4739
8623 self.ipfix_domain_id = 1
8624
Matus Fabianad1f3e12018-11-28 21:26:34 -08008625 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8626
Matus Fabian878c6462018-08-23 00:33:35 -07008627 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07008628
8629 interfaces = self.vapi.nat64_interface_dump()
8630 for intf in interfaces:
Filip Vargadd1e3e72019-04-15 18:52:43 +02008631 self.vapi.nat64_add_del_interface(0,
8632 intf.flags,
8633 intf.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07008634
Matus Fabiana431ad12018-01-04 04:03:14 -08008635 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07008636 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02008637 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07008638 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8639 bibe.o_addr,
8640 bibe.i_port,
8641 bibe.o_port,
8642 bibe.proto,
8643 bibe.vrf_id,
8644 is_add=0)
8645
8646 adresses = self.vapi.nat64_pool_addr_dump()
8647 for addr in adresses:
8648 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8649 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07008650 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07008651 is_add=0)
8652
Matus Fabian428dc912017-06-21 06:15:18 -07008653 prefixes = self.vapi.nat64_prefix_dump()
8654 for prefix in prefixes:
Filip Vargadd1e3e72019-04-15 18:52:43 +02008655 self.vapi.nat64_add_del_prefix(str(prefix.prefix),
Matus Fabian428dc912017-06-21 06:15:18 -07008656 vrf_id=prefix.vrf_id,
8657 is_add=0)
8658
Matus Fabianfd0d5082018-12-18 01:08:51 -08008659 bibs = self.statistics.get_counter('/nat64/total-bibs')
8660 self.assertEqual(bibs[0][0], 0)
8661 sessions = self.statistics.get_counter('/nat64/total-sessions')
8662 self.assertEqual(sessions[0][0], 0)
8663
Matus Fabian06596c52017-06-06 04:53:28 -07008664 def tearDown(self):
8665 super(TestNAT64, self).tearDown()
8666 if not self.vpp_dead:
Matus Fabian06596c52017-06-06 04:53:28 -07008667 self.clear_nat64()
8668
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008669 def show_commands_at_teardown(self):
8670 self.logger.info(self.vapi.cli("show nat64 pool"))
8671 self.logger.info(self.vapi.cli("show nat64 interfaces"))
8672 self.logger.info(self.vapi.cli("show nat64 prefix"))
8673 self.logger.info(self.vapi.cli("show nat64 bib all"))
8674 self.logger.info(self.vapi.cli("show nat64 session table all"))
8675 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
8676
Matus Fabian8ebe6252017-11-06 05:04:53 -08008677
8678class TestDSlite(MethodHolder):
8679 """ DS-Lite Test Cases """
8680
8681 @classmethod
8682 def setUpClass(cls):
8683 super(TestDSlite, cls).setUpClass()
8684
8685 try:
8686 cls.nat_addr = '10.0.0.3'
Matus Fabian8ebe6252017-11-06 05:04:53 -08008687
Matus Fabianad1f3e12018-11-28 21:26:34 -08008688 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008689 cls.pg0.admin_up()
8690 cls.pg0.config_ip4()
8691 cls.pg0.resolve_arp()
8692 cls.pg1.admin_up()
8693 cls.pg1.config_ip6()
8694 cls.pg1.generate_remote_hosts(2)
8695 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08008696 cls.pg2.admin_up()
8697 cls.pg2.config_ip4()
8698 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08008699
8700 except Exception:
8701 super(TestDSlite, cls).tearDownClass()
8702 raise
8703
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008704 @classmethod
8705 def tearDownClass(cls):
8706 super(TestDSlite, cls).tearDownClass()
8707
Matus Fabianad1f3e12018-11-28 21:26:34 -08008708 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8709 sv6enc, proto):
8710 message = data.decode('utf-8')
8711 try:
8712 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08008713 except ParseError as e:
8714 self.logger.error(e)
8715 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08008716 self.assertEqual(message.severity, SyslogSeverity.info)
8717 self.assertEqual(message.appname, 'NAT')
8718 self.assertEqual(message.msgid, 'APMADD')
8719 sd_params = message.sd.get('napmap')
8720 self.assertTrue(sd_params is not None)
8721 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8722 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8723 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8724 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8725 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8726 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8727 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8728 self.assertTrue(sd_params.get('SSUBIX') is not None)
8729 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008730
Matus Fabian8ebe6252017-11-06 05:04:53 -08008731 def test_dslite(self):
8732 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07008733 nat_config = self.vapi.nat_show_config()
8734 self.assertEqual(0, nat_config.dslite_ce)
8735
Filip Vargadd1e3e72019-04-15 18:52:43 +02008736 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr,
8737 self.nat_addr)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008738 aftr_ip4 = '192.0.0.1'
Matus Fabian8ebe6252017-11-06 05:04:53 -08008739 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
Filip Vargadd1e3e72019-04-15 18:52:43 +02008740 self.vapi.dslite_set_aftr_addr(aftr_ip6, aftr_ip4)
Ole Troanf159f582019-02-28 20:20:47 +01008741 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008742
8743 # UDP
8744 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8745 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8746 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8747 UDP(sport=20000, dport=10000))
8748 self.pg1.add_stream(p)
8749 self.pg_enable_capture(self.pg_interfaces)
8750 self.pg_start()
8751 capture = self.pg0.get_capture(1)
8752 capture = capture[0]
8753 self.assertFalse(capture.haslayer(IPv6))
8754 self.assertEqual(capture[IP].src, self.nat_addr)
8755 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8756 self.assertNotEqual(capture[UDP].sport, 20000)
8757 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008758 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008759 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008760 capture = self.pg2.get_capture(1)
8761 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8762 20000, self.nat_addr, out_port,
8763 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008764
8765 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8766 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8767 UDP(sport=10000, dport=out_port))
8768 self.pg0.add_stream(p)
8769 self.pg_enable_capture(self.pg_interfaces)
8770 self.pg_start()
8771 capture = self.pg1.get_capture(1)
8772 capture = capture[0]
8773 self.assertEqual(capture[IPv6].src, aftr_ip6)
8774 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8775 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8776 self.assertEqual(capture[IP].dst, '192.168.1.1')
8777 self.assertEqual(capture[UDP].sport, 10000)
8778 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008779 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008780
8781 # TCP
8782 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8783 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8784 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8785 TCP(sport=20001, dport=10001))
8786 self.pg1.add_stream(p)
8787 self.pg_enable_capture(self.pg_interfaces)
8788 self.pg_start()
8789 capture = self.pg0.get_capture(1)
8790 capture = capture[0]
8791 self.assertFalse(capture.haslayer(IPv6))
8792 self.assertEqual(capture[IP].src, self.nat_addr)
8793 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8794 self.assertNotEqual(capture[TCP].sport, 20001)
8795 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008796 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008797 out_port = capture[TCP].sport
8798
8799 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8800 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8801 TCP(sport=10001, dport=out_port))
8802 self.pg0.add_stream(p)
8803 self.pg_enable_capture(self.pg_interfaces)
8804 self.pg_start()
8805 capture = self.pg1.get_capture(1)
8806 capture = capture[0]
8807 self.assertEqual(capture[IPv6].src, aftr_ip6)
8808 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8809 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8810 self.assertEqual(capture[IP].dst, '192.168.1.1')
8811 self.assertEqual(capture[TCP].sport, 10001)
8812 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008813 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008814
8815 # ICMP
8816 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8817 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8818 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8819 ICMP(id=4000, type='echo-request'))
8820 self.pg1.add_stream(p)
8821 self.pg_enable_capture(self.pg_interfaces)
8822 self.pg_start()
8823 capture = self.pg0.get_capture(1)
8824 capture = capture[0]
8825 self.assertFalse(capture.haslayer(IPv6))
8826 self.assertEqual(capture[IP].src, self.nat_addr)
8827 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8828 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008829 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008830 out_id = capture[ICMP].id
8831
8832 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8833 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8834 ICMP(id=out_id, type='echo-reply'))
8835 self.pg0.add_stream(p)
8836 self.pg_enable_capture(self.pg_interfaces)
8837 self.pg_start()
8838 capture = self.pg1.get_capture(1)
8839 capture = capture[0]
8840 self.assertEqual(capture[IPv6].src, aftr_ip6)
8841 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8842 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8843 self.assertEqual(capture[IP].dst, '192.168.1.1')
8844 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008845 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008846
Matus Fabian331acc62017-12-08 03:38:51 -08008847 # ping DS-Lite AFTR tunnel endpoint address
8848 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8849 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8850 ICMPv6EchoRequest())
8851 self.pg1.add_stream(p)
8852 self.pg_enable_capture(self.pg_interfaces)
8853 self.pg_start()
8854 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008855 capture = capture[0]
8856 self.assertEqual(capture[IPv6].src, aftr_ip6)
8857 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8858 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8859
Matus Fabianfd0d5082018-12-18 01:08:51 -08008860 b4s = self.statistics.get_counter('/dslite/total-b4s')
8861 self.assertEqual(b4s[0][0], 2)
8862 sessions = self.statistics.get_counter('/dslite/total-sessions')
8863 self.assertEqual(sessions[0][0], 3)
8864
Matus Fabian8ebe6252017-11-06 05:04:53 -08008865 def tearDown(self):
8866 super(TestDSlite, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008867
8868 def show_commands_at_teardown(self):
8869 self.logger.info(self.vapi.cli("show dslite pool"))
8870 self.logger.info(
8871 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8872 self.logger.info(self.vapi.cli("show dslite sessions"))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008873
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008874
8875class TestDSliteCE(MethodHolder):
8876 """ DS-Lite CE Test Cases """
8877
8878 @classmethod
8879 def setUpConstants(cls):
8880 super(TestDSliteCE, cls).setUpConstants()
8881 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8882
8883 @classmethod
8884 def setUpClass(cls):
8885 super(TestDSliteCE, cls).setUpClass()
8886
8887 try:
8888 cls.create_pg_interfaces(range(2))
8889 cls.pg0.admin_up()
8890 cls.pg0.config_ip4()
8891 cls.pg0.resolve_arp()
8892 cls.pg1.admin_up()
8893 cls.pg1.config_ip6()
8894 cls.pg1.generate_remote_hosts(1)
8895 cls.pg1.configure_ipv6_neighbors()
8896
8897 except Exception:
8898 super(TestDSliteCE, cls).tearDownClass()
8899 raise
8900
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07008901 @classmethod
8902 def tearDownClass(cls):
8903 super(TestDSliteCE, cls).tearDownClass()
8904
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008905 def test_dslite_ce(self):
8906 """ Test DS-Lite CE """
8907
Matus Fabian69ce30d2018-08-22 01:27:10 -07008908 nat_config = self.vapi.nat_show_config()
8909 self.assertEqual(1, nat_config.dslite_ce)
8910
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008911 b4_ip4 = '192.0.0.2'
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008912 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
Filip Vargadd1e3e72019-04-15 18:52:43 +02008913 self.vapi.dslite_set_b4_addr(b4_ip6, b4_ip4)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008914
8915 aftr_ip4 = '192.0.0.1'
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008916 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8917 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008918 self.vapi.dslite_set_aftr_addr(aftr_ip6, aftr_ip4)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008919
8920 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8921 dst_address_length=128,
8922 next_hop_address=self.pg1.remote_ip6n,
8923 next_hop_sw_if_index=self.pg1.sw_if_index,
8924 is_ipv6=1)
8925
8926 # UDP encapsulation
8927 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8928 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8929 UDP(sport=10000, dport=20000))
8930 self.pg0.add_stream(p)
8931 self.pg_enable_capture(self.pg_interfaces)
8932 self.pg_start()
8933 capture = self.pg1.get_capture(1)
8934 capture = capture[0]
8935 self.assertEqual(capture[IPv6].src, b4_ip6)
8936 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8937 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8938 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8939 self.assertEqual(capture[UDP].sport, 10000)
8940 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008941 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008942
8943 # UDP decapsulation
8944 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8945 IPv6(dst=b4_ip6, src=aftr_ip6) /
8946 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8947 UDP(sport=20000, dport=10000))
8948 self.pg1.add_stream(p)
8949 self.pg_enable_capture(self.pg_interfaces)
8950 self.pg_start()
8951 capture = self.pg0.get_capture(1)
8952 capture = capture[0]
8953 self.assertFalse(capture.haslayer(IPv6))
8954 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8955 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8956 self.assertEqual(capture[UDP].sport, 20000)
8957 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008958 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008959
8960 # ping DS-Lite B4 tunnel endpoint address
8961 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8962 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8963 ICMPv6EchoRequest())
8964 self.pg1.add_stream(p)
8965 self.pg_enable_capture(self.pg_interfaces)
8966 self.pg_start()
8967 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008968 capture = capture[0]
8969 self.assertEqual(capture[IPv6].src, b4_ip6)
8970 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8971 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8972
8973 def tearDown(self):
8974 super(TestDSliteCE, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07008975
8976 def show_commands_at_teardown(self):
8977 self.logger.info(
8978 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8979 self.logger.info(
8980 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008981
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008982
8983class TestNAT66(MethodHolder):
8984 """ NAT66 Test Cases """
8985
8986 @classmethod
8987 def setUpClass(cls):
8988 super(TestNAT66, cls).setUpClass()
8989
8990 try:
8991 cls.nat_addr = 'fd01:ff::2'
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008992
8993 cls.create_pg_interfaces(range(2))
8994 cls.interfaces = list(cls.pg_interfaces)
8995
8996 for i in cls.interfaces:
8997 i.admin_up()
8998 i.config_ip6()
8999 i.configure_ipv6_neighbors()
9000
9001 except Exception:
9002 super(TestNAT66, cls).tearDownClass()
9003 raise
9004
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009005 @classmethod
9006 def tearDownClass(cls):
9007 super(TestNAT66, cls).tearDownClass()
9008
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009009 def test_static(self):
9010 """ 1:1 NAT66 test """
Filip Vargadd1e3e72019-04-15 18:52:43 +02009011 flags = self.config_flags.NAT_IS_INSIDE
9012 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index, flags=flags)
9013 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009014 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02009015 self.nat_addr)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009016
9017 # in2out
9018 pkts = []
9019 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9020 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9021 TCP())
9022 pkts.append(p)
9023 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9024 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9025 UDP())
9026 pkts.append(p)
9027 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9028 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9029 ICMPv6EchoRequest())
9030 pkts.append(p)
9031 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9032 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9033 GRE() / IP() / TCP())
9034 pkts.append(p)
9035 self.pg0.add_stream(pkts)
9036 self.pg_enable_capture(self.pg_interfaces)
9037 self.pg_start()
9038 capture = self.pg1.get_capture(len(pkts))
9039 for packet in capture:
9040 try:
9041 self.assertEqual(packet[IPv6].src, self.nat_addr)
9042 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02009043 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009044 except:
9045 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9046 raise
9047
9048 # out2in
9049 pkts = []
9050 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9051 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9052 TCP())
9053 pkts.append(p)
9054 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9055 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9056 UDP())
9057 pkts.append(p)
9058 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9059 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9060 ICMPv6EchoReply())
9061 pkts.append(p)
9062 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9063 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9064 GRE() / IP() / TCP())
9065 pkts.append(p)
9066 self.pg1.add_stream(pkts)
9067 self.pg_enable_capture(self.pg_interfaces)
9068 self.pg_start()
9069 capture = self.pg0.get_capture(len(pkts))
9070 for packet in capture:
9071 try:
9072 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9073 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02009074 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009075 except:
9076 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9077 raise
9078
9079 sm = self.vapi.nat66_static_mapping_dump()
9080 self.assertEqual(len(sm), 1)
9081 self.assertEqual(sm[0].total_pkts, 8)
9082
Juraj Sloboda9341e342018-04-13 12:00:46 +02009083 def test_check_no_translate(self):
9084 """ NAT66 translate only when egress interface is outside interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02009085 flags = self.config_flags.NAT_IS_INSIDE
9086 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index, flags=flags)
9087 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, flags=flags)
Juraj Sloboda9341e342018-04-13 12:00:46 +02009088 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
Filip Vargadd1e3e72019-04-15 18:52:43 +02009089 self.nat_addr)
Juraj Sloboda9341e342018-04-13 12:00:46 +02009090
9091 # in2out
9092 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9093 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9094 UDP())
9095 self.pg0.add_stream([p])
9096 self.pg_enable_capture(self.pg_interfaces)
9097 self.pg_start()
9098 capture = self.pg1.get_capture(1)
9099 packet = capture[0]
9100 try:
9101 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9102 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9103 except:
9104 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9105 raise
9106
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009107 def clear_nat66(self):
9108 """
9109 Clear NAT66 configuration.
9110 """
9111 interfaces = self.vapi.nat66_interface_dump()
9112 for intf in interfaces:
9113 self.vapi.nat66_add_del_interface(intf.sw_if_index,
Filip Vargadd1e3e72019-04-15 18:52:43 +02009114 is_add=0,
9115 flags=intf.flags)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009116
9117 static_mappings = self.vapi.nat66_static_mapping_dump()
9118 for sm in static_mappings:
9119 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
9120 sm.external_ip_address,
9121 sm.vrf_id,
9122 is_add=0)
9123
9124 def tearDown(self):
9125 super(TestNAT66, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009126 self.clear_nat66()
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009127
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009128 def show_commands_at_teardown(self):
9129 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9130 self.logger.info(self.vapi.cli("show nat66 static mappings"))
Klement Sekerad81ae412018-05-16 10:52:54 +02009131
Matus Fabiande886752016-12-07 03:38:19 -08009132if __name__ == '__main__':
9133 unittest.main(testRunner=VppTestRunner)