blob: 7c841f515c4f4f6ce394a4aff2afbdd7a602c089 [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 Fabianebdf1902018-05-04 03:57:42 -0700696 def initiate_tcp_session(self, in_if, out_if):
697 """
698 Initiates TCP session
699
700 :param in_if: Inside interface
701 :param out_if: Outside interface
702 """
703 try:
704 # SYN packet in->out
705 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
706 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
707 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
708 flags="S"))
709 in_if.add_stream(p)
710 self.pg_enable_capture(self.pg_interfaces)
711 self.pg_start()
712 capture = out_if.get_capture(1)
713 p = capture[0]
714 self.tcp_port_out = p[TCP].sport
715
716 # SYN + ACK packet out->in
717 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
718 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
719 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
720 flags="SA"))
721 out_if.add_stream(p)
722 self.pg_enable_capture(self.pg_interfaces)
723 self.pg_start()
724 in_if.get_capture(1)
725
726 # ACK packet in->out
727 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
728 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
729 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
730 flags="A"))
731 in_if.add_stream(p)
732 self.pg_enable_capture(self.pg_interfaces)
733 self.pg_start()
734 out_if.get_capture(1)
735
736 except:
737 self.logger.error("TCP 3 way handshake failed")
738 raise
739
Matus Fabianeea28d72017-01-13 04:15:54 -0800740 def verify_ipfix_nat44_ses(self, data):
741 """
742 Verify IPFIX NAT44 session create/delete event
743
744 :param data: Decoded IPFIX data records
745 """
746 nat44_ses_create_num = 0
747 nat44_ses_delete_num = 0
748 self.assertEqual(6, len(data))
749 for record in data:
750 # natEvent
751 self.assertIn(ord(record[230]), [4, 5])
752 if ord(record[230]) == 4:
753 nat44_ses_create_num += 1
754 else:
755 nat44_ses_delete_num += 1
756 # sourceIPv4Address
757 self.assertEqual(self.pg0.remote_ip4n, record[8])
758 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700759 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800760 record[225])
761 # ingressVRFID
762 self.assertEqual(struct.pack("!I", 0), record[234])
763 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
764 if IP_PROTOS.icmp == ord(record[4]):
765 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
766 self.assertEqual(struct.pack("!H", self.icmp_id_out),
767 record[227])
768 elif IP_PROTOS.tcp == ord(record[4]):
769 self.assertEqual(struct.pack("!H", self.tcp_port_in),
770 record[7])
771 self.assertEqual(struct.pack("!H", self.tcp_port_out),
772 record[227])
773 elif IP_PROTOS.udp == ord(record[4]):
774 self.assertEqual(struct.pack("!H", self.udp_port_in),
775 record[7])
776 self.assertEqual(struct.pack("!H", self.udp_port_out),
777 record[227])
778 else:
779 self.fail("Invalid protocol")
780 self.assertEqual(3, nat44_ses_create_num)
781 self.assertEqual(3, nat44_ses_delete_num)
782
783 def verify_ipfix_addr_exhausted(self, data):
784 """
785 Verify IPFIX NAT addresses event
786
787 :param data: Decoded IPFIX data records
788 """
789 self.assertEqual(1, len(data))
790 record = data[0]
791 # natEvent
792 self.assertEqual(ord(record[230]), 3)
793 # natPoolID
794 self.assertEqual(struct.pack("!I", 0), record[283])
795
Matus Fabiana431ad12018-01-04 04:03:14 -0800796 def verify_ipfix_max_sessions(self, data, limit):
797 """
798 Verify IPFIX maximum session entries exceeded event
799
800 :param data: Decoded IPFIX data records
801 :param limit: Number of maximum session entries that can be created.
802 """
803 self.assertEqual(1, len(data))
804 record = data[0]
805 # natEvent
806 self.assertEqual(ord(record[230]), 13)
807 # natQuotaExceededEvent
808 self.assertEqual(struct.pack("I", 1), record[466])
809 # maxSessionEntries
810 self.assertEqual(struct.pack("I", limit), record[471])
811
812 def verify_ipfix_max_bibs(self, data, limit):
813 """
814 Verify IPFIX maximum BIB entries exceeded event
815
816 :param data: Decoded IPFIX data records
817 :param limit: Number of maximum BIB entries that can be created.
818 """
819 self.assertEqual(1, len(data))
820 record = data[0]
821 # natEvent
822 self.assertEqual(ord(record[230]), 13)
823 # natQuotaExceededEvent
824 self.assertEqual(struct.pack("I", 2), record[466])
825 # maxBIBEntries
826 self.assertEqual(struct.pack("I", limit), record[472])
827
828 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
829 """
830 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
831
832 :param data: Decoded IPFIX data records
833 :param limit: Number of maximum fragments pending reassembly
834 :param src_addr: IPv6 source address
835 """
836 self.assertEqual(1, len(data))
837 record = data[0]
838 # natEvent
839 self.assertEqual(ord(record[230]), 13)
840 # natQuotaExceededEvent
841 self.assertEqual(struct.pack("I", 5), record[466])
842 # maxFragmentsPendingReassembly
843 self.assertEqual(struct.pack("I", limit), record[475])
844 # sourceIPv6Address
845 self.assertEqual(src_addr, record[27])
846
847 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
848 """
849 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
850
851 :param data: Decoded IPFIX data records
852 :param limit: Number of maximum fragments pending reassembly
853 :param src_addr: IPv4 source address
854 """
855 self.assertEqual(1, len(data))
856 record = data[0]
857 # natEvent
858 self.assertEqual(ord(record[230]), 13)
859 # natQuotaExceededEvent
860 self.assertEqual(struct.pack("I", 5), record[466])
861 # maxFragmentsPendingReassembly
862 self.assertEqual(struct.pack("I", limit), record[475])
863 # sourceIPv4Address
864 self.assertEqual(src_addr, record[8])
865
866 def verify_ipfix_bib(self, data, is_create, src_addr):
867 """
868 Verify IPFIX NAT64 BIB create and delete events
869
870 :param data: Decoded IPFIX data records
871 :param is_create: Create event if nonzero value otherwise delete event
872 :param src_addr: IPv6 source address
873 """
874 self.assertEqual(1, len(data))
875 record = data[0]
876 # natEvent
877 if is_create:
878 self.assertEqual(ord(record[230]), 10)
879 else:
880 self.assertEqual(ord(record[230]), 11)
881 # sourceIPv6Address
882 self.assertEqual(src_addr, record[27])
883 # postNATSourceIPv4Address
884 self.assertEqual(self.nat_addr_n, record[225])
885 # protocolIdentifier
886 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
887 # ingressVRFID
888 self.assertEqual(struct.pack("!I", 0), record[234])
889 # sourceTransportPort
890 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
891 # postNAPTSourceTransportPort
892 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
893
894 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
895 dst_port):
896 """
897 Verify IPFIX NAT64 session create and delete events
898
899 :param data: Decoded IPFIX data records
900 :param is_create: Create event if nonzero value otherwise delete event
901 :param src_addr: IPv6 source address
902 :param dst_addr: IPv4 destination address
903 :param dst_port: destination TCP port
904 """
905 self.assertEqual(1, len(data))
906 record = data[0]
907 # natEvent
908 if is_create:
909 self.assertEqual(ord(record[230]), 6)
910 else:
911 self.assertEqual(ord(record[230]), 7)
912 # sourceIPv6Address
913 self.assertEqual(src_addr, record[27])
914 # destinationIPv6Address
915 self.assertEqual(socket.inet_pton(socket.AF_INET6,
916 self.compose_ip6(dst_addr,
917 '64:ff9b::',
918 96)),
919 record[28])
920 # postNATSourceIPv4Address
921 self.assertEqual(self.nat_addr_n, record[225])
922 # postNATDestinationIPv4Address
923 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
924 record[226])
925 # protocolIdentifier
926 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
927 # ingressVRFID
928 self.assertEqual(struct.pack("!I", 0), record[234])
929 # sourceTransportPort
930 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
931 # postNAPTSourceTransportPort
932 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
933 # destinationTransportPort
934 self.assertEqual(struct.pack("!H", dst_port), record[11])
935 # postNAPTDestinationTransportPort
936 self.assertEqual(struct.pack("!H", dst_port), record[228])
937
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700938
Matus Fabian2ba92e32017-08-21 07:05:03 -0700939class TestNAT44(MethodHolder):
940 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700941
942 @classmethod
943 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -0700944 super(TestNAT44, cls).setUpClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700945
946 try:
947 cls.tcp_port_in = 6303
948 cls.tcp_port_out = 6303
949 cls.udp_port_in = 6304
950 cls.udp_port_out = 6304
951 cls.icmp_id_in = 6305
952 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -0700953 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +0100954 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700955 cls.ipfix_src_port = 4739
956 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -0700957 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700958
Matus Fabian36ea2d62017-10-24 04:13:49 -0700959 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700960 cls.interfaces = list(cls.pg_interfaces[0:4])
961
962 for i in cls.interfaces:
963 i.admin_up()
964 i.config_ip4()
965 i.resolve_arp()
966
Matus Fabian6fa74c62017-06-05 05:55:48 -0700967 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700968 cls.pg0.configure_ipv4_neighbors()
969
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200970 cls.pg1.generate_remote_hosts(1)
971 cls.pg1.configure_ipv4_neighbors()
972
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700973 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -0700974 cls.vapi.ip_table_add_del(10, is_add=1)
975 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700976
977 cls.pg4._local_ip4 = "172.16.255.1"
978 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
979 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
980 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -0700981 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700982 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -0700983 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700984 cls.pg5.set_table_ip4(10)
985 cls.pg6._local_ip4 = "172.16.255.1"
986 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
987 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
988 cls.pg6.set_table_ip4(20)
989 for i in cls.overlapping_interfaces:
990 i.config_ip4()
991 i.admin_up()
992 i.resolve_arp()
993
994 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -0700995 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700996
Matus Fabian36ea2d62017-10-24 04:13:49 -0700997 cls.pg9.generate_remote_hosts(2)
998 cls.pg9.config_ip4()
999 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1000 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1001 ip_addr_n,
1002 24)
1003 cls.pg9.admin_up()
1004 cls.pg9.resolve_arp()
1005 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1006 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1007 cls.pg9.resolve_arp()
1008
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001009 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001010 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001011 raise
1012
Matus Fabian2ba92e32017-08-21 07:05:03 -07001013 def clear_nat44(self):
Matus Fabiande886752016-12-07 03:38:19 -08001014 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001015 Clear NAT44 configuration.
Matus Fabiande886752016-12-07 03:38:19 -08001016 """
Martin Gálik406eb1d2017-05-04 04:35:04 -07001017 # I found no elegant way to do this
1018 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
1019 dst_address_length=32,
1020 next_hop_address=self.pg7.remote_ip4n,
1021 next_hop_sw_if_index=self.pg7.sw_if_index,
1022 is_add=0)
1023 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
1024 dst_address_length=32,
1025 next_hop_address=self.pg8.remote_ip4n,
1026 next_hop_sw_if_index=self.pg8.sw_if_index,
1027 is_add=0)
1028
1029 for intf in [self.pg7, self.pg8]:
1030 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
1031 for n in neighbors:
1032 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
1033 n.mac_address,
1034 n.ip_address,
1035 is_add=0)
1036
Matus Fabian36532bd2017-01-23 23:42:28 -08001037 if self.pg7.has_ip4_config:
1038 self.pg7.unconfig_ip4()
1039
Matus Fabian240b5ef2018-01-11 04:09:17 -08001040 self.vapi.nat44_forwarding_enable_disable(0)
1041
Matus Fabian2ba92e32017-08-21 07:05:03 -07001042 interfaces = self.vapi.nat44_interface_addr_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08001043 for intf in interfaces:
Matus Fabianb932d262017-12-18 05:38:24 -08001044 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
1045 twice_nat=intf.twice_nat,
1046 is_add=0)
Matus Fabian8bf68e82017-01-12 04:24:35 -08001047
Matus Fabian2ba92e32017-08-21 07:05:03 -07001048 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
1049 domain_id=self.ipfix_domain_id)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001050 self.ipfix_src_port = 4739
1051 self.ipfix_domain_id = 1
Matus Fabianeea28d72017-01-13 04:15:54 -08001052
Matus Fabian2ba92e32017-08-21 07:05:03 -07001053 interfaces = self.vapi.nat44_interface_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001054 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07001055 if intf.is_inside > 1:
1056 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
1057 0,
1058 is_add=0)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001059 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
1060 intf.is_inside,
1061 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001062
Matus Fabian2ba92e32017-08-21 07:05:03 -07001063 interfaces = self.vapi.nat44_interface_output_feature_dump()
Matus Fabian93d84c92017-07-19 08:06:01 -07001064 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001065 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
1066 intf.is_inside,
1067 is_add=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07001068
Matus Fabian2ba92e32017-08-21 07:05:03 -07001069 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001070 for sm in static_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001071 self.vapi.nat44_add_del_static_mapping(
1072 sm.local_ip_address,
1073 sm.external_ip_address,
1074 local_port=sm.local_port,
1075 external_port=sm.external_port,
1076 addr_only=sm.addr_only,
1077 vrf_id=sm.vrf_id,
1078 protocol=sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001079 twice_nat=sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001080 self_twice_nat=sm.self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001081 out2in_only=sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001082 tag=sm.tag,
Matus Fabianea2600a2018-03-28 04:06:26 -07001083 external_sw_if_index=sm.external_sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001084 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001085
Matus Fabian704018c2017-09-04 02:17:18 -07001086 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
1087 for lb_sm in lb_static_mappings:
1088 self.vapi.nat44_add_del_lb_static_mapping(
1089 lb_sm.external_addr,
1090 lb_sm.external_port,
1091 lb_sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001092 vrf_id=lb_sm.vrf_id,
1093 twice_nat=lb_sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001094 self_twice_nat=lb_sm.self_twice_nat,
Matus Fabian240b5ef2018-01-11 04:09:17 -08001095 out2in_only=lb_sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001096 tag=lb_sm.tag,
Ole Troan895b6e82017-10-20 13:28:20 +02001097 is_add=0,
1098 local_num=0,
1099 locals=[])
Matus Fabian704018c2017-09-04 02:17:18 -07001100
Matus Fabianab7a8052017-11-28 04:29:41 -08001101 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1102 for id_m in identity_mappings:
1103 self.vapi.nat44_add_del_identity_mapping(
1104 addr_only=id_m.addr_only,
1105 ip=id_m.ip_address,
1106 port=id_m.port,
1107 sw_if_index=id_m.sw_if_index,
1108 vrf_id=id_m.vrf_id,
1109 protocol=id_m.protocol,
1110 is_add=0)
1111
Matus Fabian2ba92e32017-08-21 07:05:03 -07001112 adresses = self.vapi.nat44_address_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001113 for addr in adresses:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001114 self.vapi.nat44_add_del_address_range(addr.ip_address,
1115 addr.ip_address,
Matus Fabianb932d262017-12-18 05:38:24 -08001116 twice_nat=addr.twice_nat,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001117 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001118
Matus Fabianefcd1e92017-08-15 06:59:19 -07001119 self.vapi.nat_set_reass()
1120 self.vapi.nat_set_reass(is_ip6=1)
1121
Matus Fabian2ba92e32017-08-21 07:05:03 -07001122 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1123 local_port=0, external_port=0, vrf_id=0,
1124 is_add=1, external_sw_if_index=0xFFFFFFFF,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001125 proto=0, twice_nat=0, self_twice_nat=0,
1126 out2in_only=0, tag=""):
Matus Fabiande886752016-12-07 03:38:19 -08001127 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001128 Add/delete NAT44 static mapping
Matus Fabiande886752016-12-07 03:38:19 -08001129
1130 :param local_ip: Local IP address
1131 :param external_ip: External IP address
1132 :param local_port: Local port number (Optional)
1133 :param external_port: External port number (Optional)
1134 :param vrf_id: VRF ID (Default 0)
1135 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabian36532bd2017-01-23 23:42:28 -08001136 :param external_sw_if_index: External interface instead of IP address
Matus Fabian09d96f42017-02-02 01:43:00 -08001137 :param proto: IP protocol (Mandatory if port specified)
Matus Fabianb932d262017-12-18 05:38:24 -08001138 :param twice_nat: 1 if translate external host address and port
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001139 :param self_twice_nat: 1 if translate external host address and port
1140 whenever external host address equals
1141 local address of internal host
Matus Fabiane82488f2018-01-18 03:38:45 -08001142 :param out2in_only: if 1 rule is matching only out2in direction
Matus Fabian5f224992018-01-25 21:59:16 -08001143 :param tag: Opaque string tag
Matus Fabiande886752016-12-07 03:38:19 -08001144 """
1145 addr_only = 1
1146 if local_port and external_port:
1147 addr_only = 0
1148 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1149 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001150 self.vapi.nat44_add_del_static_mapping(
Klement Sekerada505f62017-01-04 12:58:53 +01001151 l_ip,
1152 e_ip,
Matus Fabian36532bd2017-01-23 23:42:28 -08001153 external_sw_if_index,
Klement Sekerada505f62017-01-04 12:58:53 +01001154 local_port,
1155 external_port,
1156 addr_only,
1157 vrf_id,
Matus Fabian09d96f42017-02-02 01:43:00 -08001158 proto,
Matus Fabianb932d262017-12-18 05:38:24 -08001159 twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001160 self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001161 out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001162 tag,
Klement Sekerada505f62017-01-04 12:58:53 +01001163 is_add)
Matus Fabiande886752016-12-07 03:38:19 -08001164
Matus Fabianb932d262017-12-18 05:38:24 -08001165 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
Matus Fabiande886752016-12-07 03:38:19 -08001166 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001167 Add/delete NAT44 address
Matus Fabiande886752016-12-07 03:38:19 -08001168
1169 :param ip: IP address
1170 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabianb932d262017-12-18 05:38:24 -08001171 :param twice_nat: twice NAT address for extenal hosts
Matus Fabiande886752016-12-07 03:38:19 -08001172 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001173 nat_addr = socket.inet_pton(socket.AF_INET, ip)
1174 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
Matus Fabianb932d262017-12-18 05:38:24 -08001175 vrf_id=vrf_id,
1176 twice_nat=twice_nat)
Matus Fabiande886752016-12-07 03:38:19 -08001177
1178 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001179 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001180
Matus Fabian2ba92e32017-08-21 07:05:03 -07001181 self.nat44_add_address(self.nat_addr)
1182 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1183 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1184 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001185
1186 # in2out
1187 pkts = self.create_stream_in(self.pg0, self.pg1)
1188 self.pg0.add_stream(pkts)
1189 self.pg_enable_capture(self.pg_interfaces)
1190 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001191 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001192 self.verify_capture_out(capture)
1193
1194 # out2in
1195 pkts = self.create_stream_out(self.pg1)
1196 self.pg1.add_stream(pkts)
1197 self.pg_enable_capture(self.pg_interfaces)
1198 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001199 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001200 self.verify_capture_in(capture, self.pg0)
1201
Juraj Slobodab33f4132017-02-08 23:54:21 -08001202 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001203 """ NAT44 handling of client packets with TTL=1 """
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=1)
1212 self.pg0.add_stream(pkts)
1213 self.pg_enable_capture(self.pg_interfaces)
1214 self.pg_start()
1215
1216 # Client side - verify ICMP type 11 packets
1217 capture = self.pg0.get_capture(len(pkts))
1218 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1219
1220 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001221 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001222
Matus Fabian2ba92e32017-08-21 07:05:03 -07001223 self.nat44_add_address(self.nat_addr)
1224 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1225 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1226 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001227
1228 # Client side - create sessions
1229 pkts = self.create_stream_in(self.pg0, self.pg1)
1230 self.pg0.add_stream(pkts)
1231 self.pg_enable_capture(self.pg_interfaces)
1232 self.pg_start()
1233
1234 # Server side - generate traffic
1235 capture = self.pg1.get_capture(len(pkts))
1236 self.verify_capture_out(capture)
1237 pkts = self.create_stream_out(self.pg1, ttl=1)
1238 self.pg1.add_stream(pkts)
1239 self.pg_enable_capture(self.pg_interfaces)
1240 self.pg_start()
1241
1242 # Server side - verify ICMP type 11 packets
1243 capture = self.pg1.get_capture(len(pkts))
1244 self.verify_capture_out_with_icmp_errors(capture,
1245 src_ip=self.pg1.local_ip4)
1246
1247 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001248 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001249
Matus Fabian2ba92e32017-08-21 07:05:03 -07001250 self.nat44_add_address(self.nat_addr)
1251 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1252 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1253 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001254
1255 # Client side - generate traffic
1256 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1257 self.pg0.add_stream(pkts)
1258 self.pg_enable_capture(self.pg_interfaces)
1259 self.pg_start()
1260
1261 # Server side - simulate ICMP type 11 response
1262 capture = self.pg1.get_capture(len(pkts))
1263 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001264 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001265 ICMP(type=11) / packet[IP] for packet in capture]
1266 self.pg1.add_stream(pkts)
1267 self.pg_enable_capture(self.pg_interfaces)
1268 self.pg_start()
1269
1270 # Client side - verify ICMP type 11 packets
1271 capture = self.pg0.get_capture(len(pkts))
1272 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1273
1274 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001275 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001276
Matus Fabian2ba92e32017-08-21 07:05:03 -07001277 self.nat44_add_address(self.nat_addr)
1278 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1279 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1280 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001281
1282 # Client side - create sessions
1283 pkts = self.create_stream_in(self.pg0, self.pg1)
1284 self.pg0.add_stream(pkts)
1285 self.pg_enable_capture(self.pg_interfaces)
1286 self.pg_start()
1287
1288 # Server side - generate traffic
1289 capture = self.pg1.get_capture(len(pkts))
1290 self.verify_capture_out(capture)
1291 pkts = self.create_stream_out(self.pg1, ttl=2)
1292 self.pg1.add_stream(pkts)
1293 self.pg_enable_capture(self.pg_interfaces)
1294 self.pg_start()
1295
1296 # Client side - simulate ICMP type 11 response
1297 capture = self.pg0.get_capture(len(pkts))
1298 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1299 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1300 ICMP(type=11) / packet[IP] for packet in capture]
1301 self.pg0.add_stream(pkts)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304
1305 # Server side - verify ICMP type 11 packets
1306 capture = self.pg1.get_capture(len(pkts))
1307 self.verify_capture_out_with_icmp_errors(capture)
1308
Juraj Sloboda665e4822017-02-16 17:17:19 -08001309 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001310 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001311
Matus Fabian2ba92e32017-08-21 07:05:03 -07001312 self.nat44_add_address(self.nat_addr)
1313 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1314 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1315 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001316
1317 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1318 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1319 ICMP(id=self.icmp_id_out, type='echo-request'))
1320 pkts = [p]
1321 self.pg1.add_stream(pkts)
1322 self.pg_enable_capture(self.pg_interfaces)
1323 self.pg_start()
1324 capture = self.pg1.get_capture(len(pkts))
1325 self.assertEqual(1, len(capture))
1326 packet = capture[0]
1327 try:
1328 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1329 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1330 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1331 self.assertEqual(packet[ICMP].type, 0) # echo reply
1332 except:
1333 self.logger.error(ppp("Unexpected or invalid packet "
1334 "(outside network):", packet))
1335 raise
1336
Juraj Slobodad3677682017-04-14 03:24:45 +02001337 def test_ping_internal_host_from_outside(self):
1338 """ Ping internal host from outside network """
1339
Matus Fabian2ba92e32017-08-21 07:05:03 -07001340 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1341 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1342 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1343 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001344
1345 # out2in
1346 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001347 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001348 ICMP(id=self.icmp_id_out, type='echo-request'))
1349 self.pg1.add_stream(pkt)
1350 self.pg_enable_capture(self.pg_interfaces)
1351 self.pg_start()
1352 capture = self.pg0.get_capture(1)
1353 self.verify_capture_in(capture, self.pg0, packet_num=1)
1354 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1355
1356 # in2out
1357 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1358 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1359 ICMP(id=self.icmp_id_in, type='echo-reply'))
1360 self.pg0.add_stream(pkt)
1361 self.pg_enable_capture(self.pg_interfaces)
1362 self.pg_start()
1363 capture = self.pg1.get_capture(1)
1364 self.verify_capture_out(capture, same_port=True, packet_num=1)
1365 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1366
Juraj Sloboda7b929792017-11-23 13:20:48 +01001367 def test_forwarding(self):
1368 """ NAT44 forwarding test """
1369
1370 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1371 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1372 is_inside=0)
1373 self.vapi.nat44_forwarding_enable_disable(1)
1374
1375 real_ip = self.pg0.remote_ip4n
1376 alias_ip = self.nat_addr_n
1377 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1378 external_ip=alias_ip)
1379
1380 try:
1381 # in2out - static mapping match
1382
1383 pkts = self.create_stream_out(self.pg1)
1384 self.pg1.add_stream(pkts)
1385 self.pg_enable_capture(self.pg_interfaces)
1386 self.pg_start()
1387 capture = self.pg0.get_capture(len(pkts))
1388 self.verify_capture_in(capture, self.pg0)
1389
1390 pkts = self.create_stream_in(self.pg0, self.pg1)
1391 self.pg0.add_stream(pkts)
1392 self.pg_enable_capture(self.pg_interfaces)
1393 self.pg_start()
1394 capture = self.pg1.get_capture(len(pkts))
1395 self.verify_capture_out(capture, same_port=True)
1396
1397 # in2out - no static mapping match
1398
1399 host0 = self.pg0.remote_hosts[0]
1400 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1401 try:
1402 pkts = self.create_stream_out(self.pg1,
1403 dst_ip=self.pg0.remote_ip4,
1404 use_inside_ports=True)
1405 self.pg1.add_stream(pkts)
1406 self.pg_enable_capture(self.pg_interfaces)
1407 self.pg_start()
1408 capture = self.pg0.get_capture(len(pkts))
1409 self.verify_capture_in(capture, self.pg0)
1410
1411 pkts = self.create_stream_in(self.pg0, self.pg1)
1412 self.pg0.add_stream(pkts)
1413 self.pg_enable_capture(self.pg_interfaces)
1414 self.pg_start()
1415 capture = self.pg1.get_capture(len(pkts))
1416 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1417 same_port=True)
1418 finally:
1419 self.pg0.remote_hosts[0] = host0
1420
1421 finally:
1422 self.vapi.nat44_forwarding_enable_disable(0)
1423 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1424 external_ip=alias_ip,
1425 is_add=0)
1426
Matus Fabiande886752016-12-07 03:38:19 -08001427 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001428 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001429
1430 nat_ip = "10.0.0.10"
1431 self.tcp_port_out = 6303
1432 self.udp_port_out = 6304
1433 self.icmp_id_out = 6305
1434
Matus Fabian2ba92e32017-08-21 07:05:03 -07001435 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1436 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1437 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1438 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001439 sm = self.vapi.nat44_static_mapping_dump()
1440 self.assertEqual(len(sm), 1)
1441 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001442 self.assertEqual(sm[0].protocol, 0)
1443 self.assertEqual(sm[0].local_port, 0)
1444 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001445
1446 # in2out
1447 pkts = self.create_stream_in(self.pg0, self.pg1)
1448 self.pg0.add_stream(pkts)
1449 self.pg_enable_capture(self.pg_interfaces)
1450 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001451 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001452 self.verify_capture_out(capture, nat_ip, True)
1453
1454 # out2in
1455 pkts = self.create_stream_out(self.pg1, nat_ip)
1456 self.pg1.add_stream(pkts)
1457 self.pg_enable_capture(self.pg_interfaces)
1458 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001459 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001460 self.verify_capture_in(capture, self.pg0)
1461
1462 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001463 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001464
1465 nat_ip = "10.0.0.20"
1466 self.tcp_port_out = 6303
1467 self.udp_port_out = 6304
1468 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001469 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001470
Matus Fabian5f224992018-01-25 21:59:16 -08001471 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001472 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1473 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1474 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001475 sm = self.vapi.nat44_static_mapping_dump()
1476 self.assertEqual(len(sm), 1)
1477 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001478
1479 # out2in
1480 pkts = self.create_stream_out(self.pg1, nat_ip)
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 # in2out
1488 pkts = self.create_stream_in(self.pg0, self.pg1)
1489 self.pg0.add_stream(pkts)
1490 self.pg_enable_capture(self.pg_interfaces)
1491 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001492 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001493 self.verify_capture_out(capture, nat_ip, True)
1494
1495 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001496 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001497
1498 self.tcp_port_out = 3606
1499 self.udp_port_out = 3607
1500 self.icmp_id_out = 3608
1501
Matus Fabian2ba92e32017-08-21 07:05:03 -07001502 self.nat44_add_address(self.nat_addr)
1503 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1504 self.tcp_port_in, self.tcp_port_out,
1505 proto=IP_PROTOS.tcp)
1506 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1507 self.udp_port_in, self.udp_port_out,
1508 proto=IP_PROTOS.udp)
1509 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1510 self.icmp_id_in, self.icmp_id_out,
1511 proto=IP_PROTOS.icmp)
1512 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1513 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1514 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001515
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
1524 # out2in
1525 pkts = self.create_stream_out(self.pg1)
1526 self.pg1.add_stream(pkts)
1527 self.pg_enable_capture(self.pg_interfaces)
1528 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001529 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001530 self.verify_capture_in(capture, self.pg0)
1531
1532 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001533 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001534
1535 self.tcp_port_out = 30606
1536 self.udp_port_out = 30607
1537 self.icmp_id_out = 30608
1538
Matus Fabian2ba92e32017-08-21 07:05:03 -07001539 self.nat44_add_address(self.nat_addr)
1540 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1541 self.tcp_port_in, self.tcp_port_out,
1542 proto=IP_PROTOS.tcp)
1543 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1544 self.udp_port_in, self.udp_port_out,
1545 proto=IP_PROTOS.udp)
1546 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1547 self.icmp_id_in, self.icmp_id_out,
1548 proto=IP_PROTOS.icmp)
1549 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1550 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1551 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001552
1553 # out2in
1554 pkts = self.create_stream_out(self.pg1)
1555 self.pg1.add_stream(pkts)
1556 self.pg_enable_capture(self.pg_interfaces)
1557 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001558 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001559 self.verify_capture_in(capture, self.pg0)
1560
1561 # in2out
1562 pkts = self.create_stream_in(self.pg0, self.pg1)
1563 self.pg0.add_stream(pkts)
1564 self.pg_enable_capture(self.pg_interfaces)
1565 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001566 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001567 self.verify_capture_out(capture)
1568
Matus Fabiane82488f2018-01-18 03:38:45 -08001569 def test_static_with_port_out2(self):
1570 """ 1:1 NAPT symmetrical rule """
1571
1572 external_port = 80
1573 local_port = 8080
1574
1575 self.vapi.nat44_forwarding_enable_disable(1)
1576 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1577 local_port, external_port,
1578 proto=IP_PROTOS.tcp, out2in_only=1)
1579 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1580 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1581 is_inside=0)
1582
1583 # from client to service
1584 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1585 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1586 TCP(sport=12345, dport=external_port))
1587 self.pg1.add_stream(p)
1588 self.pg_enable_capture(self.pg_interfaces)
1589 self.pg_start()
1590 capture = self.pg0.get_capture(1)
1591 p = capture[0]
1592 server = None
1593 try:
1594 ip = p[IP]
1595 tcp = p[TCP]
1596 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1597 self.assertEqual(tcp.dport, local_port)
1598 self.check_tcp_checksum(p)
1599 self.check_ip_checksum(p)
1600 except:
1601 self.logger.error(ppp("Unexpected or invalid packet:", p))
1602 raise
1603
Matus Fabian87233b52018-01-26 03:17:01 -08001604 # ICMP error
1605 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1606 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1607 ICMP(type=11) / capture[0][IP])
1608 self.pg0.add_stream(p)
1609 self.pg_enable_capture(self.pg_interfaces)
1610 self.pg_start()
1611 capture = self.pg1.get_capture(1)
1612 p = capture[0]
1613 try:
1614 self.assertEqual(p[IP].src, self.nat_addr)
1615 inner = p[IPerror]
1616 self.assertEqual(inner.dst, self.nat_addr)
1617 self.assertEqual(inner[TCPerror].dport, external_port)
1618 except:
1619 self.logger.error(ppp("Unexpected or invalid packet:", p))
1620 raise
1621
Matus Fabiane82488f2018-01-18 03:38:45 -08001622 # from service back to client
1623 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1624 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1625 TCP(sport=local_port, dport=12345))
1626 self.pg0.add_stream(p)
1627 self.pg_enable_capture(self.pg_interfaces)
1628 self.pg_start()
1629 capture = self.pg1.get_capture(1)
1630 p = capture[0]
1631 try:
1632 ip = p[IP]
1633 tcp = p[TCP]
1634 self.assertEqual(ip.src, self.nat_addr)
1635 self.assertEqual(tcp.sport, external_port)
1636 self.check_tcp_checksum(p)
1637 self.check_ip_checksum(p)
1638 except:
1639 self.logger.error(ppp("Unexpected or invalid packet:", p))
1640 raise
1641
Matus Fabian87233b52018-01-26 03:17:01 -08001642 # ICMP error
1643 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1644 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1645 ICMP(type=11) / capture[0][IP])
1646 self.pg1.add_stream(p)
1647 self.pg_enable_capture(self.pg_interfaces)
1648 self.pg_start()
1649 capture = self.pg0.get_capture(1)
1650 p = capture[0]
1651 try:
1652 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1653 inner = p[IPerror]
1654 self.assertEqual(inner.src, self.pg0.remote_ip4)
1655 self.assertEqual(inner[TCPerror].sport, local_port)
1656 except:
1657 self.logger.error(ppp("Unexpected or invalid packet:", p))
1658 raise
1659
Matus Fabiane82488f2018-01-18 03:38:45 -08001660 # from client to server (no translation)
1661 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1662 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1663 TCP(sport=12346, dport=local_port))
1664 self.pg1.add_stream(p)
1665 self.pg_enable_capture(self.pg_interfaces)
1666 self.pg_start()
1667 capture = self.pg0.get_capture(1)
1668 p = capture[0]
1669 server = None
1670 try:
1671 ip = p[IP]
1672 tcp = p[TCP]
1673 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1674 self.assertEqual(tcp.dport, local_port)
1675 self.check_tcp_checksum(p)
1676 self.check_ip_checksum(p)
1677 except:
1678 self.logger.error(ppp("Unexpected or invalid packet:", p))
1679 raise
1680
1681 # from service back to client (no translation)
1682 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1683 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1684 TCP(sport=local_port, dport=12346))
1685 self.pg0.add_stream(p)
1686 self.pg_enable_capture(self.pg_interfaces)
1687 self.pg_start()
1688 capture = self.pg1.get_capture(1)
1689 p = capture[0]
1690 try:
1691 ip = p[IP]
1692 tcp = p[TCP]
1693 self.assertEqual(ip.src, self.pg0.remote_ip4)
1694 self.assertEqual(tcp.sport, local_port)
1695 self.check_tcp_checksum(p)
1696 self.check_ip_checksum(p)
1697 except:
1698 self.logger.error(ppp("Unexpected or invalid packet:", p))
1699 raise
1700
Matus Fabiande886752016-12-07 03:38:19 -08001701 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001702 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001703
1704 nat_ip1 = "10.0.0.30"
1705 nat_ip2 = "10.0.0.40"
1706 self.tcp_port_out = 6303
1707 self.udp_port_out = 6304
1708 self.icmp_id_out = 6305
1709
Matus Fabian2ba92e32017-08-21 07:05:03 -07001710 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1711 vrf_id=10)
1712 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1713 vrf_id=10)
1714 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1715 is_inside=0)
1716 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1717 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001718
Matus Fabian2ba92e32017-08-21 07:05:03 -07001719 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001720 pkts = self.create_stream_in(self.pg4, self.pg3)
1721 self.pg4.add_stream(pkts)
1722 self.pg_enable_capture(self.pg_interfaces)
1723 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001724 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001725 self.verify_capture_out(capture, nat_ip1, True)
1726
Matus Fabian2ba92e32017-08-21 07:05:03 -07001727 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001728 # are dropped)
1729 pkts = self.create_stream_in(self.pg0, self.pg3)
1730 self.pg0.add_stream(pkts)
1731 self.pg_enable_capture(self.pg_interfaces)
1732 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001733 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001734
Matus Fabianb793d092018-01-31 05:50:21 -08001735 def test_dynamic_to_static(self):
1736 """ Switch from dynamic translation to 1:1NAT """
1737 nat_ip = "10.0.0.10"
1738 self.tcp_port_out = 6303
1739 self.udp_port_out = 6304
1740 self.icmp_id_out = 6305
1741
1742 self.nat44_add_address(self.nat_addr)
1743 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1744 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1745 is_inside=0)
1746
1747 # dynamic
1748 pkts = self.create_stream_in(self.pg0, self.pg1)
1749 self.pg0.add_stream(pkts)
1750 self.pg_enable_capture(self.pg_interfaces)
1751 self.pg_start()
1752 capture = self.pg1.get_capture(len(pkts))
1753 self.verify_capture_out(capture)
1754
1755 # 1:1NAT
1756 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1757 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1758 self.assertEqual(len(sessions), 0)
1759 pkts = self.create_stream_in(self.pg0, self.pg1)
1760 self.pg0.add_stream(pkts)
1761 self.pg_enable_capture(self.pg_interfaces)
1762 self.pg_start()
1763 capture = self.pg1.get_capture(len(pkts))
1764 self.verify_capture_out(capture, nat_ip, True)
1765
Matus Fabianab7a8052017-11-28 04:29:41 -08001766 def test_identity_nat(self):
1767 """ Identity NAT """
1768
1769 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1770 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1771 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1772 is_inside=0)
1773
1774 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1775 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1776 TCP(sport=12345, dport=56789))
1777 self.pg1.add_stream(p)
1778 self.pg_enable_capture(self.pg_interfaces)
1779 self.pg_start()
1780 capture = self.pg0.get_capture(1)
1781 p = capture[0]
1782 try:
1783 ip = p[IP]
1784 tcp = p[TCP]
1785 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1786 self.assertEqual(ip.src, self.pg1.remote_ip4)
1787 self.assertEqual(tcp.dport, 56789)
1788 self.assertEqual(tcp.sport, 12345)
1789 self.check_tcp_checksum(p)
1790 self.check_ip_checksum(p)
1791 except:
1792 self.logger.error(ppp("Unexpected or invalid packet:", p))
1793 raise
1794
Matus Fabian704018c2017-09-04 02:17:18 -07001795 def test_static_lb(self):
1796 """ NAT44 local service load balancing """
1797 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1798 external_port = 80
1799 local_port = 8080
1800 server1 = self.pg0.remote_hosts[0]
1801 server2 = self.pg0.remote_hosts[1]
1802
1803 locals = [{'addr': server1.ip4n,
1804 'port': local_port,
1805 'probability': 70},
1806 {'addr': server2.ip4n,
1807 'port': local_port,
1808 'probability': 30}]
1809
1810 self.nat44_add_address(self.nat_addr)
1811 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1812 external_port,
1813 IP_PROTOS.tcp,
1814 local_num=len(locals),
1815 locals=locals)
1816 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1817 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1818 is_inside=0)
1819
1820 # from client to service
1821 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1822 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1823 TCP(sport=12345, dport=external_port))
1824 self.pg1.add_stream(p)
1825 self.pg_enable_capture(self.pg_interfaces)
1826 self.pg_start()
1827 capture = self.pg0.get_capture(1)
1828 p = capture[0]
1829 server = None
1830 try:
1831 ip = p[IP]
1832 tcp = p[TCP]
1833 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1834 if ip.dst == server1.ip4:
1835 server = server1
1836 else:
1837 server = server2
1838 self.assertEqual(tcp.dport, local_port)
1839 self.check_tcp_checksum(p)
1840 self.check_ip_checksum(p)
1841 except:
1842 self.logger.error(ppp("Unexpected or invalid packet:", p))
1843 raise
1844
1845 # from service back to client
1846 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1847 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1848 TCP(sport=local_port, dport=12345))
1849 self.pg0.add_stream(p)
1850 self.pg_enable_capture(self.pg_interfaces)
1851 self.pg_start()
1852 capture = self.pg1.get_capture(1)
1853 p = capture[0]
1854 try:
1855 ip = p[IP]
1856 tcp = p[TCP]
1857 self.assertEqual(ip.src, self.nat_addr)
1858 self.assertEqual(tcp.sport, external_port)
1859 self.check_tcp_checksum(p)
1860 self.check_ip_checksum(p)
1861 except:
1862 self.logger.error(ppp("Unexpected or invalid packet:", p))
1863 raise
1864
Matus Fabian2aad8762018-03-07 04:57:22 -08001865 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1866 def test_static_lb_multi_clients(self):
1867 """ NAT44 local service load balancing - multiple clients"""
1868
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': 90},
1878 {'addr': server2.ip4n,
1879 'port': local_port,
1880 'probability': 10}]
1881
1882 self.nat44_add_address(self.nat_addr)
1883 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1884 external_port,
1885 IP_PROTOS.tcp,
1886 local_num=len(locals),
1887 locals=locals)
1888 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1889 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1890 is_inside=0)
1891
Matus Fabian704018c2017-09-04 02:17:18 -07001892 server1_n = 0
1893 server2_n = 0
Matus Fabian2aad8762018-03-07 04:57:22 -08001894 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
Matus Fabian704018c2017-09-04 02:17:18 -07001895 pkts = []
1896 for client in clients:
1897 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1898 IP(src=client, dst=self.nat_addr) /
1899 TCP(sport=12345, dport=external_port))
1900 pkts.append(p)
1901 self.pg1.add_stream(pkts)
1902 self.pg_enable_capture(self.pg_interfaces)
1903 self.pg_start()
1904 capture = self.pg0.get_capture(len(pkts))
1905 for p in capture:
1906 if p[IP].dst == server1.ip4:
1907 server1_n += 1
1908 else:
1909 server2_n += 1
1910 self.assertTrue(server1_n > server2_n)
1911
Matus Fabian240b5ef2018-01-11 04:09:17 -08001912 def test_static_lb_2(self):
1913 """ NAT44 local service load balancing (asymmetrical rule) """
1914 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1915 external_port = 80
1916 local_port = 8080
1917 server1 = self.pg0.remote_hosts[0]
1918 server2 = self.pg0.remote_hosts[1]
1919
1920 locals = [{'addr': server1.ip4n,
1921 'port': local_port,
1922 'probability': 70},
1923 {'addr': server2.ip4n,
1924 'port': local_port,
1925 'probability': 30}]
1926
1927 self.vapi.nat44_forwarding_enable_disable(1)
1928 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1929 external_port,
1930 IP_PROTOS.tcp,
1931 out2in_only=1,
1932 local_num=len(locals),
1933 locals=locals)
1934 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1935 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1936 is_inside=0)
1937
1938 # from client to service
1939 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1940 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1941 TCP(sport=12345, dport=external_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.assertIn(ip.dst, [server1.ip4, server2.ip4])
1952 if ip.dst == server1.ip4:
1953 server = server1
1954 else:
1955 server = server2
1956 self.assertEqual(tcp.dport, local_port)
1957 self.check_tcp_checksum(p)
1958 self.check_ip_checksum(p)
1959 except:
1960 self.logger.error(ppp("Unexpected or invalid packet:", p))
1961 raise
1962
1963 # from service back to client
1964 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1965 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1966 TCP(sport=local_port, dport=12345))
1967 self.pg0.add_stream(p)
1968 self.pg_enable_capture(self.pg_interfaces)
1969 self.pg_start()
1970 capture = self.pg1.get_capture(1)
1971 p = capture[0]
1972 try:
1973 ip = p[IP]
1974 tcp = p[TCP]
1975 self.assertEqual(ip.src, self.nat_addr)
1976 self.assertEqual(tcp.sport, external_port)
1977 self.check_tcp_checksum(p)
1978 self.check_ip_checksum(p)
1979 except:
1980 self.logger.error(ppp("Unexpected or invalid packet:", p))
1981 raise
1982
1983 # from client to server (no translation)
1984 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1985 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1986 TCP(sport=12346, dport=local_port))
1987 self.pg1.add_stream(p)
1988 self.pg_enable_capture(self.pg_interfaces)
1989 self.pg_start()
1990 capture = self.pg0.get_capture(1)
1991 p = capture[0]
1992 server = None
1993 try:
1994 ip = p[IP]
1995 tcp = p[TCP]
1996 self.assertEqual(ip.dst, server1.ip4)
1997 self.assertEqual(tcp.dport, local_port)
1998 self.check_tcp_checksum(p)
1999 self.check_ip_checksum(p)
2000 except:
2001 self.logger.error(ppp("Unexpected or invalid packet:", p))
2002 raise
2003
2004 # from service back to client (no translation)
2005 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
2006 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
2007 TCP(sport=local_port, dport=12346))
2008 self.pg0.add_stream(p)
2009 self.pg_enable_capture(self.pg_interfaces)
2010 self.pg_start()
2011 capture = self.pg1.get_capture(1)
2012 p = capture[0]
2013 try:
2014 ip = p[IP]
2015 tcp = p[TCP]
2016 self.assertEqual(ip.src, server1.ip4)
2017 self.assertEqual(tcp.sport, local_port)
2018 self.check_tcp_checksum(p)
2019 self.check_ip_checksum(p)
2020 except:
2021 self.logger.error(ppp("Unexpected or invalid packet:", p))
2022 raise
2023
Matus Fabiande886752016-12-07 03:38:19 -08002024 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002025 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002026
Matus Fabian2ba92e32017-08-21 07:05:03 -07002027 self.nat44_add_address(self.nat_addr)
2028 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2029 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2030 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2031 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002032
Matus Fabian2ba92e32017-08-21 07:05:03 -07002033 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002034 pkts = self.create_stream_in(self.pg0, self.pg1)
2035 self.pg0.add_stream(pkts)
2036 self.pg_enable_capture(self.pg_interfaces)
2037 self.pg_start()
2038 capture = self.pg1.get_capture(len(pkts))
2039 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2040
Matus Fabian2ba92e32017-08-21 07:05:03 -07002041 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002042 pkts = self.create_stream_in(self.pg0, self.pg2)
2043 self.pg0.add_stream(pkts)
2044 self.pg_enable_capture(self.pg_interfaces)
2045 self.pg_start()
2046 capture = self.pg2.get_capture(len(pkts))
2047 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2048
Matus Fabiande886752016-12-07 03:38:19 -08002049 # in2out 1st interface
2050 pkts = self.create_stream_in(self.pg0, self.pg3)
2051 self.pg0.add_stream(pkts)
2052 self.pg_enable_capture(self.pg_interfaces)
2053 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002054 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002055 self.verify_capture_out(capture)
2056
2057 # out2in 1st interface
2058 pkts = self.create_stream_out(self.pg3)
2059 self.pg3.add_stream(pkts)
2060 self.pg_enable_capture(self.pg_interfaces)
2061 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002062 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002063 self.verify_capture_in(capture, self.pg0)
2064
2065 # in2out 2nd interface
2066 pkts = self.create_stream_in(self.pg1, self.pg3)
2067 self.pg1.add_stream(pkts)
2068 self.pg_enable_capture(self.pg_interfaces)
2069 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002070 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002071 self.verify_capture_out(capture)
2072
2073 # out2in 2nd interface
2074 pkts = self.create_stream_out(self.pg3)
2075 self.pg3.add_stream(pkts)
2076 self.pg_enable_capture(self.pg_interfaces)
2077 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002078 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002079 self.verify_capture_in(capture, self.pg1)
2080
Matus Fabiande886752016-12-07 03:38:19 -08002081 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002082 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002083
Matus Fabian675a69c2017-01-18 01:46:01 -08002084 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002085 self.nat44_add_address(self.nat_addr)
2086 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2087 is_inside=0)
2088 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2089 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2090 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2091 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2092 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002093
Matus Fabian2ba92e32017-08-21 07:05:03 -07002094 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002095 pkts = self.create_stream_in(self.pg4, self.pg5)
2096 self.pg4.add_stream(pkts)
2097 self.pg_enable_capture(self.pg_interfaces)
2098 self.pg_start()
2099 capture = self.pg5.get_capture(len(pkts))
2100 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2101
Matus Fabian2ba92e32017-08-21 07:05:03 -07002102 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002103 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2104 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2105 TCP(sport=1234, dport=5678))
2106 self.pg4.add_stream(p)
2107 self.pg_enable_capture(self.pg_interfaces)
2108 self.pg_start()
2109 capture = self.pg6.get_capture(1)
2110 p = capture[0]
2111 try:
2112 ip = p[IP]
2113 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002114 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002115 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2116 self.assertNotEqual(tcp.sport, 1234)
2117 self.assertEqual(tcp.dport, 5678)
2118 except:
2119 self.logger.error(ppp("Unexpected or invalid packet:", p))
2120 raise
Matus Fabiande886752016-12-07 03:38:19 -08002121
2122 # in2out 1st interface
2123 pkts = self.create_stream_in(self.pg4, self.pg3)
2124 self.pg4.add_stream(pkts)
2125 self.pg_enable_capture(self.pg_interfaces)
2126 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002127 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002128 self.verify_capture_out(capture)
2129
2130 # out2in 1st interface
2131 pkts = self.create_stream_out(self.pg3)
2132 self.pg3.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.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002136 self.verify_capture_in(capture, self.pg4)
2137
2138 # in2out 2nd interface
2139 pkts = self.create_stream_in(self.pg5, self.pg3)
2140 self.pg5.add_stream(pkts)
2141 self.pg_enable_capture(self.pg_interfaces)
2142 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002143 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002144 self.verify_capture_out(capture)
2145
2146 # out2in 2nd interface
2147 pkts = self.create_stream_out(self.pg3)
2148 self.pg3.add_stream(pkts)
2149 self.pg_enable_capture(self.pg_interfaces)
2150 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002151 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002152 self.verify_capture_in(capture, self.pg5)
2153
magalik23caa882017-02-08 23:25:45 -08002154 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002155 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002156 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002157 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002158 self.assertEqual(len(sessions), 3)
2159 for session in sessions:
2160 self.assertFalse(session.is_static)
2161 self.assertEqual(session.inside_ip_address[0:4],
2162 self.pg5.remote_ip4n)
2163 self.assertEqual(session.outside_ip_address,
2164 addresses[0].ip_address)
2165 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2166 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2167 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2168 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2169 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2170 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2171 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2172 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2173 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2174
Matus Fabiande886752016-12-07 03:38:19 -08002175 # in2out 3rd interface
2176 pkts = self.create_stream_in(self.pg6, self.pg3)
2177 self.pg6.add_stream(pkts)
2178 self.pg_enable_capture(self.pg_interfaces)
2179 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002180 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002181 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002182
2183 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002184 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002185 self.pg3.add_stream(pkts)
2186 self.pg_enable_capture(self.pg_interfaces)
2187 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002188 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002189 self.verify_capture_in(capture, self.pg6)
2190
magalik23caa882017-02-08 23:25:45 -08002191 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002192 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002193 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002194 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002195 self.assertEqual(len(addresses), 1)
2196 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002197 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2198 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002199 for session in sessions:
2200 self.assertEqual(user.ip_address, session.inside_ip_address)
2201 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2202 self.assertTrue(session.protocol in
2203 [IP_PROTOS.tcp, IP_PROTOS.udp,
2204 IP_PROTOS.icmp])
2205
2206 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002207 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002208 self.assertTrue(len(sessions) >= 4)
2209 for session in sessions:
2210 self.assertFalse(session.is_static)
2211 self.assertEqual(session.inside_ip_address[0:4],
2212 self.pg4.remote_ip4n)
2213 self.assertEqual(session.outside_ip_address,
2214 addresses[0].ip_address)
2215
2216 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002217 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002218 self.assertTrue(len(sessions) >= 3)
2219 for session in sessions:
2220 self.assertTrue(session.is_static)
2221 self.assertEqual(session.inside_ip_address[0:4],
2222 self.pg6.remote_ip4n)
2223 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2224 map(int, static_nat_ip.split('.')))
2225 self.assertTrue(session.inside_port in
2226 [self.tcp_port_in, self.udp_port_in,
2227 self.icmp_id_in])
2228
Matus Fabianf78a70d2016-12-12 04:30:39 -08002229 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002230 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002231
2232 host = self.pg0.remote_hosts[0]
2233 server = self.pg0.remote_hosts[1]
2234 host_in_port = 1234
2235 host_out_port = 0
2236 server_in_port = 5678
2237 server_out_port = 8765
2238
Matus Fabian2ba92e32017-08-21 07:05:03 -07002239 self.nat44_add_address(self.nat_addr)
2240 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2241 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2242 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002243 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002244 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2245 server_in_port, server_out_port,
2246 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002247
2248 # send packet from host to server
2249 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002250 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002251 TCP(sport=host_in_port, dport=server_out_port))
2252 self.pg0.add_stream(p)
2253 self.pg_enable_capture(self.pg_interfaces)
2254 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002255 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002256 p = capture[0]
2257 try:
2258 ip = p[IP]
2259 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002260 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002261 self.assertEqual(ip.dst, server.ip4)
2262 self.assertNotEqual(tcp.sport, host_in_port)
2263 self.assertEqual(tcp.dport, server_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002264 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002265 host_out_port = tcp.sport
2266 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002267 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002268 raise
2269
2270 # send reply from server to host
2271 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002272 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002273 TCP(sport=server_in_port, dport=host_out_port))
2274 self.pg0.add_stream(p)
2275 self.pg_enable_capture(self.pg_interfaces)
2276 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002277 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002278 p = capture[0]
2279 try:
2280 ip = p[IP]
2281 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002282 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002283 self.assertEqual(ip.dst, host.ip4)
2284 self.assertEqual(tcp.sport, server_out_port)
2285 self.assertEqual(tcp.dport, host_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002286 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002287 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002288 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002289 raise
2290
Matus Fabian6fa74c62017-06-05 05:55:48 -07002291 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002292 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002293
2294 server1_nat_ip = "10.0.0.10"
2295 server2_nat_ip = "10.0.0.11"
2296 host = self.pg0.remote_hosts[0]
2297 server1 = self.pg0.remote_hosts[1]
2298 server2 = self.pg0.remote_hosts[2]
2299 server_tcp_port = 22
2300 server_udp_port = 20
2301
Matus Fabian2ba92e32017-08-21 07:05:03 -07002302 self.nat44_add_address(self.nat_addr)
2303 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2304 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2305 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002306
2307 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002308 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2309 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002310
2311 # host to server1
2312 pkts = []
2313 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2314 IP(src=host.ip4, dst=server1_nat_ip) /
2315 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2316 pkts.append(p)
2317 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2318 IP(src=host.ip4, dst=server1_nat_ip) /
2319 UDP(sport=self.udp_port_in, dport=server_udp_port))
2320 pkts.append(p)
2321 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2322 IP(src=host.ip4, dst=server1_nat_ip) /
2323 ICMP(id=self.icmp_id_in, type='echo-request'))
2324 pkts.append(p)
2325 self.pg0.add_stream(pkts)
2326 self.pg_enable_capture(self.pg_interfaces)
2327 self.pg_start()
2328 capture = self.pg0.get_capture(len(pkts))
2329 for packet in capture:
2330 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002331 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002332 self.assertEqual(packet[IP].dst, server1.ip4)
2333 if packet.haslayer(TCP):
2334 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2335 self.assertEqual(packet[TCP].dport, server_tcp_port)
2336 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002337 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002338 elif packet.haslayer(UDP):
2339 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2340 self.assertEqual(packet[UDP].dport, server_udp_port)
2341 self.udp_port_out = packet[UDP].sport
2342 else:
2343 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2344 self.icmp_id_out = packet[ICMP].id
2345 except:
2346 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2347 raise
2348
2349 # server1 to host
2350 pkts = []
2351 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002352 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002353 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2354 pkts.append(p)
2355 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002356 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002357 UDP(sport=server_udp_port, dport=self.udp_port_out))
2358 pkts.append(p)
2359 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002360 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002361 ICMP(id=self.icmp_id_out, type='echo-reply'))
2362 pkts.append(p)
2363 self.pg0.add_stream(pkts)
2364 self.pg_enable_capture(self.pg_interfaces)
2365 self.pg_start()
2366 capture = self.pg0.get_capture(len(pkts))
2367 for packet in capture:
2368 try:
2369 self.assertEqual(packet[IP].src, server1_nat_ip)
2370 self.assertEqual(packet[IP].dst, host.ip4)
2371 if packet.haslayer(TCP):
2372 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2373 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002374 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002375 elif packet.haslayer(UDP):
2376 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2377 self.assertEqual(packet[UDP].sport, server_udp_port)
2378 else:
2379 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2380 except:
2381 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2382 raise
2383
2384 # server2 to server1
2385 pkts = []
2386 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2387 IP(src=server2.ip4, dst=server1_nat_ip) /
2388 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2389 pkts.append(p)
2390 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2391 IP(src=server2.ip4, dst=server1_nat_ip) /
2392 UDP(sport=self.udp_port_in, dport=server_udp_port))
2393 pkts.append(p)
2394 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2395 IP(src=server2.ip4, dst=server1_nat_ip) /
2396 ICMP(id=self.icmp_id_in, type='echo-request'))
2397 pkts.append(p)
2398 self.pg0.add_stream(pkts)
2399 self.pg_enable_capture(self.pg_interfaces)
2400 self.pg_start()
2401 capture = self.pg0.get_capture(len(pkts))
2402 for packet in capture:
2403 try:
2404 self.assertEqual(packet[IP].src, server2_nat_ip)
2405 self.assertEqual(packet[IP].dst, server1.ip4)
2406 if packet.haslayer(TCP):
2407 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2408 self.assertEqual(packet[TCP].dport, server_tcp_port)
2409 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002410 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002411 elif packet.haslayer(UDP):
2412 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2413 self.assertEqual(packet[UDP].dport, server_udp_port)
2414 self.udp_port_out = packet[UDP].sport
2415 else:
2416 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2417 self.icmp_id_out = packet[ICMP].id
2418 except:
2419 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2420 raise
2421
2422 # server1 to server2
2423 pkts = []
2424 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2425 IP(src=server1.ip4, dst=server2_nat_ip) /
2426 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2427 pkts.append(p)
2428 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2429 IP(src=server1.ip4, dst=server2_nat_ip) /
2430 UDP(sport=server_udp_port, dport=self.udp_port_out))
2431 pkts.append(p)
2432 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2433 IP(src=server1.ip4, dst=server2_nat_ip) /
2434 ICMP(id=self.icmp_id_out, type='echo-reply'))
2435 pkts.append(p)
2436 self.pg0.add_stream(pkts)
2437 self.pg_enable_capture(self.pg_interfaces)
2438 self.pg_start()
2439 capture = self.pg0.get_capture(len(pkts))
2440 for packet in capture:
2441 try:
2442 self.assertEqual(packet[IP].src, server1_nat_ip)
2443 self.assertEqual(packet[IP].dst, server2.ip4)
2444 if packet.haslayer(TCP):
2445 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2446 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002447 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002448 elif packet.haslayer(UDP):
2449 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2450 self.assertEqual(packet[UDP].sport, server_udp_port)
2451 else:
2452 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2453 except:
2454 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2455 raise
2456
Matus Fabian9902fcd2016-12-21 23:58:46 -08002457 def test_max_translations_per_user(self):
2458 """ MAX translations per user - recycle the least recently used """
2459
Matus Fabian2ba92e32017-08-21 07:05:03 -07002460 self.nat44_add_address(self.nat_addr)
2461 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2462 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2463 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002464
2465 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002466 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002467
2468 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002469 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002470 pkts = []
2471 for port in range(0, pkts_num):
2472 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2473 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2474 TCP(sport=1025 + port))
2475 pkts.append(p)
2476 self.pg0.add_stream(pkts)
2477 self.pg_enable_capture(self.pg_interfaces)
2478 self.pg_start()
2479
2480 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002481 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002482
Matus Fabian132dc492018-05-09 04:51:03 -07002483 users = self.vapi.nat44_user_dump()
2484 for user in users:
2485 if user.ip_address == self.pg0.remote_ip4n:
2486 self.assertEqual(user.nsessions,
2487 nat44_config.max_translations_per_user)
2488 self.assertEqual(user.nstaticsessions, 0)
2489
2490 tcp_port = 22
2491 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2492 tcp_port, tcp_port,
2493 proto=IP_PROTOS.tcp)
2494 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2495 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2496 TCP(sport=tcp_port))
2497 self.pg0.add_stream(p)
2498 self.pg_enable_capture(self.pg_interfaces)
2499 self.pg_start()
2500 self.pg1.get_capture(1)
2501 users = self.vapi.nat44_user_dump()
2502 for user in users:
2503 if user.ip_address == self.pg0.remote_ip4n:
2504 self.assertEqual(user.nsessions,
2505 nat44_config.max_translations_per_user - 1)
2506 self.assertEqual(user.nstaticsessions, 1)
2507
Matus Fabian8bf68e82017-01-12 04:24:35 -08002508 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002509 """ Acquire NAT44 addresses from interface """
2510 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002511
2512 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002513 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002514 self.assertEqual(0, len(adresses))
2515
2516 # configure interface address and check NAT address pool
2517 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002518 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002519 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002520 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002521
2522 # remove interface address and check NAT address pool
2523 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002524 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002525 self.assertEqual(0, len(adresses))
2526
Matus Fabian36532bd2017-01-23 23:42:28 -08002527 def test_interface_addr_static_mapping(self):
2528 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002529 tag = "testTAG"
2530
Matus Fabian2ba92e32017-08-21 07:05:03 -07002531 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2532 self.nat44_add_static_mapping(
2533 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002534 external_sw_if_index=self.pg7.sw_if_index,
2535 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002536
Matus Fabiane22e5462017-02-14 23:33:43 -08002537 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002538 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002539 self.assertEqual(1, len(static_mappings))
2540 self.assertEqual(self.pg7.sw_if_index,
2541 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002542 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002543
2544 # configure interface address and check static mappings
2545 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002546 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002547 self.assertEqual(2, len(static_mappings))
2548 resolved = False
2549 for sm in static_mappings:
2550 if sm.external_sw_if_index == 0xFFFFFFFF:
2551 self.assertEqual(sm.external_ip_address[0:4],
2552 self.pg7.local_ip4n)
2553 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2554 resolved = True
2555 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002556
2557 # remove interface address and check static mappings
2558 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002559 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002560 self.assertEqual(1, len(static_mappings))
2561 self.assertEqual(self.pg7.sw_if_index,
2562 static_mappings[0].external_sw_if_index)
2563 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2564
2565 # configure interface address again and check static mappings
2566 self.pg7.config_ip4()
2567 static_mappings = self.vapi.nat44_static_mapping_dump()
2568 self.assertEqual(2, len(static_mappings))
2569 resolved = False
2570 for sm in static_mappings:
2571 if sm.external_sw_if_index == 0xFFFFFFFF:
2572 self.assertEqual(sm.external_ip_address[0:4],
2573 self.pg7.local_ip4n)
2574 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2575 resolved = True
2576 self.assertTrue(resolved)
2577
2578 # remove static mapping
2579 self.nat44_add_static_mapping(
2580 '1.2.3.4',
2581 external_sw_if_index=self.pg7.sw_if_index,
2582 tag=tag,
2583 is_add=0)
2584 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002585 self.assertEqual(0, len(static_mappings))
2586
Matus Fabianab7a8052017-11-28 04:29:41 -08002587 def test_interface_addr_identity_nat(self):
2588 """ Identity NAT with addresses from interface """
2589
2590 port = 53053
2591 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2592 self.vapi.nat44_add_del_identity_mapping(
2593 sw_if_index=self.pg7.sw_if_index,
2594 port=port,
2595 protocol=IP_PROTOS.tcp,
2596 addr_only=0)
2597
2598 # identity mappings with external interface
2599 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2600 self.assertEqual(1, len(identity_mappings))
2601 self.assertEqual(self.pg7.sw_if_index,
2602 identity_mappings[0].sw_if_index)
2603
2604 # configure interface address and check identity mappings
2605 self.pg7.config_ip4()
2606 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002607 resolved = False
2608 self.assertEqual(2, len(identity_mappings))
2609 for sm in identity_mappings:
2610 if sm.sw_if_index == 0xFFFFFFFF:
2611 self.assertEqual(identity_mappings[0].ip_address,
2612 self.pg7.local_ip4n)
2613 self.assertEqual(port, identity_mappings[0].port)
2614 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2615 resolved = True
2616 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002617
2618 # remove interface address and check identity mappings
2619 self.pg7.unconfig_ip4()
2620 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002621 self.assertEqual(1, len(identity_mappings))
2622 self.assertEqual(self.pg7.sw_if_index,
2623 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002624
Matus Fabianeea28d72017-01-13 04:15:54 -08002625 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002626 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002627 self.ipfix_domain_id = 10
2628 self.ipfix_src_port = 20202
2629 colector_port = 30303
2630 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002631 self.nat44_add_address(self.nat_addr)
2632 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2633 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2634 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002635 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2636 src_address=self.pg3.local_ip4n,
2637 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002638 template_interval=10,
2639 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002640 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2641 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002642
2643 pkts = self.create_stream_in(self.pg0, self.pg1)
2644 self.pg0.add_stream(pkts)
2645 self.pg_enable_capture(self.pg_interfaces)
2646 self.pg_start()
2647 capture = self.pg1.get_capture(len(pkts))
2648 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002649 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002650 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002651 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002652 ipfix = IPFIXDecoder()
2653 # first load template
2654 for p in capture:
2655 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002656 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2657 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2658 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2659 self.assertEqual(p[UDP].dport, colector_port)
2660 self.assertEqual(p[IPFIX].observationDomainID,
2661 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002662 if p.haslayer(Template):
2663 ipfix.add_template(p.getlayer(Template))
2664 # verify events in data set
2665 for p in capture:
2666 if p.haslayer(Data):
2667 data = ipfix.decode_data_set(p.getlayer(Set))
2668 self.verify_ipfix_nat44_ses(data)
2669
2670 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002671 """ IPFIX logging NAT addresses exhausted """
2672 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2673 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2674 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002675 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2676 src_address=self.pg3.local_ip4n,
2677 path_mtu=512,
2678 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002679 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2680 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002681
2682 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2683 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2684 TCP(sport=3025))
2685 self.pg0.add_stream(p)
2686 self.pg_enable_capture(self.pg_interfaces)
2687 self.pg_start()
2688 capture = self.pg1.get_capture(0)
2689 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002690 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002691 ipfix = IPFIXDecoder()
2692 # first load template
2693 for p in capture:
2694 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002695 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2696 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2697 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2698 self.assertEqual(p[UDP].dport, 4739)
2699 self.assertEqual(p[IPFIX].observationDomainID,
2700 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002701 if p.haslayer(Template):
2702 ipfix.add_template(p.getlayer(Template))
2703 # verify events in data set
2704 for p in capture:
2705 if p.haslayer(Data):
2706 data = ipfix.decode_data_set(p.getlayer(Set))
2707 self.verify_ipfix_addr_exhausted(data)
2708
Matus Fabiana431ad12018-01-04 04:03:14 -08002709 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2710 def test_ipfix_max_sessions(self):
2711 """ IPFIX logging maximum session entries exceeded """
2712 self.nat44_add_address(self.nat_addr)
2713 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2714 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2715 is_inside=0)
2716
2717 nat44_config = self.vapi.nat_show_config()
2718 max_sessions = 10 * nat44_config.translation_buckets
2719
2720 pkts = []
2721 for i in range(0, max_sessions):
2722 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2723 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2724 IP(src=src, dst=self.pg1.remote_ip4) /
2725 TCP(sport=1025))
2726 pkts.append(p)
2727 self.pg0.add_stream(pkts)
2728 self.pg_enable_capture(self.pg_interfaces)
2729 self.pg_start()
2730
2731 self.pg1.get_capture(max_sessions)
2732 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2733 src_address=self.pg3.local_ip4n,
2734 path_mtu=512,
2735 template_interval=10)
2736 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2737 src_port=self.ipfix_src_port)
2738
2739 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2740 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2741 TCP(sport=1025))
2742 self.pg0.add_stream(p)
2743 self.pg_enable_capture(self.pg_interfaces)
2744 self.pg_start()
2745 self.pg1.get_capture(0)
2746 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2747 capture = self.pg3.get_capture(9)
2748 ipfix = IPFIXDecoder()
2749 # first load template
2750 for p in capture:
2751 self.assertTrue(p.haslayer(IPFIX))
2752 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2753 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2754 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2755 self.assertEqual(p[UDP].dport, 4739)
2756 self.assertEqual(p[IPFIX].observationDomainID,
2757 self.ipfix_domain_id)
2758 if p.haslayer(Template):
2759 ipfix.add_template(p.getlayer(Template))
2760 # verify events in data set
2761 for p in capture:
2762 if p.haslayer(Data):
2763 data = ipfix.decode_data_set(p.getlayer(Set))
2764 self.verify_ipfix_max_sessions(data, max_sessions)
2765
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002766 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002767 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002768 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002769 self.nat44_add_address(self.nat_addr)
2770 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2771 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2772 is_inside=0)
2773 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002774
Matus Fabian2ba92e32017-08-21 07:05:03 -07002775 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002776 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002777 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002778 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2779 self.pg1.add_stream(p)
2780 self.pg_enable_capture(self.pg_interfaces)
2781 self.pg_start()
2782 capture = self.pg1.get_capture(1)
2783 self.assertTrue(capture[0].haslayer(ARP))
2784 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2785
2786 # 1:1 NAT address
2787 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2788 ARP(op=ARP.who_has, pdst=static_addr,
2789 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2790 self.pg1.add_stream(p)
2791 self.pg_enable_capture(self.pg_interfaces)
2792 self.pg_start()
2793 capture = self.pg1.get_capture(1)
2794 self.assertTrue(capture[0].haslayer(ARP))
2795 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2796
Matus Fabian2ba92e32017-08-21 07:05:03 -07002797 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002798 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002799 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002800 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2801 self.pg2.add_stream(p)
2802 self.pg_enable_capture(self.pg_interfaces)
2803 self.pg_start()
2804 capture = self.pg1.get_capture(0)
2805
2806 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002807 self.nat44_add_address(self.nat_addr, is_add=0)
2808 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2809 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002810
2811 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002812 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002813 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2814 self.pg1.add_stream(p)
2815 self.pg_enable_capture(self.pg_interfaces)
2816 self.pg_start()
2817 capture = self.pg1.get_capture(0)
2818
2819 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2820 ARP(op=ARP.who_has, pdst=static_addr,
2821 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2822 self.pg1.add_stream(p)
2823 self.pg_enable_capture(self.pg_interfaces)
2824 self.pg_start()
2825 capture = self.pg1.get_capture(0)
2826
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002827 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002828 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002829
2830 vrf_id1 = 1
2831 vrf_id2 = 2
2832 nat_ip1 = "10.0.0.10"
2833 nat_ip2 = "10.0.0.11"
2834
2835 self.pg0.unconfig_ip4()
2836 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002837 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2838 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002839 self.pg0.set_table_ip4(vrf_id1)
2840 self.pg1.set_table_ip4(vrf_id2)
2841 self.pg0.config_ip4()
2842 self.pg1.config_ip4()
2843
Matus Fabian2ba92e32017-08-21 07:05:03 -07002844 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2845 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2846 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2847 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2848 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2849 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002850
2851 # first VRF
2852 pkts = self.create_stream_in(self.pg0, self.pg2)
2853 self.pg0.add_stream(pkts)
2854 self.pg_enable_capture(self.pg_interfaces)
2855 self.pg_start()
2856 capture = self.pg2.get_capture(len(pkts))
2857 self.verify_capture_out(capture, nat_ip1)
2858
2859 # second VRF
2860 pkts = self.create_stream_in(self.pg1, self.pg2)
2861 self.pg1.add_stream(pkts)
2862 self.pg_enable_capture(self.pg_interfaces)
2863 self.pg_start()
2864 capture = self.pg2.get_capture(len(pkts))
2865 self.verify_capture_out(capture, nat_ip2)
2866
Neale Ranns15002542017-09-10 04:39:11 -07002867 self.pg0.unconfig_ip4()
2868 self.pg1.unconfig_ip4()
2869 self.pg0.set_table_ip4(0)
2870 self.pg1.set_table_ip4(0)
2871 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2872 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2873
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002874 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002875 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002876
2877 nat_ip1 = "10.0.0.10"
2878 nat_ip2 = "10.0.0.11"
2879
Matus Fabian2ba92e32017-08-21 07:05:03 -07002880 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002881 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002882 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2883 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2884 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2885 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002886
2887 # first VRF
2888 pkts = self.create_stream_in(self.pg0, self.pg2)
2889 self.pg0.add_stream(pkts)
2890 self.pg_enable_capture(self.pg_interfaces)
2891 self.pg_start()
2892 capture = self.pg2.get_capture(len(pkts))
2893 self.verify_capture_out(capture, nat_ip1)
2894
2895 # second VRF
2896 pkts = self.create_stream_in(self.pg1, self.pg2)
2897 self.pg1.add_stream(pkts)
2898 self.pg_enable_capture(self.pg_interfaces)
2899 self.pg_start()
2900 capture = self.pg2.get_capture(len(pkts))
2901 self.verify_capture_out(capture, nat_ip1)
2902
Martin Gálik406eb1d2017-05-04 04:35:04 -07002903 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002904 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002905
2906 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002907 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002908 self.pg7.remote_ip4n,
2909 is_static=1)
2910 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002911 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002912 self.pg8.remote_ip4n,
2913 is_static=1)
2914
2915 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2916 dst_address_length=32,
2917 next_hop_address=self.pg7.remote_ip4n,
2918 next_hop_sw_if_index=self.pg7.sw_if_index)
2919 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2920 dst_address_length=32,
2921 next_hop_address=self.pg8.remote_ip4n,
2922 next_hop_sw_if_index=self.pg8.sw_if_index)
2923
Matus Fabian2ba92e32017-08-21 07:05:03 -07002924 self.nat44_add_address(self.nat_addr)
2925 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2926 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2927 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002928
2929 # in2out
2930 pkts = self.create_stream_in(self.pg7, self.pg8)
2931 self.pg7.add_stream(pkts)
2932 self.pg_enable_capture(self.pg_interfaces)
2933 self.pg_start()
2934 capture = self.pg8.get_capture(len(pkts))
2935 self.verify_capture_out(capture)
2936
2937 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002938 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002939 self.pg8.add_stream(pkts)
2940 self.pg_enable_capture(self.pg_interfaces)
2941 self.pg_start()
2942 capture = self.pg7.get_capture(len(pkts))
2943 self.verify_capture_in(capture, self.pg7)
2944
2945 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002946 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002947
2948 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002949 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002950 self.pg7.remote_ip4n,
2951 is_static=1)
2952 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002953 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002954 self.pg8.remote_ip4n,
2955 is_static=1)
2956
2957 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2958 dst_address_length=32,
2959 next_hop_address=self.pg7.remote_ip4n,
2960 next_hop_sw_if_index=self.pg7.sw_if_index)
2961 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2962 dst_address_length=32,
2963 next_hop_address=self.pg8.remote_ip4n,
2964 next_hop_sw_if_index=self.pg8.sw_if_index)
2965
Matus Fabian2ba92e32017-08-21 07:05:03 -07002966 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2967 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2968 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2969 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002970
2971 # out2in
2972 pkts = self.create_stream_out(self.pg8)
2973 self.pg8.add_stream(pkts)
2974 self.pg_enable_capture(self.pg_interfaces)
2975 self.pg_start()
2976 capture = self.pg7.get_capture(len(pkts))
2977 self.verify_capture_in(capture, self.pg7)
2978
2979 # in2out
2980 pkts = self.create_stream_in(self.pg7, self.pg8)
2981 self.pg7.add_stream(pkts)
2982 self.pg_enable_capture(self.pg_interfaces)
2983 self.pg_start()
2984 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002985 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002986
2987 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002988 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002989
2990 self.tcp_port_out = 30606
2991 self.udp_port_out = 30607
2992 self.icmp_id_out = 30608
2993
2994 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002995 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002996 self.pg7.remote_ip4n,
2997 is_static=1)
2998 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002999 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07003000 self.pg8.remote_ip4n,
3001 is_static=1)
3002
3003 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3004 dst_address_length=32,
3005 next_hop_address=self.pg7.remote_ip4n,
3006 next_hop_sw_if_index=self.pg7.sw_if_index)
3007 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3008 dst_address_length=32,
3009 next_hop_address=self.pg8.remote_ip4n,
3010 next_hop_sw_if_index=self.pg8.sw_if_index)
3011
Matus Fabian2ba92e32017-08-21 07:05:03 -07003012 self.nat44_add_address(self.nat_addr)
3013 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3014 self.tcp_port_in, self.tcp_port_out,
3015 proto=IP_PROTOS.tcp)
3016 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3017 self.udp_port_in, self.udp_port_out,
3018 proto=IP_PROTOS.udp)
3019 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3020 self.icmp_id_in, self.icmp_id_out,
3021 proto=IP_PROTOS.icmp)
3022 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3023 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3024 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003025
3026 # out2in
3027 pkts = self.create_stream_out(self.pg8)
3028 self.pg8.add_stream(pkts)
3029 self.pg_enable_capture(self.pg_interfaces)
3030 self.pg_start()
3031 capture = self.pg7.get_capture(len(pkts))
3032 self.verify_capture_in(capture, self.pg7)
3033
3034 # in2out
3035 pkts = self.create_stream_in(self.pg7, self.pg8)
3036 self.pg7.add_stream(pkts)
3037 self.pg_enable_capture(self.pg_interfaces)
3038 self.pg_start()
3039 capture = self.pg8.get_capture(len(pkts))
3040 self.verify_capture_out(capture)
3041
Matus Fabian328dbc82017-06-19 04:28:04 -07003042 def test_static_unknown_proto(self):
3043 """ 1:1 NAT translate packet with unknown protocol """
3044 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003045 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3046 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3047 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3048 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003049
3050 # in2out
3051 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3052 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3053 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003054 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003055 TCP(sport=1234, dport=1234))
3056 self.pg0.add_stream(p)
3057 self.pg_enable_capture(self.pg_interfaces)
3058 self.pg_start()
3059 p = self.pg1.get_capture(1)
3060 packet = p[0]
3061 try:
3062 self.assertEqual(packet[IP].src, nat_ip)
3063 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3064 self.assertTrue(packet.haslayer(GRE))
3065 self.check_ip_checksum(packet)
3066 except:
3067 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3068 raise
3069
3070 # out2in
3071 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3072 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3073 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003074 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003075 TCP(sport=1234, dport=1234))
3076 self.pg1.add_stream(p)
3077 self.pg_enable_capture(self.pg_interfaces)
3078 self.pg_start()
3079 p = self.pg0.get_capture(1)
3080 packet = p[0]
3081 try:
3082 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3083 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3084 self.assertTrue(packet.haslayer(GRE))
3085 self.check_ip_checksum(packet)
3086 except:
3087 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3088 raise
3089
Matus Fabian7968e6c2017-07-06 05:37:49 -07003090 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003091 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3092
3093 host = self.pg0.remote_hosts[0]
3094 server = self.pg0.remote_hosts[1]
3095
3096 host_nat_ip = "10.0.0.10"
3097 server_nat_ip = "10.0.0.11"
3098
Matus Fabian2ba92e32017-08-21 07:05:03 -07003099 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3100 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3101 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3102 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3103 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003104
3105 # host to server
3106 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3107 IP(src=host.ip4, dst=server_nat_ip) /
3108 GRE() /
3109 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3110 TCP(sport=1234, dport=1234))
3111 self.pg0.add_stream(p)
3112 self.pg_enable_capture(self.pg_interfaces)
3113 self.pg_start()
3114 p = self.pg0.get_capture(1)
3115 packet = p[0]
3116 try:
3117 self.assertEqual(packet[IP].src, host_nat_ip)
3118 self.assertEqual(packet[IP].dst, server.ip4)
3119 self.assertTrue(packet.haslayer(GRE))
3120 self.check_ip_checksum(packet)
3121 except:
3122 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3123 raise
3124
3125 # server to host
3126 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3127 IP(src=server.ip4, dst=host_nat_ip) /
3128 GRE() /
3129 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3130 TCP(sport=1234, dport=1234))
3131 self.pg0.add_stream(p)
3132 self.pg_enable_capture(self.pg_interfaces)
3133 self.pg_start()
3134 p = self.pg0.get_capture(1)
3135 packet = p[0]
3136 try:
3137 self.assertEqual(packet[IP].src, server_nat_ip)
3138 self.assertEqual(packet[IP].dst, host.ip4)
3139 self.assertTrue(packet.haslayer(GRE))
3140 self.check_ip_checksum(packet)
3141 except:
3142 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3143 raise
3144
Matus Fabian7968e6c2017-07-06 05:37:49 -07003145 def test_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003146 """ NAT44 translate packet with unknown protocol """
3147 self.nat44_add_address(self.nat_addr)
3148 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3149 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3150 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003151
3152 # in2out
3153 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3154 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3155 TCP(sport=self.tcp_port_in, dport=20))
3156 self.pg0.add_stream(p)
3157 self.pg_enable_capture(self.pg_interfaces)
3158 self.pg_start()
3159 p = self.pg1.get_capture(1)
3160
3161 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3162 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3163 GRE() /
3164 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3165 TCP(sport=1234, dport=1234))
3166 self.pg0.add_stream(p)
3167 self.pg_enable_capture(self.pg_interfaces)
3168 self.pg_start()
3169 p = self.pg1.get_capture(1)
3170 packet = p[0]
3171 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003172 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003173 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3174 self.assertTrue(packet.haslayer(GRE))
3175 self.check_ip_checksum(packet)
3176 except:
3177 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3178 raise
3179
3180 # out2in
3181 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003182 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003183 GRE() /
3184 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3185 TCP(sport=1234, dport=1234))
3186 self.pg1.add_stream(p)
3187 self.pg_enable_capture(self.pg_interfaces)
3188 self.pg_start()
3189 p = self.pg0.get_capture(1)
3190 packet = p[0]
3191 try:
3192 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3193 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3194 self.assertTrue(packet.haslayer(GRE))
3195 self.check_ip_checksum(packet)
3196 except:
3197 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3198 raise
3199
3200 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003201 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003202 host = self.pg0.remote_hosts[0]
3203 server = self.pg0.remote_hosts[1]
3204 host_in_port = 1234
3205 host_out_port = 0
3206 server_in_port = 5678
3207 server_out_port = 8765
3208 server_nat_ip = "10.0.0.11"
3209
Matus Fabian2ba92e32017-08-21 07:05:03 -07003210 self.nat44_add_address(self.nat_addr)
3211 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3212 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3213 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003214
3215 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003216 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003217
3218 # host to server
3219 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3220 IP(src=host.ip4, dst=server_nat_ip) /
3221 TCP(sport=host_in_port, dport=server_out_port))
3222 self.pg0.add_stream(p)
3223 self.pg_enable_capture(self.pg_interfaces)
3224 self.pg_start()
3225 capture = self.pg0.get_capture(1)
3226
3227 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3228 IP(src=host.ip4, dst=server_nat_ip) /
3229 GRE() /
3230 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3231 TCP(sport=1234, dport=1234))
3232 self.pg0.add_stream(p)
3233 self.pg_enable_capture(self.pg_interfaces)
3234 self.pg_start()
3235 p = self.pg0.get_capture(1)
3236 packet = p[0]
3237 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003238 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003239 self.assertEqual(packet[IP].dst, server.ip4)
3240 self.assertTrue(packet.haslayer(GRE))
3241 self.check_ip_checksum(packet)
3242 except:
3243 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3244 raise
3245
3246 # server to host
3247 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003248 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003249 GRE() /
3250 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3251 TCP(sport=1234, dport=1234))
3252 self.pg0.add_stream(p)
3253 self.pg_enable_capture(self.pg_interfaces)
3254 self.pg_start()
3255 p = self.pg0.get_capture(1)
3256 packet = p[0]
3257 try:
3258 self.assertEqual(packet[IP].src, server_nat_ip)
3259 self.assertEqual(packet[IP].dst, host.ip4)
3260 self.assertTrue(packet.haslayer(GRE))
3261 self.check_ip_checksum(packet)
3262 except:
3263 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3264 raise
3265
Matus Fabian93d84c92017-07-19 08:06:01 -07003266 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003267 """ NAT44 interface output feature (in2out postrouting) """
3268 self.nat44_add_address(self.nat_addr)
3269 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003270 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3271 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003272 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003273
3274 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003275 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003276 self.pg0.add_stream(pkts)
3277 self.pg_enable_capture(self.pg_interfaces)
3278 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003279 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003280 self.verify_capture_out(capture)
3281
3282 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003283 pkts = self.create_stream_out(self.pg3)
3284 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003285 self.pg_enable_capture(self.pg_interfaces)
3286 self.pg_start()
3287 capture = self.pg0.get_capture(len(pkts))
3288 self.verify_capture_in(capture, self.pg0)
3289
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003290 # from non-NAT interface to NAT inside interface
3291 pkts = self.create_stream_in(self.pg2, self.pg0)
3292 self.pg2.add_stream(pkts)
3293 self.pg_enable_capture(self.pg_interfaces)
3294 self.pg_start()
3295 capture = self.pg0.get_capture(len(pkts))
3296 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3297
Matus Fabian93d84c92017-07-19 08:06:01 -07003298 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003299 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003300 nat_ip_vrf10 = "10.0.0.10"
3301 nat_ip_vrf20 = "10.0.0.20"
3302
3303 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3304 dst_address_length=32,
3305 next_hop_address=self.pg3.remote_ip4n,
3306 next_hop_sw_if_index=self.pg3.sw_if_index,
3307 table_id=10)
3308 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3309 dst_address_length=32,
3310 next_hop_address=self.pg3.remote_ip4n,
3311 next_hop_sw_if_index=self.pg3.sw_if_index,
3312 table_id=20)
3313
Matus Fabian2ba92e32017-08-21 07:05:03 -07003314 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3315 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3316 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3317 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3318 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3319 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003320
3321 # in2out VRF 10
3322 pkts = self.create_stream_in(self.pg4, self.pg3)
3323 self.pg4.add_stream(pkts)
3324 self.pg_enable_capture(self.pg_interfaces)
3325 self.pg_start()
3326 capture = self.pg3.get_capture(len(pkts))
3327 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3328
3329 # out2in VRF 10
3330 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3331 self.pg3.add_stream(pkts)
3332 self.pg_enable_capture(self.pg_interfaces)
3333 self.pg_start()
3334 capture = self.pg4.get_capture(len(pkts))
3335 self.verify_capture_in(capture, self.pg4)
3336
3337 # in2out VRF 20
3338 pkts = self.create_stream_in(self.pg6, self.pg3)
3339 self.pg6.add_stream(pkts)
3340 self.pg_enable_capture(self.pg_interfaces)
3341 self.pg_start()
3342 capture = self.pg3.get_capture(len(pkts))
3343 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3344
3345 # out2in VRF 20
3346 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3347 self.pg3.add_stream(pkts)
3348 self.pg_enable_capture(self.pg_interfaces)
3349 self.pg_start()
3350 capture = self.pg6.get_capture(len(pkts))
3351 self.verify_capture_in(capture, self.pg6)
3352
Matus Fabian161c59c2017-07-21 03:46:03 -07003353 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003354 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003355 host = self.pg0.remote_hosts[0]
3356 server = self.pg0.remote_hosts[1]
3357 host_in_port = 1234
3358 host_out_port = 0
3359 server_in_port = 5678
3360 server_out_port = 8765
3361
Matus Fabian2ba92e32017-08-21 07:05:03 -07003362 self.nat44_add_address(self.nat_addr)
3363 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3364 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3365 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003366
3367 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003368 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3369 server_in_port, server_out_port,
3370 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003371
3372 # send packet from host to server
3373 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003374 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003375 TCP(sport=host_in_port, dport=server_out_port))
3376 self.pg0.add_stream(p)
3377 self.pg_enable_capture(self.pg_interfaces)
3378 self.pg_start()
3379 capture = self.pg0.get_capture(1)
3380 p = capture[0]
3381 try:
3382 ip = p[IP]
3383 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003384 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003385 self.assertEqual(ip.dst, server.ip4)
3386 self.assertNotEqual(tcp.sport, host_in_port)
3387 self.assertEqual(tcp.dport, server_in_port)
3388 self.check_tcp_checksum(p)
3389 host_out_port = tcp.sport
3390 except:
3391 self.logger.error(ppp("Unexpected or invalid packet:", p))
3392 raise
3393
3394 # send reply from server to host
3395 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003396 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003397 TCP(sport=server_in_port, dport=host_out_port))
3398 self.pg0.add_stream(p)
3399 self.pg_enable_capture(self.pg_interfaces)
3400 self.pg_start()
3401 capture = self.pg0.get_capture(1)
3402 p = capture[0]
3403 try:
3404 ip = p[IP]
3405 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003406 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003407 self.assertEqual(ip.dst, host.ip4)
3408 self.assertEqual(tcp.sport, server_out_port)
3409 self.assertEqual(tcp.dport, host_in_port)
3410 self.check_tcp_checksum(p)
3411 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003412 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003413 raise
3414
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003415 def test_output_feature_and_service(self):
3416 """ NAT44 interface output feature and services """
3417 external_addr = '1.2.3.4'
3418 external_port = 80
3419 local_port = 8080
3420
3421 self.vapi.nat44_forwarding_enable_disable(1)
3422 self.nat44_add_address(self.nat_addr)
Matus Fabiana15cd022018-04-24 05:23:56 -07003423 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003424 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3425 local_port, external_port,
3426 proto=IP_PROTOS.tcp, out2in_only=1)
3427 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
Matus Fabiana15cd022018-04-24 05:23:56 -07003428 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3429 is_inside=0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003430 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3431 is_inside=0)
3432
3433 # from client to service
3434 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3435 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3436 TCP(sport=12345, dport=external_port))
3437 self.pg1.add_stream(p)
3438 self.pg_enable_capture(self.pg_interfaces)
3439 self.pg_start()
3440 capture = self.pg0.get_capture(1)
3441 p = capture[0]
3442 server = None
3443 try:
3444 ip = p[IP]
3445 tcp = p[TCP]
3446 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3447 self.assertEqual(tcp.dport, local_port)
3448 self.check_tcp_checksum(p)
3449 self.check_ip_checksum(p)
3450 except:
3451 self.logger.error(ppp("Unexpected or invalid packet:", p))
3452 raise
3453
3454 # from service back to client
3455 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3456 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3457 TCP(sport=local_port, dport=12345))
3458 self.pg0.add_stream(p)
3459 self.pg_enable_capture(self.pg_interfaces)
3460 self.pg_start()
3461 capture = self.pg1.get_capture(1)
3462 p = capture[0]
3463 try:
3464 ip = p[IP]
3465 tcp = p[TCP]
3466 self.assertEqual(ip.src, external_addr)
3467 self.assertEqual(tcp.sport, external_port)
3468 self.check_tcp_checksum(p)
3469 self.check_ip_checksum(p)
3470 except:
3471 self.logger.error(ppp("Unexpected or invalid packet:", p))
3472 raise
3473
3474 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003475 pkts = self.create_stream_in(self.pg0, self.pg1)
3476 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003477 self.pg_enable_capture(self.pg_interfaces)
3478 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003479 capture = self.pg1.get_capture(len(pkts))
3480 self.verify_capture_out(capture)
3481 pkts = self.create_stream_in(self.pg0, self.pg1)
3482 self.pg0.add_stream(pkts)
3483 self.pg_enable_capture(self.pg_interfaces)
3484 self.pg_start()
3485 capture = self.pg1.get_capture(len(pkts))
3486 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003487
3488 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003489 pkts = self.create_stream_out(self.pg1)
3490 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003491 self.pg_enable_capture(self.pg_interfaces)
3492 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003493 capture = self.pg0.get_capture(len(pkts))
3494 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003495
Matus Fabian204591d2018-03-01 04:48:33 -08003496 def test_output_feature_and_service2(self):
3497 """ NAT44 interface output feature and service host direct access """
3498 self.vapi.nat44_forwarding_enable_disable(1)
3499 self.nat44_add_address(self.nat_addr)
3500 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3501 is_inside=0)
3502
3503 # session initiaded from service host - translate
3504 pkts = self.create_stream_in(self.pg0, self.pg1)
3505 self.pg0.add_stream(pkts)
3506 self.pg_enable_capture(self.pg_interfaces)
3507 self.pg_start()
3508 capture = self.pg1.get_capture(len(pkts))
3509 self.verify_capture_out(capture)
3510
3511 pkts = self.create_stream_out(self.pg1)
3512 self.pg1.add_stream(pkts)
3513 self.pg_enable_capture(self.pg_interfaces)
3514 self.pg_start()
3515 capture = self.pg0.get_capture(len(pkts))
3516 self.verify_capture_in(capture, self.pg0)
3517
3518 tcp_port_out = self.tcp_port_out
3519 udp_port_out = self.udp_port_out
3520 icmp_id_out = self.icmp_id_out
3521
3522 # session initiaded from remote host - do not translate
3523 pkts = self.create_stream_out(self.pg1,
3524 self.pg0.remote_ip4,
3525 use_inside_ports=True)
3526 self.pg1.add_stream(pkts)
3527 self.pg_enable_capture(self.pg_interfaces)
3528 self.pg_start()
3529 capture = self.pg0.get_capture(len(pkts))
3530 self.verify_capture_in(capture, self.pg0)
3531
3532 pkts = self.create_stream_in(self.pg0, self.pg1)
3533 self.pg0.add_stream(pkts)
3534 self.pg_enable_capture(self.pg_interfaces)
3535 self.pg_start()
3536 capture = self.pg1.get_capture(len(pkts))
3537 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3538 same_port=True)
3539
Matus Fabian4d023c82018-03-22 05:50:47 -07003540 def test_output_feature_and_service3(self):
3541 """ NAT44 interface output feature and DST NAT """
3542 external_addr = '1.2.3.4'
3543 external_port = 80
3544 local_port = 8080
3545
3546 self.vapi.nat44_forwarding_enable_disable(1)
3547 self.nat44_add_address(self.nat_addr)
3548 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3549 local_port, external_port,
3550 proto=IP_PROTOS.tcp, out2in_only=1)
3551 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3552 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3553 is_inside=0)
3554 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3555 is_inside=0)
3556
3557 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3558 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3559 TCP(sport=12345, dport=external_port))
3560 self.pg0.add_stream(p)
3561 self.pg_enable_capture(self.pg_interfaces)
3562 self.pg_start()
3563 capture = self.pg1.get_capture(1)
3564 p = capture[0]
3565 try:
3566 ip = p[IP]
3567 tcp = p[TCP]
3568 self.assertEqual(ip.src, self.pg0.remote_ip4)
3569 self.assertEqual(tcp.sport, 12345)
3570 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3571 self.assertEqual(tcp.dport, local_port)
3572 self.check_tcp_checksum(p)
3573 self.check_ip_checksum(p)
3574 except:
3575 self.logger.error(ppp("Unexpected or invalid packet:", p))
3576 raise
3577
3578 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3579 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3580 TCP(sport=local_port, dport=12345))
3581 self.pg1.add_stream(p)
3582 self.pg_enable_capture(self.pg_interfaces)
3583 self.pg_start()
3584 capture = self.pg0.get_capture(1)
3585 p = capture[0]
3586 try:
3587 ip = p[IP]
3588 tcp = p[TCP]
3589 self.assertEqual(ip.src, external_addr)
3590 self.assertEqual(tcp.sport, external_port)
3591 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3592 self.assertEqual(tcp.dport, 12345)
3593 self.check_tcp_checksum(p)
3594 self.check_ip_checksum(p)
3595 except:
3596 self.logger.error(ppp("Unexpected or invalid packet:", p))
3597 raise
3598
Matus Fabian36ea2d62017-10-24 04:13:49 -07003599 def test_one_armed_nat44(self):
3600 """ One armed NAT44 """
3601 remote_host = self.pg9.remote_hosts[0]
3602 local_host = self.pg9.remote_hosts[1]
3603 external_port = 0
3604
3605 self.nat44_add_address(self.nat_addr)
3606 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3607 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3608 is_inside=0)
3609
3610 # in2out
3611 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3612 IP(src=local_host.ip4, dst=remote_host.ip4) /
3613 TCP(sport=12345, dport=80))
3614 self.pg9.add_stream(p)
3615 self.pg_enable_capture(self.pg_interfaces)
3616 self.pg_start()
3617 capture = self.pg9.get_capture(1)
3618 p = capture[0]
3619 try:
3620 ip = p[IP]
3621 tcp = p[TCP]
3622 self.assertEqual(ip.src, self.nat_addr)
3623 self.assertEqual(ip.dst, remote_host.ip4)
3624 self.assertNotEqual(tcp.sport, 12345)
3625 external_port = tcp.sport
3626 self.assertEqual(tcp.dport, 80)
3627 self.check_tcp_checksum(p)
3628 self.check_ip_checksum(p)
3629 except:
3630 self.logger.error(ppp("Unexpected or invalid packet:", p))
3631 raise
3632
3633 # out2in
3634 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3635 IP(src=remote_host.ip4, dst=self.nat_addr) /
3636 TCP(sport=80, dport=external_port))
3637 self.pg9.add_stream(p)
3638 self.pg_enable_capture(self.pg_interfaces)
3639 self.pg_start()
3640 capture = self.pg9.get_capture(1)
3641 p = capture[0]
3642 try:
3643 ip = p[IP]
3644 tcp = p[TCP]
3645 self.assertEqual(ip.src, remote_host.ip4)
3646 self.assertEqual(ip.dst, local_host.ip4)
3647 self.assertEqual(tcp.sport, 80)
3648 self.assertEqual(tcp.dport, 12345)
3649 self.check_tcp_checksum(p)
3650 self.check_ip_checksum(p)
3651 except:
3652 self.logger.error(ppp("Unexpected or invalid packet:", p))
3653 raise
3654
Matus Fabiand95c39e2018-01-23 06:07:01 -08003655 def test_one_armed_nat44_static(self):
3656 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3657 remote_host = self.pg9.remote_hosts[0]
3658 local_host = self.pg9.remote_hosts[1]
3659 external_port = 80
3660 local_port = 8080
3661 eh_port_in = 0
3662
3663 self.vapi.nat44_forwarding_enable_disable(1)
3664 self.nat44_add_address(self.nat_addr, twice_nat=1)
3665 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3666 local_port, external_port,
3667 proto=IP_PROTOS.tcp, out2in_only=1,
3668 twice_nat=1)
3669 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3670 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3671 is_inside=0)
3672
3673 # from client to service
3674 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3675 IP(src=remote_host.ip4, dst=self.nat_addr) /
3676 TCP(sport=12345, dport=external_port))
3677 self.pg9.add_stream(p)
3678 self.pg_enable_capture(self.pg_interfaces)
3679 self.pg_start()
3680 capture = self.pg9.get_capture(1)
3681 p = capture[0]
3682 server = None
3683 try:
3684 ip = p[IP]
3685 tcp = p[TCP]
3686 self.assertEqual(ip.dst, local_host.ip4)
3687 self.assertEqual(ip.src, self.nat_addr)
3688 self.assertEqual(tcp.dport, local_port)
3689 self.assertNotEqual(tcp.sport, 12345)
3690 eh_port_in = tcp.sport
3691 self.check_tcp_checksum(p)
3692 self.check_ip_checksum(p)
3693 except:
3694 self.logger.error(ppp("Unexpected or invalid packet:", p))
3695 raise
3696
3697 # from service back to client
3698 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3699 IP(src=local_host.ip4, dst=self.nat_addr) /
3700 TCP(sport=local_port, dport=eh_port_in))
3701 self.pg9.add_stream(p)
3702 self.pg_enable_capture(self.pg_interfaces)
3703 self.pg_start()
3704 capture = self.pg9.get_capture(1)
3705 p = capture[0]
3706 try:
3707 ip = p[IP]
3708 tcp = p[TCP]
3709 self.assertEqual(ip.src, self.nat_addr)
3710 self.assertEqual(ip.dst, remote_host.ip4)
3711 self.assertEqual(tcp.sport, external_port)
3712 self.assertEqual(tcp.dport, 12345)
3713 self.check_tcp_checksum(p)
3714 self.check_ip_checksum(p)
3715 except:
3716 self.logger.error(ppp("Unexpected or invalid packet:", p))
3717 raise
3718
Matus Fabian5ba86f72017-10-26 03:37:38 -07003719 def test_del_session(self):
3720 """ Delete NAT44 session """
3721 self.nat44_add_address(self.nat_addr)
3722 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3723 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3724 is_inside=0)
3725
3726 pkts = self.create_stream_in(self.pg0, self.pg1)
3727 self.pg0.add_stream(pkts)
3728 self.pg_enable_capture(self.pg_interfaces)
3729 self.pg_start()
3730 capture = self.pg1.get_capture(len(pkts))
3731
3732 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3733 nsessions = len(sessions)
3734
3735 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3736 sessions[0].inside_port,
3737 sessions[0].protocol)
3738 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3739 sessions[1].outside_port,
3740 sessions[1].protocol,
3741 is_in=0)
3742
3743 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3744 self.assertEqual(nsessions - len(sessions), 2)
3745
Matus Fabianefcd1e92017-08-15 06:59:19 -07003746 def test_set_get_reass(self):
3747 """ NAT44 set/get virtual fragmentation reassembly """
3748 reas_cfg1 = self.vapi.nat_get_reass()
3749
3750 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3751 max_reass=reas_cfg1.ip4_max_reass * 2,
3752 max_frag=reas_cfg1.ip4_max_frag * 2)
3753
3754 reas_cfg2 = self.vapi.nat_get_reass()
3755
3756 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3757 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3758 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3759
3760 self.vapi.nat_set_reass(drop_frag=1)
3761 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3762
3763 def test_frag_in_order(self):
3764 """ NAT44 translate fragments arriving in order """
3765 self.nat44_add_address(self.nat_addr)
3766 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3767 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3768 is_inside=0)
3769
3770 data = "A" * 4 + "B" * 16 + "C" * 3
3771 self.tcp_port_in = random.randint(1025, 65535)
3772
3773 reass = self.vapi.nat_reass_dump()
3774 reass_n_start = len(reass)
3775
3776 # in2out
3777 pkts = self.create_stream_frag(self.pg0,
3778 self.pg1.remote_ip4,
3779 self.tcp_port_in,
3780 20,
3781 data)
3782 self.pg0.add_stream(pkts)
3783 self.pg_enable_capture(self.pg_interfaces)
3784 self.pg_start()
3785 frags = self.pg1.get_capture(len(pkts))
3786 p = self.reass_frags_and_verify(frags,
3787 self.nat_addr,
3788 self.pg1.remote_ip4)
3789 self.assertEqual(p[TCP].dport, 20)
3790 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3791 self.tcp_port_out = p[TCP].sport
3792 self.assertEqual(data, p[Raw].load)
3793
3794 # out2in
3795 pkts = self.create_stream_frag(self.pg1,
3796 self.nat_addr,
3797 20,
3798 self.tcp_port_out,
3799 data)
3800 self.pg1.add_stream(pkts)
3801 self.pg_enable_capture(self.pg_interfaces)
3802 self.pg_start()
3803 frags = self.pg0.get_capture(len(pkts))
3804 p = self.reass_frags_and_verify(frags,
3805 self.pg1.remote_ip4,
3806 self.pg0.remote_ip4)
3807 self.assertEqual(p[TCP].sport, 20)
3808 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3809 self.assertEqual(data, p[Raw].load)
3810
3811 reass = self.vapi.nat_reass_dump()
3812 reass_n_end = len(reass)
3813
3814 self.assertEqual(reass_n_end - reass_n_start, 2)
3815
3816 def test_reass_hairpinning(self):
3817 """ NAT44 fragments hairpinning """
3818 host = self.pg0.remote_hosts[0]
3819 server = self.pg0.remote_hosts[1]
3820 host_in_port = random.randint(1025, 65535)
3821 host_out_port = 0
3822 server_in_port = random.randint(1025, 65535)
3823 server_out_port = random.randint(1025, 65535)
3824 data = "A" * 4 + "B" * 16 + "C" * 3
3825
3826 self.nat44_add_address(self.nat_addr)
3827 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3828 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3829 is_inside=0)
3830 # add static mapping for server
3831 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3832 server_in_port, server_out_port,
3833 proto=IP_PROTOS.tcp)
3834
3835 # send packet from host to server
3836 pkts = self.create_stream_frag(self.pg0,
3837 self.nat_addr,
3838 host_in_port,
3839 server_out_port,
3840 data)
3841 self.pg0.add_stream(pkts)
3842 self.pg_enable_capture(self.pg_interfaces)
3843 self.pg_start()
3844 frags = self.pg0.get_capture(len(pkts))
3845 p = self.reass_frags_and_verify(frags,
3846 self.nat_addr,
3847 server.ip4)
3848 self.assertNotEqual(p[TCP].sport, host_in_port)
3849 self.assertEqual(p[TCP].dport, server_in_port)
3850 self.assertEqual(data, p[Raw].load)
3851
3852 def test_frag_out_of_order(self):
3853 """ NAT44 translate fragments arriving out of order """
3854 self.nat44_add_address(self.nat_addr)
3855 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3856 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3857 is_inside=0)
3858
3859 data = "A" * 4 + "B" * 16 + "C" * 3
3860 random.randint(1025, 65535)
3861
3862 # in2out
3863 pkts = self.create_stream_frag(self.pg0,
3864 self.pg1.remote_ip4,
3865 self.tcp_port_in,
3866 20,
3867 data)
3868 pkts.reverse()
3869 self.pg0.add_stream(pkts)
3870 self.pg_enable_capture(self.pg_interfaces)
3871 self.pg_start()
3872 frags = self.pg1.get_capture(len(pkts))
3873 p = self.reass_frags_and_verify(frags,
3874 self.nat_addr,
3875 self.pg1.remote_ip4)
3876 self.assertEqual(p[TCP].dport, 20)
3877 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3878 self.tcp_port_out = p[TCP].sport
3879 self.assertEqual(data, p[Raw].load)
3880
3881 # out2in
3882 pkts = self.create_stream_frag(self.pg1,
3883 self.nat_addr,
3884 20,
3885 self.tcp_port_out,
3886 data)
3887 pkts.reverse()
3888 self.pg1.add_stream(pkts)
3889 self.pg_enable_capture(self.pg_interfaces)
3890 self.pg_start()
3891 frags = self.pg0.get_capture(len(pkts))
3892 p = self.reass_frags_and_verify(frags,
3893 self.pg1.remote_ip4,
3894 self.pg0.remote_ip4)
3895 self.assertEqual(p[TCP].sport, 20)
3896 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3897 self.assertEqual(data, p[Raw].load)
3898
Matus Fabian27697102017-11-09 01:43:47 -08003899 def test_port_restricted(self):
3900 """ Port restricted NAT44 (MAP-E CE) """
3901 self.nat44_add_address(self.nat_addr)
3902 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3903 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3904 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003905 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003906 "psid-offset 6 psid-len 6")
3907
3908 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3909 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3910 TCP(sport=4567, dport=22))
3911 self.pg0.add_stream(p)
3912 self.pg_enable_capture(self.pg_interfaces)
3913 self.pg_start()
3914 capture = self.pg1.get_capture(1)
3915 p = capture[0]
3916 try:
3917 ip = p[IP]
3918 tcp = p[TCP]
3919 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3920 self.assertEqual(ip.src, self.nat_addr)
3921 self.assertEqual(tcp.dport, 22)
3922 self.assertNotEqual(tcp.sport, 4567)
3923 self.assertEqual((tcp.sport >> 6) & 63, 10)
3924 self.check_tcp_checksum(p)
3925 self.check_ip_checksum(p)
3926 except:
3927 self.logger.error(ppp("Unexpected or invalid packet:", p))
3928 raise
3929
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003930 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
3931 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08003932 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003933
Matus Fabianb932d262017-12-18 05:38:24 -08003934 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003935 if lb:
3936 if not same_pg:
3937 port_in1 = port_in
3938 port_in2 = port_in
3939 else:
3940 port_in1 = port_in+1
3941 port_in2 = port_in+2
3942
Matus Fabianb932d262017-12-18 05:38:24 -08003943 port_out = 80
3944 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003945
3946 server1 = self.pg0.remote_hosts[0]
3947 server2 = self.pg0.remote_hosts[1]
3948 if lb and same_pg:
3949 server2 = server1
3950 if not lb:
3951 server = server1
3952
3953 pg0 = self.pg0
3954 if same_pg:
3955 pg1 = self.pg0
3956 else:
3957 pg1 = self.pg1
3958
3959 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
3960 client_id == 1)
3961
Matus Fabianb932d262017-12-18 05:38:24 -08003962 self.nat44_add_address(self.nat_addr)
3963 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003964 if not lb:
3965 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
3966 port_in, port_out,
3967 proto=IP_PROTOS.tcp,
3968 twice_nat=int(not self_twice_nat),
3969 self_twice_nat=int(self_twice_nat))
3970 else:
3971 locals = [{'addr': server1.ip4n,
3972 'port': port_in1,
3973 'probability': 50},
3974 {'addr': server2.ip4n,
3975 'port': port_in2,
3976 'probability': 50}]
3977 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3978 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
3979 port_out,
3980 IP_PROTOS.tcp,
3981 twice_nat=int(
3982 not self_twice_nat),
3983 self_twice_nat=int(
3984 self_twice_nat),
3985 local_num=len(locals),
3986 locals=locals)
3987 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
3988 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08003989 is_inside=0)
3990
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003991 if same_pg:
3992 if not lb:
3993 client = server
3994 else:
3995 assert client_id is not None
3996 if client_id == 1:
3997 client = self.pg0.remote_hosts[0]
3998 elif client_id == 2:
3999 client = self.pg0.remote_hosts[1]
4000 else:
4001 client = pg1.remote_hosts[0]
4002 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4003 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004004 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004005 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004006 self.pg_enable_capture(self.pg_interfaces)
4007 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004008 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004009 p = capture[0]
4010 try:
4011 ip = p[IP]
4012 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004013 if lb:
4014 if ip.dst == server1.ip4:
4015 server = server1
4016 port_in = port_in1
4017 else:
4018 server = server2
4019 port_in = port_in2
4020 self.assertEqual(ip.dst, server.ip4)
4021 if lb and same_pg:
4022 self.assertIn(tcp.dport, [port_in1, port_in2])
4023 else:
4024 self.assertEqual(tcp.dport, port_in)
4025 if eh_translate:
4026 self.assertEqual(ip.src, twice_nat_addr)
4027 self.assertNotEqual(tcp.sport, eh_port_out)
4028 else:
4029 self.assertEqual(ip.src, client.ip4)
4030 self.assertEqual(tcp.sport, eh_port_out)
4031 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004032 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004033 saved_port_in = tcp.dport
Matus Fabianb932d262017-12-18 05:38:24 -08004034 self.check_tcp_checksum(p)
4035 self.check_ip_checksum(p)
4036 except:
4037 self.logger.error(ppp("Unexpected or invalid packet:", p))
4038 raise
4039
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004040 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4041 IP(src=server.ip4, dst=eh_addr_in) /
4042 TCP(sport=saved_port_in, dport=eh_port_in))
4043 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004044 self.pg_enable_capture(self.pg_interfaces)
4045 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004046 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004047 p = capture[0]
4048 try:
4049 ip = p[IP]
4050 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004051 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004052 self.assertEqual(ip.src, self.nat_addr)
4053 self.assertEqual(tcp.dport, eh_port_out)
4054 self.assertEqual(tcp.sport, port_out)
4055 self.check_tcp_checksum(p)
4056 self.check_ip_checksum(p)
4057 except:
4058 self.logger.error(ppp("Unexpected or invalid packet:", p))
4059 raise
4060
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004061 def test_twice_nat(self):
4062 """ Twice NAT44 """
4063 self.twice_nat_common()
4064
4065 def test_self_twice_nat_positive(self):
4066 """ Self Twice NAT44 (positive test) """
4067 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4068
4069 def test_self_twice_nat_negative(self):
4070 """ Self Twice NAT44 (negative test) """
4071 self.twice_nat_common(self_twice_nat=True)
4072
Matus Fabianb932d262017-12-18 05:38:24 -08004073 def test_twice_nat_lb(self):
4074 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004075 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004076
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004077 def test_self_twice_nat_lb_positive(self):
4078 """ Self Twice NAT44 local service load balancing (positive test) """
4079 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4080 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004081
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004082 def test_self_twice_nat_lb_negative(self):
4083 """ Self Twice NAT44 local service load balancing (negative test) """
4084 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4085 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004086
4087 def test_twice_nat_interface_addr(self):
4088 """ Acquire twice NAT44 addresses from interface """
4089 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
4090
4091 # no address in NAT pool
4092 adresses = self.vapi.nat44_address_dump()
4093 self.assertEqual(0, len(adresses))
4094
4095 # configure interface address and check NAT address pool
4096 self.pg7.config_ip4()
4097 adresses = self.vapi.nat44_address_dump()
4098 self.assertEqual(1, len(adresses))
4099 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
4100 self.assertEqual(adresses[0].twice_nat, 1)
4101
4102 # remove interface address and check NAT address pool
4103 self.pg7.unconfig_ip4()
4104 adresses = self.vapi.nat44_address_dump()
4105 self.assertEqual(0, len(adresses))
4106
Matus Fabiana431ad12018-01-04 04:03:14 -08004107 def test_ipfix_max_frags(self):
4108 """ IPFIX logging maximum fragments pending reassembly exceeded """
4109 self.nat44_add_address(self.nat_addr)
4110 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4111 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4112 is_inside=0)
4113 self.vapi.nat_set_reass(max_frag=0)
4114 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4115 src_address=self.pg3.local_ip4n,
4116 path_mtu=512,
4117 template_interval=10)
4118 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4119 src_port=self.ipfix_src_port)
4120
4121 data = "A" * 4 + "B" * 16 + "C" * 3
4122 self.tcp_port_in = random.randint(1025, 65535)
4123 pkts = self.create_stream_frag(self.pg0,
4124 self.pg1.remote_ip4,
4125 self.tcp_port_in,
4126 20,
4127 data)
4128 self.pg0.add_stream(pkts[-1])
4129 self.pg_enable_capture(self.pg_interfaces)
4130 self.pg_start()
4131 frags = self.pg1.get_capture(0)
4132 self.vapi.cli("ipfix flush") # FIXME this should be an API call
4133 capture = self.pg3.get_capture(9)
4134 ipfix = IPFIXDecoder()
4135 # first load template
4136 for p in capture:
4137 self.assertTrue(p.haslayer(IPFIX))
4138 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4139 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4140 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4141 self.assertEqual(p[UDP].dport, 4739)
4142 self.assertEqual(p[IPFIX].observationDomainID,
4143 self.ipfix_domain_id)
4144 if p.haslayer(Template):
4145 ipfix.add_template(p.getlayer(Template))
4146 # verify events in data set
4147 for p in capture:
4148 if p.haslayer(Data):
4149 data = ipfix.decode_data_set(p.getlayer(Set))
4150 self.verify_ipfix_max_fragments_ip4(data, 0,
4151 self.pg0.remote_ip4n)
4152
Matus Fabianebdf1902018-05-04 03:57:42 -07004153 def test_tcp_session_close_in(self):
4154 """ Close TCP session from inside network """
4155 self.nat44_add_address(self.nat_addr)
4156 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4157 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4158 is_inside=0)
4159
4160 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4161 start_sessnum = len(sessions)
4162
4163 self.initiate_tcp_session(self.pg0, self.pg1)
4164
4165 # close the session from inside
4166 try:
4167 # FIN packet in -> out
4168 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4169 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4170 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4171 flags="FA"))
4172 self.pg0.add_stream(p)
4173 self.pg_enable_capture(self.pg_interfaces)
4174 self.pg_start()
4175 self.pg1.get_capture(1)
4176
4177 pkts = []
4178
4179 # ACK packet out -> in
4180 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4181 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4182 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4183 flags="A"))
4184 pkts.append(p)
4185
4186 # FIN packet out -> in
4187 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4188 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4189 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4190 flags="FA"))
4191 pkts.append(p)
4192
4193 self.pg1.add_stream(pkts)
4194 self.pg_enable_capture(self.pg_interfaces)
4195 self.pg_start()
4196 self.pg0.get_capture(2)
4197
4198 # ACK packet in -> out
4199 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4200 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4201 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4202 flags="A"))
4203 self.pg0.add_stream(p)
4204 self.pg_enable_capture(self.pg_interfaces)
4205 self.pg_start()
4206 self.pg1.get_capture(1)
4207
4208 self.initiate_tcp_session(self.pg0, self.pg1)
4209 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4210 0)
4211 self.assertEqual(len(sessions) - start_sessnum, 2)
4212 except:
4213 self.logger.error("TCP session termination failed")
4214 raise
4215
4216 def test_tcp_session_close_out(self):
4217 """ Close TCP session from outside network """
4218 self.nat44_add_address(self.nat_addr)
4219 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4220 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4221 is_inside=0)
4222
4223 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4224 start_sessnum = len(sessions)
4225
4226 self.initiate_tcp_session(self.pg0, self.pg1)
4227
4228 # close the session from outside
4229 try:
4230 # FIN packet out -> in
4231 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4232 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4233 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4234 flags="FA"))
4235 self.pg1.add_stream(p)
4236 self.pg_enable_capture(self.pg_interfaces)
4237 self.pg_start()
4238 self.pg0.get_capture(1)
4239
4240 pkts = []
4241
4242 # ACK packet in -> out
4243 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4244 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4245 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4246 flags="A"))
4247 pkts.append(p)
4248
4249 # ACK packet in -> out
4250 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4251 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4252 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4253 flags="FA"))
4254 pkts.append(p)
4255
4256 self.pg0.add_stream(pkts)
4257 self.pg_enable_capture(self.pg_interfaces)
4258 self.pg_start()
4259 self.pg1.get_capture(2)
4260
4261 # ACK packet out -> in
4262 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4263 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4264 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4265 flags="A"))
4266 self.pg1.add_stream(p)
4267 self.pg_enable_capture(self.pg_interfaces)
4268 self.pg_start()
4269 self.pg0.get_capture(1)
4270
4271 self.initiate_tcp_session(self.pg0, self.pg1)
4272 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4273 0)
4274 self.assertEqual(len(sessions) - start_sessnum, 2)
4275 except:
4276 self.logger.error("TCP session termination failed")
4277 raise
4278
4279 def test_tcp_session_close_simultaneous(self):
4280 """ Close TCP session from inside network """
4281 self.nat44_add_address(self.nat_addr)
4282 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4283 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4284 is_inside=0)
4285
4286 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4287 start_sessnum = len(sessions)
4288
4289 self.initiate_tcp_session(self.pg0, self.pg1)
4290
4291 # close the session from inside
4292 try:
4293 # FIN packet in -> out
4294 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4295 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4296 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4297 flags="FA"))
4298 self.pg0.add_stream(p)
4299 self.pg_enable_capture(self.pg_interfaces)
4300 self.pg_start()
4301 self.pg1.get_capture(1)
4302
4303 # FIN packet out -> in
4304 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4305 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4306 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4307 flags="FA"))
4308 self.pg1.add_stream(p)
4309 self.pg_enable_capture(self.pg_interfaces)
4310 self.pg_start()
4311 self.pg0.get_capture(1)
4312
4313 # ACK packet in -> out
4314 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4315 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4316 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4317 flags="A"))
4318 self.pg0.add_stream(p)
4319 self.pg_enable_capture(self.pg_interfaces)
4320 self.pg_start()
4321 self.pg1.get_capture(1)
4322
4323 # ACK packet out -> in
4324 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4325 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4326 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4327 flags="A"))
4328 self.pg1.add_stream(p)
4329 self.pg_enable_capture(self.pg_interfaces)
4330 self.pg_start()
4331 self.pg0.get_capture(1)
4332
4333 self.initiate_tcp_session(self.pg0, self.pg1)
4334 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4335 0)
4336 self.assertEqual(len(sessions) - start_sessnum, 2)
4337 except:
4338 self.logger.error("TCP session termination failed")
4339 raise
4340
Matus Fabiande886752016-12-07 03:38:19 -08004341 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004342 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004343 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004344 self.logger.info(self.vapi.cli("show nat44 addresses"))
4345 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4346 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4347 self.logger.info(self.vapi.cli("show nat44 interface address"))
4348 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004349 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004350 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004351 self.clear_nat44()
Matus Fabiande886752016-12-07 03:38:19 -08004352
Matus Fabianeea28d72017-01-13 04:15:54 -08004353
Juraj Slobodacba69362017-12-19 02:09:32 +01004354class TestNAT44Out2InDPO(MethodHolder):
4355 """ NAT44 Test Cases using out2in DPO """
4356
4357 @classmethod
4358 def setUpConstants(cls):
4359 super(TestNAT44Out2InDPO, cls).setUpConstants()
4360 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4361
4362 @classmethod
4363 def setUpClass(cls):
4364 super(TestNAT44Out2InDPO, cls).setUpClass()
4365
4366 try:
4367 cls.tcp_port_in = 6303
4368 cls.tcp_port_out = 6303
4369 cls.udp_port_in = 6304
4370 cls.udp_port_out = 6304
4371 cls.icmp_id_in = 6305
4372 cls.icmp_id_out = 6305
4373 cls.nat_addr = '10.0.0.3'
4374 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4375 cls.dst_ip4 = '192.168.70.1'
4376
4377 cls.create_pg_interfaces(range(2))
4378
4379 cls.pg0.admin_up()
4380 cls.pg0.config_ip4()
4381 cls.pg0.resolve_arp()
4382
4383 cls.pg1.admin_up()
4384 cls.pg1.config_ip6()
4385 cls.pg1.resolve_ndp()
4386
4387 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4388 dst_address_length=0,
4389 next_hop_address=cls.pg1.remote_ip6n,
4390 next_hop_sw_if_index=cls.pg1.sw_if_index)
4391
4392 except Exception:
4393 super(TestNAT44Out2InDPO, cls).tearDownClass()
4394 raise
4395
4396 def configure_xlat(self):
4397 self.dst_ip6_pfx = '1:2:3::'
4398 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4399 self.dst_ip6_pfx)
4400 self.dst_ip6_pfx_len = 96
4401 self.src_ip6_pfx = '4:5:6::'
4402 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4403 self.src_ip6_pfx)
4404 self.src_ip6_pfx_len = 96
4405 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4406 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4407 '\x00\x00\x00\x00', 0, is_translation=1,
4408 is_rfc6052=1)
4409
4410 def test_464xlat_ce(self):
4411 """ Test 464XLAT CE with NAT44 """
4412
4413 self.configure_xlat()
4414
4415 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4416 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4417
4418 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4419 self.dst_ip6_pfx_len)
4420 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4421 self.src_ip6_pfx_len)
4422
4423 try:
4424 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4425 self.pg0.add_stream(pkts)
4426 self.pg_enable_capture(self.pg_interfaces)
4427 self.pg_start()
4428 capture = self.pg1.get_capture(len(pkts))
4429 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4430 dst_ip=out_src_ip6)
4431
4432 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4433 out_dst_ip6)
4434 self.pg1.add_stream(pkts)
4435 self.pg_enable_capture(self.pg_interfaces)
4436 self.pg_start()
4437 capture = self.pg0.get_capture(len(pkts))
4438 self.verify_capture_in(capture, self.pg0)
4439 finally:
4440 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4441 is_add=0)
4442 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4443 self.nat_addr_n, is_add=0)
4444
4445 def test_464xlat_ce_no_nat(self):
4446 """ Test 464XLAT CE without NAT44 """
4447
4448 self.configure_xlat()
4449
4450 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4451 self.dst_ip6_pfx_len)
4452 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4453 self.src_ip6_pfx_len)
4454
4455 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4456 self.pg0.add_stream(pkts)
4457 self.pg_enable_capture(self.pg_interfaces)
4458 self.pg_start()
4459 capture = self.pg1.get_capture(len(pkts))
4460 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4461 nat_ip=out_dst_ip6, same_port=True)
4462
4463 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4464 self.pg1.add_stream(pkts)
4465 self.pg_enable_capture(self.pg_interfaces)
4466 self.pg_start()
4467 capture = self.pg0.get_capture(len(pkts))
4468 self.verify_capture_in(capture, self.pg0)
4469
4470
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004471class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004472 """ Deterministic NAT Test Cases """
4473
4474 @classmethod
4475 def setUpConstants(cls):
4476 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004477 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004478
4479 @classmethod
4480 def setUpClass(cls):
4481 super(TestDeterministicNAT, cls).setUpClass()
4482
4483 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004484 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004485 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004486 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004487 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004488 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004489 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004490
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004491 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004492 cls.interfaces = list(cls.pg_interfaces)
4493
4494 for i in cls.interfaces:
4495 i.admin_up()
4496 i.config_ip4()
4497 i.resolve_arp()
4498
Martin Gálik977c1cb2017-03-30 23:21:51 -07004499 cls.pg0.generate_remote_hosts(2)
4500 cls.pg0.configure_ipv4_neighbors()
4501
Matus Fabian066f0342017-02-10 03:48:01 -08004502 except Exception:
4503 super(TestDeterministicNAT, cls).tearDownClass()
4504 raise
4505
Martin Gálik977c1cb2017-03-30 23:21:51 -07004506 def create_stream_in(self, in_if, out_if, ttl=64):
4507 """
4508 Create packet stream for inside network
4509
4510 :param in_if: Inside interface
4511 :param out_if: Outside interface
4512 :param ttl: TTL of generated packets
4513 """
4514 pkts = []
4515 # TCP
4516 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4517 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004518 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004519 pkts.append(p)
4520
4521 # UDP
4522 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4523 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004524 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004525 pkts.append(p)
4526
4527 # ICMP
4528 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4529 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4530 ICMP(id=self.icmp_id_in, type='echo-request'))
4531 pkts.append(p)
4532
4533 return pkts
4534
4535 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4536 """
4537 Create packet stream for outside network
4538
4539 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004540 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004541 :param ttl: TTL of generated packets
4542 """
4543 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004544 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004545 pkts = []
4546 # TCP
4547 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4548 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004549 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004550 pkts.append(p)
4551
4552 # UDP
4553 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4554 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004555 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004556 pkts.append(p)
4557
4558 # ICMP
4559 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4560 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4561 ICMP(id=self.icmp_external_id, type='echo-reply'))
4562 pkts.append(p)
4563
4564 return pkts
4565
4566 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4567 """
4568 Verify captured packets on outside network
4569
4570 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004571 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004572 :param same_port: Sorce port number is not translated (Default False)
4573 :param packet_num: Expected number of packets (Default 3)
4574 """
4575 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004576 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004577 self.assertEqual(packet_num, len(capture))
4578 for packet in capture:
4579 try:
4580 self.assertEqual(packet[IP].src, nat_ip)
4581 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004582 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004583 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004584 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004585 else:
4586 self.icmp_external_id = packet[ICMP].id
4587 except:
4588 self.logger.error(ppp("Unexpected or invalid packet "
4589 "(outside network):", packet))
4590 raise
4591
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004592 def verify_ipfix_max_entries_per_user(self, data):
4593 """
4594 Verify IPFIX maximum entries per user exceeded event
4595
4596 :param data: Decoded IPFIX data records
4597 """
4598 self.assertEqual(1, len(data))
4599 record = data[0]
4600 # natEvent
4601 self.assertEqual(ord(record[230]), 13)
4602 # natQuotaExceededEvent
4603 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004604 # maxEntriesPerUser
4605 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004606 # sourceIPv4Address
4607 self.assertEqual(self.pg0.remote_ip4n, record[8])
4608
Matus Fabian066f0342017-02-10 03:48:01 -08004609 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004610 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004611 in_addr = '172.16.255.0'
4612 out_addr = '172.17.255.50'
4613 in_addr_t = '172.16.255.20'
4614 in_addr_n = socket.inet_aton(in_addr)
4615 out_addr_n = socket.inet_aton(out_addr)
4616 in_addr_t_n = socket.inet_aton(in_addr_t)
4617 in_plen = 24
4618 out_plen = 32
4619
Matus Fabian2ba92e32017-08-21 07:05:03 -07004620 nat_config = self.vapi.nat_show_config()
4621 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004622
Matus Fabian2ba92e32017-08-21 07:05:03 -07004623 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004624
Matus Fabian2ba92e32017-08-21 07:05:03 -07004625 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004626 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004627 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004628 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4629
Matus Fabian2ba92e32017-08-21 07:05:03 -07004630 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004631 self.assertEqual(len(deterministic_mappings), 1)
4632 dsm = deterministic_mappings[0]
4633 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4634 self.assertEqual(in_plen, dsm.in_plen)
4635 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4636 self.assertEqual(out_plen, dsm.out_plen)
4637
Matus Fabian2ba92e32017-08-21 07:05:03 -07004638 self.clear_nat_det()
4639 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004640 self.assertEqual(len(deterministic_mappings), 0)
4641
Matus Fabian6a0946f2017-04-12 03:36:13 -07004642 def test_set_timeouts(self):
4643 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004644 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004645
Matus Fabian2ba92e32017-08-21 07:05:03 -07004646 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4647 timeouts_before.tcp_established + 10,
4648 timeouts_before.tcp_transitory + 10,
4649 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004650
Matus Fabian2ba92e32017-08-21 07:05:03 -07004651 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004652
4653 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4654 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4655 self.assertNotEqual(timeouts_before.tcp_established,
4656 timeouts_after.tcp_established)
4657 self.assertNotEqual(timeouts_before.tcp_transitory,
4658 timeouts_after.tcp_transitory)
4659
Martin Gálik977c1cb2017-03-30 23:21:51 -07004660 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004661 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004662
4663 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004664
Matus Fabian2ba92e32017-08-21 07:05:03 -07004665 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4666 32,
4667 socket.inet_aton(nat_ip),
4668 32)
4669 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4670 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4671 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004672
4673 # in2out
4674 pkts = self.create_stream_in(self.pg0, self.pg1)
4675 self.pg0.add_stream(pkts)
4676 self.pg_enable_capture(self.pg_interfaces)
4677 self.pg_start()
4678 capture = self.pg1.get_capture(len(pkts))
4679 self.verify_capture_out(capture, nat_ip)
4680
4681 # out2in
4682 pkts = self.create_stream_out(self.pg1, nat_ip)
4683 self.pg1.add_stream(pkts)
4684 self.pg_enable_capture(self.pg_interfaces)
4685 self.pg_start()
4686 capture = self.pg0.get_capture(len(pkts))
4687 self.verify_capture_in(capture, self.pg0)
4688
Martin Gálik9806eae2017-04-25 01:25:08 -07004689 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004690 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004691 self.assertEqual(len(sessions), 3)
4692
4693 # TCP session
4694 s = sessions[0]
4695 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4696 self.assertEqual(s.in_port, self.tcp_port_in)
4697 self.assertEqual(s.out_port, self.tcp_port_out)
4698 self.assertEqual(s.ext_port, self.tcp_external_port)
4699
4700 # UDP session
4701 s = sessions[1]
4702 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4703 self.assertEqual(s.in_port, self.udp_port_in)
4704 self.assertEqual(s.out_port, self.udp_port_out)
4705 self.assertEqual(s.ext_port, self.udp_external_port)
4706
4707 # ICMP session
4708 s = sessions[2]
4709 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4710 self.assertEqual(s.in_port, self.icmp_id_in)
4711 self.assertEqual(s.out_port, self.icmp_external_id)
4712
Martin Gálik977c1cb2017-03-30 23:21:51 -07004713 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004714 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004715
4716 nat_ip = "10.0.0.10"
4717 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004718 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004719
4720 host0 = self.pg0.remote_hosts[0]
4721 host1 = self.pg0.remote_hosts[1]
4722
Matus Fabian2ba92e32017-08-21 07:05:03 -07004723 self.vapi.nat_det_add_del_map(host0.ip4n,
4724 24,
4725 socket.inet_aton(nat_ip),
4726 32)
4727 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4728 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4729 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004730
4731 # host0 to out
4732 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4733 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004734 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004735 self.pg0.add_stream(p)
4736 self.pg_enable_capture(self.pg_interfaces)
4737 self.pg_start()
4738 capture = self.pg1.get_capture(1)
4739 p = capture[0]
4740 try:
4741 ip = p[IP]
4742 tcp = p[TCP]
4743 self.assertEqual(ip.src, nat_ip)
4744 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004745 self.assertEqual(tcp.dport, external_port)
4746 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004747 except:
4748 self.logger.error(ppp("Unexpected or invalid packet:", p))
4749 raise
4750
4751 # host1 to out
4752 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4753 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004754 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004755 self.pg0.add_stream(p)
4756 self.pg_enable_capture(self.pg_interfaces)
4757 self.pg_start()
4758 capture = self.pg1.get_capture(1)
4759 p = capture[0]
4760 try:
4761 ip = p[IP]
4762 tcp = p[TCP]
4763 self.assertEqual(ip.src, nat_ip)
4764 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004765 self.assertEqual(tcp.dport, external_port)
4766 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004767 except:
4768 self.logger.error(ppp("Unexpected or invalid packet:", p))
4769 raise
4770
Matus Fabian2ba92e32017-08-21 07:05:03 -07004771 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004772 self.assertEqual(1, len(dms))
4773 self.assertEqual(2, dms[0].ses_num)
4774
4775 # out to host0
4776 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4777 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004778 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004779 self.pg1.add_stream(p)
4780 self.pg_enable_capture(self.pg_interfaces)
4781 self.pg_start()
4782 capture = self.pg0.get_capture(1)
4783 p = capture[0]
4784 try:
4785 ip = p[IP]
4786 tcp = p[TCP]
4787 self.assertEqual(ip.src, self.pg1.remote_ip4)
4788 self.assertEqual(ip.dst, host0.ip4)
4789 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004790 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004791 except:
4792 self.logger.error(ppp("Unexpected or invalid packet:", p))
4793 raise
4794
4795 # out to host1
4796 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4797 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004798 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004799 self.pg1.add_stream(p)
4800 self.pg_enable_capture(self.pg_interfaces)
4801 self.pg_start()
4802 capture = self.pg0.get_capture(1)
4803 p = capture[0]
4804 try:
4805 ip = p[IP]
4806 tcp = p[TCP]
4807 self.assertEqual(ip.src, self.pg1.remote_ip4)
4808 self.assertEqual(ip.dst, host1.ip4)
4809 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004810 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004811 except:
4812 self.logger.error(ppp("Unexpected or invalid packet", p))
4813 raise
4814
Martin Gálik6bc8c642017-04-19 01:12:27 -07004815 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004816 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4817 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004818 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004819 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004820 dms = self.vapi.nat_det_map_dump()
4821 self.assertEqual(dms[0].ses_num, 1)
4822
4823 self.vapi.nat_det_close_session_in(host0.ip4n,
4824 port_in,
4825 self.pg1.remote_ip4n,
4826 external_port)
4827 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004828 self.assertEqual(dms[0].ses_num, 0)
4829
Martin Gálik977c1cb2017-03-30 23:21:51 -07004830 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004831 """ Deterministic NAT TCP session close from inside network """
4832 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4833 32,
4834 socket.inet_aton(self.nat_addr),
4835 32)
4836 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4837 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4838 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004839
4840 self.initiate_tcp_session(self.pg0, self.pg1)
4841
4842 # close the session from inside
4843 try:
4844 # FIN packet in -> out
4845 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4846 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004847 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004848 flags="F"))
4849 self.pg0.add_stream(p)
4850 self.pg_enable_capture(self.pg_interfaces)
4851 self.pg_start()
4852 self.pg1.get_capture(1)
4853
4854 pkts = []
4855
4856 # ACK packet out -> in
4857 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004858 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004859 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004860 flags="A"))
4861 pkts.append(p)
4862
4863 # FIN packet out -> in
4864 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004865 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004866 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004867 flags="F"))
4868 pkts.append(p)
4869
4870 self.pg1.add_stream(pkts)
4871 self.pg_enable_capture(self.pg_interfaces)
4872 self.pg_start()
4873 self.pg0.get_capture(2)
4874
4875 # ACK packet in -> out
4876 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4877 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004878 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004879 flags="A"))
4880 self.pg0.add_stream(p)
4881 self.pg_enable_capture(self.pg_interfaces)
4882 self.pg_start()
4883 self.pg1.get_capture(1)
4884
Matus Fabian2ba92e32017-08-21 07:05:03 -07004885 # Check if deterministic NAT44 closed the session
4886 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004887 self.assertEqual(0, dms[0].ses_num)
4888 except:
4889 self.logger.error("TCP session termination failed")
4890 raise
4891
4892 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004893 """ Deterministic NAT TCP session close from outside network """
4894 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4895 32,
4896 socket.inet_aton(self.nat_addr),
4897 32)
4898 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4899 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4900 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004901
4902 self.initiate_tcp_session(self.pg0, self.pg1)
4903
4904 # close the session from outside
4905 try:
4906 # FIN packet out -> in
4907 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004908 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004909 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004910 flags="F"))
4911 self.pg1.add_stream(p)
4912 self.pg_enable_capture(self.pg_interfaces)
4913 self.pg_start()
4914 self.pg0.get_capture(1)
4915
4916 pkts = []
4917
4918 # ACK packet in -> out
4919 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4920 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004921 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004922 flags="A"))
4923 pkts.append(p)
4924
4925 # ACK packet in -> out
4926 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4927 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004928 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004929 flags="F"))
4930 pkts.append(p)
4931
4932 self.pg0.add_stream(pkts)
4933 self.pg_enable_capture(self.pg_interfaces)
4934 self.pg_start()
4935 self.pg1.get_capture(2)
4936
4937 # ACK packet out -> in
4938 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004939 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004940 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004941 flags="A"))
4942 self.pg1.add_stream(p)
4943 self.pg_enable_capture(self.pg_interfaces)
4944 self.pg_start()
4945 self.pg0.get_capture(1)
4946
Matus Fabian2ba92e32017-08-21 07:05:03 -07004947 # Check if deterministic NAT44 closed the session
4948 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004949 self.assertEqual(0, dms[0].ses_num)
4950 except:
4951 self.logger.error("TCP session termination failed")
4952 raise
4953
4954 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4955 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004956 """ Deterministic NAT session timeouts """
4957 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4958 32,
4959 socket.inet_aton(self.nat_addr),
4960 32)
4961 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4962 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4963 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004964
4965 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004966 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004967 pkts = self.create_stream_in(self.pg0, self.pg1)
4968 self.pg0.add_stream(pkts)
4969 self.pg_enable_capture(self.pg_interfaces)
4970 self.pg_start()
4971 capture = self.pg1.get_capture(len(pkts))
4972 sleep(15)
4973
Matus Fabian2ba92e32017-08-21 07:05:03 -07004974 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004975 self.assertEqual(0, dms[0].ses_num)
4976
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004977 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004978 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004979 """ Deterministic NAT maximum sessions per user limit """
4980 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4981 32,
4982 socket.inet_aton(self.nat_addr),
4983 32)
4984 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4985 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4986 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004987 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4988 src_address=self.pg2.local_ip4n,
4989 path_mtu=512,
4990 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004991 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004992
4993 pkts = []
4994 for port in range(1025, 2025):
4995 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4996 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4997 UDP(sport=port, dport=port))
4998 pkts.append(p)
4999
5000 self.pg0.add_stream(pkts)
5001 self.pg_enable_capture(self.pg_interfaces)
5002 self.pg_start()
5003 capture = self.pg1.get_capture(len(pkts))
5004
5005 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5006 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005007 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005008 self.pg0.add_stream(p)
5009 self.pg_enable_capture(self.pg_interfaces)
5010 self.pg_start()
5011 capture = self.pg1.assert_nothing_captured()
5012
Martin Gálikf7e655d2017-04-27 02:13:26 -07005013 # verify ICMP error packet
5014 capture = self.pg0.get_capture(1)
5015 p = capture[0]
5016 self.assertTrue(p.haslayer(ICMP))
5017 icmp = p[ICMP]
5018 self.assertEqual(icmp.type, 3)
5019 self.assertEqual(icmp.code, 1)
5020 self.assertTrue(icmp.haslayer(IPerror))
5021 inner_ip = icmp[IPerror]
5022 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5023 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5024
Matus Fabian2ba92e32017-08-21 07:05:03 -07005025 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005026
5027 self.assertEqual(1000, dms[0].ses_num)
5028
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005029 # verify IPFIX logging
5030 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005031 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005032 capture = self.pg2.get_capture(2)
5033 ipfix = IPFIXDecoder()
5034 # first load template
5035 for p in capture:
5036 self.assertTrue(p.haslayer(IPFIX))
5037 if p.haslayer(Template):
5038 ipfix.add_template(p.getlayer(Template))
5039 # verify events in data set
5040 for p in capture:
5041 if p.haslayer(Data):
5042 data = ipfix.decode_data_set(p.getlayer(Set))
5043 self.verify_ipfix_max_entries_per_user(data)
5044
Matus Fabian2ba92e32017-08-21 07:05:03 -07005045 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005046 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005047 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005048 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005049 self.vapi.nat_ipfix(enable=0)
5050 self.vapi.nat_det_set_timeouts()
5051 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005052 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005053 self.vapi.nat_det_add_del_map(dsm.in_addr,
5054 dsm.in_plen,
5055 dsm.out_addr,
5056 dsm.out_plen,
5057 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005058
Matus Fabian2ba92e32017-08-21 07:05:03 -07005059 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005060 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005061 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5062 intf.is_inside,
5063 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005064
Matus Fabian066f0342017-02-10 03:48:01 -08005065 def tearDown(self):
5066 super(TestDeterministicNAT, self).tearDown()
5067 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005068 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5069 self.logger.info(
5070 self.vapi.cli("show nat44 deterministic mappings"))
5071 self.logger.info(
5072 self.vapi.cli("show nat44 deterministic timeouts"))
5073 self.logger.info(
5074 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005075 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005076
Matus Fabian06596c52017-06-06 04:53:28 -07005077
5078class TestNAT64(MethodHolder):
5079 """ NAT64 Test Cases """
5080
5081 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005082 def setUpConstants(cls):
5083 super(TestNAT64, cls).setUpConstants()
5084 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5085 "nat64 st hash buckets 256", "}"])
5086
5087 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005088 def setUpClass(cls):
5089 super(TestNAT64, cls).setUpClass()
5090
5091 try:
5092 cls.tcp_port_in = 6303
5093 cls.tcp_port_out = 6303
5094 cls.udp_port_in = 6304
5095 cls.udp_port_out = 6304
5096 cls.icmp_id_in = 6305
5097 cls.icmp_id_out = 6305
5098 cls.nat_addr = '10.0.0.3'
5099 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005100 cls.vrf1_id = 10
5101 cls.vrf1_nat_addr = '10.0.10.3'
5102 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5103 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005104 cls.ipfix_src_port = 4739
5105 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005106
Matus Fabian0938dcf2017-11-08 01:59:38 -08005107 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07005108 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005109 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005110 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5111
Neale Ranns15002542017-09-10 04:39:11 -07005112 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5113
Matus Fabian029f3d22017-06-15 02:28:50 -07005114 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5115
5116 cls.pg0.generate_remote_hosts(2)
5117
Matus Fabian06596c52017-06-06 04:53:28 -07005118 for i in cls.ip6_interfaces:
5119 i.admin_up()
5120 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005121 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005122
5123 for i in cls.ip4_interfaces:
5124 i.admin_up()
5125 i.config_ip4()
5126 i.resolve_arp()
5127
Matus Fabian36ea2d62017-10-24 04:13:49 -07005128 cls.pg3.admin_up()
5129 cls.pg3.config_ip4()
5130 cls.pg3.resolve_arp()
5131 cls.pg3.config_ip6()
5132 cls.pg3.configure_ipv6_neighbors()
5133
Matus Fabian06596c52017-06-06 04:53:28 -07005134 except Exception:
5135 super(TestNAT64, cls).tearDownClass()
5136 raise
5137
5138 def test_pool(self):
5139 """ Add/delete address to NAT64 pool """
5140 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5141
5142 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5143
5144 addresses = self.vapi.nat64_pool_addr_dump()
5145 self.assertEqual(len(addresses), 1)
5146 self.assertEqual(addresses[0].address, nat_addr)
5147
5148 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5149
5150 addresses = self.vapi.nat64_pool_addr_dump()
5151 self.assertEqual(len(addresses), 0)
5152
5153 def test_interface(self):
5154 """ Enable/disable NAT64 feature on the interface """
5155 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5156 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5157
5158 interfaces = self.vapi.nat64_interface_dump()
5159 self.assertEqual(len(interfaces), 2)
5160 pg0_found = False
5161 pg1_found = False
5162 for intf in interfaces:
5163 if intf.sw_if_index == self.pg0.sw_if_index:
5164 self.assertEqual(intf.is_inside, 1)
5165 pg0_found = True
5166 elif intf.sw_if_index == self.pg1.sw_if_index:
5167 self.assertEqual(intf.is_inside, 0)
5168 pg1_found = True
5169 self.assertTrue(pg0_found)
5170 self.assertTrue(pg1_found)
5171
5172 features = self.vapi.cli("show interface features pg0")
5173 self.assertNotEqual(features.find('nat64-in2out'), -1)
5174 features = self.vapi.cli("show interface features pg1")
5175 self.assertNotEqual(features.find('nat64-out2in'), -1)
5176
5177 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5178 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5179
5180 interfaces = self.vapi.nat64_interface_dump()
5181 self.assertEqual(len(interfaces), 0)
5182
5183 def test_static_bib(self):
5184 """ Add/delete static BIB entry """
5185 in_addr = socket.inet_pton(socket.AF_INET6,
5186 '2001:db8:85a3::8a2e:370:7334')
5187 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5188 in_port = 1234
5189 out_port = 5678
5190 proto = IP_PROTOS.tcp
5191
5192 self.vapi.nat64_add_del_static_bib(in_addr,
5193 out_addr,
5194 in_port,
5195 out_port,
5196 proto)
5197 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5198 static_bib_num = 0
5199 for bibe in bib:
5200 if bibe.is_static:
5201 static_bib_num += 1
5202 self.assertEqual(bibe.i_addr, in_addr)
5203 self.assertEqual(bibe.o_addr, out_addr)
5204 self.assertEqual(bibe.i_port, in_port)
5205 self.assertEqual(bibe.o_port, out_port)
5206 self.assertEqual(static_bib_num, 1)
5207
5208 self.vapi.nat64_add_del_static_bib(in_addr,
5209 out_addr,
5210 in_port,
5211 out_port,
5212 proto,
5213 is_add=0)
5214 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5215 static_bib_num = 0
5216 for bibe in bib:
5217 if bibe.is_static:
5218 static_bib_num += 1
5219 self.assertEqual(static_bib_num, 0)
5220
5221 def test_set_timeouts(self):
5222 """ Set NAT64 timeouts """
5223 # verify default values
5224 timeouts = self.vapi.nat64_get_timeouts()
5225 self.assertEqual(timeouts.udp, 300)
5226 self.assertEqual(timeouts.icmp, 60)
5227 self.assertEqual(timeouts.tcp_trans, 240)
5228 self.assertEqual(timeouts.tcp_est, 7440)
5229 self.assertEqual(timeouts.tcp_incoming_syn, 6)
5230
5231 # set and verify custom values
5232 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5233 tcp_est=7450, tcp_incoming_syn=10)
5234 timeouts = self.vapi.nat64_get_timeouts()
5235 self.assertEqual(timeouts.udp, 200)
5236 self.assertEqual(timeouts.icmp, 30)
5237 self.assertEqual(timeouts.tcp_trans, 250)
5238 self.assertEqual(timeouts.tcp_est, 7450)
5239 self.assertEqual(timeouts.tcp_incoming_syn, 10)
5240
5241 def test_dynamic(self):
5242 """ NAT64 dynamic translation test """
5243 self.tcp_port_in = 6303
5244 self.udp_port_in = 6304
5245 self.icmp_id_in = 6305
5246
5247 ses_num_start = self.nat64_get_ses_num()
5248
5249 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5250 self.nat_addr_n)
5251 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5252 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5253
5254 # in2out
5255 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5256 self.pg0.add_stream(pkts)
5257 self.pg_enable_capture(self.pg_interfaces)
5258 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005259 capture = self.pg1.get_capture(len(pkts))
5260 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005261 dst_ip=self.pg1.remote_ip4)
5262
5263 # out2in
5264 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5265 self.pg1.add_stream(pkts)
5266 self.pg_enable_capture(self.pg_interfaces)
5267 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005268 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005269 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5270 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5271
5272 # in2out
5273 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5274 self.pg0.add_stream(pkts)
5275 self.pg_enable_capture(self.pg_interfaces)
5276 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005277 capture = self.pg1.get_capture(len(pkts))
5278 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005279 dst_ip=self.pg1.remote_ip4)
5280
5281 # out2in
5282 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5283 self.pg1.add_stream(pkts)
5284 self.pg_enable_capture(self.pg_interfaces)
5285 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005286 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005287 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5288
5289 ses_num_end = self.nat64_get_ses_num()
5290
5291 self.assertEqual(ses_num_end - ses_num_start, 3)
5292
Matus Fabian029f3d22017-06-15 02:28:50 -07005293 # tenant with specific VRF
5294 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5295 self.vrf1_nat_addr_n,
5296 vrf_id=self.vrf1_id)
5297 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5298
5299 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5300 self.pg2.add_stream(pkts)
5301 self.pg_enable_capture(self.pg_interfaces)
5302 self.pg_start()
5303 capture = self.pg1.get_capture(len(pkts))
5304 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5305 dst_ip=self.pg1.remote_ip4)
5306
5307 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5308 self.pg1.add_stream(pkts)
5309 self.pg_enable_capture(self.pg_interfaces)
5310 self.pg_start()
5311 capture = self.pg2.get_capture(len(pkts))
5312 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5313
Matus Fabian06596c52017-06-06 04:53:28 -07005314 def test_static(self):
5315 """ NAT64 static translation test """
5316 self.tcp_port_in = 60303
5317 self.udp_port_in = 60304
5318 self.icmp_id_in = 60305
5319 self.tcp_port_out = 60303
5320 self.udp_port_out = 60304
5321 self.icmp_id_out = 60305
5322
5323 ses_num_start = self.nat64_get_ses_num()
5324
5325 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5326 self.nat_addr_n)
5327 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5328 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5329
5330 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5331 self.nat_addr_n,
5332 self.tcp_port_in,
5333 self.tcp_port_out,
5334 IP_PROTOS.tcp)
5335 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5336 self.nat_addr_n,
5337 self.udp_port_in,
5338 self.udp_port_out,
5339 IP_PROTOS.udp)
5340 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5341 self.nat_addr_n,
5342 self.icmp_id_in,
5343 self.icmp_id_out,
5344 IP_PROTOS.icmp)
5345
5346 # in2out
5347 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5348 self.pg0.add_stream(pkts)
5349 self.pg_enable_capture(self.pg_interfaces)
5350 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005351 capture = self.pg1.get_capture(len(pkts))
5352 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005353 dst_ip=self.pg1.remote_ip4, same_port=True)
5354
5355 # out2in
5356 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5357 self.pg1.add_stream(pkts)
5358 self.pg_enable_capture(self.pg_interfaces)
5359 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005360 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005361 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5362 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5363
5364 ses_num_end = self.nat64_get_ses_num()
5365
5366 self.assertEqual(ses_num_end - ses_num_start, 3)
5367
5368 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5369 def test_session_timeout(self):
5370 """ NAT64 session timeout """
5371 self.icmp_id_in = 1234
5372 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5373 self.nat_addr_n)
5374 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5375 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5376 self.vapi.nat64_set_timeouts(icmp=5)
5377
5378 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5379 self.pg0.add_stream(pkts)
5380 self.pg_enable_capture(self.pg_interfaces)
5381 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005382 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005383
5384 ses_num_before_timeout = self.nat64_get_ses_num()
5385
5386 sleep(15)
5387
5388 # ICMP session after timeout
5389 ses_num_after_timeout = self.nat64_get_ses_num()
5390 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5391
Matus Fabian732036d2017-06-08 05:24:28 -07005392 def test_icmp_error(self):
5393 """ NAT64 ICMP Error message translation """
5394 self.tcp_port_in = 6303
5395 self.udp_port_in = 6304
5396 self.icmp_id_in = 6305
5397
5398 ses_num_start = self.nat64_get_ses_num()
5399
5400 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5401 self.nat_addr_n)
5402 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5403 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5404
5405 # send some packets to create sessions
5406 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5407 self.pg0.add_stream(pkts)
5408 self.pg_enable_capture(self.pg_interfaces)
5409 self.pg_start()
5410 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005411 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005412 nat_ip=self.nat_addr,
5413 dst_ip=self.pg1.remote_ip4)
5414
5415 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5416 self.pg1.add_stream(pkts)
5417 self.pg_enable_capture(self.pg_interfaces)
5418 self.pg_start()
5419 capture_ip6 = self.pg0.get_capture(len(pkts))
5420 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5421 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5422 self.pg0.remote_ip6)
5423
5424 # in2out
5425 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5426 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5427 ICMPv6DestUnreach(code=1) /
5428 packet[IPv6] for packet in capture_ip6]
5429 self.pg0.add_stream(pkts)
5430 self.pg_enable_capture(self.pg_interfaces)
5431 self.pg_start()
5432 capture = self.pg1.get_capture(len(pkts))
5433 for packet in capture:
5434 try:
5435 self.assertEqual(packet[IP].src, self.nat_addr)
5436 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5437 self.assertEqual(packet[ICMP].type, 3)
5438 self.assertEqual(packet[ICMP].code, 13)
5439 inner = packet[IPerror]
5440 self.assertEqual(inner.src, self.pg1.remote_ip4)
5441 self.assertEqual(inner.dst, self.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005442 self.check_icmp_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005443 if inner.haslayer(TCPerror):
5444 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5445 elif inner.haslayer(UDPerror):
5446 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5447 else:
5448 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5449 except:
5450 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5451 raise
5452
5453 # out2in
5454 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5455 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5456 ICMP(type=3, code=13) /
5457 packet[IP] for packet in capture_ip4]
5458 self.pg1.add_stream(pkts)
5459 self.pg_enable_capture(self.pg_interfaces)
5460 self.pg_start()
5461 capture = self.pg0.get_capture(len(pkts))
5462 for packet in capture:
5463 try:
5464 self.assertEqual(packet[IPv6].src, ip.src)
5465 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5466 icmp = packet[ICMPv6DestUnreach]
5467 self.assertEqual(icmp.code, 1)
5468 inner = icmp[IPerror6]
5469 self.assertEqual(inner.src, self.pg0.remote_ip6)
5470 self.assertEqual(inner.dst, ip.src)
Matus Fabian029f3d22017-06-15 02:28:50 -07005471 self.check_icmpv6_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005472 if inner.haslayer(TCPerror):
5473 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5474 elif inner.haslayer(UDPerror):
5475 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5476 else:
5477 self.assertEqual(inner[ICMPv6EchoRequest].id,
5478 self.icmp_id_in)
5479 except:
5480 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5481 raise
5482
Matus Fabian029f3d22017-06-15 02:28:50 -07005483 def test_hairpinning(self):
5484 """ NAT64 hairpinning """
5485
5486 client = self.pg0.remote_hosts[0]
5487 server = self.pg0.remote_hosts[1]
5488 server_tcp_in_port = 22
5489 server_tcp_out_port = 4022
5490 server_udp_in_port = 23
5491 server_udp_out_port = 4023
5492 client_tcp_in_port = 1234
5493 client_udp_in_port = 1235
5494 client_tcp_out_port = 0
5495 client_udp_out_port = 0
5496 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5497 nat_addr_ip6 = ip.src
5498
5499 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5500 self.nat_addr_n)
5501 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5502 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5503
5504 self.vapi.nat64_add_del_static_bib(server.ip6n,
5505 self.nat_addr_n,
5506 server_tcp_in_port,
5507 server_tcp_out_port,
5508 IP_PROTOS.tcp)
5509 self.vapi.nat64_add_del_static_bib(server.ip6n,
5510 self.nat_addr_n,
5511 server_udp_in_port,
5512 server_udp_out_port,
5513 IP_PROTOS.udp)
5514
5515 # client to server
5516 pkts = []
5517 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5518 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5519 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5520 pkts.append(p)
5521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5522 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5523 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5524 pkts.append(p)
5525 self.pg0.add_stream(pkts)
5526 self.pg_enable_capture(self.pg_interfaces)
5527 self.pg_start()
5528 capture = self.pg0.get_capture(len(pkts))
5529 for packet in capture:
5530 try:
5531 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5532 self.assertEqual(packet[IPv6].dst, server.ip6)
5533 if packet.haslayer(TCP):
5534 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5535 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
5536 self.check_tcp_checksum(packet)
5537 client_tcp_out_port = packet[TCP].sport
5538 else:
5539 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5540 self.assertEqual(packet[UDP].dport, server_udp_in_port)
5541 self.check_udp_checksum(packet)
5542 client_udp_out_port = packet[UDP].sport
5543 except:
5544 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5545 raise
5546
5547 # server to client
5548 pkts = []
5549 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5550 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5551 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5552 pkts.append(p)
5553 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5554 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5555 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5556 pkts.append(p)
5557 self.pg0.add_stream(pkts)
5558 self.pg_enable_capture(self.pg_interfaces)
5559 self.pg_start()
5560 capture = self.pg0.get_capture(len(pkts))
5561 for packet in capture:
5562 try:
5563 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5564 self.assertEqual(packet[IPv6].dst, client.ip6)
5565 if packet.haslayer(TCP):
5566 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5567 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
5568 self.check_tcp_checksum(packet)
5569 else:
5570 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5571 self.assertEqual(packet[UDP].dport, client_udp_in_port)
5572 self.check_udp_checksum(packet)
5573 except:
5574 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5575 raise
5576
5577 # ICMP error
5578 pkts = []
5579 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5580 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5581 ICMPv6DestUnreach(code=1) /
5582 packet[IPv6] for packet in capture]
5583 self.pg0.add_stream(pkts)
5584 self.pg_enable_capture(self.pg_interfaces)
5585 self.pg_start()
5586 capture = self.pg0.get_capture(len(pkts))
5587 for packet in capture:
5588 try:
5589 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5590 self.assertEqual(packet[IPv6].dst, server.ip6)
5591 icmp = packet[ICMPv6DestUnreach]
5592 self.assertEqual(icmp.code, 1)
5593 inner = icmp[IPerror6]
5594 self.assertEqual(inner.src, server.ip6)
5595 self.assertEqual(inner.dst, nat_addr_ip6)
5596 self.check_icmpv6_checksum(packet)
5597 if inner.haslayer(TCPerror):
5598 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5599 self.assertEqual(inner[TCPerror].dport,
5600 client_tcp_out_port)
5601 else:
5602 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5603 self.assertEqual(inner[UDPerror].dport,
5604 client_udp_out_port)
5605 except:
5606 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5607 raise
5608
Matus Fabian428dc912017-06-21 06:15:18 -07005609 def test_prefix(self):
5610 """ NAT64 Network-Specific Prefix """
5611
5612 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5613 self.nat_addr_n)
5614 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5615 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5616 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5617 self.vrf1_nat_addr_n,
5618 vrf_id=self.vrf1_id)
5619 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5620
5621 # Add global prefix
5622 global_pref64 = "2001:db8::"
5623 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5624 global_pref64_len = 32
5625 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5626
5627 prefix = self.vapi.nat64_prefix_dump()
5628 self.assertEqual(len(prefix), 1)
5629 self.assertEqual(prefix[0].prefix, global_pref64_n)
5630 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5631 self.assertEqual(prefix[0].vrf_id, 0)
5632
5633 # Add tenant specific prefix
5634 vrf1_pref64 = "2001:db8:122:300::"
5635 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5636 vrf1_pref64_len = 56
5637 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5638 vrf1_pref64_len,
5639 vrf_id=self.vrf1_id)
5640 prefix = self.vapi.nat64_prefix_dump()
5641 self.assertEqual(len(prefix), 2)
5642
5643 # Global prefix
5644 pkts = self.create_stream_in_ip6(self.pg0,
5645 self.pg1,
5646 pref=global_pref64,
5647 plen=global_pref64_len)
5648 self.pg0.add_stream(pkts)
5649 self.pg_enable_capture(self.pg_interfaces)
5650 self.pg_start()
5651 capture = self.pg1.get_capture(len(pkts))
5652 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5653 dst_ip=self.pg1.remote_ip4)
5654
5655 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5656 self.pg1.add_stream(pkts)
5657 self.pg_enable_capture(self.pg_interfaces)
5658 self.pg_start()
5659 capture = self.pg0.get_capture(len(pkts))
5660 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5661 global_pref64,
5662 global_pref64_len)
5663 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5664
5665 # Tenant specific prefix
5666 pkts = self.create_stream_in_ip6(self.pg2,
5667 self.pg1,
5668 pref=vrf1_pref64,
5669 plen=vrf1_pref64_len)
5670 self.pg2.add_stream(pkts)
5671 self.pg_enable_capture(self.pg_interfaces)
5672 self.pg_start()
5673 capture = self.pg1.get_capture(len(pkts))
5674 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5675 dst_ip=self.pg1.remote_ip4)
5676
5677 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5678 self.pg1.add_stream(pkts)
5679 self.pg_enable_capture(self.pg_interfaces)
5680 self.pg_start()
5681 capture = self.pg2.get_capture(len(pkts))
5682 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5683 vrf1_pref64,
5684 vrf1_pref64_len)
5685 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5686
Matus Fabianf8cd5812017-07-11 03:55:02 -07005687 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005688 """ NAT64 translate packet with unknown protocol """
5689
5690 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5691 self.nat_addr_n)
5692 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5693 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5694 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5695
5696 # in2out
5697 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5698 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5699 TCP(sport=self.tcp_port_in, dport=20))
5700 self.pg0.add_stream(p)
5701 self.pg_enable_capture(self.pg_interfaces)
5702 self.pg_start()
5703 p = self.pg1.get_capture(1)
5704
5705 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005706 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005707 GRE() /
5708 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5709 TCP(sport=1234, dport=1234))
5710 self.pg0.add_stream(p)
5711 self.pg_enable_capture(self.pg_interfaces)
5712 self.pg_start()
5713 p = self.pg1.get_capture(1)
5714 packet = p[0]
5715 try:
5716 self.assertEqual(packet[IP].src, self.nat_addr)
5717 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5718 self.assertTrue(packet.haslayer(GRE))
5719 self.check_ip_checksum(packet)
5720 except:
5721 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5722 raise
5723
5724 # out2in
5725 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5726 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5727 GRE() /
5728 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5729 TCP(sport=1234, dport=1234))
5730 self.pg1.add_stream(p)
5731 self.pg_enable_capture(self.pg_interfaces)
5732 self.pg_start()
5733 p = self.pg0.get_capture(1)
5734 packet = p[0]
5735 try:
5736 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005737 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5738 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005739 except:
5740 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5741 raise
5742
Matus Fabianf8cd5812017-07-11 03:55:02 -07005743 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005744 """ NAT64 translate packet with unknown protocol - hairpinning """
5745
5746 client = self.pg0.remote_hosts[0]
5747 server = self.pg0.remote_hosts[1]
5748 server_tcp_in_port = 22
5749 server_tcp_out_port = 4022
5750 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005751 client_tcp_out_port = 1235
5752 server_nat_ip = "10.0.0.100"
5753 client_nat_ip = "10.0.0.110"
5754 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5755 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5756 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5757 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005758
Matus Fabianf8cd5812017-07-11 03:55:02 -07005759 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5760 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005761 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5762 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5763
5764 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005765 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005766 server_tcp_in_port,
5767 server_tcp_out_port,
5768 IP_PROTOS.tcp)
5769
Matus Fabianf8cd5812017-07-11 03:55:02 -07005770 self.vapi.nat64_add_del_static_bib(server.ip6n,
5771 server_nat_ip_n,
5772 0,
5773 0,
5774 IP_PROTOS.gre)
5775
5776 self.vapi.nat64_add_del_static_bib(client.ip6n,
5777 client_nat_ip_n,
5778 client_tcp_in_port,
5779 client_tcp_out_port,
5780 IP_PROTOS.tcp)
5781
Matus Fabian7968e6c2017-07-06 05:37:49 -07005782 # client to server
5783 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005784 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005785 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5786 self.pg0.add_stream(p)
5787 self.pg_enable_capture(self.pg_interfaces)
5788 self.pg_start()
5789 p = self.pg0.get_capture(1)
5790
5791 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005792 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005793 GRE() /
5794 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5795 TCP(sport=1234, dport=1234))
5796 self.pg0.add_stream(p)
5797 self.pg_enable_capture(self.pg_interfaces)
5798 self.pg_start()
5799 p = self.pg0.get_capture(1)
5800 packet = p[0]
5801 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005802 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005803 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005804 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005805 except:
5806 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5807 raise
5808
5809 # server to client
5810 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005811 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005812 GRE() /
5813 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5814 TCP(sport=1234, dport=1234))
5815 self.pg0.add_stream(p)
5816 self.pg_enable_capture(self.pg_interfaces)
5817 self.pg_start()
5818 p = self.pg0.get_capture(1)
5819 packet = p[0]
5820 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005821 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005822 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005823 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005824 except:
5825 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5826 raise
5827
Matus Fabian36ea2d62017-10-24 04:13:49 -07005828 def test_one_armed_nat64(self):
5829 """ One armed NAT64 """
5830 external_port = 0
5831 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5832 '64:ff9b::',
5833 96)
5834
5835 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5836 self.nat_addr_n)
5837 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5838 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5839
5840 # in2out
5841 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5842 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5843 TCP(sport=12345, dport=80))
5844 self.pg3.add_stream(p)
5845 self.pg_enable_capture(self.pg_interfaces)
5846 self.pg_start()
5847 capture = self.pg3.get_capture(1)
5848 p = capture[0]
5849 try:
5850 ip = p[IP]
5851 tcp = p[TCP]
5852 self.assertEqual(ip.src, self.nat_addr)
5853 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5854 self.assertNotEqual(tcp.sport, 12345)
5855 external_port = tcp.sport
5856 self.assertEqual(tcp.dport, 80)
5857 self.check_tcp_checksum(p)
5858 self.check_ip_checksum(p)
5859 except:
5860 self.logger.error(ppp("Unexpected or invalid packet:", p))
5861 raise
5862
5863 # out2in
5864 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5865 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5866 TCP(sport=80, dport=external_port))
5867 self.pg3.add_stream(p)
5868 self.pg_enable_capture(self.pg_interfaces)
5869 self.pg_start()
5870 capture = self.pg3.get_capture(1)
5871 p = capture[0]
5872 try:
5873 ip = p[IPv6]
5874 tcp = p[TCP]
5875 self.assertEqual(ip.src, remote_host_ip6)
5876 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5877 self.assertEqual(tcp.sport, 80)
5878 self.assertEqual(tcp.dport, 12345)
5879 self.check_tcp_checksum(p)
5880 except:
5881 self.logger.error(ppp("Unexpected or invalid packet:", p))
5882 raise
5883
Matus Fabianefcd1e92017-08-15 06:59:19 -07005884 def test_frag_in_order(self):
5885 """ NAT64 translate fragments arriving in order """
5886 self.tcp_port_in = random.randint(1025, 65535)
5887
5888 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5889 self.nat_addr_n)
5890 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5891 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5892
5893 reass = self.vapi.nat_reass_dump()
5894 reass_n_start = len(reass)
5895
5896 # in2out
5897 data = 'a' * 200
5898 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5899 self.tcp_port_in, 20, data)
5900 self.pg0.add_stream(pkts)
5901 self.pg_enable_capture(self.pg_interfaces)
5902 self.pg_start()
5903 frags = self.pg1.get_capture(len(pkts))
5904 p = self.reass_frags_and_verify(frags,
5905 self.nat_addr,
5906 self.pg1.remote_ip4)
5907 self.assertEqual(p[TCP].dport, 20)
5908 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5909 self.tcp_port_out = p[TCP].sport
5910 self.assertEqual(data, p[Raw].load)
5911
5912 # out2in
5913 data = "A" * 4 + "b" * 16 + "C" * 3
5914 pkts = self.create_stream_frag(self.pg1,
5915 self.nat_addr,
5916 20,
5917 self.tcp_port_out,
5918 data)
5919 self.pg1.add_stream(pkts)
5920 self.pg_enable_capture(self.pg_interfaces)
5921 self.pg_start()
5922 frags = self.pg0.get_capture(len(pkts))
5923 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5924 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5925 self.assertEqual(p[TCP].sport, 20)
5926 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5927 self.assertEqual(data, p[Raw].load)
5928
5929 reass = self.vapi.nat_reass_dump()
5930 reass_n_end = len(reass)
5931
5932 self.assertEqual(reass_n_end - reass_n_start, 2)
5933
5934 def test_reass_hairpinning(self):
5935 """ NAT64 fragments hairpinning """
5936 data = 'a' * 200
5937 client = self.pg0.remote_hosts[0]
5938 server = self.pg0.remote_hosts[1]
5939 server_in_port = random.randint(1025, 65535)
5940 server_out_port = random.randint(1025, 65535)
5941 client_in_port = random.randint(1025, 65535)
5942 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5943 nat_addr_ip6 = ip.src
5944
5945 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5946 self.nat_addr_n)
5947 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5948 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5949
5950 # add static BIB entry for server
5951 self.vapi.nat64_add_del_static_bib(server.ip6n,
5952 self.nat_addr_n,
5953 server_in_port,
5954 server_out_port,
5955 IP_PROTOS.tcp)
5956
5957 # send packet from host to server
5958 pkts = self.create_stream_frag_ip6(self.pg0,
5959 self.nat_addr,
5960 client_in_port,
5961 server_out_port,
5962 data)
5963 self.pg0.add_stream(pkts)
5964 self.pg_enable_capture(self.pg_interfaces)
5965 self.pg_start()
5966 frags = self.pg0.get_capture(len(pkts))
5967 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5968 self.assertNotEqual(p[TCP].sport, client_in_port)
5969 self.assertEqual(p[TCP].dport, server_in_port)
5970 self.assertEqual(data, p[Raw].load)
5971
5972 def test_frag_out_of_order(self):
5973 """ NAT64 translate fragments arriving out of order """
5974 self.tcp_port_in = random.randint(1025, 65535)
5975
5976 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5977 self.nat_addr_n)
5978 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5979 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5980
5981 # in2out
5982 data = 'a' * 200
5983 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5984 self.tcp_port_in, 20, data)
5985 pkts.reverse()
5986 self.pg0.add_stream(pkts)
5987 self.pg_enable_capture(self.pg_interfaces)
5988 self.pg_start()
5989 frags = self.pg1.get_capture(len(pkts))
5990 p = self.reass_frags_and_verify(frags,
5991 self.nat_addr,
5992 self.pg1.remote_ip4)
5993 self.assertEqual(p[TCP].dport, 20)
5994 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5995 self.tcp_port_out = p[TCP].sport
5996 self.assertEqual(data, p[Raw].load)
5997
5998 # out2in
5999 data = "A" * 4 + "B" * 16 + "C" * 3
6000 pkts = self.create_stream_frag(self.pg1,
6001 self.nat_addr,
6002 20,
6003 self.tcp_port_out,
6004 data)
6005 pkts.reverse()
6006 self.pg1.add_stream(pkts)
6007 self.pg_enable_capture(self.pg_interfaces)
6008 self.pg_start()
6009 frags = self.pg0.get_capture(len(pkts))
6010 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6011 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6012 self.assertEqual(p[TCP].sport, 20)
6013 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6014 self.assertEqual(data, p[Raw].load)
6015
Matus Fabian0938dcf2017-11-08 01:59:38 -08006016 def test_interface_addr(self):
6017 """ Acquire NAT64 pool addresses from interface """
6018 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6019
6020 # no address in NAT64 pool
6021 adresses = self.vapi.nat44_address_dump()
6022 self.assertEqual(0, len(adresses))
6023
6024 # configure interface address and check NAT64 address pool
6025 self.pg4.config_ip4()
6026 addresses = self.vapi.nat64_pool_addr_dump()
6027 self.assertEqual(len(addresses), 1)
6028 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6029
6030 # remove interface address and check NAT64 address pool
6031 self.pg4.unconfig_ip4()
6032 addresses = self.vapi.nat64_pool_addr_dump()
6033 self.assertEqual(0, len(adresses))
6034
Matus Fabiana431ad12018-01-04 04:03:14 -08006035 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6036 def test_ipfix_max_bibs_sessions(self):
6037 """ IPFIX logging maximum session and BIB entries exceeded """
6038 max_bibs = 1280
6039 max_sessions = 2560
6040 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6041 '64:ff9b::',
6042 96)
6043
6044 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6045 self.nat_addr_n)
6046 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6047 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6048
6049 pkts = []
6050 src = ""
6051 for i in range(0, max_bibs):
6052 src = "fd01:aa::%x" % (i)
6053 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6054 IPv6(src=src, dst=remote_host_ip6) /
6055 TCP(sport=12345, dport=80))
6056 pkts.append(p)
6057 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6058 IPv6(src=src, dst=remote_host_ip6) /
6059 TCP(sport=12345, dport=22))
6060 pkts.append(p)
6061 self.pg0.add_stream(pkts)
6062 self.pg_enable_capture(self.pg_interfaces)
6063 self.pg_start()
6064 self.pg1.get_capture(max_sessions)
6065
6066 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6067 src_address=self.pg3.local_ip4n,
6068 path_mtu=512,
6069 template_interval=10)
6070 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6071 src_port=self.ipfix_src_port)
6072
6073 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6074 IPv6(src=src, dst=remote_host_ip6) /
6075 TCP(sport=12345, dport=25))
6076 self.pg0.add_stream(p)
6077 self.pg_enable_capture(self.pg_interfaces)
6078 self.pg_start()
6079 self.pg1.get_capture(0)
6080 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6081 capture = self.pg3.get_capture(9)
6082 ipfix = IPFIXDecoder()
6083 # first load template
6084 for p in capture:
6085 self.assertTrue(p.haslayer(IPFIX))
6086 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6087 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6088 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6089 self.assertEqual(p[UDP].dport, 4739)
6090 self.assertEqual(p[IPFIX].observationDomainID,
6091 self.ipfix_domain_id)
6092 if p.haslayer(Template):
6093 ipfix.add_template(p.getlayer(Template))
6094 # verify events in data set
6095 for p in capture:
6096 if p.haslayer(Data):
6097 data = ipfix.decode_data_set(p.getlayer(Set))
6098 self.verify_ipfix_max_sessions(data, max_sessions)
6099
6100 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6101 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6102 TCP(sport=12345, dport=80))
6103 self.pg0.add_stream(p)
6104 self.pg_enable_capture(self.pg_interfaces)
6105 self.pg_start()
6106 self.pg1.get_capture(0)
6107 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6108 capture = self.pg3.get_capture(1)
6109 # verify events in data set
6110 for p in capture:
6111 self.assertTrue(p.haslayer(IPFIX))
6112 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6113 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6114 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6115 self.assertEqual(p[UDP].dport, 4739)
6116 self.assertEqual(p[IPFIX].observationDomainID,
6117 self.ipfix_domain_id)
6118 if p.haslayer(Data):
6119 data = ipfix.decode_data_set(p.getlayer(Set))
6120 self.verify_ipfix_max_bibs(data, max_bibs)
6121
6122 def test_ipfix_max_frags(self):
6123 """ IPFIX logging maximum fragments pending reassembly exceeded """
6124 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6125 self.nat_addr_n)
6126 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6127 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6128 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6129 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6130 src_address=self.pg3.local_ip4n,
6131 path_mtu=512,
6132 template_interval=10)
6133 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6134 src_port=self.ipfix_src_port)
6135
6136 data = 'a' * 200
6137 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6138 self.tcp_port_in, 20, data)
6139 self.pg0.add_stream(pkts[-1])
6140 self.pg_enable_capture(self.pg_interfaces)
6141 self.pg_start()
6142 self.pg1.get_capture(0)
6143 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6144 capture = self.pg3.get_capture(9)
6145 ipfix = IPFIXDecoder()
6146 # first load template
6147 for p in capture:
6148 self.assertTrue(p.haslayer(IPFIX))
6149 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6150 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6151 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6152 self.assertEqual(p[UDP].dport, 4739)
6153 self.assertEqual(p[IPFIX].observationDomainID,
6154 self.ipfix_domain_id)
6155 if p.haslayer(Template):
6156 ipfix.add_template(p.getlayer(Template))
6157 # verify events in data set
6158 for p in capture:
6159 if p.haslayer(Data):
6160 data = ipfix.decode_data_set(p.getlayer(Set))
6161 self.verify_ipfix_max_fragments_ip6(data, 0,
6162 self.pg0.remote_ip6n)
6163
6164 def test_ipfix_bib_ses(self):
6165 """ IPFIX logging NAT64 BIB/session create and delete events """
6166 self.tcp_port_in = random.randint(1025, 65535)
6167 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6168 '64:ff9b::',
6169 96)
6170
6171 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6172 self.nat_addr_n)
6173 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6174 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6175 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6176 src_address=self.pg3.local_ip4n,
6177 path_mtu=512,
6178 template_interval=10)
6179 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6180 src_port=self.ipfix_src_port)
6181
6182 # Create
6183 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6184 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6185 TCP(sport=self.tcp_port_in, dport=25))
6186 self.pg0.add_stream(p)
6187 self.pg_enable_capture(self.pg_interfaces)
6188 self.pg_start()
6189 p = self.pg1.get_capture(1)
6190 self.tcp_port_out = p[0][TCP].sport
6191 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6192 capture = self.pg3.get_capture(10)
6193 ipfix = IPFIXDecoder()
6194 # first load template
6195 for p in capture:
6196 self.assertTrue(p.haslayer(IPFIX))
6197 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6198 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6199 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6200 self.assertEqual(p[UDP].dport, 4739)
6201 self.assertEqual(p[IPFIX].observationDomainID,
6202 self.ipfix_domain_id)
6203 if p.haslayer(Template):
6204 ipfix.add_template(p.getlayer(Template))
6205 # verify events in data set
6206 for p in capture:
6207 if p.haslayer(Data):
6208 data = ipfix.decode_data_set(p.getlayer(Set))
6209 if ord(data[0][230]) == 10:
6210 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6211 elif ord(data[0][230]) == 6:
6212 self.verify_ipfix_nat64_ses(data,
6213 1,
6214 self.pg0.remote_ip6n,
6215 self.pg1.remote_ip4,
6216 25)
6217 else:
6218 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6219
6220 # Delete
6221 self.pg_enable_capture(self.pg_interfaces)
6222 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6223 self.nat_addr_n,
6224 is_add=0)
6225 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6226 capture = self.pg3.get_capture(2)
6227 # verify events in data set
6228 for p in capture:
6229 self.assertTrue(p.haslayer(IPFIX))
6230 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6231 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6232 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6233 self.assertEqual(p[UDP].dport, 4739)
6234 self.assertEqual(p[IPFIX].observationDomainID,
6235 self.ipfix_domain_id)
6236 if p.haslayer(Data):
6237 data = ipfix.decode_data_set(p.getlayer(Set))
6238 if ord(data[0][230]) == 11:
6239 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6240 elif ord(data[0][230]) == 7:
6241 self.verify_ipfix_nat64_ses(data,
6242 0,
6243 self.pg0.remote_ip6n,
6244 self.pg1.remote_ip4,
6245 25)
6246 else:
6247 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6248
Matus Fabian06596c52017-06-06 04:53:28 -07006249 def nat64_get_ses_num(self):
6250 """
6251 Return number of active NAT64 sessions.
6252 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006253 st = self.vapi.nat64_st_dump()
6254 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006255
6256 def clear_nat64(self):
6257 """
6258 Clear NAT64 configuration.
6259 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006260 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6261 domain_id=self.ipfix_domain_id)
6262 self.ipfix_src_port = 4739
6263 self.ipfix_domain_id = 1
6264
Matus Fabian06596c52017-06-06 04:53:28 -07006265 self.vapi.nat64_set_timeouts()
6266
6267 interfaces = self.vapi.nat64_interface_dump()
6268 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006269 if intf.is_inside > 1:
6270 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6271 0,
6272 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006273 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6274 intf.is_inside,
6275 is_add=0)
6276
Matus Fabiana431ad12018-01-04 04:03:14 -08006277 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006278 for bibe in bib:
6279 if bibe.is_static:
6280 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6281 bibe.o_addr,
6282 bibe.i_port,
6283 bibe.o_port,
6284 bibe.proto,
6285 bibe.vrf_id,
6286 is_add=0)
6287
6288 adresses = self.vapi.nat64_pool_addr_dump()
6289 for addr in adresses:
6290 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6291 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006292 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006293 is_add=0)
6294
Matus Fabian428dc912017-06-21 06:15:18 -07006295 prefixes = self.vapi.nat64_prefix_dump()
6296 for prefix in prefixes:
6297 self.vapi.nat64_add_del_prefix(prefix.prefix,
6298 prefix.prefix_len,
6299 vrf_id=prefix.vrf_id,
6300 is_add=0)
6301
Matus Fabian06596c52017-06-06 04:53:28 -07006302 def tearDown(self):
6303 super(TestNAT64, self).tearDown()
6304 if not self.vpp_dead:
6305 self.logger.info(self.vapi.cli("show nat64 pool"))
6306 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006307 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006308 self.logger.info(self.vapi.cli("show nat64 bib all"))
6309 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006310 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006311 self.clear_nat64()
6312
Matus Fabian8ebe6252017-11-06 05:04:53 -08006313
6314class TestDSlite(MethodHolder):
6315 """ DS-Lite Test Cases """
6316
6317 @classmethod
6318 def setUpClass(cls):
6319 super(TestDSlite, cls).setUpClass()
6320
6321 try:
6322 cls.nat_addr = '10.0.0.3'
6323 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6324
6325 cls.create_pg_interfaces(range(2))
6326 cls.pg0.admin_up()
6327 cls.pg0.config_ip4()
6328 cls.pg0.resolve_arp()
6329 cls.pg1.admin_up()
6330 cls.pg1.config_ip6()
6331 cls.pg1.generate_remote_hosts(2)
6332 cls.pg1.configure_ipv6_neighbors()
6333
6334 except Exception:
6335 super(TestDSlite, cls).tearDownClass()
6336 raise
6337
6338 def test_dslite(self):
6339 """ Test DS-Lite """
6340 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6341 self.nat_addr_n)
6342 aftr_ip4 = '192.0.0.1'
6343 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6344 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6345 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6346 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6347
6348 # UDP
6349 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6350 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6351 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6352 UDP(sport=20000, dport=10000))
6353 self.pg1.add_stream(p)
6354 self.pg_enable_capture(self.pg_interfaces)
6355 self.pg_start()
6356 capture = self.pg0.get_capture(1)
6357 capture = capture[0]
6358 self.assertFalse(capture.haslayer(IPv6))
6359 self.assertEqual(capture[IP].src, self.nat_addr)
6360 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6361 self.assertNotEqual(capture[UDP].sport, 20000)
6362 self.assertEqual(capture[UDP].dport, 10000)
6363 self.check_ip_checksum(capture)
6364 out_port = capture[UDP].sport
6365
6366 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6367 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6368 UDP(sport=10000, dport=out_port))
6369 self.pg0.add_stream(p)
6370 self.pg_enable_capture(self.pg_interfaces)
6371 self.pg_start()
6372 capture = self.pg1.get_capture(1)
6373 capture = capture[0]
6374 self.assertEqual(capture[IPv6].src, aftr_ip6)
6375 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6376 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6377 self.assertEqual(capture[IP].dst, '192.168.1.1')
6378 self.assertEqual(capture[UDP].sport, 10000)
6379 self.assertEqual(capture[UDP].dport, 20000)
6380 self.check_ip_checksum(capture)
6381
6382 # TCP
6383 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6384 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6385 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6386 TCP(sport=20001, dport=10001))
6387 self.pg1.add_stream(p)
6388 self.pg_enable_capture(self.pg_interfaces)
6389 self.pg_start()
6390 capture = self.pg0.get_capture(1)
6391 capture = capture[0]
6392 self.assertFalse(capture.haslayer(IPv6))
6393 self.assertEqual(capture[IP].src, self.nat_addr)
6394 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6395 self.assertNotEqual(capture[TCP].sport, 20001)
6396 self.assertEqual(capture[TCP].dport, 10001)
6397 self.check_ip_checksum(capture)
6398 self.check_tcp_checksum(capture)
6399 out_port = capture[TCP].sport
6400
6401 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6402 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6403 TCP(sport=10001, dport=out_port))
6404 self.pg0.add_stream(p)
6405 self.pg_enable_capture(self.pg_interfaces)
6406 self.pg_start()
6407 capture = self.pg1.get_capture(1)
6408 capture = capture[0]
6409 self.assertEqual(capture[IPv6].src, aftr_ip6)
6410 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6411 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6412 self.assertEqual(capture[IP].dst, '192.168.1.1')
6413 self.assertEqual(capture[TCP].sport, 10001)
6414 self.assertEqual(capture[TCP].dport, 20001)
6415 self.check_ip_checksum(capture)
6416 self.check_tcp_checksum(capture)
6417
6418 # ICMP
6419 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6420 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6421 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6422 ICMP(id=4000, type='echo-request'))
6423 self.pg1.add_stream(p)
6424 self.pg_enable_capture(self.pg_interfaces)
6425 self.pg_start()
6426 capture = self.pg0.get_capture(1)
6427 capture = capture[0]
6428 self.assertFalse(capture.haslayer(IPv6))
6429 self.assertEqual(capture[IP].src, self.nat_addr)
6430 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6431 self.assertNotEqual(capture[ICMP].id, 4000)
6432 self.check_ip_checksum(capture)
6433 self.check_icmp_checksum(capture)
6434 out_id = capture[ICMP].id
6435
6436 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6437 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6438 ICMP(id=out_id, type='echo-reply'))
6439 self.pg0.add_stream(p)
6440 self.pg_enable_capture(self.pg_interfaces)
6441 self.pg_start()
6442 capture = self.pg1.get_capture(1)
6443 capture = capture[0]
6444 self.assertEqual(capture[IPv6].src, aftr_ip6)
6445 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6446 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6447 self.assertEqual(capture[IP].dst, '192.168.1.1')
6448 self.assertEqual(capture[ICMP].id, 4000)
6449 self.check_ip_checksum(capture)
6450 self.check_icmp_checksum(capture)
6451
Matus Fabian331acc62017-12-08 03:38:51 -08006452 # ping DS-Lite AFTR tunnel endpoint address
6453 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6454 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6455 ICMPv6EchoRequest())
6456 self.pg1.add_stream(p)
6457 self.pg_enable_capture(self.pg_interfaces)
6458 self.pg_start()
6459 capture = self.pg1.get_capture(1)
6460 self.assertEqual(1, len(capture))
6461 capture = capture[0]
6462 self.assertEqual(capture[IPv6].src, aftr_ip6)
6463 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6464 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6465
Matus Fabian8ebe6252017-11-06 05:04:53 -08006466 def tearDown(self):
6467 super(TestDSlite, self).tearDown()
6468 if not self.vpp_dead:
6469 self.logger.info(self.vapi.cli("show dslite pool"))
6470 self.logger.info(
6471 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6472 self.logger.info(self.vapi.cli("show dslite sessions"))
6473
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006474
6475class TestDSliteCE(MethodHolder):
6476 """ DS-Lite CE Test Cases """
6477
6478 @classmethod
6479 def setUpConstants(cls):
6480 super(TestDSliteCE, cls).setUpConstants()
6481 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6482
6483 @classmethod
6484 def setUpClass(cls):
6485 super(TestDSliteCE, cls).setUpClass()
6486
6487 try:
6488 cls.create_pg_interfaces(range(2))
6489 cls.pg0.admin_up()
6490 cls.pg0.config_ip4()
6491 cls.pg0.resolve_arp()
6492 cls.pg1.admin_up()
6493 cls.pg1.config_ip6()
6494 cls.pg1.generate_remote_hosts(1)
6495 cls.pg1.configure_ipv6_neighbors()
6496
6497 except Exception:
6498 super(TestDSliteCE, cls).tearDownClass()
6499 raise
6500
6501 def test_dslite_ce(self):
6502 """ Test DS-Lite CE """
6503
6504 b4_ip4 = '192.0.0.2'
6505 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6506 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6507 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6508 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6509
6510 aftr_ip4 = '192.0.0.1'
6511 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6512 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6513 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6514 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6515
6516 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6517 dst_address_length=128,
6518 next_hop_address=self.pg1.remote_ip6n,
6519 next_hop_sw_if_index=self.pg1.sw_if_index,
6520 is_ipv6=1)
6521
6522 # UDP encapsulation
6523 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6524 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6525 UDP(sport=10000, dport=20000))
6526 self.pg0.add_stream(p)
6527 self.pg_enable_capture(self.pg_interfaces)
6528 self.pg_start()
6529 capture = self.pg1.get_capture(1)
6530 capture = capture[0]
6531 self.assertEqual(capture[IPv6].src, b4_ip6)
6532 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6533 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6534 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6535 self.assertEqual(capture[UDP].sport, 10000)
6536 self.assertEqual(capture[UDP].dport, 20000)
6537 self.check_ip_checksum(capture)
6538
6539 # UDP decapsulation
6540 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6541 IPv6(dst=b4_ip6, src=aftr_ip6) /
6542 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6543 UDP(sport=20000, dport=10000))
6544 self.pg1.add_stream(p)
6545 self.pg_enable_capture(self.pg_interfaces)
6546 self.pg_start()
6547 capture = self.pg0.get_capture(1)
6548 capture = capture[0]
6549 self.assertFalse(capture.haslayer(IPv6))
6550 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6551 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6552 self.assertEqual(capture[UDP].sport, 20000)
6553 self.assertEqual(capture[UDP].dport, 10000)
6554 self.check_ip_checksum(capture)
6555
6556 # ping DS-Lite B4 tunnel endpoint address
6557 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6558 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6559 ICMPv6EchoRequest())
6560 self.pg1.add_stream(p)
6561 self.pg_enable_capture(self.pg_interfaces)
6562 self.pg_start()
6563 capture = self.pg1.get_capture(1)
6564 self.assertEqual(1, len(capture))
6565 capture = capture[0]
6566 self.assertEqual(capture[IPv6].src, b4_ip6)
6567 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6568 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6569
6570 def tearDown(self):
6571 super(TestDSliteCE, self).tearDown()
6572 if not self.vpp_dead:
6573 self.logger.info(
6574 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6575 self.logger.info(
6576 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6577
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006578
6579class TestNAT66(MethodHolder):
6580 """ NAT66 Test Cases """
6581
6582 @classmethod
6583 def setUpClass(cls):
6584 super(TestNAT66, cls).setUpClass()
6585
6586 try:
6587 cls.nat_addr = 'fd01:ff::2'
6588 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6589
6590 cls.create_pg_interfaces(range(2))
6591 cls.interfaces = list(cls.pg_interfaces)
6592
6593 for i in cls.interfaces:
6594 i.admin_up()
6595 i.config_ip6()
6596 i.configure_ipv6_neighbors()
6597
6598 except Exception:
6599 super(TestNAT66, cls).tearDownClass()
6600 raise
6601
6602 def test_static(self):
6603 """ 1:1 NAT66 test """
6604 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6605 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6606 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6607 self.nat_addr_n)
6608
6609 # in2out
6610 pkts = []
6611 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6612 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6613 TCP())
6614 pkts.append(p)
6615 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6616 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6617 UDP())
6618 pkts.append(p)
6619 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6620 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6621 ICMPv6EchoRequest())
6622 pkts.append(p)
6623 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6624 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6625 GRE() / IP() / TCP())
6626 pkts.append(p)
6627 self.pg0.add_stream(pkts)
6628 self.pg_enable_capture(self.pg_interfaces)
6629 self.pg_start()
6630 capture = self.pg1.get_capture(len(pkts))
6631 for packet in capture:
6632 try:
6633 self.assertEqual(packet[IPv6].src, self.nat_addr)
6634 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6635 if packet.haslayer(TCP):
6636 self.check_tcp_checksum(packet)
6637 elif packet.haslayer(UDP):
6638 self.check_udp_checksum(packet)
6639 elif packet.haslayer(ICMPv6EchoRequest):
6640 self.check_icmpv6_checksum(packet)
6641 except:
6642 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6643 raise
6644
6645 # out2in
6646 pkts = []
6647 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6648 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6649 TCP())
6650 pkts.append(p)
6651 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6652 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6653 UDP())
6654 pkts.append(p)
6655 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6656 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6657 ICMPv6EchoReply())
6658 pkts.append(p)
6659 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6660 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6661 GRE() / IP() / TCP())
6662 pkts.append(p)
6663 self.pg1.add_stream(pkts)
6664 self.pg_enable_capture(self.pg_interfaces)
6665 self.pg_start()
6666 capture = self.pg0.get_capture(len(pkts))
6667 for packet in capture:
6668 try:
6669 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6670 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6671 if packet.haslayer(TCP):
6672 self.check_tcp_checksum(packet)
6673 elif packet.haslayer(UDP):
6674 self.check_udp_checksum(packet)
6675 elif packet.haslayer(ICMPv6EchoReply):
6676 self.check_icmpv6_checksum(packet)
6677 except:
6678 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6679 raise
6680
6681 sm = self.vapi.nat66_static_mapping_dump()
6682 self.assertEqual(len(sm), 1)
6683 self.assertEqual(sm[0].total_pkts, 8)
6684
Juraj Sloboda9341e342018-04-13 12:00:46 +02006685 def test_check_no_translate(self):
6686 """ NAT66 translate only when egress interface is outside interface """
6687 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6688 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6689 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6690 self.nat_addr_n)
6691
6692 # in2out
6693 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6694 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6695 UDP())
6696 self.pg0.add_stream([p])
6697 self.pg_enable_capture(self.pg_interfaces)
6698 self.pg_start()
6699 capture = self.pg1.get_capture(1)
6700 packet = capture[0]
6701 try:
6702 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6703 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6704 except:
6705 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6706 raise
6707
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006708 def clear_nat66(self):
6709 """
6710 Clear NAT66 configuration.
6711 """
6712 interfaces = self.vapi.nat66_interface_dump()
6713 for intf in interfaces:
6714 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6715 intf.is_inside,
6716 is_add=0)
6717
6718 static_mappings = self.vapi.nat66_static_mapping_dump()
6719 for sm in static_mappings:
6720 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6721 sm.external_ip_address,
6722 sm.vrf_id,
6723 is_add=0)
6724
6725 def tearDown(self):
6726 super(TestNAT66, self).tearDown()
6727 if not self.vpp_dead:
6728 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6729 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6730 self.clear_nat66()
6731
Matus Fabiande886752016-12-07 03:38:19 -08006732if __name__ == '__main__':
6733 unittest.main(testRunner=VppTestRunner)