blob: fce7efe36ee825c0c6465116a7a41c86009c9fbb [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
Matus Fabiande886752016-12-07 03:38:19 -08009from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080010from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Juraj Slobodac746a152018-07-09 02:36:37 +020011from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
Paul Vinciguerra978aa642018-11-24 22:19:12 -080012 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
Matus Fabianefcd1e92017-08-15 06:59:19 -070013from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070014from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080015from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070016from scapy.packet import bind_layers, Raw
Klement Sekera9225dee2016-12-12 08:36:58 +010017from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080018from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070019from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070020from util import ip4_range
Ole Troan8006c6a2018-12-17 12:02:26 +010021from vpp_papi import mac_pton
Matus Fabianad1f3e12018-11-28 21:26:34 -080022from syslog_rfc5424_parser import SyslogMessage, ParseError
23from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
24from vpp_papi_provider import SYSLOG_SEVERITY
Ole Troan7f991832018-12-06 17:35:12 +010025from io import BytesIO
Neale Ranns37029302018-08-10 05:30:06 -070026from vpp_papi import VppEnum
Matus Fabian34931eb2019-02-26 09:05:23 -080027from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
28 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
29 PacketListField
30
31
32# NAT HA protocol event data
33class Event(Packet):
34 name = "Event"
35 fields_desc = [ByteEnumField("event_type", None,
36 {1: "add", 2: "del", 3: "refresh"}),
37 ByteEnumField("protocol", None,
38 {0: "udp", 1: "tcp", 2: "icmp"}),
39 ShortField("flags", 0),
40 IPField("in_addr", None),
41 IPField("out_addr", None),
42 ShortField("in_port", None),
43 ShortField("out_port", None),
44 IPField("eh_addr", None),
45 IPField("ehn_addr", None),
46 ShortField("eh_port", None),
47 ShortField("ehn_port", None),
48 IntField("fib_index", None),
49 IntField("total_pkts", 0),
50 LongField("total_bytes", 0)]
51
52 def extract_padding(self, s):
53 return "", s
54
55
56# NAT HA protocol header
57class HANATStateSync(Packet):
58 name = "HA NAT state sync"
59 fields_desc = [XByteField("version", 1),
60 FlagsField("flags", 0, 8, ['ACK']),
61 FieldLenField("count", None, count_of="events"),
62 IntField("sequence_number", 1),
63 IntField("thread_index", 0),
64 PacketListField("events", [], Event,
65 count_from=lambda pkt:pkt.count)]
Matus Fabiande886752016-12-07 03:38:19 -080066
67
Martin Gálikd7f75cd2017-03-27 06:02:47 -070068class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070069 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080070
Matus Fabiana6110b62018-06-13 05:39:07 -070071 def clear_nat44(self):
72 """
73 Clear NAT44 configuration.
74 """
75 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
76 # I found no elegant way to do this
77 self.vapi.ip_add_del_route(
78 dst_address=self.pg7.remote_ip4n,
79 dst_address_length=32,
80 next_hop_address=self.pg7.remote_ip4n,
81 next_hop_sw_if_index=self.pg7.sw_if_index,
82 is_add=0)
83 self.vapi.ip_add_del_route(
84 dst_address=self.pg8.remote_ip4n,
85 dst_address_length=32,
86 next_hop_address=self.pg8.remote_ip4n,
87 next_hop_sw_if_index=self.pg8.sw_if_index,
88 is_add=0)
89
90 for intf in [self.pg7, self.pg8]:
Neale Ranns37029302018-08-10 05:30:06 -070091 self.vapi.ip_neighbor_add_del(
92 intf.sw_if_index,
93 intf.remote_mac,
94 intf.remote_ip4,
95 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
96 IP_API_NEIGHBOR_FLAG_STATIC),
97 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -070098
99 if self.pg7.has_ip4_config:
100 self.pg7.unconfig_ip4()
101
102 self.vapi.nat44_forwarding_enable_disable(0)
103
104 interfaces = self.vapi.nat44_interface_addr_dump()
105 for intf in interfaces:
106 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
107 twice_nat=intf.twice_nat,
108 is_add=0)
109
110 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
111 domain_id=self.ipfix_domain_id)
112 self.ipfix_src_port = 4739
113 self.ipfix_domain_id = 1
114
Matus Fabianad1f3e12018-11-28 21:26:34 -0800115 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
116
Matus Fabian34931eb2019-02-26 09:05:23 -0800117 self.vapi.nat_ha_set_listener('0.0.0.0', 0)
118 self.vapi.nat_ha_set_failover('0.0.0.0', 0)
119
Matus Fabiana6110b62018-06-13 05:39:07 -0700120 interfaces = self.vapi.nat44_interface_dump()
121 for intf in interfaces:
122 if intf.is_inside > 1:
123 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
124 0,
125 is_add=0)
126 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
127 intf.is_inside,
128 is_add=0)
129
130 interfaces = self.vapi.nat44_interface_output_feature_dump()
131 for intf in interfaces:
132 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
133 intf.is_inside,
134 is_add=0)
135
136 static_mappings = self.vapi.nat44_static_mapping_dump()
137 for sm in static_mappings:
138 self.vapi.nat44_add_del_static_mapping(
139 sm.local_ip_address,
140 sm.external_ip_address,
141 local_port=sm.local_port,
142 external_port=sm.external_port,
143 addr_only=sm.addr_only,
144 vrf_id=sm.vrf_id,
145 protocol=sm.protocol,
146 twice_nat=sm.twice_nat,
147 self_twice_nat=sm.self_twice_nat,
148 out2in_only=sm.out2in_only,
149 tag=sm.tag,
150 external_sw_if_index=sm.external_sw_if_index,
151 is_add=0)
152
153 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
154 for lb_sm in lb_static_mappings:
155 self.vapi.nat44_add_del_lb_static_mapping(
156 lb_sm.external_addr,
157 lb_sm.external_port,
158 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700159 twice_nat=lb_sm.twice_nat,
160 self_twice_nat=lb_sm.self_twice_nat,
161 out2in_only=lb_sm.out2in_only,
162 tag=lb_sm.tag,
163 is_add=0,
164 local_num=0,
165 locals=[])
166
167 identity_mappings = self.vapi.nat44_identity_mapping_dump()
168 for id_m in identity_mappings:
169 self.vapi.nat44_add_del_identity_mapping(
170 addr_only=id_m.addr_only,
171 ip=id_m.ip_address,
172 port=id_m.port,
173 sw_if_index=id_m.sw_if_index,
174 vrf_id=id_m.vrf_id,
175 protocol=id_m.protocol,
176 is_add=0)
177
178 adresses = self.vapi.nat44_address_dump()
179 for addr in adresses:
180 self.vapi.nat44_add_del_address_range(addr.ip_address,
181 addr.ip_address,
182 twice_nat=addr.twice_nat,
183 is_add=0)
184
185 self.vapi.nat_set_reass()
186 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700187 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700188 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700189 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabianbb4e0222018-09-13 02:36:25 -0700190 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700191
192 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
193 local_port=0, external_port=0, vrf_id=0,
194 is_add=1, external_sw_if_index=0xFFFFFFFF,
195 proto=0, twice_nat=0, self_twice_nat=0,
196 out2in_only=0, tag=""):
197 """
198 Add/delete NAT44 static mapping
199
200 :param local_ip: Local IP address
201 :param external_ip: External IP address
202 :param local_port: Local port number (Optional)
203 :param external_port: External port number (Optional)
204 :param vrf_id: VRF ID (Default 0)
205 :param is_add: 1 if add, 0 if delete (Default add)
206 :param external_sw_if_index: External interface instead of IP address
207 :param proto: IP protocol (Mandatory if port specified)
208 :param twice_nat: 1 if translate external host address and port
209 :param self_twice_nat: 1 if translate external host address and port
210 whenever external host address equals
211 local address of internal host
212 :param out2in_only: if 1 rule is matching only out2in direction
213 :param tag: Opaque string tag
214 """
215 addr_only = 1
216 if local_port and external_port:
217 addr_only = 0
218 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
219 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
220 self.vapi.nat44_add_del_static_mapping(
221 l_ip,
222 e_ip,
223 external_sw_if_index,
224 local_port,
225 external_port,
226 addr_only,
227 vrf_id,
228 proto,
229 twice_nat,
230 self_twice_nat,
231 out2in_only,
232 tag,
233 is_add)
234
235 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
236 """
237 Add/delete NAT44 address
238
239 :param ip: IP address
240 :param is_add: 1 if add, 0 if delete (Default add)
241 :param twice_nat: twice NAT address for extenal hosts
242 """
243 nat_addr = socket.inet_pton(socket.AF_INET, ip)
244 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
245 vrf_id=vrf_id,
246 twice_nat=twice_nat)
247
Juraj Slobodacba69362017-12-19 02:09:32 +0100248 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800249 """
250 Create packet stream for inside network
251
252 :param in_if: Inside interface
253 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100254 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800255 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800256 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100257 if dst_ip is None:
258 dst_ip = out_if.remote_ip4
259
Matus Fabiande886752016-12-07 03:38:19 -0800260 pkts = []
261 # TCP
262 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100263 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700264 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800265 pkts.append(p)
266
267 # UDP
268 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100269 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700270 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800271 pkts.append(p)
272
273 # ICMP
274 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100275 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800276 ICMP(id=self.icmp_id_in, type='echo-request'))
277 pkts.append(p)
278
279 return pkts
280
Matus Fabian428dc912017-06-21 06:15:18 -0700281 def compose_ip6(self, ip4, pref, plen):
282 """
283 Compose IPv4-embedded IPv6 addresses
284
285 :param ip4: IPv4 address
286 :param pref: IPv6 prefix
287 :param plen: IPv6 prefix length
288 :returns: IPv4-embedded IPv6 addresses
289 """
290 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
291 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
292 if plen == 32:
293 pref_n[4] = ip4_n[0]
294 pref_n[5] = ip4_n[1]
295 pref_n[6] = ip4_n[2]
296 pref_n[7] = ip4_n[3]
297 elif plen == 40:
298 pref_n[5] = ip4_n[0]
299 pref_n[6] = ip4_n[1]
300 pref_n[7] = ip4_n[2]
301 pref_n[9] = ip4_n[3]
302 elif plen == 48:
303 pref_n[6] = ip4_n[0]
304 pref_n[7] = ip4_n[1]
305 pref_n[9] = ip4_n[2]
306 pref_n[10] = ip4_n[3]
307 elif plen == 56:
308 pref_n[7] = ip4_n[0]
309 pref_n[9] = ip4_n[1]
310 pref_n[10] = ip4_n[2]
311 pref_n[11] = ip4_n[3]
312 elif plen == 64:
313 pref_n[9] = ip4_n[0]
314 pref_n[10] = ip4_n[1]
315 pref_n[11] = ip4_n[2]
316 pref_n[12] = ip4_n[3]
317 elif plen == 96:
318 pref_n[12] = ip4_n[0]
319 pref_n[13] = ip4_n[1]
320 pref_n[14] = ip4_n[2]
321 pref_n[15] = ip4_n[3]
322 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
323
Juraj Slobodacba69362017-12-19 02:09:32 +0100324 def extract_ip4(self, ip6, plen):
325 """
326 Extract IPv4 address embedded in IPv6 addresses
327
328 :param ip6: IPv6 address
329 :param plen: IPv6 prefix length
330 :returns: extracted IPv4 address
331 """
332 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
333 ip4_n = [None] * 4
334 if plen == 32:
335 ip4_n[0] = ip6_n[4]
336 ip4_n[1] = ip6_n[5]
337 ip4_n[2] = ip6_n[6]
338 ip4_n[3] = ip6_n[7]
339 elif plen == 40:
340 ip4_n[0] = ip6_n[5]
341 ip4_n[1] = ip6_n[6]
342 ip4_n[2] = ip6_n[7]
343 ip4_n[3] = ip6_n[9]
344 elif plen == 48:
345 ip4_n[0] = ip6_n[6]
346 ip4_n[1] = ip6_n[7]
347 ip4_n[2] = ip6_n[9]
348 ip4_n[3] = ip6_n[10]
349 elif plen == 56:
350 ip4_n[0] = ip6_n[7]
351 ip4_n[1] = ip6_n[9]
352 ip4_n[2] = ip6_n[10]
353 ip4_n[3] = ip6_n[11]
354 elif plen == 64:
355 ip4_n[0] = ip6_n[9]
356 ip4_n[1] = ip6_n[10]
357 ip4_n[2] = ip6_n[11]
358 ip4_n[3] = ip6_n[12]
359 elif plen == 96:
360 ip4_n[0] = ip6_n[12]
361 ip4_n[1] = ip6_n[13]
362 ip4_n[2] = ip6_n[14]
363 ip4_n[3] = ip6_n[15]
364 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
365
Matus Fabian428dc912017-06-21 06:15:18 -0700366 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700367 """
368 Create IPv6 packet stream for inside network
369
370 :param in_if: Inside interface
371 :param out_if: Outside interface
372 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700373 :param pref: NAT64 prefix
374 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700375 """
376 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700377 if pref is None:
378 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
379 else:
380 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
381
Matus Fabian06596c52017-06-06 04:53:28 -0700382 # TCP
383 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
384 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
385 TCP(sport=self.tcp_port_in, dport=20))
386 pkts.append(p)
387
388 # UDP
389 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
390 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
391 UDP(sport=self.udp_port_in, dport=20))
392 pkts.append(p)
393
394 # ICMP
395 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
396 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
397 ICMPv6EchoRequest(id=self.icmp_id_in))
398 pkts.append(p)
399
400 return pkts
401
Juraj Sloboda7b929792017-11-23 13:20:48 +0100402 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
403 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800404 """
405 Create packet stream for outside network
406
407 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700408 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800409 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100410 :param use_inside_ports: Use inside NAT ports as destination ports
411 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800412 """
413 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700414 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100415 if not use_inside_ports:
416 tcp_port = self.tcp_port_out
417 udp_port = self.udp_port_out
418 icmp_id = self.icmp_id_out
419 else:
420 tcp_port = self.tcp_port_in
421 udp_port = self.udp_port_in
422 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800423 pkts = []
424 # TCP
425 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800426 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100427 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800428 pkts.append(p)
429
430 # UDP
431 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800432 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100433 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800434 pkts.append(p)
435
436 # ICMP
437 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800438 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100439 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800440 pkts.append(p)
441
442 return pkts
443
Juraj Slobodacba69362017-12-19 02:09:32 +0100444 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
445 """
446 Create packet stream for outside network
447
448 :param out_if: Outside interface
449 :param dst_ip: Destination IP address (Default use global NAT address)
450 :param hl: HL of generated packets
451 """
452 pkts = []
453 # TCP
454 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
455 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
456 TCP(dport=self.tcp_port_out, sport=20))
457 pkts.append(p)
458
459 # UDP
460 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
461 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
462 UDP(dport=self.udp_port_out, sport=20))
463 pkts.append(p)
464
465 # ICMP
466 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
467 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
468 ICMPv6EchoReply(id=self.icmp_id_out))
469 pkts.append(p)
470
471 return pkts
472
Matus Fabiande886752016-12-07 03:38:19 -0800473 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700474 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800475 """
476 Verify captured packets on outside network
477
478 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700479 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800480 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700481 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100482 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800483 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100484 if is_ip6:
485 IP46 = IPv6
486 ICMP46 = ICMPv6EchoRequest
487 else:
488 IP46 = IP
489 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800490 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700491 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800492 for packet in capture:
493 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100494 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200495 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100496 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700497 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100498 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800499 if packet.haslayer(TCP):
500 if same_port:
501 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
502 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100503 self.assertNotEqual(
504 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800505 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200506 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800507 elif packet.haslayer(UDP):
508 if same_port:
509 self.assertEqual(packet[UDP].sport, self.udp_port_in)
510 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100511 self.assertNotEqual(
512 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800513 self.udp_port_out = packet[UDP].sport
514 else:
515 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100516 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800517 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100518 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
519 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200520 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800521 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100522 self.logger.error(ppp("Unexpected or invalid packet "
523 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800524 raise
525
Juraj Slobodacba69362017-12-19 02:09:32 +0100526 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700527 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100528 """
529 Verify captured packets on outside network
530
531 :param capture: Captured packets
532 :param nat_ip: Translated IP address
533 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100534 :param dst_ip: Destination IP address (Default do not verify)
535 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700536 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
537 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100538
Matus Fabian05ca4a32018-09-04 23:45:13 -0700539 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800540 """
541 Verify captured packets on inside network
542
543 :param capture: Captured packets
544 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800545 """
Matus Fabiande886752016-12-07 03:38:19 -0800546 for packet in capture:
547 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200548 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800549 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
550 if packet.haslayer(TCP):
551 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
552 elif packet.haslayer(UDP):
553 self.assertEqual(packet[UDP].dport, self.udp_port_in)
554 else:
555 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
556 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100557 self.logger.error(ppp("Unexpected or invalid packet "
558 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800559 raise
560
Matus Fabian05ca4a32018-09-04 23:45:13 -0700561 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700562 """
563 Verify captured IPv6 packets on inside network
564
565 :param capture: Captured packets
566 :param src_ip: Source IP
567 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700568 """
Matus Fabian06596c52017-06-06 04:53:28 -0700569 for packet in capture:
570 try:
571 self.assertEqual(packet[IPv6].src, src_ip)
572 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200573 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700574 if packet.haslayer(TCP):
575 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
576 elif packet.haslayer(UDP):
577 self.assertEqual(packet[UDP].dport, self.udp_port_in)
578 else:
579 self.assertEqual(packet[ICMPv6EchoReply].id,
580 self.icmp_id_in)
581 except:
582 self.logger.error(ppp("Unexpected or invalid packet "
583 "(inside network):", packet))
584 raise
585
Matus Fabian675a69c2017-01-18 01:46:01 -0800586 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
587 """
588 Verify captured packet that don't have to be translated
589
590 :param capture: Captured packets
591 :param ingress_if: Ingress interface
592 :param egress_if: Egress interface
593 """
594 for packet in capture:
595 try:
596 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
597 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
598 if packet.haslayer(TCP):
599 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
600 elif packet.haslayer(UDP):
601 self.assertEqual(packet[UDP].sport, self.udp_port_in)
602 else:
603 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
604 except:
605 self.logger.error(ppp("Unexpected or invalid packet "
606 "(inside network):", packet))
607 raise
608
Juraj Slobodab33f4132017-02-08 23:54:21 -0800609 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700610 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800611 """
612 Verify captured packets with ICMP errors on outside network
613
614 :param capture: Captured packets
615 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700616 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800617 :param icmp_type: Type of error ICMP packet
618 we are expecting (Default 11)
619 """
620 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700621 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800622 for packet in capture:
623 try:
624 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800625 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800626 icmp = packet[ICMP]
627 self.assertEqual(icmp.type, icmp_type)
628 self.assertTrue(icmp.haslayer(IPerror))
629 inner_ip = icmp[IPerror]
630 if inner_ip.haslayer(TCPerror):
631 self.assertEqual(inner_ip[TCPerror].dport,
632 self.tcp_port_out)
633 elif inner_ip.haslayer(UDPerror):
634 self.assertEqual(inner_ip[UDPerror].dport,
635 self.udp_port_out)
636 else:
637 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
638 except:
639 self.logger.error(ppp("Unexpected or invalid packet "
640 "(outside network):", packet))
641 raise
642
Matus Fabian05ca4a32018-09-04 23:45:13 -0700643 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800644 """
645 Verify captured packets with ICMP errors on inside network
646
647 :param capture: Captured packets
648 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800649 :param icmp_type: Type of error ICMP packet
650 we are expecting (Default 11)
651 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800652 for packet in capture:
653 try:
654 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800655 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800656 icmp = packet[ICMP]
657 self.assertEqual(icmp.type, icmp_type)
658 self.assertTrue(icmp.haslayer(IPerror))
659 inner_ip = icmp[IPerror]
660 if inner_ip.haslayer(TCPerror):
661 self.assertEqual(inner_ip[TCPerror].sport,
662 self.tcp_port_in)
663 elif inner_ip.haslayer(UDPerror):
664 self.assertEqual(inner_ip[UDPerror].sport,
665 self.udp_port_in)
666 else:
667 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
668 except:
669 self.logger.error(ppp("Unexpected or invalid packet "
670 "(inside network):", packet))
671 raise
672
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200673 def create_stream_frag(self, src_if, dst, sport, dport, data,
674 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700675 """
676 Create fragmented packet stream
677
678 :param src_if: Source interface
679 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200680 :param sport: Source port
681 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700682 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200683 :param proto: protocol (TCP, UDP, ICMP)
684 :param echo_reply: use echo_reply if protocol is ICMP
Matus Fabianefcd1e92017-08-15 06:59:19 -0700685 :returns: Fragmets
686 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200687 if proto == IP_PROTOS.tcp:
688 p = (IP(src=src_if.remote_ip4, dst=dst) /
689 TCP(sport=sport, dport=dport) /
690 Raw(data))
691 p = p.__class__(str(p))
692 chksum = p['TCP'].chksum
693 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
694 elif proto == IP_PROTOS.udp:
695 proto_header = UDP(sport=sport, dport=dport)
696 elif proto == IP_PROTOS.icmp:
697 if not echo_reply:
698 proto_header = ICMP(id=sport, type='echo-request')
699 else:
700 proto_header = ICMP(id=sport, type='echo-reply')
701 else:
702 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700703 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700704 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200705 if proto == IP_PROTOS.tcp:
706 raw = Raw(data[0:4])
707 else:
708 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700709 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
710 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200711 proto_header /
712 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700713 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200714 if proto == IP_PROTOS.tcp:
715 raw = Raw(data[4:20])
716 else:
717 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700718 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
719 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200720 proto=proto) /
721 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700722 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200723 if proto == IP_PROTOS.tcp:
724 raw = Raw(data[20:])
725 else:
726 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700727 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200728 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700729 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200730 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700731 pkts.append(p)
732 return pkts
733
734 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
735 pref=None, plen=0, frag_size=128):
736 """
737 Create fragmented packet stream
738
739 :param src_if: Source interface
740 :param dst: Destination IPv4 address
741 :param sport: Source TCP port
742 :param dport: Destination TCP port
743 :param data: Payload data
744 :param pref: NAT64 prefix
745 :param plen: NAT64 prefix length
746 :param fragsize: size of fragments
747 :returns: Fragmets
748 """
749 if pref is None:
750 dst_ip6 = ''.join(['64:ff9b::', dst])
751 else:
752 dst_ip6 = self.compose_ip6(dst, pref, plen)
753
754 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
755 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
756 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
757 TCP(sport=sport, dport=dport) /
758 Raw(data))
759
760 return fragment6(p, frag_size)
761
762 def reass_frags_and_verify(self, frags, src, dst):
763 """
764 Reassemble and verify fragmented packet
765
766 :param frags: Captured fragments
767 :param src: Source IPv4 address to verify
768 :param dst: Destination IPv4 address to verify
769
770 :returns: Reassembled IPv4 packet
771 """
Ole Troan7f991832018-12-06 17:35:12 +0100772 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700773 for p in frags:
774 self.assertEqual(p[IP].src, src)
775 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200776 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700777 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100778 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700779 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
780 proto=frags[0][IP].proto)
781 if ip.proto == IP_PROTOS.tcp:
782 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200783 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700784 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200785 p = (ip / UDP(buffer.getvalue()[:8]) /
786 Raw(buffer.getvalue()[8:]))
787 elif ip.proto == IP_PROTOS.icmp:
788 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700789 return p
790
791 def reass_frags_and_verify_ip6(self, frags, src, dst):
792 """
793 Reassemble and verify fragmented packet
794
795 :param frags: Captured fragments
796 :param src: Source IPv6 address to verify
797 :param dst: Destination IPv6 address to verify
798
799 :returns: Reassembled IPv6 packet
800 """
Ole Troan7f991832018-12-06 17:35:12 +0100801 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700802 for p in frags:
803 self.assertEqual(p[IPv6].src, src)
804 self.assertEqual(p[IPv6].dst, dst)
805 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100806 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700807 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
808 nh=frags[0][IPv6ExtHdrFragment].nh)
809 if ip.nh == IP_PROTOS.tcp:
810 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700811 elif ip.nh == IP_PROTOS.udp:
812 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200813 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700814 return p
815
Matus Fabianebdf1902018-05-04 03:57:42 -0700816 def initiate_tcp_session(self, in_if, out_if):
817 """
818 Initiates TCP session
819
820 :param in_if: Inside interface
821 :param out_if: Outside interface
822 """
823 try:
824 # SYN packet in->out
825 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
826 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
827 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
828 flags="S"))
829 in_if.add_stream(p)
830 self.pg_enable_capture(self.pg_interfaces)
831 self.pg_start()
832 capture = out_if.get_capture(1)
833 p = capture[0]
834 self.tcp_port_out = p[TCP].sport
835
836 # SYN + ACK packet out->in
837 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
838 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
839 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
840 flags="SA"))
841 out_if.add_stream(p)
842 self.pg_enable_capture(self.pg_interfaces)
843 self.pg_start()
844 in_if.get_capture(1)
845
846 # ACK packet in->out
847 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
848 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
849 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
850 flags="A"))
851 in_if.add_stream(p)
852 self.pg_enable_capture(self.pg_interfaces)
853 self.pg_start()
854 out_if.get_capture(1)
855
856 except:
857 self.logger.error("TCP 3 way handshake failed")
858 raise
859
Matus Fabianeea28d72017-01-13 04:15:54 -0800860 def verify_ipfix_nat44_ses(self, data):
861 """
862 Verify IPFIX NAT44 session create/delete event
863
864 :param data: Decoded IPFIX data records
865 """
866 nat44_ses_create_num = 0
867 nat44_ses_delete_num = 0
868 self.assertEqual(6, len(data))
869 for record in data:
870 # natEvent
871 self.assertIn(ord(record[230]), [4, 5])
872 if ord(record[230]) == 4:
873 nat44_ses_create_num += 1
874 else:
875 nat44_ses_delete_num += 1
876 # sourceIPv4Address
877 self.assertEqual(self.pg0.remote_ip4n, record[8])
878 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700879 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800880 record[225])
881 # ingressVRFID
882 self.assertEqual(struct.pack("!I", 0), record[234])
883 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
884 if IP_PROTOS.icmp == ord(record[4]):
885 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
886 self.assertEqual(struct.pack("!H", self.icmp_id_out),
887 record[227])
888 elif IP_PROTOS.tcp == ord(record[4]):
889 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])
893 elif IP_PROTOS.udp == ord(record[4]):
894 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
912 self.assertEqual(ord(record[230]), 3)
913 # 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
926 self.assertEqual(ord(record[230]), 13)
927 # 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
942 self.assertEqual(ord(record[230]), 13)
943 # 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
959 self.assertEqual(ord(record[230]), 13)
960 # 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
978 self.assertEqual(ord(record[230]), 13)
979 # 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:
998 self.assertEqual(ord(record[230]), 10)
999 else:
1000 self.assertEqual(ord(record[230]), 11)
1001 # sourceIPv6Address
1002 self.assertEqual(src_addr, record[27])
1003 # postNATSourceIPv4Address
1004 self.assertEqual(self.nat_addr_n, record[225])
1005 # protocolIdentifier
1006 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1007 # 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:
1029 self.assertEqual(ord(record[230]), 6)
1030 else:
1031 self.assertEqual(ord(record[230]), 7)
1032 # 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
1046 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1047 # 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
1078 self.assertEqual(ord(record[230]), 13)
1079 # 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:
1169 data = "A" * 4 + "B" * 16 + "C" * 3
1170 else:
1171 data = "A" * 16 + "B" * 16 + "C" * 3
1172 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:
1250 data = "A" * 4 + "B" * 16 + "C" * 3
1251 else:
1252 data = "A" * 16 + "B" * 16 + "C" * 3
1253 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:
1319 data = "A" * 4 + "B" * 16 + "C" * 3
1320 else:
1321 data = "A" * 16 + "B" * 16 + "C" * 3
1322
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:
1348 data = "A" * 4 + "B" * 16 + "C" * 3
1349 else:
1350 data = "A" * 16 + "B" * 16 + "C" * 3
1351 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:
1424 data = "A" * 4 + "B" * 16 + "C" * 3
1425 else:
1426 data = "A" * 16 + "B" * 16 + "C" * 3
1427 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'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001501 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001502 cls.ipfix_src_port = 4739
1503 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001504 cls.tcp_external_port = 80
Matus Fabian34931eb2019-02-26 09:05:23 -08001505 cls.udp_external_port = 69
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001506
Matus Fabian36ea2d62017-10-24 04:13:49 -07001507 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001508 cls.interfaces = list(cls.pg_interfaces[0:4])
1509
1510 for i in cls.interfaces:
1511 i.admin_up()
1512 i.config_ip4()
1513 i.resolve_arp()
1514
Matus Fabian6fa74c62017-06-05 05:55:48 -07001515 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001516 cls.pg0.configure_ipv4_neighbors()
1517
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001518 cls.pg1.generate_remote_hosts(1)
1519 cls.pg1.configure_ipv4_neighbors()
1520
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001521 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001522 cls.vapi.ip_table_add_del(10, is_add=1)
1523 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001524
1525 cls.pg4._local_ip4 = "172.16.255.1"
1526 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1527 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1528 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001529 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001530 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001531 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001532 cls.pg5.set_table_ip4(10)
1533 cls.pg6._local_ip4 = "172.16.255.1"
1534 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1535 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1536 cls.pg6.set_table_ip4(20)
1537 for i in cls.overlapping_interfaces:
1538 i.config_ip4()
1539 i.admin_up()
1540 i.resolve_arp()
1541
1542 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001543 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001544
Matus Fabian36ea2d62017-10-24 04:13:49 -07001545 cls.pg9.generate_remote_hosts(2)
1546 cls.pg9.config_ip4()
1547 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1548 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1549 ip_addr_n,
1550 24)
1551 cls.pg9.admin_up()
1552 cls.pg9.resolve_arp()
1553 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1554 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1555 cls.pg9.resolve_arp()
1556
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001557 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001558 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001559 raise
1560
Matus Fabiande886752016-12-07 03:38:19 -08001561 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001562 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001563 self.nat44_add_address(self.nat_addr)
1564 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1565 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1566 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001567
1568 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08001569 tcpn = self.statistics.get_counter(
1570 '/err/nat44-in2out-slowpath/TCP packets')
1571 udpn = self.statistics.get_counter(
1572 '/err/nat44-in2out-slowpath/UDP packets')
1573 icmpn = self.statistics.get_counter(
1574 '/err/nat44-in2out-slowpath/ICMP packets')
1575 totaln = self.statistics.get_counter(
1576 '/err/nat44-in2out-slowpath/good in2out packets processed')
1577
Matus Fabiande886752016-12-07 03:38:19 -08001578 pkts = self.create_stream_in(self.pg0, self.pg1)
1579 self.pg0.add_stream(pkts)
1580 self.pg_enable_capture(self.pg_interfaces)
1581 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001582 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001583 self.verify_capture_out(capture)
1584
Matus Fabiana5e73762018-12-14 01:55:16 -08001585 err = self.statistics.get_counter(
1586 '/err/nat44-in2out-slowpath/TCP packets')
1587 self.assertEqual(err - tcpn, 1)
1588 err = self.statistics.get_counter(
1589 '/err/nat44-in2out-slowpath/UDP packets')
1590 self.assertEqual(err - udpn, 1)
1591 err = self.statistics.get_counter(
1592 '/err/nat44-in2out-slowpath/ICMP packets')
1593 self.assertEqual(err - icmpn, 1)
1594 err = self.statistics.get_counter(
1595 '/err/nat44-in2out-slowpath/good in2out packets processed')
1596 self.assertEqual(err - totaln, 3)
1597
Matus Fabiande886752016-12-07 03:38:19 -08001598 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08001599 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1600 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1601 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1602 totaln = self.statistics.get_counter(
1603 '/err/nat44-out2in/good out2in packets processed')
1604
Matus Fabiande886752016-12-07 03:38:19 -08001605 pkts = self.create_stream_out(self.pg1)
1606 self.pg1.add_stream(pkts)
1607 self.pg_enable_capture(self.pg_interfaces)
1608 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001609 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001610 self.verify_capture_in(capture, self.pg0)
1611
Matus Fabiana5e73762018-12-14 01:55:16 -08001612 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1613 self.assertEqual(err - tcpn, 1)
1614 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1615 self.assertEqual(err - udpn, 1)
1616 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1617 self.assertEqual(err - icmpn, 1)
1618 err = self.statistics.get_counter(
1619 '/err/nat44-out2in/good out2in packets processed')
1620 self.assertEqual(err - totaln, 3)
1621
Matus Fabianfd0d5082018-12-18 01:08:51 -08001622 users = self.statistics.get_counter('/nat44/total-users')
1623 self.assertEqual(users[0][0], 1)
1624 sessions = self.statistics.get_counter('/nat44/total-sessions')
1625 self.assertEqual(sessions[0][0], 3)
1626
Juraj Slobodab33f4132017-02-08 23:54:21 -08001627 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001628 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001629
Matus Fabian2ba92e32017-08-21 07:05:03 -07001630 self.nat44_add_address(self.nat_addr)
1631 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1632 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1633 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001634
1635 # Client side - generate traffic
1636 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1637 self.pg0.add_stream(pkts)
1638 self.pg_enable_capture(self.pg_interfaces)
1639 self.pg_start()
1640
1641 # Client side - verify ICMP type 11 packets
1642 capture = self.pg0.get_capture(len(pkts))
1643 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1644
1645 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001646 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001647
Matus Fabian2ba92e32017-08-21 07:05:03 -07001648 self.nat44_add_address(self.nat_addr)
1649 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1650 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1651 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001652
1653 # Client side - create sessions
1654 pkts = self.create_stream_in(self.pg0, self.pg1)
1655 self.pg0.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1657 self.pg_start()
1658
1659 # Server side - generate traffic
1660 capture = self.pg1.get_capture(len(pkts))
1661 self.verify_capture_out(capture)
1662 pkts = self.create_stream_out(self.pg1, ttl=1)
1663 self.pg1.add_stream(pkts)
1664 self.pg_enable_capture(self.pg_interfaces)
1665 self.pg_start()
1666
1667 # Server side - verify ICMP type 11 packets
1668 capture = self.pg1.get_capture(len(pkts))
1669 self.verify_capture_out_with_icmp_errors(capture,
1670 src_ip=self.pg1.local_ip4)
1671
1672 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001673 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001674
Matus Fabian2ba92e32017-08-21 07:05:03 -07001675 self.nat44_add_address(self.nat_addr)
1676 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1677 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1678 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001679
1680 # Client side - generate traffic
1681 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1682 self.pg0.add_stream(pkts)
1683 self.pg_enable_capture(self.pg_interfaces)
1684 self.pg_start()
1685
1686 # Server side - simulate ICMP type 11 response
1687 capture = self.pg1.get_capture(len(pkts))
1688 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001689 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001690 ICMP(type=11) / packet[IP] for packet in capture]
1691 self.pg1.add_stream(pkts)
1692 self.pg_enable_capture(self.pg_interfaces)
1693 self.pg_start()
1694
1695 # Client side - verify ICMP type 11 packets
1696 capture = self.pg0.get_capture(len(pkts))
1697 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1698
1699 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001700 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001701
Matus Fabian2ba92e32017-08-21 07:05:03 -07001702 self.nat44_add_address(self.nat_addr)
1703 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1704 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1705 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001706
1707 # Client side - create sessions
1708 pkts = self.create_stream_in(self.pg0, self.pg1)
1709 self.pg0.add_stream(pkts)
1710 self.pg_enable_capture(self.pg_interfaces)
1711 self.pg_start()
1712
1713 # Server side - generate traffic
1714 capture = self.pg1.get_capture(len(pkts))
1715 self.verify_capture_out(capture)
1716 pkts = self.create_stream_out(self.pg1, ttl=2)
1717 self.pg1.add_stream(pkts)
1718 self.pg_enable_capture(self.pg_interfaces)
1719 self.pg_start()
1720
1721 # Client side - simulate ICMP type 11 response
1722 capture = self.pg0.get_capture(len(pkts))
1723 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1724 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1725 ICMP(type=11) / packet[IP] for packet in capture]
1726 self.pg0.add_stream(pkts)
1727 self.pg_enable_capture(self.pg_interfaces)
1728 self.pg_start()
1729
1730 # Server side - verify ICMP type 11 packets
1731 capture = self.pg1.get_capture(len(pkts))
1732 self.verify_capture_out_with_icmp_errors(capture)
1733
Juraj Sloboda665e4822017-02-16 17:17:19 -08001734 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001735 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001736
Matus Fabian2ba92e32017-08-21 07:05:03 -07001737 self.nat44_add_address(self.nat_addr)
1738 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1739 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1740 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001741
1742 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1743 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1744 ICMP(id=self.icmp_id_out, type='echo-request'))
1745 pkts = [p]
1746 self.pg1.add_stream(pkts)
1747 self.pg_enable_capture(self.pg_interfaces)
1748 self.pg_start()
1749 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001750 packet = capture[0]
1751 try:
1752 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1753 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1754 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1755 self.assertEqual(packet[ICMP].type, 0) # echo reply
1756 except:
1757 self.logger.error(ppp("Unexpected or invalid packet "
1758 "(outside network):", packet))
1759 raise
1760
Juraj Slobodad3677682017-04-14 03:24:45 +02001761 def test_ping_internal_host_from_outside(self):
1762 """ Ping internal host from outside network """
1763
Matus Fabian2ba92e32017-08-21 07:05:03 -07001764 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1765 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1766 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1767 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001768
1769 # out2in
1770 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001771 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001772 ICMP(id=self.icmp_id_out, type='echo-request'))
1773 self.pg1.add_stream(pkt)
1774 self.pg_enable_capture(self.pg_interfaces)
1775 self.pg_start()
1776 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001777 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001778 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1779
1780 # in2out
1781 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1782 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1783 ICMP(id=self.icmp_id_in, type='echo-reply'))
1784 self.pg0.add_stream(pkt)
1785 self.pg_enable_capture(self.pg_interfaces)
1786 self.pg_start()
1787 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001788 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001789 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1790
Matus Fabianc79396e2018-07-23 00:05:22 -07001791 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001792 """ NAT44 forwarding test """
1793
1794 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1795 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1796 is_inside=0)
1797 self.vapi.nat44_forwarding_enable_disable(1)
1798
1799 real_ip = self.pg0.remote_ip4n
1800 alias_ip = self.nat_addr_n
1801 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1802 external_ip=alias_ip)
1803
1804 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001805 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001806
1807 pkts = self.create_stream_out(self.pg1)
1808 self.pg1.add_stream(pkts)
1809 self.pg_enable_capture(self.pg_interfaces)
1810 self.pg_start()
1811 capture = self.pg0.get_capture(len(pkts))
1812 self.verify_capture_in(capture, self.pg0)
1813
1814 pkts = self.create_stream_in(self.pg0, self.pg1)
1815 self.pg0.add_stream(pkts)
1816 self.pg_enable_capture(self.pg_interfaces)
1817 self.pg_start()
1818 capture = self.pg1.get_capture(len(pkts))
1819 self.verify_capture_out(capture, same_port=True)
1820
Matus Fabianc79396e2018-07-23 00:05:22 -07001821 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001822
1823 host0 = self.pg0.remote_hosts[0]
1824 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1825 try:
1826 pkts = self.create_stream_out(self.pg1,
1827 dst_ip=self.pg0.remote_ip4,
1828 use_inside_ports=True)
1829 self.pg1.add_stream(pkts)
1830 self.pg_enable_capture(self.pg_interfaces)
1831 self.pg_start()
1832 capture = self.pg0.get_capture(len(pkts))
1833 self.verify_capture_in(capture, self.pg0)
1834
1835 pkts = self.create_stream_in(self.pg0, self.pg1)
1836 self.pg0.add_stream(pkts)
1837 self.pg_enable_capture(self.pg_interfaces)
1838 self.pg_start()
1839 capture = self.pg1.get_capture(len(pkts))
1840 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1841 same_port=True)
1842 finally:
1843 self.pg0.remote_hosts[0] = host0
1844
1845 finally:
1846 self.vapi.nat44_forwarding_enable_disable(0)
1847 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1848 external_ip=alias_ip,
1849 is_add=0)
1850
Matus Fabiande886752016-12-07 03:38:19 -08001851 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001852 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001853
1854 nat_ip = "10.0.0.10"
1855 self.tcp_port_out = 6303
1856 self.udp_port_out = 6304
1857 self.icmp_id_out = 6305
1858
Matus Fabian2ba92e32017-08-21 07:05:03 -07001859 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1860 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1861 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1862 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001863 sm = self.vapi.nat44_static_mapping_dump()
1864 self.assertEqual(len(sm), 1)
1865 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001866 self.assertEqual(sm[0].protocol, 0)
1867 self.assertEqual(sm[0].local_port, 0)
1868 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001869
1870 # in2out
1871 pkts = self.create_stream_in(self.pg0, self.pg1)
1872 self.pg0.add_stream(pkts)
1873 self.pg_enable_capture(self.pg_interfaces)
1874 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001875 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001876 self.verify_capture_out(capture, nat_ip, True)
1877
1878 # out2in
1879 pkts = self.create_stream_out(self.pg1, nat_ip)
1880 self.pg1.add_stream(pkts)
1881 self.pg_enable_capture(self.pg_interfaces)
1882 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001883 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001884 self.verify_capture_in(capture, self.pg0)
1885
1886 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001887 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001888
1889 nat_ip = "10.0.0.20"
1890 self.tcp_port_out = 6303
1891 self.udp_port_out = 6304
1892 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001893 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001894
Matus Fabian5f224992018-01-25 21:59:16 -08001895 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001896 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1897 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1898 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001899 sm = self.vapi.nat44_static_mapping_dump()
1900 self.assertEqual(len(sm), 1)
1901 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001902
1903 # out2in
1904 pkts = self.create_stream_out(self.pg1, nat_ip)
1905 self.pg1.add_stream(pkts)
1906 self.pg_enable_capture(self.pg_interfaces)
1907 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001908 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001909 self.verify_capture_in(capture, self.pg0)
1910
1911 # in2out
1912 pkts = self.create_stream_in(self.pg0, self.pg1)
1913 self.pg0.add_stream(pkts)
1914 self.pg_enable_capture(self.pg_interfaces)
1915 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001916 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001917 self.verify_capture_out(capture, nat_ip, True)
1918
1919 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001920 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001921
1922 self.tcp_port_out = 3606
1923 self.udp_port_out = 3607
1924 self.icmp_id_out = 3608
1925
Matus Fabian2ba92e32017-08-21 07:05:03 -07001926 self.nat44_add_address(self.nat_addr)
1927 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1928 self.tcp_port_in, self.tcp_port_out,
1929 proto=IP_PROTOS.tcp)
1930 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1931 self.udp_port_in, self.udp_port_out,
1932 proto=IP_PROTOS.udp)
1933 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1934 self.icmp_id_in, self.icmp_id_out,
1935 proto=IP_PROTOS.icmp)
1936 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1937 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1938 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001939
1940 # in2out
1941 pkts = self.create_stream_in(self.pg0, self.pg1)
1942 self.pg0.add_stream(pkts)
1943 self.pg_enable_capture(self.pg_interfaces)
1944 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001945 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001946 self.verify_capture_out(capture)
1947
1948 # out2in
1949 pkts = self.create_stream_out(self.pg1)
1950 self.pg1.add_stream(pkts)
1951 self.pg_enable_capture(self.pg_interfaces)
1952 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001953 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001954 self.verify_capture_in(capture, self.pg0)
1955
1956 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001957 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001958
1959 self.tcp_port_out = 30606
1960 self.udp_port_out = 30607
1961 self.icmp_id_out = 30608
1962
Matus Fabian2ba92e32017-08-21 07:05:03 -07001963 self.nat44_add_address(self.nat_addr)
1964 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1965 self.tcp_port_in, self.tcp_port_out,
1966 proto=IP_PROTOS.tcp)
1967 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1968 self.udp_port_in, self.udp_port_out,
1969 proto=IP_PROTOS.udp)
1970 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1971 self.icmp_id_in, self.icmp_id_out,
1972 proto=IP_PROTOS.icmp)
1973 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1974 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1975 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001976
1977 # out2in
1978 pkts = self.create_stream_out(self.pg1)
1979 self.pg1.add_stream(pkts)
1980 self.pg_enable_capture(self.pg_interfaces)
1981 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001982 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001983 self.verify_capture_in(capture, self.pg0)
1984
1985 # in2out
1986 pkts = self.create_stream_in(self.pg0, self.pg1)
1987 self.pg0.add_stream(pkts)
1988 self.pg_enable_capture(self.pg_interfaces)
1989 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001990 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001991 self.verify_capture_out(capture)
1992
1993 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001994 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001995
1996 nat_ip1 = "10.0.0.30"
1997 nat_ip2 = "10.0.0.40"
1998 self.tcp_port_out = 6303
1999 self.udp_port_out = 6304
2000 self.icmp_id_out = 6305
2001
Matus Fabian2ba92e32017-08-21 07:05:03 -07002002 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2003 vrf_id=10)
2004 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2005 vrf_id=10)
2006 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2007 is_inside=0)
2008 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2009 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08002010
Matus Fabian2ba92e32017-08-21 07:05:03 -07002011 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002012 pkts = self.create_stream_in(self.pg4, self.pg3)
2013 self.pg4.add_stream(pkts)
2014 self.pg_enable_capture(self.pg_interfaces)
2015 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002016 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002017 self.verify_capture_out(capture, nat_ip1, True)
2018
Matus Fabian2ba92e32017-08-21 07:05:03 -07002019 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002020 # are dropped)
2021 pkts = self.create_stream_in(self.pg0, self.pg3)
2022 self.pg0.add_stream(pkts)
2023 self.pg_enable_capture(self.pg_interfaces)
2024 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002025 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002026
Matus Fabianb793d092018-01-31 05:50:21 -08002027 def test_dynamic_to_static(self):
2028 """ Switch from dynamic translation to 1:1NAT """
2029 nat_ip = "10.0.0.10"
2030 self.tcp_port_out = 6303
2031 self.udp_port_out = 6304
2032 self.icmp_id_out = 6305
2033
2034 self.nat44_add_address(self.nat_addr)
2035 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2036 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2037 is_inside=0)
2038
2039 # dynamic
2040 pkts = self.create_stream_in(self.pg0, self.pg1)
2041 self.pg0.add_stream(pkts)
2042 self.pg_enable_capture(self.pg_interfaces)
2043 self.pg_start()
2044 capture = self.pg1.get_capture(len(pkts))
2045 self.verify_capture_out(capture)
2046
2047 # 1:1NAT
2048 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2049 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2050 self.assertEqual(len(sessions), 0)
2051 pkts = self.create_stream_in(self.pg0, self.pg1)
2052 self.pg0.add_stream(pkts)
2053 self.pg_enable_capture(self.pg_interfaces)
2054 self.pg_start()
2055 capture = self.pg1.get_capture(len(pkts))
2056 self.verify_capture_out(capture, nat_ip, True)
2057
Matus Fabianab7a8052017-11-28 04:29:41 -08002058 def test_identity_nat(self):
2059 """ Identity NAT """
2060
2061 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
2062 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2063 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2064 is_inside=0)
2065
2066 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2067 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2068 TCP(sport=12345, dport=56789))
2069 self.pg1.add_stream(p)
2070 self.pg_enable_capture(self.pg_interfaces)
2071 self.pg_start()
2072 capture = self.pg0.get_capture(1)
2073 p = capture[0]
2074 try:
2075 ip = p[IP]
2076 tcp = p[TCP]
2077 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2078 self.assertEqual(ip.src, self.pg1.remote_ip4)
2079 self.assertEqual(tcp.dport, 56789)
2080 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002081 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002082 except:
2083 self.logger.error(ppp("Unexpected or invalid packet:", p))
2084 raise
2085
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002086 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2087 self.assertEqual(len(sessions), 0)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002088 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2089 vrf_id=1)
2090 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2091 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002092
Matus Fabiande886752016-12-07 03:38:19 -08002093 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002094 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002095
Matus Fabian2ba92e32017-08-21 07:05:03 -07002096 self.nat44_add_address(self.nat_addr)
2097 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2098 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2099 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2100 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002101
Matus Fabian2ba92e32017-08-21 07:05:03 -07002102 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002103 pkts = self.create_stream_in(self.pg0, self.pg1)
2104 self.pg0.add_stream(pkts)
2105 self.pg_enable_capture(self.pg_interfaces)
2106 self.pg_start()
2107 capture = self.pg1.get_capture(len(pkts))
2108 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2109
Matus Fabian2ba92e32017-08-21 07:05:03 -07002110 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002111 pkts = self.create_stream_in(self.pg0, self.pg2)
2112 self.pg0.add_stream(pkts)
2113 self.pg_enable_capture(self.pg_interfaces)
2114 self.pg_start()
2115 capture = self.pg2.get_capture(len(pkts))
2116 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2117
Matus Fabiande886752016-12-07 03:38:19 -08002118 # in2out 1st interface
2119 pkts = self.create_stream_in(self.pg0, self.pg3)
2120 self.pg0.add_stream(pkts)
2121 self.pg_enable_capture(self.pg_interfaces)
2122 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002123 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002124 self.verify_capture_out(capture)
2125
2126 # out2in 1st interface
2127 pkts = self.create_stream_out(self.pg3)
2128 self.pg3.add_stream(pkts)
2129 self.pg_enable_capture(self.pg_interfaces)
2130 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002131 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002132 self.verify_capture_in(capture, self.pg0)
2133
2134 # in2out 2nd interface
2135 pkts = self.create_stream_in(self.pg1, self.pg3)
2136 self.pg1.add_stream(pkts)
2137 self.pg_enable_capture(self.pg_interfaces)
2138 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002139 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002140 self.verify_capture_out(capture)
2141
2142 # out2in 2nd interface
2143 pkts = self.create_stream_out(self.pg3)
2144 self.pg3.add_stream(pkts)
2145 self.pg_enable_capture(self.pg_interfaces)
2146 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002147 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002148 self.verify_capture_in(capture, self.pg1)
2149
Matus Fabiande886752016-12-07 03:38:19 -08002150 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002151 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002152
Matus Fabian675a69c2017-01-18 01:46:01 -08002153 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002154 self.nat44_add_address(self.nat_addr)
2155 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2156 is_inside=0)
2157 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2158 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2159 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2160 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2161 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002162
Matus Fabian2ba92e32017-08-21 07:05:03 -07002163 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002164 pkts = self.create_stream_in(self.pg4, self.pg5)
2165 self.pg4.add_stream(pkts)
2166 self.pg_enable_capture(self.pg_interfaces)
2167 self.pg_start()
2168 capture = self.pg5.get_capture(len(pkts))
2169 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2170
Matus Fabian2ba92e32017-08-21 07:05:03 -07002171 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002172 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2173 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2174 TCP(sport=1234, dport=5678))
2175 self.pg4.add_stream(p)
2176 self.pg_enable_capture(self.pg_interfaces)
2177 self.pg_start()
2178 capture = self.pg6.get_capture(1)
2179 p = capture[0]
2180 try:
2181 ip = p[IP]
2182 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002183 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002184 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2185 self.assertNotEqual(tcp.sport, 1234)
2186 self.assertEqual(tcp.dport, 5678)
2187 except:
2188 self.logger.error(ppp("Unexpected or invalid packet:", p))
2189 raise
Matus Fabiande886752016-12-07 03:38:19 -08002190
2191 # in2out 1st interface
2192 pkts = self.create_stream_in(self.pg4, self.pg3)
2193 self.pg4.add_stream(pkts)
2194 self.pg_enable_capture(self.pg_interfaces)
2195 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002196 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002197 self.verify_capture_out(capture)
2198
2199 # out2in 1st interface
2200 pkts = self.create_stream_out(self.pg3)
2201 self.pg3.add_stream(pkts)
2202 self.pg_enable_capture(self.pg_interfaces)
2203 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002204 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002205 self.verify_capture_in(capture, self.pg4)
2206
2207 # in2out 2nd interface
2208 pkts = self.create_stream_in(self.pg5, self.pg3)
2209 self.pg5.add_stream(pkts)
2210 self.pg_enable_capture(self.pg_interfaces)
2211 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002212 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002213 self.verify_capture_out(capture)
2214
2215 # out2in 2nd interface
2216 pkts = self.create_stream_out(self.pg3)
2217 self.pg3.add_stream(pkts)
2218 self.pg_enable_capture(self.pg_interfaces)
2219 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002220 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002221 self.verify_capture_in(capture, self.pg5)
2222
magalik23caa882017-02-08 23:25:45 -08002223 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002224 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002225 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002226 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002227 self.assertEqual(len(sessions), 3)
2228 for session in sessions:
2229 self.assertFalse(session.is_static)
2230 self.assertEqual(session.inside_ip_address[0:4],
2231 self.pg5.remote_ip4n)
2232 self.assertEqual(session.outside_ip_address,
2233 addresses[0].ip_address)
2234 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2235 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2236 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2237 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2238 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2239 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2240 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2241 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2242 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2243
Matus Fabiande886752016-12-07 03:38:19 -08002244 # in2out 3rd interface
2245 pkts = self.create_stream_in(self.pg6, self.pg3)
2246 self.pg6.add_stream(pkts)
2247 self.pg_enable_capture(self.pg_interfaces)
2248 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002249 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002250 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002251
2252 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002253 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002254 self.pg3.add_stream(pkts)
2255 self.pg_enable_capture(self.pg_interfaces)
2256 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002257 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002258 self.verify_capture_in(capture, self.pg6)
2259
magalik23caa882017-02-08 23:25:45 -08002260 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002261 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002262 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002263 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002264 self.assertEqual(len(addresses), 1)
2265 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002266 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2267 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002268 for session in sessions:
2269 self.assertEqual(user.ip_address, session.inside_ip_address)
2270 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2271 self.assertTrue(session.protocol in
2272 [IP_PROTOS.tcp, IP_PROTOS.udp,
2273 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002274 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002275
2276 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002277 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002278 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002279 for session in sessions:
2280 self.assertFalse(session.is_static)
2281 self.assertEqual(session.inside_ip_address[0:4],
2282 self.pg4.remote_ip4n)
2283 self.assertEqual(session.outside_ip_address,
2284 addresses[0].ip_address)
2285
2286 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002287 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002288 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002289 for session in sessions:
2290 self.assertTrue(session.is_static)
2291 self.assertEqual(session.inside_ip_address[0:4],
2292 self.pg6.remote_ip4n)
Matus Fabian34931eb2019-02-26 09:05:23 -08002293 self.assertEqual(session.outside_ip_address,
2294 socket.inet_pton(socket.AF_INET, static_nat_ip))
magalik23caa882017-02-08 23:25:45 -08002295 self.assertTrue(session.inside_port in
2296 [self.tcp_port_in, self.udp_port_in,
2297 self.icmp_id_in])
2298
Matus Fabianf78a70d2016-12-12 04:30:39 -08002299 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002300 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002301
2302 host = self.pg0.remote_hosts[0]
2303 server = self.pg0.remote_hosts[1]
2304 host_in_port = 1234
2305 host_out_port = 0
2306 server_in_port = 5678
2307 server_out_port = 8765
2308
Matus Fabian2ba92e32017-08-21 07:05:03 -07002309 self.nat44_add_address(self.nat_addr)
2310 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2311 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2312 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002313 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002314 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2315 server_in_port, server_out_port,
2316 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002317
2318 # send packet from host to server
2319 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002320 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002321 TCP(sport=host_in_port, dport=server_out_port))
2322 self.pg0.add_stream(p)
2323 self.pg_enable_capture(self.pg_interfaces)
2324 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002325 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002326 p = capture[0]
2327 try:
2328 ip = p[IP]
2329 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002330 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002331 self.assertEqual(ip.dst, server.ip4)
2332 self.assertNotEqual(tcp.sport, host_in_port)
2333 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002334 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002335 host_out_port = tcp.sport
2336 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002337 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002338 raise
2339
2340 # send reply from server to host
2341 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002342 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002343 TCP(sport=server_in_port, dport=host_out_port))
2344 self.pg0.add_stream(p)
2345 self.pg_enable_capture(self.pg_interfaces)
2346 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002347 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002348 p = capture[0]
2349 try:
2350 ip = p[IP]
2351 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002352 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002353 self.assertEqual(ip.dst, host.ip4)
2354 self.assertEqual(tcp.sport, server_out_port)
2355 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002356 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002357 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002358 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002359 raise
2360
Matus Fabian6fa74c62017-06-05 05:55:48 -07002361 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002362 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002363
2364 server1_nat_ip = "10.0.0.10"
2365 server2_nat_ip = "10.0.0.11"
2366 host = self.pg0.remote_hosts[0]
2367 server1 = self.pg0.remote_hosts[1]
2368 server2 = self.pg0.remote_hosts[2]
2369 server_tcp_port = 22
2370 server_udp_port = 20
2371
Matus Fabian2ba92e32017-08-21 07:05:03 -07002372 self.nat44_add_address(self.nat_addr)
2373 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2374 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2375 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002376
2377 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002378 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2379 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002380
2381 # host to server1
2382 pkts = []
2383 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2384 IP(src=host.ip4, dst=server1_nat_ip) /
2385 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2386 pkts.append(p)
2387 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2388 IP(src=host.ip4, dst=server1_nat_ip) /
2389 UDP(sport=self.udp_port_in, dport=server_udp_port))
2390 pkts.append(p)
2391 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2392 IP(src=host.ip4, dst=server1_nat_ip) /
2393 ICMP(id=self.icmp_id_in, type='echo-request'))
2394 pkts.append(p)
2395 self.pg0.add_stream(pkts)
2396 self.pg_enable_capture(self.pg_interfaces)
2397 self.pg_start()
2398 capture = self.pg0.get_capture(len(pkts))
2399 for packet in capture:
2400 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002401 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002402 self.assertEqual(packet[IP].dst, server1.ip4)
2403 if packet.haslayer(TCP):
2404 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2405 self.assertEqual(packet[TCP].dport, server_tcp_port)
2406 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002407 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002408 elif packet.haslayer(UDP):
2409 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2410 self.assertEqual(packet[UDP].dport, server_udp_port)
2411 self.udp_port_out = packet[UDP].sport
2412 else:
2413 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2414 self.icmp_id_out = packet[ICMP].id
2415 except:
2416 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2417 raise
2418
2419 # server1 to host
2420 pkts = []
2421 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002422 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002423 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2424 pkts.append(p)
2425 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002426 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002427 UDP(sport=server_udp_port, dport=self.udp_port_out))
2428 pkts.append(p)
2429 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002430 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002431 ICMP(id=self.icmp_id_out, type='echo-reply'))
2432 pkts.append(p)
2433 self.pg0.add_stream(pkts)
2434 self.pg_enable_capture(self.pg_interfaces)
2435 self.pg_start()
2436 capture = self.pg0.get_capture(len(pkts))
2437 for packet in capture:
2438 try:
2439 self.assertEqual(packet[IP].src, server1_nat_ip)
2440 self.assertEqual(packet[IP].dst, host.ip4)
2441 if packet.haslayer(TCP):
2442 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2443 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002444 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002445 elif packet.haslayer(UDP):
2446 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2447 self.assertEqual(packet[UDP].sport, server_udp_port)
2448 else:
2449 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2450 except:
2451 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2452 raise
2453
2454 # server2 to server1
2455 pkts = []
2456 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2457 IP(src=server2.ip4, dst=server1_nat_ip) /
2458 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2459 pkts.append(p)
2460 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2461 IP(src=server2.ip4, dst=server1_nat_ip) /
2462 UDP(sport=self.udp_port_in, dport=server_udp_port))
2463 pkts.append(p)
2464 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2465 IP(src=server2.ip4, dst=server1_nat_ip) /
2466 ICMP(id=self.icmp_id_in, type='echo-request'))
2467 pkts.append(p)
2468 self.pg0.add_stream(pkts)
2469 self.pg_enable_capture(self.pg_interfaces)
2470 self.pg_start()
2471 capture = self.pg0.get_capture(len(pkts))
2472 for packet in capture:
2473 try:
2474 self.assertEqual(packet[IP].src, server2_nat_ip)
2475 self.assertEqual(packet[IP].dst, server1.ip4)
2476 if packet.haslayer(TCP):
2477 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2478 self.assertEqual(packet[TCP].dport, server_tcp_port)
2479 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002480 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002481 elif packet.haslayer(UDP):
2482 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2483 self.assertEqual(packet[UDP].dport, server_udp_port)
2484 self.udp_port_out = packet[UDP].sport
2485 else:
2486 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2487 self.icmp_id_out = packet[ICMP].id
2488 except:
2489 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2490 raise
2491
2492 # server1 to server2
2493 pkts = []
2494 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2495 IP(src=server1.ip4, dst=server2_nat_ip) /
2496 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2497 pkts.append(p)
2498 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2499 IP(src=server1.ip4, dst=server2_nat_ip) /
2500 UDP(sport=server_udp_port, dport=self.udp_port_out))
2501 pkts.append(p)
2502 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2503 IP(src=server1.ip4, dst=server2_nat_ip) /
2504 ICMP(id=self.icmp_id_out, type='echo-reply'))
2505 pkts.append(p)
2506 self.pg0.add_stream(pkts)
2507 self.pg_enable_capture(self.pg_interfaces)
2508 self.pg_start()
2509 capture = self.pg0.get_capture(len(pkts))
2510 for packet in capture:
2511 try:
2512 self.assertEqual(packet[IP].src, server1_nat_ip)
2513 self.assertEqual(packet[IP].dst, server2.ip4)
2514 if packet.haslayer(TCP):
2515 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2516 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002517 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002518 elif packet.haslayer(UDP):
2519 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2520 self.assertEqual(packet[UDP].sport, server_udp_port)
2521 else:
2522 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2523 except:
2524 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2525 raise
2526
Matus Fabian9902fcd2016-12-21 23:58:46 -08002527 def test_max_translations_per_user(self):
2528 """ MAX translations per user - recycle the least recently used """
2529
Matus Fabian2ba92e32017-08-21 07:05:03 -07002530 self.nat44_add_address(self.nat_addr)
2531 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2532 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2533 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002534
2535 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002536 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002537
2538 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002539 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002540 pkts = []
2541 for port in range(0, pkts_num):
2542 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2543 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2544 TCP(sport=1025 + port))
2545 pkts.append(p)
2546 self.pg0.add_stream(pkts)
2547 self.pg_enable_capture(self.pg_interfaces)
2548 self.pg_start()
2549
2550 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002551 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002552
Matus Fabian132dc492018-05-09 04:51:03 -07002553 users = self.vapi.nat44_user_dump()
2554 for user in users:
2555 if user.ip_address == self.pg0.remote_ip4n:
2556 self.assertEqual(user.nsessions,
2557 nat44_config.max_translations_per_user)
2558 self.assertEqual(user.nstaticsessions, 0)
2559
2560 tcp_port = 22
2561 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2562 tcp_port, tcp_port,
2563 proto=IP_PROTOS.tcp)
2564 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2565 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2566 TCP(sport=tcp_port))
2567 self.pg0.add_stream(p)
2568 self.pg_enable_capture(self.pg_interfaces)
2569 self.pg_start()
2570 self.pg1.get_capture(1)
2571 users = self.vapi.nat44_user_dump()
2572 for user in users:
2573 if user.ip_address == self.pg0.remote_ip4n:
2574 self.assertEqual(user.nsessions,
2575 nat44_config.max_translations_per_user - 1)
2576 self.assertEqual(user.nstaticsessions, 1)
2577
Matus Fabian8bf68e82017-01-12 04:24:35 -08002578 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002579 """ Acquire NAT44 addresses from interface """
2580 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002581
2582 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002583 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002584 self.assertEqual(0, len(adresses))
2585
2586 # configure interface address and check NAT address pool
2587 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002588 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002589 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002590 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002591
2592 # remove interface address and check NAT address pool
2593 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002594 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002595 self.assertEqual(0, len(adresses))
2596
Matus Fabian36532bd2017-01-23 23:42:28 -08002597 def test_interface_addr_static_mapping(self):
2598 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002599 tag = "testTAG"
2600
Matus Fabian2ba92e32017-08-21 07:05:03 -07002601 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2602 self.nat44_add_static_mapping(
2603 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002604 external_sw_if_index=self.pg7.sw_if_index,
2605 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002606
Matus Fabiane22e5462017-02-14 23:33:43 -08002607 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002608 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002609 self.assertEqual(1, len(static_mappings))
2610 self.assertEqual(self.pg7.sw_if_index,
2611 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002612 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002613
2614 # configure interface address and check static mappings
2615 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002616 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002617 self.assertEqual(2, len(static_mappings))
2618 resolved = False
2619 for sm in static_mappings:
2620 if sm.external_sw_if_index == 0xFFFFFFFF:
2621 self.assertEqual(sm.external_ip_address[0:4],
2622 self.pg7.local_ip4n)
2623 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2624 resolved = True
2625 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002626
2627 # remove interface address and check static mappings
2628 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002629 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002630 self.assertEqual(1, len(static_mappings))
2631 self.assertEqual(self.pg7.sw_if_index,
2632 static_mappings[0].external_sw_if_index)
2633 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2634
2635 # configure interface address again and check static mappings
2636 self.pg7.config_ip4()
2637 static_mappings = self.vapi.nat44_static_mapping_dump()
2638 self.assertEqual(2, len(static_mappings))
2639 resolved = False
2640 for sm in static_mappings:
2641 if sm.external_sw_if_index == 0xFFFFFFFF:
2642 self.assertEqual(sm.external_ip_address[0:4],
2643 self.pg7.local_ip4n)
2644 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2645 resolved = True
2646 self.assertTrue(resolved)
2647
2648 # remove static mapping
2649 self.nat44_add_static_mapping(
2650 '1.2.3.4',
2651 external_sw_if_index=self.pg7.sw_if_index,
2652 tag=tag,
2653 is_add=0)
2654 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002655 self.assertEqual(0, len(static_mappings))
2656
Matus Fabianab7a8052017-11-28 04:29:41 -08002657 def test_interface_addr_identity_nat(self):
2658 """ Identity NAT with addresses from interface """
2659
2660 port = 53053
2661 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2662 self.vapi.nat44_add_del_identity_mapping(
2663 sw_if_index=self.pg7.sw_if_index,
2664 port=port,
2665 protocol=IP_PROTOS.tcp,
2666 addr_only=0)
2667
2668 # identity mappings with external interface
2669 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2670 self.assertEqual(1, len(identity_mappings))
2671 self.assertEqual(self.pg7.sw_if_index,
2672 identity_mappings[0].sw_if_index)
2673
2674 # configure interface address and check identity mappings
2675 self.pg7.config_ip4()
2676 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002677 resolved = False
2678 self.assertEqual(2, len(identity_mappings))
2679 for sm in identity_mappings:
2680 if sm.sw_if_index == 0xFFFFFFFF:
2681 self.assertEqual(identity_mappings[0].ip_address,
2682 self.pg7.local_ip4n)
2683 self.assertEqual(port, identity_mappings[0].port)
2684 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2685 resolved = True
2686 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002687
2688 # remove interface address and check identity mappings
2689 self.pg7.unconfig_ip4()
2690 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002691 self.assertEqual(1, len(identity_mappings))
2692 self.assertEqual(self.pg7.sw_if_index,
2693 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002694
Matus Fabianeea28d72017-01-13 04:15:54 -08002695 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002696 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002697 self.ipfix_domain_id = 10
2698 self.ipfix_src_port = 20202
2699 colector_port = 30303
2700 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002701 self.nat44_add_address(self.nat_addr)
2702 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2703 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2704 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002705 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2706 src_address=self.pg3.local_ip4n,
2707 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002708 template_interval=10,
2709 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002710 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2711 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002712
2713 pkts = self.create_stream_in(self.pg0, self.pg1)
2714 self.pg0.add_stream(pkts)
2715 self.pg_enable_capture(self.pg_interfaces)
2716 self.pg_start()
2717 capture = self.pg1.get_capture(len(pkts))
2718 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002719 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002720 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002721 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002722 ipfix = IPFIXDecoder()
2723 # first load template
2724 for p in capture:
2725 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002726 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2727 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2728 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2729 self.assertEqual(p[UDP].dport, colector_port)
2730 self.assertEqual(p[IPFIX].observationDomainID,
2731 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002732 if p.haslayer(Template):
2733 ipfix.add_template(p.getlayer(Template))
2734 # verify events in data set
2735 for p in capture:
2736 if p.haslayer(Data):
2737 data = ipfix.decode_data_set(p.getlayer(Set))
2738 self.verify_ipfix_nat44_ses(data)
2739
2740 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002741 """ IPFIX logging NAT addresses exhausted """
2742 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2743 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2744 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002745 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2746 src_address=self.pg3.local_ip4n,
2747 path_mtu=512,
2748 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002749 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2750 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002751
2752 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2753 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2754 TCP(sport=3025))
2755 self.pg0.add_stream(p)
2756 self.pg_enable_capture(self.pg_interfaces)
2757 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002758 self.pg1.assert_nothing_captured()
2759 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002760 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002761 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002762 ipfix = IPFIXDecoder()
2763 # first load template
2764 for p in capture:
2765 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002766 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2767 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2768 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2769 self.assertEqual(p[UDP].dport, 4739)
2770 self.assertEqual(p[IPFIX].observationDomainID,
2771 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002772 if p.haslayer(Template):
2773 ipfix.add_template(p.getlayer(Template))
2774 # verify events in data set
2775 for p in capture:
2776 if p.haslayer(Data):
2777 data = ipfix.decode_data_set(p.getlayer(Set))
2778 self.verify_ipfix_addr_exhausted(data)
2779
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002780 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002781 def test_ipfix_max_sessions(self):
2782 """ IPFIX logging maximum session entries exceeded """
2783 self.nat44_add_address(self.nat_addr)
2784 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2785 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2786 is_inside=0)
2787
2788 nat44_config = self.vapi.nat_show_config()
2789 max_sessions = 10 * nat44_config.translation_buckets
2790
2791 pkts = []
2792 for i in range(0, max_sessions):
2793 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2794 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2795 IP(src=src, dst=self.pg1.remote_ip4) /
2796 TCP(sport=1025))
2797 pkts.append(p)
2798 self.pg0.add_stream(pkts)
2799 self.pg_enable_capture(self.pg_interfaces)
2800 self.pg_start()
2801
2802 self.pg1.get_capture(max_sessions)
2803 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2804 src_address=self.pg3.local_ip4n,
2805 path_mtu=512,
2806 template_interval=10)
2807 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2808 src_port=self.ipfix_src_port)
2809
2810 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2811 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2812 TCP(sport=1025))
2813 self.pg0.add_stream(p)
2814 self.pg_enable_capture(self.pg_interfaces)
2815 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002816 self.pg1.assert_nothing_captured()
2817 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002818 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2819 capture = self.pg3.get_capture(9)
2820 ipfix = IPFIXDecoder()
2821 # first load template
2822 for p in capture:
2823 self.assertTrue(p.haslayer(IPFIX))
2824 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2825 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2826 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2827 self.assertEqual(p[UDP].dport, 4739)
2828 self.assertEqual(p[IPFIX].observationDomainID,
2829 self.ipfix_domain_id)
2830 if p.haslayer(Template):
2831 ipfix.add_template(p.getlayer(Template))
2832 # verify events in data set
2833 for p in capture:
2834 if p.haslayer(Data):
2835 data = ipfix.decode_data_set(p.getlayer(Set))
2836 self.verify_ipfix_max_sessions(data, max_sessions)
2837
Matus Fabianad1f3e12018-11-28 21:26:34 -08002838 def test_syslog_apmap(self):
2839 """ Test syslog address and port mapping creation and deletion """
2840 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
2841 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
2842 self.nat44_add_address(self.nat_addr)
2843 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2844 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2845 is_inside=0)
2846
2847 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2848 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2849 TCP(sport=self.tcp_port_in, dport=20))
2850 self.pg0.add_stream(p)
2851 self.pg_enable_capture(self.pg_interfaces)
2852 self.pg_start()
2853 capture = self.pg1.get_capture(1)
2854 self.tcp_port_out = capture[0][TCP].sport
2855 capture = self.pg3.get_capture(1)
2856 self.verify_syslog_apmap(capture[0][Raw].load)
2857
2858 self.pg_enable_capture(self.pg_interfaces)
2859 self.pg_start()
2860 self.nat44_add_address(self.nat_addr, is_add=0)
2861 capture = self.pg3.get_capture(1)
2862 self.verify_syslog_apmap(capture[0][Raw].load, False)
2863
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002864 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002865 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002866 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002867 self.nat44_add_address(self.nat_addr)
2868 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2869 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2870 is_inside=0)
2871 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002872
Matus Fabian2ba92e32017-08-21 07:05:03 -07002873 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002874 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002875 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002876 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2877 self.pg1.add_stream(p)
2878 self.pg_enable_capture(self.pg_interfaces)
2879 self.pg_start()
2880 capture = self.pg1.get_capture(1)
2881 self.assertTrue(capture[0].haslayer(ARP))
2882 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2883
2884 # 1:1 NAT address
2885 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2886 ARP(op=ARP.who_has, pdst=static_addr,
2887 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2888 self.pg1.add_stream(p)
2889 self.pg_enable_capture(self.pg_interfaces)
2890 self.pg_start()
2891 capture = self.pg1.get_capture(1)
2892 self.assertTrue(capture[0].haslayer(ARP))
2893 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2894
Matus Fabian2ba92e32017-08-21 07:05:03 -07002895 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002896 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002897 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002898 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2899 self.pg2.add_stream(p)
2900 self.pg_enable_capture(self.pg_interfaces)
2901 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002902 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002903
2904 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002905 self.nat44_add_address(self.nat_addr, is_add=0)
2906 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2907 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002908
2909 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002910 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002911 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2912 self.pg1.add_stream(p)
2913 self.pg_enable_capture(self.pg_interfaces)
2914 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002915 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002916
2917 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2918 ARP(op=ARP.who_has, pdst=static_addr,
2919 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2920 self.pg1.add_stream(p)
2921 self.pg_enable_capture(self.pg_interfaces)
2922 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002923 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002924
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002925 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002926 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002927
2928 vrf_id1 = 1
2929 vrf_id2 = 2
2930 nat_ip1 = "10.0.0.10"
2931 nat_ip2 = "10.0.0.11"
2932
2933 self.pg0.unconfig_ip4()
2934 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002935 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2936 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002937 self.pg0.set_table_ip4(vrf_id1)
2938 self.pg1.set_table_ip4(vrf_id2)
2939 self.pg0.config_ip4()
2940 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002941 self.pg0.resolve_arp()
2942 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002943
Matus Fabian2ba92e32017-08-21 07:05:03 -07002944 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2945 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2946 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2947 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2948 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2949 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002950
Matus Fabian8008d7c2018-07-09 01:34:20 -07002951 try:
2952 # first VRF
2953 pkts = self.create_stream_in(self.pg0, self.pg2)
2954 self.pg0.add_stream(pkts)
2955 self.pg_enable_capture(self.pg_interfaces)
2956 self.pg_start()
2957 capture = self.pg2.get_capture(len(pkts))
2958 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002959
Matus Fabian8008d7c2018-07-09 01:34:20 -07002960 # second VRF
2961 pkts = self.create_stream_in(self.pg1, self.pg2)
2962 self.pg1.add_stream(pkts)
2963 self.pg_enable_capture(self.pg_interfaces)
2964 self.pg_start()
2965 capture = self.pg2.get_capture(len(pkts))
2966 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002967
Matus Fabian8008d7c2018-07-09 01:34:20 -07002968 finally:
2969 self.pg0.unconfig_ip4()
2970 self.pg1.unconfig_ip4()
2971 self.pg0.set_table_ip4(0)
2972 self.pg1.set_table_ip4(0)
2973 self.pg0.config_ip4()
2974 self.pg1.config_ip4()
2975 self.pg0.resolve_arp()
2976 self.pg1.resolve_arp()
2977 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2978 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002979
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002980 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002981 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002982
2983 nat_ip1 = "10.0.0.10"
2984 nat_ip2 = "10.0.0.11"
2985
Matus Fabian2ba92e32017-08-21 07:05:03 -07002986 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002987 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002988 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2989 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2990 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2991 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002992
2993 # first VRF
2994 pkts = self.create_stream_in(self.pg0, self.pg2)
2995 self.pg0.add_stream(pkts)
2996 self.pg_enable_capture(self.pg_interfaces)
2997 self.pg_start()
2998 capture = self.pg2.get_capture(len(pkts))
2999 self.verify_capture_out(capture, nat_ip1)
3000
3001 # second VRF
3002 pkts = self.create_stream_in(self.pg1, self.pg2)
3003 self.pg1.add_stream(pkts)
3004 self.pg_enable_capture(self.pg_interfaces)
3005 self.pg_start()
3006 capture = self.pg2.get_capture(len(pkts))
3007 self.verify_capture_out(capture, nat_ip1)
3008
Martin Gálik406eb1d2017-05-04 04:35:04 -07003009 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003010 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003011
Neale Ranns37029302018-08-10 05:30:06 -07003012 self.vapi.ip_neighbor_add_del(
3013 self.pg7.sw_if_index,
3014 self.pg7.remote_mac,
3015 self.pg7.remote_ip4,
3016 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3017 IP_API_NEIGHBOR_FLAG_STATIC))
3018 self.vapi.ip_neighbor_add_del(
3019 self.pg8.sw_if_index,
3020 self.pg8.remote_mac,
3021 self.pg8.remote_ip4,
3022 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3023 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003024
3025 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3026 dst_address_length=32,
3027 next_hop_address=self.pg7.remote_ip4n,
3028 next_hop_sw_if_index=self.pg7.sw_if_index)
3029 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3030 dst_address_length=32,
3031 next_hop_address=self.pg8.remote_ip4n,
3032 next_hop_sw_if_index=self.pg8.sw_if_index)
3033
Matus Fabian2ba92e32017-08-21 07:05:03 -07003034 self.nat44_add_address(self.nat_addr)
3035 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3036 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3037 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003038
3039 # in2out
3040 pkts = self.create_stream_in(self.pg7, self.pg8)
3041 self.pg7.add_stream(pkts)
3042 self.pg_enable_capture(self.pg_interfaces)
3043 self.pg_start()
3044 capture = self.pg8.get_capture(len(pkts))
3045 self.verify_capture_out(capture)
3046
3047 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003048 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003049 self.pg8.add_stream(pkts)
3050 self.pg_enable_capture(self.pg_interfaces)
3051 self.pg_start()
3052 capture = self.pg7.get_capture(len(pkts))
3053 self.verify_capture_in(capture, self.pg7)
3054
3055 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003056 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003057
Neale Ranns37029302018-08-10 05:30:06 -07003058 self.vapi.ip_neighbor_add_del(
3059 self.pg7.sw_if_index,
3060 self.pg7.remote_mac,
3061 self.pg7.remote_ip4,
3062 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3063 IP_API_NEIGHBOR_FLAG_STATIC))
3064 self.vapi.ip_neighbor_add_del(
3065 self.pg8.sw_if_index,
3066 self.pg8.remote_mac,
3067 self.pg8.remote_ip4,
3068 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3069 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003070
3071 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3072 dst_address_length=32,
3073 next_hop_address=self.pg7.remote_ip4n,
3074 next_hop_sw_if_index=self.pg7.sw_if_index)
3075 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3076 dst_address_length=32,
3077 next_hop_address=self.pg8.remote_ip4n,
3078 next_hop_sw_if_index=self.pg8.sw_if_index)
3079
Matus Fabian2ba92e32017-08-21 07:05:03 -07003080 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3081 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3082 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3083 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003084
3085 # out2in
3086 pkts = self.create_stream_out(self.pg8)
3087 self.pg8.add_stream(pkts)
3088 self.pg_enable_capture(self.pg_interfaces)
3089 self.pg_start()
3090 capture = self.pg7.get_capture(len(pkts))
3091 self.verify_capture_in(capture, self.pg7)
3092
3093 # in2out
3094 pkts = self.create_stream_in(self.pg7, self.pg8)
3095 self.pg7.add_stream(pkts)
3096 self.pg_enable_capture(self.pg_interfaces)
3097 self.pg_start()
3098 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003099 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003100
3101 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003102 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003103
3104 self.tcp_port_out = 30606
3105 self.udp_port_out = 30607
3106 self.icmp_id_out = 30608
3107
Neale Ranns37029302018-08-10 05:30:06 -07003108 self.vapi.ip_neighbor_add_del(
3109 self.pg7.sw_if_index,
3110 self.pg7.remote_mac,
3111 self.pg7.remote_ip4,
3112 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3113 IP_API_NEIGHBOR_FLAG_STATIC))
3114 self.vapi.ip_neighbor_add_del(
3115 self.pg8.sw_if_index,
3116 self.pg8.remote_mac,
3117 self.pg8.remote_ip4,
3118 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3119 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003120
3121 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3122 dst_address_length=32,
3123 next_hop_address=self.pg7.remote_ip4n,
3124 next_hop_sw_if_index=self.pg7.sw_if_index)
3125 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3126 dst_address_length=32,
3127 next_hop_address=self.pg8.remote_ip4n,
3128 next_hop_sw_if_index=self.pg8.sw_if_index)
3129
Matus Fabian2ba92e32017-08-21 07:05:03 -07003130 self.nat44_add_address(self.nat_addr)
3131 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3132 self.tcp_port_in, self.tcp_port_out,
3133 proto=IP_PROTOS.tcp)
3134 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3135 self.udp_port_in, self.udp_port_out,
3136 proto=IP_PROTOS.udp)
3137 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3138 self.icmp_id_in, self.icmp_id_out,
3139 proto=IP_PROTOS.icmp)
3140 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3141 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3142 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003143
3144 # out2in
3145 pkts = self.create_stream_out(self.pg8)
3146 self.pg8.add_stream(pkts)
3147 self.pg_enable_capture(self.pg_interfaces)
3148 self.pg_start()
3149 capture = self.pg7.get_capture(len(pkts))
3150 self.verify_capture_in(capture, self.pg7)
3151
3152 # in2out
3153 pkts = self.create_stream_in(self.pg7, self.pg8)
3154 self.pg7.add_stream(pkts)
3155 self.pg_enable_capture(self.pg_interfaces)
3156 self.pg_start()
3157 capture = self.pg8.get_capture(len(pkts))
3158 self.verify_capture_out(capture)
3159
Matus Fabian328dbc82017-06-19 04:28:04 -07003160 def test_static_unknown_proto(self):
3161 """ 1:1 NAT translate packet with unknown protocol """
3162 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003163 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3164 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3165 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3166 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003167
3168 # in2out
3169 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3170 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3171 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003172 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003173 TCP(sport=1234, dport=1234))
3174 self.pg0.add_stream(p)
3175 self.pg_enable_capture(self.pg_interfaces)
3176 self.pg_start()
3177 p = self.pg1.get_capture(1)
3178 packet = p[0]
3179 try:
3180 self.assertEqual(packet[IP].src, nat_ip)
3181 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003182 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003183 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003184 except:
3185 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3186 raise
3187
3188 # out2in
3189 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3190 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3191 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003192 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003193 TCP(sport=1234, dport=1234))
3194 self.pg1.add_stream(p)
3195 self.pg_enable_capture(self.pg_interfaces)
3196 self.pg_start()
3197 p = self.pg0.get_capture(1)
3198 packet = p[0]
3199 try:
3200 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3201 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003202 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003203 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003204 except:
3205 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3206 raise
3207
Matus Fabian7968e6c2017-07-06 05:37:49 -07003208 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003209 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3210
3211 host = self.pg0.remote_hosts[0]
3212 server = self.pg0.remote_hosts[1]
3213
3214 host_nat_ip = "10.0.0.10"
3215 server_nat_ip = "10.0.0.11"
3216
Matus Fabian2ba92e32017-08-21 07:05:03 -07003217 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3218 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3219 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3220 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3221 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003222
3223 # host to server
3224 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3225 IP(src=host.ip4, dst=server_nat_ip) /
3226 GRE() /
3227 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3228 TCP(sport=1234, dport=1234))
3229 self.pg0.add_stream(p)
3230 self.pg_enable_capture(self.pg_interfaces)
3231 self.pg_start()
3232 p = self.pg0.get_capture(1)
3233 packet = p[0]
3234 try:
3235 self.assertEqual(packet[IP].src, host_nat_ip)
3236 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003237 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003238 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003239 except:
3240 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3241 raise
3242
3243 # server to host
3244 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3245 IP(src=server.ip4, dst=host_nat_ip) /
3246 GRE() /
3247 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3248 TCP(sport=1234, dport=1234))
3249 self.pg0.add_stream(p)
3250 self.pg_enable_capture(self.pg_interfaces)
3251 self.pg_start()
3252 p = self.pg0.get_capture(1)
3253 packet = p[0]
3254 try:
3255 self.assertEqual(packet[IP].src, server_nat_ip)
3256 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003257 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003258 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003259 except:
3260 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3261 raise
3262
Matus Fabian93d84c92017-07-19 08:06:01 -07003263 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003264 """ NAT44 interface output feature (in2out postrouting) """
3265 self.nat44_add_address(self.nat_addr)
3266 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003267 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3268 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003269 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003270
3271 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003272 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003273 self.pg0.add_stream(pkts)
3274 self.pg_enable_capture(self.pg_interfaces)
3275 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003276 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003277 self.verify_capture_out(capture)
3278
3279 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003280 pkts = self.create_stream_out(self.pg3)
3281 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003282 self.pg_enable_capture(self.pg_interfaces)
3283 self.pg_start()
3284 capture = self.pg0.get_capture(len(pkts))
3285 self.verify_capture_in(capture, self.pg0)
3286
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003287 # from non-NAT interface to NAT inside interface
3288 pkts = self.create_stream_in(self.pg2, self.pg0)
3289 self.pg2.add_stream(pkts)
3290 self.pg_enable_capture(self.pg_interfaces)
3291 self.pg_start()
3292 capture = self.pg0.get_capture(len(pkts))
3293 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3294
Matus Fabian93d84c92017-07-19 08:06:01 -07003295 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003296 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003297 nat_ip_vrf10 = "10.0.0.10"
3298 nat_ip_vrf20 = "10.0.0.20"
3299
3300 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3301 dst_address_length=32,
3302 next_hop_address=self.pg3.remote_ip4n,
3303 next_hop_sw_if_index=self.pg3.sw_if_index,
3304 table_id=10)
3305 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3306 dst_address_length=32,
3307 next_hop_address=self.pg3.remote_ip4n,
3308 next_hop_sw_if_index=self.pg3.sw_if_index,
3309 table_id=20)
3310
Matus Fabian2ba92e32017-08-21 07:05:03 -07003311 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3312 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3313 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3314 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3315 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3316 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003317
3318 # in2out VRF 10
3319 pkts = self.create_stream_in(self.pg4, self.pg3)
3320 self.pg4.add_stream(pkts)
3321 self.pg_enable_capture(self.pg_interfaces)
3322 self.pg_start()
3323 capture = self.pg3.get_capture(len(pkts))
3324 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3325
3326 # out2in VRF 10
3327 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3328 self.pg3.add_stream(pkts)
3329 self.pg_enable_capture(self.pg_interfaces)
3330 self.pg_start()
3331 capture = self.pg4.get_capture(len(pkts))
3332 self.verify_capture_in(capture, self.pg4)
3333
3334 # in2out VRF 20
3335 pkts = self.create_stream_in(self.pg6, self.pg3)
3336 self.pg6.add_stream(pkts)
3337 self.pg_enable_capture(self.pg_interfaces)
3338 self.pg_start()
3339 capture = self.pg3.get_capture(len(pkts))
3340 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3341
3342 # out2in VRF 20
3343 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3344 self.pg3.add_stream(pkts)
3345 self.pg_enable_capture(self.pg_interfaces)
3346 self.pg_start()
3347 capture = self.pg6.get_capture(len(pkts))
3348 self.verify_capture_in(capture, self.pg6)
3349
Matus Fabian161c59c2017-07-21 03:46:03 -07003350 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003351 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003352 host = self.pg0.remote_hosts[0]
3353 server = self.pg0.remote_hosts[1]
3354 host_in_port = 1234
3355 host_out_port = 0
3356 server_in_port = 5678
3357 server_out_port = 8765
3358
Matus Fabian2ba92e32017-08-21 07:05:03 -07003359 self.nat44_add_address(self.nat_addr)
3360 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3361 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3362 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003363
3364 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003365 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3366 server_in_port, server_out_port,
3367 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003368
3369 # send packet from host to server
3370 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003371 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003372 TCP(sport=host_in_port, dport=server_out_port))
3373 self.pg0.add_stream(p)
3374 self.pg_enable_capture(self.pg_interfaces)
3375 self.pg_start()
3376 capture = self.pg0.get_capture(1)
3377 p = capture[0]
3378 try:
3379 ip = p[IP]
3380 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003381 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003382 self.assertEqual(ip.dst, server.ip4)
3383 self.assertNotEqual(tcp.sport, host_in_port)
3384 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003385 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003386 host_out_port = tcp.sport
3387 except:
3388 self.logger.error(ppp("Unexpected or invalid packet:", p))
3389 raise
3390
3391 # send reply from server to host
3392 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003393 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003394 TCP(sport=server_in_port, dport=host_out_port))
3395 self.pg0.add_stream(p)
3396 self.pg_enable_capture(self.pg_interfaces)
3397 self.pg_start()
3398 capture = self.pg0.get_capture(1)
3399 p = capture[0]
3400 try:
3401 ip = p[IP]
3402 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003403 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003404 self.assertEqual(ip.dst, host.ip4)
3405 self.assertEqual(tcp.sport, server_out_port)
3406 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003407 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003408 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003409 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003410 raise
3411
Matus Fabian36ea2d62017-10-24 04:13:49 -07003412 def test_one_armed_nat44(self):
3413 """ One armed NAT44 """
3414 remote_host = self.pg9.remote_hosts[0]
3415 local_host = self.pg9.remote_hosts[1]
3416 external_port = 0
3417
3418 self.nat44_add_address(self.nat_addr)
3419 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3420 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3421 is_inside=0)
3422
3423 # in2out
3424 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3425 IP(src=local_host.ip4, dst=remote_host.ip4) /
3426 TCP(sport=12345, dport=80))
3427 self.pg9.add_stream(p)
3428 self.pg_enable_capture(self.pg_interfaces)
3429 self.pg_start()
3430 capture = self.pg9.get_capture(1)
3431 p = capture[0]
3432 try:
3433 ip = p[IP]
3434 tcp = p[TCP]
3435 self.assertEqual(ip.src, self.nat_addr)
3436 self.assertEqual(ip.dst, remote_host.ip4)
3437 self.assertNotEqual(tcp.sport, 12345)
3438 external_port = tcp.sport
3439 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003440 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003441 except:
3442 self.logger.error(ppp("Unexpected or invalid packet:", p))
3443 raise
3444
3445 # out2in
3446 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3447 IP(src=remote_host.ip4, dst=self.nat_addr) /
3448 TCP(sport=80, dport=external_port))
3449 self.pg9.add_stream(p)
3450 self.pg_enable_capture(self.pg_interfaces)
3451 self.pg_start()
3452 capture = self.pg9.get_capture(1)
3453 p = capture[0]
3454 try:
3455 ip = p[IP]
3456 tcp = p[TCP]
3457 self.assertEqual(ip.src, remote_host.ip4)
3458 self.assertEqual(ip.dst, local_host.ip4)
3459 self.assertEqual(tcp.sport, 80)
3460 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003461 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003462 except:
3463 self.logger.error(ppp("Unexpected or invalid packet:", p))
3464 raise
3465
Matus Fabiana5e73762018-12-14 01:55:16 -08003466 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3467 self.assertEqual(err, 1)
3468 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3469 self.assertEqual(err, 1)
3470
Matus Fabian5ba86f72017-10-26 03:37:38 -07003471 def test_del_session(self):
3472 """ Delete NAT44 session """
3473 self.nat44_add_address(self.nat_addr)
3474 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3475 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3476 is_inside=0)
3477
3478 pkts = self.create_stream_in(self.pg0, self.pg1)
3479 self.pg0.add_stream(pkts)
3480 self.pg_enable_capture(self.pg_interfaces)
3481 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003482 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003483
3484 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3485 nsessions = len(sessions)
3486
3487 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3488 sessions[0].inside_port,
3489 sessions[0].protocol)
3490 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3491 sessions[1].outside_port,
3492 sessions[1].protocol,
3493 is_in=0)
3494
3495 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3496 self.assertEqual(nsessions - len(sessions), 2)
3497
Matus Fabian68ba8802018-08-08 05:52:47 -07003498 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3499 sessions[0].inside_port,
3500 sessions[0].protocol)
3501
3502 self.verify_no_nat44_user()
3503
Matus Fabianefcd1e92017-08-15 06:59:19 -07003504 def test_set_get_reass(self):
3505 """ NAT44 set/get virtual fragmentation reassembly """
3506 reas_cfg1 = self.vapi.nat_get_reass()
3507
3508 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3509 max_reass=reas_cfg1.ip4_max_reass * 2,
3510 max_frag=reas_cfg1.ip4_max_frag * 2)
3511
3512 reas_cfg2 = self.vapi.nat_get_reass()
3513
3514 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3515 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3516 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3517
3518 self.vapi.nat_set_reass(drop_frag=1)
3519 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3520
3521 def test_frag_in_order(self):
3522 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003523
Matus Fabianefcd1e92017-08-15 06:59:19 -07003524 self.nat44_add_address(self.nat_addr)
3525 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3526 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3527 is_inside=0)
3528
Matus Fabianda41d722018-10-19 04:01:19 -07003529 self.frag_in_order(proto=IP_PROTOS.tcp)
3530 self.frag_in_order(proto=IP_PROTOS.udp)
3531 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003532
Matus Fabian111add72018-11-20 02:19:05 -08003533 def test_frag_forwarding(self):
3534 """ NAT44 forwarding fragment test """
3535 self.vapi.nat44_add_interface_addr(self.pg1.sw_if_index)
3536 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3537 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3538 is_inside=0)
3539 self.vapi.nat44_forwarding_enable_disable(1)
3540
3541 data = "A" * 16 + "B" * 16 + "C" * 3
3542 pkts = self.create_stream_frag(self.pg1,
3543 self.pg0.remote_ip4,
3544 4789,
3545 4789,
3546 data,
3547 proto=IP_PROTOS.udp)
3548 self.pg1.add_stream(pkts)
3549 self.pg_enable_capture(self.pg_interfaces)
3550 self.pg_start()
3551 frags = self.pg0.get_capture(len(pkts))
3552 p = self.reass_frags_and_verify(frags,
3553 self.pg1.remote_ip4,
3554 self.pg0.remote_ip4)
3555 self.assertEqual(p[UDP].sport, 4789)
3556 self.assertEqual(p[UDP].dport, 4789)
3557 self.assertEqual(data, p[Raw].load)
3558
Matus Fabianefcd1e92017-08-15 06:59:19 -07003559 def test_reass_hairpinning(self):
3560 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003561
Matus Fabianda41d722018-10-19 04:01:19 -07003562 self.server = self.pg0.remote_hosts[1]
3563 self.host_in_port = random.randint(1025, 65535)
3564 self.server_in_port = random.randint(1025, 65535)
3565 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003566
3567 self.nat44_add_address(self.nat_addr)
3568 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3569 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3570 is_inside=0)
3571 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003572 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3573 self.server_in_port,
3574 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003575 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003576 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3577 self.server_in_port,
3578 self.server_out_port,
3579 proto=IP_PROTOS.udp)
3580 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003581
Matus Fabianda41d722018-10-19 04:01:19 -07003582 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3583 self.reass_hairpinning(proto=IP_PROTOS.udp)
3584 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003585
3586 def test_frag_out_of_order(self):
3587 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003588
Matus Fabianefcd1e92017-08-15 06:59:19 -07003589 self.nat44_add_address(self.nat_addr)
3590 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3591 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3592 is_inside=0)
3593
Matus Fabianda41d722018-10-19 04:01:19 -07003594 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3595 self.frag_out_of_order(proto=IP_PROTOS.udp)
3596 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003597
Matus Fabian27697102017-11-09 01:43:47 -08003598 def test_port_restricted(self):
3599 """ Port restricted NAT44 (MAP-E CE) """
3600 self.nat44_add_address(self.nat_addr)
3601 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3602 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3603 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003604 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3605 psid_offset=6,
3606 psid_length=6,
3607 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003608
3609 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3610 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3611 TCP(sport=4567, dport=22))
3612 self.pg0.add_stream(p)
3613 self.pg_enable_capture(self.pg_interfaces)
3614 self.pg_start()
3615 capture = self.pg1.get_capture(1)
3616 p = capture[0]
3617 try:
3618 ip = p[IP]
3619 tcp = p[TCP]
3620 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3621 self.assertEqual(ip.src, self.nat_addr)
3622 self.assertEqual(tcp.dport, 22)
3623 self.assertNotEqual(tcp.sport, 4567)
3624 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003625 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003626 except:
3627 self.logger.error(ppp("Unexpected or invalid packet:", p))
3628 raise
3629
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003630 def test_port_range(self):
3631 """ External address port range """
3632 self.nat44_add_address(self.nat_addr)
3633 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3634 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3635 is_inside=0)
3636 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3637 start_port=1025,
3638 end_port=1027)
3639
3640 pkts = []
3641 for port in range(0, 5):
3642 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3643 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3644 TCP(sport=1125 + port))
3645 pkts.append(p)
3646 self.pg0.add_stream(pkts)
3647 self.pg_enable_capture(self.pg_interfaces)
3648 self.pg_start()
3649 capture = self.pg1.get_capture(3)
3650 for p in capture:
3651 tcp = p[TCP]
3652 self.assertGreaterEqual(tcp.sport, 1025)
3653 self.assertLessEqual(tcp.sport, 1027)
3654
Matus Fabiana6110b62018-06-13 05:39:07 -07003655 def test_ipfix_max_frags(self):
3656 """ IPFIX logging maximum fragments pending reassembly exceeded """
3657 self.nat44_add_address(self.nat_addr)
3658 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3659 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3660 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003661 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003662 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3663 src_address=self.pg3.local_ip4n,
3664 path_mtu=512,
3665 template_interval=10)
3666 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3667 src_port=self.ipfix_src_port)
3668
3669 data = "A" * 4 + "B" * 16 + "C" * 3
3670 self.tcp_port_in = random.randint(1025, 65535)
3671 pkts = self.create_stream_frag(self.pg0,
3672 self.pg1.remote_ip4,
3673 self.tcp_port_in,
3674 20,
3675 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003676 pkts.reverse()
3677 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003678 self.pg_enable_capture(self.pg_interfaces)
3679 self.pg_start()
3680 self.pg1.assert_nothing_captured()
3681 sleep(1)
3682 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3683 capture = self.pg3.get_capture(9)
3684 ipfix = IPFIXDecoder()
3685 # first load template
3686 for p in capture:
3687 self.assertTrue(p.haslayer(IPFIX))
3688 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3689 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3690 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3691 self.assertEqual(p[UDP].dport, 4739)
3692 self.assertEqual(p[IPFIX].observationDomainID,
3693 self.ipfix_domain_id)
3694 if p.haslayer(Template):
3695 ipfix.add_template(p.getlayer(Template))
3696 # verify events in data set
3697 for p in capture:
3698 if p.haslayer(Data):
3699 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003700 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003701 self.pg0.remote_ip4n)
3702
Matus Fabian8008d7c2018-07-09 01:34:20 -07003703 def test_multiple_outside_vrf(self):
3704 """ Multiple outside VRF """
3705 vrf_id1 = 1
3706 vrf_id2 = 2
3707
3708 self.pg1.unconfig_ip4()
3709 self.pg2.unconfig_ip4()
3710 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3711 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3712 self.pg1.set_table_ip4(vrf_id1)
3713 self.pg2.set_table_ip4(vrf_id2)
3714 self.pg1.config_ip4()
3715 self.pg2.config_ip4()
3716 self.pg1.resolve_arp()
3717 self.pg2.resolve_arp()
3718
3719 self.nat44_add_address(self.nat_addr)
3720 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3721 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3722 is_inside=0)
3723 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3724 is_inside=0)
3725
3726 try:
3727 # first VRF
3728 pkts = self.create_stream_in(self.pg0, self.pg1)
3729 self.pg0.add_stream(pkts)
3730 self.pg_enable_capture(self.pg_interfaces)
3731 self.pg_start()
3732 capture = self.pg1.get_capture(len(pkts))
3733 self.verify_capture_out(capture, self.nat_addr)
3734
3735 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3736 self.pg1.add_stream(pkts)
3737 self.pg_enable_capture(self.pg_interfaces)
3738 self.pg_start()
3739 capture = self.pg0.get_capture(len(pkts))
3740 self.verify_capture_in(capture, self.pg0)
3741
3742 self.tcp_port_in = 60303
3743 self.udp_port_in = 60304
3744 self.icmp_id_in = 60305
3745
3746 # second VRF
3747 pkts = self.create_stream_in(self.pg0, self.pg2)
3748 self.pg0.add_stream(pkts)
3749 self.pg_enable_capture(self.pg_interfaces)
3750 self.pg_start()
3751 capture = self.pg2.get_capture(len(pkts))
3752 self.verify_capture_out(capture, self.nat_addr)
3753
3754 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3755 self.pg2.add_stream(pkts)
3756 self.pg_enable_capture(self.pg_interfaces)
3757 self.pg_start()
3758 capture = self.pg0.get_capture(len(pkts))
3759 self.verify_capture_in(capture, self.pg0)
3760
3761 finally:
3762 self.pg1.unconfig_ip4()
3763 self.pg2.unconfig_ip4()
3764 self.pg1.set_table_ip4(0)
3765 self.pg2.set_table_ip4(0)
3766 self.pg1.config_ip4()
3767 self.pg2.config_ip4()
3768 self.pg1.resolve_arp()
3769 self.pg2.resolve_arp()
3770
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08003771 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07003772 def test_session_timeout(self):
3773 """ NAT44 session timeouts """
3774 self.nat44_add_address(self.nat_addr)
3775 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3776 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3777 is_inside=0)
3778 self.vapi.nat_set_timeouts(udp=5)
3779
3780 max_sessions = 1000
3781 pkts = []
3782 for i in range(0, max_sessions):
3783 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3784 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3785 IP(src=src, dst=self.pg1.remote_ip4) /
3786 UDP(sport=1025, dport=53))
3787 pkts.append(p)
3788 self.pg0.add_stream(pkts)
3789 self.pg_enable_capture(self.pg_interfaces)
3790 self.pg_start()
3791 self.pg1.get_capture(max_sessions)
3792
3793 sleep(6)
3794
3795 pkts = []
3796 for i in range(0, max_sessions):
3797 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3798 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3799 IP(src=src, dst=self.pg1.remote_ip4) /
3800 UDP(sport=1026, dport=53))
3801 pkts.append(p)
3802 self.pg0.add_stream(pkts)
3803 self.pg_enable_capture(self.pg_interfaces)
3804 self.pg_start()
3805 self.pg1.get_capture(max_sessions)
3806
3807 nsessions = 0
3808 users = self.vapi.nat44_user_dump()
3809 for user in users:
3810 nsessions = nsessions + user.nsessions
3811 self.assertLess(nsessions, 2 * max_sessions)
3812
Matus Fabianbb4e0222018-09-13 02:36:25 -07003813 def test_mss_clamping(self):
3814 """ TCP MSS clamping """
3815 self.nat44_add_address(self.nat_addr)
3816 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3817 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3818 is_inside=0)
3819
3820 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3821 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3822 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3823 flags="S", options=[('MSS', 1400)]))
3824
3825 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3826 self.pg0.add_stream(p)
3827 self.pg_enable_capture(self.pg_interfaces)
3828 self.pg_start()
3829 capture = self.pg1.get_capture(1)
3830 # Negotiated MSS value greater than configured - changed
3831 self.verify_mss_value(capture[0], 1000)
3832
3833 self.vapi.nat_set_mss_clamping(enable=0)
3834 self.pg0.add_stream(p)
3835 self.pg_enable_capture(self.pg_interfaces)
3836 self.pg_start()
3837 capture = self.pg1.get_capture(1)
3838 # MSS clamping disabled - negotiated MSS unchanged
3839 self.verify_mss_value(capture[0], 1400)
3840
3841 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3842 self.pg0.add_stream(p)
3843 self.pg_enable_capture(self.pg_interfaces)
3844 self.pg_start()
3845 capture = self.pg1.get_capture(1)
3846 # Negotiated MSS value smaller than configured - unchanged
3847 self.verify_mss_value(capture[0], 1400)
3848
Matus Fabian34931eb2019-02-26 09:05:23 -08003849 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3850 def test_ha_send(self):
3851 """ Send HA session synchronization events (active) """
3852 self.nat44_add_address(self.nat_addr)
3853 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3854 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3855 is_inside=0)
3856 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3857 self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3858 bind_layers(UDP, HANATStateSync, sport=12345)
3859
3860 # create sessions
3861 pkts = self.create_stream_in(self.pg0, self.pg1)
3862 self.pg0.add_stream(pkts)
3863 self.pg_enable_capture(self.pg_interfaces)
3864 self.pg_start()
3865 capture = self.pg1.get_capture(len(pkts))
3866 self.verify_capture_out(capture)
3867 # active send HA events
3868 self.vapi.nat_ha_flush()
3869 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3870 self.assertEqual(stats[0][0], 3)
3871 capture = self.pg3.get_capture(1)
3872 p = capture[0]
3873 self.assert_packet_checksums_valid(p)
3874 try:
3875 ip = p[IP]
3876 udp = p[UDP]
3877 hanat = p[HANATStateSync]
3878 except IndexError:
3879 self.logger.error(ppp("Invalid packet:", p))
3880 raise
3881 else:
3882 self.assertEqual(ip.src, self.pg3.local_ip4)
3883 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3884 self.assertEqual(udp.sport, 12345)
3885 self.assertEqual(udp.dport, 12346)
3886 self.assertEqual(hanat.version, 1)
3887 self.assertEqual(hanat.thread_index, 0)
3888 self.assertEqual(hanat.count, 3)
3889 seq = hanat.sequence_number
3890 for event in hanat.events:
3891 self.assertEqual(event.event_type, 1)
3892 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3893 self.assertEqual(event.out_addr, self.nat_addr)
3894 self.assertEqual(event.fib_index, 0)
3895
3896 # ACK received events
3897 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3898 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3899 UDP(sport=12346, dport=12345) /
3900 HANATStateSync(sequence_number=seq, flags='ACK'))
3901 self.pg3.add_stream(ack)
3902 self.pg_start()
3903 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3904 self.assertEqual(stats[0][0], 1)
3905
3906 # delete one session
3907 self.pg_enable_capture(self.pg_interfaces)
3908 self.vapi.nat44_del_session(self.pg0.remote_ip4n, self.tcp_port_in,
3909 IP_PROTOS.tcp)
3910 self.vapi.nat_ha_flush()
3911 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3912 self.assertEqual(stats[0][0], 1)
3913 capture = self.pg3.get_capture(1)
3914 p = capture[0]
3915 try:
3916 hanat = p[HANATStateSync]
3917 except IndexError:
3918 self.logger.error(ppp("Invalid packet:", p))
3919 raise
3920 else:
3921 self.assertGreater(hanat.sequence_number, seq)
3922
3923 # do not send ACK, active retry send HA event again
3924 self.pg_enable_capture(self.pg_interfaces)
3925 sleep(12)
3926 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3927 self.assertEqual(stats[0][0], 3)
3928 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3929 self.assertEqual(stats[0][0], 1)
3930 capture = self.pg3.get_capture(3)
3931 for packet in capture:
3932 self.assertEqual(packet, p)
3933
3934 # session counters refresh
3935 pkts = self.create_stream_out(self.pg1)
3936 self.pg1.add_stream(pkts)
3937 self.pg_enable_capture(self.pg_interfaces)
3938 self.pg_start()
3939 self.pg0.get_capture(2)
3940 self.vapi.nat_ha_flush()
3941 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3942 self.assertEqual(stats[0][0], 2)
3943 capture = self.pg3.get_capture(1)
3944 p = capture[0]
3945 self.assert_packet_checksums_valid(p)
3946 try:
3947 ip = p[IP]
3948 udp = p[UDP]
3949 hanat = p[HANATStateSync]
3950 except IndexError:
3951 self.logger.error(ppp("Invalid packet:", p))
3952 raise
3953 else:
3954 self.assertEqual(ip.src, self.pg3.local_ip4)
3955 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3956 self.assertEqual(udp.sport, 12345)
3957 self.assertEqual(udp.dport, 12346)
3958 self.assertEqual(hanat.version, 1)
3959 self.assertEqual(hanat.count, 2)
3960 seq = hanat.sequence_number
3961 for event in hanat.events:
3962 self.assertEqual(event.event_type, 3)
3963 self.assertEqual(event.out_addr, self.nat_addr)
3964 self.assertEqual(event.fib_index, 0)
3965 self.assertEqual(event.total_pkts, 2)
3966 self.assertGreater(event.total_bytes, 0)
3967
3968 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3969 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3970 UDP(sport=12346, dport=12345) /
3971 HANATStateSync(sequence_number=seq, flags='ACK'))
3972 self.pg3.add_stream(ack)
3973 self.pg_start()
3974 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3975 self.assertEqual(stats[0][0], 2)
3976
3977 def test_ha_recv(self):
3978 """ Receive HA session synchronization events (passive) """
3979 self.nat44_add_address(self.nat_addr)
3980 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3981 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3982 is_inside=0)
3983 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3984 bind_layers(UDP, HANATStateSync, sport=12345)
3985
3986 self.tcp_port_out = random.randint(1025, 65535)
3987 self.udp_port_out = random.randint(1025, 65535)
3988
3989 # send HA session add events to failover/passive
3990 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3991 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3992 UDP(sport=12346, dport=12345) /
3993 HANATStateSync(sequence_number=1, events=[
3994 Event(event_type='add', protocol='tcp',
3995 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3996 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3997 eh_addr=self.pg1.remote_ip4,
3998 ehn_addr=self.pg1.remote_ip4,
3999 eh_port=self.tcp_external_port,
4000 ehn_port=self.tcp_external_port, fib_index=0),
4001 Event(event_type='add', protocol='udp',
4002 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4003 in_port=self.udp_port_in, out_port=self.udp_port_out,
4004 eh_addr=self.pg1.remote_ip4,
4005 ehn_addr=self.pg1.remote_ip4,
4006 eh_port=self.udp_external_port,
4007 ehn_port=self.udp_external_port, fib_index=0)]))
4008
4009 self.pg3.add_stream(p)
4010 self.pg_enable_capture(self.pg_interfaces)
4011 self.pg_start()
4012 # receive ACK
4013 capture = self.pg3.get_capture(1)
4014 p = capture[0]
4015 try:
4016 hanat = p[HANATStateSync]
4017 except IndexError:
4018 self.logger.error(ppp("Invalid packet:", p))
4019 raise
4020 else:
4021 self.assertEqual(hanat.sequence_number, 1)
4022 self.assertEqual(hanat.flags, 'ACK')
4023 self.assertEqual(hanat.version, 1)
4024 self.assertEqual(hanat.thread_index, 0)
4025 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4026 self.assertEqual(stats[0][0], 1)
4027 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4028 self.assertEqual(stats[0][0], 2)
4029 users = self.statistics.get_counter('/nat44/total-users')
4030 self.assertEqual(users[0][0], 1)
4031 sessions = self.statistics.get_counter('/nat44/total-sessions')
4032 self.assertEqual(sessions[0][0], 2)
4033 users = self.vapi.nat44_user_dump()
4034 self.assertEqual(len(users), 1)
4035 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4036 # there should be 2 sessions created by HA
4037 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4038 users[0].vrf_id)
4039 self.assertEqual(len(sessions), 2)
4040 for session in sessions:
4041 self.assertEqual(session.inside_ip_address, self.pg0.remote_ip4n)
4042 self.assertEqual(session.outside_ip_address, self.nat_addr_n)
4043 self.assertIn(session.inside_port,
4044 [self.tcp_port_in, self.udp_port_in])
4045 self.assertIn(session.outside_port,
4046 [self.tcp_port_out, self.udp_port_out])
4047 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4048
4049 # send HA session delete event to failover/passive
4050 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4051 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4052 UDP(sport=12346, dport=12345) /
4053 HANATStateSync(sequence_number=2, events=[
4054 Event(event_type='del', protocol='udp',
4055 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4056 in_port=self.udp_port_in, out_port=self.udp_port_out,
4057 eh_addr=self.pg1.remote_ip4,
4058 ehn_addr=self.pg1.remote_ip4,
4059 eh_port=self.udp_external_port,
4060 ehn_port=self.udp_external_port, fib_index=0)]))
4061
4062 self.pg3.add_stream(p)
4063 self.pg_enable_capture(self.pg_interfaces)
4064 self.pg_start()
4065 # receive ACK
4066 capture = self.pg3.get_capture(1)
4067 p = capture[0]
4068 try:
4069 hanat = p[HANATStateSync]
4070 except IndexError:
4071 self.logger.error(ppp("Invalid packet:", p))
4072 raise
4073 else:
4074 self.assertEqual(hanat.sequence_number, 2)
4075 self.assertEqual(hanat.flags, 'ACK')
4076 self.assertEqual(hanat.version, 1)
4077 users = self.vapi.nat44_user_dump()
4078 self.assertEqual(len(users), 1)
4079 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4080 # now we should have only 1 session, 1 deleted by HA
4081 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4082 users[0].vrf_id)
4083 self.assertEqual(len(sessions), 1)
4084 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4085 self.assertEqual(stats[0][0], 1)
4086
4087 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4088 self.assertEqual(stats, 2)
4089
4090 # send HA session refresh event to failover/passive
4091 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4092 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4093 UDP(sport=12346, dport=12345) /
4094 HANATStateSync(sequence_number=3, events=[
4095 Event(event_type='refresh', protocol='tcp',
4096 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4097 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4098 eh_addr=self.pg1.remote_ip4,
4099 ehn_addr=self.pg1.remote_ip4,
4100 eh_port=self.tcp_external_port,
4101 ehn_port=self.tcp_external_port, fib_index=0,
4102 total_bytes=1024, total_pkts=2)]))
4103 self.pg3.add_stream(p)
4104 self.pg_enable_capture(self.pg_interfaces)
4105 self.pg_start()
4106 # receive ACK
4107 capture = self.pg3.get_capture(1)
4108 p = capture[0]
4109 try:
4110 hanat = p[HANATStateSync]
4111 except IndexError:
4112 self.logger.error(ppp("Invalid packet:", p))
4113 raise
4114 else:
4115 self.assertEqual(hanat.sequence_number, 3)
4116 self.assertEqual(hanat.flags, 'ACK')
4117 self.assertEqual(hanat.version, 1)
4118 users = self.vapi.nat44_user_dump()
4119 self.assertEqual(len(users), 1)
4120 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4121 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4122 users[0].vrf_id)
4123 self.assertEqual(len(sessions), 1)
4124 session = sessions[0]
4125 self.assertEqual(session.total_bytes, 1024)
4126 self.assertEqual(session.total_pkts, 2)
4127 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4128 self.assertEqual(stats[0][0], 1)
4129
4130 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4131 self.assertEqual(stats, 3)
4132
4133 # send packet to test session created by HA
4134 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4135 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4136 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4137 self.pg1.add_stream(p)
4138 self.pg_enable_capture(self.pg_interfaces)
4139 self.pg_start()
4140 capture = self.pg0.get_capture(1)
4141 p = capture[0]
4142 try:
4143 ip = p[IP]
4144 tcp = p[TCP]
4145 except IndexError:
4146 self.logger.error(ppp("Invalid packet:", p))
4147 raise
4148 else:
4149 self.assertEqual(ip.src, self.pg1.remote_ip4)
4150 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4151 self.assertEqual(tcp.sport, self.tcp_external_port)
4152 self.assertEqual(tcp.dport, self.tcp_port_in)
4153
Matus Fabiana6110b62018-06-13 05:39:07 -07004154 def tearDown(self):
4155 super(TestNAT44, self).tearDown()
4156 if not self.vpp_dead:
4157 self.logger.info(self.vapi.cli("show nat44 addresses"))
4158 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4159 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4160 self.logger.info(self.vapi.cli("show nat44 interface address"))
4161 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4162 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4163 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07004164 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07004165 self.logger.info(
4166 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabian34931eb2019-02-26 09:05:23 -08004167 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004168 self.clear_nat44()
4169 self.vapi.cli("clear logging")
4170
4171
4172class TestNAT44EndpointDependent(MethodHolder):
4173 """ Endpoint-Dependent mapping and filtering test cases """
4174
4175 @classmethod
4176 def setUpConstants(cls):
4177 super(TestNAT44EndpointDependent, cls).setUpConstants()
4178 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4179
4180 @classmethod
4181 def setUpClass(cls):
4182 super(TestNAT44EndpointDependent, cls).setUpClass()
4183 cls.vapi.cli("set log class nat level debug")
4184 try:
4185 cls.tcp_port_in = 6303
4186 cls.tcp_port_out = 6303
4187 cls.udp_port_in = 6304
4188 cls.udp_port_out = 6304
4189 cls.icmp_id_in = 6305
4190 cls.icmp_id_out = 6305
4191 cls.nat_addr = '10.0.0.3'
4192 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4193 cls.ipfix_src_port = 4739
4194 cls.ipfix_domain_id = 1
4195 cls.tcp_external_port = 80
4196
Matus Fabian8008d7c2018-07-09 01:34:20 -07004197 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004198 cls.interfaces = list(cls.pg_interfaces[0:3])
4199
4200 for i in cls.interfaces:
4201 i.admin_up()
4202 i.config_ip4()
4203 i.resolve_arp()
4204
4205 cls.pg0.generate_remote_hosts(3)
4206 cls.pg0.configure_ipv4_neighbors()
4207
4208 cls.pg3.admin_up()
4209
4210 cls.pg4.generate_remote_hosts(2)
4211 cls.pg4.config_ip4()
4212 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
4213 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
4214 ip_addr_n,
4215 24)
4216 cls.pg4.admin_up()
4217 cls.pg4.resolve_arp()
4218 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4219 cls.pg4.resolve_arp()
4220
Matus Fabian8008d7c2018-07-09 01:34:20 -07004221 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4222 cls.vapi.ip_table_add_del(1, is_add=1)
4223
4224 cls.pg5._local_ip4 = "10.1.1.1"
4225 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4226 cls.pg5.local_ip4)
4227 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4228 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4229 socket.AF_INET, cls.pg5.remote_ip4)
4230 cls.pg5.set_table_ip4(1)
4231 cls.pg5.config_ip4()
4232 cls.pg5.admin_up()
4233 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4234 dst_address_length=32,
4235 table_id=1,
4236 next_hop_sw_if_index=cls.pg5.sw_if_index,
4237 next_hop_address=zero_ip4n)
4238
4239 cls.pg6._local_ip4 = "10.1.2.1"
4240 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4241 cls.pg6.local_ip4)
4242 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4243 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4244 socket.AF_INET, cls.pg6.remote_ip4)
4245 cls.pg6.set_table_ip4(1)
4246 cls.pg6.config_ip4()
4247 cls.pg6.admin_up()
4248 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4249 dst_address_length=32,
4250 table_id=1,
4251 next_hop_sw_if_index=cls.pg6.sw_if_index,
4252 next_hop_address=zero_ip4n)
4253
4254 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4255 dst_address_length=16,
4256 next_hop_address=zero_ip4n,
4257 table_id=0,
4258 next_hop_table_id=1)
4259 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4260 dst_address_length=0,
4261 next_hop_address=zero_ip4n,
4262 table_id=1,
4263 next_hop_table_id=0)
4264 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4265 dst_address_length=0,
4266 table_id=0,
4267 next_hop_sw_if_index=cls.pg1.sw_if_index,
4268 next_hop_address=cls.pg1.local_ip4n)
4269
4270 cls.pg5.resolve_arp()
4271 cls.pg6.resolve_arp()
4272
Matus Fabiana6110b62018-06-13 05:39:07 -07004273 except Exception:
4274 super(TestNAT44EndpointDependent, cls).tearDownClass()
4275 raise
4276
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004277 def test_frag_in_order(self):
4278 """ NAT44 translate fragments arriving in order """
4279 self.nat44_add_address(self.nat_addr)
4280 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4281 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4282 is_inside=0)
4283 self.frag_in_order(proto=IP_PROTOS.tcp)
4284 self.frag_in_order(proto=IP_PROTOS.udp)
4285 self.frag_in_order(proto=IP_PROTOS.icmp)
4286
4287 def test_frag_in_order_dont_translate(self):
4288 """ NAT44 don't translate fragments arriving in order """
4289 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4290 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4291 is_inside=0)
4292 self.vapi.nat44_forwarding_enable_disable(enable=True)
4293 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4294
4295 def test_frag_out_of_order(self):
4296 """ NAT44 translate fragments arriving out of order """
4297 self.nat44_add_address(self.nat_addr)
4298 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4299 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4300 is_inside=0)
4301 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4302 self.frag_out_of_order(proto=IP_PROTOS.udp)
4303 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4304
4305 def test_frag_out_of_order_dont_translate(self):
4306 """ NAT44 don't translate fragments arriving out of order """
4307 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4308 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4309 is_inside=0)
4310 self.vapi.nat44_forwarding_enable_disable(enable=True)
4311 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4312
4313 def test_frag_in_order_in_plus_out(self):
4314 """ in+out interface fragments in order """
4315 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4316 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4317 is_inside=0)
4318 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4319 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4320 is_inside=0)
4321
4322 self.server = self.pg1.remote_hosts[0]
4323
4324 self.server_in_addr = self.server.ip4
4325 self.server_out_addr = '11.11.11.11'
4326 self.server_in_port = random.randint(1025, 65535)
4327 self.server_out_port = random.randint(1025, 65535)
4328
4329 self.nat44_add_address(self.server_out_addr)
4330
4331 # add static mappings for server
4332 self.nat44_add_static_mapping(self.server_in_addr,
4333 self.server_out_addr,
4334 self.server_in_port,
4335 self.server_out_port,
4336 proto=IP_PROTOS.tcp)
4337 self.nat44_add_static_mapping(self.server_in_addr,
4338 self.server_out_addr,
4339 self.server_in_port,
4340 self.server_out_port,
4341 proto=IP_PROTOS.udp)
4342 self.nat44_add_static_mapping(self.server_in_addr,
4343 self.server_out_addr,
4344 proto=IP_PROTOS.icmp)
4345
4346 self.vapi.nat_set_reass(timeout=10)
4347
4348 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4349 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4350 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4351
4352 def test_frag_out_of_order_in_plus_out(self):
4353 """ in+out interface fragments out of order """
4354 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4355 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4356 is_inside=0)
4357 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4358 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4359 is_inside=0)
4360
4361 self.server = self.pg1.remote_hosts[0]
4362
4363 self.server_in_addr = self.server.ip4
4364 self.server_out_addr = '11.11.11.11'
4365 self.server_in_port = random.randint(1025, 65535)
4366 self.server_out_port = random.randint(1025, 65535)
4367
4368 self.nat44_add_address(self.server_out_addr)
4369
4370 # add static mappings for server
4371 self.nat44_add_static_mapping(self.server_in_addr,
4372 self.server_out_addr,
4373 self.server_in_port,
4374 self.server_out_port,
4375 proto=IP_PROTOS.tcp)
4376 self.nat44_add_static_mapping(self.server_in_addr,
4377 self.server_out_addr,
4378 self.server_in_port,
4379 self.server_out_port,
4380 proto=IP_PROTOS.udp)
4381 self.nat44_add_static_mapping(self.server_in_addr,
4382 self.server_out_addr,
4383 proto=IP_PROTOS.icmp)
4384
4385 self.vapi.nat_set_reass(timeout=10)
4386
4387 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4388 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4389 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4390
4391 def test_reass_hairpinning(self):
4392 """ NAT44 fragments hairpinning """
4393 self.server = self.pg0.remote_hosts[1]
4394 self.host_in_port = random.randint(1025, 65535)
4395 self.server_in_port = random.randint(1025, 65535)
4396 self.server_out_port = random.randint(1025, 65535)
4397
4398 self.nat44_add_address(self.nat_addr)
4399 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4400 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4401 is_inside=0)
4402 # add static mapping for server
4403 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4404 self.server_in_port,
4405 self.server_out_port,
4406 proto=IP_PROTOS.tcp)
4407 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4408 self.server_in_port,
4409 self.server_out_port,
4410 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004411 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004412
4413 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4414 self.reass_hairpinning(proto=IP_PROTOS.udp)
4415 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4416
Matus Fabiana6110b62018-06-13 05:39:07 -07004417 def test_dynamic(self):
4418 """ NAT44 dynamic translation test """
4419
4420 self.nat44_add_address(self.nat_addr)
4421 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4422 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4423 is_inside=0)
4424
Matus Fabian69ce30d2018-08-22 01:27:10 -07004425 nat_config = self.vapi.nat_show_config()
4426 self.assertEqual(1, nat_config.endpoint_dependent)
4427
Matus Fabiana6110b62018-06-13 05:39:07 -07004428 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004429 tcpn = self.statistics.get_counter(
4430 '/err/nat44-ed-in2out-slowpath/TCP packets')
4431 udpn = self.statistics.get_counter(
4432 '/err/nat44-ed-in2out-slowpath/UDP packets')
4433 icmpn = self.statistics.get_counter(
4434 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4435 totaln = self.statistics.get_counter(
4436 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4437
Matus Fabiana6110b62018-06-13 05:39:07 -07004438 pkts = self.create_stream_in(self.pg0, self.pg1)
4439 self.pg0.add_stream(pkts)
4440 self.pg_enable_capture(self.pg_interfaces)
4441 self.pg_start()
4442 capture = self.pg1.get_capture(len(pkts))
4443 self.verify_capture_out(capture)
4444
Matus Fabiana5e73762018-12-14 01:55:16 -08004445 err = self.statistics.get_counter(
4446 '/err/nat44-ed-in2out-slowpath/TCP packets')
4447 self.assertEqual(err - tcpn, 1)
4448 err = self.statistics.get_counter(
4449 '/err/nat44-ed-in2out-slowpath/UDP packets')
4450 self.assertEqual(err - udpn, 1)
4451 err = self.statistics.get_counter(
4452 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4453 self.assertEqual(err - icmpn, 1)
4454 err = self.statistics.get_counter(
4455 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4456 self.assertEqual(err - totaln, 3)
4457
Matus Fabiana6110b62018-06-13 05:39:07 -07004458 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004459 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4460 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4461 icmpn = self.statistics.get_counter(
4462 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4463 totaln = self.statistics.get_counter(
4464 '/err/nat44-ed-out2in/good out2in packets processed')
4465
Matus Fabiana6110b62018-06-13 05:39:07 -07004466 pkts = self.create_stream_out(self.pg1)
4467 self.pg1.add_stream(pkts)
4468 self.pg_enable_capture(self.pg_interfaces)
4469 self.pg_start()
4470 capture = self.pg0.get_capture(len(pkts))
4471 self.verify_capture_in(capture, self.pg0)
4472
Matus Fabiana5e73762018-12-14 01:55:16 -08004473 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4474 self.assertEqual(err - tcpn, 1)
4475 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4476 self.assertEqual(err - udpn, 1)
4477 err = self.statistics.get_counter(
4478 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4479 self.assertEqual(err - icmpn, 1)
4480 err = self.statistics.get_counter(
4481 '/err/nat44-ed-out2in/good out2in packets processed')
4482 self.assertEqual(err - totaln, 2)
4483
Matus Fabianfd0d5082018-12-18 01:08:51 -08004484 users = self.statistics.get_counter('/nat44/total-users')
4485 self.assertEqual(users[0][0], 1)
4486 sessions = self.statistics.get_counter('/nat44/total-sessions')
4487 self.assertEqual(sessions[0][0], 3)
4488
Matus Fabiana6110b62018-06-13 05:39:07 -07004489 def test_forwarding(self):
4490 """ NAT44 forwarding test """
4491
4492 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4493 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4494 is_inside=0)
4495 self.vapi.nat44_forwarding_enable_disable(1)
4496
4497 real_ip = self.pg0.remote_ip4n
4498 alias_ip = self.nat_addr_n
4499 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4500 external_ip=alias_ip)
4501
4502 try:
4503 # in2out - static mapping match
4504
4505 pkts = self.create_stream_out(self.pg1)
4506 self.pg1.add_stream(pkts)
4507 self.pg_enable_capture(self.pg_interfaces)
4508 self.pg_start()
4509 capture = self.pg0.get_capture(len(pkts))
4510 self.verify_capture_in(capture, self.pg0)
4511
4512 pkts = self.create_stream_in(self.pg0, self.pg1)
4513 self.pg0.add_stream(pkts)
4514 self.pg_enable_capture(self.pg_interfaces)
4515 self.pg_start()
4516 capture = self.pg1.get_capture(len(pkts))
4517 self.verify_capture_out(capture, same_port=True)
4518
4519 # in2out - no static mapping match
4520
4521 host0 = self.pg0.remote_hosts[0]
4522 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4523 try:
4524 pkts = self.create_stream_out(self.pg1,
4525 dst_ip=self.pg0.remote_ip4,
4526 use_inside_ports=True)
4527 self.pg1.add_stream(pkts)
4528 self.pg_enable_capture(self.pg_interfaces)
4529 self.pg_start()
4530 capture = self.pg0.get_capture(len(pkts))
4531 self.verify_capture_in(capture, self.pg0)
4532
4533 pkts = self.create_stream_in(self.pg0, self.pg1)
4534 self.pg0.add_stream(pkts)
4535 self.pg_enable_capture(self.pg_interfaces)
4536 self.pg_start()
4537 capture = self.pg1.get_capture(len(pkts))
4538 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4539 same_port=True)
4540 finally:
4541 self.pg0.remote_hosts[0] = host0
4542
4543 user = self.pg0.remote_hosts[1]
4544 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4545 self.assertEqual(len(sessions), 3)
4546 self.assertTrue(sessions[0].ext_host_valid)
4547 self.vapi.nat44_del_session(
4548 sessions[0].inside_ip_address,
4549 sessions[0].inside_port,
4550 sessions[0].protocol,
4551 ext_host_address=sessions[0].ext_host_address,
4552 ext_host_port=sessions[0].ext_host_port)
4553 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4554 self.assertEqual(len(sessions), 2)
4555
4556 finally:
4557 self.vapi.nat44_forwarding_enable_disable(0)
4558 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4559 external_ip=alias_ip,
4560 is_add=0)
4561
4562 def test_static_lb(self):
4563 """ NAT44 local service load balancing """
4564 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4565 external_port = 80
4566 local_port = 8080
4567 server1 = self.pg0.remote_hosts[0]
4568 server2 = self.pg0.remote_hosts[1]
4569
4570 locals = [{'addr': server1.ip4n,
4571 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004572 'probability': 70,
4573 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004574 {'addr': server2.ip4n,
4575 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004576 'probability': 30,
4577 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004578
4579 self.nat44_add_address(self.nat_addr)
4580 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4581 external_port,
4582 IP_PROTOS.tcp,
4583 local_num=len(locals),
4584 locals=locals)
4585 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4586 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4587 is_inside=0)
4588
4589 # from client to service
4590 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4591 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4592 TCP(sport=12345, dport=external_port))
4593 self.pg1.add_stream(p)
4594 self.pg_enable_capture(self.pg_interfaces)
4595 self.pg_start()
4596 capture = self.pg0.get_capture(1)
4597 p = capture[0]
4598 server = None
4599 try:
4600 ip = p[IP]
4601 tcp = p[TCP]
4602 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4603 if ip.dst == server1.ip4:
4604 server = server1
4605 else:
4606 server = server2
4607 self.assertEqual(tcp.dport, local_port)
4608 self.assert_packet_checksums_valid(p)
4609 except:
4610 self.logger.error(ppp("Unexpected or invalid packet:", p))
4611 raise
4612
4613 # from service back to client
4614 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4615 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4616 TCP(sport=local_port, dport=12345))
4617 self.pg0.add_stream(p)
4618 self.pg_enable_capture(self.pg_interfaces)
4619 self.pg_start()
4620 capture = self.pg1.get_capture(1)
4621 p = capture[0]
4622 try:
4623 ip = p[IP]
4624 tcp = p[TCP]
4625 self.assertEqual(ip.src, self.nat_addr)
4626 self.assertEqual(tcp.sport, external_port)
4627 self.assert_packet_checksums_valid(p)
4628 except:
4629 self.logger.error(ppp("Unexpected or invalid packet:", p))
4630 raise
4631
4632 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4633 self.assertEqual(len(sessions), 1)
4634 self.assertTrue(sessions[0].ext_host_valid)
4635 self.vapi.nat44_del_session(
4636 sessions[0].inside_ip_address,
4637 sessions[0].inside_port,
4638 sessions[0].protocol,
4639 ext_host_address=sessions[0].ext_host_address,
4640 ext_host_port=sessions[0].ext_host_port)
4641 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4642 self.assertEqual(len(sessions), 0)
4643
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004644 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004645 def test_static_lb_multi_clients(self):
4646 """ NAT44 local service load balancing - multiple clients"""
4647
4648 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4649 external_port = 80
4650 local_port = 8080
4651 server1 = self.pg0.remote_hosts[0]
4652 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004653 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004654
4655 locals = [{'addr': server1.ip4n,
4656 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004657 'probability': 90,
4658 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004659 {'addr': server2.ip4n,
4660 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004661 'probability': 10,
4662 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004663
4664 self.nat44_add_address(self.nat_addr)
4665 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4666 external_port,
4667 IP_PROTOS.tcp,
4668 local_num=len(locals),
4669 locals=locals)
4670 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4671 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4672 is_inside=0)
4673
4674 server1_n = 0
4675 server2_n = 0
4676 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4677 pkts = []
4678 for client in clients:
4679 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4680 IP(src=client, dst=self.nat_addr) /
4681 TCP(sport=12345, dport=external_port))
4682 pkts.append(p)
4683 self.pg1.add_stream(pkts)
4684 self.pg_enable_capture(self.pg_interfaces)
4685 self.pg_start()
4686 capture = self.pg0.get_capture(len(pkts))
4687 for p in capture:
4688 if p[IP].dst == server1.ip4:
4689 server1_n += 1
4690 else:
4691 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004692 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004693
Matus Fabianb6865082018-12-06 03:11:09 -08004694 # add new back-end
4695 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4696 external_port,
4697 server3.ip4n,
4698 local_port,
4699 IP_PROTOS.tcp,
4700 20)
4701 server1_n = 0
4702 server2_n = 0
4703 server3_n = 0
4704 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4705 pkts = []
4706 for client in clients:
4707 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4708 IP(src=client, dst=self.nat_addr) /
4709 TCP(sport=12346, dport=external_port))
4710 pkts.append(p)
4711 self.assertGreater(len(pkts), 0)
4712 self.pg1.add_stream(pkts)
4713 self.pg_enable_capture(self.pg_interfaces)
4714 self.pg_start()
4715 capture = self.pg0.get_capture(len(pkts))
4716 for p in capture:
4717 if p[IP].dst == server1.ip4:
4718 server1_n += 1
4719 elif p[IP].dst == server2.ip4:
4720 server2_n += 1
4721 else:
4722 server3_n += 1
4723 self.assertGreater(server1_n, 0)
4724 self.assertGreater(server2_n, 0)
4725 self.assertGreater(server3_n, 0)
4726
4727 # remove one back-end
4728 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4729 external_port,
4730 server2.ip4n,
4731 local_port,
4732 IP_PROTOS.tcp,
4733 10,
4734 is_add=0)
4735 server1_n = 0
4736 server2_n = 0
4737 server3_n = 0
4738 self.pg1.add_stream(pkts)
4739 self.pg_enable_capture(self.pg_interfaces)
4740 self.pg_start()
4741 capture = self.pg0.get_capture(len(pkts))
4742 for p in capture:
4743 if p[IP].dst == server1.ip4:
4744 server1_n += 1
4745 elif p[IP].dst == server2.ip4:
4746 server2_n += 1
4747 else:
4748 server3_n += 1
4749 self.assertGreater(server1_n, 0)
4750 self.assertEqual(server2_n, 0)
4751 self.assertGreater(server3_n, 0)
4752
Matus Fabiana6110b62018-06-13 05:39:07 -07004753 def test_static_lb_2(self):
4754 """ NAT44 local service load balancing (asymmetrical rule) """
4755 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4756 external_port = 80
4757 local_port = 8080
4758 server1 = self.pg0.remote_hosts[0]
4759 server2 = self.pg0.remote_hosts[1]
4760
4761 locals = [{'addr': server1.ip4n,
4762 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004763 'probability': 70,
4764 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004765 {'addr': server2.ip4n,
4766 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004767 'probability': 30,
4768 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004769
4770 self.vapi.nat44_forwarding_enable_disable(1)
4771 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4772 external_port,
4773 IP_PROTOS.tcp,
4774 out2in_only=1,
4775 local_num=len(locals),
4776 locals=locals)
4777 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4778 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4779 is_inside=0)
4780
4781 # from client to service
4782 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4783 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4784 TCP(sport=12345, dport=external_port))
4785 self.pg1.add_stream(p)
4786 self.pg_enable_capture(self.pg_interfaces)
4787 self.pg_start()
4788 capture = self.pg0.get_capture(1)
4789 p = capture[0]
4790 server = None
4791 try:
4792 ip = p[IP]
4793 tcp = p[TCP]
4794 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4795 if ip.dst == server1.ip4:
4796 server = server1
4797 else:
4798 server = server2
4799 self.assertEqual(tcp.dport, local_port)
4800 self.assert_packet_checksums_valid(p)
4801 except:
4802 self.logger.error(ppp("Unexpected or invalid packet:", p))
4803 raise
4804
4805 # from service back to client
4806 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4807 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4808 TCP(sport=local_port, dport=12345))
4809 self.pg0.add_stream(p)
4810 self.pg_enable_capture(self.pg_interfaces)
4811 self.pg_start()
4812 capture = self.pg1.get_capture(1)
4813 p = capture[0]
4814 try:
4815 ip = p[IP]
4816 tcp = p[TCP]
4817 self.assertEqual(ip.src, self.nat_addr)
4818 self.assertEqual(tcp.sport, external_port)
4819 self.assert_packet_checksums_valid(p)
4820 except:
4821 self.logger.error(ppp("Unexpected or invalid packet:", p))
4822 raise
4823
4824 # from client to server (no translation)
4825 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4826 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4827 TCP(sport=12346, dport=local_port))
4828 self.pg1.add_stream(p)
4829 self.pg_enable_capture(self.pg_interfaces)
4830 self.pg_start()
4831 capture = self.pg0.get_capture(1)
4832 p = capture[0]
4833 server = None
4834 try:
4835 ip = p[IP]
4836 tcp = p[TCP]
4837 self.assertEqual(ip.dst, server1.ip4)
4838 self.assertEqual(tcp.dport, local_port)
4839 self.assert_packet_checksums_valid(p)
4840 except:
4841 self.logger.error(ppp("Unexpected or invalid packet:", p))
4842 raise
4843
4844 # from service back to client (no translation)
4845 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4846 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4847 TCP(sport=local_port, dport=12346))
4848 self.pg0.add_stream(p)
4849 self.pg_enable_capture(self.pg_interfaces)
4850 self.pg_start()
4851 capture = self.pg1.get_capture(1)
4852 p = capture[0]
4853 try:
4854 ip = p[IP]
4855 tcp = p[TCP]
4856 self.assertEqual(ip.src, server1.ip4)
4857 self.assertEqual(tcp.sport, local_port)
4858 self.assert_packet_checksums_valid(p)
4859 except:
4860 self.logger.error(ppp("Unexpected or invalid packet:", p))
4861 raise
4862
Matus Fabianea5b5be2018-09-03 05:02:23 -07004863 def test_lb_affinity(self):
4864 """ NAT44 local service load balancing affinity """
4865 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4866 external_port = 80
4867 local_port = 8080
4868 server1 = self.pg0.remote_hosts[0]
4869 server2 = self.pg0.remote_hosts[1]
4870
4871 locals = [{'addr': server1.ip4n,
4872 'port': local_port,
4873 'probability': 50,
4874 'vrf_id': 0},
4875 {'addr': server2.ip4n,
4876 'port': local_port,
4877 'probability': 50,
4878 'vrf_id': 0}]
4879
4880 self.nat44_add_address(self.nat_addr)
4881 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4882 external_port,
4883 IP_PROTOS.tcp,
4884 affinity=10800,
4885 local_num=len(locals),
4886 locals=locals)
4887 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4888 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4889 is_inside=0)
4890
4891 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4892 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4893 TCP(sport=1025, dport=external_port))
4894 self.pg1.add_stream(p)
4895 self.pg_enable_capture(self.pg_interfaces)
4896 self.pg_start()
4897 capture = self.pg0.get_capture(1)
4898 backend = capture[0][IP].dst
4899
4900 sessions = self.vapi.nat44_user_session_dump(
4901 socket.inet_pton(socket.AF_INET, backend), 0)
4902 self.assertEqual(len(sessions), 1)
4903 self.assertTrue(sessions[0].ext_host_valid)
4904 self.vapi.nat44_del_session(
4905 sessions[0].inside_ip_address,
4906 sessions[0].inside_port,
4907 sessions[0].protocol,
4908 ext_host_address=sessions[0].ext_host_address,
4909 ext_host_port=sessions[0].ext_host_port)
4910
4911 pkts = []
4912 for port in range(1030, 1100):
4913 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4914 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4915 TCP(sport=port, dport=external_port))
4916 pkts.append(p)
4917 self.pg1.add_stream(pkts)
4918 self.pg_enable_capture(self.pg_interfaces)
4919 self.pg_start()
4920 capture = self.pg0.get_capture(len(pkts))
4921 for p in capture:
4922 self.assertEqual(p[IP].dst, backend)
4923
Matus Fabiana6110b62018-06-13 05:39:07 -07004924 def test_unknown_proto(self):
4925 """ NAT44 translate packet with unknown protocol """
4926 self.nat44_add_address(self.nat_addr)
4927 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4928 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4929 is_inside=0)
4930
4931 # in2out
4932 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4933 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4934 TCP(sport=self.tcp_port_in, dport=20))
4935 self.pg0.add_stream(p)
4936 self.pg_enable_capture(self.pg_interfaces)
4937 self.pg_start()
4938 p = self.pg1.get_capture(1)
4939
4940 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4941 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4942 GRE() /
4943 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4944 TCP(sport=1234, dport=1234))
4945 self.pg0.add_stream(p)
4946 self.pg_enable_capture(self.pg_interfaces)
4947 self.pg_start()
4948 p = self.pg1.get_capture(1)
4949 packet = p[0]
4950 try:
4951 self.assertEqual(packet[IP].src, self.nat_addr)
4952 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004953 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004954 self.assert_packet_checksums_valid(packet)
4955 except:
4956 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4957 raise
4958
4959 # out2in
4960 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4961 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4962 GRE() /
4963 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4964 TCP(sport=1234, dport=1234))
4965 self.pg1.add_stream(p)
4966 self.pg_enable_capture(self.pg_interfaces)
4967 self.pg_start()
4968 p = self.pg0.get_capture(1)
4969 packet = p[0]
4970 try:
4971 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4972 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004973 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004974 self.assert_packet_checksums_valid(packet)
4975 except:
4976 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4977 raise
4978
4979 def test_hairpinning_unknown_proto(self):
4980 """ NAT44 translate packet with unknown protocol - hairpinning """
4981 host = self.pg0.remote_hosts[0]
4982 server = self.pg0.remote_hosts[1]
4983 host_in_port = 1234
4984 server_out_port = 8765
4985 server_nat_ip = "10.0.0.11"
4986
4987 self.nat44_add_address(self.nat_addr)
4988 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4989 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4990 is_inside=0)
4991
4992 # add static mapping for server
4993 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4994
4995 # host to server
4996 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4997 IP(src=host.ip4, dst=server_nat_ip) /
4998 TCP(sport=host_in_port, dport=server_out_port))
4999 self.pg0.add_stream(p)
5000 self.pg_enable_capture(self.pg_interfaces)
5001 self.pg_start()
5002 self.pg0.get_capture(1)
5003
5004 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5005 IP(src=host.ip4, dst=server_nat_ip) /
5006 GRE() /
5007 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5008 TCP(sport=1234, dport=1234))
5009 self.pg0.add_stream(p)
5010 self.pg_enable_capture(self.pg_interfaces)
5011 self.pg_start()
5012 p = self.pg0.get_capture(1)
5013 packet = p[0]
5014 try:
5015 self.assertEqual(packet[IP].src, self.nat_addr)
5016 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005017 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005018 self.assert_packet_checksums_valid(packet)
5019 except:
5020 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5021 raise
5022
5023 # server to host
5024 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5025 IP(src=server.ip4, dst=self.nat_addr) /
5026 GRE() /
5027 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5028 TCP(sport=1234, dport=1234))
5029 self.pg0.add_stream(p)
5030 self.pg_enable_capture(self.pg_interfaces)
5031 self.pg_start()
5032 p = self.pg0.get_capture(1)
5033 packet = p[0]
5034 try:
5035 self.assertEqual(packet[IP].src, server_nat_ip)
5036 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005037 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005038 self.assert_packet_checksums_valid(packet)
5039 except:
5040 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5041 raise
5042
5043 def test_output_feature_and_service(self):
5044 """ NAT44 interface output feature and services """
5045 external_addr = '1.2.3.4'
5046 external_port = 80
5047 local_port = 8080
5048
5049 self.vapi.nat44_forwarding_enable_disable(1)
5050 self.nat44_add_address(self.nat_addr)
5051 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
5052 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5053 local_port, external_port,
5054 proto=IP_PROTOS.tcp, out2in_only=1)
5055 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5056 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5057 is_inside=0)
5058 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5059 is_inside=0)
5060
5061 # from client to service
5062 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5063 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5064 TCP(sport=12345, dport=external_port))
5065 self.pg1.add_stream(p)
5066 self.pg_enable_capture(self.pg_interfaces)
5067 self.pg_start()
5068 capture = self.pg0.get_capture(1)
5069 p = capture[0]
5070 try:
5071 ip = p[IP]
5072 tcp = p[TCP]
5073 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5074 self.assertEqual(tcp.dport, local_port)
5075 self.assert_packet_checksums_valid(p)
5076 except:
5077 self.logger.error(ppp("Unexpected or invalid packet:", p))
5078 raise
5079
5080 # from service back to client
5081 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5082 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5083 TCP(sport=local_port, dport=12345))
5084 self.pg0.add_stream(p)
5085 self.pg_enable_capture(self.pg_interfaces)
5086 self.pg_start()
5087 capture = self.pg1.get_capture(1)
5088 p = capture[0]
5089 try:
5090 ip = p[IP]
5091 tcp = p[TCP]
5092 self.assertEqual(ip.src, external_addr)
5093 self.assertEqual(tcp.sport, external_port)
5094 self.assert_packet_checksums_valid(p)
5095 except:
5096 self.logger.error(ppp("Unexpected or invalid packet:", p))
5097 raise
5098
5099 # from local network host to external network
5100 pkts = self.create_stream_in(self.pg0, self.pg1)
5101 self.pg0.add_stream(pkts)
5102 self.pg_enable_capture(self.pg_interfaces)
5103 self.pg_start()
5104 capture = self.pg1.get_capture(len(pkts))
5105 self.verify_capture_out(capture)
5106 pkts = self.create_stream_in(self.pg0, self.pg1)
5107 self.pg0.add_stream(pkts)
5108 self.pg_enable_capture(self.pg_interfaces)
5109 self.pg_start()
5110 capture = self.pg1.get_capture(len(pkts))
5111 self.verify_capture_out(capture)
5112
5113 # from external network back to local network host
5114 pkts = self.create_stream_out(self.pg1)
5115 self.pg1.add_stream(pkts)
5116 self.pg_enable_capture(self.pg_interfaces)
5117 self.pg_start()
5118 capture = self.pg0.get_capture(len(pkts))
5119 self.verify_capture_in(capture, self.pg0)
5120
5121 def test_output_feature_and_service2(self):
5122 """ NAT44 interface output feature and service host direct access """
5123 self.vapi.nat44_forwarding_enable_disable(1)
5124 self.nat44_add_address(self.nat_addr)
5125 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5126 is_inside=0)
5127
5128 # session initiaded from service host - translate
5129 pkts = self.create_stream_in(self.pg0, self.pg1)
5130 self.pg0.add_stream(pkts)
5131 self.pg_enable_capture(self.pg_interfaces)
5132 self.pg_start()
5133 capture = self.pg1.get_capture(len(pkts))
5134 self.verify_capture_out(capture)
5135
5136 pkts = self.create_stream_out(self.pg1)
5137 self.pg1.add_stream(pkts)
5138 self.pg_enable_capture(self.pg_interfaces)
5139 self.pg_start()
5140 capture = self.pg0.get_capture(len(pkts))
5141 self.verify_capture_in(capture, self.pg0)
5142
5143 # session initiaded from remote host - do not translate
5144 self.tcp_port_in = 60303
5145 self.udp_port_in = 60304
5146 self.icmp_id_in = 60305
5147 pkts = self.create_stream_out(self.pg1,
5148 self.pg0.remote_ip4,
5149 use_inside_ports=True)
5150 self.pg1.add_stream(pkts)
5151 self.pg_enable_capture(self.pg_interfaces)
5152 self.pg_start()
5153 capture = self.pg0.get_capture(len(pkts))
5154 self.verify_capture_in(capture, self.pg0)
5155
5156 pkts = self.create_stream_in(self.pg0, self.pg1)
5157 self.pg0.add_stream(pkts)
5158 self.pg_enable_capture(self.pg_interfaces)
5159 self.pg_start()
5160 capture = self.pg1.get_capture(len(pkts))
5161 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5162 same_port=True)
5163
5164 def test_output_feature_and_service3(self):
5165 """ NAT44 interface output feature and DST NAT """
5166 external_addr = '1.2.3.4'
5167 external_port = 80
5168 local_port = 8080
5169
5170 self.vapi.nat44_forwarding_enable_disable(1)
5171 self.nat44_add_address(self.nat_addr)
5172 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5173 local_port, external_port,
5174 proto=IP_PROTOS.tcp, out2in_only=1)
5175 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5176 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5177 is_inside=0)
5178 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5179 is_inside=0)
5180
5181 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5182 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5183 TCP(sport=12345, dport=external_port))
5184 self.pg0.add_stream(p)
5185 self.pg_enable_capture(self.pg_interfaces)
5186 self.pg_start()
5187 capture = self.pg1.get_capture(1)
5188 p = capture[0]
5189 try:
5190 ip = p[IP]
5191 tcp = p[TCP]
5192 self.assertEqual(ip.src, self.pg0.remote_ip4)
5193 self.assertEqual(tcp.sport, 12345)
5194 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5195 self.assertEqual(tcp.dport, local_port)
5196 self.assert_packet_checksums_valid(p)
5197 except:
5198 self.logger.error(ppp("Unexpected or invalid packet:", p))
5199 raise
5200
5201 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5202 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5203 TCP(sport=local_port, dport=12345))
5204 self.pg1.add_stream(p)
5205 self.pg_enable_capture(self.pg_interfaces)
5206 self.pg_start()
5207 capture = self.pg0.get_capture(1)
5208 p = capture[0]
5209 try:
5210 ip = p[IP]
5211 tcp = p[TCP]
5212 self.assertEqual(ip.src, external_addr)
5213 self.assertEqual(tcp.sport, external_port)
5214 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5215 self.assertEqual(tcp.dport, 12345)
5216 self.assert_packet_checksums_valid(p)
5217 except:
5218 self.logger.error(ppp("Unexpected or invalid packet:", p))
5219 raise
5220
Matus Fabian182e37e2018-08-14 04:21:26 -07005221 def test_next_src_nat(self):
5222 """ On way back forward packet to nat44-in2out node. """
5223 twice_nat_addr = '10.0.1.3'
5224 external_port = 80
5225 local_port = 8080
5226 post_twice_nat_port = 0
5227
5228 self.vapi.nat44_forwarding_enable_disable(1)
5229 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5230 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5231 local_port, external_port,
5232 proto=IP_PROTOS.tcp, out2in_only=1,
5233 self_twice_nat=1, vrf_id=1)
5234 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5235 is_inside=0)
5236
5237 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5238 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5239 TCP(sport=12345, dport=external_port))
5240 self.pg6.add_stream(p)
5241 self.pg_enable_capture(self.pg_interfaces)
5242 self.pg_start()
5243 capture = self.pg6.get_capture(1)
5244 p = capture[0]
5245 try:
5246 ip = p[IP]
5247 tcp = p[TCP]
5248 self.assertEqual(ip.src, twice_nat_addr)
5249 self.assertNotEqual(tcp.sport, 12345)
5250 post_twice_nat_port = tcp.sport
5251 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5252 self.assertEqual(tcp.dport, local_port)
5253 self.assert_packet_checksums_valid(p)
5254 except:
5255 self.logger.error(ppp("Unexpected or invalid packet:", p))
5256 raise
5257
5258 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5259 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5260 TCP(sport=local_port, dport=post_twice_nat_port))
5261 self.pg6.add_stream(p)
5262 self.pg_enable_capture(self.pg_interfaces)
5263 self.pg_start()
5264 capture = self.pg6.get_capture(1)
5265 p = capture[0]
5266 try:
5267 ip = p[IP]
5268 tcp = p[TCP]
5269 self.assertEqual(ip.src, self.pg1.remote_ip4)
5270 self.assertEqual(tcp.sport, external_port)
5271 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5272 self.assertEqual(tcp.dport, 12345)
5273 self.assert_packet_checksums_valid(p)
5274 except:
5275 self.logger.error(ppp("Unexpected or invalid packet:", p))
5276 raise
5277
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005278 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5279 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005280 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005281
Matus Fabianb932d262017-12-18 05:38:24 -08005282 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005283 if lb:
5284 if not same_pg:
5285 port_in1 = port_in
5286 port_in2 = port_in
5287 else:
5288 port_in1 = port_in+1
5289 port_in2 = port_in+2
5290
Matus Fabianb932d262017-12-18 05:38:24 -08005291 port_out = 80
5292 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005293
5294 server1 = self.pg0.remote_hosts[0]
5295 server2 = self.pg0.remote_hosts[1]
5296 if lb and same_pg:
5297 server2 = server1
5298 if not lb:
5299 server = server1
5300
5301 pg0 = self.pg0
5302 if same_pg:
5303 pg1 = self.pg0
5304 else:
5305 pg1 = self.pg1
5306
5307 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5308 client_id == 1)
5309
Matus Fabianb932d262017-12-18 05:38:24 -08005310 self.nat44_add_address(self.nat_addr)
5311 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005312 if not lb:
5313 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5314 port_in, port_out,
5315 proto=IP_PROTOS.tcp,
5316 twice_nat=int(not self_twice_nat),
5317 self_twice_nat=int(self_twice_nat))
5318 else:
5319 locals = [{'addr': server1.ip4n,
5320 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005321 'probability': 50,
5322 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005323 {'addr': server2.ip4n,
5324 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005325 'probability': 50,
5326 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005327 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
5328 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
5329 port_out,
5330 IP_PROTOS.tcp,
5331 twice_nat=int(
5332 not self_twice_nat),
5333 self_twice_nat=int(
5334 self_twice_nat),
5335 local_num=len(locals),
5336 locals=locals)
5337 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
5338 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08005339 is_inside=0)
5340
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005341 if same_pg:
5342 if not lb:
5343 client = server
5344 else:
5345 assert client_id is not None
5346 if client_id == 1:
5347 client = self.pg0.remote_hosts[0]
5348 elif client_id == 2:
5349 client = self.pg0.remote_hosts[1]
5350 else:
5351 client = pg1.remote_hosts[0]
5352 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5353 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005354 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005355 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005356 self.pg_enable_capture(self.pg_interfaces)
5357 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005358 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005359 p = capture[0]
5360 try:
5361 ip = p[IP]
5362 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005363 if lb:
5364 if ip.dst == server1.ip4:
5365 server = server1
5366 port_in = port_in1
5367 else:
5368 server = server2
5369 port_in = port_in2
5370 self.assertEqual(ip.dst, server.ip4)
5371 if lb and same_pg:
5372 self.assertIn(tcp.dport, [port_in1, port_in2])
5373 else:
5374 self.assertEqual(tcp.dport, port_in)
5375 if eh_translate:
5376 self.assertEqual(ip.src, twice_nat_addr)
5377 self.assertNotEqual(tcp.sport, eh_port_out)
5378 else:
5379 self.assertEqual(ip.src, client.ip4)
5380 self.assertEqual(tcp.sport, eh_port_out)
5381 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005382 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005383 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005384 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005385 except:
5386 self.logger.error(ppp("Unexpected or invalid packet:", p))
5387 raise
5388
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005389 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5390 IP(src=server.ip4, dst=eh_addr_in) /
5391 TCP(sport=saved_port_in, dport=eh_port_in))
5392 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005393 self.pg_enable_capture(self.pg_interfaces)
5394 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005395 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005396 p = capture[0]
5397 try:
5398 ip = p[IP]
5399 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005400 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005401 self.assertEqual(ip.src, self.nat_addr)
5402 self.assertEqual(tcp.dport, eh_port_out)
5403 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005404 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005405 except:
5406 self.logger.error(ppp("Unexpected or invalid packet:", p))
5407 raise
5408
Matus Fabian70a26ac2018-05-14 06:20:28 -07005409 if eh_translate:
5410 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5411 self.assertEqual(len(sessions), 1)
5412 self.assertTrue(sessions[0].ext_host_valid)
5413 self.assertTrue(sessions[0].is_twicenat)
5414 self.vapi.nat44_del_session(
5415 sessions[0].inside_ip_address,
5416 sessions[0].inside_port,
5417 sessions[0].protocol,
5418 ext_host_address=sessions[0].ext_host_nat_address,
5419 ext_host_port=sessions[0].ext_host_nat_port)
5420 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5421 self.assertEqual(len(sessions), 0)
5422
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005423 def test_twice_nat(self):
5424 """ Twice NAT44 """
5425 self.twice_nat_common()
5426
5427 def test_self_twice_nat_positive(self):
5428 """ Self Twice NAT44 (positive test) """
5429 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5430
5431 def test_self_twice_nat_negative(self):
5432 """ Self Twice NAT44 (negative test) """
5433 self.twice_nat_common(self_twice_nat=True)
5434
Matus Fabianb932d262017-12-18 05:38:24 -08005435 def test_twice_nat_lb(self):
5436 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005437 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005438
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005439 def test_self_twice_nat_lb_positive(self):
5440 """ Self Twice NAT44 local service load balancing (positive test) """
5441 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5442 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005443
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005444 def test_self_twice_nat_lb_negative(self):
5445 """ Self Twice NAT44 local service load balancing (negative test) """
5446 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5447 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005448
5449 def test_twice_nat_interface_addr(self):
5450 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07005451 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005452
5453 # no address in NAT pool
5454 adresses = self.vapi.nat44_address_dump()
5455 self.assertEqual(0, len(adresses))
5456
5457 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005458 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005459 adresses = self.vapi.nat44_address_dump()
5460 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07005461 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08005462 self.assertEqual(adresses[0].twice_nat, 1)
5463
5464 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005465 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005466 adresses = self.vapi.nat44_address_dump()
5467 self.assertEqual(0, len(adresses))
5468
Matus Fabian6c01dce2018-11-16 04:41:31 -08005469 def test_tcp_close(self):
5470 """ Close TCP session from inside network - output feature """
5471 self.vapi.nat44_forwarding_enable_disable(1)
5472 self.nat44_add_address(self.pg1.local_ip4)
5473 twice_nat_addr = '10.0.1.3'
5474 service_ip = '192.168.16.150'
5475 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5476 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5477 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5478 is_inside=0)
5479 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5480 is_inside=0)
5481 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5482 service_ip,
5483 80,
5484 80,
5485 proto=IP_PROTOS.tcp,
5486 out2in_only=1,
5487 twice_nat=1)
5488 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5489 start_sessnum = len(sessions)
5490
5491 # SYN packet out->in
5492 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5493 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5494 TCP(sport=33898, dport=80, flags="S"))
5495 self.pg1.add_stream(p)
5496 self.pg_enable_capture(self.pg_interfaces)
5497 self.pg_start()
5498 capture = self.pg0.get_capture(1)
5499 p = capture[0]
5500 tcp_port = p[TCP].sport
5501
5502 # SYN + ACK packet in->out
5503 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5504 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5505 TCP(sport=80, dport=tcp_port, flags="SA"))
5506 self.pg0.add_stream(p)
5507 self.pg_enable_capture(self.pg_interfaces)
5508 self.pg_start()
5509 self.pg1.get_capture(1)
5510
5511 # ACK packet out->in
5512 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5513 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5514 TCP(sport=33898, dport=80, flags="A"))
5515 self.pg1.add_stream(p)
5516 self.pg_enable_capture(self.pg_interfaces)
5517 self.pg_start()
5518 self.pg0.get_capture(1)
5519
5520 # FIN packet in -> out
5521 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5522 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5523 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5524 self.pg0.add_stream(p)
5525 self.pg_enable_capture(self.pg_interfaces)
5526 self.pg_start()
5527 self.pg1.get_capture(1)
5528
5529 # FIN+ACK packet out -> in
5530 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5531 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5532 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5533 self.pg1.add_stream(p)
5534 self.pg_enable_capture(self.pg_interfaces)
5535 self.pg_start()
5536 self.pg0.get_capture(1)
5537
5538 # ACK packet in -> out
5539 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5540 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5541 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5542 self.pg0.add_stream(p)
5543 self.pg_enable_capture(self.pg_interfaces)
5544 self.pg_start()
5545 self.pg1.get_capture(1)
5546
5547 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5548 0)
5549 self.assertEqual(len(sessions) - start_sessnum, 0)
5550
Matus Fabianebdf1902018-05-04 03:57:42 -07005551 def test_tcp_session_close_in(self):
5552 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005553 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005554 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005555 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5556 self.nat_addr,
5557 self.tcp_port_in,
5558 self.tcp_port_out,
5559 proto=IP_PROTOS.tcp,
5560 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005561 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5562 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5563 is_inside=0)
5564
5565 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5566 start_sessnum = len(sessions)
5567
5568 self.initiate_tcp_session(self.pg0, self.pg1)
5569
Matus Fabian229c1aa2018-05-28 04:09:52 -07005570 # FIN packet in -> out
5571 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5572 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5573 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5574 flags="FA", seq=100, ack=300))
5575 self.pg0.add_stream(p)
5576 self.pg_enable_capture(self.pg_interfaces)
5577 self.pg_start()
5578 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005579
Matus Fabian229c1aa2018-05-28 04:09:52 -07005580 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005581
Matus Fabian229c1aa2018-05-28 04:09:52 -07005582 # ACK packet out -> in
5583 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5584 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5585 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5586 flags="A", seq=300, ack=101))
5587 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005588
Matus Fabian229c1aa2018-05-28 04:09:52 -07005589 # FIN packet out -> in
5590 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5591 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5592 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5593 flags="FA", seq=300, ack=101))
5594 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005595
Matus Fabian229c1aa2018-05-28 04:09:52 -07005596 self.pg1.add_stream(pkts)
5597 self.pg_enable_capture(self.pg_interfaces)
5598 self.pg_start()
5599 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005600
Matus Fabian229c1aa2018-05-28 04:09:52 -07005601 # ACK packet in -> out
5602 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5603 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5604 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5605 flags="A", seq=101, ack=301))
5606 self.pg0.add_stream(p)
5607 self.pg_enable_capture(self.pg_interfaces)
5608 self.pg_start()
5609 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005610
Matus Fabian229c1aa2018-05-28 04:09:52 -07005611 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5612 0)
5613 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005614
5615 def test_tcp_session_close_out(self):
5616 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005617 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005618 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005619 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5620 self.nat_addr,
5621 self.tcp_port_in,
5622 self.tcp_port_out,
5623 proto=IP_PROTOS.tcp,
5624 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005625 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5626 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5627 is_inside=0)
5628
5629 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5630 start_sessnum = len(sessions)
5631
5632 self.initiate_tcp_session(self.pg0, self.pg1)
5633
Matus Fabian229c1aa2018-05-28 04:09:52 -07005634 # FIN packet out -> in
5635 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5636 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5637 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5638 flags="FA", seq=100, ack=300))
5639 self.pg1.add_stream(p)
5640 self.pg_enable_capture(self.pg_interfaces)
5641 self.pg_start()
5642 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005643
Matus Fabian229c1aa2018-05-28 04:09:52 -07005644 # FIN+ACK packet in -> out
5645 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5646 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5647 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5648 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005649
Matus Fabian229c1aa2018-05-28 04:09:52 -07005650 self.pg0.add_stream(p)
5651 self.pg_enable_capture(self.pg_interfaces)
5652 self.pg_start()
5653 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005654
Matus Fabian229c1aa2018-05-28 04:09:52 -07005655 # ACK packet out -> in
5656 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5657 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5658 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5659 flags="A", seq=101, ack=301))
5660 self.pg1.add_stream(p)
5661 self.pg_enable_capture(self.pg_interfaces)
5662 self.pg_start()
5663 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005664
Matus Fabian229c1aa2018-05-28 04:09:52 -07005665 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5666 0)
5667 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005668
5669 def test_tcp_session_close_simultaneous(self):
5670 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005671 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005672 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005673 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5674 self.nat_addr,
5675 self.tcp_port_in,
5676 self.tcp_port_out,
5677 proto=IP_PROTOS.tcp,
5678 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005679 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5680 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5681 is_inside=0)
5682
5683 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5684 start_sessnum = len(sessions)
5685
5686 self.initiate_tcp_session(self.pg0, self.pg1)
5687
Matus Fabian229c1aa2018-05-28 04:09:52 -07005688 # FIN packet in -> out
5689 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5690 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5691 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5692 flags="FA", seq=100, ack=300))
5693 self.pg0.add_stream(p)
5694 self.pg_enable_capture(self.pg_interfaces)
5695 self.pg_start()
5696 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005697
Matus Fabian229c1aa2018-05-28 04:09:52 -07005698 # FIN packet out -> in
5699 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5700 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5701 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5702 flags="FA", seq=300, ack=100))
5703 self.pg1.add_stream(p)
5704 self.pg_enable_capture(self.pg_interfaces)
5705 self.pg_start()
5706 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005707
Matus Fabian229c1aa2018-05-28 04:09:52 -07005708 # ACK packet in -> out
5709 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5710 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5711 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5712 flags="A", seq=101, ack=301))
5713 self.pg0.add_stream(p)
5714 self.pg_enable_capture(self.pg_interfaces)
5715 self.pg_start()
5716 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005717
Matus Fabian229c1aa2018-05-28 04:09:52 -07005718 # ACK packet out -> in
5719 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5720 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5721 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5722 flags="A", seq=301, ack=101))
5723 self.pg1.add_stream(p)
5724 self.pg_enable_capture(self.pg_interfaces)
5725 self.pg_start()
5726 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005727
Matus Fabian229c1aa2018-05-28 04:09:52 -07005728 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5729 0)
5730 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005731
Matus Fabiana6110b62018-06-13 05:39:07 -07005732 def test_one_armed_nat44_static(self):
5733 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5734 remote_host = self.pg4.remote_hosts[0]
5735 local_host = self.pg4.remote_hosts[1]
5736 external_port = 80
5737 local_port = 8080
5738 eh_port_in = 0
5739
5740 self.vapi.nat44_forwarding_enable_disable(1)
5741 self.nat44_add_address(self.nat_addr, twice_nat=1)
5742 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5743 local_port, external_port,
5744 proto=IP_PROTOS.tcp, out2in_only=1,
5745 twice_nat=1)
5746 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5747 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5748 is_inside=0)
5749
5750 # from client to service
5751 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5752 IP(src=remote_host.ip4, dst=self.nat_addr) /
5753 TCP(sport=12345, dport=external_port))
5754 self.pg4.add_stream(p)
5755 self.pg_enable_capture(self.pg_interfaces)
5756 self.pg_start()
5757 capture = self.pg4.get_capture(1)
5758 p = capture[0]
5759 try:
5760 ip = p[IP]
5761 tcp = p[TCP]
5762 self.assertEqual(ip.dst, local_host.ip4)
5763 self.assertEqual(ip.src, self.nat_addr)
5764 self.assertEqual(tcp.dport, local_port)
5765 self.assertNotEqual(tcp.sport, 12345)
5766 eh_port_in = tcp.sport
5767 self.assert_packet_checksums_valid(p)
5768 except:
5769 self.logger.error(ppp("Unexpected or invalid packet:", p))
5770 raise
5771
5772 # from service back to client
5773 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5774 IP(src=local_host.ip4, dst=self.nat_addr) /
5775 TCP(sport=local_port, dport=eh_port_in))
5776 self.pg4.add_stream(p)
5777 self.pg_enable_capture(self.pg_interfaces)
5778 self.pg_start()
5779 capture = self.pg4.get_capture(1)
5780 p = capture[0]
5781 try:
5782 ip = p[IP]
5783 tcp = p[TCP]
5784 self.assertEqual(ip.src, self.nat_addr)
5785 self.assertEqual(ip.dst, remote_host.ip4)
5786 self.assertEqual(tcp.sport, external_port)
5787 self.assertEqual(tcp.dport, 12345)
5788 self.assert_packet_checksums_valid(p)
5789 except:
5790 self.logger.error(ppp("Unexpected or invalid packet:", p))
5791 raise
5792
5793 def test_static_with_port_out2(self):
5794 """ 1:1 NAPT asymmetrical rule """
5795
5796 external_port = 80
5797 local_port = 8080
5798
5799 self.vapi.nat44_forwarding_enable_disable(1)
5800 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5801 local_port, external_port,
5802 proto=IP_PROTOS.tcp, out2in_only=1)
5803 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5804 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5805 is_inside=0)
5806
5807 # from client to service
5808 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5809 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5810 TCP(sport=12345, dport=external_port))
5811 self.pg1.add_stream(p)
5812 self.pg_enable_capture(self.pg_interfaces)
5813 self.pg_start()
5814 capture = self.pg0.get_capture(1)
5815 p = capture[0]
5816 try:
5817 ip = p[IP]
5818 tcp = p[TCP]
5819 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5820 self.assertEqual(tcp.dport, local_port)
5821 self.assert_packet_checksums_valid(p)
5822 except:
5823 self.logger.error(ppp("Unexpected or invalid packet:", p))
5824 raise
5825
5826 # ICMP error
5827 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5828 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5829 ICMP(type=11) / capture[0][IP])
5830 self.pg0.add_stream(p)
5831 self.pg_enable_capture(self.pg_interfaces)
5832 self.pg_start()
5833 capture = self.pg1.get_capture(1)
5834 p = capture[0]
5835 try:
5836 self.assertEqual(p[IP].src, self.nat_addr)
5837 inner = p[IPerror]
5838 self.assertEqual(inner.dst, self.nat_addr)
5839 self.assertEqual(inner[TCPerror].dport, external_port)
5840 except:
5841 self.logger.error(ppp("Unexpected or invalid packet:", p))
5842 raise
5843
5844 # from service back to client
5845 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5846 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5847 TCP(sport=local_port, dport=12345))
5848 self.pg0.add_stream(p)
5849 self.pg_enable_capture(self.pg_interfaces)
5850 self.pg_start()
5851 capture = self.pg1.get_capture(1)
5852 p = capture[0]
5853 try:
5854 ip = p[IP]
5855 tcp = p[TCP]
5856 self.assertEqual(ip.src, self.nat_addr)
5857 self.assertEqual(tcp.sport, external_port)
5858 self.assert_packet_checksums_valid(p)
5859 except:
5860 self.logger.error(ppp("Unexpected or invalid packet:", p))
5861 raise
5862
5863 # ICMP error
5864 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5865 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5866 ICMP(type=11) / capture[0][IP])
5867 self.pg1.add_stream(p)
5868 self.pg_enable_capture(self.pg_interfaces)
5869 self.pg_start()
5870 capture = self.pg0.get_capture(1)
5871 p = capture[0]
5872 try:
5873 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5874 inner = p[IPerror]
5875 self.assertEqual(inner.src, self.pg0.remote_ip4)
5876 self.assertEqual(inner[TCPerror].sport, local_port)
5877 except:
5878 self.logger.error(ppp("Unexpected or invalid packet:", p))
5879 raise
5880
5881 # from client to server (no translation)
5882 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5883 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5884 TCP(sport=12346, dport=local_port))
5885 self.pg1.add_stream(p)
5886 self.pg_enable_capture(self.pg_interfaces)
5887 self.pg_start()
5888 capture = self.pg0.get_capture(1)
5889 p = capture[0]
5890 try:
5891 ip = p[IP]
5892 tcp = p[TCP]
5893 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5894 self.assertEqual(tcp.dport, local_port)
5895 self.assert_packet_checksums_valid(p)
5896 except:
5897 self.logger.error(ppp("Unexpected or invalid packet:", p))
5898 raise
5899
5900 # from service back to client (no translation)
5901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5902 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5903 TCP(sport=local_port, dport=12346))
5904 self.pg0.add_stream(p)
5905 self.pg_enable_capture(self.pg_interfaces)
5906 self.pg_start()
5907 capture = self.pg1.get_capture(1)
5908 p = capture[0]
5909 try:
5910 ip = p[IP]
5911 tcp = p[TCP]
5912 self.assertEqual(ip.src, self.pg0.remote_ip4)
5913 self.assertEqual(tcp.sport, local_port)
5914 self.assert_packet_checksums_valid(p)
5915 except:
5916 self.logger.error(ppp("Unexpected or invalid packet:", p))
5917 raise
5918
Matus Fabian235a47e2018-06-25 16:42:36 -07005919 def test_output_feature(self):
5920 """ NAT44 interface output feature (in2out postrouting) """
5921 self.vapi.nat44_forwarding_enable_disable(1)
5922 self.nat44_add_address(self.nat_addr)
5923 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5924 is_inside=0)
5925 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5926 is_inside=0)
5927
5928 # in2out
5929 pkts = self.create_stream_in(self.pg0, self.pg1)
5930 self.pg0.add_stream(pkts)
5931 self.pg_enable_capture(self.pg_interfaces)
5932 self.pg_start()
5933 capture = self.pg1.get_capture(len(pkts))
5934 self.verify_capture_out(capture)
5935
5936 # out2in
5937 pkts = self.create_stream_out(self.pg1)
5938 self.pg1.add_stream(pkts)
5939 self.pg_enable_capture(self.pg_interfaces)
5940 self.pg_start()
5941 capture = self.pg0.get_capture(len(pkts))
5942 self.verify_capture_in(capture, self.pg0)
5943
Matus Fabian8008d7c2018-07-09 01:34:20 -07005944 def test_multiple_vrf(self):
5945 """ Multiple VRF setup """
5946 external_addr = '1.2.3.4'
5947 external_port = 80
5948 local_port = 8080
5949 port = 0
5950
5951 self.vapi.nat44_forwarding_enable_disable(1)
5952 self.nat44_add_address(self.nat_addr)
5953 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5954 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5955 is_inside=0)
5956 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5957 is_inside=0)
5958 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5959 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5960 is_inside=0)
5961 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5962 is_inside=0)
5963 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5964 local_port, external_port, vrf_id=1,
5965 proto=IP_PROTOS.tcp, out2in_only=1)
5966 self.nat44_add_static_mapping(
5967 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5968 local_port=local_port, vrf_id=0, external_port=external_port,
5969 proto=IP_PROTOS.tcp, out2in_only=1)
5970
5971 # from client to service (both VRF1)
5972 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5973 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5974 TCP(sport=12345, dport=external_port))
5975 self.pg6.add_stream(p)
5976 self.pg_enable_capture(self.pg_interfaces)
5977 self.pg_start()
5978 capture = self.pg5.get_capture(1)
5979 p = capture[0]
5980 try:
5981 ip = p[IP]
5982 tcp = p[TCP]
5983 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5984 self.assertEqual(tcp.dport, local_port)
5985 self.assert_packet_checksums_valid(p)
5986 except:
5987 self.logger.error(ppp("Unexpected or invalid packet:", p))
5988 raise
5989
5990 # from service back to client (both VRF1)
5991 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5992 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5993 TCP(sport=local_port, dport=12345))
5994 self.pg5.add_stream(p)
5995 self.pg_enable_capture(self.pg_interfaces)
5996 self.pg_start()
5997 capture = self.pg6.get_capture(1)
5998 p = capture[0]
5999 try:
6000 ip = p[IP]
6001 tcp = p[TCP]
6002 self.assertEqual(ip.src, external_addr)
6003 self.assertEqual(tcp.sport, external_port)
6004 self.assert_packet_checksums_valid(p)
6005 except:
6006 self.logger.error(ppp("Unexpected or invalid packet:", p))
6007 raise
6008
6009 # dynamic NAT from VRF1 to VRF0 (output-feature)
6010 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6011 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6012 TCP(sport=2345, dport=22))
6013 self.pg5.add_stream(p)
6014 self.pg_enable_capture(self.pg_interfaces)
6015 self.pg_start()
6016 capture = self.pg1.get_capture(1)
6017 p = capture[0]
6018 try:
6019 ip = p[IP]
6020 tcp = p[TCP]
6021 self.assertEqual(ip.src, self.nat_addr)
6022 self.assertNotEqual(tcp.sport, 2345)
6023 self.assert_packet_checksums_valid(p)
6024 port = tcp.sport
6025 except:
6026 self.logger.error(ppp("Unexpected or invalid packet:", p))
6027 raise
6028
6029 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6030 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6031 TCP(sport=22, dport=port))
6032 self.pg1.add_stream(p)
6033 self.pg_enable_capture(self.pg_interfaces)
6034 self.pg_start()
6035 capture = self.pg5.get_capture(1)
6036 p = capture[0]
6037 try:
6038 ip = p[IP]
6039 tcp = p[TCP]
6040 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6041 self.assertEqual(tcp.dport, 2345)
6042 self.assert_packet_checksums_valid(p)
6043 except:
6044 self.logger.error(ppp("Unexpected or invalid packet:", p))
6045 raise
6046
6047 # from client VRF1 to service VRF0
6048 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6049 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6050 TCP(sport=12346, dport=external_port))
6051 self.pg6.add_stream(p)
6052 self.pg_enable_capture(self.pg_interfaces)
6053 self.pg_start()
6054 capture = self.pg0.get_capture(1)
6055 p = capture[0]
6056 try:
6057 ip = p[IP]
6058 tcp = p[TCP]
6059 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6060 self.assertEqual(tcp.dport, local_port)
6061 self.assert_packet_checksums_valid(p)
6062 except:
6063 self.logger.error(ppp("Unexpected or invalid packet:", p))
6064 raise
6065
6066 # from service VRF0 back to client VRF1
6067 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6068 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6069 TCP(sport=local_port, dport=12346))
6070 self.pg0.add_stream(p)
6071 self.pg_enable_capture(self.pg_interfaces)
6072 self.pg_start()
6073 capture = self.pg6.get_capture(1)
6074 p = capture[0]
6075 try:
6076 ip = p[IP]
6077 tcp = p[TCP]
6078 self.assertEqual(ip.src, self.pg0.local_ip4)
6079 self.assertEqual(tcp.sport, external_port)
6080 self.assert_packet_checksums_valid(p)
6081 except:
6082 self.logger.error(ppp("Unexpected or invalid packet:", p))
6083 raise
6084
6085 # from client VRF0 to service VRF1
6086 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6087 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6088 TCP(sport=12347, dport=external_port))
6089 self.pg0.add_stream(p)
6090 self.pg_enable_capture(self.pg_interfaces)
6091 self.pg_start()
6092 capture = self.pg5.get_capture(1)
6093 p = capture[0]
6094 try:
6095 ip = p[IP]
6096 tcp = p[TCP]
6097 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6098 self.assertEqual(tcp.dport, local_port)
6099 self.assert_packet_checksums_valid(p)
6100 except:
6101 self.logger.error(ppp("Unexpected or invalid packet:", p))
6102 raise
6103
6104 # from service VRF1 back to client VRF0
6105 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6106 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6107 TCP(sport=local_port, dport=12347))
6108 self.pg5.add_stream(p)
6109 self.pg_enable_capture(self.pg_interfaces)
6110 self.pg_start()
6111 capture = self.pg0.get_capture(1)
6112 p = capture[0]
6113 try:
6114 ip = p[IP]
6115 tcp = p[TCP]
6116 self.assertEqual(ip.src, external_addr)
6117 self.assertEqual(tcp.sport, external_port)
6118 self.assert_packet_checksums_valid(p)
6119 except:
6120 self.logger.error(ppp("Unexpected or invalid packet:", p))
6121 raise
6122
6123 # from client to server (both VRF1, no translation)
6124 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6125 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6126 TCP(sport=12348, dport=local_port))
6127 self.pg6.add_stream(p)
6128 self.pg_enable_capture(self.pg_interfaces)
6129 self.pg_start()
6130 capture = self.pg5.get_capture(1)
6131 p = capture[0]
6132 try:
6133 ip = p[IP]
6134 tcp = p[TCP]
6135 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6136 self.assertEqual(tcp.dport, local_port)
6137 self.assert_packet_checksums_valid(p)
6138 except:
6139 self.logger.error(ppp("Unexpected or invalid packet:", p))
6140 raise
6141
6142 # from server back to client (both VRF1, no translation)
6143 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6144 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6145 TCP(sport=local_port, dport=12348))
6146 self.pg5.add_stream(p)
6147 self.pg_enable_capture(self.pg_interfaces)
6148 self.pg_start()
6149 capture = self.pg6.get_capture(1)
6150 p = capture[0]
6151 try:
6152 ip = p[IP]
6153 tcp = p[TCP]
6154 self.assertEqual(ip.src, self.pg5.remote_ip4)
6155 self.assertEqual(tcp.sport, local_port)
6156 self.assert_packet_checksums_valid(p)
6157 except:
6158 self.logger.error(ppp("Unexpected or invalid packet:", p))
6159 raise
6160
6161 # from client VRF1 to server VRF0 (no translation)
6162 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6163 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6164 TCP(sport=local_port, dport=12349))
6165 self.pg0.add_stream(p)
6166 self.pg_enable_capture(self.pg_interfaces)
6167 self.pg_start()
6168 capture = self.pg6.get_capture(1)
6169 p = capture[0]
6170 try:
6171 ip = p[IP]
6172 tcp = p[TCP]
6173 self.assertEqual(ip.src, self.pg0.remote_ip4)
6174 self.assertEqual(tcp.sport, local_port)
6175 self.assert_packet_checksums_valid(p)
6176 except:
6177 self.logger.error(ppp("Unexpected or invalid packet:", p))
6178 raise
6179
6180 # from server VRF0 back to client VRF1 (no translation)
6181 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6182 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6183 TCP(sport=local_port, dport=12349))
6184 self.pg0.add_stream(p)
6185 self.pg_enable_capture(self.pg_interfaces)
6186 self.pg_start()
6187 capture = self.pg6.get_capture(1)
6188 p = capture[0]
6189 try:
6190 ip = p[IP]
6191 tcp = p[TCP]
6192 self.assertEqual(ip.src, self.pg0.remote_ip4)
6193 self.assertEqual(tcp.sport, local_port)
6194 self.assert_packet_checksums_valid(p)
6195 except:
6196 self.logger.error(ppp("Unexpected or invalid packet:", p))
6197 raise
6198
6199 # from client VRF0 to server VRF1 (no translation)
6200 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6201 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6202 TCP(sport=12344, dport=local_port))
6203 self.pg0.add_stream(p)
6204 self.pg_enable_capture(self.pg_interfaces)
6205 self.pg_start()
6206 capture = self.pg5.get_capture(1)
6207 p = capture[0]
6208 try:
6209 ip = p[IP]
6210 tcp = p[TCP]
6211 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6212 self.assertEqual(tcp.dport, local_port)
6213 self.assert_packet_checksums_valid(p)
6214 except:
6215 self.logger.error(ppp("Unexpected or invalid packet:", p))
6216 raise
6217
6218 # from server VRF1 back to client VRF0 (no translation)
6219 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6220 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6221 TCP(sport=local_port, dport=12344))
6222 self.pg5.add_stream(p)
6223 self.pg_enable_capture(self.pg_interfaces)
6224 self.pg_start()
6225 capture = self.pg0.get_capture(1)
6226 p = capture[0]
6227 try:
6228 ip = p[IP]
6229 tcp = p[TCP]
6230 self.assertEqual(ip.src, self.pg5.remote_ip4)
6231 self.assertEqual(tcp.sport, local_port)
6232 self.assert_packet_checksums_valid(p)
6233 except:
6234 self.logger.error(ppp("Unexpected or invalid packet:", p))
6235 raise
6236
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006237 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006238 def test_session_timeout(self):
6239 """ NAT44 session timeouts """
6240 self.nat44_add_address(self.nat_addr)
6241 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6242 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6243 is_inside=0)
6244 self.vapi.nat_set_timeouts(icmp=5)
6245
6246 max_sessions = 1000
6247 pkts = []
6248 for i in range(0, max_sessions):
6249 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6250 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6251 IP(src=src, dst=self.pg1.remote_ip4) /
6252 ICMP(id=1025, type='echo-request'))
6253 pkts.append(p)
6254 self.pg0.add_stream(pkts)
6255 self.pg_enable_capture(self.pg_interfaces)
6256 self.pg_start()
6257 self.pg1.get_capture(max_sessions)
6258
6259 sleep(10)
6260
6261 pkts = []
6262 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006263 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006264 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6265 IP(src=src, dst=self.pg1.remote_ip4) /
6266 ICMP(id=1026, type='echo-request'))
6267 pkts.append(p)
6268 self.pg0.add_stream(pkts)
6269 self.pg_enable_capture(self.pg_interfaces)
6270 self.pg_start()
6271 self.pg1.get_capture(max_sessions)
6272
6273 nsessions = 0
6274 users = self.vapi.nat44_user_dump()
6275 for user in users:
6276 nsessions = nsessions + user.nsessions
6277 self.assertLess(nsessions, 2 * max_sessions)
6278
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006279 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006280 def test_session_rst_timeout(self):
6281 """ NAT44 session RST timeouts """
6282 self.nat44_add_address(self.nat_addr)
6283 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6284 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6285 is_inside=0)
6286 self.vapi.nat_set_timeouts(tcp_transitory=5)
6287
Matus Fabian15e8e682018-11-21 04:53:10 -08006288 self.initiate_tcp_session(self.pg0, self.pg1)
6289 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6290 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6291 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6292 flags="R"))
6293 self.pg0.add_stream(p)
6294 self.pg_enable_capture(self.pg_interfaces)
6295 self.pg_start()
6296 self.pg1.get_capture(1)
6297
Matus Fabian15e8e682018-11-21 04:53:10 -08006298 sleep(6)
6299
6300 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6301 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6302 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6303 flags="S"))
6304 self.pg0.add_stream(p)
6305 self.pg_enable_capture(self.pg_interfaces)
6306 self.pg_start()
6307 self.pg1.get_capture(1)
6308
6309 nsessions = 0
6310 users = self.vapi.nat44_user_dump()
6311 self.assertEqual(len(users), 1)
6312 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006313 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006314
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006315 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006316 def test_session_limit_per_user(self):
6317 """ Maximum sessions per user limit """
6318 self.nat44_add_address(self.nat_addr)
6319 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6320 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6321 is_inside=0)
6322 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6323 src_address=self.pg2.local_ip4n,
6324 path_mtu=512,
6325 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07006326 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006327
6328 # get maximum number of translations per user
6329 nat44_config = self.vapi.nat_show_config()
6330
6331 pkts = []
6332 for port in range(0, nat44_config.max_translations_per_user):
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 UDP(sport=1025 + port, dport=1025 + port))
6336 pkts.append(p)
6337
6338 self.pg0.add_stream(pkts)
6339 self.pg_enable_capture(self.pg_interfaces)
6340 self.pg_start()
6341 capture = self.pg1.get_capture(len(pkts))
6342
6343 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6344 src_port=self.ipfix_src_port)
6345
6346 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6347 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6348 UDP(sport=3001, dport=3002))
6349 self.pg0.add_stream(p)
6350 self.pg_enable_capture(self.pg_interfaces)
6351 self.pg_start()
6352 capture = self.pg1.assert_nothing_captured()
6353
6354 # verify IPFIX logging
6355 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6356 sleep(1)
6357 capture = self.pg2.get_capture(10)
6358 ipfix = IPFIXDecoder()
6359 # first load template
6360 for p in capture:
6361 self.assertTrue(p.haslayer(IPFIX))
6362 if p.haslayer(Template):
6363 ipfix.add_template(p.getlayer(Template))
6364 # verify events in data set
6365 for p in capture:
6366 if p.haslayer(Data):
6367 data = ipfix.decode_data_set(p.getlayer(Set))
6368 self.verify_ipfix_max_entries_per_user(
6369 data,
6370 nat44_config.max_translations_per_user,
6371 self.pg0.remote_ip4n)
6372
Matus Fabian8fdc0152018-09-24 04:41:28 -07006373 sleep(6)
6374 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6375 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6376 UDP(sport=3001, dport=3002))
6377 self.pg0.add_stream(p)
6378 self.pg_enable_capture(self.pg_interfaces)
6379 self.pg_start()
6380 self.pg1.get_capture(1)
6381
Matus Fabianad1f3e12018-11-28 21:26:34 -08006382 def test_syslog_sess(self):
6383 """ Test syslog session creation and deletion """
6384 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
6385 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
6386 self.nat44_add_address(self.nat_addr)
6387 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6388 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6389 is_inside=0)
6390
6391 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6392 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6393 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6394 self.pg0.add_stream(p)
6395 self.pg_enable_capture(self.pg_interfaces)
6396 self.pg_start()
6397 capture = self.pg1.get_capture(1)
6398 self.tcp_port_out = capture[0][TCP].sport
6399 capture = self.pg2.get_capture(1)
6400 self.verify_syslog_sess(capture[0][Raw].load)
6401
6402 self.pg_enable_capture(self.pg_interfaces)
6403 self.pg_start()
6404 self.nat44_add_address(self.nat_addr, is_add=0)
6405 capture = self.pg2.get_capture(1)
6406 self.verify_syslog_sess(capture[0][Raw].load, False)
6407
Matus Fabiande886752016-12-07 03:38:19 -08006408 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006409 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006410 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006411 self.logger.info(self.vapi.cli("show nat44 addresses"))
6412 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6413 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6414 self.logger.info(self.vapi.cli("show nat44 interface address"))
6415 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07006416 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07006417 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006418 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006419 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006420
Matus Fabianeea28d72017-01-13 04:15:54 -08006421
Juraj Slobodacba69362017-12-19 02:09:32 +01006422class TestNAT44Out2InDPO(MethodHolder):
6423 """ NAT44 Test Cases using out2in DPO """
6424
6425 @classmethod
6426 def setUpConstants(cls):
6427 super(TestNAT44Out2InDPO, cls).setUpConstants()
6428 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6429
6430 @classmethod
6431 def setUpClass(cls):
6432 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006433 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006434
6435 try:
6436 cls.tcp_port_in = 6303
6437 cls.tcp_port_out = 6303
6438 cls.udp_port_in = 6304
6439 cls.udp_port_out = 6304
6440 cls.icmp_id_in = 6305
6441 cls.icmp_id_out = 6305
6442 cls.nat_addr = '10.0.0.3'
6443 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6444 cls.dst_ip4 = '192.168.70.1'
6445
6446 cls.create_pg_interfaces(range(2))
6447
6448 cls.pg0.admin_up()
6449 cls.pg0.config_ip4()
6450 cls.pg0.resolve_arp()
6451
6452 cls.pg1.admin_up()
6453 cls.pg1.config_ip6()
6454 cls.pg1.resolve_ndp()
6455
6456 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
6457 dst_address_length=0,
6458 next_hop_address=cls.pg1.remote_ip6n,
6459 next_hop_sw_if_index=cls.pg1.sw_if_index)
6460
6461 except Exception:
6462 super(TestNAT44Out2InDPO, cls).tearDownClass()
6463 raise
6464
6465 def configure_xlat(self):
6466 self.dst_ip6_pfx = '1:2:3::'
6467 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6468 self.dst_ip6_pfx)
6469 self.dst_ip6_pfx_len = 96
6470 self.src_ip6_pfx = '4:5:6::'
6471 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6472 self.src_ip6_pfx)
6473 self.src_ip6_pfx_len = 96
6474 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6475 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006476 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006477
Ole Troanffba3c32018-11-22 12:53:00 +01006478 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006479 def test_464xlat_ce(self):
6480 """ Test 464XLAT CE with NAT44 """
6481
Matus Fabian69ce30d2018-08-22 01:27:10 -07006482 nat_config = self.vapi.nat_show_config()
6483 self.assertEqual(1, nat_config.out2in_dpo)
6484
Juraj Slobodacba69362017-12-19 02:09:32 +01006485 self.configure_xlat()
6486
6487 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6488 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6489
6490 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6491 self.dst_ip6_pfx_len)
6492 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6493 self.src_ip6_pfx_len)
6494
6495 try:
6496 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6497 self.pg0.add_stream(pkts)
6498 self.pg_enable_capture(self.pg_interfaces)
6499 self.pg_start()
6500 capture = self.pg1.get_capture(len(pkts))
6501 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6502 dst_ip=out_src_ip6)
6503
6504 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6505 out_dst_ip6)
6506 self.pg1.add_stream(pkts)
6507 self.pg_enable_capture(self.pg_interfaces)
6508 self.pg_start()
6509 capture = self.pg0.get_capture(len(pkts))
6510 self.verify_capture_in(capture, self.pg0)
6511 finally:
6512 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6513 is_add=0)
6514 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6515 self.nat_addr_n, is_add=0)
6516
Ole Troanffba3c32018-11-22 12:53:00 +01006517 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006518 def test_464xlat_ce_no_nat(self):
6519 """ Test 464XLAT CE without NAT44 """
6520
6521 self.configure_xlat()
6522
6523 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6524 self.dst_ip6_pfx_len)
6525 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6526 self.src_ip6_pfx_len)
6527
6528 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6529 self.pg0.add_stream(pkts)
6530 self.pg_enable_capture(self.pg_interfaces)
6531 self.pg_start()
6532 capture = self.pg1.get_capture(len(pkts))
6533 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6534 nat_ip=out_dst_ip6, same_port=True)
6535
6536 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6537 self.pg1.add_stream(pkts)
6538 self.pg_enable_capture(self.pg_interfaces)
6539 self.pg_start()
6540 capture = self.pg0.get_capture(len(pkts))
6541 self.verify_capture_in(capture, self.pg0)
6542
6543
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006544class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006545 """ Deterministic NAT Test Cases """
6546
6547 @classmethod
6548 def setUpConstants(cls):
6549 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006550 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006551
6552 @classmethod
6553 def setUpClass(cls):
6554 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006555 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006556
6557 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006558 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006559 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006560 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006561 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006562 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006563 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006564
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006565 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006566 cls.interfaces = list(cls.pg_interfaces)
6567
6568 for i in cls.interfaces:
6569 i.admin_up()
6570 i.config_ip4()
6571 i.resolve_arp()
6572
Martin Gálik977c1cb2017-03-30 23:21:51 -07006573 cls.pg0.generate_remote_hosts(2)
6574 cls.pg0.configure_ipv4_neighbors()
6575
Matus Fabian066f0342017-02-10 03:48:01 -08006576 except Exception:
6577 super(TestDeterministicNAT, cls).tearDownClass()
6578 raise
6579
Martin Gálik977c1cb2017-03-30 23:21:51 -07006580 def create_stream_in(self, in_if, out_if, ttl=64):
6581 """
6582 Create packet stream for inside network
6583
6584 :param in_if: Inside interface
6585 :param out_if: Outside interface
6586 :param ttl: TTL of generated packets
6587 """
6588 pkts = []
6589 # TCP
6590 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6591 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006592 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006593 pkts.append(p)
6594
6595 # UDP
6596 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6597 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006598 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006599 pkts.append(p)
6600
6601 # ICMP
6602 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6603 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6604 ICMP(id=self.icmp_id_in, type='echo-request'))
6605 pkts.append(p)
6606
6607 return pkts
6608
6609 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6610 """
6611 Create packet stream for outside network
6612
6613 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006614 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006615 :param ttl: TTL of generated packets
6616 """
6617 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006618 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006619 pkts = []
6620 # TCP
6621 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6622 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006623 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006624 pkts.append(p)
6625
6626 # UDP
6627 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6628 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006629 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006630 pkts.append(p)
6631
6632 # ICMP
6633 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6634 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6635 ICMP(id=self.icmp_external_id, type='echo-reply'))
6636 pkts.append(p)
6637
6638 return pkts
6639
Matus Fabian05ca4a32018-09-04 23:45:13 -07006640 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006641 """
6642 Verify captured packets on outside network
6643
6644 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006645 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006646 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006647 """
6648 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006649 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006650 for packet in capture:
6651 try:
6652 self.assertEqual(packet[IP].src, nat_ip)
6653 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006654 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006655 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006656 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006657 else:
6658 self.icmp_external_id = packet[ICMP].id
6659 except:
6660 self.logger.error(ppp("Unexpected or invalid packet "
6661 "(outside network):", packet))
6662 raise
6663
Matus Fabian066f0342017-02-10 03:48:01 -08006664 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006665 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006666 in_addr = '172.16.255.0'
6667 out_addr = '172.17.255.50'
6668 in_addr_t = '172.16.255.20'
6669 in_addr_n = socket.inet_aton(in_addr)
6670 out_addr_n = socket.inet_aton(out_addr)
6671 in_addr_t_n = socket.inet_aton(in_addr_t)
6672 in_plen = 24
6673 out_plen = 32
6674
Matus Fabian2ba92e32017-08-21 07:05:03 -07006675 nat_config = self.vapi.nat_show_config()
6676 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006677
Matus Fabian2ba92e32017-08-21 07:05:03 -07006678 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006679
Matus Fabian2ba92e32017-08-21 07:05:03 -07006680 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006681 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006682 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006683 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6684
Matus Fabian2ba92e32017-08-21 07:05:03 -07006685 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006686 self.assertEqual(len(deterministic_mappings), 1)
6687 dsm = deterministic_mappings[0]
6688 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6689 self.assertEqual(in_plen, dsm.in_plen)
6690 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6691 self.assertEqual(out_plen, dsm.out_plen)
6692
Matus Fabian2ba92e32017-08-21 07:05:03 -07006693 self.clear_nat_det()
6694 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006695 self.assertEqual(len(deterministic_mappings), 0)
6696
Matus Fabian6a0946f2017-04-12 03:36:13 -07006697 def test_set_timeouts(self):
6698 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006699 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006700
Matus Fabian878c6462018-08-23 00:33:35 -07006701 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6702 timeouts_before.tcp_established + 10,
6703 timeouts_before.tcp_transitory + 10,
6704 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006705
Matus Fabian878c6462018-08-23 00:33:35 -07006706 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006707
6708 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6709 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6710 self.assertNotEqual(timeouts_before.tcp_established,
6711 timeouts_after.tcp_established)
6712 self.assertNotEqual(timeouts_before.tcp_transitory,
6713 timeouts_after.tcp_transitory)
6714
Martin Gálik977c1cb2017-03-30 23:21:51 -07006715 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006716 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006717
6718 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006719
Matus Fabian2ba92e32017-08-21 07:05:03 -07006720 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6721 32,
6722 socket.inet_aton(nat_ip),
6723 32)
6724 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6725 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6726 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006727
6728 # in2out
6729 pkts = self.create_stream_in(self.pg0, self.pg1)
6730 self.pg0.add_stream(pkts)
6731 self.pg_enable_capture(self.pg_interfaces)
6732 self.pg_start()
6733 capture = self.pg1.get_capture(len(pkts))
6734 self.verify_capture_out(capture, nat_ip)
6735
6736 # out2in
6737 pkts = self.create_stream_out(self.pg1, nat_ip)
6738 self.pg1.add_stream(pkts)
6739 self.pg_enable_capture(self.pg_interfaces)
6740 self.pg_start()
6741 capture = self.pg0.get_capture(len(pkts))
6742 self.verify_capture_in(capture, self.pg0)
6743
Martin Gálik9806eae2017-04-25 01:25:08 -07006744 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006745 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006746 self.assertEqual(len(sessions), 3)
6747
6748 # TCP session
6749 s = sessions[0]
6750 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6751 self.assertEqual(s.in_port, self.tcp_port_in)
6752 self.assertEqual(s.out_port, self.tcp_port_out)
6753 self.assertEqual(s.ext_port, self.tcp_external_port)
6754
6755 # UDP session
6756 s = sessions[1]
6757 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6758 self.assertEqual(s.in_port, self.udp_port_in)
6759 self.assertEqual(s.out_port, self.udp_port_out)
6760 self.assertEqual(s.ext_port, self.udp_external_port)
6761
6762 # ICMP session
6763 s = sessions[2]
6764 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6765 self.assertEqual(s.in_port, self.icmp_id_in)
6766 self.assertEqual(s.out_port, self.icmp_external_id)
6767
Martin Gálik977c1cb2017-03-30 23:21:51 -07006768 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006769 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006770
6771 nat_ip = "10.0.0.10"
6772 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006773 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006774
6775 host0 = self.pg0.remote_hosts[0]
6776 host1 = self.pg0.remote_hosts[1]
6777
Matus Fabian2ba92e32017-08-21 07:05:03 -07006778 self.vapi.nat_det_add_del_map(host0.ip4n,
6779 24,
6780 socket.inet_aton(nat_ip),
6781 32)
6782 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6783 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6784 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006785
6786 # host0 to out
6787 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6788 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006789 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006790 self.pg0.add_stream(p)
6791 self.pg_enable_capture(self.pg_interfaces)
6792 self.pg_start()
6793 capture = self.pg1.get_capture(1)
6794 p = capture[0]
6795 try:
6796 ip = p[IP]
6797 tcp = p[TCP]
6798 self.assertEqual(ip.src, nat_ip)
6799 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006800 self.assertEqual(tcp.dport, external_port)
6801 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006802 except:
6803 self.logger.error(ppp("Unexpected or invalid packet:", p))
6804 raise
6805
6806 # host1 to out
6807 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6808 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006809 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006810 self.pg0.add_stream(p)
6811 self.pg_enable_capture(self.pg_interfaces)
6812 self.pg_start()
6813 capture = self.pg1.get_capture(1)
6814 p = capture[0]
6815 try:
6816 ip = p[IP]
6817 tcp = p[TCP]
6818 self.assertEqual(ip.src, nat_ip)
6819 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006820 self.assertEqual(tcp.dport, external_port)
6821 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006822 except:
6823 self.logger.error(ppp("Unexpected or invalid packet:", p))
6824 raise
6825
Matus Fabian2ba92e32017-08-21 07:05:03 -07006826 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006827 self.assertEqual(1, len(dms))
6828 self.assertEqual(2, dms[0].ses_num)
6829
6830 # out to host0
6831 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6832 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006833 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006834 self.pg1.add_stream(p)
6835 self.pg_enable_capture(self.pg_interfaces)
6836 self.pg_start()
6837 capture = self.pg0.get_capture(1)
6838 p = capture[0]
6839 try:
6840 ip = p[IP]
6841 tcp = p[TCP]
6842 self.assertEqual(ip.src, self.pg1.remote_ip4)
6843 self.assertEqual(ip.dst, host0.ip4)
6844 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006845 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006846 except:
6847 self.logger.error(ppp("Unexpected or invalid packet:", p))
6848 raise
6849
6850 # out to host1
6851 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6852 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006853 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006854 self.pg1.add_stream(p)
6855 self.pg_enable_capture(self.pg_interfaces)
6856 self.pg_start()
6857 capture = self.pg0.get_capture(1)
6858 p = capture[0]
6859 try:
6860 ip = p[IP]
6861 tcp = p[TCP]
6862 self.assertEqual(ip.src, self.pg1.remote_ip4)
6863 self.assertEqual(ip.dst, host1.ip4)
6864 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006865 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006866 except:
6867 self.logger.error(ppp("Unexpected or invalid packet", p))
6868 raise
6869
Martin Gálik6bc8c642017-04-19 01:12:27 -07006870 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006871 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6872 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006873 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006874 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006875 dms = self.vapi.nat_det_map_dump()
6876 self.assertEqual(dms[0].ses_num, 1)
6877
6878 self.vapi.nat_det_close_session_in(host0.ip4n,
6879 port_in,
6880 self.pg1.remote_ip4n,
6881 external_port)
6882 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006883 self.assertEqual(dms[0].ses_num, 0)
6884
Martin Gálik977c1cb2017-03-30 23:21:51 -07006885 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006886 """ Deterministic NAT TCP session close from inside network """
6887 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6888 32,
6889 socket.inet_aton(self.nat_addr),
6890 32)
6891 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6892 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6893 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006894
6895 self.initiate_tcp_session(self.pg0, self.pg1)
6896
6897 # close the session from inside
6898 try:
6899 # FIN packet in -> out
6900 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6901 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006902 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006903 flags="F"))
6904 self.pg0.add_stream(p)
6905 self.pg_enable_capture(self.pg_interfaces)
6906 self.pg_start()
6907 self.pg1.get_capture(1)
6908
6909 pkts = []
6910
6911 # ACK packet out -> in
6912 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006913 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006914 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006915 flags="A"))
6916 pkts.append(p)
6917
6918 # FIN packet out -> in
6919 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006920 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006921 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006922 flags="F"))
6923 pkts.append(p)
6924
6925 self.pg1.add_stream(pkts)
6926 self.pg_enable_capture(self.pg_interfaces)
6927 self.pg_start()
6928 self.pg0.get_capture(2)
6929
6930 # ACK packet in -> out
6931 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6932 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006933 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006934 flags="A"))
6935 self.pg0.add_stream(p)
6936 self.pg_enable_capture(self.pg_interfaces)
6937 self.pg_start()
6938 self.pg1.get_capture(1)
6939
Matus Fabian2ba92e32017-08-21 07:05:03 -07006940 # Check if deterministic NAT44 closed the session
6941 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006942 self.assertEqual(0, dms[0].ses_num)
6943 except:
6944 self.logger.error("TCP session termination failed")
6945 raise
6946
6947 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006948 """ Deterministic NAT TCP session close from outside network """
6949 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6950 32,
6951 socket.inet_aton(self.nat_addr),
6952 32)
6953 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6954 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6955 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006956
6957 self.initiate_tcp_session(self.pg0, self.pg1)
6958
6959 # close the session from outside
6960 try:
6961 # FIN packet out -> in
6962 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006963 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006964 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006965 flags="F"))
6966 self.pg1.add_stream(p)
6967 self.pg_enable_capture(self.pg_interfaces)
6968 self.pg_start()
6969 self.pg0.get_capture(1)
6970
6971 pkts = []
6972
6973 # ACK packet in -> out
6974 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6975 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006976 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006977 flags="A"))
6978 pkts.append(p)
6979
6980 # ACK packet in -> out
6981 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6982 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006983 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006984 flags="F"))
6985 pkts.append(p)
6986
6987 self.pg0.add_stream(pkts)
6988 self.pg_enable_capture(self.pg_interfaces)
6989 self.pg_start()
6990 self.pg1.get_capture(2)
6991
6992 # ACK packet out -> in
6993 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006994 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006995 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006996 flags="A"))
6997 self.pg1.add_stream(p)
6998 self.pg_enable_capture(self.pg_interfaces)
6999 self.pg_start()
7000 self.pg0.get_capture(1)
7001
Matus Fabian2ba92e32017-08-21 07:05:03 -07007002 # Check if deterministic NAT44 closed the session
7003 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007004 self.assertEqual(0, dms[0].ses_num)
7005 except:
7006 self.logger.error("TCP session termination failed")
7007 raise
7008
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007009 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007010 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007011 """ Deterministic NAT session timeouts """
7012 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7013 32,
7014 socket.inet_aton(self.nat_addr),
7015 32)
7016 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7017 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7018 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007019
7020 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07007021 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007022 pkts = self.create_stream_in(self.pg0, self.pg1)
7023 self.pg0.add_stream(pkts)
7024 self.pg_enable_capture(self.pg_interfaces)
7025 self.pg_start()
7026 capture = self.pg1.get_capture(len(pkts))
7027 sleep(15)
7028
Matus Fabian2ba92e32017-08-21 07:05:03 -07007029 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007030 self.assertEqual(0, dms[0].ses_num)
7031
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007032 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007033 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007034 """ Deterministic NAT maximum sessions per user limit """
7035 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7036 32,
7037 socket.inet_aton(self.nat_addr),
7038 32)
7039 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7040 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7041 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007042 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7043 src_address=self.pg2.local_ip4n,
7044 path_mtu=512,
7045 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07007046 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007047
7048 pkts = []
7049 for port in range(1025, 2025):
7050 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7051 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7052 UDP(sport=port, dport=port))
7053 pkts.append(p)
7054
7055 self.pg0.add_stream(pkts)
7056 self.pg_enable_capture(self.pg_interfaces)
7057 self.pg_start()
7058 capture = self.pg1.get_capture(len(pkts))
7059
7060 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7061 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007062 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007063 self.pg0.add_stream(p)
7064 self.pg_enable_capture(self.pg_interfaces)
7065 self.pg_start()
7066 capture = self.pg1.assert_nothing_captured()
7067
Martin Gálikf7e655d2017-04-27 02:13:26 -07007068 # verify ICMP error packet
7069 capture = self.pg0.get_capture(1)
7070 p = capture[0]
7071 self.assertTrue(p.haslayer(ICMP))
7072 icmp = p[ICMP]
7073 self.assertEqual(icmp.type, 3)
7074 self.assertEqual(icmp.code, 1)
7075 self.assertTrue(icmp.haslayer(IPerror))
7076 inner_ip = icmp[IPerror]
7077 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7078 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7079
Matus Fabian2ba92e32017-08-21 07:05:03 -07007080 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007081
7082 self.assertEqual(1000, dms[0].ses_num)
7083
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007084 # verify IPFIX logging
7085 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007086 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007087 capture = self.pg2.get_capture(2)
7088 ipfix = IPFIXDecoder()
7089 # first load template
7090 for p in capture:
7091 self.assertTrue(p.haslayer(IPFIX))
7092 if p.haslayer(Template):
7093 ipfix.add_template(p.getlayer(Template))
7094 # verify events in data set
7095 for p in capture:
7096 if p.haslayer(Data):
7097 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007098 self.verify_ipfix_max_entries_per_user(data,
7099 1000,
7100 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007101
Matus Fabian2ba92e32017-08-21 07:05:03 -07007102 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007103 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007104 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007105 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007106 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007107 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007108 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007109 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007110 self.vapi.nat_det_add_del_map(dsm.in_addr,
7111 dsm.in_plen,
7112 dsm.out_addr,
7113 dsm.out_plen,
7114 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08007115
Matus Fabian2ba92e32017-08-21 07:05:03 -07007116 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007117 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007118 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7119 intf.is_inside,
7120 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007121
Matus Fabian066f0342017-02-10 03:48:01 -08007122 def tearDown(self):
7123 super(TestDeterministicNAT, self).tearDown()
7124 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08007125 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07007126 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08007127 self.logger.info(
7128 self.vapi.cli("show nat44 deterministic mappings"))
7129 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08007130 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07007131 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007132
Matus Fabian06596c52017-06-06 04:53:28 -07007133
7134class TestNAT64(MethodHolder):
7135 """ NAT64 Test Cases """
7136
7137 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007138 def setUpConstants(cls):
7139 super(TestNAT64, cls).setUpConstants()
7140 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7141 "nat64 st hash buckets 256", "}"])
7142
7143 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007144 def setUpClass(cls):
7145 super(TestNAT64, cls).setUpClass()
7146
7147 try:
7148 cls.tcp_port_in = 6303
7149 cls.tcp_port_out = 6303
7150 cls.udp_port_in = 6304
7151 cls.udp_port_out = 6304
7152 cls.icmp_id_in = 6305
7153 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007154 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007155 cls.nat_addr = '10.0.0.3'
7156 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007157 cls.vrf1_id = 10
7158 cls.vrf1_nat_addr = '10.0.10.3'
7159 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7160 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08007161 cls.ipfix_src_port = 4739
7162 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007163
Juraj Slobodac746a152018-07-09 02:36:37 +02007164 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007165 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007166 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007167 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7168
Neale Ranns15002542017-09-10 04:39:11 -07007169 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
7170
Matus Fabian029f3d22017-06-15 02:28:50 -07007171 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7172
7173 cls.pg0.generate_remote_hosts(2)
7174
Matus Fabian06596c52017-06-06 04:53:28 -07007175 for i in cls.ip6_interfaces:
7176 i.admin_up()
7177 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007178 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007179
7180 for i in cls.ip4_interfaces:
7181 i.admin_up()
7182 i.config_ip4()
7183 i.resolve_arp()
7184
Matus Fabian36ea2d62017-10-24 04:13:49 -07007185 cls.pg3.admin_up()
7186 cls.pg3.config_ip4()
7187 cls.pg3.resolve_arp()
7188 cls.pg3.config_ip6()
7189 cls.pg3.configure_ipv6_neighbors()
7190
Juraj Slobodac746a152018-07-09 02:36:37 +02007191 cls.pg5.admin_up()
7192 cls.pg5.config_ip6()
7193
Matus Fabian06596c52017-06-06 04:53:28 -07007194 except Exception:
7195 super(TestNAT64, cls).tearDownClass()
7196 raise
7197
Juraj Slobodac746a152018-07-09 02:36:37 +02007198 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7199 """ NAT64 inside interface handles Neighbor Advertisement """
7200
7201 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7202
7203 # Try to send ping
7204 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7205 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7206 ICMPv6EchoRequest())
7207 pkts = [ping]
7208 self.pg5.add_stream(pkts)
7209 self.pg_enable_capture(self.pg_interfaces)
7210 self.pg_start()
7211
7212 # Wait for Neighbor Solicitation
7213 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007214 packet = capture[0]
7215 try:
7216 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007217 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007218 tgt = packet[ICMPv6ND_NS].tgt
7219 except:
7220 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7221 raise
7222
7223 # Send Neighbor Advertisement
7224 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7225 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7226 ICMPv6ND_NA(tgt=tgt) /
7227 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7228 pkts = [p]
7229 self.pg5.add_stream(pkts)
7230 self.pg_enable_capture(self.pg_interfaces)
7231 self.pg_start()
7232
7233 # Try to send ping again
7234 pkts = [ping]
7235 self.pg5.add_stream(pkts)
7236 self.pg_enable_capture(self.pg_interfaces)
7237 self.pg_start()
7238
7239 # Wait for ping reply
7240 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007241 packet = capture[0]
7242 try:
7243 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7244 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007245 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007246 except:
7247 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7248 raise
7249
Matus Fabian06596c52017-06-06 04:53:28 -07007250 def test_pool(self):
7251 """ Add/delete address to NAT64 pool """
7252 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7253
7254 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7255
7256 addresses = self.vapi.nat64_pool_addr_dump()
7257 self.assertEqual(len(addresses), 1)
7258 self.assertEqual(addresses[0].address, nat_addr)
7259
7260 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7261
7262 addresses = self.vapi.nat64_pool_addr_dump()
7263 self.assertEqual(len(addresses), 0)
7264
7265 def test_interface(self):
7266 """ Enable/disable NAT64 feature on the interface """
7267 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7268 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7269
7270 interfaces = self.vapi.nat64_interface_dump()
7271 self.assertEqual(len(interfaces), 2)
7272 pg0_found = False
7273 pg1_found = False
7274 for intf in interfaces:
7275 if intf.sw_if_index == self.pg0.sw_if_index:
7276 self.assertEqual(intf.is_inside, 1)
7277 pg0_found = True
7278 elif intf.sw_if_index == self.pg1.sw_if_index:
7279 self.assertEqual(intf.is_inside, 0)
7280 pg1_found = True
7281 self.assertTrue(pg0_found)
7282 self.assertTrue(pg1_found)
7283
7284 features = self.vapi.cli("show interface features pg0")
7285 self.assertNotEqual(features.find('nat64-in2out'), -1)
7286 features = self.vapi.cli("show interface features pg1")
7287 self.assertNotEqual(features.find('nat64-out2in'), -1)
7288
7289 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7290 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7291
7292 interfaces = self.vapi.nat64_interface_dump()
7293 self.assertEqual(len(interfaces), 0)
7294
7295 def test_static_bib(self):
7296 """ Add/delete static BIB entry """
7297 in_addr = socket.inet_pton(socket.AF_INET6,
7298 '2001:db8:85a3::8a2e:370:7334')
7299 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7300 in_port = 1234
7301 out_port = 5678
7302 proto = IP_PROTOS.tcp
7303
7304 self.vapi.nat64_add_del_static_bib(in_addr,
7305 out_addr,
7306 in_port,
7307 out_port,
7308 proto)
7309 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7310 static_bib_num = 0
7311 for bibe in bib:
7312 if bibe.is_static:
7313 static_bib_num += 1
7314 self.assertEqual(bibe.i_addr, in_addr)
7315 self.assertEqual(bibe.o_addr, out_addr)
7316 self.assertEqual(bibe.i_port, in_port)
7317 self.assertEqual(bibe.o_port, out_port)
7318 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007319 bibs = self.statistics.get_counter('/nat64/total-bibs')
7320 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007321
7322 self.vapi.nat64_add_del_static_bib(in_addr,
7323 out_addr,
7324 in_port,
7325 out_port,
7326 proto,
7327 is_add=0)
7328 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7329 static_bib_num = 0
7330 for bibe in bib:
7331 if bibe.is_static:
7332 static_bib_num += 1
7333 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007334 bibs = self.statistics.get_counter('/nat64/total-bibs')
7335 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007336
7337 def test_set_timeouts(self):
7338 """ Set NAT64 timeouts """
7339 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007340 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007341 self.assertEqual(timeouts.udp, 300)
7342 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007343 self.assertEqual(timeouts.tcp_transitory, 240)
7344 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007345
7346 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07007347 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7348 tcp_established=7450)
7349 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007350 self.assertEqual(timeouts.udp, 200)
7351 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007352 self.assertEqual(timeouts.tcp_transitory, 250)
7353 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007354
7355 def test_dynamic(self):
7356 """ NAT64 dynamic translation test """
7357 self.tcp_port_in = 6303
7358 self.udp_port_in = 6304
7359 self.icmp_id_in = 6305
7360
7361 ses_num_start = self.nat64_get_ses_num()
7362
7363 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7364 self.nat_addr_n)
7365 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7366 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7367
7368 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007369 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7370 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7371 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7372 totaln = self.statistics.get_counter(
7373 '/err/nat64-in2out/good in2out packets processed')
7374
Matus Fabian06596c52017-06-06 04:53:28 -07007375 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7376 self.pg0.add_stream(pkts)
7377 self.pg_enable_capture(self.pg_interfaces)
7378 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007379 capture = self.pg1.get_capture(len(pkts))
7380 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007381 dst_ip=self.pg1.remote_ip4)
7382
Matus Fabiana5e73762018-12-14 01:55:16 -08007383 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7384 self.assertEqual(err - tcpn, 1)
7385 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7386 self.assertEqual(err - udpn, 1)
7387 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7388 self.assertEqual(err - icmpn, 1)
7389 err = self.statistics.get_counter(
7390 '/err/nat64-in2out/good in2out packets processed')
7391 self.assertEqual(err - totaln, 3)
7392
Matus Fabian06596c52017-06-06 04:53:28 -07007393 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007394 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7395 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7396 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7397 totaln = self.statistics.get_counter(
7398 '/err/nat64-out2in/good out2in packets processed')
7399
Matus Fabian06596c52017-06-06 04:53:28 -07007400 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7401 self.pg1.add_stream(pkts)
7402 self.pg_enable_capture(self.pg_interfaces)
7403 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007404 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007405 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7406 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7407
Matus Fabiana5e73762018-12-14 01:55:16 -08007408 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7409 self.assertEqual(err - tcpn, 1)
7410 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7411 self.assertEqual(err - udpn, 1)
7412 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7413 self.assertEqual(err - icmpn, 1)
7414 err = self.statistics.get_counter(
7415 '/err/nat64-out2in/good out2in packets processed')
7416 self.assertEqual(err - totaln, 3)
7417
Matus Fabianfd0d5082018-12-18 01:08:51 -08007418 bibs = self.statistics.get_counter('/nat64/total-bibs')
7419 self.assertEqual(bibs[0][0], 3)
7420 sessions = self.statistics.get_counter('/nat64/total-sessions')
7421 self.assertEqual(sessions[0][0], 3)
7422
Matus Fabian06596c52017-06-06 04:53:28 -07007423 # in2out
7424 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7425 self.pg0.add_stream(pkts)
7426 self.pg_enable_capture(self.pg_interfaces)
7427 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007428 capture = self.pg1.get_capture(len(pkts))
7429 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007430 dst_ip=self.pg1.remote_ip4)
7431
7432 # out2in
7433 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7434 self.pg1.add_stream(pkts)
7435 self.pg_enable_capture(self.pg_interfaces)
7436 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007437 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007438 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7439
7440 ses_num_end = self.nat64_get_ses_num()
7441
7442 self.assertEqual(ses_num_end - ses_num_start, 3)
7443
Matus Fabian029f3d22017-06-15 02:28:50 -07007444 # tenant with specific VRF
7445 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7446 self.vrf1_nat_addr_n,
7447 vrf_id=self.vrf1_id)
7448 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7449
7450 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7451 self.pg2.add_stream(pkts)
7452 self.pg_enable_capture(self.pg_interfaces)
7453 self.pg_start()
7454 capture = self.pg1.get_capture(len(pkts))
7455 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7456 dst_ip=self.pg1.remote_ip4)
7457
7458 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7459 self.pg1.add_stream(pkts)
7460 self.pg_enable_capture(self.pg_interfaces)
7461 self.pg_start()
7462 capture = self.pg2.get_capture(len(pkts))
7463 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7464
Matus Fabian06596c52017-06-06 04:53:28 -07007465 def test_static(self):
7466 """ NAT64 static translation test """
7467 self.tcp_port_in = 60303
7468 self.udp_port_in = 60304
7469 self.icmp_id_in = 60305
7470 self.tcp_port_out = 60303
7471 self.udp_port_out = 60304
7472 self.icmp_id_out = 60305
7473
7474 ses_num_start = self.nat64_get_ses_num()
7475
7476 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7477 self.nat_addr_n)
7478 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7479 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7480
7481 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7482 self.nat_addr_n,
7483 self.tcp_port_in,
7484 self.tcp_port_out,
7485 IP_PROTOS.tcp)
7486 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7487 self.nat_addr_n,
7488 self.udp_port_in,
7489 self.udp_port_out,
7490 IP_PROTOS.udp)
7491 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7492 self.nat_addr_n,
7493 self.icmp_id_in,
7494 self.icmp_id_out,
7495 IP_PROTOS.icmp)
7496
7497 # in2out
7498 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7499 self.pg0.add_stream(pkts)
7500 self.pg_enable_capture(self.pg_interfaces)
7501 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007502 capture = self.pg1.get_capture(len(pkts))
7503 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007504 dst_ip=self.pg1.remote_ip4, same_port=True)
7505
7506 # out2in
7507 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7508 self.pg1.add_stream(pkts)
7509 self.pg_enable_capture(self.pg_interfaces)
7510 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007511 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007512 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7513 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7514
7515 ses_num_end = self.nat64_get_ses_num()
7516
7517 self.assertEqual(ses_num_end - ses_num_start, 3)
7518
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007519 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07007520 def test_session_timeout(self):
7521 """ NAT64 session timeout """
7522 self.icmp_id_in = 1234
7523 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7524 self.nat_addr_n)
7525 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7526 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007527 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07007528
7529 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7530 self.pg0.add_stream(pkts)
7531 self.pg_enable_capture(self.pg_interfaces)
7532 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007533 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007534
7535 ses_num_before_timeout = self.nat64_get_ses_num()
7536
7537 sleep(15)
7538
Matus Fabian8fed4242018-08-14 05:14:55 -07007539 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07007540 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07007541 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07007542
Matus Fabian732036d2017-06-08 05:24:28 -07007543 def test_icmp_error(self):
7544 """ NAT64 ICMP Error message translation """
7545 self.tcp_port_in = 6303
7546 self.udp_port_in = 6304
7547 self.icmp_id_in = 6305
7548
Matus Fabian732036d2017-06-08 05:24:28 -07007549 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7550 self.nat_addr_n)
7551 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7552 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7553
7554 # send some packets to create sessions
7555 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7556 self.pg0.add_stream(pkts)
7557 self.pg_enable_capture(self.pg_interfaces)
7558 self.pg_start()
7559 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07007560 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07007561 nat_ip=self.nat_addr,
7562 dst_ip=self.pg1.remote_ip4)
7563
7564 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7565 self.pg1.add_stream(pkts)
7566 self.pg_enable_capture(self.pg_interfaces)
7567 self.pg_start()
7568 capture_ip6 = self.pg0.get_capture(len(pkts))
7569 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7570 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7571 self.pg0.remote_ip6)
7572
7573 # in2out
7574 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7575 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7576 ICMPv6DestUnreach(code=1) /
7577 packet[IPv6] for packet in capture_ip6]
7578 self.pg0.add_stream(pkts)
7579 self.pg_enable_capture(self.pg_interfaces)
7580 self.pg_start()
7581 capture = self.pg1.get_capture(len(pkts))
7582 for packet in capture:
7583 try:
7584 self.assertEqual(packet[IP].src, self.nat_addr)
7585 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7586 self.assertEqual(packet[ICMP].type, 3)
7587 self.assertEqual(packet[ICMP].code, 13)
7588 inner = packet[IPerror]
7589 self.assertEqual(inner.src, self.pg1.remote_ip4)
7590 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007591 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007592 if inner.haslayer(TCPerror):
7593 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7594 elif inner.haslayer(UDPerror):
7595 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7596 else:
7597 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7598 except:
7599 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7600 raise
7601
7602 # out2in
7603 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7604 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7605 ICMP(type=3, code=13) /
7606 packet[IP] for packet in capture_ip4]
7607 self.pg1.add_stream(pkts)
7608 self.pg_enable_capture(self.pg_interfaces)
7609 self.pg_start()
7610 capture = self.pg0.get_capture(len(pkts))
7611 for packet in capture:
7612 try:
7613 self.assertEqual(packet[IPv6].src, ip.src)
7614 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7615 icmp = packet[ICMPv6DestUnreach]
7616 self.assertEqual(icmp.code, 1)
7617 inner = icmp[IPerror6]
7618 self.assertEqual(inner.src, self.pg0.remote_ip6)
7619 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007620 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007621 if inner.haslayer(TCPerror):
7622 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7623 elif inner.haslayer(UDPerror):
7624 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7625 else:
7626 self.assertEqual(inner[ICMPv6EchoRequest].id,
7627 self.icmp_id_in)
7628 except:
7629 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7630 raise
7631
Matus Fabian029f3d22017-06-15 02:28:50 -07007632 def test_hairpinning(self):
7633 """ NAT64 hairpinning """
7634
7635 client = self.pg0.remote_hosts[0]
7636 server = self.pg0.remote_hosts[1]
7637 server_tcp_in_port = 22
7638 server_tcp_out_port = 4022
7639 server_udp_in_port = 23
7640 server_udp_out_port = 4023
7641 client_tcp_in_port = 1234
7642 client_udp_in_port = 1235
7643 client_tcp_out_port = 0
7644 client_udp_out_port = 0
7645 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7646 nat_addr_ip6 = ip.src
7647
7648 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7649 self.nat_addr_n)
7650 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7651 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7652
7653 self.vapi.nat64_add_del_static_bib(server.ip6n,
7654 self.nat_addr_n,
7655 server_tcp_in_port,
7656 server_tcp_out_port,
7657 IP_PROTOS.tcp)
7658 self.vapi.nat64_add_del_static_bib(server.ip6n,
7659 self.nat_addr_n,
7660 server_udp_in_port,
7661 server_udp_out_port,
7662 IP_PROTOS.udp)
7663
7664 # client to server
7665 pkts = []
7666 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7667 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7668 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7669 pkts.append(p)
7670 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7671 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7672 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7673 pkts.append(p)
7674 self.pg0.add_stream(pkts)
7675 self.pg_enable_capture(self.pg_interfaces)
7676 self.pg_start()
7677 capture = self.pg0.get_capture(len(pkts))
7678 for packet in capture:
7679 try:
7680 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7681 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007682 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007683 if packet.haslayer(TCP):
7684 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7685 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007686 client_tcp_out_port = packet[TCP].sport
7687 else:
7688 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7689 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007690 client_udp_out_port = packet[UDP].sport
7691 except:
7692 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7693 raise
7694
7695 # server to client
7696 pkts = []
7697 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7698 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7699 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7700 pkts.append(p)
7701 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7702 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7703 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7704 pkts.append(p)
7705 self.pg0.add_stream(pkts)
7706 self.pg_enable_capture(self.pg_interfaces)
7707 self.pg_start()
7708 capture = self.pg0.get_capture(len(pkts))
7709 for packet in capture:
7710 try:
7711 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7712 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007713 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007714 if packet.haslayer(TCP):
7715 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7716 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007717 else:
7718 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7719 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007720 except:
7721 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7722 raise
7723
7724 # ICMP error
7725 pkts = []
7726 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7727 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7728 ICMPv6DestUnreach(code=1) /
7729 packet[IPv6] for packet in capture]
7730 self.pg0.add_stream(pkts)
7731 self.pg_enable_capture(self.pg_interfaces)
7732 self.pg_start()
7733 capture = self.pg0.get_capture(len(pkts))
7734 for packet in capture:
7735 try:
7736 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7737 self.assertEqual(packet[IPv6].dst, server.ip6)
7738 icmp = packet[ICMPv6DestUnreach]
7739 self.assertEqual(icmp.code, 1)
7740 inner = icmp[IPerror6]
7741 self.assertEqual(inner.src, server.ip6)
7742 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007743 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007744 if inner.haslayer(TCPerror):
7745 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7746 self.assertEqual(inner[TCPerror].dport,
7747 client_tcp_out_port)
7748 else:
7749 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7750 self.assertEqual(inner[UDPerror].dport,
7751 client_udp_out_port)
7752 except:
7753 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7754 raise
7755
Matus Fabian428dc912017-06-21 06:15:18 -07007756 def test_prefix(self):
7757 """ NAT64 Network-Specific Prefix """
7758
7759 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7760 self.nat_addr_n)
7761 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7762 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7763 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7764 self.vrf1_nat_addr_n,
7765 vrf_id=self.vrf1_id)
7766 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7767
7768 # Add global prefix
7769 global_pref64 = "2001:db8::"
7770 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7771 global_pref64_len = 32
7772 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7773
7774 prefix = self.vapi.nat64_prefix_dump()
7775 self.assertEqual(len(prefix), 1)
7776 self.assertEqual(prefix[0].prefix, global_pref64_n)
7777 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7778 self.assertEqual(prefix[0].vrf_id, 0)
7779
7780 # Add tenant specific prefix
7781 vrf1_pref64 = "2001:db8:122:300::"
7782 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7783 vrf1_pref64_len = 56
7784 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7785 vrf1_pref64_len,
7786 vrf_id=self.vrf1_id)
7787 prefix = self.vapi.nat64_prefix_dump()
7788 self.assertEqual(len(prefix), 2)
7789
7790 # Global prefix
7791 pkts = self.create_stream_in_ip6(self.pg0,
7792 self.pg1,
7793 pref=global_pref64,
7794 plen=global_pref64_len)
7795 self.pg0.add_stream(pkts)
7796 self.pg_enable_capture(self.pg_interfaces)
7797 self.pg_start()
7798 capture = self.pg1.get_capture(len(pkts))
7799 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7800 dst_ip=self.pg1.remote_ip4)
7801
7802 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7803 self.pg1.add_stream(pkts)
7804 self.pg_enable_capture(self.pg_interfaces)
7805 self.pg_start()
7806 capture = self.pg0.get_capture(len(pkts))
7807 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7808 global_pref64,
7809 global_pref64_len)
7810 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7811
7812 # Tenant specific prefix
7813 pkts = self.create_stream_in_ip6(self.pg2,
7814 self.pg1,
7815 pref=vrf1_pref64,
7816 plen=vrf1_pref64_len)
7817 self.pg2.add_stream(pkts)
7818 self.pg_enable_capture(self.pg_interfaces)
7819 self.pg_start()
7820 capture = self.pg1.get_capture(len(pkts))
7821 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7822 dst_ip=self.pg1.remote_ip4)
7823
7824 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7825 self.pg1.add_stream(pkts)
7826 self.pg_enable_capture(self.pg_interfaces)
7827 self.pg_start()
7828 capture = self.pg2.get_capture(len(pkts))
7829 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7830 vrf1_pref64,
7831 vrf1_pref64_len)
7832 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7833
Matus Fabianf8cd5812017-07-11 03:55:02 -07007834 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007835 """ NAT64 translate packet with unknown protocol """
7836
7837 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7838 self.nat_addr_n)
7839 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7840 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7841 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7842
7843 # in2out
7844 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7845 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7846 TCP(sport=self.tcp_port_in, dport=20))
7847 self.pg0.add_stream(p)
7848 self.pg_enable_capture(self.pg_interfaces)
7849 self.pg_start()
7850 p = self.pg1.get_capture(1)
7851
7852 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007853 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007854 GRE() /
7855 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7856 TCP(sport=1234, dport=1234))
7857 self.pg0.add_stream(p)
7858 self.pg_enable_capture(self.pg_interfaces)
7859 self.pg_start()
7860 p = self.pg1.get_capture(1)
7861 packet = p[0]
7862 try:
7863 self.assertEqual(packet[IP].src, self.nat_addr)
7864 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007865 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02007866 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007867 except:
7868 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7869 raise
7870
7871 # out2in
7872 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7873 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7874 GRE() /
7875 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7876 TCP(sport=1234, dport=1234))
7877 self.pg1.add_stream(p)
7878 self.pg_enable_capture(self.pg_interfaces)
7879 self.pg_start()
7880 p = self.pg0.get_capture(1)
7881 packet = p[0]
7882 try:
7883 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007884 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7885 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007886 except:
7887 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7888 raise
7889
Matus Fabianf8cd5812017-07-11 03:55:02 -07007890 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007891 """ NAT64 translate packet with unknown protocol - hairpinning """
7892
7893 client = self.pg0.remote_hosts[0]
7894 server = self.pg0.remote_hosts[1]
7895 server_tcp_in_port = 22
7896 server_tcp_out_port = 4022
7897 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007898 client_tcp_out_port = 1235
7899 server_nat_ip = "10.0.0.100"
7900 client_nat_ip = "10.0.0.110"
7901 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7902 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7903 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7904 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007905
Matus Fabianf8cd5812017-07-11 03:55:02 -07007906 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7907 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007908 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7909 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7910
7911 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007912 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007913 server_tcp_in_port,
7914 server_tcp_out_port,
7915 IP_PROTOS.tcp)
7916
Matus Fabianf8cd5812017-07-11 03:55:02 -07007917 self.vapi.nat64_add_del_static_bib(server.ip6n,
7918 server_nat_ip_n,
7919 0,
7920 0,
7921 IP_PROTOS.gre)
7922
7923 self.vapi.nat64_add_del_static_bib(client.ip6n,
7924 client_nat_ip_n,
7925 client_tcp_in_port,
7926 client_tcp_out_port,
7927 IP_PROTOS.tcp)
7928
Matus Fabian7968e6c2017-07-06 05:37:49 -07007929 # client to server
7930 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007931 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007932 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7933 self.pg0.add_stream(p)
7934 self.pg_enable_capture(self.pg_interfaces)
7935 self.pg_start()
7936 p = self.pg0.get_capture(1)
7937
7938 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007939 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007940 GRE() /
7941 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7942 TCP(sport=1234, dport=1234))
7943 self.pg0.add_stream(p)
7944 self.pg_enable_capture(self.pg_interfaces)
7945 self.pg_start()
7946 p = self.pg0.get_capture(1)
7947 packet = p[0]
7948 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007949 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007950 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007951 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007952 except:
7953 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7954 raise
7955
7956 # server to client
7957 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007958 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007959 GRE() /
7960 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7961 TCP(sport=1234, dport=1234))
7962 self.pg0.add_stream(p)
7963 self.pg_enable_capture(self.pg_interfaces)
7964 self.pg_start()
7965 p = self.pg0.get_capture(1)
7966 packet = p[0]
7967 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007968 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007969 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007970 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007971 except:
7972 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7973 raise
7974
Matus Fabian36ea2d62017-10-24 04:13:49 -07007975 def test_one_armed_nat64(self):
7976 """ One armed NAT64 """
7977 external_port = 0
7978 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7979 '64:ff9b::',
7980 96)
7981
7982 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7983 self.nat_addr_n)
7984 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7985 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7986
7987 # in2out
7988 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7989 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7990 TCP(sport=12345, dport=80))
7991 self.pg3.add_stream(p)
7992 self.pg_enable_capture(self.pg_interfaces)
7993 self.pg_start()
7994 capture = self.pg3.get_capture(1)
7995 p = capture[0]
7996 try:
7997 ip = p[IP]
7998 tcp = p[TCP]
7999 self.assertEqual(ip.src, self.nat_addr)
8000 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8001 self.assertNotEqual(tcp.sport, 12345)
8002 external_port = tcp.sport
8003 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008004 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008005 except:
8006 self.logger.error(ppp("Unexpected or invalid packet:", p))
8007 raise
8008
8009 # out2in
8010 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8011 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8012 TCP(sport=80, dport=external_port))
8013 self.pg3.add_stream(p)
8014 self.pg_enable_capture(self.pg_interfaces)
8015 self.pg_start()
8016 capture = self.pg3.get_capture(1)
8017 p = capture[0]
8018 try:
8019 ip = p[IPv6]
8020 tcp = p[TCP]
8021 self.assertEqual(ip.src, remote_host_ip6)
8022 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8023 self.assertEqual(tcp.sport, 80)
8024 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008025 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008026 except:
8027 self.logger.error(ppp("Unexpected or invalid packet:", p))
8028 raise
8029
Matus Fabianefcd1e92017-08-15 06:59:19 -07008030 def test_frag_in_order(self):
8031 """ NAT64 translate fragments arriving in order """
8032 self.tcp_port_in = random.randint(1025, 65535)
8033
8034 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8035 self.nat_addr_n)
8036 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8037 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8038
8039 reass = self.vapi.nat_reass_dump()
8040 reass_n_start = len(reass)
8041
8042 # in2out
8043 data = 'a' * 200
8044 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8045 self.tcp_port_in, 20, data)
8046 self.pg0.add_stream(pkts)
8047 self.pg_enable_capture(self.pg_interfaces)
8048 self.pg_start()
8049 frags = self.pg1.get_capture(len(pkts))
8050 p = self.reass_frags_and_verify(frags,
8051 self.nat_addr,
8052 self.pg1.remote_ip4)
8053 self.assertEqual(p[TCP].dport, 20)
8054 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8055 self.tcp_port_out = p[TCP].sport
8056 self.assertEqual(data, p[Raw].load)
8057
8058 # out2in
8059 data = "A" * 4 + "b" * 16 + "C" * 3
8060 pkts = self.create_stream_frag(self.pg1,
8061 self.nat_addr,
8062 20,
8063 self.tcp_port_out,
8064 data)
8065 self.pg1.add_stream(pkts)
8066 self.pg_enable_capture(self.pg_interfaces)
8067 self.pg_start()
8068 frags = self.pg0.get_capture(len(pkts))
8069 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8070 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8071 self.assertEqual(p[TCP].sport, 20)
8072 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8073 self.assertEqual(data, p[Raw].load)
8074
8075 reass = self.vapi.nat_reass_dump()
8076 reass_n_end = len(reass)
8077
8078 self.assertEqual(reass_n_end - reass_n_start, 2)
8079
8080 def test_reass_hairpinning(self):
8081 """ NAT64 fragments hairpinning """
8082 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008083 server = self.pg0.remote_hosts[1]
8084 server_in_port = random.randint(1025, 65535)
8085 server_out_port = random.randint(1025, 65535)
8086 client_in_port = random.randint(1025, 65535)
8087 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8088 nat_addr_ip6 = ip.src
8089
8090 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8091 self.nat_addr_n)
8092 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8093 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8094
8095 # add static BIB entry for server
8096 self.vapi.nat64_add_del_static_bib(server.ip6n,
8097 self.nat_addr_n,
8098 server_in_port,
8099 server_out_port,
8100 IP_PROTOS.tcp)
8101
8102 # send packet from host to server
8103 pkts = self.create_stream_frag_ip6(self.pg0,
8104 self.nat_addr,
8105 client_in_port,
8106 server_out_port,
8107 data)
8108 self.pg0.add_stream(pkts)
8109 self.pg_enable_capture(self.pg_interfaces)
8110 self.pg_start()
8111 frags = self.pg0.get_capture(len(pkts))
8112 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8113 self.assertNotEqual(p[TCP].sport, client_in_port)
8114 self.assertEqual(p[TCP].dport, server_in_port)
8115 self.assertEqual(data, p[Raw].load)
8116
8117 def test_frag_out_of_order(self):
8118 """ NAT64 translate fragments arriving out of order """
8119 self.tcp_port_in = random.randint(1025, 65535)
8120
8121 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8122 self.nat_addr_n)
8123 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8124 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8125
8126 # in2out
8127 data = 'a' * 200
8128 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8129 self.tcp_port_in, 20, data)
8130 pkts.reverse()
8131 self.pg0.add_stream(pkts)
8132 self.pg_enable_capture(self.pg_interfaces)
8133 self.pg_start()
8134 frags = self.pg1.get_capture(len(pkts))
8135 p = self.reass_frags_and_verify(frags,
8136 self.nat_addr,
8137 self.pg1.remote_ip4)
8138 self.assertEqual(p[TCP].dport, 20)
8139 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8140 self.tcp_port_out = p[TCP].sport
8141 self.assertEqual(data, p[Raw].load)
8142
8143 # out2in
8144 data = "A" * 4 + "B" * 16 + "C" * 3
8145 pkts = self.create_stream_frag(self.pg1,
8146 self.nat_addr,
8147 20,
8148 self.tcp_port_out,
8149 data)
8150 pkts.reverse()
8151 self.pg1.add_stream(pkts)
8152 self.pg_enable_capture(self.pg_interfaces)
8153 self.pg_start()
8154 frags = self.pg0.get_capture(len(pkts))
8155 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8156 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8157 self.assertEqual(p[TCP].sport, 20)
8158 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8159 self.assertEqual(data, p[Raw].load)
8160
Matus Fabian0938dcf2017-11-08 01:59:38 -08008161 def test_interface_addr(self):
8162 """ Acquire NAT64 pool addresses from interface """
8163 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
8164
8165 # no address in NAT64 pool
8166 adresses = self.vapi.nat44_address_dump()
8167 self.assertEqual(0, len(adresses))
8168
8169 # configure interface address and check NAT64 address pool
8170 self.pg4.config_ip4()
8171 addresses = self.vapi.nat64_pool_addr_dump()
8172 self.assertEqual(len(addresses), 1)
8173 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8174
8175 # remove interface address and check NAT64 address pool
8176 self.pg4.unconfig_ip4()
8177 addresses = self.vapi.nat64_pool_addr_dump()
8178 self.assertEqual(0, len(adresses))
8179
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008180 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008181 def test_ipfix_max_bibs_sessions(self):
8182 """ IPFIX logging maximum session and BIB entries exceeded """
8183 max_bibs = 1280
8184 max_sessions = 2560
8185 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8186 '64:ff9b::',
8187 96)
8188
8189 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8190 self.nat_addr_n)
8191 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8192 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8193
8194 pkts = []
8195 src = ""
8196 for i in range(0, max_bibs):
8197 src = "fd01:aa::%x" % (i)
8198 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8199 IPv6(src=src, dst=remote_host_ip6) /
8200 TCP(sport=12345, dport=80))
8201 pkts.append(p)
8202 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8203 IPv6(src=src, dst=remote_host_ip6) /
8204 TCP(sport=12345, dport=22))
8205 pkts.append(p)
8206 self.pg0.add_stream(pkts)
8207 self.pg_enable_capture(self.pg_interfaces)
8208 self.pg_start()
8209 self.pg1.get_capture(max_sessions)
8210
8211 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8212 src_address=self.pg3.local_ip4n,
8213 path_mtu=512,
8214 template_interval=10)
8215 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
8216 src_port=self.ipfix_src_port)
8217
8218 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8219 IPv6(src=src, dst=remote_host_ip6) /
8220 TCP(sport=12345, dport=25))
8221 self.pg0.add_stream(p)
8222 self.pg_enable_capture(self.pg_interfaces)
8223 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008224 self.pg1.assert_nothing_captured()
8225 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008226 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8227 capture = self.pg3.get_capture(9)
8228 ipfix = IPFIXDecoder()
8229 # first load template
8230 for p in capture:
8231 self.assertTrue(p.haslayer(IPFIX))
8232 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8233 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8234 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8235 self.assertEqual(p[UDP].dport, 4739)
8236 self.assertEqual(p[IPFIX].observationDomainID,
8237 self.ipfix_domain_id)
8238 if p.haslayer(Template):
8239 ipfix.add_template(p.getlayer(Template))
8240 # verify events in data set
8241 for p in capture:
8242 if p.haslayer(Data):
8243 data = ipfix.decode_data_set(p.getlayer(Set))
8244 self.verify_ipfix_max_sessions(data, max_sessions)
8245
8246 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8247 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8248 TCP(sport=12345, dport=80))
8249 self.pg0.add_stream(p)
8250 self.pg_enable_capture(self.pg_interfaces)
8251 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008252 self.pg1.assert_nothing_captured()
8253 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008254 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8255 capture = self.pg3.get_capture(1)
8256 # verify events in data set
8257 for p in capture:
8258 self.assertTrue(p.haslayer(IPFIX))
8259 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8260 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8261 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8262 self.assertEqual(p[UDP].dport, 4739)
8263 self.assertEqual(p[IPFIX].observationDomainID,
8264 self.ipfix_domain_id)
8265 if p.haslayer(Data):
8266 data = ipfix.decode_data_set(p.getlayer(Set))
8267 self.verify_ipfix_max_bibs(data, max_bibs)
8268
8269 def test_ipfix_max_frags(self):
8270 """ IPFIX logging maximum fragments pending reassembly exceeded """
8271 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8272 self.nat_addr_n)
8273 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8274 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008275 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008276 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8277 src_address=self.pg3.local_ip4n,
8278 path_mtu=512,
8279 template_interval=10)
8280 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
8281 src_port=self.ipfix_src_port)
8282
8283 data = 'a' * 200
8284 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8285 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008286 pkts.reverse()
8287 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008288 self.pg_enable_capture(self.pg_interfaces)
8289 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008290 self.pg1.assert_nothing_captured()
8291 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008292 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8293 capture = self.pg3.get_capture(9)
8294 ipfix = IPFIXDecoder()
8295 # first load template
8296 for p in capture:
8297 self.assertTrue(p.haslayer(IPFIX))
8298 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8299 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8300 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8301 self.assertEqual(p[UDP].dport, 4739)
8302 self.assertEqual(p[IPFIX].observationDomainID,
8303 self.ipfix_domain_id)
8304 if p.haslayer(Template):
8305 ipfix.add_template(p.getlayer(Template))
8306 # verify events in data set
8307 for p in capture:
8308 if p.haslayer(Data):
8309 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008310 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008311 self.pg0.remote_ip6n)
8312
8313 def test_ipfix_bib_ses(self):
8314 """ IPFIX logging NAT64 BIB/session create and delete events """
8315 self.tcp_port_in = random.randint(1025, 65535)
8316 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8317 '64:ff9b::',
8318 96)
8319
8320 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8321 self.nat_addr_n)
8322 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8323 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8324 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8325 src_address=self.pg3.local_ip4n,
8326 path_mtu=512,
8327 template_interval=10)
8328 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
8329 src_port=self.ipfix_src_port)
8330
8331 # Create
8332 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8333 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8334 TCP(sport=self.tcp_port_in, dport=25))
8335 self.pg0.add_stream(p)
8336 self.pg_enable_capture(self.pg_interfaces)
8337 self.pg_start()
8338 p = self.pg1.get_capture(1)
8339 self.tcp_port_out = p[0][TCP].sport
8340 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8341 capture = self.pg3.get_capture(10)
8342 ipfix = IPFIXDecoder()
8343 # first load template
8344 for p in capture:
8345 self.assertTrue(p.haslayer(IPFIX))
8346 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8347 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8348 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8349 self.assertEqual(p[UDP].dport, 4739)
8350 self.assertEqual(p[IPFIX].observationDomainID,
8351 self.ipfix_domain_id)
8352 if p.haslayer(Template):
8353 ipfix.add_template(p.getlayer(Template))
8354 # verify events in data set
8355 for p in capture:
8356 if p.haslayer(Data):
8357 data = ipfix.decode_data_set(p.getlayer(Set))
8358 if ord(data[0][230]) == 10:
8359 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8360 elif ord(data[0][230]) == 6:
8361 self.verify_ipfix_nat64_ses(data,
8362 1,
8363 self.pg0.remote_ip6n,
8364 self.pg1.remote_ip4,
8365 25)
8366 else:
8367 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8368
8369 # Delete
8370 self.pg_enable_capture(self.pg_interfaces)
8371 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8372 self.nat_addr_n,
8373 is_add=0)
8374 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8375 capture = self.pg3.get_capture(2)
8376 # verify events in data set
8377 for p in capture:
8378 self.assertTrue(p.haslayer(IPFIX))
8379 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8380 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8381 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8382 self.assertEqual(p[UDP].dport, 4739)
8383 self.assertEqual(p[IPFIX].observationDomainID,
8384 self.ipfix_domain_id)
8385 if p.haslayer(Data):
8386 data = ipfix.decode_data_set(p.getlayer(Set))
8387 if ord(data[0][230]) == 11:
8388 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8389 elif ord(data[0][230]) == 7:
8390 self.verify_ipfix_nat64_ses(data,
8391 0,
8392 self.pg0.remote_ip6n,
8393 self.pg1.remote_ip4,
8394 25)
8395 else:
8396 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8397
Matus Fabianad1f3e12018-11-28 21:26:34 -08008398 def test_syslog_sess(self):
8399 """ Test syslog session creation and deletion """
8400 self.tcp_port_in = random.randint(1025, 65535)
8401 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8402 '64:ff9b::',
8403 96)
8404
8405 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8406 self.nat_addr_n)
8407 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8408 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8409 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
8410 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
8411
8412 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8413 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8414 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8415 self.pg0.add_stream(p)
8416 self.pg_enable_capture(self.pg_interfaces)
8417 self.pg_start()
8418 p = self.pg1.get_capture(1)
8419 self.tcp_port_out = p[0][TCP].sport
8420 capture = self.pg3.get_capture(1)
8421 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8422
8423 self.pg_enable_capture(self.pg_interfaces)
8424 self.pg_start()
8425 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8426 self.nat_addr_n,
8427 is_add=0)
8428 capture = self.pg3.get_capture(1)
8429 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8430
Matus Fabian06596c52017-06-06 04:53:28 -07008431 def nat64_get_ses_num(self):
8432 """
8433 Return number of active NAT64 sessions.
8434 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07008435 st = self.vapi.nat64_st_dump()
8436 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07008437
8438 def clear_nat64(self):
8439 """
8440 Clear NAT64 configuration.
8441 """
Matus Fabiana431ad12018-01-04 04:03:14 -08008442 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
8443 domain_id=self.ipfix_domain_id)
8444 self.ipfix_src_port = 4739
8445 self.ipfix_domain_id = 1
8446
Matus Fabianad1f3e12018-11-28 21:26:34 -08008447 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8448
Matus Fabian878c6462018-08-23 00:33:35 -07008449 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07008450
8451 interfaces = self.vapi.nat64_interface_dump()
8452 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07008453 if intf.is_inside > 1:
8454 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8455 0,
8456 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07008457 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8458 intf.is_inside,
8459 is_add=0)
8460
Matus Fabiana431ad12018-01-04 04:03:14 -08008461 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07008462 for bibe in bib:
8463 if bibe.is_static:
8464 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8465 bibe.o_addr,
8466 bibe.i_port,
8467 bibe.o_port,
8468 bibe.proto,
8469 bibe.vrf_id,
8470 is_add=0)
8471
8472 adresses = self.vapi.nat64_pool_addr_dump()
8473 for addr in adresses:
8474 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8475 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07008476 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07008477 is_add=0)
8478
Matus Fabian428dc912017-06-21 06:15:18 -07008479 prefixes = self.vapi.nat64_prefix_dump()
8480 for prefix in prefixes:
8481 self.vapi.nat64_add_del_prefix(prefix.prefix,
8482 prefix.prefix_len,
8483 vrf_id=prefix.vrf_id,
8484 is_add=0)
8485
Matus Fabianfd0d5082018-12-18 01:08:51 -08008486 bibs = self.statistics.get_counter('/nat64/total-bibs')
8487 self.assertEqual(bibs[0][0], 0)
8488 sessions = self.statistics.get_counter('/nat64/total-sessions')
8489 self.assertEqual(sessions[0][0], 0)
8490
Matus Fabian06596c52017-06-06 04:53:28 -07008491 def tearDown(self):
8492 super(TestNAT64, self).tearDown()
8493 if not self.vpp_dead:
8494 self.logger.info(self.vapi.cli("show nat64 pool"))
8495 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07008496 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07008497 self.logger.info(self.vapi.cli("show nat64 bib all"))
8498 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07008499 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07008500 self.clear_nat64()
8501
Matus Fabian8ebe6252017-11-06 05:04:53 -08008502
8503class TestDSlite(MethodHolder):
8504 """ DS-Lite Test Cases """
8505
8506 @classmethod
8507 def setUpClass(cls):
8508 super(TestDSlite, cls).setUpClass()
8509
8510 try:
8511 cls.nat_addr = '10.0.0.3'
8512 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8513
Matus Fabianad1f3e12018-11-28 21:26:34 -08008514 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008515 cls.pg0.admin_up()
8516 cls.pg0.config_ip4()
8517 cls.pg0.resolve_arp()
8518 cls.pg1.admin_up()
8519 cls.pg1.config_ip6()
8520 cls.pg1.generate_remote_hosts(2)
8521 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08008522 cls.pg2.admin_up()
8523 cls.pg2.config_ip4()
8524 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08008525
8526 except Exception:
8527 super(TestDSlite, cls).tearDownClass()
8528 raise
8529
Matus Fabianad1f3e12018-11-28 21:26:34 -08008530 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8531 sv6enc, proto):
8532 message = data.decode('utf-8')
8533 try:
8534 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08008535 except ParseError as e:
8536 self.logger.error(e)
8537 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08008538 self.assertEqual(message.severity, SyslogSeverity.info)
8539 self.assertEqual(message.appname, 'NAT')
8540 self.assertEqual(message.msgid, 'APMADD')
8541 sd_params = message.sd.get('napmap')
8542 self.assertTrue(sd_params is not None)
8543 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8544 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8545 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8546 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8547 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8548 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8549 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8550 self.assertTrue(sd_params.get('SSUBIX') is not None)
8551 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008552
Matus Fabian8ebe6252017-11-06 05:04:53 -08008553 def test_dslite(self):
8554 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07008555 nat_config = self.vapi.nat_show_config()
8556 self.assertEqual(0, nat_config.dslite_ce)
8557
Matus Fabian8ebe6252017-11-06 05:04:53 -08008558 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8559 self.nat_addr_n)
8560 aftr_ip4 = '192.0.0.1'
8561 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8562 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8563 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8564 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008565 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008566
8567 # UDP
8568 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8569 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8570 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8571 UDP(sport=20000, dport=10000))
8572 self.pg1.add_stream(p)
8573 self.pg_enable_capture(self.pg_interfaces)
8574 self.pg_start()
8575 capture = self.pg0.get_capture(1)
8576 capture = capture[0]
8577 self.assertFalse(capture.haslayer(IPv6))
8578 self.assertEqual(capture[IP].src, self.nat_addr)
8579 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8580 self.assertNotEqual(capture[UDP].sport, 20000)
8581 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008582 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008583 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008584 capture = self.pg2.get_capture(1)
8585 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8586 20000, self.nat_addr, out_port,
8587 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008588
8589 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8590 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8591 UDP(sport=10000, dport=out_port))
8592 self.pg0.add_stream(p)
8593 self.pg_enable_capture(self.pg_interfaces)
8594 self.pg_start()
8595 capture = self.pg1.get_capture(1)
8596 capture = capture[0]
8597 self.assertEqual(capture[IPv6].src, aftr_ip6)
8598 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8599 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8600 self.assertEqual(capture[IP].dst, '192.168.1.1')
8601 self.assertEqual(capture[UDP].sport, 10000)
8602 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008603 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008604
8605 # TCP
8606 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8607 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8608 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8609 TCP(sport=20001, dport=10001))
8610 self.pg1.add_stream(p)
8611 self.pg_enable_capture(self.pg_interfaces)
8612 self.pg_start()
8613 capture = self.pg0.get_capture(1)
8614 capture = capture[0]
8615 self.assertFalse(capture.haslayer(IPv6))
8616 self.assertEqual(capture[IP].src, self.nat_addr)
8617 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8618 self.assertNotEqual(capture[TCP].sport, 20001)
8619 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008620 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008621 out_port = capture[TCP].sport
8622
8623 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8624 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8625 TCP(sport=10001, dport=out_port))
8626 self.pg0.add_stream(p)
8627 self.pg_enable_capture(self.pg_interfaces)
8628 self.pg_start()
8629 capture = self.pg1.get_capture(1)
8630 capture = capture[0]
8631 self.assertEqual(capture[IPv6].src, aftr_ip6)
8632 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8633 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8634 self.assertEqual(capture[IP].dst, '192.168.1.1')
8635 self.assertEqual(capture[TCP].sport, 10001)
8636 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008637 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008638
8639 # ICMP
8640 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8641 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8642 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8643 ICMP(id=4000, type='echo-request'))
8644 self.pg1.add_stream(p)
8645 self.pg_enable_capture(self.pg_interfaces)
8646 self.pg_start()
8647 capture = self.pg0.get_capture(1)
8648 capture = capture[0]
8649 self.assertFalse(capture.haslayer(IPv6))
8650 self.assertEqual(capture[IP].src, self.nat_addr)
8651 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8652 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008653 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008654 out_id = capture[ICMP].id
8655
8656 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8657 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8658 ICMP(id=out_id, type='echo-reply'))
8659 self.pg0.add_stream(p)
8660 self.pg_enable_capture(self.pg_interfaces)
8661 self.pg_start()
8662 capture = self.pg1.get_capture(1)
8663 capture = capture[0]
8664 self.assertEqual(capture[IPv6].src, aftr_ip6)
8665 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8666 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8667 self.assertEqual(capture[IP].dst, '192.168.1.1')
8668 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008669 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008670
Matus Fabian331acc62017-12-08 03:38:51 -08008671 # ping DS-Lite AFTR tunnel endpoint address
8672 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8673 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8674 ICMPv6EchoRequest())
8675 self.pg1.add_stream(p)
8676 self.pg_enable_capture(self.pg_interfaces)
8677 self.pg_start()
8678 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008679 capture = capture[0]
8680 self.assertEqual(capture[IPv6].src, aftr_ip6)
8681 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8682 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8683
Matus Fabianfd0d5082018-12-18 01:08:51 -08008684 b4s = self.statistics.get_counter('/dslite/total-b4s')
8685 self.assertEqual(b4s[0][0], 2)
8686 sessions = self.statistics.get_counter('/dslite/total-sessions')
8687 self.assertEqual(sessions[0][0], 3)
8688
Matus Fabian8ebe6252017-11-06 05:04:53 -08008689 def tearDown(self):
8690 super(TestDSlite, self).tearDown()
8691 if not self.vpp_dead:
8692 self.logger.info(self.vapi.cli("show dslite pool"))
8693 self.logger.info(
8694 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8695 self.logger.info(self.vapi.cli("show dslite sessions"))
8696
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008697
8698class TestDSliteCE(MethodHolder):
8699 """ DS-Lite CE Test Cases """
8700
8701 @classmethod
8702 def setUpConstants(cls):
8703 super(TestDSliteCE, cls).setUpConstants()
8704 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8705
8706 @classmethod
8707 def setUpClass(cls):
8708 super(TestDSliteCE, cls).setUpClass()
8709
8710 try:
8711 cls.create_pg_interfaces(range(2))
8712 cls.pg0.admin_up()
8713 cls.pg0.config_ip4()
8714 cls.pg0.resolve_arp()
8715 cls.pg1.admin_up()
8716 cls.pg1.config_ip6()
8717 cls.pg1.generate_remote_hosts(1)
8718 cls.pg1.configure_ipv6_neighbors()
8719
8720 except Exception:
8721 super(TestDSliteCE, cls).tearDownClass()
8722 raise
8723
8724 def test_dslite_ce(self):
8725 """ Test DS-Lite CE """
8726
Matus Fabian69ce30d2018-08-22 01:27:10 -07008727 nat_config = self.vapi.nat_show_config()
8728 self.assertEqual(1, nat_config.dslite_ce)
8729
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008730 b4_ip4 = '192.0.0.2'
8731 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8732 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8733 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8734 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8735
8736 aftr_ip4 = '192.0.0.1'
8737 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8738 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8739 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8740 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8741
8742 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8743 dst_address_length=128,
8744 next_hop_address=self.pg1.remote_ip6n,
8745 next_hop_sw_if_index=self.pg1.sw_if_index,
8746 is_ipv6=1)
8747
8748 # UDP encapsulation
8749 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8750 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8751 UDP(sport=10000, dport=20000))
8752 self.pg0.add_stream(p)
8753 self.pg_enable_capture(self.pg_interfaces)
8754 self.pg_start()
8755 capture = self.pg1.get_capture(1)
8756 capture = capture[0]
8757 self.assertEqual(capture[IPv6].src, b4_ip6)
8758 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8759 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8760 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8761 self.assertEqual(capture[UDP].sport, 10000)
8762 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008763 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008764
8765 # UDP decapsulation
8766 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8767 IPv6(dst=b4_ip6, src=aftr_ip6) /
8768 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8769 UDP(sport=20000, dport=10000))
8770 self.pg1.add_stream(p)
8771 self.pg_enable_capture(self.pg_interfaces)
8772 self.pg_start()
8773 capture = self.pg0.get_capture(1)
8774 capture = capture[0]
8775 self.assertFalse(capture.haslayer(IPv6))
8776 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8777 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8778 self.assertEqual(capture[UDP].sport, 20000)
8779 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008780 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008781
8782 # ping DS-Lite B4 tunnel endpoint address
8783 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8784 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8785 ICMPv6EchoRequest())
8786 self.pg1.add_stream(p)
8787 self.pg_enable_capture(self.pg_interfaces)
8788 self.pg_start()
8789 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008790 capture = capture[0]
8791 self.assertEqual(capture[IPv6].src, b4_ip6)
8792 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8793 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8794
8795 def tearDown(self):
8796 super(TestDSliteCE, self).tearDown()
8797 if not self.vpp_dead:
8798 self.logger.info(
8799 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8800 self.logger.info(
8801 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8802
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008803
8804class TestNAT66(MethodHolder):
8805 """ NAT66 Test Cases """
8806
8807 @classmethod
8808 def setUpClass(cls):
8809 super(TestNAT66, cls).setUpClass()
8810
8811 try:
8812 cls.nat_addr = 'fd01:ff::2'
8813 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8814
8815 cls.create_pg_interfaces(range(2))
8816 cls.interfaces = list(cls.pg_interfaces)
8817
8818 for i in cls.interfaces:
8819 i.admin_up()
8820 i.config_ip6()
8821 i.configure_ipv6_neighbors()
8822
8823 except Exception:
8824 super(TestNAT66, cls).tearDownClass()
8825 raise
8826
8827 def test_static(self):
8828 """ 1:1 NAT66 test """
8829 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8830 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8831 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8832 self.nat_addr_n)
8833
8834 # in2out
8835 pkts = []
8836 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8837 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8838 TCP())
8839 pkts.append(p)
8840 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8841 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8842 UDP())
8843 pkts.append(p)
8844 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8845 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8846 ICMPv6EchoRequest())
8847 pkts.append(p)
8848 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8849 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8850 GRE() / IP() / TCP())
8851 pkts.append(p)
8852 self.pg0.add_stream(pkts)
8853 self.pg_enable_capture(self.pg_interfaces)
8854 self.pg_start()
8855 capture = self.pg1.get_capture(len(pkts))
8856 for packet in capture:
8857 try:
8858 self.assertEqual(packet[IPv6].src, self.nat_addr)
8859 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008860 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008861 except:
8862 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8863 raise
8864
8865 # out2in
8866 pkts = []
8867 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8868 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8869 TCP())
8870 pkts.append(p)
8871 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8872 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8873 UDP())
8874 pkts.append(p)
8875 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8876 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8877 ICMPv6EchoReply())
8878 pkts.append(p)
8879 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8880 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8881 GRE() / IP() / TCP())
8882 pkts.append(p)
8883 self.pg1.add_stream(pkts)
8884 self.pg_enable_capture(self.pg_interfaces)
8885 self.pg_start()
8886 capture = self.pg0.get_capture(len(pkts))
8887 for packet in capture:
8888 try:
8889 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8890 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008891 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008892 except:
8893 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8894 raise
8895
8896 sm = self.vapi.nat66_static_mapping_dump()
8897 self.assertEqual(len(sm), 1)
8898 self.assertEqual(sm[0].total_pkts, 8)
8899
Juraj Sloboda9341e342018-04-13 12:00:46 +02008900 def test_check_no_translate(self):
8901 """ NAT66 translate only when egress interface is outside interface """
8902 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8903 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8904 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8905 self.nat_addr_n)
8906
8907 # in2out
8908 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8909 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8910 UDP())
8911 self.pg0.add_stream([p])
8912 self.pg_enable_capture(self.pg_interfaces)
8913 self.pg_start()
8914 capture = self.pg1.get_capture(1)
8915 packet = capture[0]
8916 try:
8917 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8918 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8919 except:
8920 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8921 raise
8922
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008923 def clear_nat66(self):
8924 """
8925 Clear NAT66 configuration.
8926 """
8927 interfaces = self.vapi.nat66_interface_dump()
8928 for intf in interfaces:
8929 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8930 intf.is_inside,
8931 is_add=0)
8932
8933 static_mappings = self.vapi.nat66_static_mapping_dump()
8934 for sm in static_mappings:
8935 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8936 sm.external_ip_address,
8937 sm.vrf_id,
8938 is_add=0)
8939
8940 def tearDown(self):
8941 super(TestNAT66, self).tearDown()
8942 if not self.vpp_dead:
8943 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8944 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8945 self.clear_nat66()
8946
Klement Sekerad81ae412018-05-16 10:52:54 +02008947
Matus Fabiande886752016-12-07 03:38:19 -08008948if __name__ == '__main__':
8949 unittest.main(testRunner=VppTestRunner)