blob: 09fdb108c0be51fad73f4af0cf5e4e2318cdb303 [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 Fabiande886752016-12-07 03:38:19 -08006
7from framework import VppTestCase, VppTestRunner
Matus Fabiande886752016-12-07 03:38:19 -08008from scapy.layers.inet import IP, TCP, UDP, ICMP
9from scapy.layers.l2 import Ether
Matus Fabianeea28d72017-01-13 04:15:54 -080010from scapy.data import IP_PROTOS
Klement Sekera9225dee2016-12-12 08:36:58 +010011from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080012from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Matus Fabiande886752016-12-07 03:38:19 -080013
14
15class TestSNAT(VppTestCase):
16 """ SNAT Test Cases """
17
18 @classmethod
19 def setUpClass(cls):
20 super(TestSNAT, cls).setUpClass()
21
22 try:
23 cls.tcp_port_in = 6303
24 cls.tcp_port_out = 6303
25 cls.udp_port_in = 6304
26 cls.udp_port_out = 6304
27 cls.icmp_id_in = 6305
28 cls.icmp_id_out = 6305
29 cls.snat_addr = '10.0.0.3'
30
Matus Fabian8bf68e82017-01-12 04:24:35 -080031 cls.create_pg_interfaces(range(8))
Matus Fabiande886752016-12-07 03:38:19 -080032 cls.interfaces = list(cls.pg_interfaces[0:4])
33
34 for i in cls.interfaces:
35 i.admin_up()
36 i.config_ip4()
37 i.resolve_arp()
38
Matus Fabianf78a70d2016-12-12 04:30:39 -080039 cls.pg0.generate_remote_hosts(2)
40 cls.pg0.configure_ipv4_neighbors()
41
Matus Fabiande886752016-12-07 03:38:19 -080042 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
43
Matus Fabian675a69c2017-01-18 01:46:01 -080044 cls.pg4._local_ip4 = "172.16.255.1"
45 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
46 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
47 cls.pg4.set_table_ip4(10)
48 cls.pg5._local_ip4 = "172.16.255.3"
49 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
50 cls.pg5._remote_hosts[0]._ip4 = "172.16.255.4"
51 cls.pg5.set_table_ip4(10)
52 cls.pg6._local_ip4 = "172.16.255.1"
53 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
54 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
55 cls.pg6.set_table_ip4(20)
Matus Fabiande886752016-12-07 03:38:19 -080056 for i in cls.overlapping_interfaces:
Matus Fabiande886752016-12-07 03:38:19 -080057 i.config_ip4()
58 i.admin_up()
59 i.resolve_arp()
60
Matus Fabian8bf68e82017-01-12 04:24:35 -080061 cls.pg7.admin_up()
62
Matus Fabiande886752016-12-07 03:38:19 -080063 except Exception:
64 super(TestSNAT, cls).tearDownClass()
65 raise
66
67 def create_stream_in(self, in_if, out_if):
68 """
69 Create packet stream for inside network
70
71 :param in_if: Inside interface
72 :param out_if: Outside interface
73 """
74 pkts = []
75 # TCP
76 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
77 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
78 TCP(sport=self.tcp_port_in))
79 pkts.append(p)
80
81 # UDP
82 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
83 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
84 UDP(sport=self.udp_port_in))
85 pkts.append(p)
86
87 # ICMP
88 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
89 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
90 ICMP(id=self.icmp_id_in, type='echo-request'))
91 pkts.append(p)
92
93 return pkts
94
95 def create_stream_out(self, out_if, dst_ip=None):
96 """
97 Create packet stream for outside network
98
99 :param out_if: Outside interface
100 :param dst_ip: Destination IP address (Default use global SNAT address)
101 """
102 if dst_ip is None:
Klement Sekera9225dee2016-12-12 08:36:58 +0100103 dst_ip = self.snat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800104 pkts = []
105 # TCP
106 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
107 IP(src=out_if.remote_ip4, dst=dst_ip) /
108 TCP(dport=self.tcp_port_out))
109 pkts.append(p)
110
111 # UDP
112 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
113 IP(src=out_if.remote_ip4, dst=dst_ip) /
114 UDP(dport=self.udp_port_out))
115 pkts.append(p)
116
117 # ICMP
118 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
119 IP(src=out_if.remote_ip4, dst=dst_ip) /
120 ICMP(id=self.icmp_id_out, type='echo-reply'))
121 pkts.append(p)
122
123 return pkts
124
125 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
126 packet_num=3):
127 """
128 Verify captured packets on outside network
129
130 :param capture: Captured packets
131 :param nat_ip: Translated IP address (Default use global SNAT address)
132 :param same_port: Sorce port number is not translated (Default False)
133 :param packet_num: Expected number of packets (Default 3)
134 """
135 if nat_ip is None:
136 nat_ip = self.snat_addr
137 self.assertEqual(packet_num, len(capture))
138 for packet in capture:
139 try:
140 self.assertEqual(packet[IP].src, nat_ip)
141 if packet.haslayer(TCP):
142 if same_port:
143 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
144 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100145 self.assertNotEqual(
146 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800147 self.tcp_port_out = packet[TCP].sport
148 elif packet.haslayer(UDP):
149 if same_port:
150 self.assertEqual(packet[UDP].sport, self.udp_port_in)
151 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100152 self.assertNotEqual(
153 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800154 self.udp_port_out = packet[UDP].sport
155 else:
156 if same_port:
157 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
158 else:
159 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
160 self.icmp_id_out = packet[ICMP].id
161 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100162 self.logger.error(ppp("Unexpected or invalid packet "
163 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800164 raise
165
166 def verify_capture_in(self, capture, in_if, packet_num=3):
167 """
168 Verify captured packets on inside network
169
170 :param capture: Captured packets
171 :param in_if: Inside interface
172 :param packet_num: Expected number of packets (Default 3)
173 """
174 self.assertEqual(packet_num, len(capture))
175 for packet in capture:
176 try:
177 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
178 if packet.haslayer(TCP):
179 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
180 elif packet.haslayer(UDP):
181 self.assertEqual(packet[UDP].dport, self.udp_port_in)
182 else:
183 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
184 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100185 self.logger.error(ppp("Unexpected or invalid packet "
186 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800187 raise
188
Matus Fabian675a69c2017-01-18 01:46:01 -0800189 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
190 """
191 Verify captured packet that don't have to be translated
192
193 :param capture: Captured packets
194 :param ingress_if: Ingress interface
195 :param egress_if: Egress interface
196 """
197 for packet in capture:
198 try:
199 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
200 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
201 if packet.haslayer(TCP):
202 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
203 elif packet.haslayer(UDP):
204 self.assertEqual(packet[UDP].sport, self.udp_port_in)
205 else:
206 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
207 except:
208 self.logger.error(ppp("Unexpected or invalid packet "
209 "(inside network):", packet))
210 raise
211
Matus Fabianeea28d72017-01-13 04:15:54 -0800212 def verify_ipfix_nat44_ses(self, data):
213 """
214 Verify IPFIX NAT44 session create/delete event
215
216 :param data: Decoded IPFIX data records
217 """
218 nat44_ses_create_num = 0
219 nat44_ses_delete_num = 0
220 self.assertEqual(6, len(data))
221 for record in data:
222 # natEvent
223 self.assertIn(ord(record[230]), [4, 5])
224 if ord(record[230]) == 4:
225 nat44_ses_create_num += 1
226 else:
227 nat44_ses_delete_num += 1
228 # sourceIPv4Address
229 self.assertEqual(self.pg0.remote_ip4n, record[8])
230 # postNATSourceIPv4Address
231 self.assertEqual(socket.inet_pton(socket.AF_INET, self.snat_addr),
232 record[225])
233 # ingressVRFID
234 self.assertEqual(struct.pack("!I", 0), record[234])
235 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
236 if IP_PROTOS.icmp == ord(record[4]):
237 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
238 self.assertEqual(struct.pack("!H", self.icmp_id_out),
239 record[227])
240 elif IP_PROTOS.tcp == ord(record[4]):
241 self.assertEqual(struct.pack("!H", self.tcp_port_in),
242 record[7])
243 self.assertEqual(struct.pack("!H", self.tcp_port_out),
244 record[227])
245 elif IP_PROTOS.udp == ord(record[4]):
246 self.assertEqual(struct.pack("!H", self.udp_port_in),
247 record[7])
248 self.assertEqual(struct.pack("!H", self.udp_port_out),
249 record[227])
250 else:
251 self.fail("Invalid protocol")
252 self.assertEqual(3, nat44_ses_create_num)
253 self.assertEqual(3, nat44_ses_delete_num)
254
255 def verify_ipfix_addr_exhausted(self, data):
256 """
257 Verify IPFIX NAT addresses event
258
259 :param data: Decoded IPFIX data records
260 """
261 self.assertEqual(1, len(data))
262 record = data[0]
263 # natEvent
264 self.assertEqual(ord(record[230]), 3)
265 # natPoolID
266 self.assertEqual(struct.pack("!I", 0), record[283])
267
Matus Fabiande886752016-12-07 03:38:19 -0800268 def clear_snat(self):
269 """
270 Clear SNAT configuration.
271 """
Matus Fabian8bf68e82017-01-12 04:24:35 -0800272 interfaces = self.vapi.snat_interface_addr_dump()
273 for intf in interfaces:
274 self.vapi.snat_add_interface_addr(intf.sw_if_index, is_add=0)
275
Matus Fabianeea28d72017-01-13 04:15:54 -0800276 self.vapi.snat_ipfix(enable=0)
277
Matus Fabiande886752016-12-07 03:38:19 -0800278 interfaces = self.vapi.snat_interface_dump()
279 for intf in interfaces:
280 self.vapi.snat_interface_add_del_feature(intf.sw_if_index,
281 intf.is_inside,
282 is_add=0)
283
284 static_mappings = self.vapi.snat_static_mapping_dump()
285 for sm in static_mappings:
286 self.vapi.snat_add_static_mapping(sm.local_ip_address,
287 sm.external_ip_address,
288 local_port=sm.local_port,
289 external_port=sm.external_port,
290 addr_only=sm.addr_only,
291 vrf_id=sm.vrf_id,
292 is_add=0)
293
294 adresses = self.vapi.snat_address_dump()
295 for addr in adresses:
296 self.vapi.snat_add_address_range(addr.ip_address,
297 addr.ip_address,
298 is_add=0)
299
300 def snat_add_static_mapping(self, local_ip, external_ip, local_port=0,
301 external_port=0, vrf_id=0, is_add=1):
302 """
303 Add/delete S-NAT static mapping
304
305 :param local_ip: Local IP address
306 :param external_ip: External IP address
307 :param local_port: Local port number (Optional)
308 :param external_port: External port number (Optional)
309 :param vrf_id: VRF ID (Default 0)
310 :param is_add: 1 if add, 0 if delete (Default add)
311 """
312 addr_only = 1
313 if local_port and external_port:
314 addr_only = 0
315 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
316 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Klement Sekerada505f62017-01-04 12:58:53 +0100317 self.vapi.snat_add_static_mapping(
318 l_ip,
319 e_ip,
320 local_port,
321 external_port,
322 addr_only,
323 vrf_id,
324 is_add)
Matus Fabiande886752016-12-07 03:38:19 -0800325
326 def snat_add_address(self, ip, is_add=1):
327 """
328 Add/delete S-NAT address
329
330 :param ip: IP address
331 :param is_add: 1 if add, 0 if delete (Default add)
332 """
333 snat_addr = socket.inet_pton(socket.AF_INET, ip)
334 self.vapi.snat_add_address_range(snat_addr, snat_addr, is_add)
335
336 def test_dynamic(self):
337 """ SNAT dynamic translation test """
338
339 self.snat_add_address(self.snat_addr)
340 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
341 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
342 is_inside=0)
343
344 # in2out
345 pkts = self.create_stream_in(self.pg0, self.pg1)
346 self.pg0.add_stream(pkts)
347 self.pg_enable_capture(self.pg_interfaces)
348 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100349 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800350 self.verify_capture_out(capture)
351
352 # out2in
353 pkts = self.create_stream_out(self.pg1)
354 self.pg1.add_stream(pkts)
355 self.pg_enable_capture(self.pg_interfaces)
356 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100357 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800358 self.verify_capture_in(capture, self.pg0)
359
360 def test_static_in(self):
361 """ SNAT 1:1 NAT initialized from inside network """
362
363 nat_ip = "10.0.0.10"
364 self.tcp_port_out = 6303
365 self.udp_port_out = 6304
366 self.icmp_id_out = 6305
367
368 self.snat_add_static_mapping(self.pg0.remote_ip4, nat_ip)
369 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
370 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
371 is_inside=0)
372
373 # in2out
374 pkts = self.create_stream_in(self.pg0, self.pg1)
375 self.pg0.add_stream(pkts)
376 self.pg_enable_capture(self.pg_interfaces)
377 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100378 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800379 self.verify_capture_out(capture, nat_ip, True)
380
381 # out2in
382 pkts = self.create_stream_out(self.pg1, nat_ip)
383 self.pg1.add_stream(pkts)
384 self.pg_enable_capture(self.pg_interfaces)
385 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100386 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800387 self.verify_capture_in(capture, self.pg0)
388
389 def test_static_out(self):
390 """ SNAT 1:1 NAT initialized from outside network """
391
392 nat_ip = "10.0.0.20"
393 self.tcp_port_out = 6303
394 self.udp_port_out = 6304
395 self.icmp_id_out = 6305
396
397 self.snat_add_static_mapping(self.pg0.remote_ip4, nat_ip)
398 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
399 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
400 is_inside=0)
401
402 # out2in
403 pkts = self.create_stream_out(self.pg1, nat_ip)
404 self.pg1.add_stream(pkts)
405 self.pg_enable_capture(self.pg_interfaces)
406 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100407 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800408 self.verify_capture_in(capture, self.pg0)
409
410 # in2out
411 pkts = self.create_stream_in(self.pg0, self.pg1)
412 self.pg0.add_stream(pkts)
413 self.pg_enable_capture(self.pg_interfaces)
414 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100415 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800416 self.verify_capture_out(capture, nat_ip, True)
417
418 def test_static_with_port_in(self):
419 """ SNAT 1:1 NAT with port initialized from inside network """
420
421 self.tcp_port_out = 3606
422 self.udp_port_out = 3607
423 self.icmp_id_out = 3608
424
425 self.snat_add_address(self.snat_addr)
426 self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
427 self.tcp_port_in, self.tcp_port_out)
428 self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
429 self.udp_port_in, self.udp_port_out)
430 self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
431 self.icmp_id_in, self.icmp_id_out)
432 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
433 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
434 is_inside=0)
435
436 # in2out
437 pkts = self.create_stream_in(self.pg0, self.pg1)
438 self.pg0.add_stream(pkts)
439 self.pg_enable_capture(self.pg_interfaces)
440 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100441 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800442 self.verify_capture_out(capture)
443
444 # out2in
445 pkts = self.create_stream_out(self.pg1)
446 self.pg1.add_stream(pkts)
447 self.pg_enable_capture(self.pg_interfaces)
448 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100449 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800450 self.verify_capture_in(capture, self.pg0)
451
452 def test_static_with_port_out(self):
453 """ SNAT 1:1 NAT with port initialized from outside network """
454
455 self.tcp_port_out = 30606
456 self.udp_port_out = 30607
457 self.icmp_id_out = 30608
458
459 self.snat_add_address(self.snat_addr)
460 self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
461 self.tcp_port_in, self.tcp_port_out)
462 self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
463 self.udp_port_in, self.udp_port_out)
464 self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
465 self.icmp_id_in, self.icmp_id_out)
466 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
467 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
468 is_inside=0)
469
470 # out2in
471 pkts = self.create_stream_out(self.pg1)
472 self.pg1.add_stream(pkts)
473 self.pg_enable_capture(self.pg_interfaces)
474 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100475 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800476 self.verify_capture_in(capture, self.pg0)
477
478 # in2out
479 pkts = self.create_stream_in(self.pg0, self.pg1)
480 self.pg0.add_stream(pkts)
481 self.pg_enable_capture(self.pg_interfaces)
482 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100483 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800484 self.verify_capture_out(capture)
485
486 def test_static_vrf_aware(self):
487 """ SNAT 1:1 NAT VRF awareness """
488
489 nat_ip1 = "10.0.0.30"
490 nat_ip2 = "10.0.0.40"
491 self.tcp_port_out = 6303
492 self.udp_port_out = 6304
493 self.icmp_id_out = 6305
494
495 self.snat_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
Matus Fabian675a69c2017-01-18 01:46:01 -0800496 vrf_id=10)
Matus Fabiande886752016-12-07 03:38:19 -0800497 self.snat_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
Matus Fabian675a69c2017-01-18 01:46:01 -0800498 vrf_id=10)
Matus Fabiande886752016-12-07 03:38:19 -0800499 self.vapi.snat_interface_add_del_feature(self.pg3.sw_if_index,
500 is_inside=0)
501 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
502 self.vapi.snat_interface_add_del_feature(self.pg4.sw_if_index)
503
504 # inside interface VRF match SNAT static mapping VRF
505 pkts = self.create_stream_in(self.pg4, self.pg3)
506 self.pg4.add_stream(pkts)
507 self.pg_enable_capture(self.pg_interfaces)
508 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100509 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800510 self.verify_capture_out(capture, nat_ip1, True)
511
512 # inside interface VRF don't match SNAT static mapping VRF (packets
513 # are dropped)
514 pkts = self.create_stream_in(self.pg0, self.pg3)
515 self.pg0.add_stream(pkts)
516 self.pg_enable_capture(self.pg_interfaces)
517 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +0100518 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -0800519
520 def test_multiple_inside_interfaces(self):
Klement Sekerada505f62017-01-04 12:58:53 +0100521 """
522 SNAT multiple inside interfaces with non-overlapping address space
523 """
Matus Fabiande886752016-12-07 03:38:19 -0800524
525 self.snat_add_address(self.snat_addr)
526 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
527 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -0800528 self.vapi.snat_interface_add_del_feature(self.pg3.sw_if_index,
529 is_inside=0)
530
Matus Fabian675a69c2017-01-18 01:46:01 -0800531 # between two S-NAT inside interfaces (no translation)
532 pkts = self.create_stream_in(self.pg0, self.pg1)
533 self.pg0.add_stream(pkts)
534 self.pg_enable_capture(self.pg_interfaces)
535 self.pg_start()
536 capture = self.pg1.get_capture(len(pkts))
537 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
538
539 # from S-NAT inside to interface without S-NAT feature (no translation)
540 pkts = self.create_stream_in(self.pg0, self.pg2)
541 self.pg0.add_stream(pkts)
542 self.pg_enable_capture(self.pg_interfaces)
543 self.pg_start()
544 capture = self.pg2.get_capture(len(pkts))
545 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
546
Matus Fabiande886752016-12-07 03:38:19 -0800547 # in2out 1st interface
548 pkts = self.create_stream_in(self.pg0, self.pg3)
549 self.pg0.add_stream(pkts)
550 self.pg_enable_capture(self.pg_interfaces)
551 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100552 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800553 self.verify_capture_out(capture)
554
555 # out2in 1st interface
556 pkts = self.create_stream_out(self.pg3)
557 self.pg3.add_stream(pkts)
558 self.pg_enable_capture(self.pg_interfaces)
559 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100560 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800561 self.verify_capture_in(capture, self.pg0)
562
563 # in2out 2nd interface
564 pkts = self.create_stream_in(self.pg1, self.pg3)
565 self.pg1.add_stream(pkts)
566 self.pg_enable_capture(self.pg_interfaces)
567 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100568 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800569 self.verify_capture_out(capture)
570
571 # out2in 2nd interface
572 pkts = self.create_stream_out(self.pg3)
573 self.pg3.add_stream(pkts)
574 self.pg_enable_capture(self.pg_interfaces)
575 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100576 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800577 self.verify_capture_in(capture, self.pg1)
578
Matus Fabiande886752016-12-07 03:38:19 -0800579 def test_inside_overlapping_interfaces(self):
580 """ SNAT multiple inside interfaces with overlapping address space """
581
Matus Fabian675a69c2017-01-18 01:46:01 -0800582 static_nat_ip = "10.0.0.10"
Matus Fabiande886752016-12-07 03:38:19 -0800583 self.snat_add_address(self.snat_addr)
584 self.vapi.snat_interface_add_del_feature(self.pg3.sw_if_index,
585 is_inside=0)
586 self.vapi.snat_interface_add_del_feature(self.pg4.sw_if_index)
587 self.vapi.snat_interface_add_del_feature(self.pg5.sw_if_index)
588 self.vapi.snat_interface_add_del_feature(self.pg6.sw_if_index)
Matus Fabian675a69c2017-01-18 01:46:01 -0800589 self.snat_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
590 vrf_id=20)
591
592 # between S-NAT inside interfaces with same VRF (no translation)
593 pkts = self.create_stream_in(self.pg4, self.pg5)
594 self.pg4.add_stream(pkts)
595 self.pg_enable_capture(self.pg_interfaces)
596 self.pg_start()
597 capture = self.pg5.get_capture(len(pkts))
598 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
599
600 # between S-NAT inside interfaces with different VRF (hairpinning)
601 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
602 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
603 TCP(sport=1234, dport=5678))
604 self.pg4.add_stream(p)
605 self.pg_enable_capture(self.pg_interfaces)
606 self.pg_start()
607 capture = self.pg6.get_capture(1)
608 p = capture[0]
609 try:
610 ip = p[IP]
611 tcp = p[TCP]
612 self.assertEqual(ip.src, self.snat_addr)
613 self.assertEqual(ip.dst, self.pg6.remote_ip4)
614 self.assertNotEqual(tcp.sport, 1234)
615 self.assertEqual(tcp.dport, 5678)
616 except:
617 self.logger.error(ppp("Unexpected or invalid packet:", p))
618 raise
Matus Fabiande886752016-12-07 03:38:19 -0800619
620 # in2out 1st interface
621 pkts = self.create_stream_in(self.pg4, self.pg3)
622 self.pg4.add_stream(pkts)
623 self.pg_enable_capture(self.pg_interfaces)
624 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100625 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800626 self.verify_capture_out(capture)
627
628 # out2in 1st interface
629 pkts = self.create_stream_out(self.pg3)
630 self.pg3.add_stream(pkts)
631 self.pg_enable_capture(self.pg_interfaces)
632 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100633 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800634 self.verify_capture_in(capture, self.pg4)
635
636 # in2out 2nd interface
637 pkts = self.create_stream_in(self.pg5, self.pg3)
638 self.pg5.add_stream(pkts)
639 self.pg_enable_capture(self.pg_interfaces)
640 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100641 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800642 self.verify_capture_out(capture)
643
644 # out2in 2nd interface
645 pkts = self.create_stream_out(self.pg3)
646 self.pg3.add_stream(pkts)
647 self.pg_enable_capture(self.pg_interfaces)
648 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100649 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800650 self.verify_capture_in(capture, self.pg5)
651
652 # in2out 3rd interface
653 pkts = self.create_stream_in(self.pg6, self.pg3)
654 self.pg6.add_stream(pkts)
655 self.pg_enable_capture(self.pg_interfaces)
656 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100657 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -0800658 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -0800659
660 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -0800661 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800662 self.pg3.add_stream(pkts)
663 self.pg_enable_capture(self.pg_interfaces)
664 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100665 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -0800666 self.verify_capture_in(capture, self.pg6)
667
Matus Fabianf78a70d2016-12-12 04:30:39 -0800668 def test_hairpinning(self):
669 """ SNAT hairpinning """
670
671 host = self.pg0.remote_hosts[0]
672 server = self.pg0.remote_hosts[1]
673 host_in_port = 1234
674 host_out_port = 0
675 server_in_port = 5678
676 server_out_port = 8765
677
678 self.snat_add_address(self.snat_addr)
679 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
680 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
681 is_inside=0)
682 # add static mapping for server
683 self.snat_add_static_mapping(server.ip4, self.snat_addr,
684 server_in_port, server_out_port)
685
686 # send packet from host to server
687 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
688 IP(src=host.ip4, dst=self.snat_addr) /
689 TCP(sport=host_in_port, dport=server_out_port))
690 self.pg0.add_stream(p)
691 self.pg_enable_capture(self.pg_interfaces)
692 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100693 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -0800694 p = capture[0]
695 try:
696 ip = p[IP]
697 tcp = p[TCP]
698 self.assertEqual(ip.src, self.snat_addr)
699 self.assertEqual(ip.dst, server.ip4)
700 self.assertNotEqual(tcp.sport, host_in_port)
701 self.assertEqual(tcp.dport, server_in_port)
702 host_out_port = tcp.sport
703 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100704 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -0800705 raise
706
707 # send reply from server to host
708 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
709 IP(src=server.ip4, dst=self.snat_addr) /
710 TCP(sport=server_in_port, dport=host_out_port))
711 self.pg0.add_stream(p)
712 self.pg_enable_capture(self.pg_interfaces)
713 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +0100714 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -0800715 p = capture[0]
716 try:
717 ip = p[IP]
718 tcp = p[TCP]
719 self.assertEqual(ip.src, self.snat_addr)
720 self.assertEqual(ip.dst, host.ip4)
721 self.assertEqual(tcp.sport, server_out_port)
722 self.assertEqual(tcp.dport, host_in_port)
723 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100724 self.logger.error(ppp("Unexpected or invalid packet:"), p)
Matus Fabianf78a70d2016-12-12 04:30:39 -0800725 raise
726
Matus Fabian9902fcd2016-12-21 23:58:46 -0800727 def test_max_translations_per_user(self):
728 """ MAX translations per user - recycle the least recently used """
729
730 self.snat_add_address(self.snat_addr)
731 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
732 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
733 is_inside=0)
734
735 # get maximum number of translations per user
736 snat_config = self.vapi.snat_show_config()
737
738 # send more than maximum number of translations per user packets
739 pkts_num = snat_config.max_translations_per_user + 5
740 pkts = []
741 for port in range(0, pkts_num):
742 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
743 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
744 TCP(sport=1025 + port))
745 pkts.append(p)
746 self.pg0.add_stream(pkts)
747 self.pg_enable_capture(self.pg_interfaces)
748 self.pg_start()
749
750 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +0100751 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -0800752
Matus Fabian8bf68e82017-01-12 04:24:35 -0800753 def test_interface_addr(self):
754 """ Acquire SNAT addresses from interface """
755 self.vapi.snat_add_interface_addr(self.pg7.sw_if_index)
756
757 # no address in NAT pool
758 adresses = self.vapi.snat_address_dump()
759 self.assertEqual(0, len(adresses))
760
761 # configure interface address and check NAT address pool
762 self.pg7.config_ip4()
763 adresses = self.vapi.snat_address_dump()
764 self.assertEqual(1, len(adresses))
765
766 # remove interface address and check NAT address pool
767 self.pg7.unconfig_ip4()
768 adresses = self.vapi.snat_address_dump()
769 self.assertEqual(0, len(adresses))
770
Matus Fabianeea28d72017-01-13 04:15:54 -0800771 def test_ipfix_nat44_sess(self):
772 """ S-NAT IPFIX logging NAT44 session created/delted """
773 self.snat_add_address(self.snat_addr)
774 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
775 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
776 is_inside=0)
777 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
778 src_address=self.pg3.local_ip4n,
779 path_mtu=512,
780 template_interval=10)
781 self.vapi.snat_ipfix()
782
783 pkts = self.create_stream_in(self.pg0, self.pg1)
784 self.pg0.add_stream(pkts)
785 self.pg_enable_capture(self.pg_interfaces)
786 self.pg_start()
787 capture = self.pg1.get_capture(len(pkts))
788 self.verify_capture_out(capture)
789 self.snat_add_address(self.snat_addr, is_add=0)
790 self.vapi.cli("ipfix flush") # FIXME this should be an API call
791 capture = self.pg3.get_capture(3)
792 ipfix = IPFIXDecoder()
793 # first load template
794 for p in capture:
795 self.assertTrue(p.haslayer(IPFIX))
796 if p.haslayer(Template):
797 ipfix.add_template(p.getlayer(Template))
798 # verify events in data set
799 for p in capture:
800 if p.haslayer(Data):
801 data = ipfix.decode_data_set(p.getlayer(Set))
802 self.verify_ipfix_nat44_ses(data)
803
804 def test_ipfix_addr_exhausted(self):
805 """ S-NAT IPFIX logging NAT addresses exhausted """
806 self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
807 self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
808 is_inside=0)
809 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
810 src_address=self.pg3.local_ip4n,
811 path_mtu=512,
812 template_interval=10)
813 self.vapi.snat_ipfix()
814
815 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
816 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
817 TCP(sport=3025))
818 self.pg0.add_stream(p)
819 self.pg_enable_capture(self.pg_interfaces)
820 self.pg_start()
821 capture = self.pg1.get_capture(0)
822 self.vapi.cli("ipfix flush") # FIXME this should be an API call
823 capture = self.pg3.get_capture(3)
824 ipfix = IPFIXDecoder()
825 # first load template
826 for p in capture:
827 self.assertTrue(p.haslayer(IPFIX))
828 if p.haslayer(Template):
829 ipfix.add_template(p.getlayer(Template))
830 # verify events in data set
831 for p in capture:
832 if p.haslayer(Data):
833 data = ipfix.decode_data_set(p.getlayer(Set))
834 self.verify_ipfix_addr_exhausted(data)
835
Matus Fabiande886752016-12-07 03:38:19 -0800836 def tearDown(self):
837 super(TestSNAT, self).tearDown()
838 if not self.vpp_dead:
839 self.logger.info(self.vapi.cli("show snat verbose"))
840 self.clear_snat()
841
Matus Fabianeea28d72017-01-13 04:15:54 -0800842
Matus Fabiande886752016-12-07 03:38:19 -0800843if __name__ == '__main__':
844 unittest.main(testRunner=VppTestRunner)