blob: e0e50c03ddedad60e5317faa899083be4c05b259 [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
Filip Vargaf4749ca2019-04-25 14:55:32 +0200109 self.vapi.nat44_forwarding_enable_disable(enable=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700110
111 interfaces = self.vapi.nat44_interface_addr_dump()
112 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +0200113 self.vapi.nat44_add_del_interface_addr(
114 is_add=0,
115 sw_if_index=intf.sw_if_index,
116 flags=intf.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700117
Filip Vargaf4749ca2019-04-25 14:55:32 +0200118 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Ole Troane1ade682019-03-04 23:55:43 +0100119 src_port=self.ipfix_src_port,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200120 enable=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700121 self.ipfix_src_port = 4739
122 self.ipfix_domain_id = 1
123
Matus Fabianad1f3e12018-11-28 21:26:34 -0800124 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
125
Filip Vargaf4749ca2019-04-25 14:55:32 +0200126 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
127 path_mtu=512)
128 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
129 session_refresh_interval=10)
Matus Fabian34931eb2019-02-26 09:05:23 -0800130
Matus Fabiana6110b62018-06-13 05:39:07 -0700131 interfaces = self.vapi.nat44_interface_dump()
132 for intf in interfaces:
Filip Vargadd1e3e72019-04-15 18:52:43 +0200133 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
Filip Vargaf4749ca2019-04-25 14:55:32 +0200134 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
135 self.vapi.nat44_interface_add_del_feature(
136 sw_if_index=intf.sw_if_index)
137 self.vapi.nat44_interface_add_del_feature(
138 sw_if_index=intf.sw_if_index,
139 flags=intf.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700140
141 interfaces = self.vapi.nat44_interface_output_feature_dump()
142 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +0200143 self.vapi.nat44_interface_add_del_output_feature(
144 is_add=0,
145 flags=intf.flags,
146 sw_if_index=intf.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -0700147 static_mappings = self.vapi.nat44_static_mapping_dump()
148 for sm in static_mappings:
149 self.vapi.nat44_add_del_static_mapping(
Filip Vargadd1e3e72019-04-15 18:52:43 +0200150 is_add=0,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200151 local_ip_address=sm.local_ip_address,
152 external_ip_address=sm.external_ip_address,
153 external_sw_if_index=sm.external_sw_if_index,
154 local_port=sm.local_port,
155 external_port=sm.external_port,
156 vrf_id=sm.vrf_id,
157 protocol=sm.protocol,
158 flags=sm.flags, tag=sm.tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700159
160 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
161 for lb_sm in lb_static_mappings:
162 self.vapi.nat44_add_del_lb_static_mapping(
Matus Fabiana6110b62018-06-13 05:39:07 -0700163 is_add=0,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200164 flags=lb_sm.flags,
165 external_addr=lb_sm.external_addr,
166 external_port=lb_sm.external_port,
167 protocol=lb_sm.protocol,
168 local_num=0, locals=[],
169 tag=lb_sm.tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700170
171 identity_mappings = self.vapi.nat44_identity_mapping_dump()
172 for id_m in identity_mappings:
173 self.vapi.nat44_add_del_identity_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +0200174 ip_address=id_m.ip_address,
Matus Fabiana6110b62018-06-13 05:39:07 -0700175 sw_if_index=id_m.sw_if_index,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200176 port=id_m.port,
177 flags=id_m.flags,
Matus Fabiana6110b62018-06-13 05:39:07 -0700178 vrf_id=id_m.vrf_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200179 protocol=id_m.protocol)
Matus Fabiana6110b62018-06-13 05:39:07 -0700180
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700181 addresses = self.vapi.nat44_address_dump()
182 for addr in addresses:
Filip Vargaf4749ca2019-04-25 14:55:32 +0200183 self.vapi.nat44_add_del_address_range(
184 first_ip_address=addr.ip_address,
185 last_ip_address=addr.ip_address,
186 vrf_id=0xFFFFFFFF, flags=addr.flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700187
Filip Vargaf4749ca2019-04-25 14:55:32 +0200188 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
189 drop_frag=0)
190 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
191 drop_frag=0, is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700192 self.verify_no_nat44_user()
Filip Vargaf4749ca2019-04-25 14:55:32 +0200193 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
194 tcp_transitory=240, icmp=60)
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700195 self.vapi.nat_set_addr_and_port_alloc_alg()
Filip Vargaf4749ca2019-04-25 14:55:32 +0200196 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
Matus Fabiana6110b62018-06-13 05:39:07 -0700197
198 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
199 local_port=0, external_port=0, vrf_id=0,
200 is_add=1, external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200201 proto=0, tag="", flags=0):
Matus Fabiana6110b62018-06-13 05:39:07 -0700202 """
203 Add/delete NAT44 static mapping
204
205 :param local_ip: Local IP address
206 :param external_ip: External IP address
207 :param local_port: Local port number (Optional)
208 :param external_port: External port number (Optional)
209 :param vrf_id: VRF ID (Default 0)
210 :param is_add: 1 if add, 0 if delete (Default add)
211 :param external_sw_if_index: External interface instead of IP address
212 :param proto: IP protocol (Mandatory if port specified)
Matus Fabiana6110b62018-06-13 05:39:07 -0700213 :param tag: Opaque string tag
Filip Vargadd1e3e72019-04-15 18:52:43 +0200214 :param flags: NAT configuration flags
Matus Fabiana6110b62018-06-13 05:39:07 -0700215 """
Filip Vargadd1e3e72019-04-15 18:52:43 +0200216
217 if not (local_port and external_port):
218 flags |= self.config_flags.NAT_IS_ADDR_ONLY
219
Matus Fabiana6110b62018-06-13 05:39:07 -0700220 self.vapi.nat44_add_del_static_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +0200221 is_add=is_add,
222 local_ip_address=local_ip,
223 external_ip_address=external_ip,
224 external_sw_if_index=external_sw_if_index,
225 local_port=local_port,
226 external_port=external_port,
227 vrf_id=vrf_id, protocol=proto,
228 flags=flags,
229 tag=tag)
Matus Fabiana6110b62018-06-13 05:39:07 -0700230
231 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
232 """
233 Add/delete NAT44 address
234
235 :param ip: IP address
236 :param is_add: 1 if add, 0 if delete (Default add)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700237 :param twice_nat: twice NAT address for external hosts
Matus Fabiana6110b62018-06-13 05:39:07 -0700238 """
Filip Vargadd1e3e72019-04-15 18:52:43 +0200239 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
Filip Vargaf4749ca2019-04-25 14:55:32 +0200240 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
241 last_ip_address=ip,
Matus Fabiana6110b62018-06-13 05:39:07 -0700242 vrf_id=vrf_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +0200243 is_add=is_add,
Filip Vargadd1e3e72019-04-15 18:52:43 +0200244 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -0700245
Juraj Slobodacba69362017-12-19 02:09:32 +0100246 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800247 """
248 Create packet stream for inside network
249
250 :param in_if: Inside interface
251 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100252 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800253 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800254 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100255 if dst_ip is None:
256 dst_ip = out_if.remote_ip4
257
Matus Fabiande886752016-12-07 03:38:19 -0800258 pkts = []
259 # TCP
260 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100261 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700262 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800263 pkts.append(p)
264
265 # UDP
266 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100267 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700268 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800269 pkts.append(p)
270
271 # ICMP
272 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100273 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800274 ICMP(id=self.icmp_id_in, type='echo-request'))
275 pkts.append(p)
276
277 return pkts
278
Matus Fabian428dc912017-06-21 06:15:18 -0700279 def compose_ip6(self, ip4, pref, plen):
280 """
281 Compose IPv4-embedded IPv6 addresses
282
283 :param ip4: IPv4 address
284 :param pref: IPv6 prefix
285 :param plen: IPv6 prefix length
286 :returns: IPv4-embedded IPv6 addresses
287 """
288 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
289 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
290 if plen == 32:
291 pref_n[4] = ip4_n[0]
292 pref_n[5] = ip4_n[1]
293 pref_n[6] = ip4_n[2]
294 pref_n[7] = ip4_n[3]
295 elif plen == 40:
296 pref_n[5] = ip4_n[0]
297 pref_n[6] = ip4_n[1]
298 pref_n[7] = ip4_n[2]
299 pref_n[9] = ip4_n[3]
300 elif plen == 48:
301 pref_n[6] = ip4_n[0]
302 pref_n[7] = ip4_n[1]
303 pref_n[9] = ip4_n[2]
304 pref_n[10] = ip4_n[3]
305 elif plen == 56:
306 pref_n[7] = ip4_n[0]
307 pref_n[9] = ip4_n[1]
308 pref_n[10] = ip4_n[2]
309 pref_n[11] = ip4_n[3]
310 elif plen == 64:
311 pref_n[9] = ip4_n[0]
312 pref_n[10] = ip4_n[1]
313 pref_n[11] = ip4_n[2]
314 pref_n[12] = ip4_n[3]
315 elif plen == 96:
316 pref_n[12] = ip4_n[0]
317 pref_n[13] = ip4_n[1]
318 pref_n[14] = ip4_n[2]
319 pref_n[15] = ip4_n[3]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700320 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
321 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
Matus Fabian428dc912017-06-21 06:15:18 -0700322
Juraj Slobodacba69362017-12-19 02:09:32 +0100323 def extract_ip4(self, ip6, plen):
324 """
325 Extract IPv4 address embedded in IPv6 addresses
326
327 :param ip6: IPv6 address
328 :param plen: IPv6 prefix length
329 :returns: extracted IPv4 address
330 """
331 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
332 ip4_n = [None] * 4
333 if plen == 32:
334 ip4_n[0] = ip6_n[4]
335 ip4_n[1] = ip6_n[5]
336 ip4_n[2] = ip6_n[6]
337 ip4_n[3] = ip6_n[7]
338 elif plen == 40:
339 ip4_n[0] = ip6_n[5]
340 ip4_n[1] = ip6_n[6]
341 ip4_n[2] = ip6_n[7]
342 ip4_n[3] = ip6_n[9]
343 elif plen == 48:
344 ip4_n[0] = ip6_n[6]
345 ip4_n[1] = ip6_n[7]
346 ip4_n[2] = ip6_n[9]
347 ip4_n[3] = ip6_n[10]
348 elif plen == 56:
349 ip4_n[0] = ip6_n[7]
350 ip4_n[1] = ip6_n[9]
351 ip4_n[2] = ip6_n[10]
352 ip4_n[3] = ip6_n[11]
353 elif plen == 64:
354 ip4_n[0] = ip6_n[9]
355 ip4_n[1] = ip6_n[10]
356 ip4_n[2] = ip6_n[11]
357 ip4_n[3] = ip6_n[12]
358 elif plen == 96:
359 ip4_n[0] = ip6_n[12]
360 ip4_n[1] = ip6_n[13]
361 ip4_n[2] = ip6_n[14]
362 ip4_n[3] = ip6_n[15]
363 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
364
Matus Fabian428dc912017-06-21 06:15:18 -0700365 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700366 """
367 Create IPv6 packet stream for inside network
368
369 :param in_if: Inside interface
370 :param out_if: Outside interface
371 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700372 :param pref: NAT64 prefix
373 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700374 """
375 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700376 if pref is None:
377 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
378 else:
379 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
380
Matus Fabian06596c52017-06-06 04:53:28 -0700381 # TCP
382 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
383 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
384 TCP(sport=self.tcp_port_in, dport=20))
385 pkts.append(p)
386
387 # UDP
388 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
389 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
390 UDP(sport=self.udp_port_in, dport=20))
391 pkts.append(p)
392
393 # ICMP
394 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
395 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
396 ICMPv6EchoRequest(id=self.icmp_id_in))
397 pkts.append(p)
398
399 return pkts
400
Juraj Sloboda7b929792017-11-23 13:20:48 +0100401 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
402 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800403 """
404 Create packet stream for outside network
405
406 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700407 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800408 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100409 :param use_inside_ports: Use inside NAT ports as destination ports
410 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800411 """
412 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700413 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100414 if not use_inside_ports:
415 tcp_port = self.tcp_port_out
416 udp_port = self.udp_port_out
417 icmp_id = self.icmp_id_out
418 else:
419 tcp_port = self.tcp_port_in
420 udp_port = self.udp_port_in
421 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800422 pkts = []
423 # TCP
424 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800425 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100426 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800427 pkts.append(p)
428
429 # UDP
430 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800431 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100432 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800433 pkts.append(p)
434
435 # ICMP
436 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800437 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100438 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800439 pkts.append(p)
440
441 return pkts
442
Juraj Slobodacba69362017-12-19 02:09:32 +0100443 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
444 """
445 Create packet stream for outside network
446
447 :param out_if: Outside interface
448 :param dst_ip: Destination IP address (Default use global NAT address)
449 :param hl: HL of generated packets
450 """
451 pkts = []
452 # TCP
453 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
454 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
455 TCP(dport=self.tcp_port_out, sport=20))
456 pkts.append(p)
457
458 # UDP
459 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
460 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
461 UDP(dport=self.udp_port_out, sport=20))
462 pkts.append(p)
463
464 # ICMP
465 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
466 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
467 ICMPv6EchoReply(id=self.icmp_id_out))
468 pkts.append(p)
469
470 return pkts
471
Matus Fabiande886752016-12-07 03:38:19 -0800472 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700473 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800474 """
475 Verify captured packets on outside network
476
477 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700478 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700479 :param same_port: Source port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700480 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100481 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800482 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100483 if is_ip6:
484 IP46 = IPv6
485 ICMP46 = ICMPv6EchoRequest
486 else:
487 IP46 = IP
488 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800489 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700490 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800491 for packet in capture:
492 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100493 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200494 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100495 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700496 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100497 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800498 if packet.haslayer(TCP):
499 if same_port:
500 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
501 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100502 self.assertNotEqual(
503 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800504 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200505 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800506 elif packet.haslayer(UDP):
507 if same_port:
508 self.assertEqual(packet[UDP].sport, self.udp_port_in)
509 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100510 self.assertNotEqual(
511 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800512 self.udp_port_out = packet[UDP].sport
513 else:
514 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100515 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800516 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100517 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
518 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200519 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800520 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100521 self.logger.error(ppp("Unexpected or invalid packet "
522 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800523 raise
524
Juraj Slobodacba69362017-12-19 02:09:32 +0100525 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700526 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100527 """
528 Verify captured packets on outside network
529
530 :param capture: Captured packets
531 :param nat_ip: Translated IP address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700532 :param same_port: Source port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100533 :param dst_ip: Destination IP address (Default do not verify)
534 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700535 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
536 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100537
Matus Fabian05ca4a32018-09-04 23:45:13 -0700538 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800539 """
540 Verify captured packets on inside network
541
542 :param capture: Captured packets
543 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800544 """
Matus Fabiande886752016-12-07 03:38:19 -0800545 for packet in capture:
546 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200547 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800548 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
549 if packet.haslayer(TCP):
550 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
551 elif packet.haslayer(UDP):
552 self.assertEqual(packet[UDP].dport, self.udp_port_in)
553 else:
554 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
555 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100556 self.logger.error(ppp("Unexpected or invalid packet "
557 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800558 raise
559
Matus Fabian05ca4a32018-09-04 23:45:13 -0700560 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700561 """
562 Verify captured IPv6 packets on inside network
563
564 :param capture: Captured packets
565 :param src_ip: Source IP
566 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700567 """
Matus Fabian06596c52017-06-06 04:53:28 -0700568 for packet in capture:
569 try:
570 self.assertEqual(packet[IPv6].src, src_ip)
571 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200572 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700573 if packet.haslayer(TCP):
574 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
575 elif packet.haslayer(UDP):
576 self.assertEqual(packet[UDP].dport, self.udp_port_in)
577 else:
578 self.assertEqual(packet[ICMPv6EchoReply].id,
579 self.icmp_id_in)
580 except:
581 self.logger.error(ppp("Unexpected or invalid packet "
582 "(inside network):", packet))
583 raise
584
Matus Fabian675a69c2017-01-18 01:46:01 -0800585 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
586 """
587 Verify captured packet that don't have to be translated
588
589 :param capture: Captured packets
590 :param ingress_if: Ingress interface
591 :param egress_if: Egress interface
592 """
593 for packet in capture:
594 try:
595 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
596 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
597 if packet.haslayer(TCP):
598 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
599 elif packet.haslayer(UDP):
600 self.assertEqual(packet[UDP].sport, self.udp_port_in)
601 else:
602 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
603 except:
604 self.logger.error(ppp("Unexpected or invalid packet "
605 "(inside network):", packet))
606 raise
607
Juraj Slobodab33f4132017-02-08 23:54:21 -0800608 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700609 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800610 """
611 Verify captured packets with ICMP errors on outside network
612
613 :param capture: Captured packets
614 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700615 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800616 :param icmp_type: Type of error ICMP packet
617 we are expecting (Default 11)
618 """
619 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700620 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800621 for packet in capture:
622 try:
623 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800624 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800625 icmp = packet[ICMP]
626 self.assertEqual(icmp.type, icmp_type)
627 self.assertTrue(icmp.haslayer(IPerror))
628 inner_ip = icmp[IPerror]
629 if inner_ip.haslayer(TCPerror):
630 self.assertEqual(inner_ip[TCPerror].dport,
631 self.tcp_port_out)
632 elif inner_ip.haslayer(UDPerror):
633 self.assertEqual(inner_ip[UDPerror].dport,
634 self.udp_port_out)
635 else:
636 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
637 except:
638 self.logger.error(ppp("Unexpected or invalid packet "
639 "(outside network):", packet))
640 raise
641
Matus Fabian05ca4a32018-09-04 23:45:13 -0700642 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800643 """
644 Verify captured packets with ICMP errors on inside network
645
646 :param capture: Captured packets
647 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800648 :param icmp_type: Type of error ICMP packet
649 we are expecting (Default 11)
650 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800651 for packet in capture:
652 try:
653 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800654 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800655 icmp = packet[ICMP]
656 self.assertEqual(icmp.type, icmp_type)
657 self.assertTrue(icmp.haslayer(IPerror))
658 inner_ip = icmp[IPerror]
659 if inner_ip.haslayer(TCPerror):
660 self.assertEqual(inner_ip[TCPerror].sport,
661 self.tcp_port_in)
662 elif inner_ip.haslayer(UDPerror):
663 self.assertEqual(inner_ip[UDPerror].sport,
664 self.udp_port_in)
665 else:
666 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
667 except:
668 self.logger.error(ppp("Unexpected or invalid packet "
669 "(inside network):", packet))
670 raise
671
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200672 def create_stream_frag(self, src_if, dst, sport, dport, data,
673 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700674 """
675 Create fragmented packet stream
676
677 :param src_if: Source interface
678 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200679 :param sport: Source port
680 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700681 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200682 :param proto: protocol (TCP, UDP, ICMP)
683 :param echo_reply: use echo_reply if protocol is ICMP
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700684 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700685 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200686 if proto == IP_PROTOS.tcp:
687 p = (IP(src=src_if.remote_ip4, dst=dst) /
688 TCP(sport=sport, dport=dport) /
689 Raw(data))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700690 p = p.__class__(scapy.compat.raw(p))
691 chksum = p[TCP].chksum
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200692 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
693 elif proto == IP_PROTOS.udp:
694 proto_header = UDP(sport=sport, dport=dport)
695 elif proto == IP_PROTOS.icmp:
696 if not echo_reply:
697 proto_header = ICMP(id=sport, type='echo-request')
698 else:
699 proto_header = ICMP(id=sport, type='echo-reply')
700 else:
701 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700702 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700703 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200704 if proto == IP_PROTOS.tcp:
705 raw = Raw(data[0:4])
706 else:
707 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700708 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
709 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200710 proto_header /
711 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700712 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200713 if proto == IP_PROTOS.tcp:
714 raw = Raw(data[4:20])
715 else:
716 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700717 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
718 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200719 proto=proto) /
720 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700721 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200722 if proto == IP_PROTOS.tcp:
723 raw = Raw(data[20:])
724 else:
725 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700726 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200727 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700728 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200729 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700730 pkts.append(p)
731 return pkts
732
733 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
734 pref=None, plen=0, frag_size=128):
735 """
736 Create fragmented packet stream
737
738 :param src_if: Source interface
739 :param dst: Destination IPv4 address
740 :param sport: Source TCP port
741 :param dport: Destination TCP port
742 :param data: Payload data
743 :param pref: NAT64 prefix
744 :param plen: NAT64 prefix length
745 :param fragsize: size of fragments
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700746 :returns: Fragments
Matus Fabianefcd1e92017-08-15 06:59:19 -0700747 """
748 if pref is None:
749 dst_ip6 = ''.join(['64:ff9b::', dst])
750 else:
751 dst_ip6 = self.compose_ip6(dst, pref, plen)
752
753 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
754 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
755 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
756 TCP(sport=sport, dport=dport) /
757 Raw(data))
758
759 return fragment6(p, frag_size)
760
761 def reass_frags_and_verify(self, frags, src, dst):
762 """
763 Reassemble and verify fragmented packet
764
765 :param frags: Captured fragments
766 :param src: Source IPv4 address to verify
767 :param dst: Destination IPv4 address to verify
768
769 :returns: Reassembled IPv4 packet
770 """
Ole Troan7f991832018-12-06 17:35:12 +0100771 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700772 for p in frags:
773 self.assertEqual(p[IP].src, src)
774 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200775 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700776 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100777 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700778 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
779 proto=frags[0][IP].proto)
780 if ip.proto == IP_PROTOS.tcp:
781 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200782 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700783 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200784 p = (ip / UDP(buffer.getvalue()[:8]) /
785 Raw(buffer.getvalue()[8:]))
786 elif ip.proto == IP_PROTOS.icmp:
787 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700788 return p
789
790 def reass_frags_and_verify_ip6(self, frags, src, dst):
791 """
792 Reassemble and verify fragmented packet
793
794 :param frags: Captured fragments
795 :param src: Source IPv6 address to verify
796 :param dst: Destination IPv6 address to verify
797
798 :returns: Reassembled IPv6 packet
799 """
Ole Troan7f991832018-12-06 17:35:12 +0100800 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700801 for p in frags:
802 self.assertEqual(p[IPv6].src, src)
803 self.assertEqual(p[IPv6].dst, dst)
804 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100805 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700806 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
807 nh=frags[0][IPv6ExtHdrFragment].nh)
808 if ip.nh == IP_PROTOS.tcp:
809 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700810 elif ip.nh == IP_PROTOS.udp:
811 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200812 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700813 return p
814
Matus Fabianebdf1902018-05-04 03:57:42 -0700815 def initiate_tcp_session(self, in_if, out_if):
816 """
817 Initiates TCP session
818
819 :param in_if: Inside interface
820 :param out_if: Outside interface
821 """
822 try:
823 # SYN packet in->out
824 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
825 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
826 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
827 flags="S"))
828 in_if.add_stream(p)
829 self.pg_enable_capture(self.pg_interfaces)
830 self.pg_start()
831 capture = out_if.get_capture(1)
832 p = capture[0]
833 self.tcp_port_out = p[TCP].sport
834
835 # SYN + ACK packet out->in
836 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
837 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
838 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
839 flags="SA"))
840 out_if.add_stream(p)
841 self.pg_enable_capture(self.pg_interfaces)
842 self.pg_start()
843 in_if.get_capture(1)
844
845 # ACK packet in->out
846 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
847 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
848 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
849 flags="A"))
850 in_if.add_stream(p)
851 self.pg_enable_capture(self.pg_interfaces)
852 self.pg_start()
853 out_if.get_capture(1)
854
855 except:
856 self.logger.error("TCP 3 way handshake failed")
857 raise
858
Matus Fabianeea28d72017-01-13 04:15:54 -0800859 def verify_ipfix_nat44_ses(self, data):
860 """
861 Verify IPFIX NAT44 session create/delete event
862
863 :param data: Decoded IPFIX data records
864 """
865 nat44_ses_create_num = 0
866 nat44_ses_delete_num = 0
867 self.assertEqual(6, len(data))
868 for record in data:
869 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700870 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
871 if scapy.compat.orb(record[230]) == 4:
Matus Fabianeea28d72017-01-13 04:15:54 -0800872 nat44_ses_create_num += 1
873 else:
874 nat44_ses_delete_num += 1
875 # sourceIPv4Address
876 self.assertEqual(self.pg0.remote_ip4n, record[8])
877 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700878 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800879 record[225])
880 # ingressVRFID
881 self.assertEqual(struct.pack("!I", 0), record[234])
Filip Vargaf4749ca2019-04-25 14:55:32 +0200882 # protocolIdentifier/sourceTransportPort
883 # /postNAPTSourceTransportPort
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700884 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800885 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
886 self.assertEqual(struct.pack("!H", self.icmp_id_out),
887 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700888 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800889 self.assertEqual(struct.pack("!H", self.tcp_port_in),
890 record[7])
891 self.assertEqual(struct.pack("!H", self.tcp_port_out),
892 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700893 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800894 self.assertEqual(struct.pack("!H", self.udp_port_in),
895 record[7])
896 self.assertEqual(struct.pack("!H", self.udp_port_out),
897 record[227])
898 else:
899 self.fail("Invalid protocol")
900 self.assertEqual(3, nat44_ses_create_num)
901 self.assertEqual(3, nat44_ses_delete_num)
902
903 def verify_ipfix_addr_exhausted(self, data):
904 """
905 Verify IPFIX NAT addresses event
906
907 :param data: Decoded IPFIX data records
908 """
909 self.assertEqual(1, len(data))
910 record = data[0]
911 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700912 self.assertEqual(scapy.compat.orb(record[230]), 3)
Matus Fabianeea28d72017-01-13 04:15:54 -0800913 # natPoolID
914 self.assertEqual(struct.pack("!I", 0), record[283])
915
Matus Fabiana431ad12018-01-04 04:03:14 -0800916 def verify_ipfix_max_sessions(self, data, limit):
917 """
918 Verify IPFIX maximum session entries exceeded event
919
920 :param data: Decoded IPFIX data records
921 :param limit: Number of maximum session entries that can be created.
922 """
923 self.assertEqual(1, len(data))
924 record = data[0]
925 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700926 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800927 # natQuotaExceededEvent
928 self.assertEqual(struct.pack("I", 1), record[466])
929 # maxSessionEntries
930 self.assertEqual(struct.pack("I", limit), record[471])
931
932 def verify_ipfix_max_bibs(self, data, limit):
933 """
934 Verify IPFIX maximum BIB entries exceeded event
935
936 :param data: Decoded IPFIX data records
937 :param limit: Number of maximum BIB entries that can be created.
938 """
939 self.assertEqual(1, len(data))
940 record = data[0]
941 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700942 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800943 # natQuotaExceededEvent
944 self.assertEqual(struct.pack("I", 2), record[466])
945 # maxBIBEntries
946 self.assertEqual(struct.pack("I", limit), record[472])
947
948 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
949 """
950 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
951
952 :param data: Decoded IPFIX data records
953 :param limit: Number of maximum fragments pending reassembly
954 :param src_addr: IPv6 source address
955 """
956 self.assertEqual(1, len(data))
957 record = data[0]
958 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700959 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800960 # natQuotaExceededEvent
961 self.assertEqual(struct.pack("I", 5), record[466])
962 # maxFragmentsPendingReassembly
963 self.assertEqual(struct.pack("I", limit), record[475])
964 # sourceIPv6Address
965 self.assertEqual(src_addr, record[27])
966
967 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
968 """
969 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
970
971 :param data: Decoded IPFIX data records
972 :param limit: Number of maximum fragments pending reassembly
973 :param src_addr: IPv4 source address
974 """
975 self.assertEqual(1, len(data))
976 record = data[0]
977 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700978 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800979 # natQuotaExceededEvent
980 self.assertEqual(struct.pack("I", 5), record[466])
981 # maxFragmentsPendingReassembly
982 self.assertEqual(struct.pack("I", limit), record[475])
983 # sourceIPv4Address
984 self.assertEqual(src_addr, record[8])
985
986 def verify_ipfix_bib(self, data, is_create, src_addr):
987 """
988 Verify IPFIX NAT64 BIB create and delete events
989
990 :param data: Decoded IPFIX data records
991 :param is_create: Create event if nonzero value otherwise delete event
992 :param src_addr: IPv6 source address
993 """
994 self.assertEqual(1, len(data))
995 record = data[0]
996 # natEvent
997 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700998 self.assertEqual(scapy.compat.orb(record[230]), 10)
Matus Fabiana431ad12018-01-04 04:03:14 -0800999 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001000 self.assertEqual(scapy.compat.orb(record[230]), 11)
Matus Fabiana431ad12018-01-04 04:03:14 -08001001 # sourceIPv6Address
1002 self.assertEqual(src_addr, record[27])
1003 # postNATSourceIPv4Address
1004 self.assertEqual(self.nat_addr_n, record[225])
1005 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001006 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001007 # ingressVRFID
1008 self.assertEqual(struct.pack("!I", 0), record[234])
1009 # sourceTransportPort
1010 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1011 # postNAPTSourceTransportPort
1012 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1013
1014 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1015 dst_port):
1016 """
1017 Verify IPFIX NAT64 session create and delete events
1018
1019 :param data: Decoded IPFIX data records
1020 :param is_create: Create event if nonzero value otherwise delete event
1021 :param src_addr: IPv6 source address
1022 :param dst_addr: IPv4 destination address
1023 :param dst_port: destination TCP port
1024 """
1025 self.assertEqual(1, len(data))
1026 record = data[0]
1027 # natEvent
1028 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001029 self.assertEqual(scapy.compat.orb(record[230]), 6)
Matus Fabiana431ad12018-01-04 04:03:14 -08001030 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001031 self.assertEqual(scapy.compat.orb(record[230]), 7)
Matus Fabiana431ad12018-01-04 04:03:14 -08001032 # sourceIPv6Address
1033 self.assertEqual(src_addr, record[27])
1034 # destinationIPv6Address
1035 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1036 self.compose_ip6(dst_addr,
1037 '64:ff9b::',
1038 96)),
1039 record[28])
1040 # postNATSourceIPv4Address
1041 self.assertEqual(self.nat_addr_n, record[225])
1042 # postNATDestinationIPv4Address
1043 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1044 record[226])
1045 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001046 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001047 # ingressVRFID
1048 self.assertEqual(struct.pack("!I", 0), record[234])
1049 # sourceTransportPort
1050 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1051 # postNAPTSourceTransportPort
1052 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1053 # destinationTransportPort
1054 self.assertEqual(struct.pack("!H", dst_port), record[11])
1055 # postNAPTDestinationTransportPort
1056 self.assertEqual(struct.pack("!H", dst_port), record[228])
1057
Matus Fabian68ba8802018-08-08 05:52:47 -07001058 def verify_no_nat44_user(self):
1059 """ Verify that there is no NAT44 user """
1060 users = self.vapi.nat44_user_dump()
1061 self.assertEqual(len(users), 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08001062 users = self.statistics.get_counter('/nat44/total-users')
1063 self.assertEqual(users[0][0], 0)
1064 sessions = self.statistics.get_counter('/nat44/total-sessions')
1065 self.assertEqual(sessions[0][0], 0)
Matus Fabian68ba8802018-08-08 05:52:47 -07001066
Matus Fabian878c6462018-08-23 00:33:35 -07001067 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1068 """
1069 Verify IPFIX maximum entries per user exceeded event
1070
1071 :param data: Decoded IPFIX data records
1072 :param limit: Number of maximum entries per user
1073 :param src_addr: IPv4 source address
1074 """
1075 self.assertEqual(1, len(data))
1076 record = data[0]
1077 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001078 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabian878c6462018-08-23 00:33:35 -07001079 # natQuotaExceededEvent
1080 self.assertEqual(struct.pack("I", 3), record[466])
1081 # maxEntriesPerUser
1082 self.assertEqual(struct.pack("I", limit), record[473])
1083 # sourceIPv4Address
1084 self.assertEqual(src_addr, record[8])
1085
Matus Fabianad1f3e12018-11-28 21:26:34 -08001086 def verify_syslog_apmap(self, data, is_add=True):
1087 message = data.decode('utf-8')
1088 try:
1089 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001090 except ParseError as e:
1091 self.logger.error(e)
1092 raise
1093 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001094 self.assertEqual(message.severity, SyslogSeverity.info)
1095 self.assertEqual(message.appname, 'NAT')
1096 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1097 sd_params = message.sd.get('napmap')
1098 self.assertTrue(sd_params is not None)
1099 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1100 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1101 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1102 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1103 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1104 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1105 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1106 self.assertTrue(sd_params.get('SSUBIX') is not None)
1107 self.assertEqual(sd_params.get('SVLAN'), '0')
Matus Fabianad1f3e12018-11-28 21:26:34 -08001108
1109 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1110 message = data.decode('utf-8')
1111 try:
1112 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001113 except ParseError as e:
1114 self.logger.error(e)
1115 raise
1116 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001117 self.assertEqual(message.severity, SyslogSeverity.info)
1118 self.assertEqual(message.appname, 'NAT')
1119 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1120 sd_params = message.sd.get('nsess')
1121 self.assertTrue(sd_params is not None)
1122 if is_ip6:
1123 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1124 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1125 else:
1126 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1127 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1128 self.assertTrue(sd_params.get('SSUBIX') is not None)
1129 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1130 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1131 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1132 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1133 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1134 self.assertEqual(sd_params.get('SVLAN'), '0')
1135 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1136 self.assertEqual(sd_params.get('XDPORT'),
1137 "%d" % self.tcp_external_port)
Matus Fabianad1f3e12018-11-28 21:26:34 -08001138
Matus Fabianbb4e0222018-09-13 02:36:25 -07001139 def verify_mss_value(self, pkt, mss):
1140 """
1141 Verify TCP MSS value
1142
1143 :param pkt:
1144 :param mss:
1145 """
1146 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1147 raise TypeError("Not a TCP/IP packet")
1148
1149 for option in pkt[TCP].options:
1150 if option[0] == 'MSS':
1151 self.assertEqual(option[1], mss)
1152 self.assert_tcp_checksum_valid(pkt)
1153
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001154 @staticmethod
1155 def proto2layer(proto):
1156 if proto == IP_PROTOS.tcp:
1157 return TCP
1158 elif proto == IP_PROTOS.udp:
1159 return UDP
1160 elif proto == IP_PROTOS.icmp:
1161 return ICMP
1162 else:
1163 raise Exception("Unsupported protocol")
1164
1165 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1166 layer = self.proto2layer(proto)
1167
1168 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001169 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001170 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001171 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001172 self.port_in = random.randint(1025, 65535)
1173
1174 reass = self.vapi.nat_reass_dump()
1175 reass_n_start = len(reass)
1176
1177 # in2out
1178 pkts = self.create_stream_frag(self.pg0,
1179 self.pg1.remote_ip4,
1180 self.port_in,
1181 20,
1182 data,
1183 proto)
1184 self.pg0.add_stream(pkts)
1185 self.pg_enable_capture(self.pg_interfaces)
1186 self.pg_start()
1187 frags = self.pg1.get_capture(len(pkts))
1188 if not dont_translate:
1189 p = self.reass_frags_and_verify(frags,
1190 self.nat_addr,
1191 self.pg1.remote_ip4)
1192 else:
1193 p = self.reass_frags_and_verify(frags,
1194 self.pg0.remote_ip4,
1195 self.pg1.remote_ip4)
1196 if proto != IP_PROTOS.icmp:
1197 if not dont_translate:
1198 self.assertEqual(p[layer].dport, 20)
1199 self.assertNotEqual(p[layer].sport, self.port_in)
1200 else:
1201 self.assertEqual(p[layer].sport, self.port_in)
1202 else:
1203 if not dont_translate:
1204 self.assertNotEqual(p[layer].id, self.port_in)
1205 else:
1206 self.assertEqual(p[layer].id, self.port_in)
1207 self.assertEqual(data, p[Raw].load)
1208
1209 # out2in
1210 if not dont_translate:
1211 dst_addr = self.nat_addr
1212 else:
1213 dst_addr = self.pg0.remote_ip4
1214 if proto != IP_PROTOS.icmp:
1215 sport = 20
1216 dport = p[layer].sport
1217 else:
1218 sport = p[layer].id
1219 dport = 0
1220 pkts = self.create_stream_frag(self.pg1,
1221 dst_addr,
1222 sport,
1223 dport,
1224 data,
1225 proto,
1226 echo_reply=True)
1227 self.pg1.add_stream(pkts)
1228 self.pg_enable_capture(self.pg_interfaces)
1229 self.pg_start()
1230 frags = self.pg0.get_capture(len(pkts))
1231 p = self.reass_frags_and_verify(frags,
1232 self.pg1.remote_ip4,
1233 self.pg0.remote_ip4)
1234 if proto != IP_PROTOS.icmp:
1235 self.assertEqual(p[layer].sport, 20)
1236 self.assertEqual(p[layer].dport, self.port_in)
1237 else:
1238 self.assertEqual(p[layer].id, self.port_in)
1239 self.assertEqual(data, p[Raw].load)
1240
1241 reass = self.vapi.nat_reass_dump()
1242 reass_n_end = len(reass)
1243
1244 self.assertEqual(reass_n_end - reass_n_start, 2)
1245
1246 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1247 layer = self.proto2layer(proto)
1248
1249 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001250 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001251 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001252 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001253 self.port_in = random.randint(1025, 65535)
1254
1255 for i in range(2):
1256 reass = self.vapi.nat_reass_dump()
1257 reass_n_start = len(reass)
1258
1259 # out2in
1260 pkts = self.create_stream_frag(self.pg0,
1261 self.server_out_addr,
1262 self.port_in,
1263 self.server_out_port,
1264 data,
1265 proto)
1266 self.pg0.add_stream(pkts)
1267 self.pg_enable_capture(self.pg_interfaces)
1268 self.pg_start()
1269 frags = self.pg1.get_capture(len(pkts))
1270 p = self.reass_frags_and_verify(frags,
1271 self.pg0.remote_ip4,
1272 self.server_in_addr)
1273 if proto != IP_PROTOS.icmp:
1274 self.assertEqual(p[layer].sport, self.port_in)
1275 self.assertEqual(p[layer].dport, self.server_in_port)
1276 else:
1277 self.assertEqual(p[layer].id, self.port_in)
1278 self.assertEqual(data, p[Raw].load)
1279
1280 # in2out
1281 if proto != IP_PROTOS.icmp:
1282 pkts = self.create_stream_frag(self.pg1,
1283 self.pg0.remote_ip4,
1284 self.server_in_port,
1285 p[layer].sport,
1286 data,
1287 proto)
1288 else:
1289 pkts = self.create_stream_frag(self.pg1,
1290 self.pg0.remote_ip4,
1291 p[layer].id,
1292 0,
1293 data,
1294 proto,
1295 echo_reply=True)
1296 self.pg1.add_stream(pkts)
1297 self.pg_enable_capture(self.pg_interfaces)
1298 self.pg_start()
1299 frags = self.pg0.get_capture(len(pkts))
1300 p = self.reass_frags_and_verify(frags,
1301 self.server_out_addr,
1302 self.pg0.remote_ip4)
1303 if proto != IP_PROTOS.icmp:
1304 self.assertEqual(p[layer].sport, self.server_out_port)
1305 self.assertEqual(p[layer].dport, self.port_in)
1306 else:
1307 self.assertEqual(p[layer].id, self.port_in)
1308 self.assertEqual(data, p[Raw].load)
1309
1310 reass = self.vapi.nat_reass_dump()
1311 reass_n_end = len(reass)
1312
1313 self.assertEqual(reass_n_end - reass_n_start, 2)
1314
1315 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1316 layer = self.proto2layer(proto)
1317
1318 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001319 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001320 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001321 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001322
1323 # send packet from host to server
1324 pkts = self.create_stream_frag(self.pg0,
1325 self.nat_addr,
1326 self.host_in_port,
1327 self.server_out_port,
1328 data,
1329 proto)
1330 self.pg0.add_stream(pkts)
1331 self.pg_enable_capture(self.pg_interfaces)
1332 self.pg_start()
1333 frags = self.pg0.get_capture(len(pkts))
1334 p = self.reass_frags_and_verify(frags,
1335 self.nat_addr,
1336 self.server.ip4)
1337 if proto != IP_PROTOS.icmp:
1338 self.assertNotEqual(p[layer].sport, self.host_in_port)
1339 self.assertEqual(p[layer].dport, self.server_in_port)
1340 else:
1341 self.assertNotEqual(p[layer].id, self.host_in_port)
1342 self.assertEqual(data, p[Raw].load)
1343
1344 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1345 layer = self.proto2layer(proto)
1346
1347 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001348 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001349 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001350 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001351 self.port_in = random.randint(1025, 65535)
1352
1353 for i in range(2):
1354 # in2out
1355 pkts = self.create_stream_frag(self.pg0,
1356 self.pg1.remote_ip4,
1357 self.port_in,
1358 20,
1359 data,
1360 proto)
1361 pkts.reverse()
1362 self.pg0.add_stream(pkts)
1363 self.pg_enable_capture(self.pg_interfaces)
1364 self.pg_start()
1365 frags = self.pg1.get_capture(len(pkts))
1366 if not dont_translate:
1367 p = self.reass_frags_and_verify(frags,
1368 self.nat_addr,
1369 self.pg1.remote_ip4)
1370 else:
1371 p = self.reass_frags_and_verify(frags,
1372 self.pg0.remote_ip4,
1373 self.pg1.remote_ip4)
1374 if proto != IP_PROTOS.icmp:
1375 if not dont_translate:
1376 self.assertEqual(p[layer].dport, 20)
1377 self.assertNotEqual(p[layer].sport, self.port_in)
1378 else:
1379 self.assertEqual(p[layer].sport, self.port_in)
1380 else:
1381 if not dont_translate:
1382 self.assertNotEqual(p[layer].id, self.port_in)
1383 else:
1384 self.assertEqual(p[layer].id, self.port_in)
1385 self.assertEqual(data, p[Raw].load)
1386
1387 # out2in
1388 if not dont_translate:
1389 dst_addr = self.nat_addr
1390 else:
1391 dst_addr = self.pg0.remote_ip4
1392 if proto != IP_PROTOS.icmp:
1393 sport = 20
1394 dport = p[layer].sport
1395 else:
1396 sport = p[layer].id
1397 dport = 0
1398 pkts = self.create_stream_frag(self.pg1,
1399 dst_addr,
1400 sport,
1401 dport,
1402 data,
1403 proto,
1404 echo_reply=True)
1405 pkts.reverse()
1406 self.pg1.add_stream(pkts)
1407 self.pg_enable_capture(self.pg_interfaces)
1408 self.pg_start()
1409 frags = self.pg0.get_capture(len(pkts))
1410 p = self.reass_frags_and_verify(frags,
1411 self.pg1.remote_ip4,
1412 self.pg0.remote_ip4)
1413 if proto != IP_PROTOS.icmp:
1414 self.assertEqual(p[layer].sport, 20)
1415 self.assertEqual(p[layer].dport, self.port_in)
1416 else:
1417 self.assertEqual(p[layer].id, self.port_in)
1418 self.assertEqual(data, p[Raw].load)
1419
1420 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1421 layer = self.proto2layer(proto)
1422
1423 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001424 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001425 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001426 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001427 self.port_in = random.randint(1025, 65535)
1428
1429 for i in range(2):
1430 # out2in
1431 pkts = self.create_stream_frag(self.pg0,
1432 self.server_out_addr,
1433 self.port_in,
1434 self.server_out_port,
1435 data,
1436 proto)
1437 pkts.reverse()
1438 self.pg0.add_stream(pkts)
1439 self.pg_enable_capture(self.pg_interfaces)
1440 self.pg_start()
1441 frags = self.pg1.get_capture(len(pkts))
1442 p = self.reass_frags_and_verify(frags,
1443 self.pg0.remote_ip4,
1444 self.server_in_addr)
1445 if proto != IP_PROTOS.icmp:
1446 self.assertEqual(p[layer].dport, self.server_in_port)
1447 self.assertEqual(p[layer].sport, self.port_in)
1448 self.assertEqual(p[layer].dport, self.server_in_port)
1449 else:
1450 self.assertEqual(p[layer].id, self.port_in)
1451 self.assertEqual(data, p[Raw].load)
1452
1453 # in2out
1454 if proto != IP_PROTOS.icmp:
1455 pkts = self.create_stream_frag(self.pg1,
1456 self.pg0.remote_ip4,
1457 self.server_in_port,
1458 p[layer].sport,
1459 data,
1460 proto)
1461 else:
1462 pkts = self.create_stream_frag(self.pg1,
1463 self.pg0.remote_ip4,
1464 p[layer].id,
1465 0,
1466 data,
1467 proto,
1468 echo_reply=True)
1469 pkts.reverse()
1470 self.pg1.add_stream(pkts)
1471 self.pg_enable_capture(self.pg_interfaces)
1472 self.pg_start()
1473 frags = self.pg0.get_capture(len(pkts))
1474 p = self.reass_frags_and_verify(frags,
1475 self.server_out_addr,
1476 self.pg0.remote_ip4)
1477 if proto != IP_PROTOS.icmp:
1478 self.assertEqual(p[layer].sport, self.server_out_port)
1479 self.assertEqual(p[layer].dport, self.port_in)
1480 else:
1481 self.assertEqual(p[layer].id, self.port_in)
1482 self.assertEqual(data, p[Raw].load)
1483
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001484
Matus Fabian2ba92e32017-08-21 07:05:03 -07001485class TestNAT44(MethodHolder):
1486 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001487
1488 @classmethod
1489 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001490 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001491 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001492
1493 try:
1494 cls.tcp_port_in = 6303
1495 cls.tcp_port_out = 6303
1496 cls.udp_port_in = 6304
1497 cls.udp_port_out = 6304
1498 cls.icmp_id_in = 6305
1499 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001500 cls.nat_addr = '10.0.0.3'
Matus Fabian6631e9c2017-05-24 01:52:20 -07001501 cls.ipfix_src_port = 4739
1502 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001503 cls.tcp_external_port = 80
Matus Fabian34931eb2019-02-26 09:05:23 -08001504 cls.udp_external_port = 69
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001505
Matus Fabian36ea2d62017-10-24 04:13:49 -07001506 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001507 cls.interfaces = list(cls.pg_interfaces[0:4])
1508
1509 for i in cls.interfaces:
1510 i.admin_up()
1511 i.config_ip4()
1512 i.resolve_arp()
1513
Matus Fabian6fa74c62017-06-05 05:55:48 -07001514 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001515 cls.pg0.configure_ipv4_neighbors()
1516
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001517 cls.pg1.generate_remote_hosts(1)
1518 cls.pg1.configure_ipv4_neighbors()
1519
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001520 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Ole Troan9a475372019-03-05 16:58:24 +01001521 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1522 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001523
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001524 cls.pg4._local_ip4 = "172.16.255.1"
1525 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001526 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1527 cls.pg4.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001528 cls.pg5._local_ip4 = "172.17.255.3"
1529 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001530 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001531 cls.pg5.set_table_ip4(10)
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001532 cls.pg6._local_ip4 = "172.16.255.1"
1533 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001534 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1535 cls.pg6.set_table_ip4(20)
1536 for i in cls.overlapping_interfaces:
1537 i.config_ip4()
1538 i.admin_up()
1539 i.resolve_arp()
1540
1541 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001542 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001543
Matus Fabian36ea2d62017-10-24 04:13:49 -07001544 cls.pg9.generate_remote_hosts(2)
1545 cls.pg9.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001546 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01001547 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00001548 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1549 address_length=24)
Matus Fabian36ea2d62017-10-24 04:13:49 -07001550 cls.pg9.admin_up()
1551 cls.pg9.resolve_arp()
1552 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1553 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1554 cls.pg9.resolve_arp()
1555
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001556 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001557 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001558 raise
1559
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001560 @classmethod
1561 def tearDownClass(cls):
1562 super(TestNAT44, cls).tearDownClass()
1563
Matus Fabiande886752016-12-07 03:38:19 -08001564 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001565 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001566 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001567 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001568 self.vapi.nat44_interface_add_del_feature(
1569 sw_if_index=self.pg0.sw_if_index,
1570 flags=flags, is_add=1)
1571 self.vapi.nat44_interface_add_del_feature(
1572 sw_if_index=self.pg1.sw_if_index,
1573 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08001574
1575 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08001576 tcpn = self.statistics.get_counter(
1577 '/err/nat44-in2out-slowpath/TCP packets')
1578 udpn = self.statistics.get_counter(
1579 '/err/nat44-in2out-slowpath/UDP packets')
1580 icmpn = self.statistics.get_counter(
1581 '/err/nat44-in2out-slowpath/ICMP packets')
1582 totaln = self.statistics.get_counter(
1583 '/err/nat44-in2out-slowpath/good in2out packets processed')
1584
Matus Fabiande886752016-12-07 03:38:19 -08001585 pkts = self.create_stream_in(self.pg0, self.pg1)
1586 self.pg0.add_stream(pkts)
1587 self.pg_enable_capture(self.pg_interfaces)
1588 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001589 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001590 self.verify_capture_out(capture)
1591
Matus Fabiana5e73762018-12-14 01:55:16 -08001592 err = self.statistics.get_counter(
1593 '/err/nat44-in2out-slowpath/TCP packets')
1594 self.assertEqual(err - tcpn, 1)
1595 err = self.statistics.get_counter(
1596 '/err/nat44-in2out-slowpath/UDP packets')
1597 self.assertEqual(err - udpn, 1)
1598 err = self.statistics.get_counter(
1599 '/err/nat44-in2out-slowpath/ICMP packets')
1600 self.assertEqual(err - icmpn, 1)
1601 err = self.statistics.get_counter(
1602 '/err/nat44-in2out-slowpath/good in2out packets processed')
1603 self.assertEqual(err - totaln, 3)
1604
Matus Fabiande886752016-12-07 03:38:19 -08001605 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08001606 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1607 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1608 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1609 totaln = self.statistics.get_counter(
1610 '/err/nat44-out2in/good out2in packets processed')
1611
Matus Fabiande886752016-12-07 03:38:19 -08001612 pkts = self.create_stream_out(self.pg1)
1613 self.pg1.add_stream(pkts)
1614 self.pg_enable_capture(self.pg_interfaces)
1615 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001616 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001617 self.verify_capture_in(capture, self.pg0)
1618
Matus Fabiana5e73762018-12-14 01:55:16 -08001619 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1620 self.assertEqual(err - tcpn, 1)
1621 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1622 self.assertEqual(err - udpn, 1)
1623 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1624 self.assertEqual(err - icmpn, 1)
1625 err = self.statistics.get_counter(
1626 '/err/nat44-out2in/good out2in packets processed')
1627 self.assertEqual(err - totaln, 3)
1628
Matus Fabianfd0d5082018-12-18 01:08:51 -08001629 users = self.statistics.get_counter('/nat44/total-users')
1630 self.assertEqual(users[0][0], 1)
1631 sessions = self.statistics.get_counter('/nat44/total-sessions')
1632 self.assertEqual(sessions[0][0], 3)
1633
Juraj Slobodab33f4132017-02-08 23:54:21 -08001634 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001635 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001636
Matus Fabian2ba92e32017-08-21 07:05:03 -07001637 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001638 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001639 self.vapi.nat44_interface_add_del_feature(
1640 sw_if_index=self.pg0.sw_if_index,
1641 flags=flags, is_add=1)
1642 self.vapi.nat44_interface_add_del_feature(
1643 sw_if_index=self.pg1.sw_if_index,
1644 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001645
1646 # Client side - generate traffic
1647 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1648 self.pg0.add_stream(pkts)
1649 self.pg_enable_capture(self.pg_interfaces)
1650 self.pg_start()
1651
1652 # Client side - verify ICMP type 11 packets
1653 capture = self.pg0.get_capture(len(pkts))
1654 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1655
1656 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001657 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001658
Matus Fabian2ba92e32017-08-21 07:05:03 -07001659 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001660 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001661 self.vapi.nat44_interface_add_del_feature(
1662 sw_if_index=self.pg0.sw_if_index,
1663 flags=flags, is_add=1)
1664 self.vapi.nat44_interface_add_del_feature(
1665 sw_if_index=self.pg1.sw_if_index,
1666 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001667
1668 # Client side - create sessions
1669 pkts = self.create_stream_in(self.pg0, self.pg1)
1670 self.pg0.add_stream(pkts)
1671 self.pg_enable_capture(self.pg_interfaces)
1672 self.pg_start()
1673
1674 # Server side - generate traffic
1675 capture = self.pg1.get_capture(len(pkts))
1676 self.verify_capture_out(capture)
1677 pkts = self.create_stream_out(self.pg1, ttl=1)
1678 self.pg1.add_stream(pkts)
1679 self.pg_enable_capture(self.pg_interfaces)
1680 self.pg_start()
1681
1682 # Server side - verify ICMP type 11 packets
1683 capture = self.pg1.get_capture(len(pkts))
1684 self.verify_capture_out_with_icmp_errors(capture,
1685 src_ip=self.pg1.local_ip4)
1686
1687 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001688 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001689
Matus Fabian2ba92e32017-08-21 07:05:03 -07001690 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001691 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001692 self.vapi.nat44_interface_add_del_feature(
1693 sw_if_index=self.pg0.sw_if_index,
1694 flags=flags, is_add=1)
1695 self.vapi.nat44_interface_add_del_feature(
1696 sw_if_index=self.pg1.sw_if_index,
1697 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001698
1699 # Client side - generate traffic
1700 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1701 self.pg0.add_stream(pkts)
1702 self.pg_enable_capture(self.pg_interfaces)
1703 self.pg_start()
1704
1705 # Server side - simulate ICMP type 11 response
1706 capture = self.pg1.get_capture(len(pkts))
1707 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001708 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001709 ICMP(type=11) / packet[IP] for packet in capture]
1710 self.pg1.add_stream(pkts)
1711 self.pg_enable_capture(self.pg_interfaces)
1712 self.pg_start()
1713
1714 # Client side - verify ICMP type 11 packets
1715 capture = self.pg0.get_capture(len(pkts))
1716 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1717
1718 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001719 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001720
Matus Fabian2ba92e32017-08-21 07:05:03 -07001721 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001722 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001723 self.vapi.nat44_interface_add_del_feature(
1724 sw_if_index=self.pg0.sw_if_index,
1725 flags=flags, is_add=1)
1726 self.vapi.nat44_interface_add_del_feature(
1727 sw_if_index=self.pg1.sw_if_index,
1728 is_add=1)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001729
1730 # Client side - create sessions
1731 pkts = self.create_stream_in(self.pg0, self.pg1)
1732 self.pg0.add_stream(pkts)
1733 self.pg_enable_capture(self.pg_interfaces)
1734 self.pg_start()
1735
1736 # Server side - generate traffic
1737 capture = self.pg1.get_capture(len(pkts))
1738 self.verify_capture_out(capture)
1739 pkts = self.create_stream_out(self.pg1, ttl=2)
1740 self.pg1.add_stream(pkts)
1741 self.pg_enable_capture(self.pg_interfaces)
1742 self.pg_start()
1743
1744 # Client side - simulate ICMP type 11 response
1745 capture = self.pg0.get_capture(len(pkts))
1746 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1747 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1748 ICMP(type=11) / packet[IP] for packet in capture]
1749 self.pg0.add_stream(pkts)
1750 self.pg_enable_capture(self.pg_interfaces)
1751 self.pg_start()
1752
1753 # Server side - verify ICMP type 11 packets
1754 capture = self.pg1.get_capture(len(pkts))
1755 self.verify_capture_out_with_icmp_errors(capture)
1756
Juraj Sloboda665e4822017-02-16 17:17:19 -08001757 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001758 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001759
Matus Fabian2ba92e32017-08-21 07:05:03 -07001760 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001761 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001762 self.vapi.nat44_interface_add_del_feature(
1763 sw_if_index=self.pg0.sw_if_index,
1764 flags=flags, is_add=1)
1765 self.vapi.nat44_interface_add_del_feature(
1766 sw_if_index=self.pg1.sw_if_index,
1767 is_add=1)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001768
1769 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1770 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1771 ICMP(id=self.icmp_id_out, type='echo-request'))
1772 pkts = [p]
1773 self.pg1.add_stream(pkts)
1774 self.pg_enable_capture(self.pg_interfaces)
1775 self.pg_start()
1776 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001777 packet = capture[0]
1778 try:
1779 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1780 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1781 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1782 self.assertEqual(packet[ICMP].type, 0) # echo reply
1783 except:
1784 self.logger.error(ppp("Unexpected or invalid packet "
1785 "(outside network):", packet))
1786 raise
1787
Juraj Slobodad3677682017-04-14 03:24:45 +02001788 def test_ping_internal_host_from_outside(self):
1789 """ Ping internal host from outside network """
1790
Matus Fabian2ba92e32017-08-21 07:05:03 -07001791 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001792 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001793 self.vapi.nat44_interface_add_del_feature(
1794 sw_if_index=self.pg0.sw_if_index,
1795 flags=flags, is_add=1)
1796 self.vapi.nat44_interface_add_del_feature(
1797 sw_if_index=self.pg1.sw_if_index,
1798 is_add=1)
Juraj Slobodad3677682017-04-14 03:24:45 +02001799
1800 # out2in
1801 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001802 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001803 ICMP(id=self.icmp_id_out, type='echo-request'))
1804 self.pg1.add_stream(pkt)
1805 self.pg_enable_capture(self.pg_interfaces)
1806 self.pg_start()
1807 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001808 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001809 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1810
1811 # in2out
1812 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1813 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1814 ICMP(id=self.icmp_id_in, type='echo-reply'))
1815 self.pg0.add_stream(pkt)
1816 self.pg_enable_capture(self.pg_interfaces)
1817 self.pg_start()
1818 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001819 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001820 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1821
Matus Fabianc79396e2018-07-23 00:05:22 -07001822 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001823 """ NAT44 forwarding test """
1824
Filip Vargadd1e3e72019-04-15 18:52:43 +02001825 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001826 self.vapi.nat44_interface_add_del_feature(
1827 sw_if_index=self.pg0.sw_if_index,
1828 flags=flags, is_add=1)
1829 self.vapi.nat44_interface_add_del_feature(
1830 sw_if_index=self.pg1.sw_if_index,
1831 is_add=1)
1832 self.vapi.nat44_forwarding_enable_disable(enable=1)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001833
1834 real_ip = self.pg0.remote_ip4n
Filip Vargadd1e3e72019-04-15 18:52:43 +02001835 alias_ip = self.nat_addr
1836 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02001837 self.vapi.nat44_add_del_static_mapping(is_add=1,
1838 local_ip_address=real_ip,
1839 external_ip_address=alias_ip,
1840 external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +02001841 flags=flags)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001842
1843 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001844 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001845
1846 pkts = self.create_stream_out(self.pg1)
1847 self.pg1.add_stream(pkts)
1848 self.pg_enable_capture(self.pg_interfaces)
1849 self.pg_start()
1850 capture = self.pg0.get_capture(len(pkts))
1851 self.verify_capture_in(capture, self.pg0)
1852
1853 pkts = self.create_stream_in(self.pg0, self.pg1)
1854 self.pg0.add_stream(pkts)
1855 self.pg_enable_capture(self.pg_interfaces)
1856 self.pg_start()
1857 capture = self.pg1.get_capture(len(pkts))
1858 self.verify_capture_out(capture, same_port=True)
1859
Matus Fabianc79396e2018-07-23 00:05:22 -07001860 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001861
1862 host0 = self.pg0.remote_hosts[0]
1863 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1864 try:
1865 pkts = self.create_stream_out(self.pg1,
1866 dst_ip=self.pg0.remote_ip4,
1867 use_inside_ports=True)
1868 self.pg1.add_stream(pkts)
1869 self.pg_enable_capture(self.pg_interfaces)
1870 self.pg_start()
1871 capture = self.pg0.get_capture(len(pkts))
1872 self.verify_capture_in(capture, self.pg0)
1873
1874 pkts = self.create_stream_in(self.pg0, self.pg1)
1875 self.pg0.add_stream(pkts)
1876 self.pg_enable_capture(self.pg_interfaces)
1877 self.pg_start()
1878 capture = self.pg1.get_capture(len(pkts))
1879 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1880 same_port=True)
1881 finally:
1882 self.pg0.remote_hosts[0] = host0
1883
1884 finally:
Filip Vargaf4749ca2019-04-25 14:55:32 +02001885 self.vapi.nat44_forwarding_enable_disable(enable=0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001886 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02001887 self.vapi.nat44_add_del_static_mapping(
1888 is_add=0,
1889 local_ip_address=real_ip,
1890 external_ip_address=alias_ip,
1891 external_sw_if_index=0xFFFFFFFF,
1892 flags=flags)
Juraj Sloboda7b929792017-11-23 13:20:48 +01001893
Matus Fabiande886752016-12-07 03:38:19 -08001894 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001895 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001896
1897 nat_ip = "10.0.0.10"
1898 self.tcp_port_out = 6303
1899 self.udp_port_out = 6304
1900 self.icmp_id_out = 6305
1901
Matus Fabian2ba92e32017-08-21 07:05:03 -07001902 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001903 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001904 self.vapi.nat44_interface_add_del_feature(
1905 sw_if_index=self.pg0.sw_if_index,
1906 flags=flags, is_add=1)
1907 self.vapi.nat44_interface_add_del_feature(
1908 sw_if_index=self.pg1.sw_if_index,
1909 is_add=1)
Matus Fabian5f224992018-01-25 21:59:16 -08001910 sm = self.vapi.nat44_static_mapping_dump()
1911 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001912 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
Matus Fabian9dba7812018-01-31 01:13:23 -08001913 self.assertEqual(sm[0].protocol, 0)
1914 self.assertEqual(sm[0].local_port, 0)
1915 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001916
1917 # in2out
1918 pkts = self.create_stream_in(self.pg0, self.pg1)
1919 self.pg0.add_stream(pkts)
1920 self.pg_enable_capture(self.pg_interfaces)
1921 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001922 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001923 self.verify_capture_out(capture, nat_ip, True)
1924
1925 # out2in
1926 pkts = self.create_stream_out(self.pg1, nat_ip)
1927 self.pg1.add_stream(pkts)
1928 self.pg_enable_capture(self.pg_interfaces)
1929 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001930 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001931 self.verify_capture_in(capture, self.pg0)
1932
1933 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001934 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001935
1936 nat_ip = "10.0.0.20"
1937 self.tcp_port_out = 6303
1938 self.udp_port_out = 6304
1939 self.icmp_id_out = 6305
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001940 tag = b"testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001941
Matus Fabian5f224992018-01-25 21:59:16 -08001942 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001943 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001944 self.vapi.nat44_interface_add_del_feature(
1945 sw_if_index=self.pg0.sw_if_index,
1946 flags=flags, is_add=1)
1947 self.vapi.nat44_interface_add_del_feature(
1948 sw_if_index=self.pg1.sw_if_index,
1949 is_add=1)
Matus Fabian5f224992018-01-25 21:59:16 -08001950 sm = self.vapi.nat44_static_mapping_dump()
1951 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001952 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001953
1954 # out2in
1955 pkts = self.create_stream_out(self.pg1, nat_ip)
1956 self.pg1.add_stream(pkts)
1957 self.pg_enable_capture(self.pg_interfaces)
1958 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001959 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001960 self.verify_capture_in(capture, self.pg0)
1961
1962 # in2out
1963 pkts = self.create_stream_in(self.pg0, self.pg1)
1964 self.pg0.add_stream(pkts)
1965 self.pg_enable_capture(self.pg_interfaces)
1966 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001967 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001968 self.verify_capture_out(capture, nat_ip, True)
1969
1970 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001971 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001972
1973 self.tcp_port_out = 3606
1974 self.udp_port_out = 3607
1975 self.icmp_id_out = 3608
1976
Matus Fabian2ba92e32017-08-21 07:05:03 -07001977 self.nat44_add_address(self.nat_addr)
1978 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1979 self.tcp_port_in, self.tcp_port_out,
1980 proto=IP_PROTOS.tcp)
1981 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1982 self.udp_port_in, self.udp_port_out,
1983 proto=IP_PROTOS.udp)
1984 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1985 self.icmp_id_in, self.icmp_id_out,
1986 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02001987 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02001988 self.vapi.nat44_interface_add_del_feature(
1989 sw_if_index=self.pg0.sw_if_index,
1990 flags=flags, is_add=1)
1991 self.vapi.nat44_interface_add_del_feature(
1992 sw_if_index=self.pg1.sw_if_index,
1993 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08001994
1995 # in2out
1996 pkts = self.create_stream_in(self.pg0, self.pg1)
1997 self.pg0.add_stream(pkts)
1998 self.pg_enable_capture(self.pg_interfaces)
1999 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002000 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002001 self.verify_capture_out(capture)
2002
2003 # out2in
2004 pkts = self.create_stream_out(self.pg1)
2005 self.pg1.add_stream(pkts)
2006 self.pg_enable_capture(self.pg_interfaces)
2007 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002008 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002009 self.verify_capture_in(capture, self.pg0)
2010
2011 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002012 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08002013
2014 self.tcp_port_out = 30606
2015 self.udp_port_out = 30607
2016 self.icmp_id_out = 30608
2017
Matus Fabian2ba92e32017-08-21 07:05:03 -07002018 self.nat44_add_address(self.nat_addr)
2019 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2020 self.tcp_port_in, self.tcp_port_out,
2021 proto=IP_PROTOS.tcp)
2022 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2023 self.udp_port_in, self.udp_port_out,
2024 proto=IP_PROTOS.udp)
2025 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2026 self.icmp_id_in, self.icmp_id_out,
2027 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002028 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002029 self.vapi.nat44_interface_add_del_feature(
2030 sw_if_index=self.pg0.sw_if_index,
2031 flags=flags, is_add=1)
2032 self.vapi.nat44_interface_add_del_feature(
2033 sw_if_index=self.pg1.sw_if_index,
2034 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08002035
2036 # out2in
2037 pkts = self.create_stream_out(self.pg1)
2038 self.pg1.add_stream(pkts)
2039 self.pg_enable_capture(self.pg_interfaces)
2040 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002041 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002042 self.verify_capture_in(capture, self.pg0)
2043
2044 # in2out
2045 pkts = self.create_stream_in(self.pg0, self.pg1)
2046 self.pg0.add_stream(pkts)
2047 self.pg_enable_capture(self.pg_interfaces)
2048 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002049 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002050 self.verify_capture_out(capture)
2051
2052 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002053 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08002054
2055 nat_ip1 = "10.0.0.30"
2056 nat_ip2 = "10.0.0.40"
2057 self.tcp_port_out = 6303
2058 self.udp_port_out = 6304
2059 self.icmp_id_out = 6305
2060
Matus Fabian2ba92e32017-08-21 07:05:03 -07002061 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2062 vrf_id=10)
2063 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2064 vrf_id=10)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002065 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002066 self.vapi.nat44_interface_add_del_feature(
2067 sw_if_index=self.pg3.sw_if_index,
2068 is_add=1)
2069 self.vapi.nat44_interface_add_del_feature(
2070 sw_if_index=self.pg0.sw_if_index,
2071 flags=flags, is_add=1)
2072 self.vapi.nat44_interface_add_del_feature(
2073 sw_if_index=self.pg4.sw_if_index,
2074 flags=flags, is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08002075
Matus Fabian2ba92e32017-08-21 07:05:03 -07002076 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002077 pkts = self.create_stream_in(self.pg4, self.pg3)
2078 self.pg4.add_stream(pkts)
2079 self.pg_enable_capture(self.pg_interfaces)
2080 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002081 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002082 self.verify_capture_out(capture, nat_ip1, True)
2083
Matus Fabian2ba92e32017-08-21 07:05:03 -07002084 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002085 # are dropped)
2086 pkts = self.create_stream_in(self.pg0, self.pg3)
2087 self.pg0.add_stream(pkts)
2088 self.pg_enable_capture(self.pg_interfaces)
2089 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002090 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002091
Matus Fabianb793d092018-01-31 05:50:21 -08002092 def test_dynamic_to_static(self):
2093 """ Switch from dynamic translation to 1:1NAT """
2094 nat_ip = "10.0.0.10"
2095 self.tcp_port_out = 6303
2096 self.udp_port_out = 6304
2097 self.icmp_id_out = 6305
2098
2099 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002100 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002101 self.vapi.nat44_interface_add_del_feature(
2102 sw_if_index=self.pg0.sw_if_index,
2103 flags=flags, is_add=1)
2104 self.vapi.nat44_interface_add_del_feature(
2105 sw_if_index=self.pg1.sw_if_index,
2106 is_add=1)
Matus Fabianb793d092018-01-31 05:50:21 -08002107
2108 # dynamic
2109 pkts = self.create_stream_in(self.pg0, self.pg1)
2110 self.pg0.add_stream(pkts)
2111 self.pg_enable_capture(self.pg_interfaces)
2112 self.pg_start()
2113 capture = self.pg1.get_capture(len(pkts))
2114 self.verify_capture_out(capture)
2115
2116 # 1:1NAT
2117 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2118 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2119 self.assertEqual(len(sessions), 0)
2120 pkts = self.create_stream_in(self.pg0, self.pg1)
2121 self.pg0.add_stream(pkts)
2122 self.pg_enable_capture(self.pg_interfaces)
2123 self.pg_start()
2124 capture = self.pg1.get_capture(len(pkts))
2125 self.verify_capture_out(capture, nat_ip, True)
2126
Matus Fabianab7a8052017-11-28 04:29:41 -08002127 def test_identity_nat(self):
2128 """ Identity NAT """
Filip Vargadd1e3e72019-04-15 18:52:43 +02002129 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02002130 self.vapi.nat44_add_del_identity_mapping(
2131 ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
2132 flags=flags, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002133 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002134 self.vapi.nat44_interface_add_del_feature(
2135 sw_if_index=self.pg0.sw_if_index,
2136 flags=flags, is_add=1)
2137 self.vapi.nat44_interface_add_del_feature(
2138 sw_if_index=self.pg1.sw_if_index,
2139 is_add=1)
Matus Fabianab7a8052017-11-28 04:29:41 -08002140
2141 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2142 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2143 TCP(sport=12345, dport=56789))
2144 self.pg1.add_stream(p)
2145 self.pg_enable_capture(self.pg_interfaces)
2146 self.pg_start()
2147 capture = self.pg0.get_capture(1)
2148 p = capture[0]
2149 try:
2150 ip = p[IP]
2151 tcp = p[TCP]
2152 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2153 self.assertEqual(ip.src, self.pg1.remote_ip4)
2154 self.assertEqual(tcp.dport, 56789)
2155 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002156 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002157 except:
2158 self.logger.error(ppp("Unexpected or invalid packet:", p))
2159 raise
2160
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002161 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2162 self.assertEqual(len(sessions), 0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002163 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02002164 self.vapi.nat44_add_del_identity_mapping(
2165 ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
2166 flags=flags, vrf_id=1, is_add=1)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002167 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2168 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002169
Matus Fabiande886752016-12-07 03:38:19 -08002170 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002171 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002172
Matus Fabian2ba92e32017-08-21 07:05:03 -07002173 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002174 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002175 self.vapi.nat44_interface_add_del_feature(
2176 sw_if_index=self.pg0.sw_if_index,
2177 flags=flags, is_add=1)
2178 self.vapi.nat44_interface_add_del_feature(
2179 sw_if_index=self.pg1.sw_if_index,
2180 flags=flags, is_add=1)
2181 self.vapi.nat44_interface_add_del_feature(
2182 sw_if_index=self.pg3.sw_if_index,
2183 is_add=1)
Matus Fabiande886752016-12-07 03:38:19 -08002184
Matus Fabian2ba92e32017-08-21 07:05:03 -07002185 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002186 pkts = self.create_stream_in(self.pg0, self.pg1)
2187 self.pg0.add_stream(pkts)
2188 self.pg_enable_capture(self.pg_interfaces)
2189 self.pg_start()
2190 capture = self.pg1.get_capture(len(pkts))
2191 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2192
Matus Fabian2ba92e32017-08-21 07:05:03 -07002193 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002194 pkts = self.create_stream_in(self.pg0, self.pg2)
2195 self.pg0.add_stream(pkts)
2196 self.pg_enable_capture(self.pg_interfaces)
2197 self.pg_start()
2198 capture = self.pg2.get_capture(len(pkts))
2199 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2200
Matus Fabiande886752016-12-07 03:38:19 -08002201 # in2out 1st interface
2202 pkts = self.create_stream_in(self.pg0, self.pg3)
2203 self.pg0.add_stream(pkts)
2204 self.pg_enable_capture(self.pg_interfaces)
2205 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002206 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002207 self.verify_capture_out(capture)
2208
2209 # out2in 1st interface
2210 pkts = self.create_stream_out(self.pg3)
2211 self.pg3.add_stream(pkts)
2212 self.pg_enable_capture(self.pg_interfaces)
2213 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002214 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002215 self.verify_capture_in(capture, self.pg0)
2216
2217 # in2out 2nd interface
2218 pkts = self.create_stream_in(self.pg1, self.pg3)
2219 self.pg1.add_stream(pkts)
2220 self.pg_enable_capture(self.pg_interfaces)
2221 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002222 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002223 self.verify_capture_out(capture)
2224
2225 # out2in 2nd interface
2226 pkts = self.create_stream_out(self.pg3)
2227 self.pg3.add_stream(pkts)
2228 self.pg_enable_capture(self.pg_interfaces)
2229 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002230 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002231 self.verify_capture_in(capture, self.pg1)
2232
Matus Fabiande886752016-12-07 03:38:19 -08002233 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002234 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002235
Matus Fabian675a69c2017-01-18 01:46:01 -08002236 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002237 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002238 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002239 self.vapi.nat44_interface_add_del_feature(
2240 sw_if_index=self.pg3.sw_if_index,
2241 is_add=1)
2242 self.vapi.nat44_interface_add_del_feature(
2243 sw_if_index=self.pg4.sw_if_index,
2244 flags=flags, is_add=1)
2245 self.vapi.nat44_interface_add_del_feature(
2246 sw_if_index=self.pg5.sw_if_index,
2247 flags=flags, is_add=1)
2248 self.vapi.nat44_interface_add_del_feature(
2249 sw_if_index=self.pg6.sw_if_index,
2250 flags=flags, is_add=1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002251 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2252 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002253
Matus Fabian2ba92e32017-08-21 07:05:03 -07002254 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002255 pkts = self.create_stream_in(self.pg4, self.pg5)
2256 self.pg4.add_stream(pkts)
2257 self.pg_enable_capture(self.pg_interfaces)
2258 self.pg_start()
2259 capture = self.pg5.get_capture(len(pkts))
2260 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2261
Matus Fabian2ba92e32017-08-21 07:05:03 -07002262 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002263 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2264 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2265 TCP(sport=1234, dport=5678))
2266 self.pg4.add_stream(p)
2267 self.pg_enable_capture(self.pg_interfaces)
2268 self.pg_start()
2269 capture = self.pg6.get_capture(1)
2270 p = capture[0]
2271 try:
2272 ip = p[IP]
2273 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002274 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002275 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2276 self.assertNotEqual(tcp.sport, 1234)
2277 self.assertEqual(tcp.dport, 5678)
2278 except:
2279 self.logger.error(ppp("Unexpected or invalid packet:", p))
2280 raise
Matus Fabiande886752016-12-07 03:38:19 -08002281
2282 # in2out 1st interface
2283 pkts = self.create_stream_in(self.pg4, self.pg3)
2284 self.pg4.add_stream(pkts)
2285 self.pg_enable_capture(self.pg_interfaces)
2286 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002287 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002288 self.verify_capture_out(capture)
2289
2290 # out2in 1st interface
2291 pkts = self.create_stream_out(self.pg3)
2292 self.pg3.add_stream(pkts)
2293 self.pg_enable_capture(self.pg_interfaces)
2294 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002295 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002296 self.verify_capture_in(capture, self.pg4)
2297
2298 # in2out 2nd interface
2299 pkts = self.create_stream_in(self.pg5, self.pg3)
2300 self.pg5.add_stream(pkts)
2301 self.pg_enable_capture(self.pg_interfaces)
2302 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002303 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002304 self.verify_capture_out(capture)
2305
2306 # out2in 2nd interface
2307 pkts = self.create_stream_out(self.pg3)
2308 self.pg3.add_stream(pkts)
2309 self.pg_enable_capture(self.pg_interfaces)
2310 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002311 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002312 self.verify_capture_in(capture, self.pg5)
2313
magalik23caa882017-02-08 23:25:45 -08002314 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002315 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002316 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002317 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002318 self.assertEqual(len(sessions), 3)
2319 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002320 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2321 self.assertEqual(str(session.inside_ip_address),
2322 self.pg5.remote_ip4)
magalik23caa882017-02-08 23:25:45 -08002323 self.assertEqual(session.outside_ip_address,
2324 addresses[0].ip_address)
2325 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2326 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2327 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2328 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2329 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2330 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2331 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2332 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2333 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2334
Matus Fabiande886752016-12-07 03:38:19 -08002335 # in2out 3rd interface
2336 pkts = self.create_stream_in(self.pg6, self.pg3)
2337 self.pg6.add_stream(pkts)
2338 self.pg_enable_capture(self.pg_interfaces)
2339 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002340 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002341 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002342
2343 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002344 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002345 self.pg3.add_stream(pkts)
2346 self.pg_enable_capture(self.pg_interfaces)
2347 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002348 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002349 self.verify_capture_in(capture, self.pg6)
2350
magalik23caa882017-02-08 23:25:45 -08002351 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002352 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002353 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002354 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002355 self.assertEqual(len(addresses), 1)
2356 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002357 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2358 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002359 for session in sessions:
2360 self.assertEqual(user.ip_address, session.inside_ip_address)
2361 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2362 self.assertTrue(session.protocol in
2363 [IP_PROTOS.tcp, IP_PROTOS.udp,
2364 IP_PROTOS.icmp])
Filip Vargadd1e3e72019-04-15 18:52:43 +02002365 self.assertFalse(session.flags &
2366 self.config_flags.NAT_IS_EXT_HOST_VALID)
magalik23caa882017-02-08 23:25:45 -08002367
2368 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002369 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002370 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002371 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002372 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2373 self.assertEqual(str(session.inside_ip_address),
2374 self.pg4.remote_ip4)
magalik23caa882017-02-08 23:25:45 -08002375 self.assertEqual(session.outside_ip_address,
2376 addresses[0].ip_address)
2377
2378 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002379 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002380 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002381 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002382 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2383 self.assertEqual(str(session.inside_ip_address),
2384 self.pg6.remote_ip4)
2385 self.assertEqual(str(session.outside_ip_address),
2386 static_nat_ip)
magalik23caa882017-02-08 23:25:45 -08002387 self.assertTrue(session.inside_port in
2388 [self.tcp_port_in, self.udp_port_in,
2389 self.icmp_id_in])
2390
Matus Fabianf78a70d2016-12-12 04:30:39 -08002391 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002392 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002393
2394 host = self.pg0.remote_hosts[0]
2395 server = self.pg0.remote_hosts[1]
2396 host_in_port = 1234
2397 host_out_port = 0
2398 server_in_port = 5678
2399 server_out_port = 8765
2400
Matus Fabian2ba92e32017-08-21 07:05:03 -07002401 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002402 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002403 self.vapi.nat44_interface_add_del_feature(
2404 sw_if_index=self.pg0.sw_if_index,
2405 flags=flags, is_add=1)
2406 self.vapi.nat44_interface_add_del_feature(
2407 sw_if_index=self.pg1.sw_if_index,
2408 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002409
Matus Fabianf78a70d2016-12-12 04:30:39 -08002410 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002411 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2412 server_in_port, server_out_port,
2413 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002414
2415 # send packet from host to server
2416 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002417 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002418 TCP(sport=host_in_port, dport=server_out_port))
2419 self.pg0.add_stream(p)
2420 self.pg_enable_capture(self.pg_interfaces)
2421 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002422 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002423 p = capture[0]
2424 try:
2425 ip = p[IP]
2426 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002427 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002428 self.assertEqual(ip.dst, server.ip4)
2429 self.assertNotEqual(tcp.sport, host_in_port)
2430 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002431 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002432 host_out_port = tcp.sport
2433 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002434 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002435 raise
2436
2437 # send reply from server to host
2438 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002439 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002440 TCP(sport=server_in_port, dport=host_out_port))
2441 self.pg0.add_stream(p)
2442 self.pg_enable_capture(self.pg_interfaces)
2443 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002444 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002445 p = capture[0]
2446 try:
2447 ip = p[IP]
2448 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002449 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002450 self.assertEqual(ip.dst, host.ip4)
2451 self.assertEqual(tcp.sport, server_out_port)
2452 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002453 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002454 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002455 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002456 raise
2457
Matus Fabian6fa74c62017-06-05 05:55:48 -07002458 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002459 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002460
2461 server1_nat_ip = "10.0.0.10"
2462 server2_nat_ip = "10.0.0.11"
2463 host = self.pg0.remote_hosts[0]
2464 server1 = self.pg0.remote_hosts[1]
2465 server2 = self.pg0.remote_hosts[2]
2466 server_tcp_port = 22
2467 server_udp_port = 20
2468
Matus Fabian2ba92e32017-08-21 07:05:03 -07002469 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002470 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002471 self.vapi.nat44_interface_add_del_feature(
2472 sw_if_index=self.pg0.sw_if_index,
2473 flags=flags, is_add=1)
2474 self.vapi.nat44_interface_add_del_feature(
2475 sw_if_index=self.pg1.sw_if_index,
2476 is_add=1)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002477
2478 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002479 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2480 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002481
2482 # host to server1
2483 pkts = []
2484 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2485 IP(src=host.ip4, dst=server1_nat_ip) /
2486 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2487 pkts.append(p)
2488 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2489 IP(src=host.ip4, dst=server1_nat_ip) /
2490 UDP(sport=self.udp_port_in, dport=server_udp_port))
2491 pkts.append(p)
2492 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2493 IP(src=host.ip4, dst=server1_nat_ip) /
2494 ICMP(id=self.icmp_id_in, type='echo-request'))
2495 pkts.append(p)
2496 self.pg0.add_stream(pkts)
2497 self.pg_enable_capture(self.pg_interfaces)
2498 self.pg_start()
2499 capture = self.pg0.get_capture(len(pkts))
2500 for packet in capture:
2501 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002502 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002503 self.assertEqual(packet[IP].dst, server1.ip4)
2504 if packet.haslayer(TCP):
2505 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2506 self.assertEqual(packet[TCP].dport, server_tcp_port)
2507 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002508 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002509 elif packet.haslayer(UDP):
2510 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2511 self.assertEqual(packet[UDP].dport, server_udp_port)
2512 self.udp_port_out = packet[UDP].sport
2513 else:
2514 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2515 self.icmp_id_out = packet[ICMP].id
2516 except:
2517 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2518 raise
2519
2520 # server1 to host
2521 pkts = []
2522 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002523 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002524 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2525 pkts.append(p)
2526 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002527 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002528 UDP(sport=server_udp_port, dport=self.udp_port_out))
2529 pkts.append(p)
2530 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002531 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002532 ICMP(id=self.icmp_id_out, type='echo-reply'))
2533 pkts.append(p)
2534 self.pg0.add_stream(pkts)
2535 self.pg_enable_capture(self.pg_interfaces)
2536 self.pg_start()
2537 capture = self.pg0.get_capture(len(pkts))
2538 for packet in capture:
2539 try:
2540 self.assertEqual(packet[IP].src, server1_nat_ip)
2541 self.assertEqual(packet[IP].dst, host.ip4)
2542 if packet.haslayer(TCP):
2543 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2544 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002545 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002546 elif packet.haslayer(UDP):
2547 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2548 self.assertEqual(packet[UDP].sport, server_udp_port)
2549 else:
2550 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2551 except:
2552 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2553 raise
2554
2555 # server2 to server1
2556 pkts = []
2557 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2558 IP(src=server2.ip4, dst=server1_nat_ip) /
2559 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2560 pkts.append(p)
2561 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2562 IP(src=server2.ip4, dst=server1_nat_ip) /
2563 UDP(sport=self.udp_port_in, dport=server_udp_port))
2564 pkts.append(p)
2565 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2566 IP(src=server2.ip4, dst=server1_nat_ip) /
2567 ICMP(id=self.icmp_id_in, type='echo-request'))
2568 pkts.append(p)
2569 self.pg0.add_stream(pkts)
2570 self.pg_enable_capture(self.pg_interfaces)
2571 self.pg_start()
2572 capture = self.pg0.get_capture(len(pkts))
2573 for packet in capture:
2574 try:
2575 self.assertEqual(packet[IP].src, server2_nat_ip)
2576 self.assertEqual(packet[IP].dst, server1.ip4)
2577 if packet.haslayer(TCP):
2578 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2579 self.assertEqual(packet[TCP].dport, server_tcp_port)
2580 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002581 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002582 elif packet.haslayer(UDP):
2583 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2584 self.assertEqual(packet[UDP].dport, server_udp_port)
2585 self.udp_port_out = packet[UDP].sport
2586 else:
2587 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2588 self.icmp_id_out = packet[ICMP].id
2589 except:
2590 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2591 raise
2592
2593 # server1 to server2
2594 pkts = []
2595 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2596 IP(src=server1.ip4, dst=server2_nat_ip) /
2597 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2598 pkts.append(p)
2599 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2600 IP(src=server1.ip4, dst=server2_nat_ip) /
2601 UDP(sport=server_udp_port, dport=self.udp_port_out))
2602 pkts.append(p)
2603 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2604 IP(src=server1.ip4, dst=server2_nat_ip) /
2605 ICMP(id=self.icmp_id_out, type='echo-reply'))
2606 pkts.append(p)
2607 self.pg0.add_stream(pkts)
2608 self.pg_enable_capture(self.pg_interfaces)
2609 self.pg_start()
2610 capture = self.pg0.get_capture(len(pkts))
2611 for packet in capture:
2612 try:
2613 self.assertEqual(packet[IP].src, server1_nat_ip)
2614 self.assertEqual(packet[IP].dst, server2.ip4)
2615 if packet.haslayer(TCP):
2616 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2617 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002618 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002619 elif packet.haslayer(UDP):
2620 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2621 self.assertEqual(packet[UDP].sport, server_udp_port)
2622 else:
2623 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2624 except:
2625 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2626 raise
2627
Matus Fabian9902fcd2016-12-21 23:58:46 -08002628 def test_max_translations_per_user(self):
2629 """ MAX translations per user - recycle the least recently used """
2630
Matus Fabian2ba92e32017-08-21 07:05:03 -07002631 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002632 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002633 self.vapi.nat44_interface_add_del_feature(
2634 sw_if_index=self.pg0.sw_if_index,
2635 flags=flags, is_add=1)
2636 self.vapi.nat44_interface_add_del_feature(
2637 sw_if_index=self.pg1.sw_if_index,
2638 is_add=1)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002639
2640 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002641 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002642
2643 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002644 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002645 pkts = []
2646 for port in range(0, pkts_num):
2647 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2648 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2649 TCP(sport=1025 + port))
2650 pkts.append(p)
2651 self.pg0.add_stream(pkts)
2652 self.pg_enable_capture(self.pg_interfaces)
2653 self.pg_start()
2654
2655 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002656 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002657
Matus Fabian132dc492018-05-09 04:51:03 -07002658 users = self.vapi.nat44_user_dump()
2659 for user in users:
2660 if user.ip_address == self.pg0.remote_ip4n:
2661 self.assertEqual(user.nsessions,
2662 nat44_config.max_translations_per_user)
2663 self.assertEqual(user.nstaticsessions, 0)
2664
2665 tcp_port = 22
2666 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2667 tcp_port, tcp_port,
2668 proto=IP_PROTOS.tcp)
2669 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2670 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2671 TCP(sport=tcp_port))
2672 self.pg0.add_stream(p)
2673 self.pg_enable_capture(self.pg_interfaces)
2674 self.pg_start()
2675 self.pg1.get_capture(1)
2676 users = self.vapi.nat44_user_dump()
2677 for user in users:
2678 if user.ip_address == self.pg0.remote_ip4n:
2679 self.assertEqual(user.nsessions,
2680 nat44_config.max_translations_per_user - 1)
2681 self.assertEqual(user.nstaticsessions, 1)
2682
Matus Fabian8bf68e82017-01-12 04:24:35 -08002683 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002684 """ Acquire NAT44 addresses from interface """
Filip Vargaf4749ca2019-04-25 14:55:32 +02002685 self.vapi.nat44_add_del_interface_addr(
2686 is_add=1,
2687 sw_if_index=self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002688
2689 # no address in NAT pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002690 addresses = self.vapi.nat44_address_dump()
2691 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002692
2693 # configure interface address and check NAT address pool
2694 self.pg7.config_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002695 addresses = self.vapi.nat44_address_dump()
2696 self.assertEqual(1, len(addresses))
Filip Vargadd1e3e72019-04-15 18:52:43 +02002697 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002698
2699 # remove interface address and check NAT address pool
2700 self.pg7.unconfig_ip4()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002701 addresses = self.vapi.nat44_address_dump()
2702 self.assertEqual(0, len(addresses))
Matus Fabian8bf68e82017-01-12 04:24:35 -08002703
Matus Fabian36532bd2017-01-23 23:42:28 -08002704 def test_interface_addr_static_mapping(self):
2705 """ Static mapping with addresses from interface """
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002706 tag = b"testTAG"
Matus Fabian5f224992018-01-25 21:59:16 -08002707
Filip Vargaf4749ca2019-04-25 14:55:32 +02002708 self.vapi.nat44_add_del_interface_addr(
2709 is_add=1,
2710 sw_if_index=self.pg7.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002711 self.nat44_add_static_mapping(
2712 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002713 external_sw_if_index=self.pg7.sw_if_index,
2714 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002715
Matus Fabiane22e5462017-02-14 23:33:43 -08002716 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002717 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002718 self.assertEqual(1, len(static_mappings))
2719 self.assertEqual(self.pg7.sw_if_index,
2720 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002721 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002722
2723 # configure interface address and check static mappings
2724 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002725 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002726 self.assertEqual(2, len(static_mappings))
2727 resolved = False
2728 for sm in static_mappings:
2729 if sm.external_sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002730 self.assertEqual(str(sm.external_ip_address),
2731 self.pg7.local_ip4)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002732 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002733 resolved = True
2734 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002735
2736 # remove interface address and check static mappings
2737 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002738 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002739 self.assertEqual(1, len(static_mappings))
2740 self.assertEqual(self.pg7.sw_if_index,
2741 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002742 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002743
2744 # configure interface address again and check static mappings
2745 self.pg7.config_ip4()
2746 static_mappings = self.vapi.nat44_static_mapping_dump()
2747 self.assertEqual(2, len(static_mappings))
2748 resolved = False
2749 for sm in static_mappings:
2750 if sm.external_sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002751 self.assertEqual(str(sm.external_ip_address),
2752 self.pg7.local_ip4)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002753 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002754 resolved = True
2755 self.assertTrue(resolved)
2756
2757 # remove static mapping
2758 self.nat44_add_static_mapping(
2759 '1.2.3.4',
2760 external_sw_if_index=self.pg7.sw_if_index,
2761 tag=tag,
2762 is_add=0)
2763 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002764 self.assertEqual(0, len(static_mappings))
2765
Matus Fabianab7a8052017-11-28 04:29:41 -08002766 def test_interface_addr_identity_nat(self):
2767 """ Identity NAT with addresses from interface """
2768
2769 port = 53053
Filip Vargaf4749ca2019-04-25 14:55:32 +02002770 self.vapi.nat44_add_del_interface_addr(
2771 is_add=1,
2772 sw_if_index=self.pg7.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002773 self.vapi.nat44_add_del_identity_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +02002774 ip_address=b'0',
Matus Fabianab7a8052017-11-28 04:29:41 -08002775 sw_if_index=self.pg7.sw_if_index,
2776 port=port,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002777 protocol=IP_PROTOS.tcp,
2778 is_add=1)
Matus Fabianab7a8052017-11-28 04:29:41 -08002779
2780 # identity mappings with external interface
2781 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2782 self.assertEqual(1, len(identity_mappings))
2783 self.assertEqual(self.pg7.sw_if_index,
2784 identity_mappings[0].sw_if_index)
2785
2786 # configure interface address and check identity mappings
2787 self.pg7.config_ip4()
2788 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002789 resolved = False
2790 self.assertEqual(2, len(identity_mappings))
2791 for sm in identity_mappings:
2792 if sm.sw_if_index == 0xFFFFFFFF:
Filip Vargadd1e3e72019-04-15 18:52:43 +02002793 self.assertEqual(str(identity_mappings[0].ip_address),
2794 self.pg7.local_ip4)
Matus Fabianea2600a2018-03-28 04:06:26 -07002795 self.assertEqual(port, identity_mappings[0].port)
2796 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2797 resolved = True
2798 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002799
2800 # remove interface address and check identity mappings
2801 self.pg7.unconfig_ip4()
2802 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002803 self.assertEqual(1, len(identity_mappings))
2804 self.assertEqual(self.pg7.sw_if_index,
2805 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002806
Matus Fabianeea28d72017-01-13 04:15:54 -08002807 def test_ipfix_nat44_sess(self):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002808 """ IPFIX logging NAT44 session created/deleted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002809 self.ipfix_domain_id = 10
2810 self.ipfix_src_port = 20202
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002811 collector_port = 30303
Matus Fabian6631e9c2017-05-24 01:52:20 -07002812 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002813 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002814 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002815 self.vapi.nat44_interface_add_del_feature(
2816 sw_if_index=self.pg0.sw_if_index,
2817 flags=flags, is_add=1)
2818 self.vapi.nat44_interface_add_del_feature(
2819 sw_if_index=self.pg1.sw_if_index,
2820 is_add=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002821 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2822 src_address=self.pg3.local_ip4n,
2823 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002824 template_interval=10,
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002825 collector_port=collector_port)
Ole Troane1ade682019-03-04 23:55:43 +01002826 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002827 src_port=self.ipfix_src_port,
2828 enable=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002829
2830 pkts = self.create_stream_in(self.pg0, self.pg1)
2831 self.pg0.add_stream(pkts)
2832 self.pg_enable_capture(self.pg_interfaces)
2833 self.pg_start()
2834 capture = self.pg1.get_capture(len(pkts))
2835 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002836 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002837 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002838 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002839 ipfix = IPFIXDecoder()
2840 # first load template
2841 for p in capture:
2842 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002843 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2844 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2845 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002846 self.assertEqual(p[UDP].dport, collector_port)
Matus Fabian6631e9c2017-05-24 01:52:20 -07002847 self.assertEqual(p[IPFIX].observationDomainID,
2848 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002849 if p.haslayer(Template):
2850 ipfix.add_template(p.getlayer(Template))
2851 # verify events in data set
2852 for p in capture:
2853 if p.haslayer(Data):
2854 data = ipfix.decode_data_set(p.getlayer(Set))
2855 self.verify_ipfix_nat44_ses(data)
2856
2857 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002858 """ IPFIX logging NAT addresses exhausted """
Filip Vargadd1e3e72019-04-15 18:52:43 +02002859 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002860 self.vapi.nat44_interface_add_del_feature(
2861 sw_if_index=self.pg0.sw_if_index,
2862 flags=flags, is_add=1)
2863 self.vapi.nat44_interface_add_del_feature(
2864 sw_if_index=self.pg1.sw_if_index,
2865 is_add=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002866 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2867 src_address=self.pg3.local_ip4n,
2868 path_mtu=512,
2869 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002870 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002871 src_port=self.ipfix_src_port,
2872 enable=1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002873
2874 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2875 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2876 TCP(sport=3025))
2877 self.pg0.add_stream(p)
2878 self.pg_enable_capture(self.pg_interfaces)
2879 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002880 self.pg1.assert_nothing_captured()
2881 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002882 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002883 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002884 ipfix = IPFIXDecoder()
2885 # first load template
2886 for p in capture:
2887 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002888 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2889 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2890 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2891 self.assertEqual(p[UDP].dport, 4739)
2892 self.assertEqual(p[IPFIX].observationDomainID,
2893 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002894 if p.haslayer(Template):
2895 ipfix.add_template(p.getlayer(Template))
2896 # verify events in data set
2897 for p in capture:
2898 if p.haslayer(Data):
2899 data = ipfix.decode_data_set(p.getlayer(Set))
2900 self.verify_ipfix_addr_exhausted(data)
2901
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002902 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002903 def test_ipfix_max_sessions(self):
2904 """ IPFIX logging maximum session entries exceeded """
2905 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002906 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002907 self.vapi.nat44_interface_add_del_feature(
2908 sw_if_index=self.pg0.sw_if_index,
2909 flags=flags, is_add=1)
2910 self.vapi.nat44_interface_add_del_feature(
2911 sw_if_index=self.pg1.sw_if_index,
2912 is_add=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002913
2914 nat44_config = self.vapi.nat_show_config()
2915 max_sessions = 10 * nat44_config.translation_buckets
2916
2917 pkts = []
2918 for i in range(0, max_sessions):
2919 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2920 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2921 IP(src=src, dst=self.pg1.remote_ip4) /
2922 TCP(sport=1025))
2923 pkts.append(p)
2924 self.pg0.add_stream(pkts)
2925 self.pg_enable_capture(self.pg_interfaces)
2926 self.pg_start()
2927
2928 self.pg1.get_capture(max_sessions)
2929 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2930 src_address=self.pg3.local_ip4n,
2931 path_mtu=512,
2932 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002933 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02002934 src_port=self.ipfix_src_port,
2935 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002936
2937 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2938 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2939 TCP(sport=1025))
2940 self.pg0.add_stream(p)
2941 self.pg_enable_capture(self.pg_interfaces)
2942 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002943 self.pg1.assert_nothing_captured()
2944 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002945 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2946 capture = self.pg3.get_capture(9)
2947 ipfix = IPFIXDecoder()
2948 # first load template
2949 for p in capture:
2950 self.assertTrue(p.haslayer(IPFIX))
2951 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2952 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2953 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2954 self.assertEqual(p[UDP].dport, 4739)
2955 self.assertEqual(p[IPFIX].observationDomainID,
2956 self.ipfix_domain_id)
2957 if p.haslayer(Template):
2958 ipfix.add_template(p.getlayer(Template))
2959 # verify events in data set
2960 for p in capture:
2961 if p.haslayer(Data):
2962 data = ipfix.decode_data_set(p.getlayer(Set))
2963 self.verify_ipfix_max_sessions(data, max_sessions)
2964
Matus Fabianad1f3e12018-11-28 21:26:34 -08002965 def test_syslog_apmap(self):
2966 """ Test syslog address and port mapping creation and deletion """
2967 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01002968 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002969 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002970 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02002971 self.vapi.nat44_interface_add_del_feature(
2972 sw_if_index=self.pg0.sw_if_index,
2973 flags=flags, is_add=1)
2974 self.vapi.nat44_interface_add_del_feature(
2975 sw_if_index=self.pg1.sw_if_index,
2976 is_add=1)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002977
2978 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2979 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2980 TCP(sport=self.tcp_port_in, dport=20))
2981 self.pg0.add_stream(p)
2982 self.pg_enable_capture(self.pg_interfaces)
2983 self.pg_start()
2984 capture = self.pg1.get_capture(1)
2985 self.tcp_port_out = capture[0][TCP].sport
2986 capture = self.pg3.get_capture(1)
2987 self.verify_syslog_apmap(capture[0][Raw].load)
2988
2989 self.pg_enable_capture(self.pg_interfaces)
2990 self.pg_start()
2991 self.nat44_add_address(self.nat_addr, is_add=0)
2992 capture = self.pg3.get_capture(1)
2993 self.verify_syslog_apmap(capture[0][Raw].load, False)
2994
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002995 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002996 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002997 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002998 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02002999 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003000 self.vapi.nat44_interface_add_del_feature(
3001 sw_if_index=self.pg0.sw_if_index,
3002 flags=flags, is_add=1)
3003 self.vapi.nat44_interface_add_del_feature(
3004 sw_if_index=self.pg1.sw_if_index,
3005 is_add=1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07003006 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003007
Matus Fabian2ba92e32017-08-21 07:05:03 -07003008 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003009 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003010 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003011 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3012 self.pg1.add_stream(p)
3013 self.pg_enable_capture(self.pg_interfaces)
3014 self.pg_start()
3015 capture = self.pg1.get_capture(1)
3016 self.assertTrue(capture[0].haslayer(ARP))
3017 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3018
3019 # 1:1 NAT address
3020 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3021 ARP(op=ARP.who_has, pdst=static_addr,
3022 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3023 self.pg1.add_stream(p)
3024 self.pg_enable_capture(self.pg_interfaces)
3025 self.pg_start()
3026 capture = self.pg1.get_capture(1)
3027 self.assertTrue(capture[0].haslayer(ARP))
3028 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3029
Matus Fabian2ba92e32017-08-21 07:05:03 -07003030 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003031 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003032 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003033 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
3034 self.pg2.add_stream(p)
3035 self.pg_enable_capture(self.pg_interfaces)
3036 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003037 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003038
3039 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07003040 self.nat44_add_address(self.nat_addr, is_add=0)
3041 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
3042 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003043
3044 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003045 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003046 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3047 self.pg1.add_stream(p)
3048 self.pg_enable_capture(self.pg_interfaces)
3049 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003050 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003051
3052 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3053 ARP(op=ARP.who_has, pdst=static_addr,
3054 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3055 self.pg1.add_stream(p)
3056 self.pg_enable_capture(self.pg_interfaces)
3057 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003058 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08003059
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003060 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003061 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003062
3063 vrf_id1 = 1
3064 vrf_id2 = 2
3065 nat_ip1 = "10.0.0.10"
3066 nat_ip2 = "10.0.0.11"
3067
3068 self.pg0.unconfig_ip4()
3069 self.pg1.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003070 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3071 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003072 self.pg0.set_table_ip4(vrf_id1)
3073 self.pg1.set_table_ip4(vrf_id2)
3074 self.pg0.config_ip4()
3075 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07003076 self.pg0.resolve_arp()
3077 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003078
Matus Fabian2ba92e32017-08-21 07:05:03 -07003079 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
3080 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003081 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003082 self.vapi.nat44_interface_add_del_feature(
3083 sw_if_index=self.pg0.sw_if_index,
3084 flags=flags, is_add=1)
3085 self.vapi.nat44_interface_add_del_feature(
3086 sw_if_index=self.pg1.sw_if_index,
3087 flags=flags, is_add=1)
3088 self.vapi.nat44_interface_add_del_feature(
3089 sw_if_index=self.pg2.sw_if_index,
3090 is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003091
Matus Fabian8008d7c2018-07-09 01:34:20 -07003092 try:
3093 # first VRF
3094 pkts = self.create_stream_in(self.pg0, self.pg2)
3095 self.pg0.add_stream(pkts)
3096 self.pg_enable_capture(self.pg_interfaces)
3097 self.pg_start()
3098 capture = self.pg2.get_capture(len(pkts))
3099 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003100
Matus Fabian8008d7c2018-07-09 01:34:20 -07003101 # second VRF
3102 pkts = self.create_stream_in(self.pg1, self.pg2)
3103 self.pg1.add_stream(pkts)
3104 self.pg_enable_capture(self.pg_interfaces)
3105 self.pg_start()
3106 capture = self.pg2.get_capture(len(pkts))
3107 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003108
Matus Fabian8008d7c2018-07-09 01:34:20 -07003109 finally:
3110 self.pg0.unconfig_ip4()
3111 self.pg1.unconfig_ip4()
3112 self.pg0.set_table_ip4(0)
3113 self.pg1.set_table_ip4(0)
3114 self.pg0.config_ip4()
3115 self.pg1.config_ip4()
3116 self.pg0.resolve_arp()
3117 self.pg1.resolve_arp()
Ole Troan9a475372019-03-05 16:58:24 +01003118 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
3119 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
Neale Ranns15002542017-09-10 04:39:11 -07003120
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003121 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003122 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003123
3124 nat_ip1 = "10.0.0.10"
3125 nat_ip2 = "10.0.0.11"
3126
Matus Fabian2ba92e32017-08-21 07:05:03 -07003127 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08003128 self.nat44_add_address(nat_ip2, vrf_id=99)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003129 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003130 self.vapi.nat44_interface_add_del_feature(
3131 sw_if_index=self.pg0.sw_if_index,
3132 flags=flags, is_add=1)
3133 self.vapi.nat44_interface_add_del_feature(
3134 sw_if_index=self.pg1.sw_if_index,
3135 flags=flags, is_add=1)
3136 self.vapi.nat44_interface_add_del_feature(
3137 sw_if_index=self.pg2.sw_if_index,
3138 is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08003139
3140 # first VRF
3141 pkts = self.create_stream_in(self.pg0, self.pg2)
3142 self.pg0.add_stream(pkts)
3143 self.pg_enable_capture(self.pg_interfaces)
3144 self.pg_start()
3145 capture = self.pg2.get_capture(len(pkts))
3146 self.verify_capture_out(capture, nat_ip1)
3147
3148 # second VRF
3149 pkts = self.create_stream_in(self.pg1, self.pg2)
3150 self.pg1.add_stream(pkts)
3151 self.pg_enable_capture(self.pg_interfaces)
3152 self.pg_start()
3153 capture = self.pg2.get_capture(len(pkts))
3154 self.verify_capture_out(capture, nat_ip1)
3155
Martin Gálik406eb1d2017-05-04 04:35:04 -07003156 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003157 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003158
Neale Ranns37029302018-08-10 05:30:06 -07003159 self.vapi.ip_neighbor_add_del(
3160 self.pg7.sw_if_index,
3161 self.pg7.remote_mac,
3162 self.pg7.remote_ip4,
3163 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3164 IP_API_NEIGHBOR_FLAG_STATIC))
3165 self.vapi.ip_neighbor_add_del(
3166 self.pg8.sw_if_index,
3167 self.pg8.remote_mac,
3168 self.pg8.remote_ip4,
3169 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3170 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003171
3172 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3173 dst_address_length=32,
3174 next_hop_address=self.pg7.remote_ip4n,
3175 next_hop_sw_if_index=self.pg7.sw_if_index)
3176 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3177 dst_address_length=32,
3178 next_hop_address=self.pg8.remote_ip4n,
3179 next_hop_sw_if_index=self.pg8.sw_if_index)
3180
Matus Fabian2ba92e32017-08-21 07:05:03 -07003181 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003182 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003183 self.vapi.nat44_interface_add_del_feature(
3184 sw_if_index=self.pg7.sw_if_index,
3185 flags=flags, is_add=1)
3186 self.vapi.nat44_interface_add_del_feature(
3187 sw_if_index=self.pg8.sw_if_index,
3188 is_add=1)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003189
3190 # in2out
3191 pkts = self.create_stream_in(self.pg7, self.pg8)
3192 self.pg7.add_stream(pkts)
3193 self.pg_enable_capture(self.pg_interfaces)
3194 self.pg_start()
3195 capture = self.pg8.get_capture(len(pkts))
3196 self.verify_capture_out(capture)
3197
3198 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003199 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003200 self.pg8.add_stream(pkts)
3201 self.pg_enable_capture(self.pg_interfaces)
3202 self.pg_start()
3203 capture = self.pg7.get_capture(len(pkts))
3204 self.verify_capture_in(capture, self.pg7)
3205
3206 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003207 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003208
Neale Ranns37029302018-08-10 05:30:06 -07003209 self.vapi.ip_neighbor_add_del(
3210 self.pg7.sw_if_index,
3211 self.pg7.remote_mac,
3212 self.pg7.remote_ip4,
3213 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3214 IP_API_NEIGHBOR_FLAG_STATIC))
3215 self.vapi.ip_neighbor_add_del(
3216 self.pg8.sw_if_index,
3217 self.pg8.remote_mac,
3218 self.pg8.remote_ip4,
3219 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3220 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003221
3222 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3223 dst_address_length=32,
3224 next_hop_address=self.pg7.remote_ip4n,
3225 next_hop_sw_if_index=self.pg7.sw_if_index)
3226 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3227 dst_address_length=32,
3228 next_hop_address=self.pg8.remote_ip4n,
3229 next_hop_sw_if_index=self.pg8.sw_if_index)
3230
Matus Fabian2ba92e32017-08-21 07:05:03 -07003231 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003232 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003233 self.vapi.nat44_interface_add_del_feature(
3234 sw_if_index=self.pg7.sw_if_index,
3235 flags=flags, is_add=1)
3236 self.vapi.nat44_interface_add_del_feature(
3237 sw_if_index=self.pg8.sw_if_index,
3238 is_add=1)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003239
3240 # out2in
3241 pkts = self.create_stream_out(self.pg8)
3242 self.pg8.add_stream(pkts)
3243 self.pg_enable_capture(self.pg_interfaces)
3244 self.pg_start()
3245 capture = self.pg7.get_capture(len(pkts))
3246 self.verify_capture_in(capture, self.pg7)
3247
3248 # in2out
3249 pkts = self.create_stream_in(self.pg7, self.pg8)
3250 self.pg7.add_stream(pkts)
3251 self.pg_enable_capture(self.pg_interfaces)
3252 self.pg_start()
3253 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003254 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003255
3256 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003257 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003258
3259 self.tcp_port_out = 30606
3260 self.udp_port_out = 30607
3261 self.icmp_id_out = 30608
3262
Neale Ranns37029302018-08-10 05:30:06 -07003263 self.vapi.ip_neighbor_add_del(
3264 self.pg7.sw_if_index,
3265 self.pg7.remote_mac,
3266 self.pg7.remote_ip4,
3267 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3268 IP_API_NEIGHBOR_FLAG_STATIC))
3269 self.vapi.ip_neighbor_add_del(
3270 self.pg8.sw_if_index,
3271 self.pg8.remote_mac,
3272 self.pg8.remote_ip4,
3273 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3274 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003275
3276 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3277 dst_address_length=32,
3278 next_hop_address=self.pg7.remote_ip4n,
3279 next_hop_sw_if_index=self.pg7.sw_if_index)
3280 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3281 dst_address_length=32,
3282 next_hop_address=self.pg8.remote_ip4n,
3283 next_hop_sw_if_index=self.pg8.sw_if_index)
3284
Matus Fabian2ba92e32017-08-21 07:05:03 -07003285 self.nat44_add_address(self.nat_addr)
3286 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3287 self.tcp_port_in, self.tcp_port_out,
3288 proto=IP_PROTOS.tcp)
3289 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3290 self.udp_port_in, self.udp_port_out,
3291 proto=IP_PROTOS.udp)
3292 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3293 self.icmp_id_in, self.icmp_id_out,
3294 proto=IP_PROTOS.icmp)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003295 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003296 self.vapi.nat44_interface_add_del_feature(
3297 sw_if_index=self.pg7.sw_if_index,
3298 flags=flags, is_add=1)
3299 self.vapi.nat44_interface_add_del_feature(
3300 sw_if_index=self.pg8.sw_if_index,
3301 is_add=1)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003302
3303 # out2in
3304 pkts = self.create_stream_out(self.pg8)
3305 self.pg8.add_stream(pkts)
3306 self.pg_enable_capture(self.pg_interfaces)
3307 self.pg_start()
3308 capture = self.pg7.get_capture(len(pkts))
3309 self.verify_capture_in(capture, self.pg7)
3310
3311 # in2out
3312 pkts = self.create_stream_in(self.pg7, self.pg8)
3313 self.pg7.add_stream(pkts)
3314 self.pg_enable_capture(self.pg_interfaces)
3315 self.pg_start()
3316 capture = self.pg8.get_capture(len(pkts))
3317 self.verify_capture_out(capture)
3318
Matus Fabian328dbc82017-06-19 04:28:04 -07003319 def test_static_unknown_proto(self):
3320 """ 1:1 NAT translate packet with unknown protocol """
3321 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003322 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003323 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003324 self.vapi.nat44_interface_add_del_feature(
3325 sw_if_index=self.pg0.sw_if_index,
3326 flags=flags, is_add=1)
3327 self.vapi.nat44_interface_add_del_feature(
3328 sw_if_index=self.pg1.sw_if_index,
3329 is_add=1)
Matus Fabian328dbc82017-06-19 04:28:04 -07003330
3331 # in2out
3332 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3333 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3334 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003335 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003336 TCP(sport=1234, dport=1234))
3337 self.pg0.add_stream(p)
3338 self.pg_enable_capture(self.pg_interfaces)
3339 self.pg_start()
3340 p = self.pg1.get_capture(1)
3341 packet = p[0]
3342 try:
3343 self.assertEqual(packet[IP].src, nat_ip)
3344 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003345 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003346 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003347 except:
3348 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3349 raise
3350
3351 # out2in
3352 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3353 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3354 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003355 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003356 TCP(sport=1234, dport=1234))
3357 self.pg1.add_stream(p)
3358 self.pg_enable_capture(self.pg_interfaces)
3359 self.pg_start()
3360 p = self.pg0.get_capture(1)
3361 packet = p[0]
3362 try:
3363 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3364 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003365 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003366 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003367 except:
3368 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3369 raise
3370
Matus Fabian7968e6c2017-07-06 05:37:49 -07003371 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003372 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3373
3374 host = self.pg0.remote_hosts[0]
3375 server = self.pg0.remote_hosts[1]
3376
3377 host_nat_ip = "10.0.0.10"
3378 server_nat_ip = "10.0.0.11"
3379
Matus Fabian2ba92e32017-08-21 07:05:03 -07003380 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3381 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003382 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003383 self.vapi.nat44_interface_add_del_feature(
3384 sw_if_index=self.pg0.sw_if_index,
3385 flags=flags, is_add=1)
3386 self.vapi.nat44_interface_add_del_feature(
3387 sw_if_index=self.pg1.sw_if_index,
3388 is_add=1)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003389
3390 # host to server
3391 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3392 IP(src=host.ip4, dst=server_nat_ip) /
3393 GRE() /
3394 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3395 TCP(sport=1234, dport=1234))
3396 self.pg0.add_stream(p)
3397 self.pg_enable_capture(self.pg_interfaces)
3398 self.pg_start()
3399 p = self.pg0.get_capture(1)
3400 packet = p[0]
3401 try:
3402 self.assertEqual(packet[IP].src, host_nat_ip)
3403 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003404 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003405 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003406 except:
3407 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3408 raise
3409
3410 # server to host
3411 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3412 IP(src=server.ip4, dst=host_nat_ip) /
3413 GRE() /
3414 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3415 TCP(sport=1234, dport=1234))
3416 self.pg0.add_stream(p)
3417 self.pg_enable_capture(self.pg_interfaces)
3418 self.pg_start()
3419 p = self.pg0.get_capture(1)
3420 packet = p[0]
3421 try:
3422 self.assertEqual(packet[IP].src, server_nat_ip)
3423 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003424 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003425 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003426 except:
3427 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3428 raise
3429
Matus Fabian93d84c92017-07-19 08:06:01 -07003430 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003431 """ NAT44 interface output feature (in2out postrouting) """
3432 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003433 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003434 self.vapi.nat44_interface_add_del_output_feature(
3435 is_add=1, flags=flags,
3436 sw_if_index=self.pg0.sw_if_index)
3437 self.vapi.nat44_interface_add_del_output_feature(
3438 is_add=1, flags=flags,
3439 sw_if_index=self.pg1.sw_if_index)
3440 self.vapi.nat44_interface_add_del_output_feature(
3441 is_add=1,
3442 sw_if_index=self.pg3.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003443
3444 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003445 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003446 self.pg0.add_stream(pkts)
3447 self.pg_enable_capture(self.pg_interfaces)
3448 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003449 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003450 self.verify_capture_out(capture)
3451
3452 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003453 pkts = self.create_stream_out(self.pg3)
3454 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003455 self.pg_enable_capture(self.pg_interfaces)
3456 self.pg_start()
3457 capture = self.pg0.get_capture(len(pkts))
3458 self.verify_capture_in(capture, self.pg0)
3459
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003460 # from non-NAT interface to NAT inside interface
3461 pkts = self.create_stream_in(self.pg2, self.pg0)
3462 self.pg2.add_stream(pkts)
3463 self.pg_enable_capture(self.pg_interfaces)
3464 self.pg_start()
3465 capture = self.pg0.get_capture(len(pkts))
3466 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3467
Matus Fabian93d84c92017-07-19 08:06:01 -07003468 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003469 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003470 nat_ip_vrf10 = "10.0.0.10"
3471 nat_ip_vrf20 = "10.0.0.20"
3472
3473 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3474 dst_address_length=32,
3475 next_hop_address=self.pg3.remote_ip4n,
3476 next_hop_sw_if_index=self.pg3.sw_if_index,
3477 table_id=10)
3478 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3479 dst_address_length=32,
3480 next_hop_address=self.pg3.remote_ip4n,
3481 next_hop_sw_if_index=self.pg3.sw_if_index,
3482 table_id=20)
3483
Matus Fabian2ba92e32017-08-21 07:05:03 -07003484 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3485 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003486 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003487 self.vapi.nat44_interface_add_del_output_feature(
3488 is_add=1, flags=flags,
3489 sw_if_index=self.pg4.sw_if_index)
3490 self.vapi.nat44_interface_add_del_output_feature(
3491 is_add=1, flags=flags,
3492 sw_if_index=self.pg6.sw_if_index)
3493 self.vapi.nat44_interface_add_del_output_feature(
3494 is_add=1,
3495 sw_if_index=self.pg3.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003496
3497 # in2out VRF 10
3498 pkts = self.create_stream_in(self.pg4, self.pg3)
3499 self.pg4.add_stream(pkts)
3500 self.pg_enable_capture(self.pg_interfaces)
3501 self.pg_start()
3502 capture = self.pg3.get_capture(len(pkts))
3503 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3504
3505 # out2in VRF 10
3506 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3507 self.pg3.add_stream(pkts)
3508 self.pg_enable_capture(self.pg_interfaces)
3509 self.pg_start()
3510 capture = self.pg4.get_capture(len(pkts))
3511 self.verify_capture_in(capture, self.pg4)
3512
3513 # in2out VRF 20
3514 pkts = self.create_stream_in(self.pg6, self.pg3)
3515 self.pg6.add_stream(pkts)
3516 self.pg_enable_capture(self.pg_interfaces)
3517 self.pg_start()
3518 capture = self.pg3.get_capture(len(pkts))
3519 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3520
3521 # out2in VRF 20
3522 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3523 self.pg3.add_stream(pkts)
3524 self.pg_enable_capture(self.pg_interfaces)
3525 self.pg_start()
3526 capture = self.pg6.get_capture(len(pkts))
3527 self.verify_capture_in(capture, self.pg6)
3528
Matus Fabian161c59c2017-07-21 03:46:03 -07003529 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003530 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003531 host = self.pg0.remote_hosts[0]
3532 server = self.pg0.remote_hosts[1]
3533 host_in_port = 1234
3534 host_out_port = 0
3535 server_in_port = 5678
3536 server_out_port = 8765
3537
Matus Fabian2ba92e32017-08-21 07:05:03 -07003538 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003539 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003540 self.vapi.nat44_interface_add_del_output_feature(
3541 is_add=1, flags=flags,
3542 sw_if_index=self.pg0.sw_if_index)
3543 self.vapi.nat44_interface_add_del_output_feature(
3544 is_add=1,
3545 sw_if_index=self.pg1.sw_if_index)
Matus Fabian93d84c92017-07-19 08:06:01 -07003546
3547 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003548 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3549 server_in_port, server_out_port,
3550 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003551
3552 # send packet from host to server
3553 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003554 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003555 TCP(sport=host_in_port, dport=server_out_port))
3556 self.pg0.add_stream(p)
3557 self.pg_enable_capture(self.pg_interfaces)
3558 self.pg_start()
3559 capture = self.pg0.get_capture(1)
3560 p = capture[0]
3561 try:
3562 ip = p[IP]
3563 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003564 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003565 self.assertEqual(ip.dst, server.ip4)
3566 self.assertNotEqual(tcp.sport, host_in_port)
3567 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003568 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003569 host_out_port = tcp.sport
3570 except:
3571 self.logger.error(ppp("Unexpected or invalid packet:", p))
3572 raise
3573
3574 # send reply from server to host
3575 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003576 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003577 TCP(sport=server_in_port, dport=host_out_port))
3578 self.pg0.add_stream(p)
3579 self.pg_enable_capture(self.pg_interfaces)
3580 self.pg_start()
3581 capture = self.pg0.get_capture(1)
3582 p = capture[0]
3583 try:
3584 ip = p[IP]
3585 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003586 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003587 self.assertEqual(ip.dst, host.ip4)
3588 self.assertEqual(tcp.sport, server_out_port)
3589 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003590 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003591 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003592 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003593 raise
3594
Matus Fabian36ea2d62017-10-24 04:13:49 -07003595 def test_one_armed_nat44(self):
3596 """ One armed NAT44 """
3597 remote_host = self.pg9.remote_hosts[0]
3598 local_host = self.pg9.remote_hosts[1]
3599 external_port = 0
3600
3601 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003602 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003603 self.vapi.nat44_interface_add_del_feature(
3604 sw_if_index=self.pg9.sw_if_index,
3605 is_add=1)
3606 self.vapi.nat44_interface_add_del_feature(
3607 sw_if_index=self.pg9.sw_if_index,
3608 flags=flags, is_add=1)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003609
3610 # in2out
3611 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3612 IP(src=local_host.ip4, dst=remote_host.ip4) /
3613 TCP(sport=12345, dport=80))
3614 self.pg9.add_stream(p)
3615 self.pg_enable_capture(self.pg_interfaces)
3616 self.pg_start()
3617 capture = self.pg9.get_capture(1)
3618 p = capture[0]
3619 try:
3620 ip = p[IP]
3621 tcp = p[TCP]
3622 self.assertEqual(ip.src, self.nat_addr)
3623 self.assertEqual(ip.dst, remote_host.ip4)
3624 self.assertNotEqual(tcp.sport, 12345)
3625 external_port = tcp.sport
3626 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003627 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003628 except:
3629 self.logger.error(ppp("Unexpected or invalid packet:", p))
3630 raise
3631
3632 # out2in
3633 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3634 IP(src=remote_host.ip4, dst=self.nat_addr) /
3635 TCP(sport=80, dport=external_port))
3636 self.pg9.add_stream(p)
3637 self.pg_enable_capture(self.pg_interfaces)
3638 self.pg_start()
3639 capture = self.pg9.get_capture(1)
3640 p = capture[0]
3641 try:
3642 ip = p[IP]
3643 tcp = p[TCP]
3644 self.assertEqual(ip.src, remote_host.ip4)
3645 self.assertEqual(ip.dst, local_host.ip4)
3646 self.assertEqual(tcp.sport, 80)
3647 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003648 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003649 except:
3650 self.logger.error(ppp("Unexpected or invalid packet:", p))
3651 raise
3652
Matus Fabiana5e73762018-12-14 01:55:16 -08003653 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3654 self.assertEqual(err, 1)
3655 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3656 self.assertEqual(err, 1)
3657
Matus Fabian5ba86f72017-10-26 03:37:38 -07003658 def test_del_session(self):
3659 """ Delete NAT44 session """
3660 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003661 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003662 self.vapi.nat44_interface_add_del_feature(
3663 sw_if_index=self.pg0.sw_if_index,
3664 flags=flags, is_add=1)
3665 self.vapi.nat44_interface_add_del_feature(
3666 sw_if_index=self.pg1.sw_if_index,
3667 is_add=1)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003668
3669 pkts = self.create_stream_in(self.pg0, self.pg1)
3670 self.pg0.add_stream(pkts)
3671 self.pg_enable_capture(self.pg_interfaces)
3672 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003673 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003674
3675 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3676 nsessions = len(sessions)
3677
Filip Vargaf4749ca2019-04-25 14:55:32 +02003678 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3679 port=sessions[0].inside_port,
3680 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003681 flags=self.config_flags.NAT_IS_INSIDE)
Filip Vargaf4749ca2019-04-25 14:55:32 +02003682 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3683 port=sessions[1].outside_port,
3684 protocol=sessions[1].protocol)
Matus Fabian5ba86f72017-10-26 03:37:38 -07003685
3686 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3687 self.assertEqual(nsessions - len(sessions), 2)
3688
Filip Vargaf4749ca2019-04-25 14:55:32 +02003689 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3690 port=sessions[0].inside_port,
3691 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02003692 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian68ba8802018-08-08 05:52:47 -07003693
3694 self.verify_no_nat44_user()
3695
Matus Fabianefcd1e92017-08-15 06:59:19 -07003696 def test_set_get_reass(self):
3697 """ NAT44 set/get virtual fragmentation reassembly """
3698 reas_cfg1 = self.vapi.nat_get_reass()
3699
3700 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3701 max_reass=reas_cfg1.ip4_max_reass * 2,
Filip Vargaf4749ca2019-04-25 14:55:32 +02003702 max_frag=reas_cfg1.ip4_max_frag * 2,
3703 drop_frag=0)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003704
3705 reas_cfg2 = self.vapi.nat_get_reass()
3706
3707 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3708 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3709 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3710
Filip Vargaf4749ca2019-04-25 14:55:32 +02003711 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
3712 drop_frag=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003713 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3714
3715 def test_frag_in_order(self):
3716 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003717
Matus Fabianefcd1e92017-08-15 06:59:19 -07003718 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003719 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003720 self.vapi.nat44_interface_add_del_feature(
3721 sw_if_index=self.pg0.sw_if_index,
3722 flags=flags, is_add=1)
3723 self.vapi.nat44_interface_add_del_feature(
3724 sw_if_index=self.pg1.sw_if_index,
3725 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003726
Matus Fabianda41d722018-10-19 04:01:19 -07003727 self.frag_in_order(proto=IP_PROTOS.tcp)
3728 self.frag_in_order(proto=IP_PROTOS.udp)
3729 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003730
Matus Fabian111add72018-11-20 02:19:05 -08003731 def test_frag_forwarding(self):
3732 """ NAT44 forwarding fragment test """
Filip Vargaf4749ca2019-04-25 14:55:32 +02003733 self.vapi.nat44_add_del_interface_addr(
3734 is_add=1,
3735 sw_if_index=self.pg1.sw_if_index)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003736 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003737 self.vapi.nat44_interface_add_del_feature(
3738 sw_if_index=self.pg0.sw_if_index,
3739 flags=flags, is_add=1)
3740 self.vapi.nat44_interface_add_del_feature(
3741 sw_if_index=self.pg1.sw_if_index,
3742 is_add=1)
3743 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian111add72018-11-20 02:19:05 -08003744
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003745 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Matus Fabian111add72018-11-20 02:19:05 -08003746 pkts = self.create_stream_frag(self.pg1,
3747 self.pg0.remote_ip4,
3748 4789,
3749 4789,
3750 data,
3751 proto=IP_PROTOS.udp)
3752 self.pg1.add_stream(pkts)
3753 self.pg_enable_capture(self.pg_interfaces)
3754 self.pg_start()
3755 frags = self.pg0.get_capture(len(pkts))
3756 p = self.reass_frags_and_verify(frags,
3757 self.pg1.remote_ip4,
3758 self.pg0.remote_ip4)
3759 self.assertEqual(p[UDP].sport, 4789)
3760 self.assertEqual(p[UDP].dport, 4789)
3761 self.assertEqual(data, p[Raw].load)
3762
Matus Fabianefcd1e92017-08-15 06:59:19 -07003763 def test_reass_hairpinning(self):
3764 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003765
Matus Fabianda41d722018-10-19 04:01:19 -07003766 self.server = self.pg0.remote_hosts[1]
3767 self.host_in_port = random.randint(1025, 65535)
3768 self.server_in_port = random.randint(1025, 65535)
3769 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003770
3771 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003772 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003773 self.vapi.nat44_interface_add_del_feature(
3774 sw_if_index=self.pg0.sw_if_index,
3775 flags=flags, is_add=1)
3776 self.vapi.nat44_interface_add_del_feature(
3777 sw_if_index=self.pg1.sw_if_index,
3778 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003779 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003780 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3781 self.server_in_port,
3782 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003783 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003784 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3785 self.server_in_port,
3786 self.server_out_port,
3787 proto=IP_PROTOS.udp)
3788 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003789
Matus Fabianda41d722018-10-19 04:01:19 -07003790 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3791 self.reass_hairpinning(proto=IP_PROTOS.udp)
3792 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003793
3794 def test_frag_out_of_order(self):
3795 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003796
Matus Fabianefcd1e92017-08-15 06:59:19 -07003797 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003798 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003799 self.vapi.nat44_interface_add_del_feature(
3800 sw_if_index=self.pg0.sw_if_index,
3801 flags=flags, is_add=1)
3802 self.vapi.nat44_interface_add_del_feature(
3803 sw_if_index=self.pg1.sw_if_index,
3804 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003805
Matus Fabianda41d722018-10-19 04:01:19 -07003806 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3807 self.frag_out_of_order(proto=IP_PROTOS.udp)
3808 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003809
Matus Fabian27697102017-11-09 01:43:47 -08003810 def test_port_restricted(self):
3811 """ Port restricted NAT44 (MAP-E CE) """
3812 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003813 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003814 self.vapi.nat44_interface_add_del_feature(
3815 sw_if_index=self.pg0.sw_if_index,
3816 flags=flags, is_add=1)
3817 self.vapi.nat44_interface_add_del_feature(
3818 sw_if_index=self.pg1.sw_if_index,
3819 is_add=1)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003820 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3821 psid_offset=6,
3822 psid_length=6,
3823 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003824
3825 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3826 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3827 TCP(sport=4567, dport=22))
3828 self.pg0.add_stream(p)
3829 self.pg_enable_capture(self.pg_interfaces)
3830 self.pg_start()
3831 capture = self.pg1.get_capture(1)
3832 p = capture[0]
3833 try:
3834 ip = p[IP]
3835 tcp = p[TCP]
3836 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3837 self.assertEqual(ip.src, self.nat_addr)
3838 self.assertEqual(tcp.dport, 22)
3839 self.assertNotEqual(tcp.sport, 4567)
3840 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003841 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003842 except:
3843 self.logger.error(ppp("Unexpected or invalid packet:", p))
3844 raise
3845
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003846 def test_port_range(self):
3847 """ External address port range """
3848 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003849 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003850 self.vapi.nat44_interface_add_del_feature(
3851 sw_if_index=self.pg0.sw_if_index,
3852 flags=flags, is_add=1)
3853 self.vapi.nat44_interface_add_del_feature(
3854 sw_if_index=self.pg1.sw_if_index,
3855 is_add=1)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003856 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3857 start_port=1025,
3858 end_port=1027)
3859
3860 pkts = []
3861 for port in range(0, 5):
3862 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3863 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3864 TCP(sport=1125 + port))
3865 pkts.append(p)
3866 self.pg0.add_stream(pkts)
3867 self.pg_enable_capture(self.pg_interfaces)
3868 self.pg_start()
3869 capture = self.pg1.get_capture(3)
3870 for p in capture:
3871 tcp = p[TCP]
3872 self.assertGreaterEqual(tcp.sport, 1025)
3873 self.assertLessEqual(tcp.sport, 1027)
3874
Matus Fabiana6110b62018-06-13 05:39:07 -07003875 def test_ipfix_max_frags(self):
3876 """ IPFIX logging maximum fragments pending reassembly exceeded """
3877 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003878 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003879 self.vapi.nat44_interface_add_del_feature(
3880 sw_if_index=self.pg0.sw_if_index,
3881 flags=flags, is_add=1)
3882 self.vapi.nat44_interface_add_del_feature(
3883 sw_if_index=self.pg1.sw_if_index,
3884 is_add=1)
3885 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
3886 drop_frag=0)
Matus Fabiana6110b62018-06-13 05:39:07 -07003887 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3888 src_address=self.pg3.local_ip4n,
3889 path_mtu=512,
3890 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01003891 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02003892 src_port=self.ipfix_src_port,
3893 enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003894
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003895 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabiana6110b62018-06-13 05:39:07 -07003896 self.tcp_port_in = random.randint(1025, 65535)
3897 pkts = self.create_stream_frag(self.pg0,
3898 self.pg1.remote_ip4,
3899 self.tcp_port_in,
3900 20,
3901 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003902 pkts.reverse()
3903 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003904 self.pg_enable_capture(self.pg_interfaces)
3905 self.pg_start()
3906 self.pg1.assert_nothing_captured()
3907 sleep(1)
3908 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3909 capture = self.pg3.get_capture(9)
3910 ipfix = IPFIXDecoder()
3911 # first load template
3912 for p in capture:
3913 self.assertTrue(p.haslayer(IPFIX))
3914 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3915 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3916 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3917 self.assertEqual(p[UDP].dport, 4739)
3918 self.assertEqual(p[IPFIX].observationDomainID,
3919 self.ipfix_domain_id)
3920 if p.haslayer(Template):
3921 ipfix.add_template(p.getlayer(Template))
3922 # verify events in data set
3923 for p in capture:
3924 if p.haslayer(Data):
3925 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003926 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003927 self.pg0.remote_ip4n)
3928
Matus Fabian8008d7c2018-07-09 01:34:20 -07003929 def test_multiple_outside_vrf(self):
3930 """ Multiple outside VRF """
3931 vrf_id1 = 1
3932 vrf_id2 = 2
3933
3934 self.pg1.unconfig_ip4()
3935 self.pg2.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003936 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3937 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003938 self.pg1.set_table_ip4(vrf_id1)
3939 self.pg2.set_table_ip4(vrf_id2)
3940 self.pg1.config_ip4()
3941 self.pg2.config_ip4()
3942 self.pg1.resolve_arp()
3943 self.pg2.resolve_arp()
3944
3945 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02003946 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02003947 self.vapi.nat44_interface_add_del_feature(
3948 sw_if_index=self.pg0.sw_if_index,
3949 flags=flags, is_add=1)
3950 self.vapi.nat44_interface_add_del_feature(
3951 sw_if_index=self.pg1.sw_if_index,
3952 is_add=1)
3953 self.vapi.nat44_interface_add_del_feature(
3954 sw_if_index=self.pg2.sw_if_index,
3955 is_add=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003956
3957 try:
3958 # first VRF
3959 pkts = self.create_stream_in(self.pg0, self.pg1)
3960 self.pg0.add_stream(pkts)
3961 self.pg_enable_capture(self.pg_interfaces)
3962 self.pg_start()
3963 capture = self.pg1.get_capture(len(pkts))
3964 self.verify_capture_out(capture, self.nat_addr)
3965
3966 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3967 self.pg1.add_stream(pkts)
3968 self.pg_enable_capture(self.pg_interfaces)
3969 self.pg_start()
3970 capture = self.pg0.get_capture(len(pkts))
3971 self.verify_capture_in(capture, self.pg0)
3972
3973 self.tcp_port_in = 60303
3974 self.udp_port_in = 60304
3975 self.icmp_id_in = 60305
3976
3977 # second VRF
3978 pkts = self.create_stream_in(self.pg0, self.pg2)
3979 self.pg0.add_stream(pkts)
3980 self.pg_enable_capture(self.pg_interfaces)
3981 self.pg_start()
3982 capture = self.pg2.get_capture(len(pkts))
3983 self.verify_capture_out(capture, self.nat_addr)
3984
3985 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3986 self.pg2.add_stream(pkts)
3987 self.pg_enable_capture(self.pg_interfaces)
3988 self.pg_start()
3989 capture = self.pg0.get_capture(len(pkts))
3990 self.verify_capture_in(capture, self.pg0)
3991
3992 finally:
3993 self.pg1.unconfig_ip4()
3994 self.pg2.unconfig_ip4()
3995 self.pg1.set_table_ip4(0)
3996 self.pg2.set_table_ip4(0)
3997 self.pg1.config_ip4()
3998 self.pg2.config_ip4()
3999 self.pg1.resolve_arp()
4000 self.pg2.resolve_arp()
4001
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004002 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07004003 def test_session_timeout(self):
4004 """ NAT44 session timeouts """
4005 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004006 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004007 self.vapi.nat44_interface_add_del_feature(
4008 sw_if_index=self.pg0.sw_if_index,
4009 flags=flags, is_add=1)
4010 self.vapi.nat44_interface_add_del_feature(
4011 sw_if_index=self.pg1.sw_if_index,
4012 is_add=1)
4013 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
4014 tcp_transitory=240, icmp=60)
Matus Fabian878c6462018-08-23 00:33:35 -07004015
4016 max_sessions = 1000
4017 pkts = []
4018 for i in range(0, max_sessions):
4019 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
4020 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4021 IP(src=src, dst=self.pg1.remote_ip4) /
4022 UDP(sport=1025, dport=53))
4023 pkts.append(p)
4024 self.pg0.add_stream(pkts)
4025 self.pg_enable_capture(self.pg_interfaces)
4026 self.pg_start()
4027 self.pg1.get_capture(max_sessions)
4028
4029 sleep(6)
4030
4031 pkts = []
4032 for i in range(0, max_sessions):
4033 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
4034 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4035 IP(src=src, dst=self.pg1.remote_ip4) /
4036 UDP(sport=1026, dport=53))
4037 pkts.append(p)
4038 self.pg0.add_stream(pkts)
4039 self.pg_enable_capture(self.pg_interfaces)
4040 self.pg_start()
4041 self.pg1.get_capture(max_sessions)
4042
4043 nsessions = 0
4044 users = self.vapi.nat44_user_dump()
4045 for user in users:
4046 nsessions = nsessions + user.nsessions
4047 self.assertLess(nsessions, 2 * max_sessions)
4048
Matus Fabianbb4e0222018-09-13 02:36:25 -07004049 def test_mss_clamping(self):
4050 """ TCP MSS clamping """
4051 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004052 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004053 self.vapi.nat44_interface_add_del_feature(
4054 sw_if_index=self.pg0.sw_if_index,
4055 flags=flags, is_add=1)
4056 self.vapi.nat44_interface_add_del_feature(
4057 sw_if_index=self.pg1.sw_if_index,
4058 is_add=1)
Matus Fabianbb4e0222018-09-13 02:36:25 -07004059
4060 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4061 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4062 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4063 flags="S", options=[('MSS', 1400)]))
4064
4065 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
4066 self.pg0.add_stream(p)
4067 self.pg_enable_capture(self.pg_interfaces)
4068 self.pg_start()
4069 capture = self.pg1.get_capture(1)
4070 # Negotiated MSS value greater than configured - changed
4071 self.verify_mss_value(capture[0], 1000)
4072
Filip Vargaf4749ca2019-04-25 14:55:32 +02004073 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
Matus Fabianbb4e0222018-09-13 02:36:25 -07004074 self.pg0.add_stream(p)
4075 self.pg_enable_capture(self.pg_interfaces)
4076 self.pg_start()
4077 capture = self.pg1.get_capture(1)
4078 # MSS clamping disabled - negotiated MSS unchanged
4079 self.verify_mss_value(capture[0], 1400)
4080
4081 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
4082 self.pg0.add_stream(p)
4083 self.pg_enable_capture(self.pg_interfaces)
4084 self.pg_start()
4085 capture = self.pg1.get_capture(1)
4086 # Negotiated MSS value smaller than configured - unchanged
4087 self.verify_mss_value(capture[0], 1400)
4088
Matus Fabian34931eb2019-02-26 09:05:23 -08004089 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4090 def test_ha_send(self):
4091 """ Send HA session synchronization events (active) """
4092 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004093 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004094 self.vapi.nat44_interface_add_del_feature(
4095 sw_if_index=self.pg0.sw_if_index,
4096 flags=flags, is_add=1)
4097 self.vapi.nat44_interface_add_del_feature(
4098 sw_if_index=self.pg1.sw_if_index,
4099 is_add=1)
4100 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4101 port=12345,
4102 path_mtu=512)
4103 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
4104 port=12346, session_refresh_interval=10)
Matus Fabian34931eb2019-02-26 09:05:23 -08004105 bind_layers(UDP, HANATStateSync, sport=12345)
4106
4107 # create sessions
4108 pkts = self.create_stream_in(self.pg0, self.pg1)
4109 self.pg0.add_stream(pkts)
4110 self.pg_enable_capture(self.pg_interfaces)
4111 self.pg_start()
4112 capture = self.pg1.get_capture(len(pkts))
4113 self.verify_capture_out(capture)
4114 # active send HA events
4115 self.vapi.nat_ha_flush()
4116 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
4117 self.assertEqual(stats[0][0], 3)
4118 capture = self.pg3.get_capture(1)
4119 p = capture[0]
4120 self.assert_packet_checksums_valid(p)
4121 try:
4122 ip = p[IP]
4123 udp = p[UDP]
4124 hanat = p[HANATStateSync]
4125 except IndexError:
4126 self.logger.error(ppp("Invalid packet:", p))
4127 raise
4128 else:
4129 self.assertEqual(ip.src, self.pg3.local_ip4)
4130 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4131 self.assertEqual(udp.sport, 12345)
4132 self.assertEqual(udp.dport, 12346)
4133 self.assertEqual(hanat.version, 1)
4134 self.assertEqual(hanat.thread_index, 0)
4135 self.assertEqual(hanat.count, 3)
4136 seq = hanat.sequence_number
4137 for event in hanat.events:
4138 self.assertEqual(event.event_type, 1)
4139 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
4140 self.assertEqual(event.out_addr, self.nat_addr)
4141 self.assertEqual(event.fib_index, 0)
4142
4143 # ACK received events
4144 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4145 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4146 UDP(sport=12346, dport=12345) /
4147 HANATStateSync(sequence_number=seq, flags='ACK'))
4148 self.pg3.add_stream(ack)
4149 self.pg_start()
4150 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4151 self.assertEqual(stats[0][0], 1)
4152
4153 # delete one session
4154 self.pg_enable_capture(self.pg_interfaces)
Filip Vargaf4749ca2019-04-25 14:55:32 +02004155 self.vapi.nat44_del_session(address=self.pg0.remote_ip4n,
4156 port=self.tcp_port_in,
4157 protocol=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004158 flags=self.config_flags.NAT_IS_INSIDE)
Matus Fabian34931eb2019-02-26 09:05:23 -08004159 self.vapi.nat_ha_flush()
4160 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
4161 self.assertEqual(stats[0][0], 1)
4162 capture = self.pg3.get_capture(1)
4163 p = capture[0]
4164 try:
4165 hanat = p[HANATStateSync]
4166 except IndexError:
4167 self.logger.error(ppp("Invalid packet:", p))
4168 raise
4169 else:
4170 self.assertGreater(hanat.sequence_number, seq)
4171
4172 # do not send ACK, active retry send HA event again
4173 self.pg_enable_capture(self.pg_interfaces)
4174 sleep(12)
4175 stats = self.statistics.get_counter('/nat44/ha/retry-count')
4176 self.assertEqual(stats[0][0], 3)
4177 stats = self.statistics.get_counter('/nat44/ha/missed-count')
4178 self.assertEqual(stats[0][0], 1)
4179 capture = self.pg3.get_capture(3)
4180 for packet in capture:
4181 self.assertEqual(packet, p)
4182
4183 # session counters refresh
4184 pkts = self.create_stream_out(self.pg1)
4185 self.pg1.add_stream(pkts)
4186 self.pg_enable_capture(self.pg_interfaces)
4187 self.pg_start()
4188 self.pg0.get_capture(2)
4189 self.vapi.nat_ha_flush()
4190 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
4191 self.assertEqual(stats[0][0], 2)
4192 capture = self.pg3.get_capture(1)
4193 p = capture[0]
4194 self.assert_packet_checksums_valid(p)
4195 try:
4196 ip = p[IP]
4197 udp = p[UDP]
4198 hanat = p[HANATStateSync]
4199 except IndexError:
4200 self.logger.error(ppp("Invalid packet:", p))
4201 raise
4202 else:
4203 self.assertEqual(ip.src, self.pg3.local_ip4)
4204 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4205 self.assertEqual(udp.sport, 12345)
4206 self.assertEqual(udp.dport, 12346)
4207 self.assertEqual(hanat.version, 1)
4208 self.assertEqual(hanat.count, 2)
4209 seq = hanat.sequence_number
4210 for event in hanat.events:
4211 self.assertEqual(event.event_type, 3)
4212 self.assertEqual(event.out_addr, self.nat_addr)
4213 self.assertEqual(event.fib_index, 0)
4214 self.assertEqual(event.total_pkts, 2)
4215 self.assertGreater(event.total_bytes, 0)
4216
4217 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4218 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4219 UDP(sport=12346, dport=12345) /
4220 HANATStateSync(sequence_number=seq, flags='ACK'))
4221 self.pg3.add_stream(ack)
4222 self.pg_start()
4223 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4224 self.assertEqual(stats[0][0], 2)
4225
4226 def test_ha_recv(self):
4227 """ Receive HA session synchronization events (passive) """
4228 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004229 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004230 self.vapi.nat44_interface_add_del_feature(
4231 sw_if_index=self.pg0.sw_if_index,
4232 flags=flags, is_add=1)
4233 self.vapi.nat44_interface_add_del_feature(
4234 sw_if_index=self.pg1.sw_if_index,
4235 is_add=1)
4236 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4237 port=12345,
4238 path_mtu=512)
Matus Fabian34931eb2019-02-26 09:05:23 -08004239 bind_layers(UDP, HANATStateSync, sport=12345)
4240
4241 self.tcp_port_out = random.randint(1025, 65535)
4242 self.udp_port_out = random.randint(1025, 65535)
4243
4244 # send HA session add events to failover/passive
4245 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4246 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4247 UDP(sport=12346, dport=12345) /
4248 HANATStateSync(sequence_number=1, events=[
4249 Event(event_type='add', protocol='tcp',
4250 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4251 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4252 eh_addr=self.pg1.remote_ip4,
4253 ehn_addr=self.pg1.remote_ip4,
4254 eh_port=self.tcp_external_port,
4255 ehn_port=self.tcp_external_port, fib_index=0),
4256 Event(event_type='add', protocol='udp',
4257 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4258 in_port=self.udp_port_in, out_port=self.udp_port_out,
4259 eh_addr=self.pg1.remote_ip4,
4260 ehn_addr=self.pg1.remote_ip4,
4261 eh_port=self.udp_external_port,
4262 ehn_port=self.udp_external_port, fib_index=0)]))
4263
4264 self.pg3.add_stream(p)
4265 self.pg_enable_capture(self.pg_interfaces)
4266 self.pg_start()
4267 # receive ACK
4268 capture = self.pg3.get_capture(1)
4269 p = capture[0]
4270 try:
4271 hanat = p[HANATStateSync]
4272 except IndexError:
4273 self.logger.error(ppp("Invalid packet:", p))
4274 raise
4275 else:
4276 self.assertEqual(hanat.sequence_number, 1)
4277 self.assertEqual(hanat.flags, 'ACK')
4278 self.assertEqual(hanat.version, 1)
4279 self.assertEqual(hanat.thread_index, 0)
4280 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4281 self.assertEqual(stats[0][0], 1)
4282 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4283 self.assertEqual(stats[0][0], 2)
4284 users = self.statistics.get_counter('/nat44/total-users')
4285 self.assertEqual(users[0][0], 1)
4286 sessions = self.statistics.get_counter('/nat44/total-sessions')
4287 self.assertEqual(sessions[0][0], 2)
4288 users = self.vapi.nat44_user_dump()
4289 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004290 self.assertEqual(str(users[0].ip_address),
4291 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004292 # there should be 2 sessions created by HA
4293 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4294 users[0].vrf_id)
4295 self.assertEqual(len(sessions), 2)
4296 for session in sessions:
Filip Vargadd1e3e72019-04-15 18:52:43 +02004297 self.assertEqual(str(session.inside_ip_address),
4298 self.pg0.remote_ip4)
4299 self.assertEqual(str(session.outside_ip_address),
4300 self.nat_addr)
Matus Fabian34931eb2019-02-26 09:05:23 -08004301 self.assertIn(session.inside_port,
4302 [self.tcp_port_in, self.udp_port_in])
4303 self.assertIn(session.outside_port,
4304 [self.tcp_port_out, self.udp_port_out])
4305 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4306
4307 # send HA session delete event to failover/passive
4308 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4309 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4310 UDP(sport=12346, dport=12345) /
4311 HANATStateSync(sequence_number=2, events=[
4312 Event(event_type='del', protocol='udp',
4313 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4314 in_port=self.udp_port_in, out_port=self.udp_port_out,
4315 eh_addr=self.pg1.remote_ip4,
4316 ehn_addr=self.pg1.remote_ip4,
4317 eh_port=self.udp_external_port,
4318 ehn_port=self.udp_external_port, fib_index=0)]))
4319
4320 self.pg3.add_stream(p)
4321 self.pg_enable_capture(self.pg_interfaces)
4322 self.pg_start()
4323 # receive ACK
4324 capture = self.pg3.get_capture(1)
4325 p = capture[0]
4326 try:
4327 hanat = p[HANATStateSync]
4328 except IndexError:
4329 self.logger.error(ppp("Invalid packet:", p))
4330 raise
4331 else:
4332 self.assertEqual(hanat.sequence_number, 2)
4333 self.assertEqual(hanat.flags, 'ACK')
4334 self.assertEqual(hanat.version, 1)
4335 users = self.vapi.nat44_user_dump()
4336 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004337 self.assertEqual(str(users[0].ip_address),
4338 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004339 # now we should have only 1 session, 1 deleted by HA
4340 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4341 users[0].vrf_id)
4342 self.assertEqual(len(sessions), 1)
4343 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4344 self.assertEqual(stats[0][0], 1)
4345
4346 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4347 self.assertEqual(stats, 2)
4348
4349 # send HA session refresh event to failover/passive
4350 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4351 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4352 UDP(sport=12346, dport=12345) /
4353 HANATStateSync(sequence_number=3, events=[
4354 Event(event_type='refresh', protocol='tcp',
4355 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4356 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4357 eh_addr=self.pg1.remote_ip4,
4358 ehn_addr=self.pg1.remote_ip4,
4359 eh_port=self.tcp_external_port,
4360 ehn_port=self.tcp_external_port, fib_index=0,
4361 total_bytes=1024, total_pkts=2)]))
4362 self.pg3.add_stream(p)
4363 self.pg_enable_capture(self.pg_interfaces)
4364 self.pg_start()
4365 # receive ACK
4366 capture = self.pg3.get_capture(1)
4367 p = capture[0]
4368 try:
4369 hanat = p[HANATStateSync]
4370 except IndexError:
4371 self.logger.error(ppp("Invalid packet:", p))
4372 raise
4373 else:
4374 self.assertEqual(hanat.sequence_number, 3)
4375 self.assertEqual(hanat.flags, 'ACK')
4376 self.assertEqual(hanat.version, 1)
4377 users = self.vapi.nat44_user_dump()
4378 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004379 self.assertEqual(str(users[0].ip_address),
4380 self.pg0.remote_ip4)
Matus Fabian34931eb2019-02-26 09:05:23 -08004381 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4382 users[0].vrf_id)
4383 self.assertEqual(len(sessions), 1)
4384 session = sessions[0]
4385 self.assertEqual(session.total_bytes, 1024)
4386 self.assertEqual(session.total_pkts, 2)
4387 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4388 self.assertEqual(stats[0][0], 1)
4389
4390 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4391 self.assertEqual(stats, 3)
4392
4393 # send packet to test session created by HA
4394 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4395 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4396 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4397 self.pg1.add_stream(p)
4398 self.pg_enable_capture(self.pg_interfaces)
4399 self.pg_start()
4400 capture = self.pg0.get_capture(1)
4401 p = capture[0]
4402 try:
4403 ip = p[IP]
4404 tcp = p[TCP]
4405 except IndexError:
4406 self.logger.error(ppp("Invalid packet:", p))
4407 raise
4408 else:
4409 self.assertEqual(ip.src, self.pg1.remote_ip4)
4410 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4411 self.assertEqual(tcp.sport, self.tcp_external_port)
4412 self.assertEqual(tcp.dport, self.tcp_port_in)
4413
Matus Fabiana6110b62018-06-13 05:39:07 -07004414 def tearDown(self):
4415 super(TestNAT44, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07004416 self.clear_nat44()
4417 self.vapi.cli("clear logging")
4418
4419 def show_commands_at_teardown(self):
4420 self.logger.info(self.vapi.cli("show nat44 addresses"))
4421 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4422 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4423 self.logger.info(self.vapi.cli("show nat44 interface address"))
4424 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4425 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4426 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4427 self.logger.info(self.vapi.cli("show nat timeouts"))
4428 self.logger.info(
4429 self.vapi.cli("show nat addr-port-assignment-alg"))
4430 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004431
4432
4433class TestNAT44EndpointDependent(MethodHolder):
4434 """ Endpoint-Dependent mapping and filtering test cases """
4435
4436 @classmethod
4437 def setUpConstants(cls):
4438 super(TestNAT44EndpointDependent, cls).setUpConstants()
4439 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4440
4441 @classmethod
4442 def setUpClass(cls):
4443 super(TestNAT44EndpointDependent, cls).setUpClass()
4444 cls.vapi.cli("set log class nat level debug")
4445 try:
4446 cls.tcp_port_in = 6303
4447 cls.tcp_port_out = 6303
4448 cls.udp_port_in = 6304
4449 cls.udp_port_out = 6304
4450 cls.icmp_id_in = 6305
4451 cls.icmp_id_out = 6305
4452 cls.nat_addr = '10.0.0.3'
Matus Fabiana6110b62018-06-13 05:39:07 -07004453 cls.ipfix_src_port = 4739
4454 cls.ipfix_domain_id = 1
4455 cls.tcp_external_port = 80
4456
Matus Fabian8008d7c2018-07-09 01:34:20 -07004457 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004458 cls.interfaces = list(cls.pg_interfaces[0:3])
4459
4460 for i in cls.interfaces:
4461 i.admin_up()
4462 i.config_ip4()
4463 i.resolve_arp()
4464
4465 cls.pg0.generate_remote_hosts(3)
4466 cls.pg0.configure_ipv4_neighbors()
4467
4468 cls.pg3.admin_up()
4469
4470 cls.pg4.generate_remote_hosts(2)
4471 cls.pg4.config_ip4()
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004472 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01004473 cls.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004474 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4475 address_length=24)
Matus Fabiana6110b62018-06-13 05:39:07 -07004476 cls.pg4.admin_up()
4477 cls.pg4.resolve_arp()
4478 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4479 cls.pg4.resolve_arp()
4480
Matus Fabian8008d7c2018-07-09 01:34:20 -07004481 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004482 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004483
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004484 cls.pg5._local_ip4 = "10.1.1.1"
4485 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4486 cls.pg5.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004487 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4488 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4489 socket.AF_INET, cls.pg5.remote_ip4)
4490 cls.pg5.set_table_ip4(1)
4491 cls.pg5.config_ip4()
4492 cls.pg5.admin_up()
4493 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4494 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004495 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004496 next_hop_sw_if_index=cls.pg5.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004497 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004498
Ole Trøan3b0d7e42019-03-15 16:14:41 +00004499 cls.pg6._local_ip4 = "10.1.2.1"
4500 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4501 cls.pg6.local_ip4)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004502 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4503 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4504 socket.AF_INET, cls.pg6.remote_ip4)
4505 cls.pg6.set_table_ip4(1)
4506 cls.pg6.config_ip4()
4507 cls.pg6.admin_up()
4508 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4509 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004510 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004511 next_hop_sw_if_index=cls.pg6.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004512 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004513
4514 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4515 dst_address_length=16,
Ole Troana5b2eec2019-03-11 19:23:25 +01004516 next_hop_address=zero_ip4n, table_id=0,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004517 next_hop_table_id=1)
4518 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4519 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004520 next_hop_address=zero_ip4n, table_id=1,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004521 next_hop_table_id=0)
4522 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4523 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004524 next_hop_address=cls.pg1.local_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004525 next_hop_sw_if_index=cls.pg1.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004526 table_id=0)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004527
4528 cls.pg5.resolve_arp()
4529 cls.pg6.resolve_arp()
4530
Matus Fabiana6110b62018-06-13 05:39:07 -07004531 except Exception:
4532 super(TestNAT44EndpointDependent, cls).tearDownClass()
4533 raise
4534
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07004535 @classmethod
4536 def tearDownClass(cls):
4537 super(TestNAT44EndpointDependent, cls).tearDownClass()
4538
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004539 def test_frag_in_order(self):
4540 """ NAT44 translate fragments arriving in order """
4541 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004542 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004543 self.vapi.nat44_interface_add_del_feature(
4544 sw_if_index=self.pg0.sw_if_index,
4545 flags=flags, is_add=1)
4546 self.vapi.nat44_interface_add_del_feature(
4547 sw_if_index=self.pg1.sw_if_index,
4548 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004549 self.frag_in_order(proto=IP_PROTOS.tcp)
4550 self.frag_in_order(proto=IP_PROTOS.udp)
4551 self.frag_in_order(proto=IP_PROTOS.icmp)
4552
4553 def test_frag_in_order_dont_translate(self):
4554 """ NAT44 don't translate fragments arriving in order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004555 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004556 self.vapi.nat44_interface_add_del_feature(
4557 sw_if_index=self.pg0.sw_if_index,
4558 flags=flags, is_add=1)
4559 self.vapi.nat44_interface_add_del_feature(
4560 sw_if_index=self.pg1.sw_if_index,
4561 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004562 self.vapi.nat44_forwarding_enable_disable(enable=True)
4563 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4564
4565 def test_frag_out_of_order(self):
4566 """ NAT44 translate fragments arriving out of order """
4567 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004568 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004569 self.vapi.nat44_interface_add_del_feature(
4570 sw_if_index=self.pg0.sw_if_index,
4571 flags=flags, is_add=1)
4572 self.vapi.nat44_interface_add_del_feature(
4573 sw_if_index=self.pg1.sw_if_index,
4574 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004575 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4576 self.frag_out_of_order(proto=IP_PROTOS.udp)
4577 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4578
4579 def test_frag_out_of_order_dont_translate(self):
4580 """ NAT44 don't translate fragments arriving out of order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004581 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004582 self.vapi.nat44_interface_add_del_feature(
4583 sw_if_index=self.pg0.sw_if_index,
4584 flags=flags, is_add=1)
4585 self.vapi.nat44_interface_add_del_feature(
4586 sw_if_index=self.pg1.sw_if_index,
4587 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004588 self.vapi.nat44_forwarding_enable_disable(enable=True)
4589 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4590
4591 def test_frag_in_order_in_plus_out(self):
4592 """ in+out interface fragments in order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004593 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004594 self.vapi.nat44_interface_add_del_feature(
4595 sw_if_index=self.pg0.sw_if_index,
4596 is_add=1)
4597 self.vapi.nat44_interface_add_del_feature(
4598 sw_if_index=self.pg0.sw_if_index,
4599 flags=flags, is_add=1)
4600 self.vapi.nat44_interface_add_del_feature(
4601 sw_if_index=self.pg1.sw_if_index,
4602 is_add=1)
4603 self.vapi.nat44_interface_add_del_feature(
4604 sw_if_index=self.pg1.sw_if_index,
4605 flags=flags, is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004606
4607 self.server = self.pg1.remote_hosts[0]
4608
4609 self.server_in_addr = self.server.ip4
4610 self.server_out_addr = '11.11.11.11'
4611 self.server_in_port = random.randint(1025, 65535)
4612 self.server_out_port = random.randint(1025, 65535)
4613
4614 self.nat44_add_address(self.server_out_addr)
4615
4616 # add static mappings for server
4617 self.nat44_add_static_mapping(self.server_in_addr,
4618 self.server_out_addr,
4619 self.server_in_port,
4620 self.server_out_port,
4621 proto=IP_PROTOS.tcp)
4622 self.nat44_add_static_mapping(self.server_in_addr,
4623 self.server_out_addr,
4624 self.server_in_port,
4625 self.server_out_port,
4626 proto=IP_PROTOS.udp)
4627 self.nat44_add_static_mapping(self.server_in_addr,
4628 self.server_out_addr,
4629 proto=IP_PROTOS.icmp)
4630
Filip Vargaf4749ca2019-04-25 14:55:32 +02004631 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4632 drop_frag=0)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004633
4634 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4635 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4636 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4637
4638 def test_frag_out_of_order_in_plus_out(self):
4639 """ in+out interface fragments out of order """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004640 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004641 self.vapi.nat44_interface_add_del_feature(
4642 sw_if_index=self.pg0.sw_if_index,
4643 is_add=1)
4644 self.vapi.nat44_interface_add_del_feature(
4645 sw_if_index=self.pg0.sw_if_index,
4646 flags=flags, is_add=1)
4647 self.vapi.nat44_interface_add_del_feature(
4648 sw_if_index=self.pg1.sw_if_index,
4649 is_add=1)
4650 self.vapi.nat44_interface_add_del_feature(
4651 sw_if_index=self.pg1.sw_if_index,
4652 flags=flags, is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004653
4654 self.server = self.pg1.remote_hosts[0]
4655
4656 self.server_in_addr = self.server.ip4
4657 self.server_out_addr = '11.11.11.11'
4658 self.server_in_port = random.randint(1025, 65535)
4659 self.server_out_port = random.randint(1025, 65535)
4660
4661 self.nat44_add_address(self.server_out_addr)
4662
4663 # add static mappings for server
4664 self.nat44_add_static_mapping(self.server_in_addr,
4665 self.server_out_addr,
4666 self.server_in_port,
4667 self.server_out_port,
4668 proto=IP_PROTOS.tcp)
4669 self.nat44_add_static_mapping(self.server_in_addr,
4670 self.server_out_addr,
4671 self.server_in_port,
4672 self.server_out_port,
4673 proto=IP_PROTOS.udp)
4674 self.nat44_add_static_mapping(self.server_in_addr,
4675 self.server_out_addr,
4676 proto=IP_PROTOS.icmp)
4677
Filip Vargaf4749ca2019-04-25 14:55:32 +02004678 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4679 drop_frag=0)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004680
4681 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4682 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4683 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4684
4685 def test_reass_hairpinning(self):
4686 """ NAT44 fragments hairpinning """
4687 self.server = self.pg0.remote_hosts[1]
4688 self.host_in_port = random.randint(1025, 65535)
4689 self.server_in_port = random.randint(1025, 65535)
4690 self.server_out_port = random.randint(1025, 65535)
4691
4692 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004693 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004694 self.vapi.nat44_interface_add_del_feature(
4695 sw_if_index=self.pg0.sw_if_index,
4696 flags=flags, is_add=1)
4697 self.vapi.nat44_interface_add_del_feature(
4698 sw_if_index=self.pg1.sw_if_index,
4699 is_add=1)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004700 # add static mapping for server
4701 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4702 self.server_in_port,
4703 self.server_out_port,
4704 proto=IP_PROTOS.tcp)
4705 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4706 self.server_in_port,
4707 self.server_out_port,
4708 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004709 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004710
4711 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4712 self.reass_hairpinning(proto=IP_PROTOS.udp)
4713 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4714
Matus Fabiana6110b62018-06-13 05:39:07 -07004715 def test_dynamic(self):
4716 """ NAT44 dynamic translation test """
4717
4718 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004719 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004720 self.vapi.nat44_interface_add_del_feature(
4721 sw_if_index=self.pg0.sw_if_index,
4722 flags=flags, is_add=1)
4723 self.vapi.nat44_interface_add_del_feature(
4724 sw_if_index=self.pg1.sw_if_index,
4725 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004726
Matus Fabian69ce30d2018-08-22 01:27:10 -07004727 nat_config = self.vapi.nat_show_config()
4728 self.assertEqual(1, nat_config.endpoint_dependent)
4729
Matus Fabiana6110b62018-06-13 05:39:07 -07004730 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004731 tcpn = self.statistics.get_counter(
4732 '/err/nat44-ed-in2out-slowpath/TCP packets')
4733 udpn = self.statistics.get_counter(
4734 '/err/nat44-ed-in2out-slowpath/UDP packets')
4735 icmpn = self.statistics.get_counter(
4736 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4737 totaln = self.statistics.get_counter(
4738 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4739
Matus Fabiana6110b62018-06-13 05:39:07 -07004740 pkts = self.create_stream_in(self.pg0, self.pg1)
4741 self.pg0.add_stream(pkts)
4742 self.pg_enable_capture(self.pg_interfaces)
4743 self.pg_start()
4744 capture = self.pg1.get_capture(len(pkts))
4745 self.verify_capture_out(capture)
4746
Matus Fabiana5e73762018-12-14 01:55:16 -08004747 err = self.statistics.get_counter(
4748 '/err/nat44-ed-in2out-slowpath/TCP packets')
4749 self.assertEqual(err - tcpn, 1)
4750 err = self.statistics.get_counter(
4751 '/err/nat44-ed-in2out-slowpath/UDP packets')
4752 self.assertEqual(err - udpn, 1)
4753 err = self.statistics.get_counter(
4754 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4755 self.assertEqual(err - icmpn, 1)
4756 err = self.statistics.get_counter(
4757 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4758 self.assertEqual(err - totaln, 3)
4759
Matus Fabiana6110b62018-06-13 05:39:07 -07004760 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004761 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4762 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4763 icmpn = self.statistics.get_counter(
4764 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4765 totaln = self.statistics.get_counter(
4766 '/err/nat44-ed-out2in/good out2in packets processed')
4767
Matus Fabiana6110b62018-06-13 05:39:07 -07004768 pkts = self.create_stream_out(self.pg1)
4769 self.pg1.add_stream(pkts)
4770 self.pg_enable_capture(self.pg_interfaces)
4771 self.pg_start()
4772 capture = self.pg0.get_capture(len(pkts))
4773 self.verify_capture_in(capture, self.pg0)
4774
Matus Fabiana5e73762018-12-14 01:55:16 -08004775 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4776 self.assertEqual(err - tcpn, 1)
4777 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4778 self.assertEqual(err - udpn, 1)
4779 err = self.statistics.get_counter(
4780 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4781 self.assertEqual(err - icmpn, 1)
4782 err = self.statistics.get_counter(
4783 '/err/nat44-ed-out2in/good out2in packets processed')
4784 self.assertEqual(err - totaln, 2)
4785
Matus Fabianfd0d5082018-12-18 01:08:51 -08004786 users = self.statistics.get_counter('/nat44/total-users')
4787 self.assertEqual(users[0][0], 1)
4788 sessions = self.statistics.get_counter('/nat44/total-sessions')
4789 self.assertEqual(sessions[0][0], 3)
4790
Matus Fabiana6110b62018-06-13 05:39:07 -07004791 def test_forwarding(self):
4792 """ NAT44 forwarding test """
4793
Filip Vargadd1e3e72019-04-15 18:52:43 +02004794 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004795 self.vapi.nat44_interface_add_del_feature(
4796 sw_if_index=self.pg0.sw_if_index,
4797 flags=flags, is_add=1)
4798 self.vapi.nat44_interface_add_del_feature(
4799 sw_if_index=self.pg1.sw_if_index,
4800 is_add=1)
4801 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004802
Filip Vargadd1e3e72019-04-15 18:52:43 +02004803 real_ip = self.pg0.remote_ip4
4804 alias_ip = self.nat_addr
4805 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02004806 self.vapi.nat44_add_del_static_mapping(is_add=1,
4807 local_ip_address=real_ip,
4808 external_ip_address=alias_ip,
4809 external_sw_if_index=0xFFFFFFFF,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004810 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07004811
4812 try:
4813 # in2out - static mapping match
4814
4815 pkts = self.create_stream_out(self.pg1)
4816 self.pg1.add_stream(pkts)
4817 self.pg_enable_capture(self.pg_interfaces)
4818 self.pg_start()
4819 capture = self.pg0.get_capture(len(pkts))
4820 self.verify_capture_in(capture, self.pg0)
4821
4822 pkts = self.create_stream_in(self.pg0, self.pg1)
4823 self.pg0.add_stream(pkts)
4824 self.pg_enable_capture(self.pg_interfaces)
4825 self.pg_start()
4826 capture = self.pg1.get_capture(len(pkts))
4827 self.verify_capture_out(capture, same_port=True)
4828
4829 # in2out - no static mapping match
4830
4831 host0 = self.pg0.remote_hosts[0]
4832 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4833 try:
4834 pkts = self.create_stream_out(self.pg1,
4835 dst_ip=self.pg0.remote_ip4,
4836 use_inside_ports=True)
4837 self.pg1.add_stream(pkts)
4838 self.pg_enable_capture(self.pg_interfaces)
4839 self.pg_start()
4840 capture = self.pg0.get_capture(len(pkts))
4841 self.verify_capture_in(capture, self.pg0)
4842
4843 pkts = self.create_stream_in(self.pg0, self.pg1)
4844 self.pg0.add_stream(pkts)
4845 self.pg_enable_capture(self.pg_interfaces)
4846 self.pg_start()
4847 capture = self.pg1.get_capture(len(pkts))
4848 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4849 same_port=True)
4850 finally:
4851 self.pg0.remote_hosts[0] = host0
4852
4853 user = self.pg0.remote_hosts[1]
4854 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4855 self.assertEqual(len(sessions), 3)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004856 self.assertTrue(sessions[0].flags &
4857 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabiana6110b62018-06-13 05:39:07 -07004858 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02004859 address=sessions[0].inside_ip_address,
4860 port=sessions[0].inside_port,
4861 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004862 flags=(self.config_flags.NAT_IS_INSIDE |
4863 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabiana6110b62018-06-13 05:39:07 -07004864 ext_host_address=sessions[0].ext_host_address,
4865 ext_host_port=sessions[0].ext_host_port)
4866 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4867 self.assertEqual(len(sessions), 2)
4868
4869 finally:
Filip Vargaf4749ca2019-04-25 14:55:32 +02004870 self.vapi.nat44_forwarding_enable_disable(enable=0)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004871 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02004872 self.vapi.nat44_add_del_static_mapping(
4873 is_add=0,
4874 local_ip_address=real_ip,
4875 external_ip_address=alias_ip,
4876 external_sw_if_index=0xFFFFFFFF,
4877 flags=flags)
Matus Fabiana6110b62018-06-13 05:39:07 -07004878
4879 def test_static_lb(self):
4880 """ NAT44 local service load balancing """
Filip Vargadd1e3e72019-04-15 18:52:43 +02004881 external_addr_n = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004882 external_port = 80
4883 local_port = 8080
4884 server1 = self.pg0.remote_hosts[0]
4885 server2 = self.pg0.remote_hosts[1]
4886
4887 locals = [{'addr': server1.ip4n,
4888 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004889 'probability': 70,
4890 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004891 {'addr': server2.ip4n,
4892 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004893 'probability': 30,
4894 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004895
4896 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02004897 self.vapi.nat44_add_del_lb_static_mapping(
4898 is_add=1,
4899 external_addr=external_addr_n,
4900 external_port=external_port,
4901 protocol=IP_PROTOS.tcp,
4902 local_num=len(locals),
4903 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004904 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004905 self.vapi.nat44_interface_add_del_feature(
4906 sw_if_index=self.pg0.sw_if_index,
4907 flags=flags, is_add=1)
4908 self.vapi.nat44_interface_add_del_feature(
4909 sw_if_index=self.pg1.sw_if_index,
4910 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004911
4912 # from client to service
4913 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4914 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4915 TCP(sport=12345, dport=external_port))
4916 self.pg1.add_stream(p)
4917 self.pg_enable_capture(self.pg_interfaces)
4918 self.pg_start()
4919 capture = self.pg0.get_capture(1)
4920 p = capture[0]
4921 server = None
4922 try:
4923 ip = p[IP]
4924 tcp = p[TCP]
4925 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4926 if ip.dst == server1.ip4:
4927 server = server1
4928 else:
4929 server = server2
4930 self.assertEqual(tcp.dport, local_port)
4931 self.assert_packet_checksums_valid(p)
4932 except:
4933 self.logger.error(ppp("Unexpected or invalid packet:", p))
4934 raise
4935
4936 # from service back to client
4937 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4938 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4939 TCP(sport=local_port, dport=12345))
4940 self.pg0.add_stream(p)
4941 self.pg_enable_capture(self.pg_interfaces)
4942 self.pg_start()
4943 capture = self.pg1.get_capture(1)
4944 p = capture[0]
4945 try:
4946 ip = p[IP]
4947 tcp = p[TCP]
4948 self.assertEqual(ip.src, self.nat_addr)
4949 self.assertEqual(tcp.sport, external_port)
4950 self.assert_packet_checksums_valid(p)
4951 except:
4952 self.logger.error(ppp("Unexpected or invalid packet:", p))
4953 raise
4954
4955 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4956 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004957 self.assertTrue(sessions[0].flags &
4958 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabiana6110b62018-06-13 05:39:07 -07004959 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02004960 address=sessions[0].inside_ip_address,
4961 port=sessions[0].inside_port,
4962 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02004963 flags=(self.config_flags.NAT_IS_INSIDE |
4964 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabiana6110b62018-06-13 05:39:07 -07004965 ext_host_address=sessions[0].ext_host_address,
4966 ext_host_port=sessions[0].ext_host_port)
4967 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4968 self.assertEqual(len(sessions), 0)
4969
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004970 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004971 def test_static_lb_multi_clients(self):
4972 """ NAT44 local service load balancing - multiple clients"""
4973
Filip Vargadd1e3e72019-04-15 18:52:43 +02004974 external_addr = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07004975 external_port = 80
4976 local_port = 8080
4977 server1 = self.pg0.remote_hosts[0]
4978 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004979 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004980
4981 locals = [{'addr': server1.ip4n,
4982 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004983 'probability': 90,
4984 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004985 {'addr': server2.ip4n,
4986 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004987 'probability': 10,
4988 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004989
4990 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02004991 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4992 external_addr=external_addr,
4993 external_port=external_port,
4994 protocol=IP_PROTOS.tcp,
Matus Fabiana6110b62018-06-13 05:39:07 -07004995 local_num=len(locals),
4996 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02004997 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02004998 self.vapi.nat44_interface_add_del_feature(
4999 sw_if_index=self.pg0.sw_if_index,
5000 flags=flags, is_add=1)
5001 self.vapi.nat44_interface_add_del_feature(
5002 sw_if_index=self.pg1.sw_if_index,
5003 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005004
5005 server1_n = 0
5006 server2_n = 0
5007 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
5008 pkts = []
5009 for client in clients:
5010 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5011 IP(src=client, dst=self.nat_addr) /
5012 TCP(sport=12345, dport=external_port))
5013 pkts.append(p)
5014 self.pg1.add_stream(pkts)
5015 self.pg_enable_capture(self.pg_interfaces)
5016 self.pg_start()
5017 capture = self.pg0.get_capture(len(pkts))
5018 for p in capture:
5019 if p[IP].dst == server1.ip4:
5020 server1_n += 1
5021 else:
5022 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08005023 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07005024
Filip Vargaf4749ca2019-04-25 14:55:32 +02005025 local = {
5026 'addr': server3.ip4n,
5027 'port': local_port,
5028 'probability': 20,
5029 'vrf_id': 0
5030 }
5031
Matus Fabianb6865082018-12-06 03:11:09 -08005032 # add new back-end
Filip Vargaf4749ca2019-04-25 14:55:32 +02005033 self.vapi.nat44_lb_static_mapping_add_del_local(
5034 is_add=1,
5035 external_addr=external_addr,
5036 external_port=external_port,
5037 local=local,
5038 protocol=IP_PROTOS.tcp)
Matus Fabianb6865082018-12-06 03:11:09 -08005039 server1_n = 0
5040 server2_n = 0
5041 server3_n = 0
5042 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5043 pkts = []
5044 for client in clients:
5045 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5046 IP(src=client, dst=self.nat_addr) /
5047 TCP(sport=12346, dport=external_port))
5048 pkts.append(p)
5049 self.assertGreater(len(pkts), 0)
5050 self.pg1.add_stream(pkts)
5051 self.pg_enable_capture(self.pg_interfaces)
5052 self.pg_start()
5053 capture = self.pg0.get_capture(len(pkts))
5054 for p in capture:
5055 if p[IP].dst == server1.ip4:
5056 server1_n += 1
5057 elif p[IP].dst == server2.ip4:
5058 server2_n += 1
5059 else:
5060 server3_n += 1
5061 self.assertGreater(server1_n, 0)
5062 self.assertGreater(server2_n, 0)
5063 self.assertGreater(server3_n, 0)
5064
Filip Vargaf4749ca2019-04-25 14:55:32 +02005065 local = {
5066 'addr': server2.ip4n,
5067 'port': local_port,
5068 'probability': 10,
5069 'vrf_id': 0
5070 }
5071
Matus Fabianb6865082018-12-06 03:11:09 -08005072 # remove one back-end
Filip Vargaf4749ca2019-04-25 14:55:32 +02005073 self.vapi.nat44_lb_static_mapping_add_del_local(
5074 is_add=0,
5075 external_addr=external_addr,
5076 external_port=external_port,
5077 local=local,
5078 protocol=IP_PROTOS.tcp)
Matus Fabianb6865082018-12-06 03:11:09 -08005079 server1_n = 0
5080 server2_n = 0
5081 server3_n = 0
5082 self.pg1.add_stream(pkts)
5083 self.pg_enable_capture(self.pg_interfaces)
5084 self.pg_start()
5085 capture = self.pg0.get_capture(len(pkts))
5086 for p in capture:
5087 if p[IP].dst == server1.ip4:
5088 server1_n += 1
5089 elif p[IP].dst == server2.ip4:
5090 server2_n += 1
5091 else:
5092 server3_n += 1
5093 self.assertGreater(server1_n, 0)
5094 self.assertEqual(server2_n, 0)
5095 self.assertGreater(server3_n, 0)
5096
Matus Fabiana6110b62018-06-13 05:39:07 -07005097 def test_static_lb_2(self):
5098 """ NAT44 local service load balancing (asymmetrical rule) """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005099 external_addr = self.nat_addr
Matus Fabiana6110b62018-06-13 05:39:07 -07005100 external_port = 80
5101 local_port = 8080
5102 server1 = self.pg0.remote_hosts[0]
5103 server2 = self.pg0.remote_hosts[1]
5104
5105 locals = [{'addr': server1.ip4n,
5106 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005107 'probability': 70,
5108 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07005109 {'addr': server2.ip4n,
5110 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005111 'probability': 30,
5112 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07005113
Filip Vargaf4749ca2019-04-25 14:55:32 +02005114 self.vapi.nat44_forwarding_enable_disable(enable=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005115 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02005116 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5117 external_addr=external_addr,
5118 external_port=external_port,
5119 protocol=IP_PROTOS.tcp,
Matus Fabiana6110b62018-06-13 05:39:07 -07005120 local_num=len(locals),
Filip Vargaf4749ca2019-04-25 14:55:32 +02005121 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005122 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005123 self.vapi.nat44_interface_add_del_feature(
5124 sw_if_index=self.pg0.sw_if_index,
5125 flags=flags, is_add=1)
5126 self.vapi.nat44_interface_add_del_feature(
5127 sw_if_index=self.pg1.sw_if_index,
5128 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005129
5130 # from client to service
5131 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5132 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5133 TCP(sport=12345, dport=external_port))
5134 self.pg1.add_stream(p)
5135 self.pg_enable_capture(self.pg_interfaces)
5136 self.pg_start()
5137 capture = self.pg0.get_capture(1)
5138 p = capture[0]
5139 server = None
5140 try:
5141 ip = p[IP]
5142 tcp = p[TCP]
5143 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5144 if ip.dst == server1.ip4:
5145 server = server1
5146 else:
5147 server = server2
5148 self.assertEqual(tcp.dport, local_port)
5149 self.assert_packet_checksums_valid(p)
5150 except:
5151 self.logger.error(ppp("Unexpected or invalid packet:", p))
5152 raise
5153
5154 # from service back to client
5155 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5156 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5157 TCP(sport=local_port, dport=12345))
5158 self.pg0.add_stream(p)
5159 self.pg_enable_capture(self.pg_interfaces)
5160 self.pg_start()
5161 capture = self.pg1.get_capture(1)
5162 p = capture[0]
5163 try:
5164 ip = p[IP]
5165 tcp = p[TCP]
5166 self.assertEqual(ip.src, self.nat_addr)
5167 self.assertEqual(tcp.sport, external_port)
5168 self.assert_packet_checksums_valid(p)
5169 except:
5170 self.logger.error(ppp("Unexpected or invalid packet:", p))
5171 raise
5172
5173 # from client to server (no translation)
5174 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5175 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5176 TCP(sport=12346, dport=local_port))
5177 self.pg1.add_stream(p)
5178 self.pg_enable_capture(self.pg_interfaces)
5179 self.pg_start()
5180 capture = self.pg0.get_capture(1)
5181 p = capture[0]
5182 server = None
5183 try:
5184 ip = p[IP]
5185 tcp = p[TCP]
5186 self.assertEqual(ip.dst, server1.ip4)
5187 self.assertEqual(tcp.dport, local_port)
5188 self.assert_packet_checksums_valid(p)
5189 except:
5190 self.logger.error(ppp("Unexpected or invalid packet:", p))
5191 raise
5192
5193 # from service back to client (no translation)
5194 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5195 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5196 TCP(sport=local_port, dport=12346))
5197 self.pg0.add_stream(p)
5198 self.pg_enable_capture(self.pg_interfaces)
5199 self.pg_start()
5200 capture = self.pg1.get_capture(1)
5201 p = capture[0]
5202 try:
5203 ip = p[IP]
5204 tcp = p[TCP]
5205 self.assertEqual(ip.src, server1.ip4)
5206 self.assertEqual(tcp.sport, local_port)
5207 self.assert_packet_checksums_valid(p)
5208 except:
5209 self.logger.error(ppp("Unexpected or invalid packet:", p))
5210 raise
5211
Matus Fabianea5b5be2018-09-03 05:02:23 -07005212 def test_lb_affinity(self):
5213 """ NAT44 local service load balancing affinity """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005214 external_addr = self.nat_addr
Matus Fabianea5b5be2018-09-03 05:02:23 -07005215 external_port = 80
5216 local_port = 8080
5217 server1 = self.pg0.remote_hosts[0]
5218 server2 = self.pg0.remote_hosts[1]
5219
5220 locals = [{'addr': server1.ip4n,
5221 'port': local_port,
5222 'probability': 50,
5223 'vrf_id': 0},
5224 {'addr': server2.ip4n,
5225 'port': local_port,
5226 'probability': 50,
5227 'vrf_id': 0}]
5228
5229 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02005230 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5231 external_addr=external_addr,
5232 external_port=external_port,
5233 protocol=IP_PROTOS.tcp,
Matus Fabianea5b5be2018-09-03 05:02:23 -07005234 affinity=10800,
5235 local_num=len(locals),
5236 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005237 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005238 self.vapi.nat44_interface_add_del_feature(
5239 sw_if_index=self.pg0.sw_if_index,
5240 flags=flags, is_add=1)
5241 self.vapi.nat44_interface_add_del_feature(
5242 sw_if_index=self.pg1.sw_if_index,
5243 is_add=1)
Matus Fabianea5b5be2018-09-03 05:02:23 -07005244
5245 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5246 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5247 TCP(sport=1025, dport=external_port))
5248 self.pg1.add_stream(p)
5249 self.pg_enable_capture(self.pg_interfaces)
5250 self.pg_start()
5251 capture = self.pg0.get_capture(1)
5252 backend = capture[0][IP].dst
5253
Filip Vargadd1e3e72019-04-15 18:52:43 +02005254 sessions = self.vapi.nat44_user_session_dump(backend, 0)
Matus Fabianea5b5be2018-09-03 05:02:23 -07005255 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005256 self.assertTrue(sessions[0].flags &
5257 self.config_flags.NAT_IS_EXT_HOST_VALID)
Matus Fabianea5b5be2018-09-03 05:02:23 -07005258 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02005259 address=sessions[0].inside_ip_address,
5260 port=sessions[0].inside_port,
5261 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005262 flags=(self.config_flags.NAT_IS_INSIDE |
5263 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabianea5b5be2018-09-03 05:02:23 -07005264 ext_host_address=sessions[0].ext_host_address,
5265 ext_host_port=sessions[0].ext_host_port)
5266
5267 pkts = []
5268 for port in range(1030, 1100):
5269 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5270 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5271 TCP(sport=port, dport=external_port))
5272 pkts.append(p)
5273 self.pg1.add_stream(pkts)
5274 self.pg_enable_capture(self.pg_interfaces)
5275 self.pg_start()
5276 capture = self.pg0.get_capture(len(pkts))
5277 for p in capture:
5278 self.assertEqual(p[IP].dst, backend)
5279
Matus Fabiana6110b62018-06-13 05:39:07 -07005280 def test_unknown_proto(self):
5281 """ NAT44 translate packet with unknown protocol """
5282 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005283 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005284 self.vapi.nat44_interface_add_del_feature(
5285 sw_if_index=self.pg0.sw_if_index,
5286 flags=flags, is_add=1)
5287 self.vapi.nat44_interface_add_del_feature(
5288 sw_if_index=self.pg1.sw_if_index,
5289 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005290
5291 # in2out
5292 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5293 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5294 TCP(sport=self.tcp_port_in, dport=20))
5295 self.pg0.add_stream(p)
5296 self.pg_enable_capture(self.pg_interfaces)
5297 self.pg_start()
5298 p = self.pg1.get_capture(1)
5299
5300 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5301 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5302 GRE() /
5303 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5304 TCP(sport=1234, dport=1234))
5305 self.pg0.add_stream(p)
5306 self.pg_enable_capture(self.pg_interfaces)
5307 self.pg_start()
5308 p = self.pg1.get_capture(1)
5309 packet = p[0]
5310 try:
5311 self.assertEqual(packet[IP].src, self.nat_addr)
5312 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005313 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005314 self.assert_packet_checksums_valid(packet)
5315 except:
5316 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5317 raise
5318
5319 # out2in
5320 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5321 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5322 GRE() /
5323 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5324 TCP(sport=1234, dport=1234))
5325 self.pg1.add_stream(p)
5326 self.pg_enable_capture(self.pg_interfaces)
5327 self.pg_start()
5328 p = self.pg0.get_capture(1)
5329 packet = p[0]
5330 try:
5331 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5332 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005333 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005334 self.assert_packet_checksums_valid(packet)
5335 except:
5336 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5337 raise
5338
5339 def test_hairpinning_unknown_proto(self):
5340 """ NAT44 translate packet with unknown protocol - hairpinning """
5341 host = self.pg0.remote_hosts[0]
5342 server = self.pg0.remote_hosts[1]
5343 host_in_port = 1234
5344 server_out_port = 8765
5345 server_nat_ip = "10.0.0.11"
5346
5347 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005348 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005349 self.vapi.nat44_interface_add_del_feature(
5350 sw_if_index=self.pg0.sw_if_index,
5351 flags=flags, is_add=1)
5352 self.vapi.nat44_interface_add_del_feature(
5353 sw_if_index=self.pg1.sw_if_index,
5354 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005355
5356 # add static mapping for server
5357 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5358
5359 # host to server
5360 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5361 IP(src=host.ip4, dst=server_nat_ip) /
5362 TCP(sport=host_in_port, dport=server_out_port))
5363 self.pg0.add_stream(p)
5364 self.pg_enable_capture(self.pg_interfaces)
5365 self.pg_start()
5366 self.pg0.get_capture(1)
5367
5368 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5369 IP(src=host.ip4, dst=server_nat_ip) /
5370 GRE() /
5371 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5372 TCP(sport=1234, dport=1234))
5373 self.pg0.add_stream(p)
5374 self.pg_enable_capture(self.pg_interfaces)
5375 self.pg_start()
5376 p = self.pg0.get_capture(1)
5377 packet = p[0]
5378 try:
5379 self.assertEqual(packet[IP].src, self.nat_addr)
5380 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005381 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005382 self.assert_packet_checksums_valid(packet)
5383 except:
5384 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5385 raise
5386
5387 # server to host
5388 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5389 IP(src=server.ip4, dst=self.nat_addr) /
5390 GRE() /
5391 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5392 TCP(sport=1234, dport=1234))
5393 self.pg0.add_stream(p)
5394 self.pg_enable_capture(self.pg_interfaces)
5395 self.pg_start()
5396 p = self.pg0.get_capture(1)
5397 packet = p[0]
5398 try:
5399 self.assertEqual(packet[IP].src, server_nat_ip)
5400 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005401 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005402 self.assert_packet_checksums_valid(packet)
5403 except:
5404 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5405 raise
5406
5407 def test_output_feature_and_service(self):
5408 """ NAT44 interface output feature and services """
5409 external_addr = '1.2.3.4'
5410 external_port = 80
5411 local_port = 8080
5412
Filip Vargaf4749ca2019-04-25 14:55:32 +02005413 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005414 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005415 flags = self.config_flags.NAT_IS_ADDR_ONLY
Filip Vargaf4749ca2019-04-25 14:55:32 +02005416 self.vapi.nat44_add_del_identity_mapping(
5417 ip_address=self.pg1.remote_ip4n, sw_if_index=0xFFFFFFFF,
5418 flags=flags, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005419 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005420 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5421 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005422 proto=IP_PROTOS.tcp, flags=flags)
5423 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005424 self.vapi.nat44_interface_add_del_feature(
5425 sw_if_index=self.pg0.sw_if_index,
5426 is_add=1)
5427 self.vapi.nat44_interface_add_del_feature(
5428 sw_if_index=self.pg0.sw_if_index,
5429 flags=flags, is_add=1)
5430 self.vapi.nat44_interface_add_del_output_feature(
5431 is_add=1,
5432 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005433
5434 # from client to service
5435 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5436 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5437 TCP(sport=12345, dport=external_port))
5438 self.pg1.add_stream(p)
5439 self.pg_enable_capture(self.pg_interfaces)
5440 self.pg_start()
5441 capture = self.pg0.get_capture(1)
5442 p = capture[0]
5443 try:
5444 ip = p[IP]
5445 tcp = p[TCP]
5446 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5447 self.assertEqual(tcp.dport, local_port)
5448 self.assert_packet_checksums_valid(p)
5449 except:
5450 self.logger.error(ppp("Unexpected or invalid packet:", p))
5451 raise
5452
5453 # from service back to client
5454 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5455 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5456 TCP(sport=local_port, dport=12345))
5457 self.pg0.add_stream(p)
5458 self.pg_enable_capture(self.pg_interfaces)
5459 self.pg_start()
5460 capture = self.pg1.get_capture(1)
5461 p = capture[0]
5462 try:
5463 ip = p[IP]
5464 tcp = p[TCP]
5465 self.assertEqual(ip.src, external_addr)
5466 self.assertEqual(tcp.sport, external_port)
5467 self.assert_packet_checksums_valid(p)
5468 except:
5469 self.logger.error(ppp("Unexpected or invalid packet:", p))
5470 raise
5471
5472 # from local network host to external network
5473 pkts = self.create_stream_in(self.pg0, self.pg1)
5474 self.pg0.add_stream(pkts)
5475 self.pg_enable_capture(self.pg_interfaces)
5476 self.pg_start()
5477 capture = self.pg1.get_capture(len(pkts))
5478 self.verify_capture_out(capture)
5479 pkts = self.create_stream_in(self.pg0, self.pg1)
5480 self.pg0.add_stream(pkts)
5481 self.pg_enable_capture(self.pg_interfaces)
5482 self.pg_start()
5483 capture = self.pg1.get_capture(len(pkts))
5484 self.verify_capture_out(capture)
5485
5486 # from external network back to local network host
5487 pkts = self.create_stream_out(self.pg1)
5488 self.pg1.add_stream(pkts)
5489 self.pg_enable_capture(self.pg_interfaces)
5490 self.pg_start()
5491 capture = self.pg0.get_capture(len(pkts))
5492 self.verify_capture_in(capture, self.pg0)
5493
5494 def test_output_feature_and_service2(self):
5495 """ NAT44 interface output feature and service host direct access """
Filip Vargaf4749ca2019-04-25 14:55:32 +02005496 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005497 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02005498 self.vapi.nat44_interface_add_del_output_feature(
5499 is_add=1,
5500 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005501
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005502 # session initiated from service host - translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005503 pkts = self.create_stream_in(self.pg0, self.pg1)
5504 self.pg0.add_stream(pkts)
5505 self.pg_enable_capture(self.pg_interfaces)
5506 self.pg_start()
5507 capture = self.pg1.get_capture(len(pkts))
5508 self.verify_capture_out(capture)
5509
5510 pkts = self.create_stream_out(self.pg1)
5511 self.pg1.add_stream(pkts)
5512 self.pg_enable_capture(self.pg_interfaces)
5513 self.pg_start()
5514 capture = self.pg0.get_capture(len(pkts))
5515 self.verify_capture_in(capture, self.pg0)
5516
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07005517 # session initiated from remote host - do not translate
Matus Fabiana6110b62018-06-13 05:39:07 -07005518 self.tcp_port_in = 60303
5519 self.udp_port_in = 60304
5520 self.icmp_id_in = 60305
5521 pkts = self.create_stream_out(self.pg1,
5522 self.pg0.remote_ip4,
5523 use_inside_ports=True)
5524 self.pg1.add_stream(pkts)
5525 self.pg_enable_capture(self.pg_interfaces)
5526 self.pg_start()
5527 capture = self.pg0.get_capture(len(pkts))
5528 self.verify_capture_in(capture, self.pg0)
5529
5530 pkts = self.create_stream_in(self.pg0, self.pg1)
5531 self.pg0.add_stream(pkts)
5532 self.pg_enable_capture(self.pg_interfaces)
5533 self.pg_start()
5534 capture = self.pg1.get_capture(len(pkts))
5535 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5536 same_port=True)
5537
5538 def test_output_feature_and_service3(self):
5539 """ NAT44 interface output feature and DST NAT """
5540 external_addr = '1.2.3.4'
5541 external_port = 80
5542 local_port = 8080
5543
Filip Vargaf4749ca2019-04-25 14:55:32 +02005544 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005545 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005546 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07005547 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5548 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005549 proto=IP_PROTOS.tcp, flags=flags)
5550 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005551 self.vapi.nat44_interface_add_del_feature(
5552 sw_if_index=self.pg0.sw_if_index,
5553 is_add=1)
5554 self.vapi.nat44_interface_add_del_feature(
5555 sw_if_index=self.pg0.sw_if_index,
5556 flags=flags, is_add=1)
5557 self.vapi.nat44_interface_add_del_output_feature(
5558 is_add=1,
5559 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana6110b62018-06-13 05:39:07 -07005560
5561 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5562 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5563 TCP(sport=12345, dport=external_port))
5564 self.pg0.add_stream(p)
5565 self.pg_enable_capture(self.pg_interfaces)
5566 self.pg_start()
5567 capture = self.pg1.get_capture(1)
5568 p = capture[0]
5569 try:
5570 ip = p[IP]
5571 tcp = p[TCP]
5572 self.assertEqual(ip.src, self.pg0.remote_ip4)
5573 self.assertEqual(tcp.sport, 12345)
5574 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5575 self.assertEqual(tcp.dport, local_port)
5576 self.assert_packet_checksums_valid(p)
5577 except:
5578 self.logger.error(ppp("Unexpected or invalid packet:", p))
5579 raise
5580
5581 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5582 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5583 TCP(sport=local_port, dport=12345))
5584 self.pg1.add_stream(p)
5585 self.pg_enable_capture(self.pg_interfaces)
5586 self.pg_start()
5587 capture = self.pg0.get_capture(1)
5588 p = capture[0]
5589 try:
5590 ip = p[IP]
5591 tcp = p[TCP]
5592 self.assertEqual(ip.src, external_addr)
5593 self.assertEqual(tcp.sport, external_port)
5594 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5595 self.assertEqual(tcp.dport, 12345)
5596 self.assert_packet_checksums_valid(p)
5597 except:
5598 self.logger.error(ppp("Unexpected or invalid packet:", p))
5599 raise
5600
Matus Fabian182e37e2018-08-14 04:21:26 -07005601 def test_next_src_nat(self):
5602 """ On way back forward packet to nat44-in2out node. """
5603 twice_nat_addr = '10.0.1.3'
5604 external_port = 80
5605 local_port = 8080
5606 post_twice_nat_port = 0
5607
Filip Vargaf4749ca2019-04-25 14:55:32 +02005608 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian182e37e2018-08-14 04:21:26 -07005609 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005610 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5611 self.config_flags.NAT_IS_SELF_TWICE_NAT)
Matus Fabian182e37e2018-08-14 04:21:26 -07005612 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5613 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005614 proto=IP_PROTOS.tcp, vrf_id=1,
5615 flags=flags)
Filip Vargaf4749ca2019-04-25 14:55:32 +02005616 self.vapi.nat44_interface_add_del_feature(
5617 sw_if_index=self.pg6.sw_if_index,
5618 is_add=1)
Matus Fabian182e37e2018-08-14 04:21:26 -07005619
5620 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5621 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5622 TCP(sport=12345, dport=external_port))
5623 self.pg6.add_stream(p)
5624 self.pg_enable_capture(self.pg_interfaces)
5625 self.pg_start()
5626 capture = self.pg6.get_capture(1)
5627 p = capture[0]
5628 try:
5629 ip = p[IP]
5630 tcp = p[TCP]
5631 self.assertEqual(ip.src, twice_nat_addr)
5632 self.assertNotEqual(tcp.sport, 12345)
5633 post_twice_nat_port = tcp.sport
5634 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5635 self.assertEqual(tcp.dport, local_port)
5636 self.assert_packet_checksums_valid(p)
5637 except:
5638 self.logger.error(ppp("Unexpected or invalid packet:", p))
5639 raise
5640
5641 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5642 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5643 TCP(sport=local_port, dport=post_twice_nat_port))
5644 self.pg6.add_stream(p)
5645 self.pg_enable_capture(self.pg_interfaces)
5646 self.pg_start()
5647 capture = self.pg6.get_capture(1)
5648 p = capture[0]
5649 try:
5650 ip = p[IP]
5651 tcp = p[TCP]
5652 self.assertEqual(ip.src, self.pg1.remote_ip4)
5653 self.assertEqual(tcp.sport, external_port)
5654 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5655 self.assertEqual(tcp.dport, 12345)
5656 self.assert_packet_checksums_valid(p)
5657 except:
5658 self.logger.error(ppp("Unexpected or invalid packet:", p))
5659 raise
5660
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005661 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5662 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005663 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005664
Matus Fabianb932d262017-12-18 05:38:24 -08005665 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005666 if lb:
5667 if not same_pg:
5668 port_in1 = port_in
5669 port_in2 = port_in
5670 else:
Ole Troan9a475372019-03-05 16:58:24 +01005671 port_in1 = port_in + 1
5672 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005673
Matus Fabianb932d262017-12-18 05:38:24 -08005674 port_out = 80
5675 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005676
5677 server1 = self.pg0.remote_hosts[0]
5678 server2 = self.pg0.remote_hosts[1]
5679 if lb and same_pg:
5680 server2 = server1
5681 if not lb:
5682 server = server1
5683
5684 pg0 = self.pg0
5685 if same_pg:
5686 pg1 = self.pg0
5687 else:
5688 pg1 = self.pg1
5689
5690 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5691 client_id == 1)
5692
Matus Fabianb932d262017-12-18 05:38:24 -08005693 self.nat44_add_address(self.nat_addr)
5694 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005695
5696 flags = 0
5697 if self_twice_nat:
5698 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5699 else:
5700 flags |= self.config_flags.NAT_IS_TWICE_NAT
5701
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005702 if not lb:
5703 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5704 port_in, port_out,
5705 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005706 flags=flags)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005707 else:
5708 locals = [{'addr': server1.ip4n,
5709 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005710 'probability': 50,
5711 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005712 {'addr': server2.ip4n,
5713 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005714 'probability': 50,
5715 'vrf_id': 0}]
Filip Vargadd1e3e72019-04-15 18:52:43 +02005716 out_addr = self.nat_addr
5717
Filip Vargaf4749ca2019-04-25 14:55:32 +02005718 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5719 external_addr=out_addr,
5720 external_port=port_out,
5721 protocol=IP_PROTOS.tcp,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005722 local_num=len(locals),
Filip Vargaf4749ca2019-04-25 14:55:32 +02005723 locals=locals)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005724 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005725 self.vapi.nat44_interface_add_del_feature(
5726 sw_if_index=pg0.sw_if_index,
5727 flags=flags, is_add=1)
5728 self.vapi.nat44_interface_add_del_feature(
5729 sw_if_index=pg1.sw_if_index,
5730 is_add=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005731
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005732 if same_pg:
5733 if not lb:
5734 client = server
5735 else:
5736 assert client_id is not None
5737 if client_id == 1:
5738 client = self.pg0.remote_hosts[0]
5739 elif client_id == 2:
5740 client = self.pg0.remote_hosts[1]
5741 else:
5742 client = pg1.remote_hosts[0]
5743 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5744 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005745 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005746 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005747 self.pg_enable_capture(self.pg_interfaces)
5748 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005749 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005750 p = capture[0]
5751 try:
5752 ip = p[IP]
5753 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005754 if lb:
5755 if ip.dst == server1.ip4:
5756 server = server1
5757 port_in = port_in1
5758 else:
5759 server = server2
5760 port_in = port_in2
5761 self.assertEqual(ip.dst, server.ip4)
5762 if lb and same_pg:
5763 self.assertIn(tcp.dport, [port_in1, port_in2])
5764 else:
5765 self.assertEqual(tcp.dport, port_in)
5766 if eh_translate:
5767 self.assertEqual(ip.src, twice_nat_addr)
5768 self.assertNotEqual(tcp.sport, eh_port_out)
5769 else:
5770 self.assertEqual(ip.src, client.ip4)
5771 self.assertEqual(tcp.sport, eh_port_out)
5772 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005773 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005774 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005775 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005776 except:
5777 self.logger.error(ppp("Unexpected or invalid packet:", p))
5778 raise
5779
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005780 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5781 IP(src=server.ip4, dst=eh_addr_in) /
5782 TCP(sport=saved_port_in, dport=eh_port_in))
5783 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005784 self.pg_enable_capture(self.pg_interfaces)
5785 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005786 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005787 p = capture[0]
5788 try:
5789 ip = p[IP]
5790 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005791 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005792 self.assertEqual(ip.src, self.nat_addr)
5793 self.assertEqual(tcp.dport, eh_port_out)
5794 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005795 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005796 except:
5797 self.logger.error(ppp("Unexpected or invalid packet:", p))
5798 raise
5799
Matus Fabian70a26ac2018-05-14 06:20:28 -07005800 if eh_translate:
5801 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5802 self.assertEqual(len(sessions), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005803 self.assertTrue(sessions[0].flags &
5804 self.config_flags.NAT_IS_EXT_HOST_VALID)
5805 self.assertTrue(sessions[0].flags &
5806 self.config_flags.NAT_IS_TWICE_NAT)
5807 self.logger.error(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian70a26ac2018-05-14 06:20:28 -07005808 self.vapi.nat44_del_session(
Filip Vargaf4749ca2019-04-25 14:55:32 +02005809 address=sessions[0].inside_ip_address,
5810 port=sessions[0].inside_port,
5811 protocol=sessions[0].protocol,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005812 flags=(self.config_flags.NAT_IS_INSIDE |
5813 self.config_flags.NAT_IS_EXT_HOST_VALID),
Matus Fabian70a26ac2018-05-14 06:20:28 -07005814 ext_host_address=sessions[0].ext_host_nat_address,
5815 ext_host_port=sessions[0].ext_host_nat_port)
5816 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5817 self.assertEqual(len(sessions), 0)
5818
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005819 def test_twice_nat(self):
5820 """ Twice NAT44 """
5821 self.twice_nat_common()
5822
5823 def test_self_twice_nat_positive(self):
5824 """ Self Twice NAT44 (positive test) """
5825 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5826
5827 def test_self_twice_nat_negative(self):
5828 """ Self Twice NAT44 (negative test) """
5829 self.twice_nat_common(self_twice_nat=True)
5830
Matus Fabianb932d262017-12-18 05:38:24 -08005831 def test_twice_nat_lb(self):
5832 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005833 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005834
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005835 def test_self_twice_nat_lb_positive(self):
5836 """ Self Twice NAT44 local service load balancing (positive test) """
5837 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5838 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005839
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005840 def test_self_twice_nat_lb_negative(self):
5841 """ Self Twice NAT44 local service load balancing (negative test) """
5842 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5843 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005844
5845 def test_twice_nat_interface_addr(self):
5846 """ Acquire twice NAT44 addresses from interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02005847 flags = self.config_flags.NAT_IS_TWICE_NAT
Filip Vargaf4749ca2019-04-25 14:55:32 +02005848 self.vapi.nat44_add_del_interface_addr(
5849 is_add=1,
5850 sw_if_index=self.pg3.sw_if_index,
5851 flags=flags)
Matus Fabianb932d262017-12-18 05:38:24 -08005852
5853 # no address in NAT pool
5854 adresses = self.vapi.nat44_address_dump()
5855 self.assertEqual(0, len(adresses))
5856
5857 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005858 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005859 adresses = self.vapi.nat44_address_dump()
5860 self.assertEqual(1, len(adresses))
Filip Vargadd1e3e72019-04-15 18:52:43 +02005861 self.assertEqual(str(adresses[0].ip_address),
5862 self.pg3.local_ip4)
5863 self.assertEqual(adresses[0].flags, flags)
Matus Fabianb932d262017-12-18 05:38:24 -08005864
5865 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005866 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005867 adresses = self.vapi.nat44_address_dump()
5868 self.assertEqual(0, len(adresses))
5869
Matus Fabian6c01dce2018-11-16 04:41:31 -08005870 def test_tcp_close(self):
5871 """ Close TCP session from inside network - output feature """
Filip Vargaf4749ca2019-04-25 14:55:32 +02005872 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005873 self.nat44_add_address(self.pg1.local_ip4)
5874 twice_nat_addr = '10.0.1.3'
5875 service_ip = '192.168.16.150'
5876 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005877 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005878 self.vapi.nat44_interface_add_del_feature(
5879 sw_if_index=self.pg0.sw_if_index,
5880 is_add=1)
5881 self.vapi.nat44_interface_add_del_feature(
5882 sw_if_index=self.pg0.sw_if_index,
5883 flags=flags, is_add=1)
5884 self.vapi.nat44_interface_add_del_output_feature(
5885 is_add=1,
5886 sw_if_index=self.pg1.sw_if_index)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005887 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5888 self.config_flags.NAT_IS_TWICE_NAT)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005889 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5890 service_ip,
5891 80,
5892 80,
5893 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005894 flags=flags)
Matus Fabian6c01dce2018-11-16 04:41:31 -08005895 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5896 start_sessnum = len(sessions)
5897
5898 # SYN packet out->in
5899 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5900 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5901 TCP(sport=33898, dport=80, flags="S"))
5902 self.pg1.add_stream(p)
5903 self.pg_enable_capture(self.pg_interfaces)
5904 self.pg_start()
5905 capture = self.pg0.get_capture(1)
5906 p = capture[0]
5907 tcp_port = p[TCP].sport
5908
5909 # SYN + ACK packet in->out
5910 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5911 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5912 TCP(sport=80, dport=tcp_port, flags="SA"))
5913 self.pg0.add_stream(p)
5914 self.pg_enable_capture(self.pg_interfaces)
5915 self.pg_start()
5916 self.pg1.get_capture(1)
5917
5918 # ACK packet out->in
5919 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5920 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5921 TCP(sport=33898, dport=80, flags="A"))
5922 self.pg1.add_stream(p)
5923 self.pg_enable_capture(self.pg_interfaces)
5924 self.pg_start()
5925 self.pg0.get_capture(1)
5926
5927 # FIN packet in -> out
5928 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5929 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5930 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5931 self.pg0.add_stream(p)
5932 self.pg_enable_capture(self.pg_interfaces)
5933 self.pg_start()
5934 self.pg1.get_capture(1)
5935
5936 # FIN+ACK packet out -> in
5937 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5938 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5939 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5940 self.pg1.add_stream(p)
5941 self.pg_enable_capture(self.pg_interfaces)
5942 self.pg_start()
5943 self.pg0.get_capture(1)
5944
5945 # ACK packet in -> out
5946 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5947 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5948 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5949 self.pg0.add_stream(p)
5950 self.pg_enable_capture(self.pg_interfaces)
5951 self.pg_start()
5952 self.pg1.get_capture(1)
5953
5954 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5955 0)
5956 self.assertEqual(len(sessions) - start_sessnum, 0)
5957
Matus Fabianebdf1902018-05-04 03:57:42 -07005958 def test_tcp_session_close_in(self):
5959 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005960 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005961 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02005962 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07005963 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5964 self.nat_addr,
5965 self.tcp_port_in,
5966 self.tcp_port_out,
5967 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02005968 flags=flags)
5969 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02005970 self.vapi.nat44_interface_add_del_feature(
5971 sw_if_index=self.pg0.sw_if_index,
5972 flags=flags, is_add=1)
5973 self.vapi.nat44_interface_add_del_feature(
5974 sw_if_index=self.pg1.sw_if_index,
5975 is_add=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005976
5977 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5978 start_sessnum = len(sessions)
5979
5980 self.initiate_tcp_session(self.pg0, self.pg1)
5981
Matus Fabian229c1aa2018-05-28 04:09:52 -07005982 # FIN packet in -> out
5983 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5984 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5985 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5986 flags="FA", seq=100, ack=300))
5987 self.pg0.add_stream(p)
5988 self.pg_enable_capture(self.pg_interfaces)
5989 self.pg_start()
5990 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005991
Matus Fabian229c1aa2018-05-28 04:09:52 -07005992 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005993
Matus Fabian229c1aa2018-05-28 04:09:52 -07005994 # ACK packet out -> in
5995 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5996 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5997 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5998 flags="A", seq=300, ack=101))
5999 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07006000
Matus Fabian229c1aa2018-05-28 04:09:52 -07006001 # FIN packet out -> in
6002 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6003 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6004 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6005 flags="FA", seq=300, ack=101))
6006 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07006007
Matus Fabian229c1aa2018-05-28 04:09:52 -07006008 self.pg1.add_stream(pkts)
6009 self.pg_enable_capture(self.pg_interfaces)
6010 self.pg_start()
6011 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07006012
Matus Fabian229c1aa2018-05-28 04:09:52 -07006013 # ACK packet in -> out
6014 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6015 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6016 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6017 flags="A", seq=101, ack=301))
6018 self.pg0.add_stream(p)
6019 self.pg_enable_capture(self.pg_interfaces)
6020 self.pg_start()
6021 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006022
Matus Fabian229c1aa2018-05-28 04:09:52 -07006023 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6024 0)
6025 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07006026
6027 def test_tcp_session_close_out(self):
6028 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07006029 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07006030 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006031 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07006032 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6033 self.nat_addr,
6034 self.tcp_port_in,
6035 self.tcp_port_out,
6036 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006037 flags=flags)
6038 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006039 self.vapi.nat44_interface_add_del_feature(
6040 sw_if_index=self.pg0.sw_if_index,
6041 flags=flags, is_add=1)
6042 self.vapi.nat44_interface_add_del_feature(
6043 sw_if_index=self.pg1.sw_if_index,
6044 is_add=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006045
6046 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
6047 start_sessnum = len(sessions)
6048
6049 self.initiate_tcp_session(self.pg0, self.pg1)
6050
Matus Fabian229c1aa2018-05-28 04:09:52 -07006051 # FIN packet out -> in
6052 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6053 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6054 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6055 flags="FA", seq=100, ack=300))
6056 self.pg1.add_stream(p)
6057 self.pg_enable_capture(self.pg_interfaces)
6058 self.pg_start()
6059 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006060
Matus Fabian229c1aa2018-05-28 04:09:52 -07006061 # FIN+ACK packet in -> out
6062 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6063 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6064 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6065 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07006066
Matus Fabian229c1aa2018-05-28 04:09:52 -07006067 self.pg0.add_stream(p)
6068 self.pg_enable_capture(self.pg_interfaces)
6069 self.pg_start()
6070 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006071
Matus Fabian229c1aa2018-05-28 04:09:52 -07006072 # ACK packet out -> in
6073 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6074 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6075 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6076 flags="A", seq=101, ack=301))
6077 self.pg1.add_stream(p)
6078 self.pg_enable_capture(self.pg_interfaces)
6079 self.pg_start()
6080 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006081
Matus Fabian229c1aa2018-05-28 04:09:52 -07006082 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6083 0)
6084 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07006085
6086 def test_tcp_session_close_simultaneous(self):
6087 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07006088 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07006089 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006090 flags = self.config_flags.NAT_IS_TWICE_NAT
Matus Fabian229c1aa2018-05-28 04:09:52 -07006091 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6092 self.nat_addr,
6093 self.tcp_port_in,
6094 self.tcp_port_out,
6095 proto=IP_PROTOS.tcp,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006096 flags=flags)
6097 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006098 self.vapi.nat44_interface_add_del_feature(
6099 sw_if_index=self.pg0.sw_if_index,
6100 flags=flags, is_add=1)
6101 self.vapi.nat44_interface_add_del_feature(
6102 sw_if_index=self.pg1.sw_if_index,
6103 is_add=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006104
6105 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
6106 start_sessnum = len(sessions)
6107
6108 self.initiate_tcp_session(self.pg0, self.pg1)
6109
Matus Fabian229c1aa2018-05-28 04:09:52 -07006110 # FIN packet in -> out
6111 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6112 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6113 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6114 flags="FA", seq=100, ack=300))
6115 self.pg0.add_stream(p)
6116 self.pg_enable_capture(self.pg_interfaces)
6117 self.pg_start()
6118 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006119
Matus Fabian229c1aa2018-05-28 04:09:52 -07006120 # FIN packet out -> in
6121 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6122 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6123 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6124 flags="FA", seq=300, ack=100))
6125 self.pg1.add_stream(p)
6126 self.pg_enable_capture(self.pg_interfaces)
6127 self.pg_start()
6128 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006129
Matus Fabian229c1aa2018-05-28 04:09:52 -07006130 # ACK packet in -> out
6131 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6132 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6133 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6134 flags="A", seq=101, ack=301))
6135 self.pg0.add_stream(p)
6136 self.pg_enable_capture(self.pg_interfaces)
6137 self.pg_start()
6138 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006139
Matus Fabian229c1aa2018-05-28 04:09:52 -07006140 # ACK packet out -> in
6141 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6142 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6143 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6144 flags="A", seq=301, ack=101))
6145 self.pg1.add_stream(p)
6146 self.pg_enable_capture(self.pg_interfaces)
6147 self.pg_start()
6148 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07006149
Matus Fabian229c1aa2018-05-28 04:09:52 -07006150 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
6151 0)
6152 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07006153
Matus Fabiana6110b62018-06-13 05:39:07 -07006154 def test_one_armed_nat44_static(self):
6155 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6156 remote_host = self.pg4.remote_hosts[0]
6157 local_host = self.pg4.remote_hosts[1]
6158 external_port = 80
6159 local_port = 8080
6160 eh_port_in = 0
6161
Filip Vargaf4749ca2019-04-25 14:55:32 +02006162 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07006163 self.nat44_add_address(self.nat_addr, twice_nat=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006164 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6165 self.config_flags.NAT_IS_TWICE_NAT)
Matus Fabiana6110b62018-06-13 05:39:07 -07006166 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6167 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006168 proto=IP_PROTOS.tcp, flags=flags)
6169 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006170 self.vapi.nat44_interface_add_del_feature(
6171 sw_if_index=self.pg4.sw_if_index,
6172 is_add=1)
6173 self.vapi.nat44_interface_add_del_feature(
6174 sw_if_index=self.pg4.sw_if_index,
6175 flags=flags, is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07006176
6177 # from client to service
6178 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6179 IP(src=remote_host.ip4, dst=self.nat_addr) /
6180 TCP(sport=12345, dport=external_port))
6181 self.pg4.add_stream(p)
6182 self.pg_enable_capture(self.pg_interfaces)
6183 self.pg_start()
6184 capture = self.pg4.get_capture(1)
6185 p = capture[0]
6186 try:
6187 ip = p[IP]
6188 tcp = p[TCP]
6189 self.assertEqual(ip.dst, local_host.ip4)
6190 self.assertEqual(ip.src, self.nat_addr)
6191 self.assertEqual(tcp.dport, local_port)
6192 self.assertNotEqual(tcp.sport, 12345)
6193 eh_port_in = tcp.sport
6194 self.assert_packet_checksums_valid(p)
6195 except:
6196 self.logger.error(ppp("Unexpected or invalid packet:", p))
6197 raise
6198
6199 # from service back to client
6200 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6201 IP(src=local_host.ip4, dst=self.nat_addr) /
6202 TCP(sport=local_port, dport=eh_port_in))
6203 self.pg4.add_stream(p)
6204 self.pg_enable_capture(self.pg_interfaces)
6205 self.pg_start()
6206 capture = self.pg4.get_capture(1)
6207 p = capture[0]
6208 try:
6209 ip = p[IP]
6210 tcp = p[TCP]
6211 self.assertEqual(ip.src, self.nat_addr)
6212 self.assertEqual(ip.dst, remote_host.ip4)
6213 self.assertEqual(tcp.sport, external_port)
6214 self.assertEqual(tcp.dport, 12345)
6215 self.assert_packet_checksums_valid(p)
6216 except:
6217 self.logger.error(ppp("Unexpected or invalid packet:", p))
6218 raise
6219
6220 def test_static_with_port_out2(self):
6221 """ 1:1 NAPT asymmetrical rule """
6222
6223 external_port = 80
6224 local_port = 8080
6225
Filip Vargaf4749ca2019-04-25 14:55:32 +02006226 self.vapi.nat44_forwarding_enable_disable(enable=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006227 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabiana6110b62018-06-13 05:39:07 -07006228 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6229 local_port, external_port,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006230 proto=IP_PROTOS.tcp, flags=flags)
6231 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006232 self.vapi.nat44_interface_add_del_feature(
6233 sw_if_index=self.pg0.sw_if_index,
6234 flags=flags, is_add=1)
6235 self.vapi.nat44_interface_add_del_feature(
6236 sw_if_index=self.pg1.sw_if_index,
6237 is_add=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07006238
6239 # from client to service
6240 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6241 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6242 TCP(sport=12345, dport=external_port))
6243 self.pg1.add_stream(p)
6244 self.pg_enable_capture(self.pg_interfaces)
6245 self.pg_start()
6246 capture = self.pg0.get_capture(1)
6247 p = capture[0]
6248 try:
6249 ip = p[IP]
6250 tcp = p[TCP]
6251 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6252 self.assertEqual(tcp.dport, local_port)
6253 self.assert_packet_checksums_valid(p)
6254 except:
6255 self.logger.error(ppp("Unexpected or invalid packet:", p))
6256 raise
6257
6258 # ICMP error
6259 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6260 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6261 ICMP(type=11) / capture[0][IP])
6262 self.pg0.add_stream(p)
6263 self.pg_enable_capture(self.pg_interfaces)
6264 self.pg_start()
6265 capture = self.pg1.get_capture(1)
6266 p = capture[0]
6267 try:
6268 self.assertEqual(p[IP].src, self.nat_addr)
6269 inner = p[IPerror]
6270 self.assertEqual(inner.dst, self.nat_addr)
6271 self.assertEqual(inner[TCPerror].dport, external_port)
6272 except:
6273 self.logger.error(ppp("Unexpected or invalid packet:", p))
6274 raise
6275
6276 # from service back to client
6277 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6278 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6279 TCP(sport=local_port, dport=12345))
6280 self.pg0.add_stream(p)
6281 self.pg_enable_capture(self.pg_interfaces)
6282 self.pg_start()
6283 capture = self.pg1.get_capture(1)
6284 p = capture[0]
6285 try:
6286 ip = p[IP]
6287 tcp = p[TCP]
6288 self.assertEqual(ip.src, self.nat_addr)
6289 self.assertEqual(tcp.sport, external_port)
6290 self.assert_packet_checksums_valid(p)
6291 except:
6292 self.logger.error(ppp("Unexpected or invalid packet:", p))
6293 raise
6294
6295 # ICMP error
6296 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6297 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6298 ICMP(type=11) / capture[0][IP])
6299 self.pg1.add_stream(p)
6300 self.pg_enable_capture(self.pg_interfaces)
6301 self.pg_start()
6302 capture = self.pg0.get_capture(1)
6303 p = capture[0]
6304 try:
6305 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6306 inner = p[IPerror]
6307 self.assertEqual(inner.src, self.pg0.remote_ip4)
6308 self.assertEqual(inner[TCPerror].sport, local_port)
6309 except:
6310 self.logger.error(ppp("Unexpected or invalid packet:", p))
6311 raise
6312
6313 # from client to server (no translation)
6314 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6315 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6316 TCP(sport=12346, dport=local_port))
6317 self.pg1.add_stream(p)
6318 self.pg_enable_capture(self.pg_interfaces)
6319 self.pg_start()
6320 capture = self.pg0.get_capture(1)
6321 p = capture[0]
6322 try:
6323 ip = p[IP]
6324 tcp = p[TCP]
6325 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6326 self.assertEqual(tcp.dport, local_port)
6327 self.assert_packet_checksums_valid(p)
6328 except:
6329 self.logger.error(ppp("Unexpected or invalid packet:", p))
6330 raise
6331
6332 # from service back to client (no translation)
6333 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6334 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6335 TCP(sport=local_port, dport=12346))
6336 self.pg0.add_stream(p)
6337 self.pg_enable_capture(self.pg_interfaces)
6338 self.pg_start()
6339 capture = self.pg1.get_capture(1)
6340 p = capture[0]
6341 try:
6342 ip = p[IP]
6343 tcp = p[TCP]
6344 self.assertEqual(ip.src, self.pg0.remote_ip4)
6345 self.assertEqual(tcp.sport, local_port)
6346 self.assert_packet_checksums_valid(p)
6347 except:
6348 self.logger.error(ppp("Unexpected or invalid packet:", p))
6349 raise
6350
Matus Fabian235a47e2018-06-25 16:42:36 -07006351 def test_output_feature(self):
6352 """ NAT44 interface output feature (in2out postrouting) """
Filip Vargaf4749ca2019-04-25 14:55:32 +02006353 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian235a47e2018-06-25 16:42:36 -07006354 self.nat44_add_address(self.nat_addr)
Filip Vargaf4749ca2019-04-25 14:55:32 +02006355 self.vapi.nat44_interface_add_del_feature(
6356 sw_if_index=self.pg0.sw_if_index,
6357 is_add=1)
6358 self.vapi.nat44_interface_add_del_output_feature(
6359 is_add=1,
6360 sw_if_index=self.pg1.sw_if_index)
Matus Fabian235a47e2018-06-25 16:42:36 -07006361
6362 # in2out
6363 pkts = self.create_stream_in(self.pg0, self.pg1)
6364 self.pg0.add_stream(pkts)
6365 self.pg_enable_capture(self.pg_interfaces)
6366 self.pg_start()
6367 capture = self.pg1.get_capture(len(pkts))
6368 self.verify_capture_out(capture)
6369
6370 # out2in
6371 pkts = self.create_stream_out(self.pg1)
6372 self.pg1.add_stream(pkts)
6373 self.pg_enable_capture(self.pg_interfaces)
6374 self.pg_start()
6375 capture = self.pg0.get_capture(len(pkts))
6376 self.verify_capture_in(capture, self.pg0)
6377
Matus Fabian8008d7c2018-07-09 01:34:20 -07006378 def test_multiple_vrf(self):
6379 """ Multiple VRF setup """
6380 external_addr = '1.2.3.4'
6381 external_port = 80
6382 local_port = 8080
6383 port = 0
6384
Filip Vargaf4749ca2019-04-25 14:55:32 +02006385 self.vapi.nat44_forwarding_enable_disable(enable=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07006386 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006387 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006388 self.vapi.nat44_interface_add_del_feature(
6389 sw_if_index=self.pg0.sw_if_index,
6390 is_add=1)
6391 self.vapi.nat44_interface_add_del_feature(
6392 sw_if_index=self.pg0.sw_if_index,
6393 flags=flags, is_add=1)
6394 self.vapi.nat44_interface_add_del_output_feature(
6395 is_add=1,
6396 sw_if_index=self.pg1.sw_if_index)
6397 self.vapi.nat44_interface_add_del_feature(
6398 sw_if_index=self.pg5.sw_if_index,
6399 is_add=1)
6400 self.vapi.nat44_interface_add_del_feature(
6401 sw_if_index=self.pg5.sw_if_index,
6402 flags=flags, is_add=1)
6403 self.vapi.nat44_interface_add_del_feature(
6404 sw_if_index=self.pg6.sw_if_index,
6405 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006406 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Matus Fabian8008d7c2018-07-09 01:34:20 -07006407 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6408 local_port, external_port, vrf_id=1,
Filip Vargadd1e3e72019-04-15 18:52:43 +02006409 proto=IP_PROTOS.tcp, flags=flags)
Matus Fabian8008d7c2018-07-09 01:34:20 -07006410 self.nat44_add_static_mapping(
Filip Vargaf4749ca2019-04-25 14:55:32 +02006411 self.pg0.remote_ip4,
6412 external_sw_if_index=self.pg0.sw_if_index,
6413 local_port=local_port,
6414 vrf_id=0,
6415 external_port=external_port,
6416 proto=IP_PROTOS.tcp,
6417 flags=flags
Filip Vargadd1e3e72019-04-15 18:52:43 +02006418 )
Matus Fabian8008d7c2018-07-09 01:34:20 -07006419
6420 # from client to service (both VRF1)
6421 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6422 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6423 TCP(sport=12345, dport=external_port))
6424 self.pg6.add_stream(p)
6425 self.pg_enable_capture(self.pg_interfaces)
6426 self.pg_start()
6427 capture = self.pg5.get_capture(1)
6428 p = capture[0]
6429 try:
6430 ip = p[IP]
6431 tcp = p[TCP]
6432 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6433 self.assertEqual(tcp.dport, local_port)
6434 self.assert_packet_checksums_valid(p)
6435 except:
6436 self.logger.error(ppp("Unexpected or invalid packet:", p))
6437 raise
6438
6439 # from service back to client (both VRF1)
6440 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6441 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6442 TCP(sport=local_port, dport=12345))
6443 self.pg5.add_stream(p)
6444 self.pg_enable_capture(self.pg_interfaces)
6445 self.pg_start()
6446 capture = self.pg6.get_capture(1)
6447 p = capture[0]
6448 try:
6449 ip = p[IP]
6450 tcp = p[TCP]
6451 self.assertEqual(ip.src, external_addr)
6452 self.assertEqual(tcp.sport, external_port)
6453 self.assert_packet_checksums_valid(p)
6454 except:
6455 self.logger.error(ppp("Unexpected or invalid packet:", p))
6456 raise
6457
6458 # dynamic NAT from VRF1 to VRF0 (output-feature)
6459 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6460 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6461 TCP(sport=2345, dport=22))
6462 self.pg5.add_stream(p)
6463 self.pg_enable_capture(self.pg_interfaces)
6464 self.pg_start()
6465 capture = self.pg1.get_capture(1)
6466 p = capture[0]
6467 try:
6468 ip = p[IP]
6469 tcp = p[TCP]
6470 self.assertEqual(ip.src, self.nat_addr)
6471 self.assertNotEqual(tcp.sport, 2345)
6472 self.assert_packet_checksums_valid(p)
6473 port = tcp.sport
6474 except:
6475 self.logger.error(ppp("Unexpected or invalid packet:", p))
6476 raise
6477
6478 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6479 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6480 TCP(sport=22, dport=port))
6481 self.pg1.add_stream(p)
6482 self.pg_enable_capture(self.pg_interfaces)
6483 self.pg_start()
6484 capture = self.pg5.get_capture(1)
6485 p = capture[0]
6486 try:
6487 ip = p[IP]
6488 tcp = p[TCP]
6489 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6490 self.assertEqual(tcp.dport, 2345)
6491 self.assert_packet_checksums_valid(p)
6492 except:
6493 self.logger.error(ppp("Unexpected or invalid packet:", p))
6494 raise
6495
6496 # from client VRF1 to service VRF0
6497 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6498 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6499 TCP(sport=12346, dport=external_port))
6500 self.pg6.add_stream(p)
6501 self.pg_enable_capture(self.pg_interfaces)
6502 self.pg_start()
6503 capture = self.pg0.get_capture(1)
6504 p = capture[0]
6505 try:
6506 ip = p[IP]
6507 tcp = p[TCP]
6508 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6509 self.assertEqual(tcp.dport, local_port)
6510 self.assert_packet_checksums_valid(p)
6511 except:
6512 self.logger.error(ppp("Unexpected or invalid packet:", p))
6513 raise
6514
6515 # from service VRF0 back to client VRF1
6516 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6517 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6518 TCP(sport=local_port, dport=12346))
6519 self.pg0.add_stream(p)
6520 self.pg_enable_capture(self.pg_interfaces)
6521 self.pg_start()
6522 capture = self.pg6.get_capture(1)
6523 p = capture[0]
6524 try:
6525 ip = p[IP]
6526 tcp = p[TCP]
6527 self.assertEqual(ip.src, self.pg0.local_ip4)
6528 self.assertEqual(tcp.sport, external_port)
6529 self.assert_packet_checksums_valid(p)
6530 except:
6531 self.logger.error(ppp("Unexpected or invalid packet:", p))
6532 raise
6533
6534 # from client VRF0 to service VRF1
6535 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6536 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6537 TCP(sport=12347, dport=external_port))
6538 self.pg0.add_stream(p)
6539 self.pg_enable_capture(self.pg_interfaces)
6540 self.pg_start()
6541 capture = self.pg5.get_capture(1)
6542 p = capture[0]
6543 try:
6544 ip = p[IP]
6545 tcp = p[TCP]
6546 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6547 self.assertEqual(tcp.dport, local_port)
6548 self.assert_packet_checksums_valid(p)
6549 except:
6550 self.logger.error(ppp("Unexpected or invalid packet:", p))
6551 raise
6552
6553 # from service VRF1 back to client VRF0
6554 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6555 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6556 TCP(sport=local_port, dport=12347))
6557 self.pg5.add_stream(p)
6558 self.pg_enable_capture(self.pg_interfaces)
6559 self.pg_start()
6560 capture = self.pg0.get_capture(1)
6561 p = capture[0]
6562 try:
6563 ip = p[IP]
6564 tcp = p[TCP]
6565 self.assertEqual(ip.src, external_addr)
6566 self.assertEqual(tcp.sport, external_port)
6567 self.assert_packet_checksums_valid(p)
6568 except:
6569 self.logger.error(ppp("Unexpected or invalid packet:", p))
6570 raise
6571
6572 # from client to server (both VRF1, no translation)
6573 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6574 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6575 TCP(sport=12348, dport=local_port))
6576 self.pg6.add_stream(p)
6577 self.pg_enable_capture(self.pg_interfaces)
6578 self.pg_start()
6579 capture = self.pg5.get_capture(1)
6580 p = capture[0]
6581 try:
6582 ip = p[IP]
6583 tcp = p[TCP]
6584 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6585 self.assertEqual(tcp.dport, local_port)
6586 self.assert_packet_checksums_valid(p)
6587 except:
6588 self.logger.error(ppp("Unexpected or invalid packet:", p))
6589 raise
6590
6591 # from server back to client (both VRF1, no translation)
6592 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6593 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6594 TCP(sport=local_port, dport=12348))
6595 self.pg5.add_stream(p)
6596 self.pg_enable_capture(self.pg_interfaces)
6597 self.pg_start()
6598 capture = self.pg6.get_capture(1)
6599 p = capture[0]
6600 try:
6601 ip = p[IP]
6602 tcp = p[TCP]
6603 self.assertEqual(ip.src, self.pg5.remote_ip4)
6604 self.assertEqual(tcp.sport, local_port)
6605 self.assert_packet_checksums_valid(p)
6606 except:
6607 self.logger.error(ppp("Unexpected or invalid packet:", p))
6608 raise
6609
6610 # from client VRF1 to server VRF0 (no translation)
6611 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6612 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6613 TCP(sport=local_port, dport=12349))
6614 self.pg0.add_stream(p)
6615 self.pg_enable_capture(self.pg_interfaces)
6616 self.pg_start()
6617 capture = self.pg6.get_capture(1)
6618 p = capture[0]
6619 try:
6620 ip = p[IP]
6621 tcp = p[TCP]
6622 self.assertEqual(ip.src, self.pg0.remote_ip4)
6623 self.assertEqual(tcp.sport, local_port)
6624 self.assert_packet_checksums_valid(p)
6625 except:
6626 self.logger.error(ppp("Unexpected or invalid packet:", p))
6627 raise
6628
6629 # from server VRF0 back to client VRF1 (no translation)
6630 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6631 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6632 TCP(sport=local_port, dport=12349))
6633 self.pg0.add_stream(p)
6634 self.pg_enable_capture(self.pg_interfaces)
6635 self.pg_start()
6636 capture = self.pg6.get_capture(1)
6637 p = capture[0]
6638 try:
6639 ip = p[IP]
6640 tcp = p[TCP]
6641 self.assertEqual(ip.src, self.pg0.remote_ip4)
6642 self.assertEqual(tcp.sport, local_port)
6643 self.assert_packet_checksums_valid(p)
6644 except:
6645 self.logger.error(ppp("Unexpected or invalid packet:", p))
6646 raise
6647
6648 # from client VRF0 to server VRF1 (no translation)
6649 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6650 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6651 TCP(sport=12344, dport=local_port))
6652 self.pg0.add_stream(p)
6653 self.pg_enable_capture(self.pg_interfaces)
6654 self.pg_start()
6655 capture = self.pg5.get_capture(1)
6656 p = capture[0]
6657 try:
6658 ip = p[IP]
6659 tcp = p[TCP]
6660 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6661 self.assertEqual(tcp.dport, local_port)
6662 self.assert_packet_checksums_valid(p)
6663 except:
6664 self.logger.error(ppp("Unexpected or invalid packet:", p))
6665 raise
6666
6667 # from server VRF1 back to client VRF0 (no translation)
6668 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6669 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6670 TCP(sport=local_port, dport=12344))
6671 self.pg5.add_stream(p)
6672 self.pg_enable_capture(self.pg_interfaces)
6673 self.pg_start()
6674 capture = self.pg0.get_capture(1)
6675 p = capture[0]
6676 try:
6677 ip = p[IP]
6678 tcp = p[TCP]
6679 self.assertEqual(ip.src, self.pg5.remote_ip4)
6680 self.assertEqual(tcp.sport, local_port)
6681 self.assert_packet_checksums_valid(p)
6682 except:
6683 self.logger.error(ppp("Unexpected or invalid packet:", p))
6684 raise
6685
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006686 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006687 def test_session_timeout(self):
6688 """ NAT44 session timeouts """
6689 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006690 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006691 self.vapi.nat44_interface_add_del_feature(
6692 sw_if_index=self.pg0.sw_if_index,
6693 flags=flags, is_add=1)
6694 self.vapi.nat44_interface_add_del_feature(
6695 sw_if_index=self.pg1.sw_if_index,
6696 is_add=1)
6697 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6698 tcp_transitory=240, icmp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006699
6700 max_sessions = 1000
6701 pkts = []
6702 for i in range(0, max_sessions):
6703 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6704 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6705 IP(src=src, dst=self.pg1.remote_ip4) /
6706 ICMP(id=1025, type='echo-request'))
6707 pkts.append(p)
6708 self.pg0.add_stream(pkts)
6709 self.pg_enable_capture(self.pg_interfaces)
6710 self.pg_start()
6711 self.pg1.get_capture(max_sessions)
6712
6713 sleep(10)
6714
6715 pkts = []
6716 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006717 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006718 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6719 IP(src=src, dst=self.pg1.remote_ip4) /
6720 ICMP(id=1026, type='echo-request'))
6721 pkts.append(p)
6722 self.pg0.add_stream(pkts)
6723 self.pg_enable_capture(self.pg_interfaces)
6724 self.pg_start()
6725 self.pg1.get_capture(max_sessions)
6726
6727 nsessions = 0
6728 users = self.vapi.nat44_user_dump()
6729 for user in users:
6730 nsessions = nsessions + user.nsessions
6731 self.assertLess(nsessions, 2 * max_sessions)
6732
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006733 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006734 def test_session_rst_timeout(self):
6735 """ NAT44 session RST timeouts """
6736 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006737 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006738 self.vapi.nat44_interface_add_del_feature(
6739 sw_if_index=self.pg0.sw_if_index,
6740 flags=flags, is_add=1)
6741 self.vapi.nat44_interface_add_del_feature(
6742 sw_if_index=self.pg1.sw_if_index,
6743 is_add=1)
6744 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6745 tcp_transitory=5, icmp=60)
Matus Fabian15e8e682018-11-21 04:53:10 -08006746
Matus Fabian15e8e682018-11-21 04:53:10 -08006747 self.initiate_tcp_session(self.pg0, self.pg1)
6748 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6749 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6750 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6751 flags="R"))
6752 self.pg0.add_stream(p)
6753 self.pg_enable_capture(self.pg_interfaces)
6754 self.pg_start()
6755 self.pg1.get_capture(1)
6756
Matus Fabian15e8e682018-11-21 04:53:10 -08006757 sleep(6)
6758
6759 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6760 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6761 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6762 flags="S"))
6763 self.pg0.add_stream(p)
6764 self.pg_enable_capture(self.pg_interfaces)
6765 self.pg_start()
6766 self.pg1.get_capture(1)
6767
6768 nsessions = 0
6769 users = self.vapi.nat44_user_dump()
6770 self.assertEqual(len(users), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006771 self.assertEqual(str(users[0].ip_address),
6772 self.pg0.remote_ip4)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006773 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006774
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006775 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006776 def test_session_limit_per_user(self):
6777 """ Maximum sessions per user limit """
6778 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006779 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006780 self.vapi.nat44_interface_add_del_feature(
6781 sw_if_index=self.pg0.sw_if_index,
6782 flags=flags, is_add=1)
6783 self.vapi.nat44_interface_add_del_feature(
6784 sw_if_index=self.pg1.sw_if_index,
6785 is_add=1)
Matus Fabian878c6462018-08-23 00:33:35 -07006786 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6787 src_address=self.pg2.local_ip4n,
6788 path_mtu=512,
6789 template_interval=10)
Filip Vargaf4749ca2019-04-25 14:55:32 +02006790 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
6791 tcp_transitory=240, icmp=60)
Matus Fabian878c6462018-08-23 00:33:35 -07006792
6793 # get maximum number of translations per user
6794 nat44_config = self.vapi.nat_show_config()
6795
6796 pkts = []
6797 for port in range(0, nat44_config.max_translations_per_user):
6798 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6799 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6800 UDP(sport=1025 + port, dport=1025 + port))
6801 pkts.append(p)
6802
6803 self.pg0.add_stream(pkts)
6804 self.pg_enable_capture(self.pg_interfaces)
6805 self.pg_start()
6806 capture = self.pg1.get_capture(len(pkts))
6807
Ole Troane1ade682019-03-04 23:55:43 +01006808 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02006809 src_port=self.ipfix_src_port,
6810 enable=1)
Matus Fabian878c6462018-08-23 00:33:35 -07006811
6812 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6813 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6814 UDP(sport=3001, dport=3002))
6815 self.pg0.add_stream(p)
6816 self.pg_enable_capture(self.pg_interfaces)
6817 self.pg_start()
6818 capture = self.pg1.assert_nothing_captured()
6819
6820 # verify IPFIX logging
6821 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6822 sleep(1)
6823 capture = self.pg2.get_capture(10)
6824 ipfix = IPFIXDecoder()
6825 # first load template
6826 for p in capture:
6827 self.assertTrue(p.haslayer(IPFIX))
6828 if p.haslayer(Template):
6829 ipfix.add_template(p.getlayer(Template))
6830 # verify events in data set
6831 for p in capture:
6832 if p.haslayer(Data):
6833 data = ipfix.decode_data_set(p.getlayer(Set))
6834 self.verify_ipfix_max_entries_per_user(
6835 data,
6836 nat44_config.max_translations_per_user,
6837 self.pg0.remote_ip4n)
6838
Matus Fabian8fdc0152018-09-24 04:41:28 -07006839 sleep(6)
6840 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6841 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6842 UDP(sport=3001, dport=3002))
6843 self.pg0.add_stream(p)
6844 self.pg_enable_capture(self.pg_interfaces)
6845 self.pg_start()
6846 self.pg1.get_capture(1)
6847
Matus Fabianad1f3e12018-11-28 21:26:34 -08006848 def test_syslog_sess(self):
6849 """ Test syslog session creation and deletion """
6850 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006851 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006852 self.nat44_add_address(self.nat_addr)
Filip Vargadd1e3e72019-04-15 18:52:43 +02006853 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006854 self.vapi.nat44_interface_add_del_feature(
6855 sw_if_index=self.pg0.sw_if_index,
6856 flags=flags, is_add=1)
6857 self.vapi.nat44_interface_add_del_feature(
6858 sw_if_index=self.pg1.sw_if_index,
6859 is_add=1)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006860
6861 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6862 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6863 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6864 self.pg0.add_stream(p)
6865 self.pg_enable_capture(self.pg_interfaces)
6866 self.pg_start()
6867 capture = self.pg1.get_capture(1)
6868 self.tcp_port_out = capture[0][TCP].sport
6869 capture = self.pg2.get_capture(1)
6870 self.verify_syslog_sess(capture[0][Raw].load)
6871
6872 self.pg_enable_capture(self.pg_interfaces)
6873 self.pg_start()
6874 self.nat44_add_address(self.nat_addr, is_add=0)
6875 capture = self.pg2.get_capture(1)
6876 self.verify_syslog_sess(capture[0][Raw].load, False)
6877
Matus Fabiande886752016-12-07 03:38:19 -08006878 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006879 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006880 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006881 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006882 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006883
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07006884 def show_commands_at_teardown(self):
6885 self.logger.info(self.vapi.cli("show nat44 addresses"))
6886 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6887 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6888 self.logger.info(self.vapi.cli("show nat44 interface address"))
6889 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6890 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6891 self.logger.info(self.vapi.cli("show nat timeouts"))
6892
Matus Fabianeea28d72017-01-13 04:15:54 -08006893
Juraj Slobodacba69362017-12-19 02:09:32 +01006894class TestNAT44Out2InDPO(MethodHolder):
6895 """ NAT44 Test Cases using out2in DPO """
6896
6897 @classmethod
6898 def setUpConstants(cls):
6899 super(TestNAT44Out2InDPO, cls).setUpConstants()
6900 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6901
6902 @classmethod
6903 def setUpClass(cls):
6904 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006905 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006906
6907 try:
6908 cls.tcp_port_in = 6303
6909 cls.tcp_port_out = 6303
6910 cls.udp_port_in = 6304
6911 cls.udp_port_out = 6304
6912 cls.icmp_id_in = 6305
6913 cls.icmp_id_out = 6305
6914 cls.nat_addr = '10.0.0.3'
Juraj Slobodacba69362017-12-19 02:09:32 +01006915 cls.dst_ip4 = '192.168.70.1'
6916
6917 cls.create_pg_interfaces(range(2))
6918
6919 cls.pg0.admin_up()
6920 cls.pg0.config_ip4()
6921 cls.pg0.resolve_arp()
6922
6923 cls.pg1.admin_up()
6924 cls.pg1.config_ip6()
6925 cls.pg1.resolve_ndp()
6926
Ole Troana5b2eec2019-03-11 19:23:25 +01006927 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
Juraj Slobodacba69362017-12-19 02:09:32 +01006928 dst_address_length=0,
6929 next_hop_address=cls.pg1.remote_ip6n,
Ole Troana5b2eec2019-03-11 19:23:25 +01006930 next_hop_sw_if_index=cls.pg1.sw_if_index,
6931 is_ipv6=True)
Juraj Slobodacba69362017-12-19 02:09:32 +01006932
6933 except Exception:
6934 super(TestNAT44Out2InDPO, cls).tearDownClass()
6935 raise
6936
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07006937 @classmethod
6938 def tearDownClass(cls):
6939 super(TestNAT44Out2InDPO, cls).tearDownClass()
6940
Juraj Slobodacba69362017-12-19 02:09:32 +01006941 def configure_xlat(self):
6942 self.dst_ip6_pfx = '1:2:3::'
6943 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6944 self.dst_ip6_pfx)
6945 self.dst_ip6_pfx_len = 96
6946 self.src_ip6_pfx = '4:5:6::'
6947 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6948 self.src_ip6_pfx)
6949 self.src_ip6_pfx_len = 96
6950 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6951 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006952 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006953
Ole Troanffba3c32018-11-22 12:53:00 +01006954 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006955 def test_464xlat_ce(self):
6956 """ Test 464XLAT CE with NAT44 """
6957
Matus Fabian69ce30d2018-08-22 01:27:10 -07006958 nat_config = self.vapi.nat_show_config()
6959 self.assertEqual(1, nat_config.out2in_dpo)
6960
Juraj Slobodacba69362017-12-19 02:09:32 +01006961 self.configure_xlat()
6962
Filip Vargadd1e3e72019-04-15 18:52:43 +02006963 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02006964 self.vapi.nat44_interface_add_del_feature(
6965 sw_if_index=self.pg0.sw_if_index,
6966 flags=flags, is_add=1)
6967 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
6968 last_ip_address=self.nat_addr_n,
6969 vrf_id=0xFFFFFFFF, is_add=1)
Juraj Slobodacba69362017-12-19 02:09:32 +01006970
6971 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6972 self.dst_ip6_pfx_len)
6973 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6974 self.src_ip6_pfx_len)
6975
6976 try:
6977 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6978 self.pg0.add_stream(pkts)
6979 self.pg_enable_capture(self.pg_interfaces)
6980 self.pg_start()
6981 capture = self.pg1.get_capture(len(pkts))
6982 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6983 dst_ip=out_src_ip6)
6984
6985 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6986 out_dst_ip6)
6987 self.pg1.add_stream(pkts)
6988 self.pg_enable_capture(self.pg_interfaces)
6989 self.pg_start()
6990 capture = self.pg0.get_capture(len(pkts))
6991 self.verify_capture_in(capture, self.pg0)
6992 finally:
Filip Vargaf4749ca2019-04-25 14:55:32 +02006993 self.vapi.nat44_interface_add_del_feature(
6994 sw_if_index=self.pg0.sw_if_index,
6995 flags=flags)
6996 self.vapi.nat44_add_del_address_range(
6997 first_ip_address=self.nat_addr_n,
6998 last_ip_address=self.nat_addr_n,
6999 vrf_id=0xFFFFFFFF)
Juraj Slobodacba69362017-12-19 02:09:32 +01007000
Ole Troanffba3c32018-11-22 12:53:00 +01007001 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01007002 def test_464xlat_ce_no_nat(self):
7003 """ Test 464XLAT CE without NAT44 """
7004
7005 self.configure_xlat()
7006
7007 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7008 self.dst_ip6_pfx_len)
7009 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7010 self.src_ip6_pfx_len)
7011
7012 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7013 self.pg0.add_stream(pkts)
7014 self.pg_enable_capture(self.pg_interfaces)
7015 self.pg_start()
7016 capture = self.pg1.get_capture(len(pkts))
7017 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7018 nat_ip=out_dst_ip6, same_port=True)
7019
7020 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7021 self.pg1.add_stream(pkts)
7022 self.pg_enable_capture(self.pg_interfaces)
7023 self.pg_start()
7024 capture = self.pg0.get_capture(len(pkts))
7025 self.verify_capture_in(capture, self.pg0)
7026
7027
Martin Gálikd7f75cd2017-03-27 06:02:47 -07007028class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08007029 """ Deterministic NAT Test Cases """
7030
7031 @classmethod
7032 def setUpConstants(cls):
7033 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007034 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08007035
7036 @classmethod
7037 def setUpClass(cls):
7038 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007039 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08007040
7041 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07007042 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07007043 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07007044 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07007045 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07007046 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07007047 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07007048
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007049 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08007050 cls.interfaces = list(cls.pg_interfaces)
7051
7052 for i in cls.interfaces:
7053 i.admin_up()
7054 i.config_ip4()
7055 i.resolve_arp()
7056
Martin Gálik977c1cb2017-03-30 23:21:51 -07007057 cls.pg0.generate_remote_hosts(2)
7058 cls.pg0.configure_ipv4_neighbors()
7059
Matus Fabian066f0342017-02-10 03:48:01 -08007060 except Exception:
7061 super(TestDeterministicNAT, cls).tearDownClass()
7062 raise
7063
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007064 @classmethod
7065 def tearDownClass(cls):
7066 super(TestDeterministicNAT, cls).tearDownClass()
7067
Martin Gálik977c1cb2017-03-30 23:21:51 -07007068 def create_stream_in(self, in_if, out_if, ttl=64):
7069 """
7070 Create packet stream for inside network
7071
7072 :param in_if: Inside interface
7073 :param out_if: Outside interface
7074 :param ttl: TTL of generated packets
7075 """
7076 pkts = []
7077 # TCP
7078 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7079 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007080 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007081 pkts.append(p)
7082
7083 # UDP
7084 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7085 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007086 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007087 pkts.append(p)
7088
7089 # ICMP
7090 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7091 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7092 ICMP(id=self.icmp_id_in, type='echo-request'))
7093 pkts.append(p)
7094
7095 return pkts
7096
7097 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7098 """
7099 Create packet stream for outside network
7100
7101 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07007102 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007103 :param ttl: TTL of generated packets
7104 """
7105 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007106 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07007107 pkts = []
7108 # TCP
7109 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7110 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007111 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007112 pkts.append(p)
7113
7114 # UDP
7115 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7116 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007117 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007118 pkts.append(p)
7119
7120 # ICMP
7121 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7122 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7123 ICMP(id=self.icmp_external_id, type='echo-reply'))
7124 pkts.append(p)
7125
7126 return pkts
7127
Matus Fabian05ca4a32018-09-04 23:45:13 -07007128 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07007129 """
7130 Verify captured packets on outside network
7131
7132 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07007133 :param nat_ip: Translated IP address (Default use global NAT address)
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07007134 :param same_port: Source port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007135 """
7136 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007137 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07007138 for packet in capture:
7139 try:
7140 self.assertEqual(packet[IP].src, nat_ip)
7141 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07007142 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007143 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07007144 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007145 else:
7146 self.icmp_external_id = packet[ICMP].id
7147 except:
7148 self.logger.error(ppp("Unexpected or invalid packet "
7149 "(outside network):", packet))
7150 raise
7151
Matus Fabian066f0342017-02-10 03:48:01 -08007152 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007153 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08007154 in_addr = '172.16.255.0'
7155 out_addr = '172.17.255.50'
7156 in_addr_t = '172.16.255.20'
Matus Fabian066f0342017-02-10 03:48:01 -08007157 in_plen = 24
7158 out_plen = 32
7159
Matus Fabian2ba92e32017-08-21 07:05:03 -07007160 nat_config = self.vapi.nat_show_config()
7161 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08007162
Filip Vargaf4749ca2019-04-25 14:55:32 +02007163 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7164 in_plen=in_plen, out_addr=out_addr,
7165 out_plen=out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08007166
Filip Vargadd1e3e72019-04-15 18:52:43 +02007167 rep1 = self.vapi.nat_det_forward(in_addr_t)
7168 self.assertEqual(str(rep1.out_addr), out_addr)
7169 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7170
7171 self.assertEqual(str(rep2.in_addr), in_addr_t)
Matus Fabian066f0342017-02-10 03:48:01 -08007172
Matus Fabian2ba92e32017-08-21 07:05:03 -07007173 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007174 self.assertEqual(len(deterministic_mappings), 1)
7175 dsm = deterministic_mappings[0]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007176 self.assertEqual(in_addr, str(dsm.in_addr))
Martin17a75cb2017-03-08 05:53:20 -08007177 self.assertEqual(in_plen, dsm.in_plen)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007178 self.assertEqual(out_addr, str(dsm.out_addr))
Martin17a75cb2017-03-08 05:53:20 -08007179 self.assertEqual(out_plen, dsm.out_plen)
7180
Matus Fabian2ba92e32017-08-21 07:05:03 -07007181 self.clear_nat_det()
7182 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07007183 self.assertEqual(len(deterministic_mappings), 0)
7184
Matus Fabian6a0946f2017-04-12 03:36:13 -07007185 def test_set_timeouts(self):
7186 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07007187 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07007188
Filip Vargaf4749ca2019-04-25 14:55:32 +02007189 self.vapi.nat_set_timeouts(
7190 udp=timeouts_before.udp + 10,
7191 tcp_established=timeouts_before.tcp_established + 10,
7192 tcp_transitory=timeouts_before.tcp_transitory + 10,
7193 icmp=timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07007194
Matus Fabian878c6462018-08-23 00:33:35 -07007195 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07007196
7197 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7198 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7199 self.assertNotEqual(timeouts_before.tcp_established,
7200 timeouts_after.tcp_established)
7201 self.assertNotEqual(timeouts_before.tcp_transitory,
7202 timeouts_after.tcp_transitory)
7203
Martin Gálik977c1cb2017-03-30 23:21:51 -07007204 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007205 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07007206
7207 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07007208
Filip Vargaf4749ca2019-04-25 14:55:32 +02007209 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7210 in_plen=32,
7211 out_addr=socket.inet_aton(nat_ip),
7212 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007213
7214 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007215 self.vapi.nat44_interface_add_del_feature(
7216 sw_if_index=self.pg0.sw_if_index,
7217 flags=flags, is_add=1)
7218 self.vapi.nat44_interface_add_del_feature(
7219 sw_if_index=self.pg1.sw_if_index,
7220 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007221
7222 # in2out
7223 pkts = self.create_stream_in(self.pg0, self.pg1)
7224 self.pg0.add_stream(pkts)
7225 self.pg_enable_capture(self.pg_interfaces)
7226 self.pg_start()
7227 capture = self.pg1.get_capture(len(pkts))
7228 self.verify_capture_out(capture, nat_ip)
7229
7230 # out2in
7231 pkts = self.create_stream_out(self.pg1, nat_ip)
7232 self.pg1.add_stream(pkts)
7233 self.pg_enable_capture(self.pg_interfaces)
7234 self.pg_start()
7235 capture = self.pg0.get_capture(len(pkts))
7236 self.verify_capture_in(capture, self.pg0)
7237
Martin Gálik9806eae2017-04-25 01:25:08 -07007238 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07007239 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07007240 self.assertEqual(len(sessions), 3)
7241
7242 # TCP session
7243 s = sessions[0]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007244 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007245 self.assertEqual(s.in_port, self.tcp_port_in)
7246 self.assertEqual(s.out_port, self.tcp_port_out)
7247 self.assertEqual(s.ext_port, self.tcp_external_port)
7248
7249 # UDP session
7250 s = sessions[1]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007251 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007252 self.assertEqual(s.in_port, self.udp_port_in)
7253 self.assertEqual(s.out_port, self.udp_port_out)
7254 self.assertEqual(s.ext_port, self.udp_external_port)
7255
7256 # ICMP session
7257 s = sessions[2]
Filip Vargadd1e3e72019-04-15 18:52:43 +02007258 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007259 self.assertEqual(s.in_port, self.icmp_id_in)
7260 self.assertEqual(s.out_port, self.icmp_external_id)
7261
Martin Gálik977c1cb2017-03-30 23:21:51 -07007262 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007263 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07007264
7265 nat_ip = "10.0.0.10"
7266 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07007267 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07007268
7269 host0 = self.pg0.remote_hosts[0]
7270 host1 = self.pg0.remote_hosts[1]
7271
Filip Vargaf4749ca2019-04-25 14:55:32 +02007272 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4n, in_plen=24,
7273 out_addr=socket.inet_aton(nat_ip),
7274 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007275 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007276 self.vapi.nat44_interface_add_del_feature(
7277 sw_if_index=self.pg0.sw_if_index,
7278 flags=flags, is_add=1)
7279 self.vapi.nat44_interface_add_del_feature(
7280 sw_if_index=self.pg1.sw_if_index,
7281 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007282
7283 # host0 to out
7284 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7285 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007286 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007287 self.pg0.add_stream(p)
7288 self.pg_enable_capture(self.pg_interfaces)
7289 self.pg_start()
7290 capture = self.pg1.get_capture(1)
7291 p = capture[0]
7292 try:
7293 ip = p[IP]
7294 tcp = p[TCP]
7295 self.assertEqual(ip.src, nat_ip)
7296 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007297 self.assertEqual(tcp.dport, external_port)
7298 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007299 except:
7300 self.logger.error(ppp("Unexpected or invalid packet:", p))
7301 raise
7302
7303 # host1 to out
7304 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7305 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007306 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007307 self.pg0.add_stream(p)
7308 self.pg_enable_capture(self.pg_interfaces)
7309 self.pg_start()
7310 capture = self.pg1.get_capture(1)
7311 p = capture[0]
7312 try:
7313 ip = p[IP]
7314 tcp = p[TCP]
7315 self.assertEqual(ip.src, nat_ip)
7316 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07007317 self.assertEqual(tcp.dport, external_port)
7318 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07007319 except:
7320 self.logger.error(ppp("Unexpected or invalid packet:", p))
7321 raise
7322
Matus Fabian2ba92e32017-08-21 07:05:03 -07007323 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007324 self.assertEqual(1, len(dms))
7325 self.assertEqual(2, dms[0].ses_num)
7326
7327 # out to host0
7328 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7329 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007330 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007331 self.pg1.add_stream(p)
7332 self.pg_enable_capture(self.pg_interfaces)
7333 self.pg_start()
7334 capture = self.pg0.get_capture(1)
7335 p = capture[0]
7336 try:
7337 ip = p[IP]
7338 tcp = p[TCP]
7339 self.assertEqual(ip.src, self.pg1.remote_ip4)
7340 self.assertEqual(ip.dst, host0.ip4)
7341 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07007342 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007343 except:
7344 self.logger.error(ppp("Unexpected or invalid packet:", p))
7345 raise
7346
7347 # out to host1
7348 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7349 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007350 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007351 self.pg1.add_stream(p)
7352 self.pg_enable_capture(self.pg_interfaces)
7353 self.pg_start()
7354 capture = self.pg0.get_capture(1)
7355 p = capture[0]
7356 try:
7357 ip = p[IP]
7358 tcp = p[TCP]
7359 self.assertEqual(ip.src, self.pg1.remote_ip4)
7360 self.assertEqual(ip.dst, host1.ip4)
7361 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07007362 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007363 except:
7364 self.logger.error(ppp("Unexpected or invalid packet", p))
7365 raise
7366
Martin Gálik6bc8c642017-04-19 01:12:27 -07007367 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07007368 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7369 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07007370 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07007371 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07007372 dms = self.vapi.nat_det_map_dump()
7373 self.assertEqual(dms[0].ses_num, 1)
7374
7375 self.vapi.nat_det_close_session_in(host0.ip4n,
7376 port_in,
7377 self.pg1.remote_ip4n,
7378 external_port)
7379 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07007380 self.assertEqual(dms[0].ses_num, 0)
7381
Martin Gálik977c1cb2017-03-30 23:21:51 -07007382 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007383 """ Deterministic NAT TCP session close from inside network """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007384 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7385 in_plen=32,
7386 out_addr=socket.inet_aton(self.nat_addr),
7387 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007388 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007389 self.vapi.nat44_interface_add_del_feature(
7390 sw_if_index=self.pg0.sw_if_index,
7391 flags=flags, is_add=1)
7392 self.vapi.nat44_interface_add_del_feature(
7393 sw_if_index=self.pg1.sw_if_index,
7394 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007395
7396 self.initiate_tcp_session(self.pg0, self.pg1)
7397
7398 # close the session from inside
7399 try:
7400 # FIN packet in -> out
7401 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7402 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007403 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007404 flags="F"))
7405 self.pg0.add_stream(p)
7406 self.pg_enable_capture(self.pg_interfaces)
7407 self.pg_start()
7408 self.pg1.get_capture(1)
7409
7410 pkts = []
7411
7412 # ACK packet out -> in
7413 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007414 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007415 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007416 flags="A"))
7417 pkts.append(p)
7418
7419 # FIN packet out -> in
7420 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007421 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007422 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007423 flags="F"))
7424 pkts.append(p)
7425
7426 self.pg1.add_stream(pkts)
7427 self.pg_enable_capture(self.pg_interfaces)
7428 self.pg_start()
7429 self.pg0.get_capture(2)
7430
7431 # ACK packet in -> out
7432 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7433 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007434 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007435 flags="A"))
7436 self.pg0.add_stream(p)
7437 self.pg_enable_capture(self.pg_interfaces)
7438 self.pg_start()
7439 self.pg1.get_capture(1)
7440
Matus Fabian2ba92e32017-08-21 07:05:03 -07007441 # Check if deterministic NAT44 closed the session
7442 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007443 self.assertEqual(0, dms[0].ses_num)
7444 except:
7445 self.logger.error("TCP session termination failed")
7446 raise
7447
7448 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007449 """ Deterministic NAT TCP session close from outside network """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007450 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7451 in_plen=32,
7452 out_addr=socket.inet_aton(self.nat_addr),
7453 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007454 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007455 self.vapi.nat44_interface_add_del_feature(
7456 sw_if_index=self.pg0.sw_if_index,
7457 flags=flags, is_add=1)
7458 self.vapi.nat44_interface_add_del_feature(
7459 sw_if_index=self.pg1.sw_if_index,
7460 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007461
7462 self.initiate_tcp_session(self.pg0, self.pg1)
7463
7464 # close the session from outside
7465 try:
7466 # FIN packet out -> in
7467 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007468 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007469 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007470 flags="F"))
7471 self.pg1.add_stream(p)
7472 self.pg_enable_capture(self.pg_interfaces)
7473 self.pg_start()
7474 self.pg0.get_capture(1)
7475
7476 pkts = []
7477
7478 # ACK packet in -> out
7479 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7480 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007481 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007482 flags="A"))
7483 pkts.append(p)
7484
7485 # ACK packet in -> out
7486 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7487 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007488 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007489 flags="F"))
7490 pkts.append(p)
7491
7492 self.pg0.add_stream(pkts)
7493 self.pg_enable_capture(self.pg_interfaces)
7494 self.pg_start()
7495 self.pg1.get_capture(2)
7496
7497 # ACK packet out -> in
7498 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07007499 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007500 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007501 flags="A"))
7502 self.pg1.add_stream(p)
7503 self.pg_enable_capture(self.pg_interfaces)
7504 self.pg_start()
7505 self.pg0.get_capture(1)
7506
Matus Fabian2ba92e32017-08-21 07:05:03 -07007507 # Check if deterministic NAT44 closed the session
7508 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007509 self.assertEqual(0, dms[0].ses_num)
7510 except:
7511 self.logger.error("TCP session termination failed")
7512 raise
7513
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007514 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007515 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007516 """ Deterministic NAT session timeouts """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007517 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7518 in_plen=32,
7519 out_addr=socket.inet_aton(self.nat_addr),
7520 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007521 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007522 self.vapi.nat44_interface_add_del_feature(
7523 sw_if_index=self.pg0.sw_if_index,
7524 flags=flags, is_add=1)
7525 self.vapi.nat44_interface_add_del_feature(
7526 sw_if_index=self.pg1.sw_if_index,
7527 is_add=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007528
7529 self.initiate_tcp_session(self.pg0, self.pg1)
Filip Vargaf4749ca2019-04-25 14:55:32 +02007530 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7531 icmp=5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007532 pkts = self.create_stream_in(self.pg0, self.pg1)
7533 self.pg0.add_stream(pkts)
7534 self.pg_enable_capture(self.pg_interfaces)
7535 self.pg_start()
7536 capture = self.pg1.get_capture(len(pkts))
7537 sleep(15)
7538
Matus Fabian2ba92e32017-08-21 07:05:03 -07007539 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007540 self.assertEqual(0, dms[0].ses_num)
7541
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007542 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007543 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007544 """ Deterministic NAT maximum sessions per user limit """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007545 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
7546 in_plen=32,
7547 out_addr=socket.inet_aton(self.nat_addr),
7548 out_plen=32)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007549 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007550 self.vapi.nat44_interface_add_del_feature(
7551 sw_if_index=self.pg0.sw_if_index,
7552 flags=flags, is_add=1)
7553 self.vapi.nat44_interface_add_del_feature(
7554 sw_if_index=self.pg1.sw_if_index,
7555 is_add=1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007556 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7557 src_address=self.pg2.local_ip4n,
7558 path_mtu=512,
7559 template_interval=10)
Filip Vargaf4749ca2019-04-25 14:55:32 +02007560 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7561 enable=1)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007562
7563 pkts = []
7564 for port in range(1025, 2025):
7565 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7566 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7567 UDP(sport=port, dport=port))
7568 pkts.append(p)
7569
7570 self.pg0.add_stream(pkts)
7571 self.pg_enable_capture(self.pg_interfaces)
7572 self.pg_start()
7573 capture = self.pg1.get_capture(len(pkts))
7574
7575 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7576 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007577 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007578 self.pg0.add_stream(p)
7579 self.pg_enable_capture(self.pg_interfaces)
7580 self.pg_start()
7581 capture = self.pg1.assert_nothing_captured()
7582
Martin Gálikf7e655d2017-04-27 02:13:26 -07007583 # verify ICMP error packet
7584 capture = self.pg0.get_capture(1)
7585 p = capture[0]
7586 self.assertTrue(p.haslayer(ICMP))
7587 icmp = p[ICMP]
7588 self.assertEqual(icmp.type, 3)
7589 self.assertEqual(icmp.code, 1)
7590 self.assertTrue(icmp.haslayer(IPerror))
7591 inner_ip = icmp[IPerror]
7592 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7593 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7594
Matus Fabian2ba92e32017-08-21 07:05:03 -07007595 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007596
7597 self.assertEqual(1000, dms[0].ses_num)
7598
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007599 # verify IPFIX logging
7600 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007601 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007602 capture = self.pg2.get_capture(2)
7603 ipfix = IPFIXDecoder()
7604 # first load template
7605 for p in capture:
7606 self.assertTrue(p.haslayer(IPFIX))
7607 if p.haslayer(Template):
7608 ipfix.add_template(p.getlayer(Template))
7609 # verify events in data set
7610 for p in capture:
7611 if p.haslayer(Data):
7612 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007613 self.verify_ipfix_max_entries_per_user(data,
7614 1000,
7615 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007616
Matus Fabian2ba92e32017-08-21 07:05:03 -07007617 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007618 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007619 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007620 """
Filip Vargaf4749ca2019-04-25 14:55:32 +02007621 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7622 enable=0)
7623 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7624 tcp_transitory=240, icmp=60)
Matus Fabian2ba92e32017-08-21 07:05:03 -07007625 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007626 for dsm in deterministic_mappings:
Filip Vargaf4749ca2019-04-25 14:55:32 +02007627 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7628 in_plen=dsm.in_plen,
7629 out_addr=dsm.out_addr,
7630 out_plen=dsm.out_plen)
Martin17a75cb2017-03-08 05:53:20 -08007631
Matus Fabian2ba92e32017-08-21 07:05:03 -07007632 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007633 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +02007634 self.vapi.nat44_interface_add_del_feature(
7635 sw_if_index=intf.sw_if_index,
7636 flags=intf.flags)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007637
Matus Fabian066f0342017-02-10 03:48:01 -08007638 def tearDown(self):
7639 super(TestDeterministicNAT, self).tearDown()
7640 if not self.vpp_dead:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007641 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007642
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07007643 def show_commands_at_teardown(self):
7644 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7645 self.logger.info(self.vapi.cli("show nat timeouts"))
7646 self.logger.info(
7647 self.vapi.cli("show nat44 deterministic mappings"))
7648 self.logger.info(
7649 self.vapi.cli("show nat44 deterministic sessions"))
7650
Matus Fabian06596c52017-06-06 04:53:28 -07007651
7652class TestNAT64(MethodHolder):
7653 """ NAT64 Test Cases """
7654
7655 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007656 def setUpConstants(cls):
7657 super(TestNAT64, cls).setUpConstants()
7658 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7659 "nat64 st hash buckets 256", "}"])
7660
7661 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007662 def setUpClass(cls):
7663 super(TestNAT64, cls).setUpClass()
7664
7665 try:
7666 cls.tcp_port_in = 6303
7667 cls.tcp_port_out = 6303
7668 cls.udp_port_in = 6304
7669 cls.udp_port_out = 6304
7670 cls.icmp_id_in = 6305
7671 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007672 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007673 cls.nat_addr = '10.0.0.3'
7674 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007675 cls.vrf1_id = 10
7676 cls.vrf1_nat_addr = '10.0.10.3'
Matus Fabiana431ad12018-01-04 04:03:14 -08007677 cls.ipfix_src_port = 4739
7678 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007679
Juraj Slobodac746a152018-07-09 02:36:37 +02007680 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007681 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007682 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007683 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7684
Ole Troan9a475372019-03-05 16:58:24 +01007685 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7686 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007687
Matus Fabian029f3d22017-06-15 02:28:50 -07007688 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7689
7690 cls.pg0.generate_remote_hosts(2)
7691
Matus Fabian06596c52017-06-06 04:53:28 -07007692 for i in cls.ip6_interfaces:
7693 i.admin_up()
7694 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007695 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007696
7697 for i in cls.ip4_interfaces:
7698 i.admin_up()
7699 i.config_ip4()
7700 i.resolve_arp()
7701
Matus Fabian36ea2d62017-10-24 04:13:49 -07007702 cls.pg3.admin_up()
7703 cls.pg3.config_ip4()
7704 cls.pg3.resolve_arp()
7705 cls.pg3.config_ip6()
7706 cls.pg3.configure_ipv6_neighbors()
7707
Juraj Slobodac746a152018-07-09 02:36:37 +02007708 cls.pg5.admin_up()
7709 cls.pg5.config_ip6()
7710
Matus Fabian06596c52017-06-06 04:53:28 -07007711 except Exception:
7712 super(TestNAT64, cls).tearDownClass()
7713 raise
7714
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07007715 @classmethod
7716 def tearDownClass(cls):
7717 super(TestNAT64, cls).tearDownClass()
7718
Juraj Slobodac746a152018-07-09 02:36:37 +02007719 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7720 """ NAT64 inside interface handles Neighbor Advertisement """
7721
Filip Vargadd1e3e72019-04-15 18:52:43 +02007722 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007723 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7724 sw_if_index=self.pg5.sw_if_index)
Juraj Slobodac746a152018-07-09 02:36:37 +02007725
7726 # Try to send ping
7727 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7728 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7729 ICMPv6EchoRequest())
7730 pkts = [ping]
7731 self.pg5.add_stream(pkts)
7732 self.pg_enable_capture(self.pg_interfaces)
7733 self.pg_start()
7734
7735 # Wait for Neighbor Solicitation
7736 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007737 packet = capture[0]
7738 try:
7739 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007740 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007741 tgt = packet[ICMPv6ND_NS].tgt
7742 except:
7743 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7744 raise
7745
7746 # Send Neighbor Advertisement
7747 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7748 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7749 ICMPv6ND_NA(tgt=tgt) /
7750 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7751 pkts = [p]
7752 self.pg5.add_stream(pkts)
7753 self.pg_enable_capture(self.pg_interfaces)
7754 self.pg_start()
7755
7756 # Try to send ping again
7757 pkts = [ping]
7758 self.pg5.add_stream(pkts)
7759 self.pg_enable_capture(self.pg_interfaces)
7760 self.pg_start()
7761
7762 # Wait for ping reply
7763 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007764 packet = capture[0]
7765 try:
7766 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7767 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007768 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007769 except:
7770 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7771 raise
7772
Matus Fabian06596c52017-06-06 04:53:28 -07007773 def test_pool(self):
7774 """ Add/delete address to NAT64 pool """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007775 nat_addr = '1.2.3.4'
Matus Fabian06596c52017-06-06 04:53:28 -07007776
Filip Vargaf4749ca2019-04-25 14:55:32 +02007777 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7778 end_addr=nat_addr,
7779 vrf_id=0xFFFFFFFF, is_add=1)
Matus Fabian06596c52017-06-06 04:53:28 -07007780
7781 addresses = self.vapi.nat64_pool_addr_dump()
7782 self.assertEqual(len(addresses), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007783 self.assertEqual(str(addresses[0].address), nat_addr)
Matus Fabian06596c52017-06-06 04:53:28 -07007784
Filip Vargaf4749ca2019-04-25 14:55:32 +02007785 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7786 end_addr=nat_addr,
7787 vrf_id=0xFFFFFFFF, is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007788
7789 addresses = self.vapi.nat64_pool_addr_dump()
7790 self.assertEqual(len(addresses), 0)
7791
7792 def test_interface(self):
7793 """ Enable/disable NAT64 feature on the interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007794 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007795 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7796 sw_if_index=self.pg0.sw_if_index)
7797 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7798 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007799
7800 interfaces = self.vapi.nat64_interface_dump()
7801 self.assertEqual(len(interfaces), 2)
7802 pg0_found = False
7803 pg1_found = False
7804 for intf in interfaces:
7805 if intf.sw_if_index == self.pg0.sw_if_index:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007806 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
Matus Fabian06596c52017-06-06 04:53:28 -07007807 pg0_found = True
7808 elif intf.sw_if_index == self.pg1.sw_if_index:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007809 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
Matus Fabian06596c52017-06-06 04:53:28 -07007810 pg1_found = True
7811 self.assertTrue(pg0_found)
7812 self.assertTrue(pg1_found)
7813
7814 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007815 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007816 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007817 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007818
Filip Vargaf4749ca2019-04-25 14:55:32 +02007819 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7820 sw_if_index=self.pg0.sw_if_index)
7821 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7822 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007823
7824 interfaces = self.vapi.nat64_interface_dump()
7825 self.assertEqual(len(interfaces), 0)
7826
7827 def test_static_bib(self):
7828 """ Add/delete static BIB entry """
Filip Vargadd1e3e72019-04-15 18:52:43 +02007829 in_addr = '2001:db8:85a3::8a2e:370:7334'
7830 out_addr = '10.1.1.3'
Matus Fabian06596c52017-06-06 04:53:28 -07007831 in_port = 1234
7832 out_port = 5678
7833 proto = IP_PROTOS.tcp
7834
Filip Vargaf4749ca2019-04-25 14:55:32 +02007835 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7836 i_port=in_port, o_port=out_port,
7837 proto=proto, vrf_id=0, is_add=1)
7838 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
Matus Fabian06596c52017-06-06 04:53:28 -07007839 static_bib_num = 0
7840 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007841 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07007842 static_bib_num += 1
Filip Vargadd1e3e72019-04-15 18:52:43 +02007843 self.assertEqual(str(bibe.i_addr), in_addr)
7844 self.assertEqual(str(bibe.o_addr), out_addr)
Matus Fabian06596c52017-06-06 04:53:28 -07007845 self.assertEqual(bibe.i_port, in_port)
7846 self.assertEqual(bibe.o_port, out_port)
7847 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007848 bibs = self.statistics.get_counter('/nat64/total-bibs')
7849 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007850
Filip Vargaf4749ca2019-04-25 14:55:32 +02007851 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7852 i_port=in_port, o_port=out_port,
7853 proto=proto, vrf_id=0, is_add=0)
7854 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
Matus Fabian06596c52017-06-06 04:53:28 -07007855 static_bib_num = 0
7856 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02007857 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Matus Fabian06596c52017-06-06 04:53:28 -07007858 static_bib_num += 1
7859 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007860 bibs = self.statistics.get_counter('/nat64/total-bibs')
7861 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007862
7863 def test_set_timeouts(self):
7864 """ Set NAT64 timeouts """
7865 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007866 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007867 self.assertEqual(timeouts.udp, 300)
7868 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007869 self.assertEqual(timeouts.tcp_transitory, 240)
7870 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007871
7872 # set and verify custom values
Filip Vargaf4749ca2019-04-25 14:55:32 +02007873 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7874 tcp_transitory=250, icmp=30)
Matus Fabian878c6462018-08-23 00:33:35 -07007875 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007876 self.assertEqual(timeouts.udp, 200)
7877 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007878 self.assertEqual(timeouts.tcp_transitory, 250)
7879 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007880
7881 def test_dynamic(self):
7882 """ NAT64 dynamic translation test """
7883 self.tcp_port_in = 6303
7884 self.udp_port_in = 6304
7885 self.icmp_id_in = 6305
7886
7887 ses_num_start = self.nat64_get_ses_num()
7888
Filip Vargaf4749ca2019-04-25 14:55:32 +02007889 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7890 end_addr=self.nat_addr,
7891 vrf_id=0xFFFFFFFF,
7892 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007893 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007894 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7895 sw_if_index=self.pg0.sw_if_index)
7896 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7897 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07007898
7899 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007900 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7901 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7902 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7903 totaln = self.statistics.get_counter(
7904 '/err/nat64-in2out/good in2out packets processed')
7905
Matus Fabian06596c52017-06-06 04:53:28 -07007906 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7907 self.pg0.add_stream(pkts)
7908 self.pg_enable_capture(self.pg_interfaces)
7909 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007910 capture = self.pg1.get_capture(len(pkts))
7911 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007912 dst_ip=self.pg1.remote_ip4)
7913
Matus Fabiana5e73762018-12-14 01:55:16 -08007914 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7915 self.assertEqual(err - tcpn, 1)
7916 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7917 self.assertEqual(err - udpn, 1)
7918 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7919 self.assertEqual(err - icmpn, 1)
7920 err = self.statistics.get_counter(
7921 '/err/nat64-in2out/good in2out packets processed')
7922 self.assertEqual(err - totaln, 3)
7923
Matus Fabian06596c52017-06-06 04:53:28 -07007924 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007925 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7926 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7927 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7928 totaln = self.statistics.get_counter(
7929 '/err/nat64-out2in/good out2in packets processed')
7930
Matus Fabian06596c52017-06-06 04:53:28 -07007931 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7932 self.pg1.add_stream(pkts)
7933 self.pg_enable_capture(self.pg_interfaces)
7934 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007935 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007936 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7937 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7938
Matus Fabiana5e73762018-12-14 01:55:16 -08007939 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7940 self.assertEqual(err - tcpn, 1)
7941 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7942 self.assertEqual(err - udpn, 1)
7943 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7944 self.assertEqual(err - icmpn, 1)
7945 err = self.statistics.get_counter(
7946 '/err/nat64-out2in/good out2in packets processed')
7947 self.assertEqual(err - totaln, 3)
7948
Matus Fabianfd0d5082018-12-18 01:08:51 -08007949 bibs = self.statistics.get_counter('/nat64/total-bibs')
7950 self.assertEqual(bibs[0][0], 3)
7951 sessions = self.statistics.get_counter('/nat64/total-sessions')
7952 self.assertEqual(sessions[0][0], 3)
7953
Matus Fabian06596c52017-06-06 04:53:28 -07007954 # in2out
7955 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7956 self.pg0.add_stream(pkts)
7957 self.pg_enable_capture(self.pg_interfaces)
7958 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007959 capture = self.pg1.get_capture(len(pkts))
7960 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007961 dst_ip=self.pg1.remote_ip4)
7962
7963 # out2in
7964 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7965 self.pg1.add_stream(pkts)
7966 self.pg_enable_capture(self.pg_interfaces)
7967 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007968 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007969 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7970
7971 ses_num_end = self.nat64_get_ses_num()
7972
7973 self.assertEqual(ses_num_end - ses_num_start, 3)
7974
Matus Fabian029f3d22017-06-15 02:28:50 -07007975 # tenant with specific VRF
Filip Vargaf4749ca2019-04-25 14:55:32 +02007976 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
7977 end_addr=self.vrf1_nat_addr,
7978 vrf_id=self.vrf1_id, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02007979 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02007980 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7981 sw_if_index=self.pg2.sw_if_index)
Matus Fabian029f3d22017-06-15 02:28:50 -07007982
7983 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
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 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7997
Matus Fabian06596c52017-06-06 04:53:28 -07007998 def test_static(self):
7999 """ NAT64 static translation test """
8000 self.tcp_port_in = 60303
8001 self.udp_port_in = 60304
8002 self.icmp_id_in = 60305
8003 self.tcp_port_out = 60303
8004 self.udp_port_out = 60304
8005 self.icmp_id_out = 60305
8006
8007 ses_num_start = self.nat64_get_ses_num()
8008
Filip Vargaf4749ca2019-04-25 14:55:32 +02008009 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8010 end_addr=self.nat_addr,
8011 vrf_id=0xFFFFFFFF,
8012 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008013 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008014 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8015 sw_if_index=self.pg0.sw_if_index)
8016 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8017 sw_if_index=self.pg1.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07008018
Filip Vargaf4749ca2019-04-25 14:55:32 +02008019 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8020 o_addr=self.nat_addr,
8021 i_port=self.tcp_port_in,
8022 o_port=self.tcp_port_out,
8023 proto=IP_PROTOS.tcp, vrf_id=0,
8024 is_add=1)
8025 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8026 o_addr=self.nat_addr,
8027 i_port=self.udp_port_in,
8028 o_port=self.udp_port_out,
8029 proto=IP_PROTOS.udp, vrf_id=0,
8030 is_add=1)
8031 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8032 o_addr=self.nat_addr,
8033 i_port=self.icmp_id_in,
8034 o_port=self.icmp_id_out,
8035 proto=IP_PROTOS.icmp, vrf_id=0,
8036 is_add=1)
Matus Fabian06596c52017-06-06 04:53:28 -07008037
8038 # in2out
8039 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8040 self.pg0.add_stream(pkts)
8041 self.pg_enable_capture(self.pg_interfaces)
8042 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07008043 capture = self.pg1.get_capture(len(pkts))
8044 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07008045 dst_ip=self.pg1.remote_ip4, same_port=True)
8046
8047 # out2in
8048 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8049 self.pg1.add_stream(pkts)
8050 self.pg_enable_capture(self.pg_interfaces)
8051 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07008052 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07008053 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8054 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8055
8056 ses_num_end = self.nat64_get_ses_num()
8057
8058 self.assertEqual(ses_num_end - ses_num_start, 3)
8059
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008060 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07008061 def test_session_timeout(self):
8062 """ NAT64 session timeout """
8063 self.icmp_id_in = 1234
Filip Vargaf4749ca2019-04-25 14:55:32 +02008064 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8065 end_addr=self.nat_addr,
8066 vrf_id=0xFFFFFFFF,
8067 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008068 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008069 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8070 sw_if_index=self.pg0.sw_if_index)
8071 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8072 sw_if_index=self.pg1.sw_if_index)
8073 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8074 tcp_transitory=5,
8075 icmp=5)
Matus Fabian06596c52017-06-06 04:53:28 -07008076
8077 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8078 self.pg0.add_stream(pkts)
8079 self.pg_enable_capture(self.pg_interfaces)
8080 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07008081 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07008082
8083 ses_num_before_timeout = self.nat64_get_ses_num()
8084
8085 sleep(15)
8086
Matus Fabian8fed4242018-08-14 05:14:55 -07008087 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07008088 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07008089 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07008090
Matus Fabian732036d2017-06-08 05:24:28 -07008091 def test_icmp_error(self):
8092 """ NAT64 ICMP Error message translation """
8093 self.tcp_port_in = 6303
8094 self.udp_port_in = 6304
8095 self.icmp_id_in = 6305
8096
Filip Vargaf4749ca2019-04-25 14:55:32 +02008097 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8098 end_addr=self.nat_addr,
8099 vrf_id=0xFFFFFFFF,
8100 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008101 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008102 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8103 sw_if_index=self.pg0.sw_if_index)
8104 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8105 sw_if_index=self.pg1.sw_if_index)
Matus Fabian732036d2017-06-08 05:24:28 -07008106
8107 # send some packets to create sessions
8108 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8109 self.pg0.add_stream(pkts)
8110 self.pg_enable_capture(self.pg_interfaces)
8111 self.pg_start()
8112 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07008113 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07008114 nat_ip=self.nat_addr,
8115 dst_ip=self.pg1.remote_ip4)
8116
8117 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8118 self.pg1.add_stream(pkts)
8119 self.pg_enable_capture(self.pg_interfaces)
8120 self.pg_start()
8121 capture_ip6 = self.pg0.get_capture(len(pkts))
8122 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8123 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8124 self.pg0.remote_ip6)
8125
8126 # in2out
8127 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8128 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8129 ICMPv6DestUnreach(code=1) /
8130 packet[IPv6] for packet in capture_ip6]
8131 self.pg0.add_stream(pkts)
8132 self.pg_enable_capture(self.pg_interfaces)
8133 self.pg_start()
8134 capture = self.pg1.get_capture(len(pkts))
8135 for packet in capture:
8136 try:
8137 self.assertEqual(packet[IP].src, self.nat_addr)
8138 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8139 self.assertEqual(packet[ICMP].type, 3)
8140 self.assertEqual(packet[ICMP].code, 13)
8141 inner = packet[IPerror]
8142 self.assertEqual(inner.src, self.pg1.remote_ip4)
8143 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02008144 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07008145 if inner.haslayer(TCPerror):
8146 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8147 elif inner.haslayer(UDPerror):
8148 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8149 else:
8150 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8151 except:
8152 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8153 raise
8154
8155 # out2in
8156 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8157 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8158 ICMP(type=3, code=13) /
8159 packet[IP] for packet in capture_ip4]
8160 self.pg1.add_stream(pkts)
8161 self.pg_enable_capture(self.pg_interfaces)
8162 self.pg_start()
8163 capture = self.pg0.get_capture(len(pkts))
8164 for packet in capture:
8165 try:
8166 self.assertEqual(packet[IPv6].src, ip.src)
8167 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8168 icmp = packet[ICMPv6DestUnreach]
8169 self.assertEqual(icmp.code, 1)
8170 inner = icmp[IPerror6]
8171 self.assertEqual(inner.src, self.pg0.remote_ip6)
8172 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02008173 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07008174 if inner.haslayer(TCPerror):
8175 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8176 elif inner.haslayer(UDPerror):
8177 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8178 else:
8179 self.assertEqual(inner[ICMPv6EchoRequest].id,
8180 self.icmp_id_in)
8181 except:
8182 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8183 raise
8184
Matus Fabian029f3d22017-06-15 02:28:50 -07008185 def test_hairpinning(self):
8186 """ NAT64 hairpinning """
8187
8188 client = self.pg0.remote_hosts[0]
8189 server = self.pg0.remote_hosts[1]
8190 server_tcp_in_port = 22
8191 server_tcp_out_port = 4022
8192 server_udp_in_port = 23
8193 server_udp_out_port = 4023
8194 client_tcp_in_port = 1234
8195 client_udp_in_port = 1235
8196 client_tcp_out_port = 0
8197 client_udp_out_port = 0
8198 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8199 nat_addr_ip6 = ip.src
8200
Filip Vargaf4749ca2019-04-25 14:55:32 +02008201 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8202 end_addr=self.nat_addr,
8203 vrf_id=0xFFFFFFFF,
8204 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008205 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008206 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8207 sw_if_index=self.pg0.sw_if_index)
8208 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8209 sw_if_index=self.pg1.sw_if_index)
Matus Fabian029f3d22017-06-15 02:28:50 -07008210
Filip Vargaf4749ca2019-04-25 14:55:32 +02008211 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8212 o_addr=self.nat_addr,
8213 i_port=server_tcp_in_port,
8214 o_port=server_tcp_out_port,
8215 proto=IP_PROTOS.tcp, vrf_id=0,
8216 is_add=1)
8217 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8218 o_addr=self.nat_addr,
8219 i_port=server_udp_in_port,
8220 o_port=server_udp_out_port,
8221 proto=IP_PROTOS.udp, vrf_id=0,
8222 is_add=1)
Matus Fabian029f3d22017-06-15 02:28:50 -07008223
8224 # client to server
8225 pkts = []
8226 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8227 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8228 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8229 pkts.append(p)
8230 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8231 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8232 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8233 pkts.append(p)
8234 self.pg0.add_stream(pkts)
8235 self.pg_enable_capture(self.pg_interfaces)
8236 self.pg_start()
8237 capture = self.pg0.get_capture(len(pkts))
8238 for packet in capture:
8239 try:
8240 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8241 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008242 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07008243 if packet.haslayer(TCP):
8244 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8245 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008246 client_tcp_out_port = packet[TCP].sport
8247 else:
8248 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8249 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008250 client_udp_out_port = packet[UDP].sport
8251 except:
8252 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8253 raise
8254
8255 # server to client
8256 pkts = []
8257 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8258 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8259 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8260 pkts.append(p)
8261 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8262 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8263 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8264 pkts.append(p)
8265 self.pg0.add_stream(pkts)
8266 self.pg_enable_capture(self.pg_interfaces)
8267 self.pg_start()
8268 capture = self.pg0.get_capture(len(pkts))
8269 for packet in capture:
8270 try:
8271 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8272 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008273 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07008274 if packet.haslayer(TCP):
8275 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8276 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008277 else:
8278 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8279 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07008280 except:
8281 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8282 raise
8283
8284 # ICMP error
8285 pkts = []
8286 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8287 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8288 ICMPv6DestUnreach(code=1) /
8289 packet[IPv6] for packet in capture]
8290 self.pg0.add_stream(pkts)
8291 self.pg_enable_capture(self.pg_interfaces)
8292 self.pg_start()
8293 capture = self.pg0.get_capture(len(pkts))
8294 for packet in capture:
8295 try:
8296 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8297 self.assertEqual(packet[IPv6].dst, server.ip6)
8298 icmp = packet[ICMPv6DestUnreach]
8299 self.assertEqual(icmp.code, 1)
8300 inner = icmp[IPerror6]
8301 self.assertEqual(inner.src, server.ip6)
8302 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008303 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07008304 if inner.haslayer(TCPerror):
8305 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8306 self.assertEqual(inner[TCPerror].dport,
8307 client_tcp_out_port)
8308 else:
8309 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8310 self.assertEqual(inner[UDPerror].dport,
8311 client_udp_out_port)
8312 except:
8313 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8314 raise
8315
Matus Fabian428dc912017-06-21 06:15:18 -07008316 def test_prefix(self):
8317 """ NAT64 Network-Specific Prefix """
8318
Filip Vargaf4749ca2019-04-25 14:55:32 +02008319 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8320 end_addr=self.nat_addr,
8321 vrf_id=0xFFFFFFFF,
8322 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008323 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008324 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8325 sw_if_index=self.pg0.sw_if_index)
8326 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8327 sw_if_index=self.pg1.sw_if_index)
8328 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8329 end_addr=self.vrf1_nat_addr,
8330 vrf_id=self.vrf1_id, is_add=1)
8331 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8332 sw_if_index=self.pg2.sw_if_index)
Matus Fabian428dc912017-06-21 06:15:18 -07008333
8334 # Add global prefix
8335 global_pref64 = "2001:db8::"
Matus Fabian428dc912017-06-21 06:15:18 -07008336 global_pref64_len = 32
Filip Vargadd1e3e72019-04-15 18:52:43 +02008337 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
Filip Vargaf4749ca2019-04-25 14:55:32 +02008338 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8339 is_add=1)
Matus Fabian428dc912017-06-21 06:15:18 -07008340
8341 prefix = self.vapi.nat64_prefix_dump()
8342 self.assertEqual(len(prefix), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008343 self.assertEqual(prefix[0].prefix,
8344 IPv6Network(unicode(global_pref64_str)))
Matus Fabian428dc912017-06-21 06:15:18 -07008345 self.assertEqual(prefix[0].vrf_id, 0)
8346
8347 # Add tenant specific prefix
8348 vrf1_pref64 = "2001:db8:122:300::"
Matus Fabian428dc912017-06-21 06:15:18 -07008349 vrf1_pref64_len = 56
Filip Vargadd1e3e72019-04-15 18:52:43 +02008350 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
Filip Vargaf4749ca2019-04-25 14:55:32 +02008351 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8352 vrf_id=self.vrf1_id, is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008353
Matus Fabian428dc912017-06-21 06:15:18 -07008354 prefix = self.vapi.nat64_prefix_dump()
8355 self.assertEqual(len(prefix), 2)
8356
8357 # Global prefix
8358 pkts = self.create_stream_in_ip6(self.pg0,
8359 self.pg1,
8360 pref=global_pref64,
8361 plen=global_pref64_len)
8362 self.pg0.add_stream(pkts)
8363 self.pg_enable_capture(self.pg_interfaces)
8364 self.pg_start()
8365 capture = self.pg1.get_capture(len(pkts))
8366 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8367 dst_ip=self.pg1.remote_ip4)
8368
8369 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8370 self.pg1.add_stream(pkts)
8371 self.pg_enable_capture(self.pg_interfaces)
8372 self.pg_start()
8373 capture = self.pg0.get_capture(len(pkts))
8374 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8375 global_pref64,
8376 global_pref64_len)
8377 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8378
8379 # Tenant specific prefix
8380 pkts = self.create_stream_in_ip6(self.pg2,
8381 self.pg1,
8382 pref=vrf1_pref64,
8383 plen=vrf1_pref64_len)
8384 self.pg2.add_stream(pkts)
8385 self.pg_enable_capture(self.pg_interfaces)
8386 self.pg_start()
8387 capture = self.pg1.get_capture(len(pkts))
8388 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8389 dst_ip=self.pg1.remote_ip4)
8390
8391 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8392 self.pg1.add_stream(pkts)
8393 self.pg_enable_capture(self.pg_interfaces)
8394 self.pg_start()
8395 capture = self.pg2.get_capture(len(pkts))
8396 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8397 vrf1_pref64,
8398 vrf1_pref64_len)
8399 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8400
Matus Fabianf8cd5812017-07-11 03:55:02 -07008401 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07008402 """ NAT64 translate packet with unknown protocol """
8403
Filip Vargaf4749ca2019-04-25 14:55:32 +02008404 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8405 end_addr=self.nat_addr,
8406 vrf_id=0xFFFFFFFF,
8407 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008408 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008409 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8410 sw_if_index=self.pg0.sw_if_index)
8411 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8412 sw_if_index=self.pg1.sw_if_index)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008413 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8414
8415 # in2out
8416 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8417 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8418 TCP(sport=self.tcp_port_in, dport=20))
8419 self.pg0.add_stream(p)
8420 self.pg_enable_capture(self.pg_interfaces)
8421 self.pg_start()
8422 p = self.pg1.get_capture(1)
8423
8424 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008425 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008426 GRE() /
8427 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8428 TCP(sport=1234, dport=1234))
8429 self.pg0.add_stream(p)
8430 self.pg_enable_capture(self.pg_interfaces)
8431 self.pg_start()
8432 p = self.pg1.get_capture(1)
8433 packet = p[0]
8434 try:
8435 self.assertEqual(packet[IP].src, self.nat_addr)
8436 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08008437 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02008438 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008439 except:
8440 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8441 raise
8442
8443 # out2in
8444 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8445 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8446 GRE() /
8447 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8448 TCP(sport=1234, dport=1234))
8449 self.pg1.add_stream(p)
8450 self.pg_enable_capture(self.pg_interfaces)
8451 self.pg_start()
8452 p = self.pg0.get_capture(1)
8453 packet = p[0]
8454 try:
8455 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008456 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8457 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008458 except:
8459 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8460 raise
8461
Matus Fabianf8cd5812017-07-11 03:55:02 -07008462 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07008463 """ NAT64 translate packet with unknown protocol - hairpinning """
8464
8465 client = self.pg0.remote_hosts[0]
8466 server = self.pg0.remote_hosts[1]
8467 server_tcp_in_port = 22
8468 server_tcp_out_port = 4022
8469 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07008470 client_tcp_out_port = 1235
8471 server_nat_ip = "10.0.0.100"
8472 client_nat_ip = "10.0.0.110"
Matus Fabianf8cd5812017-07-11 03:55:02 -07008473 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8474 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008475
Filip Vargaf4749ca2019-04-25 14:55:32 +02008476 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8477 end_addr=client_nat_ip,
8478 vrf_id=0xFFFFFFFF,
8479 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008480 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008481 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8482 sw_if_index=self.pg0.sw_if_index)
8483 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8484 sw_if_index=self.pg1.sw_if_index)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008485
Filip Vargaf4749ca2019-04-25 14:55:32 +02008486 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8487 o_addr=server_nat_ip,
8488 i_port=server_tcp_in_port,
8489 o_port=server_tcp_out_port,
8490 proto=IP_PROTOS.tcp, vrf_id=0,
8491 is_add=1)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008492
Filip Vargaf4749ca2019-04-25 14:55:32 +02008493 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8494 o_addr=server_nat_ip, i_port=0,
8495 o_port=0,
8496 proto=IP_PROTOS.gre, vrf_id=0,
8497 is_add=1)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008498
Filip Vargaf4749ca2019-04-25 14:55:32 +02008499 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8500 o_addr=client_nat_ip,
8501 i_port=client_tcp_in_port,
8502 o_port=client_tcp_out_port,
8503 proto=IP_PROTOS.tcp, vrf_id=0,
8504 is_add=1)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008505
Matus Fabian7968e6c2017-07-06 05:37:49 -07008506 # client to server
8507 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008508 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008509 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8510 self.pg0.add_stream(p)
8511 self.pg_enable_capture(self.pg_interfaces)
8512 self.pg_start()
8513 p = self.pg0.get_capture(1)
8514
8515 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008516 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008517 GRE() /
8518 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8519 TCP(sport=1234, dport=1234))
8520 self.pg0.add_stream(p)
8521 self.pg_enable_capture(self.pg_interfaces)
8522 self.pg_start()
8523 p = self.pg0.get_capture(1)
8524 packet = p[0]
8525 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07008526 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008527 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008528 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008529 except:
8530 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8531 raise
8532
8533 # server to client
8534 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07008535 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07008536 GRE() /
8537 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8538 TCP(sport=1234, dport=1234))
8539 self.pg0.add_stream(p)
8540 self.pg_enable_capture(self.pg_interfaces)
8541 self.pg_start()
8542 p = self.pg0.get_capture(1)
8543 packet = p[0]
8544 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07008545 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008546 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07008547 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07008548 except:
8549 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8550 raise
8551
Matus Fabian36ea2d62017-10-24 04:13:49 -07008552 def test_one_armed_nat64(self):
8553 """ One armed NAT64 """
8554 external_port = 0
8555 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8556 '64:ff9b::',
8557 96)
8558
Filip Vargaf4749ca2019-04-25 14:55:32 +02008559 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8560 end_addr=self.nat_addr,
8561 vrf_id=0xFFFFFFFF,
8562 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008563 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008564 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8565 sw_if_index=self.pg3.sw_if_index)
8566 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8567 sw_if_index=self.pg3.sw_if_index)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008568
8569 # in2out
8570 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8571 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8572 TCP(sport=12345, dport=80))
8573 self.pg3.add_stream(p)
8574 self.pg_enable_capture(self.pg_interfaces)
8575 self.pg_start()
8576 capture = self.pg3.get_capture(1)
8577 p = capture[0]
8578 try:
8579 ip = p[IP]
8580 tcp = p[TCP]
8581 self.assertEqual(ip.src, self.nat_addr)
8582 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8583 self.assertNotEqual(tcp.sport, 12345)
8584 external_port = tcp.sport
8585 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008586 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008587 except:
8588 self.logger.error(ppp("Unexpected or invalid packet:", p))
8589 raise
8590
8591 # out2in
8592 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8593 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8594 TCP(sport=80, dport=external_port))
8595 self.pg3.add_stream(p)
8596 self.pg_enable_capture(self.pg_interfaces)
8597 self.pg_start()
8598 capture = self.pg3.get_capture(1)
8599 p = capture[0]
8600 try:
8601 ip = p[IPv6]
8602 tcp = p[TCP]
8603 self.assertEqual(ip.src, remote_host_ip6)
8604 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8605 self.assertEqual(tcp.sport, 80)
8606 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008607 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008608 except:
8609 self.logger.error(ppp("Unexpected or invalid packet:", p))
8610 raise
8611
Matus Fabianefcd1e92017-08-15 06:59:19 -07008612 def test_frag_in_order(self):
8613 """ NAT64 translate fragments arriving in order """
8614 self.tcp_port_in = random.randint(1025, 65535)
8615
Filip Vargaf4749ca2019-04-25 14:55:32 +02008616 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8617 end_addr=self.nat_addr,
8618 vrf_id=0xFFFFFFFF,
8619 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008620 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008621 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8622 sw_if_index=self.pg0.sw_if_index)
8623 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8624 sw_if_index=self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008625
8626 reass = self.vapi.nat_reass_dump()
8627 reass_n_start = len(reass)
8628
8629 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008630 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008631 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8632 self.tcp_port_in, 20, data)
8633 self.pg0.add_stream(pkts)
8634 self.pg_enable_capture(self.pg_interfaces)
8635 self.pg_start()
8636 frags = self.pg1.get_capture(len(pkts))
8637 p = self.reass_frags_and_verify(frags,
8638 self.nat_addr,
8639 self.pg1.remote_ip4)
8640 self.assertEqual(p[TCP].dport, 20)
8641 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8642 self.tcp_port_out = p[TCP].sport
8643 self.assertEqual(data, p[Raw].load)
8644
8645 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008646 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008647 pkts = self.create_stream_frag(self.pg1,
8648 self.nat_addr,
8649 20,
8650 self.tcp_port_out,
8651 data)
8652 self.pg1.add_stream(pkts)
8653 self.pg_enable_capture(self.pg_interfaces)
8654 self.pg_start()
8655 frags = self.pg0.get_capture(len(pkts))
8656 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8657 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8658 self.assertEqual(p[TCP].sport, 20)
8659 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8660 self.assertEqual(data, p[Raw].load)
8661
8662 reass = self.vapi.nat_reass_dump()
8663 reass_n_end = len(reass)
8664
8665 self.assertEqual(reass_n_end - reass_n_start, 2)
8666
8667 def test_reass_hairpinning(self):
8668 """ NAT64 fragments hairpinning """
8669 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008670 server = self.pg0.remote_hosts[1]
8671 server_in_port = random.randint(1025, 65535)
8672 server_out_port = random.randint(1025, 65535)
8673 client_in_port = random.randint(1025, 65535)
8674 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8675 nat_addr_ip6 = ip.src
8676
Filip Vargaf4749ca2019-04-25 14:55:32 +02008677 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8678 end_addr=self.nat_addr,
8679 vrf_id=0xFFFFFFFF,
8680 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008681 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008682 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8683 sw_if_index=self.pg0.sw_if_index)
8684 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8685 sw_if_index=self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008686
8687 # add static BIB entry for server
Filip Vargaf4749ca2019-04-25 14:55:32 +02008688 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8689 o_addr=self.nat_addr,
8690 i_port=server_in_port,
8691 o_port=server_out_port,
8692 proto=IP_PROTOS.tcp, vrf_id=0,
8693 is_add=1)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008694
8695 # send packet from host to server
8696 pkts = self.create_stream_frag_ip6(self.pg0,
8697 self.nat_addr,
8698 client_in_port,
8699 server_out_port,
8700 data)
8701 self.pg0.add_stream(pkts)
8702 self.pg_enable_capture(self.pg_interfaces)
8703 self.pg_start()
8704 frags = self.pg0.get_capture(len(pkts))
8705 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8706 self.assertNotEqual(p[TCP].sport, client_in_port)
8707 self.assertEqual(p[TCP].dport, server_in_port)
8708 self.assertEqual(data, p[Raw].load)
8709
8710 def test_frag_out_of_order(self):
8711 """ NAT64 translate fragments arriving out of order """
8712 self.tcp_port_in = random.randint(1025, 65535)
8713
Filip Vargaf4749ca2019-04-25 14:55:32 +02008714 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8715 end_addr=self.nat_addr,
8716 vrf_id=0xFFFFFFFF,
8717 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008718 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008719 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8720 sw_if_index=self.pg0.sw_if_index)
8721 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8722 sw_if_index=self.pg1.sw_if_index)
Matus Fabianefcd1e92017-08-15 06:59:19 -07008723
8724 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008725 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008726 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8727 self.tcp_port_in, 20, data)
8728 pkts.reverse()
8729 self.pg0.add_stream(pkts)
8730 self.pg_enable_capture(self.pg_interfaces)
8731 self.pg_start()
8732 frags = self.pg1.get_capture(len(pkts))
8733 p = self.reass_frags_and_verify(frags,
8734 self.nat_addr,
8735 self.pg1.remote_ip4)
8736 self.assertEqual(p[TCP].dport, 20)
8737 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8738 self.tcp_port_out = p[TCP].sport
8739 self.assertEqual(data, p[Raw].load)
8740
8741 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008742 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008743 pkts = self.create_stream_frag(self.pg1,
8744 self.nat_addr,
8745 20,
8746 self.tcp_port_out,
8747 data)
8748 pkts.reverse()
8749 self.pg1.add_stream(pkts)
8750 self.pg_enable_capture(self.pg_interfaces)
8751 self.pg_start()
8752 frags = self.pg0.get_capture(len(pkts))
8753 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8754 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8755 self.assertEqual(p[TCP].sport, 20)
8756 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8757 self.assertEqual(data, p[Raw].load)
8758
Matus Fabian0938dcf2017-11-08 01:59:38 -08008759 def test_interface_addr(self):
8760 """ Acquire NAT64 pool addresses from interface """
Filip Vargaf4749ca2019-04-25 14:55:32 +02008761 self.vapi.nat64_add_del_interface_addr(
8762 is_add=1,
8763 sw_if_index=self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008764
8765 # no address in NAT64 pool
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008766 addresses = self.vapi.nat44_address_dump()
8767 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008768
8769 # configure interface address and check NAT64 address pool
8770 self.pg4.config_ip4()
8771 addresses = self.vapi.nat64_pool_addr_dump()
8772 self.assertEqual(len(addresses), 1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008773
8774 self.assertEqual(str(addresses[0].address),
8775 self.pg4.local_ip4)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008776
8777 # remove interface address and check NAT64 address pool
8778 self.pg4.unconfig_ip4()
8779 addresses = self.vapi.nat64_pool_addr_dump()
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07008780 self.assertEqual(0, len(addresses))
Matus Fabian0938dcf2017-11-08 01:59:38 -08008781
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008782 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008783 def test_ipfix_max_bibs_sessions(self):
8784 """ IPFIX logging maximum session and BIB entries exceeded """
8785 max_bibs = 1280
8786 max_sessions = 2560
8787 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8788 '64:ff9b::',
8789 96)
8790
Filip Vargaf4749ca2019-04-25 14:55:32 +02008791 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8792 end_addr=self.nat_addr,
8793 vrf_id=0xFFFFFFFF,
8794 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008795 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008796 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8797 sw_if_index=self.pg0.sw_if_index)
8798 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8799 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08008800
8801 pkts = []
8802 src = ""
8803 for i in range(0, max_bibs):
8804 src = "fd01:aa::%x" % (i)
8805 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8806 IPv6(src=src, dst=remote_host_ip6) /
8807 TCP(sport=12345, dport=80))
8808 pkts.append(p)
8809 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8810 IPv6(src=src, dst=remote_host_ip6) /
8811 TCP(sport=12345, dport=22))
8812 pkts.append(p)
8813 self.pg0.add_stream(pkts)
8814 self.pg_enable_capture(self.pg_interfaces)
8815 self.pg_start()
8816 self.pg1.get_capture(max_sessions)
8817
8818 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8819 src_address=self.pg3.local_ip4n,
8820 path_mtu=512,
8821 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008822 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02008823 src_port=self.ipfix_src_port,
8824 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008825
8826 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8827 IPv6(src=src, dst=remote_host_ip6) /
8828 TCP(sport=12345, dport=25))
8829 self.pg0.add_stream(p)
8830 self.pg_enable_capture(self.pg_interfaces)
8831 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008832 self.pg1.assert_nothing_captured()
8833 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008834 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8835 capture = self.pg3.get_capture(9)
8836 ipfix = IPFIXDecoder()
8837 # first load template
8838 for p in capture:
8839 self.assertTrue(p.haslayer(IPFIX))
8840 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8841 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8842 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8843 self.assertEqual(p[UDP].dport, 4739)
8844 self.assertEqual(p[IPFIX].observationDomainID,
8845 self.ipfix_domain_id)
8846 if p.haslayer(Template):
8847 ipfix.add_template(p.getlayer(Template))
8848 # verify events in data set
8849 for p in capture:
8850 if p.haslayer(Data):
8851 data = ipfix.decode_data_set(p.getlayer(Set))
8852 self.verify_ipfix_max_sessions(data, max_sessions)
8853
8854 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8855 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8856 TCP(sport=12345, dport=80))
8857 self.pg0.add_stream(p)
8858 self.pg_enable_capture(self.pg_interfaces)
8859 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008860 self.pg1.assert_nothing_captured()
8861 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008862 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8863 capture = self.pg3.get_capture(1)
8864 # verify events in data set
8865 for p in capture:
8866 self.assertTrue(p.haslayer(IPFIX))
8867 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8868 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8869 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8870 self.assertEqual(p[UDP].dport, 4739)
8871 self.assertEqual(p[IPFIX].observationDomainID,
8872 self.ipfix_domain_id)
8873 if p.haslayer(Data):
8874 data = ipfix.decode_data_set(p.getlayer(Set))
8875 self.verify_ipfix_max_bibs(data, max_bibs)
8876
8877 def test_ipfix_max_frags(self):
8878 """ IPFIX logging maximum fragments pending reassembly exceeded """
Filip Vargaf4749ca2019-04-25 14:55:32 +02008879 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8880 end_addr=self.nat_addr,
8881 vrf_id=0xFFFFFFFF,
8882 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008883 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008884 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8885 sw_if_index=self.pg0.sw_if_index)
8886 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8887 sw_if_index=self.pg1.sw_if_index)
8888 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
8889 drop_frag=0, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008890 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8891 src_address=self.pg3.local_ip4n,
8892 path_mtu=512,
8893 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008894 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02008895 src_port=self.ipfix_src_port,
8896 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008897
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008898 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008899 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8900 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008901 pkts.reverse()
8902 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008903 self.pg_enable_capture(self.pg_interfaces)
8904 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008905 self.pg1.assert_nothing_captured()
8906 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008907 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8908 capture = self.pg3.get_capture(9)
8909 ipfix = IPFIXDecoder()
8910 # first load template
8911 for p in capture:
8912 self.assertTrue(p.haslayer(IPFIX))
8913 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8914 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8915 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8916 self.assertEqual(p[UDP].dport, 4739)
8917 self.assertEqual(p[IPFIX].observationDomainID,
8918 self.ipfix_domain_id)
8919 if p.haslayer(Template):
8920 ipfix.add_template(p.getlayer(Template))
8921 # verify events in data set
8922 for p in capture:
8923 if p.haslayer(Data):
8924 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008925 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008926 self.pg0.remote_ip6n)
8927
8928 def test_ipfix_bib_ses(self):
8929 """ IPFIX logging NAT64 BIB/session create and delete events """
8930 self.tcp_port_in = random.randint(1025, 65535)
8931 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8932 '64:ff9b::',
8933 96)
8934
Filip Vargaf4749ca2019-04-25 14:55:32 +02008935 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8936 end_addr=self.nat_addr,
8937 vrf_id=0xFFFFFFFF,
8938 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02008939 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02008940 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8941 sw_if_index=self.pg0.sw_if_index)
8942 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8943 sw_if_index=self.pg1.sw_if_index)
Matus Fabiana431ad12018-01-04 04:03:14 -08008944 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8945 src_address=self.pg3.local_ip4n,
8946 path_mtu=512,
8947 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008948 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Filip Vargaf4749ca2019-04-25 14:55:32 +02008949 src_port=self.ipfix_src_port,
8950 enable=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008951
8952 # Create
8953 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8954 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8955 TCP(sport=self.tcp_port_in, dport=25))
8956 self.pg0.add_stream(p)
8957 self.pg_enable_capture(self.pg_interfaces)
8958 self.pg_start()
8959 p = self.pg1.get_capture(1)
8960 self.tcp_port_out = p[0][TCP].sport
8961 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8962 capture = self.pg3.get_capture(10)
8963 ipfix = IPFIXDecoder()
8964 # first load template
8965 for p in capture:
8966 self.assertTrue(p.haslayer(IPFIX))
8967 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8968 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8969 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8970 self.assertEqual(p[UDP].dport, 4739)
8971 self.assertEqual(p[IPFIX].observationDomainID,
8972 self.ipfix_domain_id)
8973 if p.haslayer(Template):
8974 ipfix.add_template(p.getlayer(Template))
8975 # verify events in data set
8976 for p in capture:
8977 if p.haslayer(Data):
8978 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008979 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008980 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008981 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008982 self.verify_ipfix_nat64_ses(data,
8983 1,
8984 self.pg0.remote_ip6n,
8985 self.pg1.remote_ip4,
8986 25)
8987 else:
8988 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8989
8990 # Delete
8991 self.pg_enable_capture(self.pg_interfaces)
Filip Vargaf4749ca2019-04-25 14:55:32 +02008992 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8993 end_addr=self.nat_addr,
8994 vrf_id=0xFFFFFFFF,
Matus Fabiana431ad12018-01-04 04:03:14 -08008995 is_add=0)
8996 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8997 capture = self.pg3.get_capture(2)
8998 # verify events in data set
8999 for p in capture:
9000 self.assertTrue(p.haslayer(IPFIX))
9001 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9002 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9003 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9004 self.assertEqual(p[UDP].dport, 4739)
9005 self.assertEqual(p[IPFIX].observationDomainID,
9006 self.ipfix_domain_id)
9007 if p.haslayer(Data):
9008 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07009009 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08009010 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07009011 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08009012 self.verify_ipfix_nat64_ses(data,
9013 0,
9014 self.pg0.remote_ip6n,
9015 self.pg1.remote_ip4,
9016 25)
9017 else:
9018 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9019
Matus Fabianad1f3e12018-11-28 21:26:34 -08009020 def test_syslog_sess(self):
9021 """ Test syslog session creation and deletion """
9022 self.tcp_port_in = random.randint(1025, 65535)
9023 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9024 '64:ff9b::',
9025 96)
9026
Filip Vargaf4749ca2019-04-25 14:55:32 +02009027 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9028 end_addr=self.nat_addr,
9029 vrf_id=0xFFFFFFFF,
9030 is_add=1)
Filip Vargadd1e3e72019-04-15 18:52:43 +02009031 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02009032 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9033 sw_if_index=self.pg0.sw_if_index)
9034 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9035 sw_if_index=self.pg1.sw_if_index)
Matus Fabianad1f3e12018-11-28 21:26:34 -08009036 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01009037 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08009038
9039 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9040 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9041 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9042 self.pg0.add_stream(p)
9043 self.pg_enable_capture(self.pg_interfaces)
9044 self.pg_start()
9045 p = self.pg1.get_capture(1)
9046 self.tcp_port_out = p[0][TCP].sport
9047 capture = self.pg3.get_capture(1)
9048 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9049
9050 self.pg_enable_capture(self.pg_interfaces)
9051 self.pg_start()
Filip Vargaf4749ca2019-04-25 14:55:32 +02009052 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9053 end_addr=self.nat_addr,
9054 vrf_id=0xFFFFFFFF,
Matus Fabianad1f3e12018-11-28 21:26:34 -08009055 is_add=0)
9056 capture = self.pg3.get_capture(1)
9057 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9058
Matus Fabian06596c52017-06-06 04:53:28 -07009059 def nat64_get_ses_num(self):
9060 """
9061 Return number of active NAT64 sessions.
9062 """
Filip Vargaf4749ca2019-04-25 14:55:32 +02009063 st = self.vapi.nat64_st_dump(proto=255)
Matus Fabianab9a59c2017-08-16 05:37:36 -07009064 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07009065
9066 def clear_nat64(self):
9067 """
9068 Clear NAT64 configuration.
9069 """
Filip Vargaf4749ca2019-04-25 14:55:32 +02009070 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
Ole Troane1ade682019-03-04 23:55:43 +01009071 src_port=self.ipfix_src_port,
Filip Vargaf4749ca2019-04-25 14:55:32 +02009072 enable=0)
Matus Fabiana431ad12018-01-04 04:03:14 -08009073 self.ipfix_src_port = 4739
9074 self.ipfix_domain_id = 1
9075
Matus Fabianad1f3e12018-11-28 21:26:34 -08009076 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
9077
Filip Vargaf4749ca2019-04-25 14:55:32 +02009078 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9079 tcp_transitory=240, icmp=60)
Matus Fabian06596c52017-06-06 04:53:28 -07009080
9081 interfaces = self.vapi.nat64_interface_dump()
9082 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009083 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9084 sw_if_index=intf.sw_if_index)
Matus Fabian06596c52017-06-06 04:53:28 -07009085
Filip Vargaf4749ca2019-04-25 14:55:32 +02009086 bib = self.vapi.nat64_bib_dump(proto=255)
Matus Fabian06596c52017-06-06 04:53:28 -07009087 for bibe in bib:
Filip Vargadd1e3e72019-04-15 18:52:43 +02009088 if bibe.flags & self.config_flags.NAT_IS_STATIC:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009089 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9090 o_addr=bibe.o_addr,
9091 i_port=bibe.i_port,
9092 o_port=bibe.o_port,
9093 proto=bibe.proto,
9094 vrf_id=bibe.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07009095 is_add=0)
9096
9097 adresses = self.vapi.nat64_pool_addr_dump()
9098 for addr in adresses:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009099 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9100 end_addr=addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07009101 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07009102 is_add=0)
9103
Matus Fabian428dc912017-06-21 06:15:18 -07009104 prefixes = self.vapi.nat64_prefix_dump()
9105 for prefix in prefixes:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009106 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9107 vrf_id=prefix.vrf_id, is_add=0)
Matus Fabian428dc912017-06-21 06:15:18 -07009108
Matus Fabianfd0d5082018-12-18 01:08:51 -08009109 bibs = self.statistics.get_counter('/nat64/total-bibs')
9110 self.assertEqual(bibs[0][0], 0)
9111 sessions = self.statistics.get_counter('/nat64/total-sessions')
9112 self.assertEqual(sessions[0][0], 0)
9113
Matus Fabian06596c52017-06-06 04:53:28 -07009114 def tearDown(self):
9115 super(TestNAT64, self).tearDown()
9116 if not self.vpp_dead:
Matus Fabian06596c52017-06-06 04:53:28 -07009117 self.clear_nat64()
9118
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009119 def show_commands_at_teardown(self):
9120 self.logger.info(self.vapi.cli("show nat64 pool"))
9121 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9122 self.logger.info(self.vapi.cli("show nat64 prefix"))
9123 self.logger.info(self.vapi.cli("show nat64 bib all"))
9124 self.logger.info(self.vapi.cli("show nat64 session table all"))
9125 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
9126
Matus Fabian8ebe6252017-11-06 05:04:53 -08009127
9128class TestDSlite(MethodHolder):
9129 """ DS-Lite Test Cases """
9130
9131 @classmethod
9132 def setUpClass(cls):
9133 super(TestDSlite, cls).setUpClass()
9134
9135 try:
9136 cls.nat_addr = '10.0.0.3'
Matus Fabian8ebe6252017-11-06 05:04:53 -08009137
Matus Fabianad1f3e12018-11-28 21:26:34 -08009138 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08009139 cls.pg0.admin_up()
9140 cls.pg0.config_ip4()
9141 cls.pg0.resolve_arp()
9142 cls.pg1.admin_up()
9143 cls.pg1.config_ip6()
9144 cls.pg1.generate_remote_hosts(2)
9145 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08009146 cls.pg2.admin_up()
9147 cls.pg2.config_ip4()
9148 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08009149
9150 except Exception:
9151 super(TestDSlite, cls).tearDownClass()
9152 raise
9153
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009154 @classmethod
9155 def tearDownClass(cls):
9156 super(TestDSlite, cls).tearDownClass()
9157
Matus Fabianad1f3e12018-11-28 21:26:34 -08009158 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
9159 sv6enc, proto):
9160 message = data.decode('utf-8')
9161 try:
9162 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08009163 except ParseError as e:
9164 self.logger.error(e)
9165 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08009166 self.assertEqual(message.severity, SyslogSeverity.info)
9167 self.assertEqual(message.appname, 'NAT')
9168 self.assertEqual(message.msgid, 'APMADD')
9169 sd_params = message.sd.get('napmap')
9170 self.assertTrue(sd_params is not None)
9171 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
9172 self.assertEqual(sd_params.get('ISADDR'), isaddr)
9173 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
9174 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
9175 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
9176 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
9177 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
9178 self.assertTrue(sd_params.get('SSUBIX') is not None)
9179 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08009180
Matus Fabian8ebe6252017-11-06 05:04:53 -08009181 def test_dslite(self):
9182 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07009183 nat_config = self.vapi.nat_show_config()
9184 self.assertEqual(0, nat_config.dslite_ce)
9185
Filip Vargaf4749ca2019-04-25 14:55:32 +02009186 self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr,
9187 end_addr=self.nat_addr,
9188 is_add=1)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009189 aftr_ip4 = '192.0.0.1'
Matus Fabian8ebe6252017-11-06 05:04:53 -08009190 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
Filip Vargaf4749ca2019-04-25 14:55:32 +02009191 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
Ole Troanf159f582019-02-28 20:20:47 +01009192 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009193
9194 # UDP
9195 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9196 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
9197 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9198 UDP(sport=20000, dport=10000))
9199 self.pg1.add_stream(p)
9200 self.pg_enable_capture(self.pg_interfaces)
9201 self.pg_start()
9202 capture = self.pg0.get_capture(1)
9203 capture = capture[0]
9204 self.assertFalse(capture.haslayer(IPv6))
9205 self.assertEqual(capture[IP].src, self.nat_addr)
9206 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9207 self.assertNotEqual(capture[UDP].sport, 20000)
9208 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009209 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009210 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08009211 capture = self.pg2.get_capture(1)
9212 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
9213 20000, self.nat_addr, out_port,
9214 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009215
9216 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9217 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9218 UDP(sport=10000, dport=out_port))
9219 self.pg0.add_stream(p)
9220 self.pg_enable_capture(self.pg_interfaces)
9221 self.pg_start()
9222 capture = self.pg1.get_capture(1)
9223 capture = capture[0]
9224 self.assertEqual(capture[IPv6].src, aftr_ip6)
9225 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9226 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9227 self.assertEqual(capture[IP].dst, '192.168.1.1')
9228 self.assertEqual(capture[UDP].sport, 10000)
9229 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009230 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009231
9232 # TCP
9233 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9234 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9235 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9236 TCP(sport=20001, dport=10001))
9237 self.pg1.add_stream(p)
9238 self.pg_enable_capture(self.pg_interfaces)
9239 self.pg_start()
9240 capture = self.pg0.get_capture(1)
9241 capture = capture[0]
9242 self.assertFalse(capture.haslayer(IPv6))
9243 self.assertEqual(capture[IP].src, self.nat_addr)
9244 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9245 self.assertNotEqual(capture[TCP].sport, 20001)
9246 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02009247 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009248 out_port = capture[TCP].sport
9249
9250 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9251 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9252 TCP(sport=10001, dport=out_port))
9253 self.pg0.add_stream(p)
9254 self.pg_enable_capture(self.pg_interfaces)
9255 self.pg_start()
9256 capture = self.pg1.get_capture(1)
9257 capture = capture[0]
9258 self.assertEqual(capture[IPv6].src, aftr_ip6)
9259 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9260 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9261 self.assertEqual(capture[IP].dst, '192.168.1.1')
9262 self.assertEqual(capture[TCP].sport, 10001)
9263 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02009264 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009265
9266 # ICMP
9267 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9268 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9269 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9270 ICMP(id=4000, type='echo-request'))
9271 self.pg1.add_stream(p)
9272 self.pg_enable_capture(self.pg_interfaces)
9273 self.pg_start()
9274 capture = self.pg0.get_capture(1)
9275 capture = capture[0]
9276 self.assertFalse(capture.haslayer(IPv6))
9277 self.assertEqual(capture[IP].src, self.nat_addr)
9278 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9279 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009280 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009281 out_id = capture[ICMP].id
9282
9283 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9284 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9285 ICMP(id=out_id, type='echo-reply'))
9286 self.pg0.add_stream(p)
9287 self.pg_enable_capture(self.pg_interfaces)
9288 self.pg_start()
9289 capture = self.pg1.get_capture(1)
9290 capture = capture[0]
9291 self.assertEqual(capture[IPv6].src, aftr_ip6)
9292 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9293 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9294 self.assertEqual(capture[IP].dst, '192.168.1.1')
9295 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009296 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08009297
Matus Fabian331acc62017-12-08 03:38:51 -08009298 # ping DS-Lite AFTR tunnel endpoint address
9299 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9300 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
9301 ICMPv6EchoRequest())
9302 self.pg1.add_stream(p)
9303 self.pg_enable_capture(self.pg_interfaces)
9304 self.pg_start()
9305 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08009306 capture = capture[0]
9307 self.assertEqual(capture[IPv6].src, aftr_ip6)
9308 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9309 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9310
Matus Fabianfd0d5082018-12-18 01:08:51 -08009311 b4s = self.statistics.get_counter('/dslite/total-b4s')
9312 self.assertEqual(b4s[0][0], 2)
9313 sessions = self.statistics.get_counter('/dslite/total-sessions')
9314 self.assertEqual(sessions[0][0], 3)
9315
Matus Fabian8ebe6252017-11-06 05:04:53 -08009316 def tearDown(self):
9317 super(TestDSlite, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009318
9319 def show_commands_at_teardown(self):
9320 self.logger.info(self.vapi.cli("show dslite pool"))
9321 self.logger.info(
9322 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9323 self.logger.info(self.vapi.cli("show dslite sessions"))
Matus Fabian8ebe6252017-11-06 05:04:53 -08009324
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009325
9326class TestDSliteCE(MethodHolder):
9327 """ DS-Lite CE Test Cases """
9328
9329 @classmethod
9330 def setUpConstants(cls):
9331 super(TestDSliteCE, cls).setUpConstants()
9332 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
9333
9334 @classmethod
9335 def setUpClass(cls):
9336 super(TestDSliteCE, cls).setUpClass()
9337
9338 try:
9339 cls.create_pg_interfaces(range(2))
9340 cls.pg0.admin_up()
9341 cls.pg0.config_ip4()
9342 cls.pg0.resolve_arp()
9343 cls.pg1.admin_up()
9344 cls.pg1.config_ip6()
9345 cls.pg1.generate_remote_hosts(1)
9346 cls.pg1.configure_ipv6_neighbors()
9347
9348 except Exception:
9349 super(TestDSliteCE, cls).tearDownClass()
9350 raise
9351
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009352 @classmethod
9353 def tearDownClass(cls):
9354 super(TestDSliteCE, cls).tearDownClass()
9355
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009356 def test_dslite_ce(self):
9357 """ Test DS-Lite CE """
9358
Matus Fabian69ce30d2018-08-22 01:27:10 -07009359 nat_config = self.vapi.nat_show_config()
9360 self.assertEqual(1, nat_config.dslite_ce)
9361
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009362 b4_ip4 = '192.0.0.2'
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009363 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
Filip Vargaf4749ca2019-04-25 14:55:32 +02009364 self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009365
9366 aftr_ip4 = '192.0.0.1'
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009367 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
9368 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
Filip Vargaf4749ca2019-04-25 14:55:32 +02009369 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009370
9371 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
9372 dst_address_length=128,
9373 next_hop_address=self.pg1.remote_ip6n,
9374 next_hop_sw_if_index=self.pg1.sw_if_index,
9375 is_ipv6=1)
9376
9377 # UDP encapsulation
9378 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9379 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
9380 UDP(sport=10000, dport=20000))
9381 self.pg0.add_stream(p)
9382 self.pg_enable_capture(self.pg_interfaces)
9383 self.pg_start()
9384 capture = self.pg1.get_capture(1)
9385 capture = capture[0]
9386 self.assertEqual(capture[IPv6].src, b4_ip6)
9387 self.assertEqual(capture[IPv6].dst, aftr_ip6)
9388 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9389 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
9390 self.assertEqual(capture[UDP].sport, 10000)
9391 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009392 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009393
9394 # UDP decapsulation
9395 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9396 IPv6(dst=b4_ip6, src=aftr_ip6) /
9397 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
9398 UDP(sport=20000, dport=10000))
9399 self.pg1.add_stream(p)
9400 self.pg_enable_capture(self.pg_interfaces)
9401 self.pg_start()
9402 capture = self.pg0.get_capture(1)
9403 capture = capture[0]
9404 self.assertFalse(capture.haslayer(IPv6))
9405 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
9406 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9407 self.assertEqual(capture[UDP].sport, 20000)
9408 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02009409 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009410
9411 # ping DS-Lite B4 tunnel endpoint address
9412 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9413 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
9414 ICMPv6EchoRequest())
9415 self.pg1.add_stream(p)
9416 self.pg_enable_capture(self.pg_interfaces)
9417 self.pg_start()
9418 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009419 capture = capture[0]
9420 self.assertEqual(capture[IPv6].src, b4_ip6)
9421 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9422 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9423
9424 def tearDown(self):
9425 super(TestDSliteCE, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009426
9427 def show_commands_at_teardown(self):
9428 self.logger.info(
9429 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9430 self.logger.info(
9431 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
Juraj Slobodac5c6a332018-01-09 16:08:32 +01009432
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009433
9434class TestNAT66(MethodHolder):
9435 """ NAT66 Test Cases """
9436
9437 @classmethod
9438 def setUpClass(cls):
9439 super(TestNAT66, cls).setUpClass()
9440
9441 try:
9442 cls.nat_addr = 'fd01:ff::2'
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009443
9444 cls.create_pg_interfaces(range(2))
9445 cls.interfaces = list(cls.pg_interfaces)
9446
9447 for i in cls.interfaces:
9448 i.admin_up()
9449 i.config_ip6()
9450 i.configure_ipv6_neighbors()
9451
9452 except Exception:
9453 super(TestNAT66, cls).tearDownClass()
9454 raise
9455
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07009456 @classmethod
9457 def tearDownClass(cls):
9458 super(TestNAT66, cls).tearDownClass()
9459
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009460 def test_static(self):
9461 """ 1:1 NAT66 test """
Filip Vargadd1e3e72019-04-15 18:52:43 +02009462 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02009463 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9464 sw_if_index=self.pg0.sw_if_index)
9465 self.vapi.nat66_add_del_interface(is_add=1,
9466 sw_if_index=self.pg1.sw_if_index)
9467 self.vapi.nat66_add_del_static_mapping(
9468 local_ip_address=self.pg0.remote_ip6n,
9469 external_ip_address=self.nat_addr,
9470 is_add=1)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009471
9472 # in2out
9473 pkts = []
9474 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9475 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9476 TCP())
9477 pkts.append(p)
9478 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9479 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9480 UDP())
9481 pkts.append(p)
9482 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9483 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9484 ICMPv6EchoRequest())
9485 pkts.append(p)
9486 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9487 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9488 GRE() / IP() / TCP())
9489 pkts.append(p)
9490 self.pg0.add_stream(pkts)
9491 self.pg_enable_capture(self.pg_interfaces)
9492 self.pg_start()
9493 capture = self.pg1.get_capture(len(pkts))
9494 for packet in capture:
9495 try:
9496 self.assertEqual(packet[IPv6].src, self.nat_addr)
9497 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02009498 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009499 except:
9500 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9501 raise
9502
9503 # out2in
9504 pkts = []
9505 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9506 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9507 TCP())
9508 pkts.append(p)
9509 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9510 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9511 UDP())
9512 pkts.append(p)
9513 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9514 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9515 ICMPv6EchoReply())
9516 pkts.append(p)
9517 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9518 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9519 GRE() / IP() / TCP())
9520 pkts.append(p)
9521 self.pg1.add_stream(pkts)
9522 self.pg_enable_capture(self.pg_interfaces)
9523 self.pg_start()
9524 capture = self.pg0.get_capture(len(pkts))
9525 for packet in capture:
9526 try:
9527 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9528 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02009529 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009530 except:
9531 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9532 raise
9533
9534 sm = self.vapi.nat66_static_mapping_dump()
9535 self.assertEqual(len(sm), 1)
9536 self.assertEqual(sm[0].total_pkts, 8)
9537
Juraj Sloboda9341e342018-04-13 12:00:46 +02009538 def test_check_no_translate(self):
9539 """ NAT66 translate only when egress interface is outside interface """
Filip Vargadd1e3e72019-04-15 18:52:43 +02009540 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargaf4749ca2019-04-25 14:55:32 +02009541 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9542 sw_if_index=self.pg0.sw_if_index)
9543 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9544 sw_if_index=self.pg1.sw_if_index)
9545 self.vapi.nat66_add_del_static_mapping(
9546 local_ip_address=self.pg0.remote_ip6n,
9547 external_ip_address=self.nat_addr,
9548 is_add=1)
Juraj Sloboda9341e342018-04-13 12:00:46 +02009549
9550 # in2out
9551 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9552 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9553 UDP())
9554 self.pg0.add_stream([p])
9555 self.pg_enable_capture(self.pg_interfaces)
9556 self.pg_start()
9557 capture = self.pg1.get_capture(1)
9558 packet = capture[0]
9559 try:
9560 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9561 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9562 except:
9563 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9564 raise
9565
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009566 def clear_nat66(self):
9567 """
9568 Clear NAT66 configuration.
9569 """
9570 interfaces = self.vapi.nat66_interface_dump()
9571 for intf in interfaces:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009572 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9573 sw_if_index=intf.sw_if_index)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009574
9575 static_mappings = self.vapi.nat66_static_mapping_dump()
9576 for sm in static_mappings:
Filip Vargaf4749ca2019-04-25 14:55:32 +02009577 self.vapi.nat66_add_del_static_mapping(
9578 local_ip_address=sm.local_ip_address,
9579 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9580 is_add=0)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009581
9582 def tearDown(self):
9583 super(TestNAT66, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009584 self.clear_nat66()
Matus Fabianf2a23cc2018-01-22 03:41:53 -08009585
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07009586 def show_commands_at_teardown(self):
9587 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9588 self.logger.info(self.vapi.cli("show nat66 static mappings"))
Klement Sekerad81ae412018-05-16 10:52:54 +02009589
Filip Vargaf4749ca2019-04-25 14:55:32 +02009590
Matus Fabiande886752016-12-07 03:38:19 -08009591if __name__ == '__main__':
9592 unittest.main(testRunner=VppTestRunner)