blob: 51a60d1b56faf1a1d220b768f1b713392aa63f0e [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 StringIO
7import random
Matus Fabiande886752016-12-07 03:38:19 -08008
Martin Gálik977c1cb2017-03-30 23:21:51 -07009from framework import VppTestCase, VppTestRunner, running_extended_tests
Matus Fabian8ebe6252017-11-06 05:04:53 -080010from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
Matus Fabiande886752016-12-07 03:38:19 -080011from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080012from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Matus Fabian06596c52017-06-06 04:53:28 -070013from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
Matus Fabianefcd1e92017-08-15 06:59:19 -070014from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070015from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080016from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070017from scapy.packet import bind_layers, Raw
18from scapy.all import fragment6
Klement Sekera9225dee2016-12-12 08:36:58 +010019from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080020from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070021from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070022from util import ip4_range
Ole Troan895b6e82017-10-20 13:28:20 +020023from util import mactobinary
Matus Fabiande886752016-12-07 03:38:19 -080024
25
Martin Gálikd7f75cd2017-03-27 06:02:47 -070026class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070027 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080028
29 @classmethod
30 def setUpClass(cls):
Martin Gálikd7f75cd2017-03-27 06:02:47 -070031 super(MethodHolder, cls).setUpClass()
Matus Fabiande886752016-12-07 03:38:19 -080032
Martin Gálikd7f75cd2017-03-27 06:02:47 -070033 def tearDown(self):
34 super(MethodHolder, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -080035
Matus Fabian029f3d22017-06-15 02:28:50 -070036 def check_ip_checksum(self, pkt):
37 """
38 Check IP checksum of the packet
39
40 :param pkt: Packet to check IP checksum
41 """
42 new = pkt.__class__(str(pkt))
43 del new['IP'].chksum
44 new = new.__class__(str(new))
45 self.assertEqual(new['IP'].chksum, pkt['IP'].chksum)
46
Matus Fabian4b30ceb2017-06-09 02:33:30 -070047 def check_tcp_checksum(self, pkt):
48 """
49 Check TCP checksum in IP packet
50
51 :param pkt: Packet to check TCP checksum
52 """
53 new = pkt.__class__(str(pkt))
54 del new['TCP'].chksum
55 new = new.__class__(str(new))
56 self.assertEqual(new['TCP'].chksum, pkt['TCP'].chksum)
57
Matus Fabian029f3d22017-06-15 02:28:50 -070058 def check_udp_checksum(self, pkt):
59 """
60 Check UDP checksum in IP packet
61
62 :param pkt: Packet to check UDP checksum
63 """
64 new = pkt.__class__(str(pkt))
65 del new['UDP'].chksum
66 new = new.__class__(str(new))
67 self.assertEqual(new['UDP'].chksum, pkt['UDP'].chksum)
68
69 def check_icmp_errror_embedded(self, pkt):
70 """
71 Check ICMP error embeded packet checksum
72
73 :param pkt: Packet to check ICMP error embeded packet checksum
74 """
75 if pkt.haslayer(IPerror):
76 new = pkt.__class__(str(pkt))
77 del new['IPerror'].chksum
78 new = new.__class__(str(new))
79 self.assertEqual(new['IPerror'].chksum, pkt['IPerror'].chksum)
80
81 if pkt.haslayer(TCPerror):
82 new = pkt.__class__(str(pkt))
83 del new['TCPerror'].chksum
84 new = new.__class__(str(new))
85 self.assertEqual(new['TCPerror'].chksum, pkt['TCPerror'].chksum)
86
87 if pkt.haslayer(UDPerror):
88 if pkt['UDPerror'].chksum != 0:
89 new = pkt.__class__(str(pkt))
90 del new['UDPerror'].chksum
91 new = new.__class__(str(new))
92 self.assertEqual(new['UDPerror'].chksum,
93 pkt['UDPerror'].chksum)
94
95 if pkt.haslayer(ICMPerror):
96 del new['ICMPerror'].chksum
97 new = new.__class__(str(new))
98 self.assertEqual(new['ICMPerror'].chksum, pkt['ICMPerror'].chksum)
99
100 def check_icmp_checksum(self, pkt):
101 """
102 Check ICMP checksum in IPv4 packet
103
104 :param pkt: Packet to check ICMP checksum
105 """
106 new = pkt.__class__(str(pkt))
107 del new['ICMP'].chksum
108 new = new.__class__(str(new))
109 self.assertEqual(new['ICMP'].chksum, pkt['ICMP'].chksum)
110 if pkt.haslayer(IPerror):
111 self.check_icmp_errror_embedded(pkt)
112
113 def check_icmpv6_checksum(self, pkt):
114 """
115 Check ICMPv6 checksum in IPv4 packet
116
117 :param pkt: Packet to check ICMPv6 checksum
118 """
119 new = pkt.__class__(str(pkt))
120 if pkt.haslayer(ICMPv6DestUnreach):
121 del new['ICMPv6DestUnreach'].cksum
122 new = new.__class__(str(new))
123 self.assertEqual(new['ICMPv6DestUnreach'].cksum,
124 pkt['ICMPv6DestUnreach'].cksum)
125 self.check_icmp_errror_embedded(pkt)
126 if pkt.haslayer(ICMPv6EchoRequest):
127 del new['ICMPv6EchoRequest'].cksum
128 new = new.__class__(str(new))
129 self.assertEqual(new['ICMPv6EchoRequest'].cksum,
130 pkt['ICMPv6EchoRequest'].cksum)
131 if pkt.haslayer(ICMPv6EchoReply):
132 del new['ICMPv6EchoReply'].cksum
133 new = new.__class__(str(new))
134 self.assertEqual(new['ICMPv6EchoReply'].cksum,
135 pkt['ICMPv6EchoReply'].cksum)
136
Juraj Slobodacba69362017-12-19 02:09:32 +0100137 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800138 """
139 Create packet stream for inside network
140
141 :param in_if: Inside interface
142 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100143 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800144 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800145 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100146 if dst_ip is None:
147 dst_ip = out_if.remote_ip4
148
Matus Fabiande886752016-12-07 03:38:19 -0800149 pkts = []
150 # TCP
151 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100152 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700153 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800154 pkts.append(p)
155
156 # UDP
157 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100158 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700159 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800160 pkts.append(p)
161
162 # ICMP
163 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100164 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800165 ICMP(id=self.icmp_id_in, type='echo-request'))
166 pkts.append(p)
167
168 return pkts
169
Matus Fabian428dc912017-06-21 06:15:18 -0700170 def compose_ip6(self, ip4, pref, plen):
171 """
172 Compose IPv4-embedded IPv6 addresses
173
174 :param ip4: IPv4 address
175 :param pref: IPv6 prefix
176 :param plen: IPv6 prefix length
177 :returns: IPv4-embedded IPv6 addresses
178 """
179 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
180 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
181 if plen == 32:
182 pref_n[4] = ip4_n[0]
183 pref_n[5] = ip4_n[1]
184 pref_n[6] = ip4_n[2]
185 pref_n[7] = ip4_n[3]
186 elif plen == 40:
187 pref_n[5] = ip4_n[0]
188 pref_n[6] = ip4_n[1]
189 pref_n[7] = ip4_n[2]
190 pref_n[9] = ip4_n[3]
191 elif plen == 48:
192 pref_n[6] = ip4_n[0]
193 pref_n[7] = ip4_n[1]
194 pref_n[9] = ip4_n[2]
195 pref_n[10] = ip4_n[3]
196 elif plen == 56:
197 pref_n[7] = ip4_n[0]
198 pref_n[9] = ip4_n[1]
199 pref_n[10] = ip4_n[2]
200 pref_n[11] = ip4_n[3]
201 elif plen == 64:
202 pref_n[9] = ip4_n[0]
203 pref_n[10] = ip4_n[1]
204 pref_n[11] = ip4_n[2]
205 pref_n[12] = ip4_n[3]
206 elif plen == 96:
207 pref_n[12] = ip4_n[0]
208 pref_n[13] = ip4_n[1]
209 pref_n[14] = ip4_n[2]
210 pref_n[15] = ip4_n[3]
211 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
212
Juraj Slobodacba69362017-12-19 02:09:32 +0100213 def extract_ip4(self, ip6, plen):
214 """
215 Extract IPv4 address embedded in IPv6 addresses
216
217 :param ip6: IPv6 address
218 :param plen: IPv6 prefix length
219 :returns: extracted IPv4 address
220 """
221 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
222 ip4_n = [None] * 4
223 if plen == 32:
224 ip4_n[0] = ip6_n[4]
225 ip4_n[1] = ip6_n[5]
226 ip4_n[2] = ip6_n[6]
227 ip4_n[3] = ip6_n[7]
228 elif plen == 40:
229 ip4_n[0] = ip6_n[5]
230 ip4_n[1] = ip6_n[6]
231 ip4_n[2] = ip6_n[7]
232 ip4_n[3] = ip6_n[9]
233 elif plen == 48:
234 ip4_n[0] = ip6_n[6]
235 ip4_n[1] = ip6_n[7]
236 ip4_n[2] = ip6_n[9]
237 ip4_n[3] = ip6_n[10]
238 elif plen == 56:
239 ip4_n[0] = ip6_n[7]
240 ip4_n[1] = ip6_n[9]
241 ip4_n[2] = ip6_n[10]
242 ip4_n[3] = ip6_n[11]
243 elif plen == 64:
244 ip4_n[0] = ip6_n[9]
245 ip4_n[1] = ip6_n[10]
246 ip4_n[2] = ip6_n[11]
247 ip4_n[3] = ip6_n[12]
248 elif plen == 96:
249 ip4_n[0] = ip6_n[12]
250 ip4_n[1] = ip6_n[13]
251 ip4_n[2] = ip6_n[14]
252 ip4_n[3] = ip6_n[15]
253 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
254
Matus Fabian428dc912017-06-21 06:15:18 -0700255 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700256 """
257 Create IPv6 packet stream for inside network
258
259 :param in_if: Inside interface
260 :param out_if: Outside interface
261 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700262 :param pref: NAT64 prefix
263 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700264 """
265 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700266 if pref is None:
267 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
268 else:
269 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
270
Matus Fabian06596c52017-06-06 04:53:28 -0700271 # TCP
272 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
273 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
274 TCP(sport=self.tcp_port_in, dport=20))
275 pkts.append(p)
276
277 # UDP
278 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
279 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
280 UDP(sport=self.udp_port_in, dport=20))
281 pkts.append(p)
282
283 # ICMP
284 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
285 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
286 ICMPv6EchoRequest(id=self.icmp_id_in))
287 pkts.append(p)
288
289 return pkts
290
Juraj Sloboda7b929792017-11-23 13:20:48 +0100291 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
292 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800293 """
294 Create packet stream for outside network
295
296 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700297 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800298 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100299 :param use_inside_ports: Use inside NAT ports as destination ports
300 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800301 """
302 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700303 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100304 if not use_inside_ports:
305 tcp_port = self.tcp_port_out
306 udp_port = self.udp_port_out
307 icmp_id = self.icmp_id_out
308 else:
309 tcp_port = self.tcp_port_in
310 udp_port = self.udp_port_in
311 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800312 pkts = []
313 # TCP
314 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800315 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100316 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800317 pkts.append(p)
318
319 # UDP
320 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800321 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100322 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800323 pkts.append(p)
324
325 # ICMP
326 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800327 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100328 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800329 pkts.append(p)
330
331 return pkts
332
Juraj Slobodacba69362017-12-19 02:09:32 +0100333 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
334 """
335 Create packet stream for outside network
336
337 :param out_if: Outside interface
338 :param dst_ip: Destination IP address (Default use global NAT address)
339 :param hl: HL of generated packets
340 """
341 pkts = []
342 # TCP
343 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
344 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
345 TCP(dport=self.tcp_port_out, sport=20))
346 pkts.append(p)
347
348 # UDP
349 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
350 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
351 UDP(dport=self.udp_port_out, sport=20))
352 pkts.append(p)
353
354 # ICMP
355 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
356 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
357 ICMPv6EchoReply(id=self.icmp_id_out))
358 pkts.append(p)
359
360 return pkts
361
Matus Fabiande886752016-12-07 03:38:19 -0800362 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Juraj Slobodacba69362017-12-19 02:09:32 +0100363 packet_num=3, dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800364 """
365 Verify captured packets on outside network
366
367 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700368 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800369 :param same_port: Sorce port number is not translated (Default False)
370 :param packet_num: Expected number of packets (Default 3)
Matus Fabian06596c52017-06-06 04:53:28 -0700371 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100372 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800373 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100374 if is_ip6:
375 IP46 = IPv6
376 ICMP46 = ICMPv6EchoRequest
377 else:
378 IP46 = IP
379 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800380 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700381 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800382 self.assertEqual(packet_num, len(capture))
383 for packet in capture:
384 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100385 if not is_ip6:
386 self.check_ip_checksum(packet)
387 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700388 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100389 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800390 if packet.haslayer(TCP):
391 if same_port:
392 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
393 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100394 self.assertNotEqual(
395 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800396 self.tcp_port_out = packet[TCP].sport
Matus Fabian029f3d22017-06-15 02:28:50 -0700397 self.check_tcp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800398 elif packet.haslayer(UDP):
399 if same_port:
400 self.assertEqual(packet[UDP].sport, self.udp_port_in)
401 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100402 self.assertNotEqual(
403 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800404 self.udp_port_out = packet[UDP].sport
405 else:
406 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100407 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800408 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100409 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
410 self.icmp_id_out = packet[ICMP46].id
411 if is_ip6:
412 self.check_icmpv6_checksum(packet)
413 else:
414 self.check_icmp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800415 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100416 self.logger.error(ppp("Unexpected or invalid packet "
417 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800418 raise
419
Juraj Slobodacba69362017-12-19 02:09:32 +0100420 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
421 packet_num=3, dst_ip=None):
422 """
423 Verify captured packets on outside network
424
425 :param capture: Captured packets
426 :param nat_ip: Translated IP address
427 :param same_port: Sorce port number is not translated (Default False)
428 :param packet_num: Expected number of packets (Default 3)
429 :param dst_ip: Destination IP address (Default do not verify)
430 """
431 return self.verify_capture_out(capture, nat_ip, same_port, packet_num,
432 dst_ip, True)
433
Matus Fabiande886752016-12-07 03:38:19 -0800434 def verify_capture_in(self, capture, in_if, packet_num=3):
435 """
436 Verify captured packets on inside network
437
438 :param capture: Captured packets
439 :param in_if: Inside interface
440 :param packet_num: Expected number of packets (Default 3)
441 """
442 self.assertEqual(packet_num, len(capture))
443 for packet in capture:
444 try:
Matus Fabian029f3d22017-06-15 02:28:50 -0700445 self.check_ip_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800446 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
447 if packet.haslayer(TCP):
448 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700449 self.check_tcp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800450 elif packet.haslayer(UDP):
451 self.assertEqual(packet[UDP].dport, self.udp_port_in)
452 else:
453 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700454 self.check_icmp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800455 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100456 self.logger.error(ppp("Unexpected or invalid packet "
457 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800458 raise
459
Matus Fabian06596c52017-06-06 04:53:28 -0700460 def verify_capture_in_ip6(self, capture, src_ip, dst_ip, packet_num=3):
461 """
462 Verify captured IPv6 packets on inside network
463
464 :param capture: Captured packets
465 :param src_ip: Source IP
466 :param dst_ip: Destination IP address
467 :param packet_num: Expected number of packets (Default 3)
468 """
469 self.assertEqual(packet_num, len(capture))
470 for packet in capture:
471 try:
472 self.assertEqual(packet[IPv6].src, src_ip)
473 self.assertEqual(packet[IPv6].dst, dst_ip)
474 if packet.haslayer(TCP):
475 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700476 self.check_tcp_checksum(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700477 elif packet.haslayer(UDP):
478 self.assertEqual(packet[UDP].dport, self.udp_port_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700479 self.check_udp_checksum(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700480 else:
481 self.assertEqual(packet[ICMPv6EchoReply].id,
482 self.icmp_id_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700483 self.check_icmpv6_checksum(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700484 except:
485 self.logger.error(ppp("Unexpected or invalid packet "
486 "(inside network):", packet))
487 raise
488
Matus Fabian675a69c2017-01-18 01:46:01 -0800489 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
490 """
491 Verify captured packet that don't have to be translated
492
493 :param capture: Captured packets
494 :param ingress_if: Ingress interface
495 :param egress_if: Egress interface
496 """
497 for packet in capture:
498 try:
499 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
500 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
501 if packet.haslayer(TCP):
502 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
503 elif packet.haslayer(UDP):
504 self.assertEqual(packet[UDP].sport, self.udp_port_in)
505 else:
506 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
507 except:
508 self.logger.error(ppp("Unexpected or invalid packet "
509 "(inside network):", packet))
510 raise
511
Juraj Slobodab33f4132017-02-08 23:54:21 -0800512 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
513 packet_num=3, icmp_type=11):
514 """
515 Verify captured packets with ICMP errors on outside network
516
517 :param capture: Captured packets
518 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700519 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800520 :param packet_num: Expected number of packets (Default 3)
521 :param icmp_type: Type of error ICMP packet
522 we are expecting (Default 11)
523 """
524 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700525 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800526 self.assertEqual(packet_num, len(capture))
527 for packet in capture:
528 try:
529 self.assertEqual(packet[IP].src, src_ip)
530 self.assertTrue(packet.haslayer(ICMP))
531 icmp = packet[ICMP]
532 self.assertEqual(icmp.type, icmp_type)
533 self.assertTrue(icmp.haslayer(IPerror))
534 inner_ip = icmp[IPerror]
535 if inner_ip.haslayer(TCPerror):
536 self.assertEqual(inner_ip[TCPerror].dport,
537 self.tcp_port_out)
538 elif inner_ip.haslayer(UDPerror):
539 self.assertEqual(inner_ip[UDPerror].dport,
540 self.udp_port_out)
541 else:
542 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
543 except:
544 self.logger.error(ppp("Unexpected or invalid packet "
545 "(outside network):", packet))
546 raise
547
548 def verify_capture_in_with_icmp_errors(self, capture, in_if, packet_num=3,
549 icmp_type=11):
550 """
551 Verify captured packets with ICMP errors on inside network
552
553 :param capture: Captured packets
554 :param in_if: Inside interface
555 :param packet_num: Expected number of packets (Default 3)
556 :param icmp_type: Type of error ICMP packet
557 we are expecting (Default 11)
558 """
559 self.assertEqual(packet_num, len(capture))
560 for packet in capture:
561 try:
562 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
563 self.assertTrue(packet.haslayer(ICMP))
564 icmp = packet[ICMP]
565 self.assertEqual(icmp.type, icmp_type)
566 self.assertTrue(icmp.haslayer(IPerror))
567 inner_ip = icmp[IPerror]
568 if inner_ip.haslayer(TCPerror):
569 self.assertEqual(inner_ip[TCPerror].sport,
570 self.tcp_port_in)
571 elif inner_ip.haslayer(UDPerror):
572 self.assertEqual(inner_ip[UDPerror].sport,
573 self.udp_port_in)
574 else:
575 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
576 except:
577 self.logger.error(ppp("Unexpected or invalid packet "
578 "(inside network):", packet))
579 raise
580
Matus Fabianefcd1e92017-08-15 06:59:19 -0700581 def create_stream_frag(self, src_if, dst, sport, dport, data):
582 """
583 Create fragmented packet stream
584
585 :param src_if: Source interface
586 :param dst: Destination IPv4 address
587 :param sport: Source TCP port
588 :param dport: Destination TCP port
589 :param data: Payload data
590 :returns: Fragmets
591 """
592 id = random.randint(0, 65535)
593 p = (IP(src=src_if.remote_ip4, dst=dst) /
594 TCP(sport=sport, dport=dport) /
595 Raw(data))
596 p = p.__class__(str(p))
597 chksum = p['TCP'].chksum
598 pkts = []
599 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
600 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
601 TCP(sport=sport, dport=dport, chksum=chksum) /
602 Raw(data[0:4]))
603 pkts.append(p)
604 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
605 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
606 proto=IP_PROTOS.tcp) /
607 Raw(data[4:20]))
608 pkts.append(p)
609 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
610 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
611 id=id) /
612 Raw(data[20:]))
613 pkts.append(p)
614 return pkts
615
616 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
617 pref=None, plen=0, frag_size=128):
618 """
619 Create fragmented packet stream
620
621 :param src_if: Source interface
622 :param dst: Destination IPv4 address
623 :param sport: Source TCP port
624 :param dport: Destination TCP port
625 :param data: Payload data
626 :param pref: NAT64 prefix
627 :param plen: NAT64 prefix length
628 :param fragsize: size of fragments
629 :returns: Fragmets
630 """
631 if pref is None:
632 dst_ip6 = ''.join(['64:ff9b::', dst])
633 else:
634 dst_ip6 = self.compose_ip6(dst, pref, plen)
635
636 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
637 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
638 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
639 TCP(sport=sport, dport=dport) /
640 Raw(data))
641
642 return fragment6(p, frag_size)
643
644 def reass_frags_and_verify(self, frags, src, dst):
645 """
646 Reassemble and verify fragmented packet
647
648 :param frags: Captured fragments
649 :param src: Source IPv4 address to verify
650 :param dst: Destination IPv4 address to verify
651
652 :returns: Reassembled IPv4 packet
653 """
654 buffer = StringIO.StringIO()
655 for p in frags:
656 self.assertEqual(p[IP].src, src)
657 self.assertEqual(p[IP].dst, dst)
658 self.check_ip_checksum(p)
659 buffer.seek(p[IP].frag * 8)
660 buffer.write(p[IP].payload)
661 ip = frags[0].getlayer(IP)
662 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
663 proto=frags[0][IP].proto)
664 if ip.proto == IP_PROTOS.tcp:
665 p = (ip / TCP(buffer.getvalue()))
666 self.check_tcp_checksum(p)
667 elif ip.proto == IP_PROTOS.udp:
668 p = (ip / UDP(buffer.getvalue()))
669 return p
670
671 def reass_frags_and_verify_ip6(self, frags, src, dst):
672 """
673 Reassemble and verify fragmented packet
674
675 :param frags: Captured fragments
676 :param src: Source IPv6 address to verify
677 :param dst: Destination IPv6 address to verify
678
679 :returns: Reassembled IPv6 packet
680 """
681 buffer = StringIO.StringIO()
682 for p in frags:
683 self.assertEqual(p[IPv6].src, src)
684 self.assertEqual(p[IPv6].dst, dst)
685 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
686 buffer.write(p[IPv6ExtHdrFragment].payload)
687 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
688 nh=frags[0][IPv6ExtHdrFragment].nh)
689 if ip.nh == IP_PROTOS.tcp:
690 p = (ip / TCP(buffer.getvalue()))
691 self.check_tcp_checksum(p)
692 elif ip.nh == IP_PROTOS.udp:
693 p = (ip / UDP(buffer.getvalue()))
694 return p
695
Matus Fabianeea28d72017-01-13 04:15:54 -0800696 def verify_ipfix_nat44_ses(self, data):
697 """
698 Verify IPFIX NAT44 session create/delete event
699
700 :param data: Decoded IPFIX data records
701 """
702 nat44_ses_create_num = 0
703 nat44_ses_delete_num = 0
704 self.assertEqual(6, len(data))
705 for record in data:
706 # natEvent
707 self.assertIn(ord(record[230]), [4, 5])
708 if ord(record[230]) == 4:
709 nat44_ses_create_num += 1
710 else:
711 nat44_ses_delete_num += 1
712 # sourceIPv4Address
713 self.assertEqual(self.pg0.remote_ip4n, record[8])
714 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700715 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800716 record[225])
717 # ingressVRFID
718 self.assertEqual(struct.pack("!I", 0), record[234])
719 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
720 if IP_PROTOS.icmp == ord(record[4]):
721 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
722 self.assertEqual(struct.pack("!H", self.icmp_id_out),
723 record[227])
724 elif IP_PROTOS.tcp == ord(record[4]):
725 self.assertEqual(struct.pack("!H", self.tcp_port_in),
726 record[7])
727 self.assertEqual(struct.pack("!H", self.tcp_port_out),
728 record[227])
729 elif IP_PROTOS.udp == ord(record[4]):
730 self.assertEqual(struct.pack("!H", self.udp_port_in),
731 record[7])
732 self.assertEqual(struct.pack("!H", self.udp_port_out),
733 record[227])
734 else:
735 self.fail("Invalid protocol")
736 self.assertEqual(3, nat44_ses_create_num)
737 self.assertEqual(3, nat44_ses_delete_num)
738
739 def verify_ipfix_addr_exhausted(self, data):
740 """
741 Verify IPFIX NAT addresses event
742
743 :param data: Decoded IPFIX data records
744 """
745 self.assertEqual(1, len(data))
746 record = data[0]
747 # natEvent
748 self.assertEqual(ord(record[230]), 3)
749 # natPoolID
750 self.assertEqual(struct.pack("!I", 0), record[283])
751
Matus Fabiana431ad12018-01-04 04:03:14 -0800752 def verify_ipfix_max_sessions(self, data, limit):
753 """
754 Verify IPFIX maximum session entries exceeded event
755
756 :param data: Decoded IPFIX data records
757 :param limit: Number of maximum session entries that can be created.
758 """
759 self.assertEqual(1, len(data))
760 record = data[0]
761 # natEvent
762 self.assertEqual(ord(record[230]), 13)
763 # natQuotaExceededEvent
764 self.assertEqual(struct.pack("I", 1), record[466])
765 # maxSessionEntries
766 self.assertEqual(struct.pack("I", limit), record[471])
767
768 def verify_ipfix_max_bibs(self, data, limit):
769 """
770 Verify IPFIX maximum BIB entries exceeded event
771
772 :param data: Decoded IPFIX data records
773 :param limit: Number of maximum BIB entries that can be created.
774 """
775 self.assertEqual(1, len(data))
776 record = data[0]
777 # natEvent
778 self.assertEqual(ord(record[230]), 13)
779 # natQuotaExceededEvent
780 self.assertEqual(struct.pack("I", 2), record[466])
781 # maxBIBEntries
782 self.assertEqual(struct.pack("I", limit), record[472])
783
784 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
785 """
786 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
787
788 :param data: Decoded IPFIX data records
789 :param limit: Number of maximum fragments pending reassembly
790 :param src_addr: IPv6 source address
791 """
792 self.assertEqual(1, len(data))
793 record = data[0]
794 # natEvent
795 self.assertEqual(ord(record[230]), 13)
796 # natQuotaExceededEvent
797 self.assertEqual(struct.pack("I", 5), record[466])
798 # maxFragmentsPendingReassembly
799 self.assertEqual(struct.pack("I", limit), record[475])
800 # sourceIPv6Address
801 self.assertEqual(src_addr, record[27])
802
803 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
804 """
805 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
806
807 :param data: Decoded IPFIX data records
808 :param limit: Number of maximum fragments pending reassembly
809 :param src_addr: IPv4 source address
810 """
811 self.assertEqual(1, len(data))
812 record = data[0]
813 # natEvent
814 self.assertEqual(ord(record[230]), 13)
815 # natQuotaExceededEvent
816 self.assertEqual(struct.pack("I", 5), record[466])
817 # maxFragmentsPendingReassembly
818 self.assertEqual(struct.pack("I", limit), record[475])
819 # sourceIPv4Address
820 self.assertEqual(src_addr, record[8])
821
822 def verify_ipfix_bib(self, data, is_create, src_addr):
823 """
824 Verify IPFIX NAT64 BIB create and delete events
825
826 :param data: Decoded IPFIX data records
827 :param is_create: Create event if nonzero value otherwise delete event
828 :param src_addr: IPv6 source address
829 """
830 self.assertEqual(1, len(data))
831 record = data[0]
832 # natEvent
833 if is_create:
834 self.assertEqual(ord(record[230]), 10)
835 else:
836 self.assertEqual(ord(record[230]), 11)
837 # sourceIPv6Address
838 self.assertEqual(src_addr, record[27])
839 # postNATSourceIPv4Address
840 self.assertEqual(self.nat_addr_n, record[225])
841 # protocolIdentifier
842 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
843 # ingressVRFID
844 self.assertEqual(struct.pack("!I", 0), record[234])
845 # sourceTransportPort
846 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
847 # postNAPTSourceTransportPort
848 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
849
850 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
851 dst_port):
852 """
853 Verify IPFIX NAT64 session create and delete events
854
855 :param data: Decoded IPFIX data records
856 :param is_create: Create event if nonzero value otherwise delete event
857 :param src_addr: IPv6 source address
858 :param dst_addr: IPv4 destination address
859 :param dst_port: destination TCP port
860 """
861 self.assertEqual(1, len(data))
862 record = data[0]
863 # natEvent
864 if is_create:
865 self.assertEqual(ord(record[230]), 6)
866 else:
867 self.assertEqual(ord(record[230]), 7)
868 # sourceIPv6Address
869 self.assertEqual(src_addr, record[27])
870 # destinationIPv6Address
871 self.assertEqual(socket.inet_pton(socket.AF_INET6,
872 self.compose_ip6(dst_addr,
873 '64:ff9b::',
874 96)),
875 record[28])
876 # postNATSourceIPv4Address
877 self.assertEqual(self.nat_addr_n, record[225])
878 # postNATDestinationIPv4Address
879 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
880 record[226])
881 # protocolIdentifier
882 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
883 # ingressVRFID
884 self.assertEqual(struct.pack("!I", 0), record[234])
885 # sourceTransportPort
886 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
887 # postNAPTSourceTransportPort
888 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
889 # destinationTransportPort
890 self.assertEqual(struct.pack("!H", dst_port), record[11])
891 # postNAPTDestinationTransportPort
892 self.assertEqual(struct.pack("!H", dst_port), record[228])
893
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700894
Matus Fabian2ba92e32017-08-21 07:05:03 -0700895class TestNAT44(MethodHolder):
896 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700897
898 @classmethod
899 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -0700900 super(TestNAT44, cls).setUpClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700901
902 try:
903 cls.tcp_port_in = 6303
904 cls.tcp_port_out = 6303
905 cls.udp_port_in = 6304
906 cls.udp_port_out = 6304
907 cls.icmp_id_in = 6305
908 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -0700909 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +0100910 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700911 cls.ipfix_src_port = 4739
912 cls.ipfix_domain_id = 1
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700913
Matus Fabian36ea2d62017-10-24 04:13:49 -0700914 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700915 cls.interfaces = list(cls.pg_interfaces[0:4])
916
917 for i in cls.interfaces:
918 i.admin_up()
919 i.config_ip4()
920 i.resolve_arp()
921
Matus Fabian6fa74c62017-06-05 05:55:48 -0700922 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700923 cls.pg0.configure_ipv4_neighbors()
924
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200925 cls.pg1.generate_remote_hosts(1)
926 cls.pg1.configure_ipv4_neighbors()
927
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700928 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -0700929 cls.vapi.ip_table_add_del(10, is_add=1)
930 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700931
932 cls.pg4._local_ip4 = "172.16.255.1"
933 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
934 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
935 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -0700936 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700937 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -0700938 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700939 cls.pg5.set_table_ip4(10)
940 cls.pg6._local_ip4 = "172.16.255.1"
941 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
942 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
943 cls.pg6.set_table_ip4(20)
944 for i in cls.overlapping_interfaces:
945 i.config_ip4()
946 i.admin_up()
947 i.resolve_arp()
948
949 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -0700950 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700951
Matus Fabian36ea2d62017-10-24 04:13:49 -0700952 cls.pg9.generate_remote_hosts(2)
953 cls.pg9.config_ip4()
954 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
955 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
956 ip_addr_n,
957 24)
958 cls.pg9.admin_up()
959 cls.pg9.resolve_arp()
960 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
961 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
962 cls.pg9.resolve_arp()
963
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700964 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700965 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700966 raise
967
Matus Fabian2ba92e32017-08-21 07:05:03 -0700968 def clear_nat44(self):
Matus Fabiande886752016-12-07 03:38:19 -0800969 """
Matus Fabian2ba92e32017-08-21 07:05:03 -0700970 Clear NAT44 configuration.
Matus Fabiande886752016-12-07 03:38:19 -0800971 """
Martin Gálik406eb1d2017-05-04 04:35:04 -0700972 # I found no elegant way to do this
973 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
974 dst_address_length=32,
975 next_hop_address=self.pg7.remote_ip4n,
976 next_hop_sw_if_index=self.pg7.sw_if_index,
977 is_add=0)
978 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
979 dst_address_length=32,
980 next_hop_address=self.pg8.remote_ip4n,
981 next_hop_sw_if_index=self.pg8.sw_if_index,
982 is_add=0)
983
984 for intf in [self.pg7, self.pg8]:
985 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
986 for n in neighbors:
987 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
988 n.mac_address,
989 n.ip_address,
990 is_add=0)
991
Matus Fabian36532bd2017-01-23 23:42:28 -0800992 if self.pg7.has_ip4_config:
993 self.pg7.unconfig_ip4()
994
Matus Fabian240b5ef2018-01-11 04:09:17 -0800995 self.vapi.nat44_forwarding_enable_disable(0)
996
Matus Fabian2ba92e32017-08-21 07:05:03 -0700997 interfaces = self.vapi.nat44_interface_addr_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -0800998 for intf in interfaces:
Matus Fabianb932d262017-12-18 05:38:24 -0800999 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
1000 twice_nat=intf.twice_nat,
1001 is_add=0)
Matus Fabian8bf68e82017-01-12 04:24:35 -08001002
Matus Fabian2ba92e32017-08-21 07:05:03 -07001003 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
1004 domain_id=self.ipfix_domain_id)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001005 self.ipfix_src_port = 4739
1006 self.ipfix_domain_id = 1
Matus Fabianeea28d72017-01-13 04:15:54 -08001007
Matus Fabian2ba92e32017-08-21 07:05:03 -07001008 interfaces = self.vapi.nat44_interface_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001009 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07001010 if intf.is_inside > 1:
1011 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
1012 0,
1013 is_add=0)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001014 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
1015 intf.is_inside,
1016 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001017
Matus Fabian2ba92e32017-08-21 07:05:03 -07001018 interfaces = self.vapi.nat44_interface_output_feature_dump()
Matus Fabian93d84c92017-07-19 08:06:01 -07001019 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001020 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
1021 intf.is_inside,
1022 is_add=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07001023
Matus Fabian2ba92e32017-08-21 07:05:03 -07001024 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001025 for sm in static_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001026 self.vapi.nat44_add_del_static_mapping(
1027 sm.local_ip_address,
1028 sm.external_ip_address,
1029 local_port=sm.local_port,
1030 external_port=sm.external_port,
1031 addr_only=sm.addr_only,
1032 vrf_id=sm.vrf_id,
1033 protocol=sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001034 twice_nat=sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001035 self_twice_nat=sm.self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001036 out2in_only=sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001037 tag=sm.tag,
Matus Fabianea2600a2018-03-28 04:06:26 -07001038 external_sw_if_index=sm.external_sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001039 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001040
Matus Fabian704018c2017-09-04 02:17:18 -07001041 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
1042 for lb_sm in lb_static_mappings:
1043 self.vapi.nat44_add_del_lb_static_mapping(
1044 lb_sm.external_addr,
1045 lb_sm.external_port,
1046 lb_sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001047 vrf_id=lb_sm.vrf_id,
1048 twice_nat=lb_sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001049 self_twice_nat=lb_sm.self_twice_nat,
Matus Fabian240b5ef2018-01-11 04:09:17 -08001050 out2in_only=lb_sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001051 tag=lb_sm.tag,
Ole Troan895b6e82017-10-20 13:28:20 +02001052 is_add=0,
1053 local_num=0,
1054 locals=[])
Matus Fabian704018c2017-09-04 02:17:18 -07001055
Matus Fabianab7a8052017-11-28 04:29:41 -08001056 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1057 for id_m in identity_mappings:
1058 self.vapi.nat44_add_del_identity_mapping(
1059 addr_only=id_m.addr_only,
1060 ip=id_m.ip_address,
1061 port=id_m.port,
1062 sw_if_index=id_m.sw_if_index,
1063 vrf_id=id_m.vrf_id,
1064 protocol=id_m.protocol,
1065 is_add=0)
1066
Matus Fabian2ba92e32017-08-21 07:05:03 -07001067 adresses = self.vapi.nat44_address_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001068 for addr in adresses:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001069 self.vapi.nat44_add_del_address_range(addr.ip_address,
1070 addr.ip_address,
Matus Fabianb932d262017-12-18 05:38:24 -08001071 twice_nat=addr.twice_nat,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001072 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001073
Matus Fabianefcd1e92017-08-15 06:59:19 -07001074 self.vapi.nat_set_reass()
1075 self.vapi.nat_set_reass(is_ip6=1)
1076
Matus Fabian2ba92e32017-08-21 07:05:03 -07001077 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1078 local_port=0, external_port=0, vrf_id=0,
1079 is_add=1, external_sw_if_index=0xFFFFFFFF,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001080 proto=0, twice_nat=0, self_twice_nat=0,
1081 out2in_only=0, tag=""):
Matus Fabiande886752016-12-07 03:38:19 -08001082 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001083 Add/delete NAT44 static mapping
Matus Fabiande886752016-12-07 03:38:19 -08001084
1085 :param local_ip: Local IP address
1086 :param external_ip: External IP address
1087 :param local_port: Local port number (Optional)
1088 :param external_port: External port number (Optional)
1089 :param vrf_id: VRF ID (Default 0)
1090 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabian36532bd2017-01-23 23:42:28 -08001091 :param external_sw_if_index: External interface instead of IP address
Matus Fabian09d96f42017-02-02 01:43:00 -08001092 :param proto: IP protocol (Mandatory if port specified)
Matus Fabianb932d262017-12-18 05:38:24 -08001093 :param twice_nat: 1 if translate external host address and port
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001094 :param self_twice_nat: 1 if translate external host address and port
1095 whenever external host address equals
1096 local address of internal host
Matus Fabiane82488f2018-01-18 03:38:45 -08001097 :param out2in_only: if 1 rule is matching only out2in direction
Matus Fabian5f224992018-01-25 21:59:16 -08001098 :param tag: Opaque string tag
Matus Fabiande886752016-12-07 03:38:19 -08001099 """
1100 addr_only = 1
1101 if local_port and external_port:
1102 addr_only = 0
1103 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1104 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001105 self.vapi.nat44_add_del_static_mapping(
Klement Sekerada505f62017-01-04 12:58:53 +01001106 l_ip,
1107 e_ip,
Matus Fabian36532bd2017-01-23 23:42:28 -08001108 external_sw_if_index,
Klement Sekerada505f62017-01-04 12:58:53 +01001109 local_port,
1110 external_port,
1111 addr_only,
1112 vrf_id,
Matus Fabian09d96f42017-02-02 01:43:00 -08001113 proto,
Matus Fabianb932d262017-12-18 05:38:24 -08001114 twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001115 self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001116 out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001117 tag,
Klement Sekerada505f62017-01-04 12:58:53 +01001118 is_add)
Matus Fabiande886752016-12-07 03:38:19 -08001119
Matus Fabianb932d262017-12-18 05:38:24 -08001120 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
Matus Fabiande886752016-12-07 03:38:19 -08001121 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001122 Add/delete NAT44 address
Matus Fabiande886752016-12-07 03:38:19 -08001123
1124 :param ip: IP address
1125 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabianb932d262017-12-18 05:38:24 -08001126 :param twice_nat: twice NAT address for extenal hosts
Matus Fabiande886752016-12-07 03:38:19 -08001127 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001128 nat_addr = socket.inet_pton(socket.AF_INET, ip)
1129 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
Matus Fabianb932d262017-12-18 05:38:24 -08001130 vrf_id=vrf_id,
1131 twice_nat=twice_nat)
Matus Fabiande886752016-12-07 03:38:19 -08001132
1133 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001134 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001135
Matus Fabian2ba92e32017-08-21 07:05:03 -07001136 self.nat44_add_address(self.nat_addr)
1137 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1138 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1139 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001140
1141 # in2out
1142 pkts = self.create_stream_in(self.pg0, self.pg1)
1143 self.pg0.add_stream(pkts)
1144 self.pg_enable_capture(self.pg_interfaces)
1145 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001146 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001147 self.verify_capture_out(capture)
1148
1149 # out2in
1150 pkts = self.create_stream_out(self.pg1)
1151 self.pg1.add_stream(pkts)
1152 self.pg_enable_capture(self.pg_interfaces)
1153 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001154 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001155 self.verify_capture_in(capture, self.pg0)
1156
Juraj Slobodab33f4132017-02-08 23:54:21 -08001157 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001158 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001159
Matus Fabian2ba92e32017-08-21 07:05:03 -07001160 self.nat44_add_address(self.nat_addr)
1161 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1162 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1163 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001164
1165 # Client side - generate traffic
1166 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1167 self.pg0.add_stream(pkts)
1168 self.pg_enable_capture(self.pg_interfaces)
1169 self.pg_start()
1170
1171 # Client side - verify ICMP type 11 packets
1172 capture = self.pg0.get_capture(len(pkts))
1173 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1174
1175 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001176 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001177
Matus Fabian2ba92e32017-08-21 07:05:03 -07001178 self.nat44_add_address(self.nat_addr)
1179 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1180 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1181 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001182
1183 # Client side - create sessions
1184 pkts = self.create_stream_in(self.pg0, self.pg1)
1185 self.pg0.add_stream(pkts)
1186 self.pg_enable_capture(self.pg_interfaces)
1187 self.pg_start()
1188
1189 # Server side - generate traffic
1190 capture = self.pg1.get_capture(len(pkts))
1191 self.verify_capture_out(capture)
1192 pkts = self.create_stream_out(self.pg1, ttl=1)
1193 self.pg1.add_stream(pkts)
1194 self.pg_enable_capture(self.pg_interfaces)
1195 self.pg_start()
1196
1197 # Server side - verify ICMP type 11 packets
1198 capture = self.pg1.get_capture(len(pkts))
1199 self.verify_capture_out_with_icmp_errors(capture,
1200 src_ip=self.pg1.local_ip4)
1201
1202 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001203 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001204
Matus Fabian2ba92e32017-08-21 07:05:03 -07001205 self.nat44_add_address(self.nat_addr)
1206 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1207 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1208 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001209
1210 # Client side - generate traffic
1211 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1212 self.pg0.add_stream(pkts)
1213 self.pg_enable_capture(self.pg_interfaces)
1214 self.pg_start()
1215
1216 # Server side - simulate ICMP type 11 response
1217 capture = self.pg1.get_capture(len(pkts))
1218 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001219 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001220 ICMP(type=11) / packet[IP] for packet in capture]
1221 self.pg1.add_stream(pkts)
1222 self.pg_enable_capture(self.pg_interfaces)
1223 self.pg_start()
1224
1225 # Client side - verify ICMP type 11 packets
1226 capture = self.pg0.get_capture(len(pkts))
1227 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1228
1229 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001230 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001231
Matus Fabian2ba92e32017-08-21 07:05:03 -07001232 self.nat44_add_address(self.nat_addr)
1233 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1234 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1235 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001236
1237 # Client side - create sessions
1238 pkts = self.create_stream_in(self.pg0, self.pg1)
1239 self.pg0.add_stream(pkts)
1240 self.pg_enable_capture(self.pg_interfaces)
1241 self.pg_start()
1242
1243 # Server side - generate traffic
1244 capture = self.pg1.get_capture(len(pkts))
1245 self.verify_capture_out(capture)
1246 pkts = self.create_stream_out(self.pg1, ttl=2)
1247 self.pg1.add_stream(pkts)
1248 self.pg_enable_capture(self.pg_interfaces)
1249 self.pg_start()
1250
1251 # Client side - simulate ICMP type 11 response
1252 capture = self.pg0.get_capture(len(pkts))
1253 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1254 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1255 ICMP(type=11) / packet[IP] for packet in capture]
1256 self.pg0.add_stream(pkts)
1257 self.pg_enable_capture(self.pg_interfaces)
1258 self.pg_start()
1259
1260 # Server side - verify ICMP type 11 packets
1261 capture = self.pg1.get_capture(len(pkts))
1262 self.verify_capture_out_with_icmp_errors(capture)
1263
Juraj Sloboda665e4822017-02-16 17:17:19 -08001264 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001265 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001266
Matus Fabian2ba92e32017-08-21 07:05:03 -07001267 self.nat44_add_address(self.nat_addr)
1268 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1269 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1270 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001271
1272 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1273 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1274 ICMP(id=self.icmp_id_out, type='echo-request'))
1275 pkts = [p]
1276 self.pg1.add_stream(pkts)
1277 self.pg_enable_capture(self.pg_interfaces)
1278 self.pg_start()
1279 capture = self.pg1.get_capture(len(pkts))
1280 self.assertEqual(1, len(capture))
1281 packet = capture[0]
1282 try:
1283 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1284 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1285 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1286 self.assertEqual(packet[ICMP].type, 0) # echo reply
1287 except:
1288 self.logger.error(ppp("Unexpected or invalid packet "
1289 "(outside network):", packet))
1290 raise
1291
Juraj Slobodad3677682017-04-14 03:24:45 +02001292 def test_ping_internal_host_from_outside(self):
1293 """ Ping internal host from outside network """
1294
Matus Fabian2ba92e32017-08-21 07:05:03 -07001295 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1296 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1297 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1298 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001299
1300 # out2in
1301 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001302 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001303 ICMP(id=self.icmp_id_out, type='echo-request'))
1304 self.pg1.add_stream(pkt)
1305 self.pg_enable_capture(self.pg_interfaces)
1306 self.pg_start()
1307 capture = self.pg0.get_capture(1)
1308 self.verify_capture_in(capture, self.pg0, packet_num=1)
1309 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1310
1311 # in2out
1312 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1313 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1314 ICMP(id=self.icmp_id_in, type='echo-reply'))
1315 self.pg0.add_stream(pkt)
1316 self.pg_enable_capture(self.pg_interfaces)
1317 self.pg_start()
1318 capture = self.pg1.get_capture(1)
1319 self.verify_capture_out(capture, same_port=True, packet_num=1)
1320 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1321
Juraj Sloboda7b929792017-11-23 13:20:48 +01001322 def test_forwarding(self):
1323 """ NAT44 forwarding test """
1324
1325 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1326 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1327 is_inside=0)
1328 self.vapi.nat44_forwarding_enable_disable(1)
1329
1330 real_ip = self.pg0.remote_ip4n
1331 alias_ip = self.nat_addr_n
1332 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1333 external_ip=alias_ip)
1334
1335 try:
1336 # in2out - static mapping match
1337
1338 pkts = self.create_stream_out(self.pg1)
1339 self.pg1.add_stream(pkts)
1340 self.pg_enable_capture(self.pg_interfaces)
1341 self.pg_start()
1342 capture = self.pg0.get_capture(len(pkts))
1343 self.verify_capture_in(capture, self.pg0)
1344
1345 pkts = self.create_stream_in(self.pg0, self.pg1)
1346 self.pg0.add_stream(pkts)
1347 self.pg_enable_capture(self.pg_interfaces)
1348 self.pg_start()
1349 capture = self.pg1.get_capture(len(pkts))
1350 self.verify_capture_out(capture, same_port=True)
1351
1352 # in2out - no static mapping match
1353
1354 host0 = self.pg0.remote_hosts[0]
1355 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1356 try:
1357 pkts = self.create_stream_out(self.pg1,
1358 dst_ip=self.pg0.remote_ip4,
1359 use_inside_ports=True)
1360 self.pg1.add_stream(pkts)
1361 self.pg_enable_capture(self.pg_interfaces)
1362 self.pg_start()
1363 capture = self.pg0.get_capture(len(pkts))
1364 self.verify_capture_in(capture, self.pg0)
1365
1366 pkts = self.create_stream_in(self.pg0, self.pg1)
1367 self.pg0.add_stream(pkts)
1368 self.pg_enable_capture(self.pg_interfaces)
1369 self.pg_start()
1370 capture = self.pg1.get_capture(len(pkts))
1371 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1372 same_port=True)
1373 finally:
1374 self.pg0.remote_hosts[0] = host0
1375
1376 finally:
1377 self.vapi.nat44_forwarding_enable_disable(0)
1378 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1379 external_ip=alias_ip,
1380 is_add=0)
1381
Matus Fabiande886752016-12-07 03:38:19 -08001382 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001383 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001384
1385 nat_ip = "10.0.0.10"
1386 self.tcp_port_out = 6303
1387 self.udp_port_out = 6304
1388 self.icmp_id_out = 6305
1389
Matus Fabian2ba92e32017-08-21 07:05:03 -07001390 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1391 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1392 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1393 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001394 sm = self.vapi.nat44_static_mapping_dump()
1395 self.assertEqual(len(sm), 1)
1396 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001397 self.assertEqual(sm[0].protocol, 0)
1398 self.assertEqual(sm[0].local_port, 0)
1399 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001400
1401 # in2out
1402 pkts = self.create_stream_in(self.pg0, self.pg1)
1403 self.pg0.add_stream(pkts)
1404 self.pg_enable_capture(self.pg_interfaces)
1405 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001406 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001407 self.verify_capture_out(capture, nat_ip, True)
1408
1409 # out2in
1410 pkts = self.create_stream_out(self.pg1, nat_ip)
1411 self.pg1.add_stream(pkts)
1412 self.pg_enable_capture(self.pg_interfaces)
1413 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001414 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001415 self.verify_capture_in(capture, self.pg0)
1416
1417 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001418 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001419
1420 nat_ip = "10.0.0.20"
1421 self.tcp_port_out = 6303
1422 self.udp_port_out = 6304
1423 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001424 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001425
Matus Fabian5f224992018-01-25 21:59:16 -08001426 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001427 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1428 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1429 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001430 sm = self.vapi.nat44_static_mapping_dump()
1431 self.assertEqual(len(sm), 1)
1432 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001433
1434 # out2in
1435 pkts = self.create_stream_out(self.pg1, nat_ip)
1436 self.pg1.add_stream(pkts)
1437 self.pg_enable_capture(self.pg_interfaces)
1438 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001439 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001440 self.verify_capture_in(capture, self.pg0)
1441
1442 # in2out
1443 pkts = self.create_stream_in(self.pg0, self.pg1)
1444 self.pg0.add_stream(pkts)
1445 self.pg_enable_capture(self.pg_interfaces)
1446 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001447 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001448 self.verify_capture_out(capture, nat_ip, True)
1449
1450 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001451 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001452
1453 self.tcp_port_out = 3606
1454 self.udp_port_out = 3607
1455 self.icmp_id_out = 3608
1456
Matus Fabian2ba92e32017-08-21 07:05:03 -07001457 self.nat44_add_address(self.nat_addr)
1458 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1459 self.tcp_port_in, self.tcp_port_out,
1460 proto=IP_PROTOS.tcp)
1461 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1462 self.udp_port_in, self.udp_port_out,
1463 proto=IP_PROTOS.udp)
1464 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1465 self.icmp_id_in, self.icmp_id_out,
1466 proto=IP_PROTOS.icmp)
1467 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1468 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1469 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001470
1471 # in2out
1472 pkts = self.create_stream_in(self.pg0, self.pg1)
1473 self.pg0.add_stream(pkts)
1474 self.pg_enable_capture(self.pg_interfaces)
1475 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001476 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001477 self.verify_capture_out(capture)
1478
1479 # out2in
1480 pkts = self.create_stream_out(self.pg1)
1481 self.pg1.add_stream(pkts)
1482 self.pg_enable_capture(self.pg_interfaces)
1483 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001484 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001485 self.verify_capture_in(capture, self.pg0)
1486
1487 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001488 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001489
1490 self.tcp_port_out = 30606
1491 self.udp_port_out = 30607
1492 self.icmp_id_out = 30608
1493
Matus Fabian2ba92e32017-08-21 07:05:03 -07001494 self.nat44_add_address(self.nat_addr)
1495 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1496 self.tcp_port_in, self.tcp_port_out,
1497 proto=IP_PROTOS.tcp)
1498 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1499 self.udp_port_in, self.udp_port_out,
1500 proto=IP_PROTOS.udp)
1501 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1502 self.icmp_id_in, self.icmp_id_out,
1503 proto=IP_PROTOS.icmp)
1504 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1505 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1506 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001507
1508 # out2in
1509 pkts = self.create_stream_out(self.pg1)
1510 self.pg1.add_stream(pkts)
1511 self.pg_enable_capture(self.pg_interfaces)
1512 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001513 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001514 self.verify_capture_in(capture, self.pg0)
1515
1516 # in2out
1517 pkts = self.create_stream_in(self.pg0, self.pg1)
1518 self.pg0.add_stream(pkts)
1519 self.pg_enable_capture(self.pg_interfaces)
1520 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001521 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001522 self.verify_capture_out(capture)
1523
Matus Fabiane82488f2018-01-18 03:38:45 -08001524 def test_static_with_port_out2(self):
1525 """ 1:1 NAPT symmetrical rule """
1526
1527 external_port = 80
1528 local_port = 8080
1529
1530 self.vapi.nat44_forwarding_enable_disable(1)
1531 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1532 local_port, external_port,
1533 proto=IP_PROTOS.tcp, out2in_only=1)
1534 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1535 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1536 is_inside=0)
1537
1538 # from client to service
1539 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1540 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1541 TCP(sport=12345, dport=external_port))
1542 self.pg1.add_stream(p)
1543 self.pg_enable_capture(self.pg_interfaces)
1544 self.pg_start()
1545 capture = self.pg0.get_capture(1)
1546 p = capture[0]
1547 server = None
1548 try:
1549 ip = p[IP]
1550 tcp = p[TCP]
1551 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1552 self.assertEqual(tcp.dport, local_port)
1553 self.check_tcp_checksum(p)
1554 self.check_ip_checksum(p)
1555 except:
1556 self.logger.error(ppp("Unexpected or invalid packet:", p))
1557 raise
1558
Matus Fabian87233b52018-01-26 03:17:01 -08001559 # ICMP error
1560 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1561 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1562 ICMP(type=11) / capture[0][IP])
1563 self.pg0.add_stream(p)
1564 self.pg_enable_capture(self.pg_interfaces)
1565 self.pg_start()
1566 capture = self.pg1.get_capture(1)
1567 p = capture[0]
1568 try:
1569 self.assertEqual(p[IP].src, self.nat_addr)
1570 inner = p[IPerror]
1571 self.assertEqual(inner.dst, self.nat_addr)
1572 self.assertEqual(inner[TCPerror].dport, external_port)
1573 except:
1574 self.logger.error(ppp("Unexpected or invalid packet:", p))
1575 raise
1576
Matus Fabiane82488f2018-01-18 03:38:45 -08001577 # from service back to client
1578 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1579 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1580 TCP(sport=local_port, dport=12345))
1581 self.pg0.add_stream(p)
1582 self.pg_enable_capture(self.pg_interfaces)
1583 self.pg_start()
1584 capture = self.pg1.get_capture(1)
1585 p = capture[0]
1586 try:
1587 ip = p[IP]
1588 tcp = p[TCP]
1589 self.assertEqual(ip.src, self.nat_addr)
1590 self.assertEqual(tcp.sport, external_port)
1591 self.check_tcp_checksum(p)
1592 self.check_ip_checksum(p)
1593 except:
1594 self.logger.error(ppp("Unexpected or invalid packet:", p))
1595 raise
1596
Matus Fabian87233b52018-01-26 03:17:01 -08001597 # ICMP error
1598 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1599 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1600 ICMP(type=11) / capture[0][IP])
1601 self.pg1.add_stream(p)
1602 self.pg_enable_capture(self.pg_interfaces)
1603 self.pg_start()
1604 capture = self.pg0.get_capture(1)
1605 p = capture[0]
1606 try:
1607 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1608 inner = p[IPerror]
1609 self.assertEqual(inner.src, self.pg0.remote_ip4)
1610 self.assertEqual(inner[TCPerror].sport, local_port)
1611 except:
1612 self.logger.error(ppp("Unexpected or invalid packet:", p))
1613 raise
1614
Matus Fabiane82488f2018-01-18 03:38:45 -08001615 # from client to server (no translation)
1616 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1617 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1618 TCP(sport=12346, dport=local_port))
1619 self.pg1.add_stream(p)
1620 self.pg_enable_capture(self.pg_interfaces)
1621 self.pg_start()
1622 capture = self.pg0.get_capture(1)
1623 p = capture[0]
1624 server = None
1625 try:
1626 ip = p[IP]
1627 tcp = p[TCP]
1628 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1629 self.assertEqual(tcp.dport, local_port)
1630 self.check_tcp_checksum(p)
1631 self.check_ip_checksum(p)
1632 except:
1633 self.logger.error(ppp("Unexpected or invalid packet:", p))
1634 raise
1635
1636 # from service back to client (no translation)
1637 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1638 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1639 TCP(sport=local_port, dport=12346))
1640 self.pg0.add_stream(p)
1641 self.pg_enable_capture(self.pg_interfaces)
1642 self.pg_start()
1643 capture = self.pg1.get_capture(1)
1644 p = capture[0]
1645 try:
1646 ip = p[IP]
1647 tcp = p[TCP]
1648 self.assertEqual(ip.src, self.pg0.remote_ip4)
1649 self.assertEqual(tcp.sport, local_port)
1650 self.check_tcp_checksum(p)
1651 self.check_ip_checksum(p)
1652 except:
1653 self.logger.error(ppp("Unexpected or invalid packet:", p))
1654 raise
1655
Matus Fabiande886752016-12-07 03:38:19 -08001656 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001657 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001658
1659 nat_ip1 = "10.0.0.30"
1660 nat_ip2 = "10.0.0.40"
1661 self.tcp_port_out = 6303
1662 self.udp_port_out = 6304
1663 self.icmp_id_out = 6305
1664
Matus Fabian2ba92e32017-08-21 07:05:03 -07001665 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1666 vrf_id=10)
1667 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1668 vrf_id=10)
1669 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1670 is_inside=0)
1671 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1672 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001673
Matus Fabian2ba92e32017-08-21 07:05:03 -07001674 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001675 pkts = self.create_stream_in(self.pg4, self.pg3)
1676 self.pg4.add_stream(pkts)
1677 self.pg_enable_capture(self.pg_interfaces)
1678 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001679 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001680 self.verify_capture_out(capture, nat_ip1, True)
1681
Matus Fabian2ba92e32017-08-21 07:05:03 -07001682 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001683 # are dropped)
1684 pkts = self.create_stream_in(self.pg0, self.pg3)
1685 self.pg0.add_stream(pkts)
1686 self.pg_enable_capture(self.pg_interfaces)
1687 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001688 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001689
Matus Fabianb793d092018-01-31 05:50:21 -08001690 def test_dynamic_to_static(self):
1691 """ Switch from dynamic translation to 1:1NAT """
1692 nat_ip = "10.0.0.10"
1693 self.tcp_port_out = 6303
1694 self.udp_port_out = 6304
1695 self.icmp_id_out = 6305
1696
1697 self.nat44_add_address(self.nat_addr)
1698 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1699 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1700 is_inside=0)
1701
1702 # dynamic
1703 pkts = self.create_stream_in(self.pg0, self.pg1)
1704 self.pg0.add_stream(pkts)
1705 self.pg_enable_capture(self.pg_interfaces)
1706 self.pg_start()
1707 capture = self.pg1.get_capture(len(pkts))
1708 self.verify_capture_out(capture)
1709
1710 # 1:1NAT
1711 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1712 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1713 self.assertEqual(len(sessions), 0)
1714 pkts = self.create_stream_in(self.pg0, self.pg1)
1715 self.pg0.add_stream(pkts)
1716 self.pg_enable_capture(self.pg_interfaces)
1717 self.pg_start()
1718 capture = self.pg1.get_capture(len(pkts))
1719 self.verify_capture_out(capture, nat_ip, True)
1720
Matus Fabianab7a8052017-11-28 04:29:41 -08001721 def test_identity_nat(self):
1722 """ Identity NAT """
1723
1724 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1725 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1726 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1727 is_inside=0)
1728
1729 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1730 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1731 TCP(sport=12345, dport=56789))
1732 self.pg1.add_stream(p)
1733 self.pg_enable_capture(self.pg_interfaces)
1734 self.pg_start()
1735 capture = self.pg0.get_capture(1)
1736 p = capture[0]
1737 try:
1738 ip = p[IP]
1739 tcp = p[TCP]
1740 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1741 self.assertEqual(ip.src, self.pg1.remote_ip4)
1742 self.assertEqual(tcp.dport, 56789)
1743 self.assertEqual(tcp.sport, 12345)
1744 self.check_tcp_checksum(p)
1745 self.check_ip_checksum(p)
1746 except:
1747 self.logger.error(ppp("Unexpected or invalid packet:", p))
1748 raise
1749
Matus Fabian704018c2017-09-04 02:17:18 -07001750 def test_static_lb(self):
1751 """ NAT44 local service load balancing """
1752 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1753 external_port = 80
1754 local_port = 8080
1755 server1 = self.pg0.remote_hosts[0]
1756 server2 = self.pg0.remote_hosts[1]
1757
1758 locals = [{'addr': server1.ip4n,
1759 'port': local_port,
1760 'probability': 70},
1761 {'addr': server2.ip4n,
1762 'port': local_port,
1763 'probability': 30}]
1764
1765 self.nat44_add_address(self.nat_addr)
1766 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1767 external_port,
1768 IP_PROTOS.tcp,
1769 local_num=len(locals),
1770 locals=locals)
1771 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1772 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1773 is_inside=0)
1774
1775 # from client to service
1776 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1777 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1778 TCP(sport=12345, dport=external_port))
1779 self.pg1.add_stream(p)
1780 self.pg_enable_capture(self.pg_interfaces)
1781 self.pg_start()
1782 capture = self.pg0.get_capture(1)
1783 p = capture[0]
1784 server = None
1785 try:
1786 ip = p[IP]
1787 tcp = p[TCP]
1788 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1789 if ip.dst == server1.ip4:
1790 server = server1
1791 else:
1792 server = server2
1793 self.assertEqual(tcp.dport, local_port)
1794 self.check_tcp_checksum(p)
1795 self.check_ip_checksum(p)
1796 except:
1797 self.logger.error(ppp("Unexpected or invalid packet:", p))
1798 raise
1799
1800 # from service back to client
1801 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1802 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1803 TCP(sport=local_port, dport=12345))
1804 self.pg0.add_stream(p)
1805 self.pg_enable_capture(self.pg_interfaces)
1806 self.pg_start()
1807 capture = self.pg1.get_capture(1)
1808 p = capture[0]
1809 try:
1810 ip = p[IP]
1811 tcp = p[TCP]
1812 self.assertEqual(ip.src, self.nat_addr)
1813 self.assertEqual(tcp.sport, external_port)
1814 self.check_tcp_checksum(p)
1815 self.check_ip_checksum(p)
1816 except:
1817 self.logger.error(ppp("Unexpected or invalid packet:", p))
1818 raise
1819
Matus Fabian2aad8762018-03-07 04:57:22 -08001820 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1821 def test_static_lb_multi_clients(self):
1822 """ NAT44 local service load balancing - multiple clients"""
1823
1824 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1825 external_port = 80
1826 local_port = 8080
1827 server1 = self.pg0.remote_hosts[0]
1828 server2 = self.pg0.remote_hosts[1]
1829
1830 locals = [{'addr': server1.ip4n,
1831 'port': local_port,
1832 'probability': 90},
1833 {'addr': server2.ip4n,
1834 'port': local_port,
1835 'probability': 10}]
1836
1837 self.nat44_add_address(self.nat_addr)
1838 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1839 external_port,
1840 IP_PROTOS.tcp,
1841 local_num=len(locals),
1842 locals=locals)
1843 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1844 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1845 is_inside=0)
1846
Matus Fabian704018c2017-09-04 02:17:18 -07001847 server1_n = 0
1848 server2_n = 0
Matus Fabian2aad8762018-03-07 04:57:22 -08001849 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
Matus Fabian704018c2017-09-04 02:17:18 -07001850 pkts = []
1851 for client in clients:
1852 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1853 IP(src=client, dst=self.nat_addr) /
1854 TCP(sport=12345, dport=external_port))
1855 pkts.append(p)
1856 self.pg1.add_stream(pkts)
1857 self.pg_enable_capture(self.pg_interfaces)
1858 self.pg_start()
1859 capture = self.pg0.get_capture(len(pkts))
1860 for p in capture:
1861 if p[IP].dst == server1.ip4:
1862 server1_n += 1
1863 else:
1864 server2_n += 1
1865 self.assertTrue(server1_n > server2_n)
1866
Matus Fabian240b5ef2018-01-11 04:09:17 -08001867 def test_static_lb_2(self):
1868 """ NAT44 local service load balancing (asymmetrical rule) """
1869 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1870 external_port = 80
1871 local_port = 8080
1872 server1 = self.pg0.remote_hosts[0]
1873 server2 = self.pg0.remote_hosts[1]
1874
1875 locals = [{'addr': server1.ip4n,
1876 'port': local_port,
1877 'probability': 70},
1878 {'addr': server2.ip4n,
1879 'port': local_port,
1880 'probability': 30}]
1881
1882 self.vapi.nat44_forwarding_enable_disable(1)
1883 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1884 external_port,
1885 IP_PROTOS.tcp,
1886 out2in_only=1,
1887 local_num=len(locals),
1888 locals=locals)
1889 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1890 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1891 is_inside=0)
1892
1893 # from client to service
1894 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1895 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1896 TCP(sport=12345, dport=external_port))
1897 self.pg1.add_stream(p)
1898 self.pg_enable_capture(self.pg_interfaces)
1899 self.pg_start()
1900 capture = self.pg0.get_capture(1)
1901 p = capture[0]
1902 server = None
1903 try:
1904 ip = p[IP]
1905 tcp = p[TCP]
1906 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1907 if ip.dst == server1.ip4:
1908 server = server1
1909 else:
1910 server = server2
1911 self.assertEqual(tcp.dport, local_port)
1912 self.check_tcp_checksum(p)
1913 self.check_ip_checksum(p)
1914 except:
1915 self.logger.error(ppp("Unexpected or invalid packet:", p))
1916 raise
1917
1918 # from service back to client
1919 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1920 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1921 TCP(sport=local_port, dport=12345))
1922 self.pg0.add_stream(p)
1923 self.pg_enable_capture(self.pg_interfaces)
1924 self.pg_start()
1925 capture = self.pg1.get_capture(1)
1926 p = capture[0]
1927 try:
1928 ip = p[IP]
1929 tcp = p[TCP]
1930 self.assertEqual(ip.src, self.nat_addr)
1931 self.assertEqual(tcp.sport, external_port)
1932 self.check_tcp_checksum(p)
1933 self.check_ip_checksum(p)
1934 except:
1935 self.logger.error(ppp("Unexpected or invalid packet:", p))
1936 raise
1937
1938 # from client to server (no translation)
1939 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1940 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1941 TCP(sport=12346, dport=local_port))
1942 self.pg1.add_stream(p)
1943 self.pg_enable_capture(self.pg_interfaces)
1944 self.pg_start()
1945 capture = self.pg0.get_capture(1)
1946 p = capture[0]
1947 server = None
1948 try:
1949 ip = p[IP]
1950 tcp = p[TCP]
1951 self.assertEqual(ip.dst, server1.ip4)
1952 self.assertEqual(tcp.dport, local_port)
1953 self.check_tcp_checksum(p)
1954 self.check_ip_checksum(p)
1955 except:
1956 self.logger.error(ppp("Unexpected or invalid packet:", p))
1957 raise
1958
1959 # from service back to client (no translation)
1960 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1961 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1962 TCP(sport=local_port, dport=12346))
1963 self.pg0.add_stream(p)
1964 self.pg_enable_capture(self.pg_interfaces)
1965 self.pg_start()
1966 capture = self.pg1.get_capture(1)
1967 p = capture[0]
1968 try:
1969 ip = p[IP]
1970 tcp = p[TCP]
1971 self.assertEqual(ip.src, server1.ip4)
1972 self.assertEqual(tcp.sport, local_port)
1973 self.check_tcp_checksum(p)
1974 self.check_ip_checksum(p)
1975 except:
1976 self.logger.error(ppp("Unexpected or invalid packet:", p))
1977 raise
1978
Matus Fabiande886752016-12-07 03:38:19 -08001979 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001980 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001981
Matus Fabian2ba92e32017-08-21 07:05:03 -07001982 self.nat44_add_address(self.nat_addr)
1983 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1984 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1985 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1986 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001987
Matus Fabian2ba92e32017-08-21 07:05:03 -07001988 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001989 pkts = self.create_stream_in(self.pg0, self.pg1)
1990 self.pg0.add_stream(pkts)
1991 self.pg_enable_capture(self.pg_interfaces)
1992 self.pg_start()
1993 capture = self.pg1.get_capture(len(pkts))
1994 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1995
Matus Fabian2ba92e32017-08-21 07:05:03 -07001996 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001997 pkts = self.create_stream_in(self.pg0, self.pg2)
1998 self.pg0.add_stream(pkts)
1999 self.pg_enable_capture(self.pg_interfaces)
2000 self.pg_start()
2001 capture = self.pg2.get_capture(len(pkts))
2002 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2003
Matus Fabiande886752016-12-07 03:38:19 -08002004 # in2out 1st interface
2005 pkts = self.create_stream_in(self.pg0, self.pg3)
2006 self.pg0.add_stream(pkts)
2007 self.pg_enable_capture(self.pg_interfaces)
2008 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002009 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002010 self.verify_capture_out(capture)
2011
2012 # out2in 1st interface
2013 pkts = self.create_stream_out(self.pg3)
2014 self.pg3.add_stream(pkts)
2015 self.pg_enable_capture(self.pg_interfaces)
2016 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002017 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002018 self.verify_capture_in(capture, self.pg0)
2019
2020 # in2out 2nd interface
2021 pkts = self.create_stream_in(self.pg1, self.pg3)
2022 self.pg1.add_stream(pkts)
2023 self.pg_enable_capture(self.pg_interfaces)
2024 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002025 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002026 self.verify_capture_out(capture)
2027
2028 # out2in 2nd interface
2029 pkts = self.create_stream_out(self.pg3)
2030 self.pg3.add_stream(pkts)
2031 self.pg_enable_capture(self.pg_interfaces)
2032 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002033 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002034 self.verify_capture_in(capture, self.pg1)
2035
Matus Fabiande886752016-12-07 03:38:19 -08002036 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002037 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002038
Matus Fabian675a69c2017-01-18 01:46:01 -08002039 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002040 self.nat44_add_address(self.nat_addr)
2041 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2042 is_inside=0)
2043 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2044 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2045 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2046 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2047 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002048
Matus Fabian2ba92e32017-08-21 07:05:03 -07002049 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002050 pkts = self.create_stream_in(self.pg4, self.pg5)
2051 self.pg4.add_stream(pkts)
2052 self.pg_enable_capture(self.pg_interfaces)
2053 self.pg_start()
2054 capture = self.pg5.get_capture(len(pkts))
2055 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2056
Matus Fabian2ba92e32017-08-21 07:05:03 -07002057 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002058 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2059 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2060 TCP(sport=1234, dport=5678))
2061 self.pg4.add_stream(p)
2062 self.pg_enable_capture(self.pg_interfaces)
2063 self.pg_start()
2064 capture = self.pg6.get_capture(1)
2065 p = capture[0]
2066 try:
2067 ip = p[IP]
2068 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002069 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002070 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2071 self.assertNotEqual(tcp.sport, 1234)
2072 self.assertEqual(tcp.dport, 5678)
2073 except:
2074 self.logger.error(ppp("Unexpected or invalid packet:", p))
2075 raise
Matus Fabiande886752016-12-07 03:38:19 -08002076
2077 # in2out 1st interface
2078 pkts = self.create_stream_in(self.pg4, self.pg3)
2079 self.pg4.add_stream(pkts)
2080 self.pg_enable_capture(self.pg_interfaces)
2081 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002082 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002083 self.verify_capture_out(capture)
2084
2085 # out2in 1st interface
2086 pkts = self.create_stream_out(self.pg3)
2087 self.pg3.add_stream(pkts)
2088 self.pg_enable_capture(self.pg_interfaces)
2089 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002090 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002091 self.verify_capture_in(capture, self.pg4)
2092
2093 # in2out 2nd interface
2094 pkts = self.create_stream_in(self.pg5, self.pg3)
2095 self.pg5.add_stream(pkts)
2096 self.pg_enable_capture(self.pg_interfaces)
2097 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002098 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002099 self.verify_capture_out(capture)
2100
2101 # out2in 2nd interface
2102 pkts = self.create_stream_out(self.pg3)
2103 self.pg3.add_stream(pkts)
2104 self.pg_enable_capture(self.pg_interfaces)
2105 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002106 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002107 self.verify_capture_in(capture, self.pg5)
2108
magalik23caa882017-02-08 23:25:45 -08002109 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002110 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002111 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002112 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002113 self.assertEqual(len(sessions), 3)
2114 for session in sessions:
2115 self.assertFalse(session.is_static)
2116 self.assertEqual(session.inside_ip_address[0:4],
2117 self.pg5.remote_ip4n)
2118 self.assertEqual(session.outside_ip_address,
2119 addresses[0].ip_address)
2120 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2121 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2122 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2123 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2124 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2125 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2126 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2127 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2128 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2129
Matus Fabiande886752016-12-07 03:38:19 -08002130 # in2out 3rd interface
2131 pkts = self.create_stream_in(self.pg6, self.pg3)
2132 self.pg6.add_stream(pkts)
2133 self.pg_enable_capture(self.pg_interfaces)
2134 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002135 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002136 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002137
2138 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002139 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002140 self.pg3.add_stream(pkts)
2141 self.pg_enable_capture(self.pg_interfaces)
2142 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002143 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002144 self.verify_capture_in(capture, self.pg6)
2145
magalik23caa882017-02-08 23:25:45 -08002146 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002147 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002148 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002149 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002150 self.assertEqual(len(addresses), 1)
2151 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002152 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2153 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002154 for session in sessions:
2155 self.assertEqual(user.ip_address, session.inside_ip_address)
2156 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2157 self.assertTrue(session.protocol in
2158 [IP_PROTOS.tcp, IP_PROTOS.udp,
2159 IP_PROTOS.icmp])
2160
2161 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002162 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002163 self.assertTrue(len(sessions) >= 4)
2164 for session in sessions:
2165 self.assertFalse(session.is_static)
2166 self.assertEqual(session.inside_ip_address[0:4],
2167 self.pg4.remote_ip4n)
2168 self.assertEqual(session.outside_ip_address,
2169 addresses[0].ip_address)
2170
2171 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002172 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002173 self.assertTrue(len(sessions) >= 3)
2174 for session in sessions:
2175 self.assertTrue(session.is_static)
2176 self.assertEqual(session.inside_ip_address[0:4],
2177 self.pg6.remote_ip4n)
2178 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2179 map(int, static_nat_ip.split('.')))
2180 self.assertTrue(session.inside_port in
2181 [self.tcp_port_in, self.udp_port_in,
2182 self.icmp_id_in])
2183
Matus Fabianf78a70d2016-12-12 04:30:39 -08002184 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002185 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002186
2187 host = self.pg0.remote_hosts[0]
2188 server = self.pg0.remote_hosts[1]
2189 host_in_port = 1234
2190 host_out_port = 0
2191 server_in_port = 5678
2192 server_out_port = 8765
2193
Matus Fabian2ba92e32017-08-21 07:05:03 -07002194 self.nat44_add_address(self.nat_addr)
2195 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2196 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2197 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002198 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002199 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2200 server_in_port, server_out_port,
2201 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002202
2203 # send packet from host to server
2204 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002205 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002206 TCP(sport=host_in_port, dport=server_out_port))
2207 self.pg0.add_stream(p)
2208 self.pg_enable_capture(self.pg_interfaces)
2209 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002210 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002211 p = capture[0]
2212 try:
2213 ip = p[IP]
2214 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002215 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002216 self.assertEqual(ip.dst, server.ip4)
2217 self.assertNotEqual(tcp.sport, host_in_port)
2218 self.assertEqual(tcp.dport, server_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002219 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002220 host_out_port = tcp.sport
2221 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002222 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002223 raise
2224
2225 # send reply from server to host
2226 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002227 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002228 TCP(sport=server_in_port, dport=host_out_port))
2229 self.pg0.add_stream(p)
2230 self.pg_enable_capture(self.pg_interfaces)
2231 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002232 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002233 p = capture[0]
2234 try:
2235 ip = p[IP]
2236 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002237 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002238 self.assertEqual(ip.dst, host.ip4)
2239 self.assertEqual(tcp.sport, server_out_port)
2240 self.assertEqual(tcp.dport, host_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002241 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002242 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002243 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002244 raise
2245
Matus Fabian6fa74c62017-06-05 05:55:48 -07002246 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002247 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002248
2249 server1_nat_ip = "10.0.0.10"
2250 server2_nat_ip = "10.0.0.11"
2251 host = self.pg0.remote_hosts[0]
2252 server1 = self.pg0.remote_hosts[1]
2253 server2 = self.pg0.remote_hosts[2]
2254 server_tcp_port = 22
2255 server_udp_port = 20
2256
Matus Fabian2ba92e32017-08-21 07:05:03 -07002257 self.nat44_add_address(self.nat_addr)
2258 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2259 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2260 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002261
2262 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002263 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2264 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002265
2266 # host to server1
2267 pkts = []
2268 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2269 IP(src=host.ip4, dst=server1_nat_ip) /
2270 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2271 pkts.append(p)
2272 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2273 IP(src=host.ip4, dst=server1_nat_ip) /
2274 UDP(sport=self.udp_port_in, dport=server_udp_port))
2275 pkts.append(p)
2276 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2277 IP(src=host.ip4, dst=server1_nat_ip) /
2278 ICMP(id=self.icmp_id_in, type='echo-request'))
2279 pkts.append(p)
2280 self.pg0.add_stream(pkts)
2281 self.pg_enable_capture(self.pg_interfaces)
2282 self.pg_start()
2283 capture = self.pg0.get_capture(len(pkts))
2284 for packet in capture:
2285 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002286 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002287 self.assertEqual(packet[IP].dst, server1.ip4)
2288 if packet.haslayer(TCP):
2289 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2290 self.assertEqual(packet[TCP].dport, server_tcp_port)
2291 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002292 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002293 elif packet.haslayer(UDP):
2294 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2295 self.assertEqual(packet[UDP].dport, server_udp_port)
2296 self.udp_port_out = packet[UDP].sport
2297 else:
2298 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2299 self.icmp_id_out = packet[ICMP].id
2300 except:
2301 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2302 raise
2303
2304 # server1 to host
2305 pkts = []
2306 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002307 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002308 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2309 pkts.append(p)
2310 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002311 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002312 UDP(sport=server_udp_port, dport=self.udp_port_out))
2313 pkts.append(p)
2314 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002315 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002316 ICMP(id=self.icmp_id_out, type='echo-reply'))
2317 pkts.append(p)
2318 self.pg0.add_stream(pkts)
2319 self.pg_enable_capture(self.pg_interfaces)
2320 self.pg_start()
2321 capture = self.pg0.get_capture(len(pkts))
2322 for packet in capture:
2323 try:
2324 self.assertEqual(packet[IP].src, server1_nat_ip)
2325 self.assertEqual(packet[IP].dst, host.ip4)
2326 if packet.haslayer(TCP):
2327 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2328 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002329 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002330 elif packet.haslayer(UDP):
2331 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2332 self.assertEqual(packet[UDP].sport, server_udp_port)
2333 else:
2334 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2335 except:
2336 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2337 raise
2338
2339 # server2 to server1
2340 pkts = []
2341 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2342 IP(src=server2.ip4, dst=server1_nat_ip) /
2343 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2344 pkts.append(p)
2345 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2346 IP(src=server2.ip4, dst=server1_nat_ip) /
2347 UDP(sport=self.udp_port_in, dport=server_udp_port))
2348 pkts.append(p)
2349 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2350 IP(src=server2.ip4, dst=server1_nat_ip) /
2351 ICMP(id=self.icmp_id_in, type='echo-request'))
2352 pkts.append(p)
2353 self.pg0.add_stream(pkts)
2354 self.pg_enable_capture(self.pg_interfaces)
2355 self.pg_start()
2356 capture = self.pg0.get_capture(len(pkts))
2357 for packet in capture:
2358 try:
2359 self.assertEqual(packet[IP].src, server2_nat_ip)
2360 self.assertEqual(packet[IP].dst, server1.ip4)
2361 if packet.haslayer(TCP):
2362 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2363 self.assertEqual(packet[TCP].dport, server_tcp_port)
2364 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002365 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002366 elif packet.haslayer(UDP):
2367 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2368 self.assertEqual(packet[UDP].dport, server_udp_port)
2369 self.udp_port_out = packet[UDP].sport
2370 else:
2371 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2372 self.icmp_id_out = packet[ICMP].id
2373 except:
2374 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2375 raise
2376
2377 # server1 to server2
2378 pkts = []
2379 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2380 IP(src=server1.ip4, dst=server2_nat_ip) /
2381 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2382 pkts.append(p)
2383 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2384 IP(src=server1.ip4, dst=server2_nat_ip) /
2385 UDP(sport=server_udp_port, dport=self.udp_port_out))
2386 pkts.append(p)
2387 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2388 IP(src=server1.ip4, dst=server2_nat_ip) /
2389 ICMP(id=self.icmp_id_out, type='echo-reply'))
2390 pkts.append(p)
2391 self.pg0.add_stream(pkts)
2392 self.pg_enable_capture(self.pg_interfaces)
2393 self.pg_start()
2394 capture = self.pg0.get_capture(len(pkts))
2395 for packet in capture:
2396 try:
2397 self.assertEqual(packet[IP].src, server1_nat_ip)
2398 self.assertEqual(packet[IP].dst, server2.ip4)
2399 if packet.haslayer(TCP):
2400 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2401 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002402 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002403 elif packet.haslayer(UDP):
2404 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2405 self.assertEqual(packet[UDP].sport, server_udp_port)
2406 else:
2407 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2408 except:
2409 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2410 raise
2411
Matus Fabian9902fcd2016-12-21 23:58:46 -08002412 def test_max_translations_per_user(self):
2413 """ MAX translations per user - recycle the least recently used """
2414
Matus Fabian2ba92e32017-08-21 07:05:03 -07002415 self.nat44_add_address(self.nat_addr)
2416 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2417 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2418 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002419
2420 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002421 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002422
2423 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002424 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002425 pkts = []
2426 for port in range(0, pkts_num):
2427 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2428 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2429 TCP(sport=1025 + port))
2430 pkts.append(p)
2431 self.pg0.add_stream(pkts)
2432 self.pg_enable_capture(self.pg_interfaces)
2433 self.pg_start()
2434
2435 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002436 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002437
Matus Fabian8bf68e82017-01-12 04:24:35 -08002438 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002439 """ Acquire NAT44 addresses from interface """
2440 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002441
2442 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002443 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002444 self.assertEqual(0, len(adresses))
2445
2446 # configure interface address and check NAT address pool
2447 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002448 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002449 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002450 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002451
2452 # remove interface address and check NAT address pool
2453 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002454 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002455 self.assertEqual(0, len(adresses))
2456
Matus Fabian36532bd2017-01-23 23:42:28 -08002457 def test_interface_addr_static_mapping(self):
2458 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002459 tag = "testTAG"
2460
Matus Fabian2ba92e32017-08-21 07:05:03 -07002461 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2462 self.nat44_add_static_mapping(
2463 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002464 external_sw_if_index=self.pg7.sw_if_index,
2465 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002466
Matus Fabiane22e5462017-02-14 23:33:43 -08002467 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002468 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002469 self.assertEqual(1, len(static_mappings))
2470 self.assertEqual(self.pg7.sw_if_index,
2471 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002472 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002473
2474 # configure interface address and check static mappings
2475 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002476 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002477 self.assertEqual(2, len(static_mappings))
2478 resolved = False
2479 for sm in static_mappings:
2480 if sm.external_sw_if_index == 0xFFFFFFFF:
2481 self.assertEqual(sm.external_ip_address[0:4],
2482 self.pg7.local_ip4n)
2483 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2484 resolved = True
2485 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002486
2487 # remove interface address and check static mappings
2488 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002489 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002490 self.assertEqual(1, len(static_mappings))
2491 self.assertEqual(self.pg7.sw_if_index,
2492 static_mappings[0].external_sw_if_index)
2493 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2494
2495 # configure interface address again and check static mappings
2496 self.pg7.config_ip4()
2497 static_mappings = self.vapi.nat44_static_mapping_dump()
2498 self.assertEqual(2, len(static_mappings))
2499 resolved = False
2500 for sm in static_mappings:
2501 if sm.external_sw_if_index == 0xFFFFFFFF:
2502 self.assertEqual(sm.external_ip_address[0:4],
2503 self.pg7.local_ip4n)
2504 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2505 resolved = True
2506 self.assertTrue(resolved)
2507
2508 # remove static mapping
2509 self.nat44_add_static_mapping(
2510 '1.2.3.4',
2511 external_sw_if_index=self.pg7.sw_if_index,
2512 tag=tag,
2513 is_add=0)
2514 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002515 self.assertEqual(0, len(static_mappings))
2516
Matus Fabianab7a8052017-11-28 04:29:41 -08002517 def test_interface_addr_identity_nat(self):
2518 """ Identity NAT with addresses from interface """
2519
2520 port = 53053
2521 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2522 self.vapi.nat44_add_del_identity_mapping(
2523 sw_if_index=self.pg7.sw_if_index,
2524 port=port,
2525 protocol=IP_PROTOS.tcp,
2526 addr_only=0)
2527
2528 # identity mappings with external interface
2529 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2530 self.assertEqual(1, len(identity_mappings))
2531 self.assertEqual(self.pg7.sw_if_index,
2532 identity_mappings[0].sw_if_index)
2533
2534 # configure interface address and check identity mappings
2535 self.pg7.config_ip4()
2536 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002537 resolved = False
2538 self.assertEqual(2, len(identity_mappings))
2539 for sm in identity_mappings:
2540 if sm.sw_if_index == 0xFFFFFFFF:
2541 self.assertEqual(identity_mappings[0].ip_address,
2542 self.pg7.local_ip4n)
2543 self.assertEqual(port, identity_mappings[0].port)
2544 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2545 resolved = True
2546 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002547
2548 # remove interface address and check identity mappings
2549 self.pg7.unconfig_ip4()
2550 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002551 self.assertEqual(1, len(identity_mappings))
2552 self.assertEqual(self.pg7.sw_if_index,
2553 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002554
Matus Fabianeea28d72017-01-13 04:15:54 -08002555 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002556 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002557 self.ipfix_domain_id = 10
2558 self.ipfix_src_port = 20202
2559 colector_port = 30303
2560 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002561 self.nat44_add_address(self.nat_addr)
2562 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2563 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2564 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002565 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2566 src_address=self.pg3.local_ip4n,
2567 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002568 template_interval=10,
2569 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002570 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2571 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002572
2573 pkts = self.create_stream_in(self.pg0, self.pg1)
2574 self.pg0.add_stream(pkts)
2575 self.pg_enable_capture(self.pg_interfaces)
2576 self.pg_start()
2577 capture = self.pg1.get_capture(len(pkts))
2578 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002579 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002580 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002581 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002582 ipfix = IPFIXDecoder()
2583 # first load template
2584 for p in capture:
2585 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002586 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2587 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2588 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2589 self.assertEqual(p[UDP].dport, colector_port)
2590 self.assertEqual(p[IPFIX].observationDomainID,
2591 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002592 if p.haslayer(Template):
2593 ipfix.add_template(p.getlayer(Template))
2594 # verify events in data set
2595 for p in capture:
2596 if p.haslayer(Data):
2597 data = ipfix.decode_data_set(p.getlayer(Set))
2598 self.verify_ipfix_nat44_ses(data)
2599
2600 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002601 """ IPFIX logging NAT addresses exhausted """
2602 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2603 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2604 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002605 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2606 src_address=self.pg3.local_ip4n,
2607 path_mtu=512,
2608 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002609 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2610 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002611
2612 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2613 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2614 TCP(sport=3025))
2615 self.pg0.add_stream(p)
2616 self.pg_enable_capture(self.pg_interfaces)
2617 self.pg_start()
2618 capture = self.pg1.get_capture(0)
2619 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002620 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002621 ipfix = IPFIXDecoder()
2622 # first load template
2623 for p in capture:
2624 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002625 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2626 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2627 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2628 self.assertEqual(p[UDP].dport, 4739)
2629 self.assertEqual(p[IPFIX].observationDomainID,
2630 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002631 if p.haslayer(Template):
2632 ipfix.add_template(p.getlayer(Template))
2633 # verify events in data set
2634 for p in capture:
2635 if p.haslayer(Data):
2636 data = ipfix.decode_data_set(p.getlayer(Set))
2637 self.verify_ipfix_addr_exhausted(data)
2638
Matus Fabiana431ad12018-01-04 04:03:14 -08002639 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2640 def test_ipfix_max_sessions(self):
2641 """ IPFIX logging maximum session entries exceeded """
2642 self.nat44_add_address(self.nat_addr)
2643 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2644 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2645 is_inside=0)
2646
2647 nat44_config = self.vapi.nat_show_config()
2648 max_sessions = 10 * nat44_config.translation_buckets
2649
2650 pkts = []
2651 for i in range(0, max_sessions):
2652 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2653 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2654 IP(src=src, dst=self.pg1.remote_ip4) /
2655 TCP(sport=1025))
2656 pkts.append(p)
2657 self.pg0.add_stream(pkts)
2658 self.pg_enable_capture(self.pg_interfaces)
2659 self.pg_start()
2660
2661 self.pg1.get_capture(max_sessions)
2662 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2663 src_address=self.pg3.local_ip4n,
2664 path_mtu=512,
2665 template_interval=10)
2666 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2667 src_port=self.ipfix_src_port)
2668
2669 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2670 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2671 TCP(sport=1025))
2672 self.pg0.add_stream(p)
2673 self.pg_enable_capture(self.pg_interfaces)
2674 self.pg_start()
2675 self.pg1.get_capture(0)
2676 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2677 capture = self.pg3.get_capture(9)
2678 ipfix = IPFIXDecoder()
2679 # first load template
2680 for p in capture:
2681 self.assertTrue(p.haslayer(IPFIX))
2682 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2683 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2684 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2685 self.assertEqual(p[UDP].dport, 4739)
2686 self.assertEqual(p[IPFIX].observationDomainID,
2687 self.ipfix_domain_id)
2688 if p.haslayer(Template):
2689 ipfix.add_template(p.getlayer(Template))
2690 # verify events in data set
2691 for p in capture:
2692 if p.haslayer(Data):
2693 data = ipfix.decode_data_set(p.getlayer(Set))
2694 self.verify_ipfix_max_sessions(data, max_sessions)
2695
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002696 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002697 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002698 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002699 self.nat44_add_address(self.nat_addr)
2700 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2701 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2702 is_inside=0)
2703 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002704
Matus Fabian2ba92e32017-08-21 07:05:03 -07002705 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002706 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002707 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002708 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2709 self.pg1.add_stream(p)
2710 self.pg_enable_capture(self.pg_interfaces)
2711 self.pg_start()
2712 capture = self.pg1.get_capture(1)
2713 self.assertTrue(capture[0].haslayer(ARP))
2714 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2715
2716 # 1:1 NAT address
2717 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2718 ARP(op=ARP.who_has, pdst=static_addr,
2719 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2720 self.pg1.add_stream(p)
2721 self.pg_enable_capture(self.pg_interfaces)
2722 self.pg_start()
2723 capture = self.pg1.get_capture(1)
2724 self.assertTrue(capture[0].haslayer(ARP))
2725 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2726
Matus Fabian2ba92e32017-08-21 07:05:03 -07002727 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002728 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002729 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002730 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2731 self.pg2.add_stream(p)
2732 self.pg_enable_capture(self.pg_interfaces)
2733 self.pg_start()
2734 capture = self.pg1.get_capture(0)
2735
2736 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002737 self.nat44_add_address(self.nat_addr, is_add=0)
2738 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2739 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002740
2741 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002742 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002743 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2744 self.pg1.add_stream(p)
2745 self.pg_enable_capture(self.pg_interfaces)
2746 self.pg_start()
2747 capture = self.pg1.get_capture(0)
2748
2749 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2750 ARP(op=ARP.who_has, pdst=static_addr,
2751 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2752 self.pg1.add_stream(p)
2753 self.pg_enable_capture(self.pg_interfaces)
2754 self.pg_start()
2755 capture = self.pg1.get_capture(0)
2756
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002757 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002758 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002759
2760 vrf_id1 = 1
2761 vrf_id2 = 2
2762 nat_ip1 = "10.0.0.10"
2763 nat_ip2 = "10.0.0.11"
2764
2765 self.pg0.unconfig_ip4()
2766 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002767 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2768 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002769 self.pg0.set_table_ip4(vrf_id1)
2770 self.pg1.set_table_ip4(vrf_id2)
2771 self.pg0.config_ip4()
2772 self.pg1.config_ip4()
2773
Matus Fabian2ba92e32017-08-21 07:05:03 -07002774 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2775 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2776 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2777 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2778 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2779 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002780
2781 # first VRF
2782 pkts = self.create_stream_in(self.pg0, self.pg2)
2783 self.pg0.add_stream(pkts)
2784 self.pg_enable_capture(self.pg_interfaces)
2785 self.pg_start()
2786 capture = self.pg2.get_capture(len(pkts))
2787 self.verify_capture_out(capture, nat_ip1)
2788
2789 # second VRF
2790 pkts = self.create_stream_in(self.pg1, self.pg2)
2791 self.pg1.add_stream(pkts)
2792 self.pg_enable_capture(self.pg_interfaces)
2793 self.pg_start()
2794 capture = self.pg2.get_capture(len(pkts))
2795 self.verify_capture_out(capture, nat_ip2)
2796
Neale Ranns15002542017-09-10 04:39:11 -07002797 self.pg0.unconfig_ip4()
2798 self.pg1.unconfig_ip4()
2799 self.pg0.set_table_ip4(0)
2800 self.pg1.set_table_ip4(0)
2801 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2802 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2803
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002804 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002805 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002806
2807 nat_ip1 = "10.0.0.10"
2808 nat_ip2 = "10.0.0.11"
2809
Matus Fabian2ba92e32017-08-21 07:05:03 -07002810 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002811 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002812 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2813 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2814 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2815 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002816
2817 # first VRF
2818 pkts = self.create_stream_in(self.pg0, self.pg2)
2819 self.pg0.add_stream(pkts)
2820 self.pg_enable_capture(self.pg_interfaces)
2821 self.pg_start()
2822 capture = self.pg2.get_capture(len(pkts))
2823 self.verify_capture_out(capture, nat_ip1)
2824
2825 # second VRF
2826 pkts = self.create_stream_in(self.pg1, self.pg2)
2827 self.pg1.add_stream(pkts)
2828 self.pg_enable_capture(self.pg_interfaces)
2829 self.pg_start()
2830 capture = self.pg2.get_capture(len(pkts))
2831 self.verify_capture_out(capture, nat_ip1)
2832
Martin Gálik406eb1d2017-05-04 04:35:04 -07002833 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002834 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002835
2836 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002837 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002838 self.pg7.remote_ip4n,
2839 is_static=1)
2840 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002841 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002842 self.pg8.remote_ip4n,
2843 is_static=1)
2844
2845 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2846 dst_address_length=32,
2847 next_hop_address=self.pg7.remote_ip4n,
2848 next_hop_sw_if_index=self.pg7.sw_if_index)
2849 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2850 dst_address_length=32,
2851 next_hop_address=self.pg8.remote_ip4n,
2852 next_hop_sw_if_index=self.pg8.sw_if_index)
2853
Matus Fabian2ba92e32017-08-21 07:05:03 -07002854 self.nat44_add_address(self.nat_addr)
2855 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2856 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2857 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002858
2859 # in2out
2860 pkts = self.create_stream_in(self.pg7, self.pg8)
2861 self.pg7.add_stream(pkts)
2862 self.pg_enable_capture(self.pg_interfaces)
2863 self.pg_start()
2864 capture = self.pg8.get_capture(len(pkts))
2865 self.verify_capture_out(capture)
2866
2867 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002868 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002869 self.pg8.add_stream(pkts)
2870 self.pg_enable_capture(self.pg_interfaces)
2871 self.pg_start()
2872 capture = self.pg7.get_capture(len(pkts))
2873 self.verify_capture_in(capture, self.pg7)
2874
2875 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002876 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002877
2878 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002879 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002880 self.pg7.remote_ip4n,
2881 is_static=1)
2882 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002883 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002884 self.pg8.remote_ip4n,
2885 is_static=1)
2886
2887 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2888 dst_address_length=32,
2889 next_hop_address=self.pg7.remote_ip4n,
2890 next_hop_sw_if_index=self.pg7.sw_if_index)
2891 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2892 dst_address_length=32,
2893 next_hop_address=self.pg8.remote_ip4n,
2894 next_hop_sw_if_index=self.pg8.sw_if_index)
2895
Matus Fabian2ba92e32017-08-21 07:05:03 -07002896 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2897 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2898 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2899 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002900
2901 # out2in
2902 pkts = self.create_stream_out(self.pg8)
2903 self.pg8.add_stream(pkts)
2904 self.pg_enable_capture(self.pg_interfaces)
2905 self.pg_start()
2906 capture = self.pg7.get_capture(len(pkts))
2907 self.verify_capture_in(capture, self.pg7)
2908
2909 # in2out
2910 pkts = self.create_stream_in(self.pg7, self.pg8)
2911 self.pg7.add_stream(pkts)
2912 self.pg_enable_capture(self.pg_interfaces)
2913 self.pg_start()
2914 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002915 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002916
2917 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002918 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002919
2920 self.tcp_port_out = 30606
2921 self.udp_port_out = 30607
2922 self.icmp_id_out = 30608
2923
2924 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002925 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002926 self.pg7.remote_ip4n,
2927 is_static=1)
2928 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002929 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002930 self.pg8.remote_ip4n,
2931 is_static=1)
2932
2933 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2934 dst_address_length=32,
2935 next_hop_address=self.pg7.remote_ip4n,
2936 next_hop_sw_if_index=self.pg7.sw_if_index)
2937 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2938 dst_address_length=32,
2939 next_hop_address=self.pg8.remote_ip4n,
2940 next_hop_sw_if_index=self.pg8.sw_if_index)
2941
Matus Fabian2ba92e32017-08-21 07:05:03 -07002942 self.nat44_add_address(self.nat_addr)
2943 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2944 self.tcp_port_in, self.tcp_port_out,
2945 proto=IP_PROTOS.tcp)
2946 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2947 self.udp_port_in, self.udp_port_out,
2948 proto=IP_PROTOS.udp)
2949 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2950 self.icmp_id_in, self.icmp_id_out,
2951 proto=IP_PROTOS.icmp)
2952 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2953 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2954 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002955
2956 # out2in
2957 pkts = self.create_stream_out(self.pg8)
2958 self.pg8.add_stream(pkts)
2959 self.pg_enable_capture(self.pg_interfaces)
2960 self.pg_start()
2961 capture = self.pg7.get_capture(len(pkts))
2962 self.verify_capture_in(capture, self.pg7)
2963
2964 # in2out
2965 pkts = self.create_stream_in(self.pg7, self.pg8)
2966 self.pg7.add_stream(pkts)
2967 self.pg_enable_capture(self.pg_interfaces)
2968 self.pg_start()
2969 capture = self.pg8.get_capture(len(pkts))
2970 self.verify_capture_out(capture)
2971
Matus Fabian328dbc82017-06-19 04:28:04 -07002972 def test_static_unknown_proto(self):
2973 """ 1:1 NAT translate packet with unknown protocol """
2974 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002975 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2976 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2977 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2978 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002979
2980 # in2out
2981 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2982 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2983 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002984 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002985 TCP(sport=1234, dport=1234))
2986 self.pg0.add_stream(p)
2987 self.pg_enable_capture(self.pg_interfaces)
2988 self.pg_start()
2989 p = self.pg1.get_capture(1)
2990 packet = p[0]
2991 try:
2992 self.assertEqual(packet[IP].src, nat_ip)
2993 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2994 self.assertTrue(packet.haslayer(GRE))
2995 self.check_ip_checksum(packet)
2996 except:
2997 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2998 raise
2999
3000 # out2in
3001 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3002 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3003 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003004 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003005 TCP(sport=1234, dport=1234))
3006 self.pg1.add_stream(p)
3007 self.pg_enable_capture(self.pg_interfaces)
3008 self.pg_start()
3009 p = self.pg0.get_capture(1)
3010 packet = p[0]
3011 try:
3012 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3013 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3014 self.assertTrue(packet.haslayer(GRE))
3015 self.check_ip_checksum(packet)
3016 except:
3017 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3018 raise
3019
Matus Fabian7968e6c2017-07-06 05:37:49 -07003020 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003021 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3022
3023 host = self.pg0.remote_hosts[0]
3024 server = self.pg0.remote_hosts[1]
3025
3026 host_nat_ip = "10.0.0.10"
3027 server_nat_ip = "10.0.0.11"
3028
Matus Fabian2ba92e32017-08-21 07:05:03 -07003029 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3030 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3031 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3032 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3033 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003034
3035 # host to server
3036 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3037 IP(src=host.ip4, dst=server_nat_ip) /
3038 GRE() /
3039 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3040 TCP(sport=1234, dport=1234))
3041 self.pg0.add_stream(p)
3042 self.pg_enable_capture(self.pg_interfaces)
3043 self.pg_start()
3044 p = self.pg0.get_capture(1)
3045 packet = p[0]
3046 try:
3047 self.assertEqual(packet[IP].src, host_nat_ip)
3048 self.assertEqual(packet[IP].dst, server.ip4)
3049 self.assertTrue(packet.haslayer(GRE))
3050 self.check_ip_checksum(packet)
3051 except:
3052 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3053 raise
3054
3055 # server to host
3056 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3057 IP(src=server.ip4, dst=host_nat_ip) /
3058 GRE() /
3059 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3060 TCP(sport=1234, dport=1234))
3061 self.pg0.add_stream(p)
3062 self.pg_enable_capture(self.pg_interfaces)
3063 self.pg_start()
3064 p = self.pg0.get_capture(1)
3065 packet = p[0]
3066 try:
3067 self.assertEqual(packet[IP].src, server_nat_ip)
3068 self.assertEqual(packet[IP].dst, host.ip4)
3069 self.assertTrue(packet.haslayer(GRE))
3070 self.check_ip_checksum(packet)
3071 except:
3072 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3073 raise
3074
Matus Fabian7968e6c2017-07-06 05:37:49 -07003075 def test_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003076 """ NAT44 translate packet with unknown protocol """
3077 self.nat44_add_address(self.nat_addr)
3078 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3079 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3080 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003081
3082 # in2out
3083 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3084 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3085 TCP(sport=self.tcp_port_in, dport=20))
3086 self.pg0.add_stream(p)
3087 self.pg_enable_capture(self.pg_interfaces)
3088 self.pg_start()
3089 p = self.pg1.get_capture(1)
3090
3091 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3092 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3093 GRE() /
3094 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3095 TCP(sport=1234, dport=1234))
3096 self.pg0.add_stream(p)
3097 self.pg_enable_capture(self.pg_interfaces)
3098 self.pg_start()
3099 p = self.pg1.get_capture(1)
3100 packet = p[0]
3101 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003102 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003103 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3104 self.assertTrue(packet.haslayer(GRE))
3105 self.check_ip_checksum(packet)
3106 except:
3107 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3108 raise
3109
3110 # out2in
3111 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003112 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003113 GRE() /
3114 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3115 TCP(sport=1234, dport=1234))
3116 self.pg1.add_stream(p)
3117 self.pg_enable_capture(self.pg_interfaces)
3118 self.pg_start()
3119 p = self.pg0.get_capture(1)
3120 packet = p[0]
3121 try:
3122 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3123 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3124 self.assertTrue(packet.haslayer(GRE))
3125 self.check_ip_checksum(packet)
3126 except:
3127 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3128 raise
3129
3130 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003131 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003132 host = self.pg0.remote_hosts[0]
3133 server = self.pg0.remote_hosts[1]
3134 host_in_port = 1234
3135 host_out_port = 0
3136 server_in_port = 5678
3137 server_out_port = 8765
3138 server_nat_ip = "10.0.0.11"
3139
Matus Fabian2ba92e32017-08-21 07:05:03 -07003140 self.nat44_add_address(self.nat_addr)
3141 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3142 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3143 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003144
3145 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003146 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003147
3148 # host to server
3149 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3150 IP(src=host.ip4, dst=server_nat_ip) /
3151 TCP(sport=host_in_port, dport=server_out_port))
3152 self.pg0.add_stream(p)
3153 self.pg_enable_capture(self.pg_interfaces)
3154 self.pg_start()
3155 capture = self.pg0.get_capture(1)
3156
3157 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3158 IP(src=host.ip4, dst=server_nat_ip) /
3159 GRE() /
3160 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3161 TCP(sport=1234, dport=1234))
3162 self.pg0.add_stream(p)
3163 self.pg_enable_capture(self.pg_interfaces)
3164 self.pg_start()
3165 p = self.pg0.get_capture(1)
3166 packet = p[0]
3167 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003168 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003169 self.assertEqual(packet[IP].dst, server.ip4)
3170 self.assertTrue(packet.haslayer(GRE))
3171 self.check_ip_checksum(packet)
3172 except:
3173 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3174 raise
3175
3176 # server to host
3177 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003178 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003179 GRE() /
3180 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3181 TCP(sport=1234, dport=1234))
3182 self.pg0.add_stream(p)
3183 self.pg_enable_capture(self.pg_interfaces)
3184 self.pg_start()
3185 p = self.pg0.get_capture(1)
3186 packet = p[0]
3187 try:
3188 self.assertEqual(packet[IP].src, server_nat_ip)
3189 self.assertEqual(packet[IP].dst, host.ip4)
3190 self.assertTrue(packet.haslayer(GRE))
3191 self.check_ip_checksum(packet)
3192 except:
3193 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3194 raise
3195
Matus Fabian93d84c92017-07-19 08:06:01 -07003196 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003197 """ NAT44 interface output feature (in2out postrouting) """
3198 self.nat44_add_address(self.nat_addr)
3199 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003200 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3201 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003202 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003203
3204 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003205 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003206 self.pg0.add_stream(pkts)
3207 self.pg_enable_capture(self.pg_interfaces)
3208 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003209 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003210 self.verify_capture_out(capture)
3211
3212 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003213 pkts = self.create_stream_out(self.pg3)
3214 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003215 self.pg_enable_capture(self.pg_interfaces)
3216 self.pg_start()
3217 capture = self.pg0.get_capture(len(pkts))
3218 self.verify_capture_in(capture, self.pg0)
3219
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003220 # from non-NAT interface to NAT inside interface
3221 pkts = self.create_stream_in(self.pg2, self.pg0)
3222 self.pg2.add_stream(pkts)
3223 self.pg_enable_capture(self.pg_interfaces)
3224 self.pg_start()
3225 capture = self.pg0.get_capture(len(pkts))
3226 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3227
Matus Fabian93d84c92017-07-19 08:06:01 -07003228 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003229 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003230 nat_ip_vrf10 = "10.0.0.10"
3231 nat_ip_vrf20 = "10.0.0.20"
3232
3233 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3234 dst_address_length=32,
3235 next_hop_address=self.pg3.remote_ip4n,
3236 next_hop_sw_if_index=self.pg3.sw_if_index,
3237 table_id=10)
3238 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3239 dst_address_length=32,
3240 next_hop_address=self.pg3.remote_ip4n,
3241 next_hop_sw_if_index=self.pg3.sw_if_index,
3242 table_id=20)
3243
Matus Fabian2ba92e32017-08-21 07:05:03 -07003244 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3245 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3246 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3247 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3248 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3249 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003250
3251 # in2out VRF 10
3252 pkts = self.create_stream_in(self.pg4, self.pg3)
3253 self.pg4.add_stream(pkts)
3254 self.pg_enable_capture(self.pg_interfaces)
3255 self.pg_start()
3256 capture = self.pg3.get_capture(len(pkts))
3257 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3258
3259 # out2in VRF 10
3260 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3261 self.pg3.add_stream(pkts)
3262 self.pg_enable_capture(self.pg_interfaces)
3263 self.pg_start()
3264 capture = self.pg4.get_capture(len(pkts))
3265 self.verify_capture_in(capture, self.pg4)
3266
3267 # in2out VRF 20
3268 pkts = self.create_stream_in(self.pg6, self.pg3)
3269 self.pg6.add_stream(pkts)
3270 self.pg_enable_capture(self.pg_interfaces)
3271 self.pg_start()
3272 capture = self.pg3.get_capture(len(pkts))
3273 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3274
3275 # out2in VRF 20
3276 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3277 self.pg3.add_stream(pkts)
3278 self.pg_enable_capture(self.pg_interfaces)
3279 self.pg_start()
3280 capture = self.pg6.get_capture(len(pkts))
3281 self.verify_capture_in(capture, self.pg6)
3282
Matus Fabian161c59c2017-07-21 03:46:03 -07003283 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003284 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003285 host = self.pg0.remote_hosts[0]
3286 server = self.pg0.remote_hosts[1]
3287 host_in_port = 1234
3288 host_out_port = 0
3289 server_in_port = 5678
3290 server_out_port = 8765
3291
Matus Fabian2ba92e32017-08-21 07:05:03 -07003292 self.nat44_add_address(self.nat_addr)
3293 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3294 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3295 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003296
3297 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003298 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3299 server_in_port, server_out_port,
3300 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003301
3302 # send packet from host to server
3303 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003304 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003305 TCP(sport=host_in_port, dport=server_out_port))
3306 self.pg0.add_stream(p)
3307 self.pg_enable_capture(self.pg_interfaces)
3308 self.pg_start()
3309 capture = self.pg0.get_capture(1)
3310 p = capture[0]
3311 try:
3312 ip = p[IP]
3313 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003314 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003315 self.assertEqual(ip.dst, server.ip4)
3316 self.assertNotEqual(tcp.sport, host_in_port)
3317 self.assertEqual(tcp.dport, server_in_port)
3318 self.check_tcp_checksum(p)
3319 host_out_port = tcp.sport
3320 except:
3321 self.logger.error(ppp("Unexpected or invalid packet:", p))
3322 raise
3323
3324 # send reply from server to host
3325 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003326 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003327 TCP(sport=server_in_port, dport=host_out_port))
3328 self.pg0.add_stream(p)
3329 self.pg_enable_capture(self.pg_interfaces)
3330 self.pg_start()
3331 capture = self.pg0.get_capture(1)
3332 p = capture[0]
3333 try:
3334 ip = p[IP]
3335 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003336 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003337 self.assertEqual(ip.dst, host.ip4)
3338 self.assertEqual(tcp.sport, server_out_port)
3339 self.assertEqual(tcp.dport, host_in_port)
3340 self.check_tcp_checksum(p)
3341 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003342 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003343 raise
3344
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003345 def test_output_feature_and_service(self):
3346 """ NAT44 interface output feature and services """
3347 external_addr = '1.2.3.4'
3348 external_port = 80
3349 local_port = 8080
3350
3351 self.vapi.nat44_forwarding_enable_disable(1)
3352 self.nat44_add_address(self.nat_addr)
Matus Fabiana15cd022018-04-24 05:23:56 -07003353 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003354 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3355 local_port, external_port,
3356 proto=IP_PROTOS.tcp, out2in_only=1)
3357 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
Matus Fabiana15cd022018-04-24 05:23:56 -07003358 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3359 is_inside=0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003360 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3361 is_inside=0)
3362
3363 # from client to service
3364 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3365 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3366 TCP(sport=12345, dport=external_port))
3367 self.pg1.add_stream(p)
3368 self.pg_enable_capture(self.pg_interfaces)
3369 self.pg_start()
3370 capture = self.pg0.get_capture(1)
3371 p = capture[0]
3372 server = None
3373 try:
3374 ip = p[IP]
3375 tcp = p[TCP]
3376 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3377 self.assertEqual(tcp.dport, local_port)
3378 self.check_tcp_checksum(p)
3379 self.check_ip_checksum(p)
3380 except:
3381 self.logger.error(ppp("Unexpected or invalid packet:", p))
3382 raise
3383
3384 # from service back to client
3385 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3386 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3387 TCP(sport=local_port, dport=12345))
3388 self.pg0.add_stream(p)
3389 self.pg_enable_capture(self.pg_interfaces)
3390 self.pg_start()
3391 capture = self.pg1.get_capture(1)
3392 p = capture[0]
3393 try:
3394 ip = p[IP]
3395 tcp = p[TCP]
3396 self.assertEqual(ip.src, external_addr)
3397 self.assertEqual(tcp.sport, external_port)
3398 self.check_tcp_checksum(p)
3399 self.check_ip_checksum(p)
3400 except:
3401 self.logger.error(ppp("Unexpected or invalid packet:", p))
3402 raise
3403
3404 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003405 pkts = self.create_stream_in(self.pg0, self.pg1)
3406 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003407 self.pg_enable_capture(self.pg_interfaces)
3408 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003409 capture = self.pg1.get_capture(len(pkts))
3410 self.verify_capture_out(capture)
3411 pkts = self.create_stream_in(self.pg0, self.pg1)
3412 self.pg0.add_stream(pkts)
3413 self.pg_enable_capture(self.pg_interfaces)
3414 self.pg_start()
3415 capture = self.pg1.get_capture(len(pkts))
3416 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003417
3418 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003419 pkts = self.create_stream_out(self.pg1)
3420 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003421 self.pg_enable_capture(self.pg_interfaces)
3422 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003423 capture = self.pg0.get_capture(len(pkts))
3424 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003425
Matus Fabian204591d2018-03-01 04:48:33 -08003426 def test_output_feature_and_service2(self):
3427 """ NAT44 interface output feature and service host direct access """
3428 self.vapi.nat44_forwarding_enable_disable(1)
3429 self.nat44_add_address(self.nat_addr)
3430 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3431 is_inside=0)
3432
3433 # session initiaded from service host - translate
3434 pkts = self.create_stream_in(self.pg0, self.pg1)
3435 self.pg0.add_stream(pkts)
3436 self.pg_enable_capture(self.pg_interfaces)
3437 self.pg_start()
3438 capture = self.pg1.get_capture(len(pkts))
3439 self.verify_capture_out(capture)
3440
3441 pkts = self.create_stream_out(self.pg1)
3442 self.pg1.add_stream(pkts)
3443 self.pg_enable_capture(self.pg_interfaces)
3444 self.pg_start()
3445 capture = self.pg0.get_capture(len(pkts))
3446 self.verify_capture_in(capture, self.pg0)
3447
3448 tcp_port_out = self.tcp_port_out
3449 udp_port_out = self.udp_port_out
3450 icmp_id_out = self.icmp_id_out
3451
3452 # session initiaded from remote host - do not translate
3453 pkts = self.create_stream_out(self.pg1,
3454 self.pg0.remote_ip4,
3455 use_inside_ports=True)
3456 self.pg1.add_stream(pkts)
3457 self.pg_enable_capture(self.pg_interfaces)
3458 self.pg_start()
3459 capture = self.pg0.get_capture(len(pkts))
3460 self.verify_capture_in(capture, self.pg0)
3461
3462 pkts = self.create_stream_in(self.pg0, self.pg1)
3463 self.pg0.add_stream(pkts)
3464 self.pg_enable_capture(self.pg_interfaces)
3465 self.pg_start()
3466 capture = self.pg1.get_capture(len(pkts))
3467 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3468 same_port=True)
3469
Matus Fabian4d023c82018-03-22 05:50:47 -07003470 def test_output_feature_and_service3(self):
3471 """ NAT44 interface output feature and DST NAT """
3472 external_addr = '1.2.3.4'
3473 external_port = 80
3474 local_port = 8080
3475
3476 self.vapi.nat44_forwarding_enable_disable(1)
3477 self.nat44_add_address(self.nat_addr)
3478 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3479 local_port, external_port,
3480 proto=IP_PROTOS.tcp, out2in_only=1)
3481 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3482 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3483 is_inside=0)
3484 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3485 is_inside=0)
3486
3487 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3488 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3489 TCP(sport=12345, dport=external_port))
3490 self.pg0.add_stream(p)
3491 self.pg_enable_capture(self.pg_interfaces)
3492 self.pg_start()
3493 capture = self.pg1.get_capture(1)
3494 p = capture[0]
3495 try:
3496 ip = p[IP]
3497 tcp = p[TCP]
3498 self.assertEqual(ip.src, self.pg0.remote_ip4)
3499 self.assertEqual(tcp.sport, 12345)
3500 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3501 self.assertEqual(tcp.dport, local_port)
3502 self.check_tcp_checksum(p)
3503 self.check_ip_checksum(p)
3504 except:
3505 self.logger.error(ppp("Unexpected or invalid packet:", p))
3506 raise
3507
3508 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3509 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3510 TCP(sport=local_port, dport=12345))
3511 self.pg1.add_stream(p)
3512 self.pg_enable_capture(self.pg_interfaces)
3513 self.pg_start()
3514 capture = self.pg0.get_capture(1)
3515 p = capture[0]
3516 try:
3517 ip = p[IP]
3518 tcp = p[TCP]
3519 self.assertEqual(ip.src, external_addr)
3520 self.assertEqual(tcp.sport, external_port)
3521 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3522 self.assertEqual(tcp.dport, 12345)
3523 self.check_tcp_checksum(p)
3524 self.check_ip_checksum(p)
3525 except:
3526 self.logger.error(ppp("Unexpected or invalid packet:", p))
3527 raise
3528
Matus Fabian36ea2d62017-10-24 04:13:49 -07003529 def test_one_armed_nat44(self):
3530 """ One armed NAT44 """
3531 remote_host = self.pg9.remote_hosts[0]
3532 local_host = self.pg9.remote_hosts[1]
3533 external_port = 0
3534
3535 self.nat44_add_address(self.nat_addr)
3536 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3537 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3538 is_inside=0)
3539
3540 # in2out
3541 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3542 IP(src=local_host.ip4, dst=remote_host.ip4) /
3543 TCP(sport=12345, dport=80))
3544 self.pg9.add_stream(p)
3545 self.pg_enable_capture(self.pg_interfaces)
3546 self.pg_start()
3547 capture = self.pg9.get_capture(1)
3548 p = capture[0]
3549 try:
3550 ip = p[IP]
3551 tcp = p[TCP]
3552 self.assertEqual(ip.src, self.nat_addr)
3553 self.assertEqual(ip.dst, remote_host.ip4)
3554 self.assertNotEqual(tcp.sport, 12345)
3555 external_port = tcp.sport
3556 self.assertEqual(tcp.dport, 80)
3557 self.check_tcp_checksum(p)
3558 self.check_ip_checksum(p)
3559 except:
3560 self.logger.error(ppp("Unexpected or invalid packet:", p))
3561 raise
3562
3563 # out2in
3564 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3565 IP(src=remote_host.ip4, dst=self.nat_addr) /
3566 TCP(sport=80, dport=external_port))
3567 self.pg9.add_stream(p)
3568 self.pg_enable_capture(self.pg_interfaces)
3569 self.pg_start()
3570 capture = self.pg9.get_capture(1)
3571 p = capture[0]
3572 try:
3573 ip = p[IP]
3574 tcp = p[TCP]
3575 self.assertEqual(ip.src, remote_host.ip4)
3576 self.assertEqual(ip.dst, local_host.ip4)
3577 self.assertEqual(tcp.sport, 80)
3578 self.assertEqual(tcp.dport, 12345)
3579 self.check_tcp_checksum(p)
3580 self.check_ip_checksum(p)
3581 except:
3582 self.logger.error(ppp("Unexpected or invalid packet:", p))
3583 raise
3584
Matus Fabiand95c39e2018-01-23 06:07:01 -08003585 def test_one_armed_nat44_static(self):
3586 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3587 remote_host = self.pg9.remote_hosts[0]
3588 local_host = self.pg9.remote_hosts[1]
3589 external_port = 80
3590 local_port = 8080
3591 eh_port_in = 0
3592
3593 self.vapi.nat44_forwarding_enable_disable(1)
3594 self.nat44_add_address(self.nat_addr, twice_nat=1)
3595 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3596 local_port, external_port,
3597 proto=IP_PROTOS.tcp, out2in_only=1,
3598 twice_nat=1)
3599 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3600 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3601 is_inside=0)
3602
3603 # from client to service
3604 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3605 IP(src=remote_host.ip4, dst=self.nat_addr) /
3606 TCP(sport=12345, dport=external_port))
3607 self.pg9.add_stream(p)
3608 self.pg_enable_capture(self.pg_interfaces)
3609 self.pg_start()
3610 capture = self.pg9.get_capture(1)
3611 p = capture[0]
3612 server = None
3613 try:
3614 ip = p[IP]
3615 tcp = p[TCP]
3616 self.assertEqual(ip.dst, local_host.ip4)
3617 self.assertEqual(ip.src, self.nat_addr)
3618 self.assertEqual(tcp.dport, local_port)
3619 self.assertNotEqual(tcp.sport, 12345)
3620 eh_port_in = tcp.sport
3621 self.check_tcp_checksum(p)
3622 self.check_ip_checksum(p)
3623 except:
3624 self.logger.error(ppp("Unexpected or invalid packet:", p))
3625 raise
3626
3627 # from service back to client
3628 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3629 IP(src=local_host.ip4, dst=self.nat_addr) /
3630 TCP(sport=local_port, dport=eh_port_in))
3631 self.pg9.add_stream(p)
3632 self.pg_enable_capture(self.pg_interfaces)
3633 self.pg_start()
3634 capture = self.pg9.get_capture(1)
3635 p = capture[0]
3636 try:
3637 ip = p[IP]
3638 tcp = p[TCP]
3639 self.assertEqual(ip.src, self.nat_addr)
3640 self.assertEqual(ip.dst, remote_host.ip4)
3641 self.assertEqual(tcp.sport, external_port)
3642 self.assertEqual(tcp.dport, 12345)
3643 self.check_tcp_checksum(p)
3644 self.check_ip_checksum(p)
3645 except:
3646 self.logger.error(ppp("Unexpected or invalid packet:", p))
3647 raise
3648
Matus Fabian5ba86f72017-10-26 03:37:38 -07003649 def test_del_session(self):
3650 """ Delete NAT44 session """
3651 self.nat44_add_address(self.nat_addr)
3652 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3653 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3654 is_inside=0)
3655
3656 pkts = self.create_stream_in(self.pg0, self.pg1)
3657 self.pg0.add_stream(pkts)
3658 self.pg_enable_capture(self.pg_interfaces)
3659 self.pg_start()
3660 capture = self.pg1.get_capture(len(pkts))
3661
3662 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3663 nsessions = len(sessions)
3664
3665 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3666 sessions[0].inside_port,
3667 sessions[0].protocol)
3668 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3669 sessions[1].outside_port,
3670 sessions[1].protocol,
3671 is_in=0)
3672
3673 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3674 self.assertEqual(nsessions - len(sessions), 2)
3675
Matus Fabianefcd1e92017-08-15 06:59:19 -07003676 def test_set_get_reass(self):
3677 """ NAT44 set/get virtual fragmentation reassembly """
3678 reas_cfg1 = self.vapi.nat_get_reass()
3679
3680 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3681 max_reass=reas_cfg1.ip4_max_reass * 2,
3682 max_frag=reas_cfg1.ip4_max_frag * 2)
3683
3684 reas_cfg2 = self.vapi.nat_get_reass()
3685
3686 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3687 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3688 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3689
3690 self.vapi.nat_set_reass(drop_frag=1)
3691 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3692
3693 def test_frag_in_order(self):
3694 """ NAT44 translate fragments arriving in order """
3695 self.nat44_add_address(self.nat_addr)
3696 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3697 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3698 is_inside=0)
3699
3700 data = "A" * 4 + "B" * 16 + "C" * 3
3701 self.tcp_port_in = random.randint(1025, 65535)
3702
3703 reass = self.vapi.nat_reass_dump()
3704 reass_n_start = len(reass)
3705
3706 # in2out
3707 pkts = self.create_stream_frag(self.pg0,
3708 self.pg1.remote_ip4,
3709 self.tcp_port_in,
3710 20,
3711 data)
3712 self.pg0.add_stream(pkts)
3713 self.pg_enable_capture(self.pg_interfaces)
3714 self.pg_start()
3715 frags = self.pg1.get_capture(len(pkts))
3716 p = self.reass_frags_and_verify(frags,
3717 self.nat_addr,
3718 self.pg1.remote_ip4)
3719 self.assertEqual(p[TCP].dport, 20)
3720 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3721 self.tcp_port_out = p[TCP].sport
3722 self.assertEqual(data, p[Raw].load)
3723
3724 # out2in
3725 pkts = self.create_stream_frag(self.pg1,
3726 self.nat_addr,
3727 20,
3728 self.tcp_port_out,
3729 data)
3730 self.pg1.add_stream(pkts)
3731 self.pg_enable_capture(self.pg_interfaces)
3732 self.pg_start()
3733 frags = self.pg0.get_capture(len(pkts))
3734 p = self.reass_frags_and_verify(frags,
3735 self.pg1.remote_ip4,
3736 self.pg0.remote_ip4)
3737 self.assertEqual(p[TCP].sport, 20)
3738 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3739 self.assertEqual(data, p[Raw].load)
3740
3741 reass = self.vapi.nat_reass_dump()
3742 reass_n_end = len(reass)
3743
3744 self.assertEqual(reass_n_end - reass_n_start, 2)
3745
3746 def test_reass_hairpinning(self):
3747 """ NAT44 fragments hairpinning """
3748 host = self.pg0.remote_hosts[0]
3749 server = self.pg0.remote_hosts[1]
3750 host_in_port = random.randint(1025, 65535)
3751 host_out_port = 0
3752 server_in_port = random.randint(1025, 65535)
3753 server_out_port = random.randint(1025, 65535)
3754 data = "A" * 4 + "B" * 16 + "C" * 3
3755
3756 self.nat44_add_address(self.nat_addr)
3757 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3758 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3759 is_inside=0)
3760 # add static mapping for server
3761 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3762 server_in_port, server_out_port,
3763 proto=IP_PROTOS.tcp)
3764
3765 # send packet from host to server
3766 pkts = self.create_stream_frag(self.pg0,
3767 self.nat_addr,
3768 host_in_port,
3769 server_out_port,
3770 data)
3771 self.pg0.add_stream(pkts)
3772 self.pg_enable_capture(self.pg_interfaces)
3773 self.pg_start()
3774 frags = self.pg0.get_capture(len(pkts))
3775 p = self.reass_frags_and_verify(frags,
3776 self.nat_addr,
3777 server.ip4)
3778 self.assertNotEqual(p[TCP].sport, host_in_port)
3779 self.assertEqual(p[TCP].dport, server_in_port)
3780 self.assertEqual(data, p[Raw].load)
3781
3782 def test_frag_out_of_order(self):
3783 """ NAT44 translate fragments arriving out of order """
3784 self.nat44_add_address(self.nat_addr)
3785 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3786 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3787 is_inside=0)
3788
3789 data = "A" * 4 + "B" * 16 + "C" * 3
3790 random.randint(1025, 65535)
3791
3792 # in2out
3793 pkts = self.create_stream_frag(self.pg0,
3794 self.pg1.remote_ip4,
3795 self.tcp_port_in,
3796 20,
3797 data)
3798 pkts.reverse()
3799 self.pg0.add_stream(pkts)
3800 self.pg_enable_capture(self.pg_interfaces)
3801 self.pg_start()
3802 frags = self.pg1.get_capture(len(pkts))
3803 p = self.reass_frags_and_verify(frags,
3804 self.nat_addr,
3805 self.pg1.remote_ip4)
3806 self.assertEqual(p[TCP].dport, 20)
3807 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3808 self.tcp_port_out = p[TCP].sport
3809 self.assertEqual(data, p[Raw].load)
3810
3811 # out2in
3812 pkts = self.create_stream_frag(self.pg1,
3813 self.nat_addr,
3814 20,
3815 self.tcp_port_out,
3816 data)
3817 pkts.reverse()
3818 self.pg1.add_stream(pkts)
3819 self.pg_enable_capture(self.pg_interfaces)
3820 self.pg_start()
3821 frags = self.pg0.get_capture(len(pkts))
3822 p = self.reass_frags_and_verify(frags,
3823 self.pg1.remote_ip4,
3824 self.pg0.remote_ip4)
3825 self.assertEqual(p[TCP].sport, 20)
3826 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3827 self.assertEqual(data, p[Raw].load)
3828
Matus Fabian27697102017-11-09 01:43:47 -08003829 def test_port_restricted(self):
3830 """ Port restricted NAT44 (MAP-E CE) """
3831 self.nat44_add_address(self.nat_addr)
3832 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3833 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3834 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003835 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003836 "psid-offset 6 psid-len 6")
3837
3838 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3839 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3840 TCP(sport=4567, dport=22))
3841 self.pg0.add_stream(p)
3842 self.pg_enable_capture(self.pg_interfaces)
3843 self.pg_start()
3844 capture = self.pg1.get_capture(1)
3845 p = capture[0]
3846 try:
3847 ip = p[IP]
3848 tcp = p[TCP]
3849 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3850 self.assertEqual(ip.src, self.nat_addr)
3851 self.assertEqual(tcp.dport, 22)
3852 self.assertNotEqual(tcp.sport, 4567)
3853 self.assertEqual((tcp.sport >> 6) & 63, 10)
3854 self.check_tcp_checksum(p)
3855 self.check_ip_checksum(p)
3856 except:
3857 self.logger.error(ppp("Unexpected or invalid packet:", p))
3858 raise
3859
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003860 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
3861 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08003862 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003863
Matus Fabianb932d262017-12-18 05:38:24 -08003864 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003865 if lb:
3866 if not same_pg:
3867 port_in1 = port_in
3868 port_in2 = port_in
3869 else:
3870 port_in1 = port_in+1
3871 port_in2 = port_in+2
3872
Matus Fabianb932d262017-12-18 05:38:24 -08003873 port_out = 80
3874 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003875
3876 server1 = self.pg0.remote_hosts[0]
3877 server2 = self.pg0.remote_hosts[1]
3878 if lb and same_pg:
3879 server2 = server1
3880 if not lb:
3881 server = server1
3882
3883 pg0 = self.pg0
3884 if same_pg:
3885 pg1 = self.pg0
3886 else:
3887 pg1 = self.pg1
3888
3889 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
3890 client_id == 1)
3891
Matus Fabianb932d262017-12-18 05:38:24 -08003892 self.nat44_add_address(self.nat_addr)
3893 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003894 if not lb:
3895 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
3896 port_in, port_out,
3897 proto=IP_PROTOS.tcp,
3898 twice_nat=int(not self_twice_nat),
3899 self_twice_nat=int(self_twice_nat))
3900 else:
3901 locals = [{'addr': server1.ip4n,
3902 'port': port_in1,
3903 'probability': 50},
3904 {'addr': server2.ip4n,
3905 'port': port_in2,
3906 'probability': 50}]
3907 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3908 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
3909 port_out,
3910 IP_PROTOS.tcp,
3911 twice_nat=int(
3912 not self_twice_nat),
3913 self_twice_nat=int(
3914 self_twice_nat),
3915 local_num=len(locals),
3916 locals=locals)
3917 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
3918 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08003919 is_inside=0)
3920
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003921 if same_pg:
3922 if not lb:
3923 client = server
3924 else:
3925 assert client_id is not None
3926 if client_id == 1:
3927 client = self.pg0.remote_hosts[0]
3928 elif client_id == 2:
3929 client = self.pg0.remote_hosts[1]
3930 else:
3931 client = pg1.remote_hosts[0]
3932 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
3933 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08003934 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003935 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003936 self.pg_enable_capture(self.pg_interfaces)
3937 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003938 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003939 p = capture[0]
3940 try:
3941 ip = p[IP]
3942 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003943 if lb:
3944 if ip.dst == server1.ip4:
3945 server = server1
3946 port_in = port_in1
3947 else:
3948 server = server2
3949 port_in = port_in2
3950 self.assertEqual(ip.dst, server.ip4)
3951 if lb and same_pg:
3952 self.assertIn(tcp.dport, [port_in1, port_in2])
3953 else:
3954 self.assertEqual(tcp.dport, port_in)
3955 if eh_translate:
3956 self.assertEqual(ip.src, twice_nat_addr)
3957 self.assertNotEqual(tcp.sport, eh_port_out)
3958 else:
3959 self.assertEqual(ip.src, client.ip4)
3960 self.assertEqual(tcp.sport, eh_port_out)
3961 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08003962 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003963 saved_port_in = tcp.dport
Matus Fabianb932d262017-12-18 05:38:24 -08003964 self.check_tcp_checksum(p)
3965 self.check_ip_checksum(p)
3966 except:
3967 self.logger.error(ppp("Unexpected or invalid packet:", p))
3968 raise
3969
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003970 p = (Ether(src=server.mac, dst=pg0.local_mac) /
3971 IP(src=server.ip4, dst=eh_addr_in) /
3972 TCP(sport=saved_port_in, dport=eh_port_in))
3973 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003974 self.pg_enable_capture(self.pg_interfaces)
3975 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003976 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003977 p = capture[0]
3978 try:
3979 ip = p[IP]
3980 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003981 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08003982 self.assertEqual(ip.src, self.nat_addr)
3983 self.assertEqual(tcp.dport, eh_port_out)
3984 self.assertEqual(tcp.sport, port_out)
3985 self.check_tcp_checksum(p)
3986 self.check_ip_checksum(p)
3987 except:
3988 self.logger.error(ppp("Unexpected or invalid packet:", p))
3989 raise
3990
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003991 def test_twice_nat(self):
3992 """ Twice NAT44 """
3993 self.twice_nat_common()
3994
3995 def test_self_twice_nat_positive(self):
3996 """ Self Twice NAT44 (positive test) """
3997 self.twice_nat_common(self_twice_nat=True, same_pg=True)
3998
3999 def test_self_twice_nat_negative(self):
4000 """ Self Twice NAT44 (negative test) """
4001 self.twice_nat_common(self_twice_nat=True)
4002
Matus Fabianb932d262017-12-18 05:38:24 -08004003 def test_twice_nat_lb(self):
4004 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004005 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004006
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004007 def test_self_twice_nat_lb_positive(self):
4008 """ Self Twice NAT44 local service load balancing (positive test) """
4009 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4010 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004011
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004012 def test_self_twice_nat_lb_negative(self):
4013 """ Self Twice NAT44 local service load balancing (negative test) """
4014 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4015 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004016
4017 def test_twice_nat_interface_addr(self):
4018 """ Acquire twice NAT44 addresses from interface """
4019 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
4020
4021 # no address in NAT pool
4022 adresses = self.vapi.nat44_address_dump()
4023 self.assertEqual(0, len(adresses))
4024
4025 # configure interface address and check NAT address pool
4026 self.pg7.config_ip4()
4027 adresses = self.vapi.nat44_address_dump()
4028 self.assertEqual(1, len(adresses))
4029 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
4030 self.assertEqual(adresses[0].twice_nat, 1)
4031
4032 # remove interface address and check NAT address pool
4033 self.pg7.unconfig_ip4()
4034 adresses = self.vapi.nat44_address_dump()
4035 self.assertEqual(0, len(adresses))
4036
Matus Fabiana431ad12018-01-04 04:03:14 -08004037 def test_ipfix_max_frags(self):
4038 """ IPFIX logging maximum fragments pending reassembly exceeded """
4039 self.nat44_add_address(self.nat_addr)
4040 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4041 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4042 is_inside=0)
4043 self.vapi.nat_set_reass(max_frag=0)
4044 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4045 src_address=self.pg3.local_ip4n,
4046 path_mtu=512,
4047 template_interval=10)
4048 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4049 src_port=self.ipfix_src_port)
4050
4051 data = "A" * 4 + "B" * 16 + "C" * 3
4052 self.tcp_port_in = random.randint(1025, 65535)
4053 pkts = self.create_stream_frag(self.pg0,
4054 self.pg1.remote_ip4,
4055 self.tcp_port_in,
4056 20,
4057 data)
4058 self.pg0.add_stream(pkts[-1])
4059 self.pg_enable_capture(self.pg_interfaces)
4060 self.pg_start()
4061 frags = self.pg1.get_capture(0)
4062 self.vapi.cli("ipfix flush") # FIXME this should be an API call
4063 capture = self.pg3.get_capture(9)
4064 ipfix = IPFIXDecoder()
4065 # first load template
4066 for p in capture:
4067 self.assertTrue(p.haslayer(IPFIX))
4068 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4069 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4070 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4071 self.assertEqual(p[UDP].dport, 4739)
4072 self.assertEqual(p[IPFIX].observationDomainID,
4073 self.ipfix_domain_id)
4074 if p.haslayer(Template):
4075 ipfix.add_template(p.getlayer(Template))
4076 # verify events in data set
4077 for p in capture:
4078 if p.haslayer(Data):
4079 data = ipfix.decode_data_set(p.getlayer(Set))
4080 self.verify_ipfix_max_fragments_ip4(data, 0,
4081 self.pg0.remote_ip4n)
4082
Matus Fabiande886752016-12-07 03:38:19 -08004083 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004084 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004085 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004086 self.logger.info(self.vapi.cli("show nat44 addresses"))
4087 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4088 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4089 self.logger.info(self.vapi.cli("show nat44 interface address"))
4090 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004091 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004092 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004093 self.clear_nat44()
Matus Fabiande886752016-12-07 03:38:19 -08004094
Matus Fabianeea28d72017-01-13 04:15:54 -08004095
Juraj Slobodacba69362017-12-19 02:09:32 +01004096class TestNAT44Out2InDPO(MethodHolder):
4097 """ NAT44 Test Cases using out2in DPO """
4098
4099 @classmethod
4100 def setUpConstants(cls):
4101 super(TestNAT44Out2InDPO, cls).setUpConstants()
4102 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4103
4104 @classmethod
4105 def setUpClass(cls):
4106 super(TestNAT44Out2InDPO, cls).setUpClass()
4107
4108 try:
4109 cls.tcp_port_in = 6303
4110 cls.tcp_port_out = 6303
4111 cls.udp_port_in = 6304
4112 cls.udp_port_out = 6304
4113 cls.icmp_id_in = 6305
4114 cls.icmp_id_out = 6305
4115 cls.nat_addr = '10.0.0.3'
4116 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4117 cls.dst_ip4 = '192.168.70.1'
4118
4119 cls.create_pg_interfaces(range(2))
4120
4121 cls.pg0.admin_up()
4122 cls.pg0.config_ip4()
4123 cls.pg0.resolve_arp()
4124
4125 cls.pg1.admin_up()
4126 cls.pg1.config_ip6()
4127 cls.pg1.resolve_ndp()
4128
4129 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4130 dst_address_length=0,
4131 next_hop_address=cls.pg1.remote_ip6n,
4132 next_hop_sw_if_index=cls.pg1.sw_if_index)
4133
4134 except Exception:
4135 super(TestNAT44Out2InDPO, cls).tearDownClass()
4136 raise
4137
4138 def configure_xlat(self):
4139 self.dst_ip6_pfx = '1:2:3::'
4140 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4141 self.dst_ip6_pfx)
4142 self.dst_ip6_pfx_len = 96
4143 self.src_ip6_pfx = '4:5:6::'
4144 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4145 self.src_ip6_pfx)
4146 self.src_ip6_pfx_len = 96
4147 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4148 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4149 '\x00\x00\x00\x00', 0, is_translation=1,
4150 is_rfc6052=1)
4151
4152 def test_464xlat_ce(self):
4153 """ Test 464XLAT CE with NAT44 """
4154
4155 self.configure_xlat()
4156
4157 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4158 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4159
4160 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4161 self.dst_ip6_pfx_len)
4162 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4163 self.src_ip6_pfx_len)
4164
4165 try:
4166 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4167 self.pg0.add_stream(pkts)
4168 self.pg_enable_capture(self.pg_interfaces)
4169 self.pg_start()
4170 capture = self.pg1.get_capture(len(pkts))
4171 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4172 dst_ip=out_src_ip6)
4173
4174 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4175 out_dst_ip6)
4176 self.pg1.add_stream(pkts)
4177 self.pg_enable_capture(self.pg_interfaces)
4178 self.pg_start()
4179 capture = self.pg0.get_capture(len(pkts))
4180 self.verify_capture_in(capture, self.pg0)
4181 finally:
4182 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4183 is_add=0)
4184 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4185 self.nat_addr_n, is_add=0)
4186
4187 def test_464xlat_ce_no_nat(self):
4188 """ Test 464XLAT CE without NAT44 """
4189
4190 self.configure_xlat()
4191
4192 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4193 self.dst_ip6_pfx_len)
4194 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4195 self.src_ip6_pfx_len)
4196
4197 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4198 self.pg0.add_stream(pkts)
4199 self.pg_enable_capture(self.pg_interfaces)
4200 self.pg_start()
4201 capture = self.pg1.get_capture(len(pkts))
4202 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4203 nat_ip=out_dst_ip6, same_port=True)
4204
4205 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4206 self.pg1.add_stream(pkts)
4207 self.pg_enable_capture(self.pg_interfaces)
4208 self.pg_start()
4209 capture = self.pg0.get_capture(len(pkts))
4210 self.verify_capture_in(capture, self.pg0)
4211
4212
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004213class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004214 """ Deterministic NAT Test Cases """
4215
4216 @classmethod
4217 def setUpConstants(cls):
4218 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004219 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004220
4221 @classmethod
4222 def setUpClass(cls):
4223 super(TestDeterministicNAT, cls).setUpClass()
4224
4225 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004226 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004227 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004228 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004229 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004230 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004231 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004232
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004233 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004234 cls.interfaces = list(cls.pg_interfaces)
4235
4236 for i in cls.interfaces:
4237 i.admin_up()
4238 i.config_ip4()
4239 i.resolve_arp()
4240
Martin Gálik977c1cb2017-03-30 23:21:51 -07004241 cls.pg0.generate_remote_hosts(2)
4242 cls.pg0.configure_ipv4_neighbors()
4243
Matus Fabian066f0342017-02-10 03:48:01 -08004244 except Exception:
4245 super(TestDeterministicNAT, cls).tearDownClass()
4246 raise
4247
Martin Gálik977c1cb2017-03-30 23:21:51 -07004248 def create_stream_in(self, in_if, out_if, ttl=64):
4249 """
4250 Create packet stream for inside network
4251
4252 :param in_if: Inside interface
4253 :param out_if: Outside interface
4254 :param ttl: TTL of generated packets
4255 """
4256 pkts = []
4257 # TCP
4258 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4259 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004260 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004261 pkts.append(p)
4262
4263 # UDP
4264 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4265 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004266 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004267 pkts.append(p)
4268
4269 # ICMP
4270 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4271 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4272 ICMP(id=self.icmp_id_in, type='echo-request'))
4273 pkts.append(p)
4274
4275 return pkts
4276
4277 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4278 """
4279 Create packet stream for outside network
4280
4281 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004282 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004283 :param ttl: TTL of generated packets
4284 """
4285 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004286 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004287 pkts = []
4288 # TCP
4289 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4290 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004291 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004292 pkts.append(p)
4293
4294 # UDP
4295 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4296 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004297 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004298 pkts.append(p)
4299
4300 # ICMP
4301 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4302 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4303 ICMP(id=self.icmp_external_id, type='echo-reply'))
4304 pkts.append(p)
4305
4306 return pkts
4307
4308 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4309 """
4310 Verify captured packets on outside network
4311
4312 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004313 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004314 :param same_port: Sorce port number is not translated (Default False)
4315 :param packet_num: Expected number of packets (Default 3)
4316 """
4317 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004318 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004319 self.assertEqual(packet_num, len(capture))
4320 for packet in capture:
4321 try:
4322 self.assertEqual(packet[IP].src, nat_ip)
4323 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004324 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004325 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004326 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004327 else:
4328 self.icmp_external_id = packet[ICMP].id
4329 except:
4330 self.logger.error(ppp("Unexpected or invalid packet "
4331 "(outside network):", packet))
4332 raise
4333
4334 def initiate_tcp_session(self, in_if, out_if):
4335 """
4336 Initiates TCP session
4337
4338 :param in_if: Inside interface
4339 :param out_if: Outside interface
4340 """
4341 try:
4342 # SYN packet in->out
4343 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
4344 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004345 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004346 flags="S"))
4347 in_if.add_stream(p)
4348 self.pg_enable_capture(self.pg_interfaces)
4349 self.pg_start()
4350 capture = out_if.get_capture(1)
4351 p = capture[0]
Martin Gálik9806eae2017-04-25 01:25:08 -07004352 self.tcp_port_out = p[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004353
4354 # SYN + ACK packet out->in
4355 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004356 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004357 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004358 flags="SA"))
4359 out_if.add_stream(p)
4360 self.pg_enable_capture(self.pg_interfaces)
4361 self.pg_start()
4362 in_if.get_capture(1)
4363
4364 # ACK packet in->out
4365 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
4366 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004367 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004368 flags="A"))
4369 in_if.add_stream(p)
4370 self.pg_enable_capture(self.pg_interfaces)
4371 self.pg_start()
4372 out_if.get_capture(1)
4373
4374 except:
4375 self.logger.error("TCP 3 way handshake failed")
4376 raise
4377
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004378 def verify_ipfix_max_entries_per_user(self, data):
4379 """
4380 Verify IPFIX maximum entries per user exceeded event
4381
4382 :param data: Decoded IPFIX data records
4383 """
4384 self.assertEqual(1, len(data))
4385 record = data[0]
4386 # natEvent
4387 self.assertEqual(ord(record[230]), 13)
4388 # natQuotaExceededEvent
4389 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004390 # maxEntriesPerUser
4391 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004392 # sourceIPv4Address
4393 self.assertEqual(self.pg0.remote_ip4n, record[8])
4394
Matus Fabian066f0342017-02-10 03:48:01 -08004395 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004396 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004397 in_addr = '172.16.255.0'
4398 out_addr = '172.17.255.50'
4399 in_addr_t = '172.16.255.20'
4400 in_addr_n = socket.inet_aton(in_addr)
4401 out_addr_n = socket.inet_aton(out_addr)
4402 in_addr_t_n = socket.inet_aton(in_addr_t)
4403 in_plen = 24
4404 out_plen = 32
4405
Matus Fabian2ba92e32017-08-21 07:05:03 -07004406 nat_config = self.vapi.nat_show_config()
4407 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004408
Matus Fabian2ba92e32017-08-21 07:05:03 -07004409 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004410
Matus Fabian2ba92e32017-08-21 07:05:03 -07004411 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004412 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004413 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004414 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4415
Matus Fabian2ba92e32017-08-21 07:05:03 -07004416 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004417 self.assertEqual(len(deterministic_mappings), 1)
4418 dsm = deterministic_mappings[0]
4419 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4420 self.assertEqual(in_plen, dsm.in_plen)
4421 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4422 self.assertEqual(out_plen, dsm.out_plen)
4423
Matus Fabian2ba92e32017-08-21 07:05:03 -07004424 self.clear_nat_det()
4425 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004426 self.assertEqual(len(deterministic_mappings), 0)
4427
Matus Fabian6a0946f2017-04-12 03:36:13 -07004428 def test_set_timeouts(self):
4429 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004430 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004431
Matus Fabian2ba92e32017-08-21 07:05:03 -07004432 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4433 timeouts_before.tcp_established + 10,
4434 timeouts_before.tcp_transitory + 10,
4435 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004436
Matus Fabian2ba92e32017-08-21 07:05:03 -07004437 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004438
4439 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4440 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4441 self.assertNotEqual(timeouts_before.tcp_established,
4442 timeouts_after.tcp_established)
4443 self.assertNotEqual(timeouts_before.tcp_transitory,
4444 timeouts_after.tcp_transitory)
4445
Martin Gálik977c1cb2017-03-30 23:21:51 -07004446 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004447 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004448
4449 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004450
Matus Fabian2ba92e32017-08-21 07:05:03 -07004451 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4452 32,
4453 socket.inet_aton(nat_ip),
4454 32)
4455 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4456 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4457 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004458
4459 # in2out
4460 pkts = self.create_stream_in(self.pg0, self.pg1)
4461 self.pg0.add_stream(pkts)
4462 self.pg_enable_capture(self.pg_interfaces)
4463 self.pg_start()
4464 capture = self.pg1.get_capture(len(pkts))
4465 self.verify_capture_out(capture, nat_ip)
4466
4467 # out2in
4468 pkts = self.create_stream_out(self.pg1, nat_ip)
4469 self.pg1.add_stream(pkts)
4470 self.pg_enable_capture(self.pg_interfaces)
4471 self.pg_start()
4472 capture = self.pg0.get_capture(len(pkts))
4473 self.verify_capture_in(capture, self.pg0)
4474
Martin Gálik9806eae2017-04-25 01:25:08 -07004475 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004476 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004477 self.assertEqual(len(sessions), 3)
4478
4479 # TCP session
4480 s = sessions[0]
4481 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4482 self.assertEqual(s.in_port, self.tcp_port_in)
4483 self.assertEqual(s.out_port, self.tcp_port_out)
4484 self.assertEqual(s.ext_port, self.tcp_external_port)
4485
4486 # UDP session
4487 s = sessions[1]
4488 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4489 self.assertEqual(s.in_port, self.udp_port_in)
4490 self.assertEqual(s.out_port, self.udp_port_out)
4491 self.assertEqual(s.ext_port, self.udp_external_port)
4492
4493 # ICMP session
4494 s = sessions[2]
4495 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4496 self.assertEqual(s.in_port, self.icmp_id_in)
4497 self.assertEqual(s.out_port, self.icmp_external_id)
4498
Martin Gálik977c1cb2017-03-30 23:21:51 -07004499 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004500 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004501
4502 nat_ip = "10.0.0.10"
4503 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004504 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004505
4506 host0 = self.pg0.remote_hosts[0]
4507 host1 = self.pg0.remote_hosts[1]
4508
Matus Fabian2ba92e32017-08-21 07:05:03 -07004509 self.vapi.nat_det_add_del_map(host0.ip4n,
4510 24,
4511 socket.inet_aton(nat_ip),
4512 32)
4513 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4514 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4515 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004516
4517 # host0 to out
4518 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4519 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004520 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004521 self.pg0.add_stream(p)
4522 self.pg_enable_capture(self.pg_interfaces)
4523 self.pg_start()
4524 capture = self.pg1.get_capture(1)
4525 p = capture[0]
4526 try:
4527 ip = p[IP]
4528 tcp = p[TCP]
4529 self.assertEqual(ip.src, nat_ip)
4530 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004531 self.assertEqual(tcp.dport, external_port)
4532 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004533 except:
4534 self.logger.error(ppp("Unexpected or invalid packet:", p))
4535 raise
4536
4537 # host1 to out
4538 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4539 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004540 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004541 self.pg0.add_stream(p)
4542 self.pg_enable_capture(self.pg_interfaces)
4543 self.pg_start()
4544 capture = self.pg1.get_capture(1)
4545 p = capture[0]
4546 try:
4547 ip = p[IP]
4548 tcp = p[TCP]
4549 self.assertEqual(ip.src, nat_ip)
4550 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004551 self.assertEqual(tcp.dport, external_port)
4552 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004553 except:
4554 self.logger.error(ppp("Unexpected or invalid packet:", p))
4555 raise
4556
Matus Fabian2ba92e32017-08-21 07:05:03 -07004557 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004558 self.assertEqual(1, len(dms))
4559 self.assertEqual(2, dms[0].ses_num)
4560
4561 # out to host0
4562 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4563 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004564 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004565 self.pg1.add_stream(p)
4566 self.pg_enable_capture(self.pg_interfaces)
4567 self.pg_start()
4568 capture = self.pg0.get_capture(1)
4569 p = capture[0]
4570 try:
4571 ip = p[IP]
4572 tcp = p[TCP]
4573 self.assertEqual(ip.src, self.pg1.remote_ip4)
4574 self.assertEqual(ip.dst, host0.ip4)
4575 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004576 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004577 except:
4578 self.logger.error(ppp("Unexpected or invalid packet:", p))
4579 raise
4580
4581 # out to host1
4582 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4583 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004584 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004585 self.pg1.add_stream(p)
4586 self.pg_enable_capture(self.pg_interfaces)
4587 self.pg_start()
4588 capture = self.pg0.get_capture(1)
4589 p = capture[0]
4590 try:
4591 ip = p[IP]
4592 tcp = p[TCP]
4593 self.assertEqual(ip.src, self.pg1.remote_ip4)
4594 self.assertEqual(ip.dst, host1.ip4)
4595 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004596 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004597 except:
4598 self.logger.error(ppp("Unexpected or invalid packet", p))
4599 raise
4600
Martin Gálik6bc8c642017-04-19 01:12:27 -07004601 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004602 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4603 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004604 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004605 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004606 dms = self.vapi.nat_det_map_dump()
4607 self.assertEqual(dms[0].ses_num, 1)
4608
4609 self.vapi.nat_det_close_session_in(host0.ip4n,
4610 port_in,
4611 self.pg1.remote_ip4n,
4612 external_port)
4613 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004614 self.assertEqual(dms[0].ses_num, 0)
4615
Martin Gálik977c1cb2017-03-30 23:21:51 -07004616 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004617 """ Deterministic NAT TCP session close from inside network """
4618 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4619 32,
4620 socket.inet_aton(self.nat_addr),
4621 32)
4622 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4623 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4624 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004625
4626 self.initiate_tcp_session(self.pg0, self.pg1)
4627
4628 # close the session from inside
4629 try:
4630 # FIN packet in -> out
4631 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4632 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004633 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004634 flags="F"))
4635 self.pg0.add_stream(p)
4636 self.pg_enable_capture(self.pg_interfaces)
4637 self.pg_start()
4638 self.pg1.get_capture(1)
4639
4640 pkts = []
4641
4642 # ACK packet out -> in
4643 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004644 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004645 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004646 flags="A"))
4647 pkts.append(p)
4648
4649 # FIN packet out -> in
4650 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004651 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004652 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004653 flags="F"))
4654 pkts.append(p)
4655
4656 self.pg1.add_stream(pkts)
4657 self.pg_enable_capture(self.pg_interfaces)
4658 self.pg_start()
4659 self.pg0.get_capture(2)
4660
4661 # ACK packet in -> out
4662 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4663 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004664 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004665 flags="A"))
4666 self.pg0.add_stream(p)
4667 self.pg_enable_capture(self.pg_interfaces)
4668 self.pg_start()
4669 self.pg1.get_capture(1)
4670
Matus Fabian2ba92e32017-08-21 07:05:03 -07004671 # Check if deterministic NAT44 closed the session
4672 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004673 self.assertEqual(0, dms[0].ses_num)
4674 except:
4675 self.logger.error("TCP session termination failed")
4676 raise
4677
4678 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004679 """ Deterministic NAT TCP session close from outside network """
4680 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4681 32,
4682 socket.inet_aton(self.nat_addr),
4683 32)
4684 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4685 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4686 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004687
4688 self.initiate_tcp_session(self.pg0, self.pg1)
4689
4690 # close the session from outside
4691 try:
4692 # FIN packet out -> in
4693 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004694 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004695 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004696 flags="F"))
4697 self.pg1.add_stream(p)
4698 self.pg_enable_capture(self.pg_interfaces)
4699 self.pg_start()
4700 self.pg0.get_capture(1)
4701
4702 pkts = []
4703
4704 # ACK packet in -> out
4705 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4706 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004707 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004708 flags="A"))
4709 pkts.append(p)
4710
4711 # ACK packet in -> out
4712 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4713 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004714 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004715 flags="F"))
4716 pkts.append(p)
4717
4718 self.pg0.add_stream(pkts)
4719 self.pg_enable_capture(self.pg_interfaces)
4720 self.pg_start()
4721 self.pg1.get_capture(2)
4722
4723 # ACK packet out -> in
4724 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004725 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004726 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004727 flags="A"))
4728 self.pg1.add_stream(p)
4729 self.pg_enable_capture(self.pg_interfaces)
4730 self.pg_start()
4731 self.pg0.get_capture(1)
4732
Matus Fabian2ba92e32017-08-21 07:05:03 -07004733 # Check if deterministic NAT44 closed the session
4734 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004735 self.assertEqual(0, dms[0].ses_num)
4736 except:
4737 self.logger.error("TCP session termination failed")
4738 raise
4739
4740 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4741 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004742 """ Deterministic NAT session timeouts """
4743 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4744 32,
4745 socket.inet_aton(self.nat_addr),
4746 32)
4747 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4748 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4749 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004750
4751 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004752 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004753 pkts = self.create_stream_in(self.pg0, self.pg1)
4754 self.pg0.add_stream(pkts)
4755 self.pg_enable_capture(self.pg_interfaces)
4756 self.pg_start()
4757 capture = self.pg1.get_capture(len(pkts))
4758 sleep(15)
4759
Matus Fabian2ba92e32017-08-21 07:05:03 -07004760 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004761 self.assertEqual(0, dms[0].ses_num)
4762
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004763 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004764 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004765 """ Deterministic NAT maximum sessions per user limit """
4766 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4767 32,
4768 socket.inet_aton(self.nat_addr),
4769 32)
4770 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4771 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4772 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004773 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4774 src_address=self.pg2.local_ip4n,
4775 path_mtu=512,
4776 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004777 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004778
4779 pkts = []
4780 for port in range(1025, 2025):
4781 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4782 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4783 UDP(sport=port, dport=port))
4784 pkts.append(p)
4785
4786 self.pg0.add_stream(pkts)
4787 self.pg_enable_capture(self.pg_interfaces)
4788 self.pg_start()
4789 capture = self.pg1.get_capture(len(pkts))
4790
4791 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4792 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07004793 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004794 self.pg0.add_stream(p)
4795 self.pg_enable_capture(self.pg_interfaces)
4796 self.pg_start()
4797 capture = self.pg1.assert_nothing_captured()
4798
Martin Gálikf7e655d2017-04-27 02:13:26 -07004799 # verify ICMP error packet
4800 capture = self.pg0.get_capture(1)
4801 p = capture[0]
4802 self.assertTrue(p.haslayer(ICMP))
4803 icmp = p[ICMP]
4804 self.assertEqual(icmp.type, 3)
4805 self.assertEqual(icmp.code, 1)
4806 self.assertTrue(icmp.haslayer(IPerror))
4807 inner_ip = icmp[IPerror]
4808 self.assertEqual(inner_ip[UDPerror].sport, 3001)
4809 self.assertEqual(inner_ip[UDPerror].dport, 3002)
4810
Matus Fabian2ba92e32017-08-21 07:05:03 -07004811 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004812
4813 self.assertEqual(1000, dms[0].ses_num)
4814
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004815 # verify IPFIX logging
4816 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004817 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004818 capture = self.pg2.get_capture(2)
4819 ipfix = IPFIXDecoder()
4820 # first load template
4821 for p in capture:
4822 self.assertTrue(p.haslayer(IPFIX))
4823 if p.haslayer(Template):
4824 ipfix.add_template(p.getlayer(Template))
4825 # verify events in data set
4826 for p in capture:
4827 if p.haslayer(Data):
4828 data = ipfix.decode_data_set(p.getlayer(Set))
4829 self.verify_ipfix_max_entries_per_user(data)
4830
Matus Fabian2ba92e32017-08-21 07:05:03 -07004831 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08004832 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004833 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08004834 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004835 self.vapi.nat_ipfix(enable=0)
4836 self.vapi.nat_det_set_timeouts()
4837 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004838 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004839 self.vapi.nat_det_add_del_map(dsm.in_addr,
4840 dsm.in_plen,
4841 dsm.out_addr,
4842 dsm.out_plen,
4843 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08004844
Matus Fabian2ba92e32017-08-21 07:05:03 -07004845 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004846 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004847 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
4848 intf.is_inside,
4849 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004850
Matus Fabian066f0342017-02-10 03:48:01 -08004851 def tearDown(self):
4852 super(TestDeterministicNAT, self).tearDown()
4853 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004854 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4855 self.logger.info(
4856 self.vapi.cli("show nat44 deterministic mappings"))
4857 self.logger.info(
4858 self.vapi.cli("show nat44 deterministic timeouts"))
4859 self.logger.info(
4860 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07004861 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08004862
Matus Fabian06596c52017-06-06 04:53:28 -07004863
4864class TestNAT64(MethodHolder):
4865 """ NAT64 Test Cases """
4866
4867 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08004868 def setUpConstants(cls):
4869 super(TestNAT64, cls).setUpConstants()
4870 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
4871 "nat64 st hash buckets 256", "}"])
4872
4873 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07004874 def setUpClass(cls):
4875 super(TestNAT64, cls).setUpClass()
4876
4877 try:
4878 cls.tcp_port_in = 6303
4879 cls.tcp_port_out = 6303
4880 cls.udp_port_in = 6304
4881 cls.udp_port_out = 6304
4882 cls.icmp_id_in = 6305
4883 cls.icmp_id_out = 6305
4884 cls.nat_addr = '10.0.0.3'
4885 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07004886 cls.vrf1_id = 10
4887 cls.vrf1_nat_addr = '10.0.10.3'
4888 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
4889 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08004890 cls.ipfix_src_port = 4739
4891 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07004892
Matus Fabian0938dcf2017-11-08 01:59:38 -08004893 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07004894 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07004895 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07004896 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
4897
Neale Ranns15002542017-09-10 04:39:11 -07004898 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
4899
Matus Fabian029f3d22017-06-15 02:28:50 -07004900 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
4901
4902 cls.pg0.generate_remote_hosts(2)
4903
Matus Fabian06596c52017-06-06 04:53:28 -07004904 for i in cls.ip6_interfaces:
4905 i.admin_up()
4906 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07004907 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07004908
4909 for i in cls.ip4_interfaces:
4910 i.admin_up()
4911 i.config_ip4()
4912 i.resolve_arp()
4913
Matus Fabian36ea2d62017-10-24 04:13:49 -07004914 cls.pg3.admin_up()
4915 cls.pg3.config_ip4()
4916 cls.pg3.resolve_arp()
4917 cls.pg3.config_ip6()
4918 cls.pg3.configure_ipv6_neighbors()
4919
Matus Fabian06596c52017-06-06 04:53:28 -07004920 except Exception:
4921 super(TestNAT64, cls).tearDownClass()
4922 raise
4923
4924 def test_pool(self):
4925 """ Add/delete address to NAT64 pool """
4926 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
4927
4928 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
4929
4930 addresses = self.vapi.nat64_pool_addr_dump()
4931 self.assertEqual(len(addresses), 1)
4932 self.assertEqual(addresses[0].address, nat_addr)
4933
4934 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
4935
4936 addresses = self.vapi.nat64_pool_addr_dump()
4937 self.assertEqual(len(addresses), 0)
4938
4939 def test_interface(self):
4940 """ Enable/disable NAT64 feature on the interface """
4941 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
4942 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
4943
4944 interfaces = self.vapi.nat64_interface_dump()
4945 self.assertEqual(len(interfaces), 2)
4946 pg0_found = False
4947 pg1_found = False
4948 for intf in interfaces:
4949 if intf.sw_if_index == self.pg0.sw_if_index:
4950 self.assertEqual(intf.is_inside, 1)
4951 pg0_found = True
4952 elif intf.sw_if_index == self.pg1.sw_if_index:
4953 self.assertEqual(intf.is_inside, 0)
4954 pg1_found = True
4955 self.assertTrue(pg0_found)
4956 self.assertTrue(pg1_found)
4957
4958 features = self.vapi.cli("show interface features pg0")
4959 self.assertNotEqual(features.find('nat64-in2out'), -1)
4960 features = self.vapi.cli("show interface features pg1")
4961 self.assertNotEqual(features.find('nat64-out2in'), -1)
4962
4963 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
4964 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
4965
4966 interfaces = self.vapi.nat64_interface_dump()
4967 self.assertEqual(len(interfaces), 0)
4968
4969 def test_static_bib(self):
4970 """ Add/delete static BIB entry """
4971 in_addr = socket.inet_pton(socket.AF_INET6,
4972 '2001:db8:85a3::8a2e:370:7334')
4973 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
4974 in_port = 1234
4975 out_port = 5678
4976 proto = IP_PROTOS.tcp
4977
4978 self.vapi.nat64_add_del_static_bib(in_addr,
4979 out_addr,
4980 in_port,
4981 out_port,
4982 proto)
4983 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
4984 static_bib_num = 0
4985 for bibe in bib:
4986 if bibe.is_static:
4987 static_bib_num += 1
4988 self.assertEqual(bibe.i_addr, in_addr)
4989 self.assertEqual(bibe.o_addr, out_addr)
4990 self.assertEqual(bibe.i_port, in_port)
4991 self.assertEqual(bibe.o_port, out_port)
4992 self.assertEqual(static_bib_num, 1)
4993
4994 self.vapi.nat64_add_del_static_bib(in_addr,
4995 out_addr,
4996 in_port,
4997 out_port,
4998 proto,
4999 is_add=0)
5000 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5001 static_bib_num = 0
5002 for bibe in bib:
5003 if bibe.is_static:
5004 static_bib_num += 1
5005 self.assertEqual(static_bib_num, 0)
5006
5007 def test_set_timeouts(self):
5008 """ Set NAT64 timeouts """
5009 # verify default values
5010 timeouts = self.vapi.nat64_get_timeouts()
5011 self.assertEqual(timeouts.udp, 300)
5012 self.assertEqual(timeouts.icmp, 60)
5013 self.assertEqual(timeouts.tcp_trans, 240)
5014 self.assertEqual(timeouts.tcp_est, 7440)
5015 self.assertEqual(timeouts.tcp_incoming_syn, 6)
5016
5017 # set and verify custom values
5018 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5019 tcp_est=7450, tcp_incoming_syn=10)
5020 timeouts = self.vapi.nat64_get_timeouts()
5021 self.assertEqual(timeouts.udp, 200)
5022 self.assertEqual(timeouts.icmp, 30)
5023 self.assertEqual(timeouts.tcp_trans, 250)
5024 self.assertEqual(timeouts.tcp_est, 7450)
5025 self.assertEqual(timeouts.tcp_incoming_syn, 10)
5026
5027 def test_dynamic(self):
5028 """ NAT64 dynamic translation test """
5029 self.tcp_port_in = 6303
5030 self.udp_port_in = 6304
5031 self.icmp_id_in = 6305
5032
5033 ses_num_start = self.nat64_get_ses_num()
5034
5035 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5036 self.nat_addr_n)
5037 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5038 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5039
5040 # in2out
5041 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5042 self.pg0.add_stream(pkts)
5043 self.pg_enable_capture(self.pg_interfaces)
5044 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005045 capture = self.pg1.get_capture(len(pkts))
5046 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005047 dst_ip=self.pg1.remote_ip4)
5048
5049 # out2in
5050 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5051 self.pg1.add_stream(pkts)
5052 self.pg_enable_capture(self.pg_interfaces)
5053 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005054 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005055 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5056 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5057
5058 # in2out
5059 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5060 self.pg0.add_stream(pkts)
5061 self.pg_enable_capture(self.pg_interfaces)
5062 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005063 capture = self.pg1.get_capture(len(pkts))
5064 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005065 dst_ip=self.pg1.remote_ip4)
5066
5067 # out2in
5068 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5069 self.pg1.add_stream(pkts)
5070 self.pg_enable_capture(self.pg_interfaces)
5071 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005072 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005073 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5074
5075 ses_num_end = self.nat64_get_ses_num()
5076
5077 self.assertEqual(ses_num_end - ses_num_start, 3)
5078
Matus Fabian029f3d22017-06-15 02:28:50 -07005079 # tenant with specific VRF
5080 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5081 self.vrf1_nat_addr_n,
5082 vrf_id=self.vrf1_id)
5083 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5084
5085 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5086 self.pg2.add_stream(pkts)
5087 self.pg_enable_capture(self.pg_interfaces)
5088 self.pg_start()
5089 capture = self.pg1.get_capture(len(pkts))
5090 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5091 dst_ip=self.pg1.remote_ip4)
5092
5093 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5094 self.pg1.add_stream(pkts)
5095 self.pg_enable_capture(self.pg_interfaces)
5096 self.pg_start()
5097 capture = self.pg2.get_capture(len(pkts))
5098 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5099
Matus Fabian06596c52017-06-06 04:53:28 -07005100 def test_static(self):
5101 """ NAT64 static translation test """
5102 self.tcp_port_in = 60303
5103 self.udp_port_in = 60304
5104 self.icmp_id_in = 60305
5105 self.tcp_port_out = 60303
5106 self.udp_port_out = 60304
5107 self.icmp_id_out = 60305
5108
5109 ses_num_start = self.nat64_get_ses_num()
5110
5111 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5112 self.nat_addr_n)
5113 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5114 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5115
5116 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5117 self.nat_addr_n,
5118 self.tcp_port_in,
5119 self.tcp_port_out,
5120 IP_PROTOS.tcp)
5121 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5122 self.nat_addr_n,
5123 self.udp_port_in,
5124 self.udp_port_out,
5125 IP_PROTOS.udp)
5126 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5127 self.nat_addr_n,
5128 self.icmp_id_in,
5129 self.icmp_id_out,
5130 IP_PROTOS.icmp)
5131
5132 # in2out
5133 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5134 self.pg0.add_stream(pkts)
5135 self.pg_enable_capture(self.pg_interfaces)
5136 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005137 capture = self.pg1.get_capture(len(pkts))
5138 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005139 dst_ip=self.pg1.remote_ip4, same_port=True)
5140
5141 # out2in
5142 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5143 self.pg1.add_stream(pkts)
5144 self.pg_enable_capture(self.pg_interfaces)
5145 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005146 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005147 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5148 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5149
5150 ses_num_end = self.nat64_get_ses_num()
5151
5152 self.assertEqual(ses_num_end - ses_num_start, 3)
5153
5154 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5155 def test_session_timeout(self):
5156 """ NAT64 session timeout """
5157 self.icmp_id_in = 1234
5158 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5159 self.nat_addr_n)
5160 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5161 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5162 self.vapi.nat64_set_timeouts(icmp=5)
5163
5164 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5165 self.pg0.add_stream(pkts)
5166 self.pg_enable_capture(self.pg_interfaces)
5167 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005168 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005169
5170 ses_num_before_timeout = self.nat64_get_ses_num()
5171
5172 sleep(15)
5173
5174 # ICMP session after timeout
5175 ses_num_after_timeout = self.nat64_get_ses_num()
5176 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5177
Matus Fabian732036d2017-06-08 05:24:28 -07005178 def test_icmp_error(self):
5179 """ NAT64 ICMP Error message translation """
5180 self.tcp_port_in = 6303
5181 self.udp_port_in = 6304
5182 self.icmp_id_in = 6305
5183
5184 ses_num_start = self.nat64_get_ses_num()
5185
5186 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5187 self.nat_addr_n)
5188 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5189 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5190
5191 # send some packets to create sessions
5192 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5193 self.pg0.add_stream(pkts)
5194 self.pg_enable_capture(self.pg_interfaces)
5195 self.pg_start()
5196 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005197 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005198 nat_ip=self.nat_addr,
5199 dst_ip=self.pg1.remote_ip4)
5200
5201 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5202 self.pg1.add_stream(pkts)
5203 self.pg_enable_capture(self.pg_interfaces)
5204 self.pg_start()
5205 capture_ip6 = self.pg0.get_capture(len(pkts))
5206 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5207 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5208 self.pg0.remote_ip6)
5209
5210 # in2out
5211 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5212 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5213 ICMPv6DestUnreach(code=1) /
5214 packet[IPv6] for packet in capture_ip6]
5215 self.pg0.add_stream(pkts)
5216 self.pg_enable_capture(self.pg_interfaces)
5217 self.pg_start()
5218 capture = self.pg1.get_capture(len(pkts))
5219 for packet in capture:
5220 try:
5221 self.assertEqual(packet[IP].src, self.nat_addr)
5222 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5223 self.assertEqual(packet[ICMP].type, 3)
5224 self.assertEqual(packet[ICMP].code, 13)
5225 inner = packet[IPerror]
5226 self.assertEqual(inner.src, self.pg1.remote_ip4)
5227 self.assertEqual(inner.dst, self.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005228 self.check_icmp_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005229 if inner.haslayer(TCPerror):
5230 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5231 elif inner.haslayer(UDPerror):
5232 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5233 else:
5234 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5235 except:
5236 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5237 raise
5238
5239 # out2in
5240 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5241 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5242 ICMP(type=3, code=13) /
5243 packet[IP] for packet in capture_ip4]
5244 self.pg1.add_stream(pkts)
5245 self.pg_enable_capture(self.pg_interfaces)
5246 self.pg_start()
5247 capture = self.pg0.get_capture(len(pkts))
5248 for packet in capture:
5249 try:
5250 self.assertEqual(packet[IPv6].src, ip.src)
5251 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5252 icmp = packet[ICMPv6DestUnreach]
5253 self.assertEqual(icmp.code, 1)
5254 inner = icmp[IPerror6]
5255 self.assertEqual(inner.src, self.pg0.remote_ip6)
5256 self.assertEqual(inner.dst, ip.src)
Matus Fabian029f3d22017-06-15 02:28:50 -07005257 self.check_icmpv6_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005258 if inner.haslayer(TCPerror):
5259 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5260 elif inner.haslayer(UDPerror):
5261 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5262 else:
5263 self.assertEqual(inner[ICMPv6EchoRequest].id,
5264 self.icmp_id_in)
5265 except:
5266 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5267 raise
5268
Matus Fabian029f3d22017-06-15 02:28:50 -07005269 def test_hairpinning(self):
5270 """ NAT64 hairpinning """
5271
5272 client = self.pg0.remote_hosts[0]
5273 server = self.pg0.remote_hosts[1]
5274 server_tcp_in_port = 22
5275 server_tcp_out_port = 4022
5276 server_udp_in_port = 23
5277 server_udp_out_port = 4023
5278 client_tcp_in_port = 1234
5279 client_udp_in_port = 1235
5280 client_tcp_out_port = 0
5281 client_udp_out_port = 0
5282 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5283 nat_addr_ip6 = ip.src
5284
5285 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5286 self.nat_addr_n)
5287 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5288 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5289
5290 self.vapi.nat64_add_del_static_bib(server.ip6n,
5291 self.nat_addr_n,
5292 server_tcp_in_port,
5293 server_tcp_out_port,
5294 IP_PROTOS.tcp)
5295 self.vapi.nat64_add_del_static_bib(server.ip6n,
5296 self.nat_addr_n,
5297 server_udp_in_port,
5298 server_udp_out_port,
5299 IP_PROTOS.udp)
5300
5301 # client to server
5302 pkts = []
5303 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5304 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5305 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5306 pkts.append(p)
5307 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5308 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5309 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5310 pkts.append(p)
5311 self.pg0.add_stream(pkts)
5312 self.pg_enable_capture(self.pg_interfaces)
5313 self.pg_start()
5314 capture = self.pg0.get_capture(len(pkts))
5315 for packet in capture:
5316 try:
5317 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5318 self.assertEqual(packet[IPv6].dst, server.ip6)
5319 if packet.haslayer(TCP):
5320 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5321 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
5322 self.check_tcp_checksum(packet)
5323 client_tcp_out_port = packet[TCP].sport
5324 else:
5325 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5326 self.assertEqual(packet[UDP].dport, server_udp_in_port)
5327 self.check_udp_checksum(packet)
5328 client_udp_out_port = packet[UDP].sport
5329 except:
5330 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5331 raise
5332
5333 # server to client
5334 pkts = []
5335 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5336 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5337 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5338 pkts.append(p)
5339 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5340 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5341 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5342 pkts.append(p)
5343 self.pg0.add_stream(pkts)
5344 self.pg_enable_capture(self.pg_interfaces)
5345 self.pg_start()
5346 capture = self.pg0.get_capture(len(pkts))
5347 for packet in capture:
5348 try:
5349 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5350 self.assertEqual(packet[IPv6].dst, client.ip6)
5351 if packet.haslayer(TCP):
5352 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5353 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
5354 self.check_tcp_checksum(packet)
5355 else:
5356 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5357 self.assertEqual(packet[UDP].dport, client_udp_in_port)
5358 self.check_udp_checksum(packet)
5359 except:
5360 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5361 raise
5362
5363 # ICMP error
5364 pkts = []
5365 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5366 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5367 ICMPv6DestUnreach(code=1) /
5368 packet[IPv6] for packet in capture]
5369 self.pg0.add_stream(pkts)
5370 self.pg_enable_capture(self.pg_interfaces)
5371 self.pg_start()
5372 capture = self.pg0.get_capture(len(pkts))
5373 for packet in capture:
5374 try:
5375 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5376 self.assertEqual(packet[IPv6].dst, server.ip6)
5377 icmp = packet[ICMPv6DestUnreach]
5378 self.assertEqual(icmp.code, 1)
5379 inner = icmp[IPerror6]
5380 self.assertEqual(inner.src, server.ip6)
5381 self.assertEqual(inner.dst, nat_addr_ip6)
5382 self.check_icmpv6_checksum(packet)
5383 if inner.haslayer(TCPerror):
5384 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5385 self.assertEqual(inner[TCPerror].dport,
5386 client_tcp_out_port)
5387 else:
5388 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5389 self.assertEqual(inner[UDPerror].dport,
5390 client_udp_out_port)
5391 except:
5392 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5393 raise
5394
Matus Fabian428dc912017-06-21 06:15:18 -07005395 def test_prefix(self):
5396 """ NAT64 Network-Specific Prefix """
5397
5398 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5399 self.nat_addr_n)
5400 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5401 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5402 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5403 self.vrf1_nat_addr_n,
5404 vrf_id=self.vrf1_id)
5405 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5406
5407 # Add global prefix
5408 global_pref64 = "2001:db8::"
5409 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5410 global_pref64_len = 32
5411 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5412
5413 prefix = self.vapi.nat64_prefix_dump()
5414 self.assertEqual(len(prefix), 1)
5415 self.assertEqual(prefix[0].prefix, global_pref64_n)
5416 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5417 self.assertEqual(prefix[0].vrf_id, 0)
5418
5419 # Add tenant specific prefix
5420 vrf1_pref64 = "2001:db8:122:300::"
5421 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5422 vrf1_pref64_len = 56
5423 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5424 vrf1_pref64_len,
5425 vrf_id=self.vrf1_id)
5426 prefix = self.vapi.nat64_prefix_dump()
5427 self.assertEqual(len(prefix), 2)
5428
5429 # Global prefix
5430 pkts = self.create_stream_in_ip6(self.pg0,
5431 self.pg1,
5432 pref=global_pref64,
5433 plen=global_pref64_len)
5434 self.pg0.add_stream(pkts)
5435 self.pg_enable_capture(self.pg_interfaces)
5436 self.pg_start()
5437 capture = self.pg1.get_capture(len(pkts))
5438 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5439 dst_ip=self.pg1.remote_ip4)
5440
5441 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5442 self.pg1.add_stream(pkts)
5443 self.pg_enable_capture(self.pg_interfaces)
5444 self.pg_start()
5445 capture = self.pg0.get_capture(len(pkts))
5446 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5447 global_pref64,
5448 global_pref64_len)
5449 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5450
5451 # Tenant specific prefix
5452 pkts = self.create_stream_in_ip6(self.pg2,
5453 self.pg1,
5454 pref=vrf1_pref64,
5455 plen=vrf1_pref64_len)
5456 self.pg2.add_stream(pkts)
5457 self.pg_enable_capture(self.pg_interfaces)
5458 self.pg_start()
5459 capture = self.pg1.get_capture(len(pkts))
5460 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5461 dst_ip=self.pg1.remote_ip4)
5462
5463 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5464 self.pg1.add_stream(pkts)
5465 self.pg_enable_capture(self.pg_interfaces)
5466 self.pg_start()
5467 capture = self.pg2.get_capture(len(pkts))
5468 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5469 vrf1_pref64,
5470 vrf1_pref64_len)
5471 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5472
Matus Fabianf8cd5812017-07-11 03:55:02 -07005473 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005474 """ NAT64 translate packet with unknown protocol """
5475
5476 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5477 self.nat_addr_n)
5478 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5479 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5480 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5481
5482 # in2out
5483 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5484 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5485 TCP(sport=self.tcp_port_in, dport=20))
5486 self.pg0.add_stream(p)
5487 self.pg_enable_capture(self.pg_interfaces)
5488 self.pg_start()
5489 p = self.pg1.get_capture(1)
5490
5491 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005492 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005493 GRE() /
5494 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5495 TCP(sport=1234, dport=1234))
5496 self.pg0.add_stream(p)
5497 self.pg_enable_capture(self.pg_interfaces)
5498 self.pg_start()
5499 p = self.pg1.get_capture(1)
5500 packet = p[0]
5501 try:
5502 self.assertEqual(packet[IP].src, self.nat_addr)
5503 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5504 self.assertTrue(packet.haslayer(GRE))
5505 self.check_ip_checksum(packet)
5506 except:
5507 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5508 raise
5509
5510 # out2in
5511 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5512 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5513 GRE() /
5514 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5515 TCP(sport=1234, dport=1234))
5516 self.pg1.add_stream(p)
5517 self.pg_enable_capture(self.pg_interfaces)
5518 self.pg_start()
5519 p = self.pg0.get_capture(1)
5520 packet = p[0]
5521 try:
5522 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005523 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5524 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005525 except:
5526 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5527 raise
5528
Matus Fabianf8cd5812017-07-11 03:55:02 -07005529 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005530 """ NAT64 translate packet with unknown protocol - hairpinning """
5531
5532 client = self.pg0.remote_hosts[0]
5533 server = self.pg0.remote_hosts[1]
5534 server_tcp_in_port = 22
5535 server_tcp_out_port = 4022
5536 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005537 client_tcp_out_port = 1235
5538 server_nat_ip = "10.0.0.100"
5539 client_nat_ip = "10.0.0.110"
5540 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5541 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5542 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5543 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005544
Matus Fabianf8cd5812017-07-11 03:55:02 -07005545 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5546 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005547 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5548 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5549
5550 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005551 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005552 server_tcp_in_port,
5553 server_tcp_out_port,
5554 IP_PROTOS.tcp)
5555
Matus Fabianf8cd5812017-07-11 03:55:02 -07005556 self.vapi.nat64_add_del_static_bib(server.ip6n,
5557 server_nat_ip_n,
5558 0,
5559 0,
5560 IP_PROTOS.gre)
5561
5562 self.vapi.nat64_add_del_static_bib(client.ip6n,
5563 client_nat_ip_n,
5564 client_tcp_in_port,
5565 client_tcp_out_port,
5566 IP_PROTOS.tcp)
5567
Matus Fabian7968e6c2017-07-06 05:37:49 -07005568 # client to server
5569 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005570 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005571 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5572 self.pg0.add_stream(p)
5573 self.pg_enable_capture(self.pg_interfaces)
5574 self.pg_start()
5575 p = self.pg0.get_capture(1)
5576
5577 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005578 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005579 GRE() /
5580 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5581 TCP(sport=1234, dport=1234))
5582 self.pg0.add_stream(p)
5583 self.pg_enable_capture(self.pg_interfaces)
5584 self.pg_start()
5585 p = self.pg0.get_capture(1)
5586 packet = p[0]
5587 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005588 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005589 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005590 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005591 except:
5592 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5593 raise
5594
5595 # server to client
5596 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005597 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005598 GRE() /
5599 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5600 TCP(sport=1234, dport=1234))
5601 self.pg0.add_stream(p)
5602 self.pg_enable_capture(self.pg_interfaces)
5603 self.pg_start()
5604 p = self.pg0.get_capture(1)
5605 packet = p[0]
5606 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005607 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005608 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005609 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005610 except:
5611 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5612 raise
5613
Matus Fabian36ea2d62017-10-24 04:13:49 -07005614 def test_one_armed_nat64(self):
5615 """ One armed NAT64 """
5616 external_port = 0
5617 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5618 '64:ff9b::',
5619 96)
5620
5621 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5622 self.nat_addr_n)
5623 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5624 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5625
5626 # in2out
5627 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5628 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5629 TCP(sport=12345, dport=80))
5630 self.pg3.add_stream(p)
5631 self.pg_enable_capture(self.pg_interfaces)
5632 self.pg_start()
5633 capture = self.pg3.get_capture(1)
5634 p = capture[0]
5635 try:
5636 ip = p[IP]
5637 tcp = p[TCP]
5638 self.assertEqual(ip.src, self.nat_addr)
5639 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5640 self.assertNotEqual(tcp.sport, 12345)
5641 external_port = tcp.sport
5642 self.assertEqual(tcp.dport, 80)
5643 self.check_tcp_checksum(p)
5644 self.check_ip_checksum(p)
5645 except:
5646 self.logger.error(ppp("Unexpected or invalid packet:", p))
5647 raise
5648
5649 # out2in
5650 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5651 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5652 TCP(sport=80, dport=external_port))
5653 self.pg3.add_stream(p)
5654 self.pg_enable_capture(self.pg_interfaces)
5655 self.pg_start()
5656 capture = self.pg3.get_capture(1)
5657 p = capture[0]
5658 try:
5659 ip = p[IPv6]
5660 tcp = p[TCP]
5661 self.assertEqual(ip.src, remote_host_ip6)
5662 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5663 self.assertEqual(tcp.sport, 80)
5664 self.assertEqual(tcp.dport, 12345)
5665 self.check_tcp_checksum(p)
5666 except:
5667 self.logger.error(ppp("Unexpected or invalid packet:", p))
5668 raise
5669
Matus Fabianefcd1e92017-08-15 06:59:19 -07005670 def test_frag_in_order(self):
5671 """ NAT64 translate fragments arriving in order """
5672 self.tcp_port_in = random.randint(1025, 65535)
5673
5674 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5675 self.nat_addr_n)
5676 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5677 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5678
5679 reass = self.vapi.nat_reass_dump()
5680 reass_n_start = len(reass)
5681
5682 # in2out
5683 data = 'a' * 200
5684 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5685 self.tcp_port_in, 20, data)
5686 self.pg0.add_stream(pkts)
5687 self.pg_enable_capture(self.pg_interfaces)
5688 self.pg_start()
5689 frags = self.pg1.get_capture(len(pkts))
5690 p = self.reass_frags_and_verify(frags,
5691 self.nat_addr,
5692 self.pg1.remote_ip4)
5693 self.assertEqual(p[TCP].dport, 20)
5694 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5695 self.tcp_port_out = p[TCP].sport
5696 self.assertEqual(data, p[Raw].load)
5697
5698 # out2in
5699 data = "A" * 4 + "b" * 16 + "C" * 3
5700 pkts = self.create_stream_frag(self.pg1,
5701 self.nat_addr,
5702 20,
5703 self.tcp_port_out,
5704 data)
5705 self.pg1.add_stream(pkts)
5706 self.pg_enable_capture(self.pg_interfaces)
5707 self.pg_start()
5708 frags = self.pg0.get_capture(len(pkts))
5709 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5710 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5711 self.assertEqual(p[TCP].sport, 20)
5712 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5713 self.assertEqual(data, p[Raw].load)
5714
5715 reass = self.vapi.nat_reass_dump()
5716 reass_n_end = len(reass)
5717
5718 self.assertEqual(reass_n_end - reass_n_start, 2)
5719
5720 def test_reass_hairpinning(self):
5721 """ NAT64 fragments hairpinning """
5722 data = 'a' * 200
5723 client = self.pg0.remote_hosts[0]
5724 server = self.pg0.remote_hosts[1]
5725 server_in_port = random.randint(1025, 65535)
5726 server_out_port = random.randint(1025, 65535)
5727 client_in_port = random.randint(1025, 65535)
5728 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5729 nat_addr_ip6 = ip.src
5730
5731 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5732 self.nat_addr_n)
5733 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5734 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5735
5736 # add static BIB entry for server
5737 self.vapi.nat64_add_del_static_bib(server.ip6n,
5738 self.nat_addr_n,
5739 server_in_port,
5740 server_out_port,
5741 IP_PROTOS.tcp)
5742
5743 # send packet from host to server
5744 pkts = self.create_stream_frag_ip6(self.pg0,
5745 self.nat_addr,
5746 client_in_port,
5747 server_out_port,
5748 data)
5749 self.pg0.add_stream(pkts)
5750 self.pg_enable_capture(self.pg_interfaces)
5751 self.pg_start()
5752 frags = self.pg0.get_capture(len(pkts))
5753 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5754 self.assertNotEqual(p[TCP].sport, client_in_port)
5755 self.assertEqual(p[TCP].dport, server_in_port)
5756 self.assertEqual(data, p[Raw].load)
5757
5758 def test_frag_out_of_order(self):
5759 """ NAT64 translate fragments arriving out of order """
5760 self.tcp_port_in = random.randint(1025, 65535)
5761
5762 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5763 self.nat_addr_n)
5764 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5765 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5766
5767 # in2out
5768 data = 'a' * 200
5769 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5770 self.tcp_port_in, 20, data)
5771 pkts.reverse()
5772 self.pg0.add_stream(pkts)
5773 self.pg_enable_capture(self.pg_interfaces)
5774 self.pg_start()
5775 frags = self.pg1.get_capture(len(pkts))
5776 p = self.reass_frags_and_verify(frags,
5777 self.nat_addr,
5778 self.pg1.remote_ip4)
5779 self.assertEqual(p[TCP].dport, 20)
5780 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5781 self.tcp_port_out = p[TCP].sport
5782 self.assertEqual(data, p[Raw].load)
5783
5784 # out2in
5785 data = "A" * 4 + "B" * 16 + "C" * 3
5786 pkts = self.create_stream_frag(self.pg1,
5787 self.nat_addr,
5788 20,
5789 self.tcp_port_out,
5790 data)
5791 pkts.reverse()
5792 self.pg1.add_stream(pkts)
5793 self.pg_enable_capture(self.pg_interfaces)
5794 self.pg_start()
5795 frags = self.pg0.get_capture(len(pkts))
5796 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5797 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5798 self.assertEqual(p[TCP].sport, 20)
5799 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5800 self.assertEqual(data, p[Raw].load)
5801
Matus Fabian0938dcf2017-11-08 01:59:38 -08005802 def test_interface_addr(self):
5803 """ Acquire NAT64 pool addresses from interface """
5804 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5805
5806 # no address in NAT64 pool
5807 adresses = self.vapi.nat44_address_dump()
5808 self.assertEqual(0, len(adresses))
5809
5810 # configure interface address and check NAT64 address pool
5811 self.pg4.config_ip4()
5812 addresses = self.vapi.nat64_pool_addr_dump()
5813 self.assertEqual(len(addresses), 1)
5814 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
5815
5816 # remove interface address and check NAT64 address pool
5817 self.pg4.unconfig_ip4()
5818 addresses = self.vapi.nat64_pool_addr_dump()
5819 self.assertEqual(0, len(adresses))
5820
Matus Fabiana431ad12018-01-04 04:03:14 -08005821 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5822 def test_ipfix_max_bibs_sessions(self):
5823 """ IPFIX logging maximum session and BIB entries exceeded """
5824 max_bibs = 1280
5825 max_sessions = 2560
5826 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5827 '64:ff9b::',
5828 96)
5829
5830 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5831 self.nat_addr_n)
5832 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5833 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5834
5835 pkts = []
5836 src = ""
5837 for i in range(0, max_bibs):
5838 src = "fd01:aa::%x" % (i)
5839 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5840 IPv6(src=src, dst=remote_host_ip6) /
5841 TCP(sport=12345, dport=80))
5842 pkts.append(p)
5843 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5844 IPv6(src=src, dst=remote_host_ip6) /
5845 TCP(sport=12345, dport=22))
5846 pkts.append(p)
5847 self.pg0.add_stream(pkts)
5848 self.pg_enable_capture(self.pg_interfaces)
5849 self.pg_start()
5850 self.pg1.get_capture(max_sessions)
5851
5852 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5853 src_address=self.pg3.local_ip4n,
5854 path_mtu=512,
5855 template_interval=10)
5856 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5857 src_port=self.ipfix_src_port)
5858
5859 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5860 IPv6(src=src, dst=remote_host_ip6) /
5861 TCP(sport=12345, dport=25))
5862 self.pg0.add_stream(p)
5863 self.pg_enable_capture(self.pg_interfaces)
5864 self.pg_start()
5865 self.pg1.get_capture(0)
5866 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5867 capture = self.pg3.get_capture(9)
5868 ipfix = IPFIXDecoder()
5869 # first load template
5870 for p in capture:
5871 self.assertTrue(p.haslayer(IPFIX))
5872 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5873 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5874 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5875 self.assertEqual(p[UDP].dport, 4739)
5876 self.assertEqual(p[IPFIX].observationDomainID,
5877 self.ipfix_domain_id)
5878 if p.haslayer(Template):
5879 ipfix.add_template(p.getlayer(Template))
5880 # verify events in data set
5881 for p in capture:
5882 if p.haslayer(Data):
5883 data = ipfix.decode_data_set(p.getlayer(Set))
5884 self.verify_ipfix_max_sessions(data, max_sessions)
5885
5886 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5887 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5888 TCP(sport=12345, dport=80))
5889 self.pg0.add_stream(p)
5890 self.pg_enable_capture(self.pg_interfaces)
5891 self.pg_start()
5892 self.pg1.get_capture(0)
5893 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5894 capture = self.pg3.get_capture(1)
5895 # verify events in data set
5896 for p in capture:
5897 self.assertTrue(p.haslayer(IPFIX))
5898 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5899 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5900 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5901 self.assertEqual(p[UDP].dport, 4739)
5902 self.assertEqual(p[IPFIX].observationDomainID,
5903 self.ipfix_domain_id)
5904 if p.haslayer(Data):
5905 data = ipfix.decode_data_set(p.getlayer(Set))
5906 self.verify_ipfix_max_bibs(data, max_bibs)
5907
5908 def test_ipfix_max_frags(self):
5909 """ IPFIX logging maximum fragments pending reassembly exceeded """
5910 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5911 self.nat_addr_n)
5912 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5913 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5914 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
5915 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5916 src_address=self.pg3.local_ip4n,
5917 path_mtu=512,
5918 template_interval=10)
5919 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5920 src_port=self.ipfix_src_port)
5921
5922 data = 'a' * 200
5923 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5924 self.tcp_port_in, 20, data)
5925 self.pg0.add_stream(pkts[-1])
5926 self.pg_enable_capture(self.pg_interfaces)
5927 self.pg_start()
5928 self.pg1.get_capture(0)
5929 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5930 capture = self.pg3.get_capture(9)
5931 ipfix = IPFIXDecoder()
5932 # first load template
5933 for p in capture:
5934 self.assertTrue(p.haslayer(IPFIX))
5935 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5936 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5937 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5938 self.assertEqual(p[UDP].dport, 4739)
5939 self.assertEqual(p[IPFIX].observationDomainID,
5940 self.ipfix_domain_id)
5941 if p.haslayer(Template):
5942 ipfix.add_template(p.getlayer(Template))
5943 # verify events in data set
5944 for p in capture:
5945 if p.haslayer(Data):
5946 data = ipfix.decode_data_set(p.getlayer(Set))
5947 self.verify_ipfix_max_fragments_ip6(data, 0,
5948 self.pg0.remote_ip6n)
5949
5950 def test_ipfix_bib_ses(self):
5951 """ IPFIX logging NAT64 BIB/session create and delete events """
5952 self.tcp_port_in = random.randint(1025, 65535)
5953 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5954 '64:ff9b::',
5955 96)
5956
5957 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5958 self.nat_addr_n)
5959 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5960 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5961 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5962 src_address=self.pg3.local_ip4n,
5963 path_mtu=512,
5964 template_interval=10)
5965 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5966 src_port=self.ipfix_src_port)
5967
5968 # Create
5969 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5970 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5971 TCP(sport=self.tcp_port_in, dport=25))
5972 self.pg0.add_stream(p)
5973 self.pg_enable_capture(self.pg_interfaces)
5974 self.pg_start()
5975 p = self.pg1.get_capture(1)
5976 self.tcp_port_out = p[0][TCP].sport
5977 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5978 capture = self.pg3.get_capture(10)
5979 ipfix = IPFIXDecoder()
5980 # first load template
5981 for p in capture:
5982 self.assertTrue(p.haslayer(IPFIX))
5983 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5984 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5985 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5986 self.assertEqual(p[UDP].dport, 4739)
5987 self.assertEqual(p[IPFIX].observationDomainID,
5988 self.ipfix_domain_id)
5989 if p.haslayer(Template):
5990 ipfix.add_template(p.getlayer(Template))
5991 # verify events in data set
5992 for p in capture:
5993 if p.haslayer(Data):
5994 data = ipfix.decode_data_set(p.getlayer(Set))
5995 if ord(data[0][230]) == 10:
5996 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
5997 elif ord(data[0][230]) == 6:
5998 self.verify_ipfix_nat64_ses(data,
5999 1,
6000 self.pg0.remote_ip6n,
6001 self.pg1.remote_ip4,
6002 25)
6003 else:
6004 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6005
6006 # Delete
6007 self.pg_enable_capture(self.pg_interfaces)
6008 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6009 self.nat_addr_n,
6010 is_add=0)
6011 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6012 capture = self.pg3.get_capture(2)
6013 # verify events in data set
6014 for p in capture:
6015 self.assertTrue(p.haslayer(IPFIX))
6016 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6017 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6018 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6019 self.assertEqual(p[UDP].dport, 4739)
6020 self.assertEqual(p[IPFIX].observationDomainID,
6021 self.ipfix_domain_id)
6022 if p.haslayer(Data):
6023 data = ipfix.decode_data_set(p.getlayer(Set))
6024 if ord(data[0][230]) == 11:
6025 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6026 elif ord(data[0][230]) == 7:
6027 self.verify_ipfix_nat64_ses(data,
6028 0,
6029 self.pg0.remote_ip6n,
6030 self.pg1.remote_ip4,
6031 25)
6032 else:
6033 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6034
Matus Fabian06596c52017-06-06 04:53:28 -07006035 def nat64_get_ses_num(self):
6036 """
6037 Return number of active NAT64 sessions.
6038 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006039 st = self.vapi.nat64_st_dump()
6040 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006041
6042 def clear_nat64(self):
6043 """
6044 Clear NAT64 configuration.
6045 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006046 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6047 domain_id=self.ipfix_domain_id)
6048 self.ipfix_src_port = 4739
6049 self.ipfix_domain_id = 1
6050
Matus Fabian06596c52017-06-06 04:53:28 -07006051 self.vapi.nat64_set_timeouts()
6052
6053 interfaces = self.vapi.nat64_interface_dump()
6054 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006055 if intf.is_inside > 1:
6056 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6057 0,
6058 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006059 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6060 intf.is_inside,
6061 is_add=0)
6062
Matus Fabiana431ad12018-01-04 04:03:14 -08006063 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006064 for bibe in bib:
6065 if bibe.is_static:
6066 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6067 bibe.o_addr,
6068 bibe.i_port,
6069 bibe.o_port,
6070 bibe.proto,
6071 bibe.vrf_id,
6072 is_add=0)
6073
6074 adresses = self.vapi.nat64_pool_addr_dump()
6075 for addr in adresses:
6076 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6077 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006078 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006079 is_add=0)
6080
Matus Fabian428dc912017-06-21 06:15:18 -07006081 prefixes = self.vapi.nat64_prefix_dump()
6082 for prefix in prefixes:
6083 self.vapi.nat64_add_del_prefix(prefix.prefix,
6084 prefix.prefix_len,
6085 vrf_id=prefix.vrf_id,
6086 is_add=0)
6087
Matus Fabian06596c52017-06-06 04:53:28 -07006088 def tearDown(self):
6089 super(TestNAT64, self).tearDown()
6090 if not self.vpp_dead:
6091 self.logger.info(self.vapi.cli("show nat64 pool"))
6092 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006093 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006094 self.logger.info(self.vapi.cli("show nat64 bib all"))
6095 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006096 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006097 self.clear_nat64()
6098
Matus Fabian8ebe6252017-11-06 05:04:53 -08006099
6100class TestDSlite(MethodHolder):
6101 """ DS-Lite Test Cases """
6102
6103 @classmethod
6104 def setUpClass(cls):
6105 super(TestDSlite, cls).setUpClass()
6106
6107 try:
6108 cls.nat_addr = '10.0.0.3'
6109 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6110
6111 cls.create_pg_interfaces(range(2))
6112 cls.pg0.admin_up()
6113 cls.pg0.config_ip4()
6114 cls.pg0.resolve_arp()
6115 cls.pg1.admin_up()
6116 cls.pg1.config_ip6()
6117 cls.pg1.generate_remote_hosts(2)
6118 cls.pg1.configure_ipv6_neighbors()
6119
6120 except Exception:
6121 super(TestDSlite, cls).tearDownClass()
6122 raise
6123
6124 def test_dslite(self):
6125 """ Test DS-Lite """
6126 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6127 self.nat_addr_n)
6128 aftr_ip4 = '192.0.0.1'
6129 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6130 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6131 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6132 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6133
6134 # UDP
6135 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6136 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6137 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6138 UDP(sport=20000, dport=10000))
6139 self.pg1.add_stream(p)
6140 self.pg_enable_capture(self.pg_interfaces)
6141 self.pg_start()
6142 capture = self.pg0.get_capture(1)
6143 capture = capture[0]
6144 self.assertFalse(capture.haslayer(IPv6))
6145 self.assertEqual(capture[IP].src, self.nat_addr)
6146 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6147 self.assertNotEqual(capture[UDP].sport, 20000)
6148 self.assertEqual(capture[UDP].dport, 10000)
6149 self.check_ip_checksum(capture)
6150 out_port = capture[UDP].sport
6151
6152 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6153 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6154 UDP(sport=10000, dport=out_port))
6155 self.pg0.add_stream(p)
6156 self.pg_enable_capture(self.pg_interfaces)
6157 self.pg_start()
6158 capture = self.pg1.get_capture(1)
6159 capture = capture[0]
6160 self.assertEqual(capture[IPv6].src, aftr_ip6)
6161 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6162 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6163 self.assertEqual(capture[IP].dst, '192.168.1.1')
6164 self.assertEqual(capture[UDP].sport, 10000)
6165 self.assertEqual(capture[UDP].dport, 20000)
6166 self.check_ip_checksum(capture)
6167
6168 # TCP
6169 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6170 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6171 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6172 TCP(sport=20001, dport=10001))
6173 self.pg1.add_stream(p)
6174 self.pg_enable_capture(self.pg_interfaces)
6175 self.pg_start()
6176 capture = self.pg0.get_capture(1)
6177 capture = capture[0]
6178 self.assertFalse(capture.haslayer(IPv6))
6179 self.assertEqual(capture[IP].src, self.nat_addr)
6180 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6181 self.assertNotEqual(capture[TCP].sport, 20001)
6182 self.assertEqual(capture[TCP].dport, 10001)
6183 self.check_ip_checksum(capture)
6184 self.check_tcp_checksum(capture)
6185 out_port = capture[TCP].sport
6186
6187 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6188 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6189 TCP(sport=10001, dport=out_port))
6190 self.pg0.add_stream(p)
6191 self.pg_enable_capture(self.pg_interfaces)
6192 self.pg_start()
6193 capture = self.pg1.get_capture(1)
6194 capture = capture[0]
6195 self.assertEqual(capture[IPv6].src, aftr_ip6)
6196 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6197 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6198 self.assertEqual(capture[IP].dst, '192.168.1.1')
6199 self.assertEqual(capture[TCP].sport, 10001)
6200 self.assertEqual(capture[TCP].dport, 20001)
6201 self.check_ip_checksum(capture)
6202 self.check_tcp_checksum(capture)
6203
6204 # ICMP
6205 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6206 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6207 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6208 ICMP(id=4000, type='echo-request'))
6209 self.pg1.add_stream(p)
6210 self.pg_enable_capture(self.pg_interfaces)
6211 self.pg_start()
6212 capture = self.pg0.get_capture(1)
6213 capture = capture[0]
6214 self.assertFalse(capture.haslayer(IPv6))
6215 self.assertEqual(capture[IP].src, self.nat_addr)
6216 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6217 self.assertNotEqual(capture[ICMP].id, 4000)
6218 self.check_ip_checksum(capture)
6219 self.check_icmp_checksum(capture)
6220 out_id = capture[ICMP].id
6221
6222 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6223 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6224 ICMP(id=out_id, type='echo-reply'))
6225 self.pg0.add_stream(p)
6226 self.pg_enable_capture(self.pg_interfaces)
6227 self.pg_start()
6228 capture = self.pg1.get_capture(1)
6229 capture = capture[0]
6230 self.assertEqual(capture[IPv6].src, aftr_ip6)
6231 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6232 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6233 self.assertEqual(capture[IP].dst, '192.168.1.1')
6234 self.assertEqual(capture[ICMP].id, 4000)
6235 self.check_ip_checksum(capture)
6236 self.check_icmp_checksum(capture)
6237
Matus Fabian331acc62017-12-08 03:38:51 -08006238 # ping DS-Lite AFTR tunnel endpoint address
6239 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6240 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6241 ICMPv6EchoRequest())
6242 self.pg1.add_stream(p)
6243 self.pg_enable_capture(self.pg_interfaces)
6244 self.pg_start()
6245 capture = self.pg1.get_capture(1)
6246 self.assertEqual(1, len(capture))
6247 capture = capture[0]
6248 self.assertEqual(capture[IPv6].src, aftr_ip6)
6249 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6250 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6251
Matus Fabian8ebe6252017-11-06 05:04:53 -08006252 def tearDown(self):
6253 super(TestDSlite, self).tearDown()
6254 if not self.vpp_dead:
6255 self.logger.info(self.vapi.cli("show dslite pool"))
6256 self.logger.info(
6257 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6258 self.logger.info(self.vapi.cli("show dslite sessions"))
6259
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006260
6261class TestDSliteCE(MethodHolder):
6262 """ DS-Lite CE Test Cases """
6263
6264 @classmethod
6265 def setUpConstants(cls):
6266 super(TestDSliteCE, cls).setUpConstants()
6267 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6268
6269 @classmethod
6270 def setUpClass(cls):
6271 super(TestDSliteCE, cls).setUpClass()
6272
6273 try:
6274 cls.create_pg_interfaces(range(2))
6275 cls.pg0.admin_up()
6276 cls.pg0.config_ip4()
6277 cls.pg0.resolve_arp()
6278 cls.pg1.admin_up()
6279 cls.pg1.config_ip6()
6280 cls.pg1.generate_remote_hosts(1)
6281 cls.pg1.configure_ipv6_neighbors()
6282
6283 except Exception:
6284 super(TestDSliteCE, cls).tearDownClass()
6285 raise
6286
6287 def test_dslite_ce(self):
6288 """ Test DS-Lite CE """
6289
6290 b4_ip4 = '192.0.0.2'
6291 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6292 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6293 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6294 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6295
6296 aftr_ip4 = '192.0.0.1'
6297 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6298 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6299 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6300 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6301
6302 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6303 dst_address_length=128,
6304 next_hop_address=self.pg1.remote_ip6n,
6305 next_hop_sw_if_index=self.pg1.sw_if_index,
6306 is_ipv6=1)
6307
6308 # UDP encapsulation
6309 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6310 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6311 UDP(sport=10000, dport=20000))
6312 self.pg0.add_stream(p)
6313 self.pg_enable_capture(self.pg_interfaces)
6314 self.pg_start()
6315 capture = self.pg1.get_capture(1)
6316 capture = capture[0]
6317 self.assertEqual(capture[IPv6].src, b4_ip6)
6318 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6319 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6320 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6321 self.assertEqual(capture[UDP].sport, 10000)
6322 self.assertEqual(capture[UDP].dport, 20000)
6323 self.check_ip_checksum(capture)
6324
6325 # UDP decapsulation
6326 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6327 IPv6(dst=b4_ip6, src=aftr_ip6) /
6328 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6329 UDP(sport=20000, dport=10000))
6330 self.pg1.add_stream(p)
6331 self.pg_enable_capture(self.pg_interfaces)
6332 self.pg_start()
6333 capture = self.pg0.get_capture(1)
6334 capture = capture[0]
6335 self.assertFalse(capture.haslayer(IPv6))
6336 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6337 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6338 self.assertEqual(capture[UDP].sport, 20000)
6339 self.assertEqual(capture[UDP].dport, 10000)
6340 self.check_ip_checksum(capture)
6341
6342 # ping DS-Lite B4 tunnel endpoint address
6343 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6344 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6345 ICMPv6EchoRequest())
6346 self.pg1.add_stream(p)
6347 self.pg_enable_capture(self.pg_interfaces)
6348 self.pg_start()
6349 capture = self.pg1.get_capture(1)
6350 self.assertEqual(1, len(capture))
6351 capture = capture[0]
6352 self.assertEqual(capture[IPv6].src, b4_ip6)
6353 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6354 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6355
6356 def tearDown(self):
6357 super(TestDSliteCE, self).tearDown()
6358 if not self.vpp_dead:
6359 self.logger.info(
6360 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6361 self.logger.info(
6362 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6363
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006364
6365class TestNAT66(MethodHolder):
6366 """ NAT66 Test Cases """
6367
6368 @classmethod
6369 def setUpClass(cls):
6370 super(TestNAT66, cls).setUpClass()
6371
6372 try:
6373 cls.nat_addr = 'fd01:ff::2'
6374 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6375
6376 cls.create_pg_interfaces(range(2))
6377 cls.interfaces = list(cls.pg_interfaces)
6378
6379 for i in cls.interfaces:
6380 i.admin_up()
6381 i.config_ip6()
6382 i.configure_ipv6_neighbors()
6383
6384 except Exception:
6385 super(TestNAT66, cls).tearDownClass()
6386 raise
6387
6388 def test_static(self):
6389 """ 1:1 NAT66 test """
6390 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6391 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6392 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6393 self.nat_addr_n)
6394
6395 # in2out
6396 pkts = []
6397 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6398 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6399 TCP())
6400 pkts.append(p)
6401 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6402 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6403 UDP())
6404 pkts.append(p)
6405 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6406 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6407 ICMPv6EchoRequest())
6408 pkts.append(p)
6409 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6410 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6411 GRE() / IP() / TCP())
6412 pkts.append(p)
6413 self.pg0.add_stream(pkts)
6414 self.pg_enable_capture(self.pg_interfaces)
6415 self.pg_start()
6416 capture = self.pg1.get_capture(len(pkts))
6417 for packet in capture:
6418 try:
6419 self.assertEqual(packet[IPv6].src, self.nat_addr)
6420 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6421 if packet.haslayer(TCP):
6422 self.check_tcp_checksum(packet)
6423 elif packet.haslayer(UDP):
6424 self.check_udp_checksum(packet)
6425 elif packet.haslayer(ICMPv6EchoRequest):
6426 self.check_icmpv6_checksum(packet)
6427 except:
6428 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6429 raise
6430
6431 # out2in
6432 pkts = []
6433 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6434 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6435 TCP())
6436 pkts.append(p)
6437 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6438 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6439 UDP())
6440 pkts.append(p)
6441 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6442 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6443 ICMPv6EchoReply())
6444 pkts.append(p)
6445 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6446 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6447 GRE() / IP() / TCP())
6448 pkts.append(p)
6449 self.pg1.add_stream(pkts)
6450 self.pg_enable_capture(self.pg_interfaces)
6451 self.pg_start()
6452 capture = self.pg0.get_capture(len(pkts))
6453 for packet in capture:
6454 try:
6455 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6456 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6457 if packet.haslayer(TCP):
6458 self.check_tcp_checksum(packet)
6459 elif packet.haslayer(UDP):
6460 self.check_udp_checksum(packet)
6461 elif packet.haslayer(ICMPv6EchoReply):
6462 self.check_icmpv6_checksum(packet)
6463 except:
6464 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6465 raise
6466
6467 sm = self.vapi.nat66_static_mapping_dump()
6468 self.assertEqual(len(sm), 1)
6469 self.assertEqual(sm[0].total_pkts, 8)
6470
Juraj Sloboda9341e342018-04-13 12:00:46 +02006471 def test_check_no_translate(self):
6472 """ NAT66 translate only when egress interface is outside interface """
6473 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6474 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6475 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6476 self.nat_addr_n)
6477
6478 # in2out
6479 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6480 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6481 UDP())
6482 self.pg0.add_stream([p])
6483 self.pg_enable_capture(self.pg_interfaces)
6484 self.pg_start()
6485 capture = self.pg1.get_capture(1)
6486 packet = capture[0]
6487 try:
6488 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6489 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6490 except:
6491 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6492 raise
6493
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006494 def clear_nat66(self):
6495 """
6496 Clear NAT66 configuration.
6497 """
6498 interfaces = self.vapi.nat66_interface_dump()
6499 for intf in interfaces:
6500 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6501 intf.is_inside,
6502 is_add=0)
6503
6504 static_mappings = self.vapi.nat66_static_mapping_dump()
6505 for sm in static_mappings:
6506 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6507 sm.external_ip_address,
6508 sm.vrf_id,
6509 is_add=0)
6510
6511 def tearDown(self):
6512 super(TestNAT66, self).tearDown()
6513 if not self.vpp_dead:
6514 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6515 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6516 self.clear_nat66()
6517
Matus Fabiande886752016-12-07 03:38:19 -08006518if __name__ == '__main__':
6519 unittest.main(testRunner=VppTestRunner)