blob: c4018cf66d864c9dfc8760bffcc0abe7f381ff95 [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 Fabian8bf68e82017-01-12 04:24:35 -08002483 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002484 """ Acquire NAT44 addresses from interface """
2485 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002486
2487 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002488 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002489 self.assertEqual(0, len(adresses))
2490
2491 # configure interface address and check NAT address pool
2492 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002493 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002494 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002495 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002496
2497 # remove interface address and check NAT address pool
2498 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002499 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002500 self.assertEqual(0, len(adresses))
2501
Matus Fabian36532bd2017-01-23 23:42:28 -08002502 def test_interface_addr_static_mapping(self):
2503 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002504 tag = "testTAG"
2505
Matus Fabian2ba92e32017-08-21 07:05:03 -07002506 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2507 self.nat44_add_static_mapping(
2508 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002509 external_sw_if_index=self.pg7.sw_if_index,
2510 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002511
Matus Fabiane22e5462017-02-14 23:33:43 -08002512 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002513 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002514 self.assertEqual(1, len(static_mappings))
2515 self.assertEqual(self.pg7.sw_if_index,
2516 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002517 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002518
2519 # configure interface address and check static mappings
2520 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002521 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002522 self.assertEqual(2, len(static_mappings))
2523 resolved = False
2524 for sm in static_mappings:
2525 if sm.external_sw_if_index == 0xFFFFFFFF:
2526 self.assertEqual(sm.external_ip_address[0:4],
2527 self.pg7.local_ip4n)
2528 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2529 resolved = True
2530 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002531
2532 # remove interface address and check static mappings
2533 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002534 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002535 self.assertEqual(1, len(static_mappings))
2536 self.assertEqual(self.pg7.sw_if_index,
2537 static_mappings[0].external_sw_if_index)
2538 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2539
2540 # configure interface address again and check static mappings
2541 self.pg7.config_ip4()
2542 static_mappings = self.vapi.nat44_static_mapping_dump()
2543 self.assertEqual(2, len(static_mappings))
2544 resolved = False
2545 for sm in static_mappings:
2546 if sm.external_sw_if_index == 0xFFFFFFFF:
2547 self.assertEqual(sm.external_ip_address[0:4],
2548 self.pg7.local_ip4n)
2549 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2550 resolved = True
2551 self.assertTrue(resolved)
2552
2553 # remove static mapping
2554 self.nat44_add_static_mapping(
2555 '1.2.3.4',
2556 external_sw_if_index=self.pg7.sw_if_index,
2557 tag=tag,
2558 is_add=0)
2559 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002560 self.assertEqual(0, len(static_mappings))
2561
Matus Fabianab7a8052017-11-28 04:29:41 -08002562 def test_interface_addr_identity_nat(self):
2563 """ Identity NAT with addresses from interface """
2564
2565 port = 53053
2566 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2567 self.vapi.nat44_add_del_identity_mapping(
2568 sw_if_index=self.pg7.sw_if_index,
2569 port=port,
2570 protocol=IP_PROTOS.tcp,
2571 addr_only=0)
2572
2573 # identity mappings with external interface
2574 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2575 self.assertEqual(1, len(identity_mappings))
2576 self.assertEqual(self.pg7.sw_if_index,
2577 identity_mappings[0].sw_if_index)
2578
2579 # configure interface address and check identity mappings
2580 self.pg7.config_ip4()
2581 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002582 resolved = False
2583 self.assertEqual(2, len(identity_mappings))
2584 for sm in identity_mappings:
2585 if sm.sw_if_index == 0xFFFFFFFF:
2586 self.assertEqual(identity_mappings[0].ip_address,
2587 self.pg7.local_ip4n)
2588 self.assertEqual(port, identity_mappings[0].port)
2589 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2590 resolved = True
2591 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002592
2593 # remove interface address and check identity mappings
2594 self.pg7.unconfig_ip4()
2595 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002596 self.assertEqual(1, len(identity_mappings))
2597 self.assertEqual(self.pg7.sw_if_index,
2598 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002599
Matus Fabianeea28d72017-01-13 04:15:54 -08002600 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002601 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002602 self.ipfix_domain_id = 10
2603 self.ipfix_src_port = 20202
2604 colector_port = 30303
2605 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002606 self.nat44_add_address(self.nat_addr)
2607 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2608 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2609 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002610 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2611 src_address=self.pg3.local_ip4n,
2612 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002613 template_interval=10,
2614 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002615 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2616 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002617
2618 pkts = self.create_stream_in(self.pg0, self.pg1)
2619 self.pg0.add_stream(pkts)
2620 self.pg_enable_capture(self.pg_interfaces)
2621 self.pg_start()
2622 capture = self.pg1.get_capture(len(pkts))
2623 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002624 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002625 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002626 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002627 ipfix = IPFIXDecoder()
2628 # first load template
2629 for p in capture:
2630 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002631 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2632 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2633 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2634 self.assertEqual(p[UDP].dport, colector_port)
2635 self.assertEqual(p[IPFIX].observationDomainID,
2636 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002637 if p.haslayer(Template):
2638 ipfix.add_template(p.getlayer(Template))
2639 # verify events in data set
2640 for p in capture:
2641 if p.haslayer(Data):
2642 data = ipfix.decode_data_set(p.getlayer(Set))
2643 self.verify_ipfix_nat44_ses(data)
2644
2645 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002646 """ IPFIX logging NAT addresses exhausted """
2647 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2648 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2649 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002650 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2651 src_address=self.pg3.local_ip4n,
2652 path_mtu=512,
2653 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002654 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2655 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002656
2657 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2658 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2659 TCP(sport=3025))
2660 self.pg0.add_stream(p)
2661 self.pg_enable_capture(self.pg_interfaces)
2662 self.pg_start()
2663 capture = self.pg1.get_capture(0)
2664 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002665 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002666 ipfix = IPFIXDecoder()
2667 # first load template
2668 for p in capture:
2669 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002670 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2671 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2672 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2673 self.assertEqual(p[UDP].dport, 4739)
2674 self.assertEqual(p[IPFIX].observationDomainID,
2675 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002676 if p.haslayer(Template):
2677 ipfix.add_template(p.getlayer(Template))
2678 # verify events in data set
2679 for p in capture:
2680 if p.haslayer(Data):
2681 data = ipfix.decode_data_set(p.getlayer(Set))
2682 self.verify_ipfix_addr_exhausted(data)
2683
Matus Fabiana431ad12018-01-04 04:03:14 -08002684 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2685 def test_ipfix_max_sessions(self):
2686 """ IPFIX logging maximum session entries exceeded """
2687 self.nat44_add_address(self.nat_addr)
2688 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2689 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2690 is_inside=0)
2691
2692 nat44_config = self.vapi.nat_show_config()
2693 max_sessions = 10 * nat44_config.translation_buckets
2694
2695 pkts = []
2696 for i in range(0, max_sessions):
2697 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2698 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2699 IP(src=src, dst=self.pg1.remote_ip4) /
2700 TCP(sport=1025))
2701 pkts.append(p)
2702 self.pg0.add_stream(pkts)
2703 self.pg_enable_capture(self.pg_interfaces)
2704 self.pg_start()
2705
2706 self.pg1.get_capture(max_sessions)
2707 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2708 src_address=self.pg3.local_ip4n,
2709 path_mtu=512,
2710 template_interval=10)
2711 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2712 src_port=self.ipfix_src_port)
2713
2714 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2715 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2716 TCP(sport=1025))
2717 self.pg0.add_stream(p)
2718 self.pg_enable_capture(self.pg_interfaces)
2719 self.pg_start()
2720 self.pg1.get_capture(0)
2721 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2722 capture = self.pg3.get_capture(9)
2723 ipfix = IPFIXDecoder()
2724 # first load template
2725 for p in capture:
2726 self.assertTrue(p.haslayer(IPFIX))
2727 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2728 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2729 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2730 self.assertEqual(p[UDP].dport, 4739)
2731 self.assertEqual(p[IPFIX].observationDomainID,
2732 self.ipfix_domain_id)
2733 if p.haslayer(Template):
2734 ipfix.add_template(p.getlayer(Template))
2735 # verify events in data set
2736 for p in capture:
2737 if p.haslayer(Data):
2738 data = ipfix.decode_data_set(p.getlayer(Set))
2739 self.verify_ipfix_max_sessions(data, max_sessions)
2740
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002741 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002742 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002743 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002744 self.nat44_add_address(self.nat_addr)
2745 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2746 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2747 is_inside=0)
2748 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002749
Matus Fabian2ba92e32017-08-21 07:05:03 -07002750 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002751 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002752 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002753 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2754 self.pg1.add_stream(p)
2755 self.pg_enable_capture(self.pg_interfaces)
2756 self.pg_start()
2757 capture = self.pg1.get_capture(1)
2758 self.assertTrue(capture[0].haslayer(ARP))
2759 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2760
2761 # 1:1 NAT address
2762 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2763 ARP(op=ARP.who_has, pdst=static_addr,
2764 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2765 self.pg1.add_stream(p)
2766 self.pg_enable_capture(self.pg_interfaces)
2767 self.pg_start()
2768 capture = self.pg1.get_capture(1)
2769 self.assertTrue(capture[0].haslayer(ARP))
2770 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2771
Matus Fabian2ba92e32017-08-21 07:05:03 -07002772 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002773 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002774 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002775 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2776 self.pg2.add_stream(p)
2777 self.pg_enable_capture(self.pg_interfaces)
2778 self.pg_start()
2779 capture = self.pg1.get_capture(0)
2780
2781 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002782 self.nat44_add_address(self.nat_addr, is_add=0)
2783 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2784 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002785
2786 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002787 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002788 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2789 self.pg1.add_stream(p)
2790 self.pg_enable_capture(self.pg_interfaces)
2791 self.pg_start()
2792 capture = self.pg1.get_capture(0)
2793
2794 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2795 ARP(op=ARP.who_has, pdst=static_addr,
2796 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2797 self.pg1.add_stream(p)
2798 self.pg_enable_capture(self.pg_interfaces)
2799 self.pg_start()
2800 capture = self.pg1.get_capture(0)
2801
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002802 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002803 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002804
2805 vrf_id1 = 1
2806 vrf_id2 = 2
2807 nat_ip1 = "10.0.0.10"
2808 nat_ip2 = "10.0.0.11"
2809
2810 self.pg0.unconfig_ip4()
2811 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002812 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2813 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002814 self.pg0.set_table_ip4(vrf_id1)
2815 self.pg1.set_table_ip4(vrf_id2)
2816 self.pg0.config_ip4()
2817 self.pg1.config_ip4()
2818
Matus Fabian2ba92e32017-08-21 07:05:03 -07002819 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2820 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2821 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2822 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2823 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2824 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002825
2826 # first VRF
2827 pkts = self.create_stream_in(self.pg0, self.pg2)
2828 self.pg0.add_stream(pkts)
2829 self.pg_enable_capture(self.pg_interfaces)
2830 self.pg_start()
2831 capture = self.pg2.get_capture(len(pkts))
2832 self.verify_capture_out(capture, nat_ip1)
2833
2834 # second VRF
2835 pkts = self.create_stream_in(self.pg1, self.pg2)
2836 self.pg1.add_stream(pkts)
2837 self.pg_enable_capture(self.pg_interfaces)
2838 self.pg_start()
2839 capture = self.pg2.get_capture(len(pkts))
2840 self.verify_capture_out(capture, nat_ip2)
2841
Neale Ranns15002542017-09-10 04:39:11 -07002842 self.pg0.unconfig_ip4()
2843 self.pg1.unconfig_ip4()
2844 self.pg0.set_table_ip4(0)
2845 self.pg1.set_table_ip4(0)
2846 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2847 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2848
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002849 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002850 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002851
2852 nat_ip1 = "10.0.0.10"
2853 nat_ip2 = "10.0.0.11"
2854
Matus Fabian2ba92e32017-08-21 07:05:03 -07002855 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002856 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002857 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2858 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2859 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2860 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002861
2862 # first VRF
2863 pkts = self.create_stream_in(self.pg0, self.pg2)
2864 self.pg0.add_stream(pkts)
2865 self.pg_enable_capture(self.pg_interfaces)
2866 self.pg_start()
2867 capture = self.pg2.get_capture(len(pkts))
2868 self.verify_capture_out(capture, nat_ip1)
2869
2870 # second VRF
2871 pkts = self.create_stream_in(self.pg1, self.pg2)
2872 self.pg1.add_stream(pkts)
2873 self.pg_enable_capture(self.pg_interfaces)
2874 self.pg_start()
2875 capture = self.pg2.get_capture(len(pkts))
2876 self.verify_capture_out(capture, nat_ip1)
2877
Martin Gálik406eb1d2017-05-04 04:35:04 -07002878 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002879 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002880
2881 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002882 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002883 self.pg7.remote_ip4n,
2884 is_static=1)
2885 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002886 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002887 self.pg8.remote_ip4n,
2888 is_static=1)
2889
2890 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2891 dst_address_length=32,
2892 next_hop_address=self.pg7.remote_ip4n,
2893 next_hop_sw_if_index=self.pg7.sw_if_index)
2894 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2895 dst_address_length=32,
2896 next_hop_address=self.pg8.remote_ip4n,
2897 next_hop_sw_if_index=self.pg8.sw_if_index)
2898
Matus Fabian2ba92e32017-08-21 07:05:03 -07002899 self.nat44_add_address(self.nat_addr)
2900 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2901 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2902 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002903
2904 # in2out
2905 pkts = self.create_stream_in(self.pg7, self.pg8)
2906 self.pg7.add_stream(pkts)
2907 self.pg_enable_capture(self.pg_interfaces)
2908 self.pg_start()
2909 capture = self.pg8.get_capture(len(pkts))
2910 self.verify_capture_out(capture)
2911
2912 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002913 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002914 self.pg8.add_stream(pkts)
2915 self.pg_enable_capture(self.pg_interfaces)
2916 self.pg_start()
2917 capture = self.pg7.get_capture(len(pkts))
2918 self.verify_capture_in(capture, self.pg7)
2919
2920 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002921 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002922
2923 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002924 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002925 self.pg7.remote_ip4n,
2926 is_static=1)
2927 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002928 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002929 self.pg8.remote_ip4n,
2930 is_static=1)
2931
2932 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2933 dst_address_length=32,
2934 next_hop_address=self.pg7.remote_ip4n,
2935 next_hop_sw_if_index=self.pg7.sw_if_index)
2936 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2937 dst_address_length=32,
2938 next_hop_address=self.pg8.remote_ip4n,
2939 next_hop_sw_if_index=self.pg8.sw_if_index)
2940
Matus Fabian2ba92e32017-08-21 07:05:03 -07002941 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2942 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2943 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2944 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002945
2946 # out2in
2947 pkts = self.create_stream_out(self.pg8)
2948 self.pg8.add_stream(pkts)
2949 self.pg_enable_capture(self.pg_interfaces)
2950 self.pg_start()
2951 capture = self.pg7.get_capture(len(pkts))
2952 self.verify_capture_in(capture, self.pg7)
2953
2954 # in2out
2955 pkts = self.create_stream_in(self.pg7, self.pg8)
2956 self.pg7.add_stream(pkts)
2957 self.pg_enable_capture(self.pg_interfaces)
2958 self.pg_start()
2959 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002960 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002961
2962 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002963 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002964
2965 self.tcp_port_out = 30606
2966 self.udp_port_out = 30607
2967 self.icmp_id_out = 30608
2968
2969 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002970 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002971 self.pg7.remote_ip4n,
2972 is_static=1)
2973 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002974 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002975 self.pg8.remote_ip4n,
2976 is_static=1)
2977
2978 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2979 dst_address_length=32,
2980 next_hop_address=self.pg7.remote_ip4n,
2981 next_hop_sw_if_index=self.pg7.sw_if_index)
2982 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2983 dst_address_length=32,
2984 next_hop_address=self.pg8.remote_ip4n,
2985 next_hop_sw_if_index=self.pg8.sw_if_index)
2986
Matus Fabian2ba92e32017-08-21 07:05:03 -07002987 self.nat44_add_address(self.nat_addr)
2988 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2989 self.tcp_port_in, self.tcp_port_out,
2990 proto=IP_PROTOS.tcp)
2991 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2992 self.udp_port_in, self.udp_port_out,
2993 proto=IP_PROTOS.udp)
2994 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2995 self.icmp_id_in, self.icmp_id_out,
2996 proto=IP_PROTOS.icmp)
2997 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2998 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2999 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003000
3001 # out2in
3002 pkts = self.create_stream_out(self.pg8)
3003 self.pg8.add_stream(pkts)
3004 self.pg_enable_capture(self.pg_interfaces)
3005 self.pg_start()
3006 capture = self.pg7.get_capture(len(pkts))
3007 self.verify_capture_in(capture, self.pg7)
3008
3009 # in2out
3010 pkts = self.create_stream_in(self.pg7, self.pg8)
3011 self.pg7.add_stream(pkts)
3012 self.pg_enable_capture(self.pg_interfaces)
3013 self.pg_start()
3014 capture = self.pg8.get_capture(len(pkts))
3015 self.verify_capture_out(capture)
3016
Matus Fabian328dbc82017-06-19 04:28:04 -07003017 def test_static_unknown_proto(self):
3018 """ 1:1 NAT translate packet with unknown protocol """
3019 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003020 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3021 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3022 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3023 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003024
3025 # in2out
3026 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3027 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3028 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003029 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003030 TCP(sport=1234, dport=1234))
3031 self.pg0.add_stream(p)
3032 self.pg_enable_capture(self.pg_interfaces)
3033 self.pg_start()
3034 p = self.pg1.get_capture(1)
3035 packet = p[0]
3036 try:
3037 self.assertEqual(packet[IP].src, nat_ip)
3038 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3039 self.assertTrue(packet.haslayer(GRE))
3040 self.check_ip_checksum(packet)
3041 except:
3042 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3043 raise
3044
3045 # out2in
3046 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3047 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3048 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003049 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003050 TCP(sport=1234, dport=1234))
3051 self.pg1.add_stream(p)
3052 self.pg_enable_capture(self.pg_interfaces)
3053 self.pg_start()
3054 p = self.pg0.get_capture(1)
3055 packet = p[0]
3056 try:
3057 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3058 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3059 self.assertTrue(packet.haslayer(GRE))
3060 self.check_ip_checksum(packet)
3061 except:
3062 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3063 raise
3064
Matus Fabian7968e6c2017-07-06 05:37:49 -07003065 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003066 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3067
3068 host = self.pg0.remote_hosts[0]
3069 server = self.pg0.remote_hosts[1]
3070
3071 host_nat_ip = "10.0.0.10"
3072 server_nat_ip = "10.0.0.11"
3073
Matus Fabian2ba92e32017-08-21 07:05:03 -07003074 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3075 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3076 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3077 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3078 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003079
3080 # host to server
3081 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3082 IP(src=host.ip4, dst=server_nat_ip) /
3083 GRE() /
3084 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3085 TCP(sport=1234, dport=1234))
3086 self.pg0.add_stream(p)
3087 self.pg_enable_capture(self.pg_interfaces)
3088 self.pg_start()
3089 p = self.pg0.get_capture(1)
3090 packet = p[0]
3091 try:
3092 self.assertEqual(packet[IP].src, host_nat_ip)
3093 self.assertEqual(packet[IP].dst, server.ip4)
3094 self.assertTrue(packet.haslayer(GRE))
3095 self.check_ip_checksum(packet)
3096 except:
3097 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3098 raise
3099
3100 # server to host
3101 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3102 IP(src=server.ip4, dst=host_nat_ip) /
3103 GRE() /
3104 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3105 TCP(sport=1234, dport=1234))
3106 self.pg0.add_stream(p)
3107 self.pg_enable_capture(self.pg_interfaces)
3108 self.pg_start()
3109 p = self.pg0.get_capture(1)
3110 packet = p[0]
3111 try:
3112 self.assertEqual(packet[IP].src, server_nat_ip)
3113 self.assertEqual(packet[IP].dst, host.ip4)
3114 self.assertTrue(packet.haslayer(GRE))
3115 self.check_ip_checksum(packet)
3116 except:
3117 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3118 raise
3119
Matus Fabian7968e6c2017-07-06 05:37:49 -07003120 def test_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003121 """ NAT44 translate packet with unknown protocol """
3122 self.nat44_add_address(self.nat_addr)
3123 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3124 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3125 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003126
3127 # in2out
3128 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3129 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3130 TCP(sport=self.tcp_port_in, dport=20))
3131 self.pg0.add_stream(p)
3132 self.pg_enable_capture(self.pg_interfaces)
3133 self.pg_start()
3134 p = self.pg1.get_capture(1)
3135
3136 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3137 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3138 GRE() /
3139 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3140 TCP(sport=1234, dport=1234))
3141 self.pg0.add_stream(p)
3142 self.pg_enable_capture(self.pg_interfaces)
3143 self.pg_start()
3144 p = self.pg1.get_capture(1)
3145 packet = p[0]
3146 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003147 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003148 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3149 self.assertTrue(packet.haslayer(GRE))
3150 self.check_ip_checksum(packet)
3151 except:
3152 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3153 raise
3154
3155 # out2in
3156 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003157 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003158 GRE() /
3159 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3160 TCP(sport=1234, dport=1234))
3161 self.pg1.add_stream(p)
3162 self.pg_enable_capture(self.pg_interfaces)
3163 self.pg_start()
3164 p = self.pg0.get_capture(1)
3165 packet = p[0]
3166 try:
3167 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3168 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3169 self.assertTrue(packet.haslayer(GRE))
3170 self.check_ip_checksum(packet)
3171 except:
3172 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3173 raise
3174
3175 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003176 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003177 host = self.pg0.remote_hosts[0]
3178 server = self.pg0.remote_hosts[1]
3179 host_in_port = 1234
3180 host_out_port = 0
3181 server_in_port = 5678
3182 server_out_port = 8765
3183 server_nat_ip = "10.0.0.11"
3184
Matus Fabian2ba92e32017-08-21 07:05:03 -07003185 self.nat44_add_address(self.nat_addr)
3186 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3187 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3188 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003189
3190 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003191 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003192
3193 # host to server
3194 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3195 IP(src=host.ip4, dst=server_nat_ip) /
3196 TCP(sport=host_in_port, dport=server_out_port))
3197 self.pg0.add_stream(p)
3198 self.pg_enable_capture(self.pg_interfaces)
3199 self.pg_start()
3200 capture = self.pg0.get_capture(1)
3201
3202 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3203 IP(src=host.ip4, dst=server_nat_ip) /
3204 GRE() /
3205 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3206 TCP(sport=1234, dport=1234))
3207 self.pg0.add_stream(p)
3208 self.pg_enable_capture(self.pg_interfaces)
3209 self.pg_start()
3210 p = self.pg0.get_capture(1)
3211 packet = p[0]
3212 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003213 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003214 self.assertEqual(packet[IP].dst, server.ip4)
3215 self.assertTrue(packet.haslayer(GRE))
3216 self.check_ip_checksum(packet)
3217 except:
3218 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3219 raise
3220
3221 # server to host
3222 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003223 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003224 GRE() /
3225 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3226 TCP(sport=1234, dport=1234))
3227 self.pg0.add_stream(p)
3228 self.pg_enable_capture(self.pg_interfaces)
3229 self.pg_start()
3230 p = self.pg0.get_capture(1)
3231 packet = p[0]
3232 try:
3233 self.assertEqual(packet[IP].src, server_nat_ip)
3234 self.assertEqual(packet[IP].dst, host.ip4)
3235 self.assertTrue(packet.haslayer(GRE))
3236 self.check_ip_checksum(packet)
3237 except:
3238 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3239 raise
3240
Matus Fabian93d84c92017-07-19 08:06:01 -07003241 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003242 """ NAT44 interface output feature (in2out postrouting) """
3243 self.nat44_add_address(self.nat_addr)
3244 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003245 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3246 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003247 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003248
3249 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003250 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003251 self.pg0.add_stream(pkts)
3252 self.pg_enable_capture(self.pg_interfaces)
3253 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003254 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003255 self.verify_capture_out(capture)
3256
3257 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003258 pkts = self.create_stream_out(self.pg3)
3259 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003260 self.pg_enable_capture(self.pg_interfaces)
3261 self.pg_start()
3262 capture = self.pg0.get_capture(len(pkts))
3263 self.verify_capture_in(capture, self.pg0)
3264
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003265 # from non-NAT interface to NAT inside interface
3266 pkts = self.create_stream_in(self.pg2, self.pg0)
3267 self.pg2.add_stream(pkts)
3268 self.pg_enable_capture(self.pg_interfaces)
3269 self.pg_start()
3270 capture = self.pg0.get_capture(len(pkts))
3271 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3272
Matus Fabian93d84c92017-07-19 08:06:01 -07003273 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003274 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003275 nat_ip_vrf10 = "10.0.0.10"
3276 nat_ip_vrf20 = "10.0.0.20"
3277
3278 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3279 dst_address_length=32,
3280 next_hop_address=self.pg3.remote_ip4n,
3281 next_hop_sw_if_index=self.pg3.sw_if_index,
3282 table_id=10)
3283 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3284 dst_address_length=32,
3285 next_hop_address=self.pg3.remote_ip4n,
3286 next_hop_sw_if_index=self.pg3.sw_if_index,
3287 table_id=20)
3288
Matus Fabian2ba92e32017-08-21 07:05:03 -07003289 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3290 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3291 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3292 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3293 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3294 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003295
3296 # in2out VRF 10
3297 pkts = self.create_stream_in(self.pg4, self.pg3)
3298 self.pg4.add_stream(pkts)
3299 self.pg_enable_capture(self.pg_interfaces)
3300 self.pg_start()
3301 capture = self.pg3.get_capture(len(pkts))
3302 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3303
3304 # out2in VRF 10
3305 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3306 self.pg3.add_stream(pkts)
3307 self.pg_enable_capture(self.pg_interfaces)
3308 self.pg_start()
3309 capture = self.pg4.get_capture(len(pkts))
3310 self.verify_capture_in(capture, self.pg4)
3311
3312 # in2out VRF 20
3313 pkts = self.create_stream_in(self.pg6, self.pg3)
3314 self.pg6.add_stream(pkts)
3315 self.pg_enable_capture(self.pg_interfaces)
3316 self.pg_start()
3317 capture = self.pg3.get_capture(len(pkts))
3318 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3319
3320 # out2in VRF 20
3321 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3322 self.pg3.add_stream(pkts)
3323 self.pg_enable_capture(self.pg_interfaces)
3324 self.pg_start()
3325 capture = self.pg6.get_capture(len(pkts))
3326 self.verify_capture_in(capture, self.pg6)
3327
Matus Fabian161c59c2017-07-21 03:46:03 -07003328 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003329 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003330 host = self.pg0.remote_hosts[0]
3331 server = self.pg0.remote_hosts[1]
3332 host_in_port = 1234
3333 host_out_port = 0
3334 server_in_port = 5678
3335 server_out_port = 8765
3336
Matus Fabian2ba92e32017-08-21 07:05:03 -07003337 self.nat44_add_address(self.nat_addr)
3338 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3339 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3340 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003341
3342 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003343 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3344 server_in_port, server_out_port,
3345 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003346
3347 # send packet from host to server
3348 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003349 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003350 TCP(sport=host_in_port, dport=server_out_port))
3351 self.pg0.add_stream(p)
3352 self.pg_enable_capture(self.pg_interfaces)
3353 self.pg_start()
3354 capture = self.pg0.get_capture(1)
3355 p = capture[0]
3356 try:
3357 ip = p[IP]
3358 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003359 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003360 self.assertEqual(ip.dst, server.ip4)
3361 self.assertNotEqual(tcp.sport, host_in_port)
3362 self.assertEqual(tcp.dport, server_in_port)
3363 self.check_tcp_checksum(p)
3364 host_out_port = tcp.sport
3365 except:
3366 self.logger.error(ppp("Unexpected or invalid packet:", p))
3367 raise
3368
3369 # send reply from server to host
3370 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003371 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003372 TCP(sport=server_in_port, dport=host_out_port))
3373 self.pg0.add_stream(p)
3374 self.pg_enable_capture(self.pg_interfaces)
3375 self.pg_start()
3376 capture = self.pg0.get_capture(1)
3377 p = capture[0]
3378 try:
3379 ip = p[IP]
3380 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003381 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003382 self.assertEqual(ip.dst, host.ip4)
3383 self.assertEqual(tcp.sport, server_out_port)
3384 self.assertEqual(tcp.dport, host_in_port)
3385 self.check_tcp_checksum(p)
3386 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003387 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003388 raise
3389
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003390 def test_output_feature_and_service(self):
3391 """ NAT44 interface output feature and services """
3392 external_addr = '1.2.3.4'
3393 external_port = 80
3394 local_port = 8080
3395
3396 self.vapi.nat44_forwarding_enable_disable(1)
3397 self.nat44_add_address(self.nat_addr)
Matus Fabiana15cd022018-04-24 05:23:56 -07003398 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003399 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3400 local_port, external_port,
3401 proto=IP_PROTOS.tcp, out2in_only=1)
3402 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
Matus Fabiana15cd022018-04-24 05:23:56 -07003403 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3404 is_inside=0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003405 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3406 is_inside=0)
3407
3408 # from client to service
3409 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3410 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3411 TCP(sport=12345, dport=external_port))
3412 self.pg1.add_stream(p)
3413 self.pg_enable_capture(self.pg_interfaces)
3414 self.pg_start()
3415 capture = self.pg0.get_capture(1)
3416 p = capture[0]
3417 server = None
3418 try:
3419 ip = p[IP]
3420 tcp = p[TCP]
3421 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3422 self.assertEqual(tcp.dport, local_port)
3423 self.check_tcp_checksum(p)
3424 self.check_ip_checksum(p)
3425 except:
3426 self.logger.error(ppp("Unexpected or invalid packet:", p))
3427 raise
3428
3429 # from service back to client
3430 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3431 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3432 TCP(sport=local_port, dport=12345))
3433 self.pg0.add_stream(p)
3434 self.pg_enable_capture(self.pg_interfaces)
3435 self.pg_start()
3436 capture = self.pg1.get_capture(1)
3437 p = capture[0]
3438 try:
3439 ip = p[IP]
3440 tcp = p[TCP]
3441 self.assertEqual(ip.src, external_addr)
3442 self.assertEqual(tcp.sport, external_port)
3443 self.check_tcp_checksum(p)
3444 self.check_ip_checksum(p)
3445 except:
3446 self.logger.error(ppp("Unexpected or invalid packet:", p))
3447 raise
3448
3449 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003450 pkts = self.create_stream_in(self.pg0, self.pg1)
3451 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003452 self.pg_enable_capture(self.pg_interfaces)
3453 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003454 capture = self.pg1.get_capture(len(pkts))
3455 self.verify_capture_out(capture)
3456 pkts = self.create_stream_in(self.pg0, self.pg1)
3457 self.pg0.add_stream(pkts)
3458 self.pg_enable_capture(self.pg_interfaces)
3459 self.pg_start()
3460 capture = self.pg1.get_capture(len(pkts))
3461 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003462
3463 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003464 pkts = self.create_stream_out(self.pg1)
3465 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003466 self.pg_enable_capture(self.pg_interfaces)
3467 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003468 capture = self.pg0.get_capture(len(pkts))
3469 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003470
Matus Fabian204591d2018-03-01 04:48:33 -08003471 def test_output_feature_and_service2(self):
3472 """ NAT44 interface output feature and service host direct access """
3473 self.vapi.nat44_forwarding_enable_disable(1)
3474 self.nat44_add_address(self.nat_addr)
3475 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3476 is_inside=0)
3477
3478 # session initiaded from service host - translate
3479 pkts = self.create_stream_in(self.pg0, self.pg1)
3480 self.pg0.add_stream(pkts)
3481 self.pg_enable_capture(self.pg_interfaces)
3482 self.pg_start()
3483 capture = self.pg1.get_capture(len(pkts))
3484 self.verify_capture_out(capture)
3485
3486 pkts = self.create_stream_out(self.pg1)
3487 self.pg1.add_stream(pkts)
3488 self.pg_enable_capture(self.pg_interfaces)
3489 self.pg_start()
3490 capture = self.pg0.get_capture(len(pkts))
3491 self.verify_capture_in(capture, self.pg0)
3492
3493 tcp_port_out = self.tcp_port_out
3494 udp_port_out = self.udp_port_out
3495 icmp_id_out = self.icmp_id_out
3496
3497 # session initiaded from remote host - do not translate
3498 pkts = self.create_stream_out(self.pg1,
3499 self.pg0.remote_ip4,
3500 use_inside_ports=True)
3501 self.pg1.add_stream(pkts)
3502 self.pg_enable_capture(self.pg_interfaces)
3503 self.pg_start()
3504 capture = self.pg0.get_capture(len(pkts))
3505 self.verify_capture_in(capture, self.pg0)
3506
3507 pkts = self.create_stream_in(self.pg0, self.pg1)
3508 self.pg0.add_stream(pkts)
3509 self.pg_enable_capture(self.pg_interfaces)
3510 self.pg_start()
3511 capture = self.pg1.get_capture(len(pkts))
3512 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3513 same_port=True)
3514
Matus Fabian4d023c82018-03-22 05:50:47 -07003515 def test_output_feature_and_service3(self):
3516 """ NAT44 interface output feature and DST NAT """
3517 external_addr = '1.2.3.4'
3518 external_port = 80
3519 local_port = 8080
3520
3521 self.vapi.nat44_forwarding_enable_disable(1)
3522 self.nat44_add_address(self.nat_addr)
3523 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3524 local_port, external_port,
3525 proto=IP_PROTOS.tcp, out2in_only=1)
3526 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3527 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3528 is_inside=0)
3529 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3530 is_inside=0)
3531
3532 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3533 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3534 TCP(sport=12345, dport=external_port))
3535 self.pg0.add_stream(p)
3536 self.pg_enable_capture(self.pg_interfaces)
3537 self.pg_start()
3538 capture = self.pg1.get_capture(1)
3539 p = capture[0]
3540 try:
3541 ip = p[IP]
3542 tcp = p[TCP]
3543 self.assertEqual(ip.src, self.pg0.remote_ip4)
3544 self.assertEqual(tcp.sport, 12345)
3545 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3546 self.assertEqual(tcp.dport, local_port)
3547 self.check_tcp_checksum(p)
3548 self.check_ip_checksum(p)
3549 except:
3550 self.logger.error(ppp("Unexpected or invalid packet:", p))
3551 raise
3552
3553 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3554 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3555 TCP(sport=local_port, dport=12345))
3556 self.pg1.add_stream(p)
3557 self.pg_enable_capture(self.pg_interfaces)
3558 self.pg_start()
3559 capture = self.pg0.get_capture(1)
3560 p = capture[0]
3561 try:
3562 ip = p[IP]
3563 tcp = p[TCP]
3564 self.assertEqual(ip.src, external_addr)
3565 self.assertEqual(tcp.sport, external_port)
3566 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3567 self.assertEqual(tcp.dport, 12345)
3568 self.check_tcp_checksum(p)
3569 self.check_ip_checksum(p)
3570 except:
3571 self.logger.error(ppp("Unexpected or invalid packet:", p))
3572 raise
3573
Matus Fabian36ea2d62017-10-24 04:13:49 -07003574 def test_one_armed_nat44(self):
3575 """ One armed NAT44 """
3576 remote_host = self.pg9.remote_hosts[0]
3577 local_host = self.pg9.remote_hosts[1]
3578 external_port = 0
3579
3580 self.nat44_add_address(self.nat_addr)
3581 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3582 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3583 is_inside=0)
3584
3585 # in2out
3586 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3587 IP(src=local_host.ip4, dst=remote_host.ip4) /
3588 TCP(sport=12345, dport=80))
3589 self.pg9.add_stream(p)
3590 self.pg_enable_capture(self.pg_interfaces)
3591 self.pg_start()
3592 capture = self.pg9.get_capture(1)
3593 p = capture[0]
3594 try:
3595 ip = p[IP]
3596 tcp = p[TCP]
3597 self.assertEqual(ip.src, self.nat_addr)
3598 self.assertEqual(ip.dst, remote_host.ip4)
3599 self.assertNotEqual(tcp.sport, 12345)
3600 external_port = tcp.sport
3601 self.assertEqual(tcp.dport, 80)
3602 self.check_tcp_checksum(p)
3603 self.check_ip_checksum(p)
3604 except:
3605 self.logger.error(ppp("Unexpected or invalid packet:", p))
3606 raise
3607
3608 # out2in
3609 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3610 IP(src=remote_host.ip4, dst=self.nat_addr) /
3611 TCP(sport=80, dport=external_port))
3612 self.pg9.add_stream(p)
3613 self.pg_enable_capture(self.pg_interfaces)
3614 self.pg_start()
3615 capture = self.pg9.get_capture(1)
3616 p = capture[0]
3617 try:
3618 ip = p[IP]
3619 tcp = p[TCP]
3620 self.assertEqual(ip.src, remote_host.ip4)
3621 self.assertEqual(ip.dst, local_host.ip4)
3622 self.assertEqual(tcp.sport, 80)
3623 self.assertEqual(tcp.dport, 12345)
3624 self.check_tcp_checksum(p)
3625 self.check_ip_checksum(p)
3626 except:
3627 self.logger.error(ppp("Unexpected or invalid packet:", p))
3628 raise
3629
Matus Fabiand95c39e2018-01-23 06:07:01 -08003630 def test_one_armed_nat44_static(self):
3631 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3632 remote_host = self.pg9.remote_hosts[0]
3633 local_host = self.pg9.remote_hosts[1]
3634 external_port = 80
3635 local_port = 8080
3636 eh_port_in = 0
3637
3638 self.vapi.nat44_forwarding_enable_disable(1)
3639 self.nat44_add_address(self.nat_addr, twice_nat=1)
3640 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3641 local_port, external_port,
3642 proto=IP_PROTOS.tcp, out2in_only=1,
3643 twice_nat=1)
3644 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3645 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3646 is_inside=0)
3647
3648 # from client to service
3649 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3650 IP(src=remote_host.ip4, dst=self.nat_addr) /
3651 TCP(sport=12345, dport=external_port))
3652 self.pg9.add_stream(p)
3653 self.pg_enable_capture(self.pg_interfaces)
3654 self.pg_start()
3655 capture = self.pg9.get_capture(1)
3656 p = capture[0]
3657 server = None
3658 try:
3659 ip = p[IP]
3660 tcp = p[TCP]
3661 self.assertEqual(ip.dst, local_host.ip4)
3662 self.assertEqual(ip.src, self.nat_addr)
3663 self.assertEqual(tcp.dport, local_port)
3664 self.assertNotEqual(tcp.sport, 12345)
3665 eh_port_in = tcp.sport
3666 self.check_tcp_checksum(p)
3667 self.check_ip_checksum(p)
3668 except:
3669 self.logger.error(ppp("Unexpected or invalid packet:", p))
3670 raise
3671
3672 # from service back to client
3673 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3674 IP(src=local_host.ip4, dst=self.nat_addr) /
3675 TCP(sport=local_port, dport=eh_port_in))
3676 self.pg9.add_stream(p)
3677 self.pg_enable_capture(self.pg_interfaces)
3678 self.pg_start()
3679 capture = self.pg9.get_capture(1)
3680 p = capture[0]
3681 try:
3682 ip = p[IP]
3683 tcp = p[TCP]
3684 self.assertEqual(ip.src, self.nat_addr)
3685 self.assertEqual(ip.dst, remote_host.ip4)
3686 self.assertEqual(tcp.sport, external_port)
3687 self.assertEqual(tcp.dport, 12345)
3688 self.check_tcp_checksum(p)
3689 self.check_ip_checksum(p)
3690 except:
3691 self.logger.error(ppp("Unexpected or invalid packet:", p))
3692 raise
3693
Matus Fabian5ba86f72017-10-26 03:37:38 -07003694 def test_del_session(self):
3695 """ Delete NAT44 session """
3696 self.nat44_add_address(self.nat_addr)
3697 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3698 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3699 is_inside=0)
3700
3701 pkts = self.create_stream_in(self.pg0, self.pg1)
3702 self.pg0.add_stream(pkts)
3703 self.pg_enable_capture(self.pg_interfaces)
3704 self.pg_start()
3705 capture = self.pg1.get_capture(len(pkts))
3706
3707 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3708 nsessions = len(sessions)
3709
3710 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3711 sessions[0].inside_port,
3712 sessions[0].protocol)
3713 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3714 sessions[1].outside_port,
3715 sessions[1].protocol,
3716 is_in=0)
3717
3718 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3719 self.assertEqual(nsessions - len(sessions), 2)
3720
Matus Fabianefcd1e92017-08-15 06:59:19 -07003721 def test_set_get_reass(self):
3722 """ NAT44 set/get virtual fragmentation reassembly """
3723 reas_cfg1 = self.vapi.nat_get_reass()
3724
3725 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3726 max_reass=reas_cfg1.ip4_max_reass * 2,
3727 max_frag=reas_cfg1.ip4_max_frag * 2)
3728
3729 reas_cfg2 = self.vapi.nat_get_reass()
3730
3731 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3732 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3733 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3734
3735 self.vapi.nat_set_reass(drop_frag=1)
3736 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3737
3738 def test_frag_in_order(self):
3739 """ NAT44 translate fragments arriving in order """
3740 self.nat44_add_address(self.nat_addr)
3741 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3742 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3743 is_inside=0)
3744
3745 data = "A" * 4 + "B" * 16 + "C" * 3
3746 self.tcp_port_in = random.randint(1025, 65535)
3747
3748 reass = self.vapi.nat_reass_dump()
3749 reass_n_start = len(reass)
3750
3751 # in2out
3752 pkts = self.create_stream_frag(self.pg0,
3753 self.pg1.remote_ip4,
3754 self.tcp_port_in,
3755 20,
3756 data)
3757 self.pg0.add_stream(pkts)
3758 self.pg_enable_capture(self.pg_interfaces)
3759 self.pg_start()
3760 frags = self.pg1.get_capture(len(pkts))
3761 p = self.reass_frags_and_verify(frags,
3762 self.nat_addr,
3763 self.pg1.remote_ip4)
3764 self.assertEqual(p[TCP].dport, 20)
3765 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3766 self.tcp_port_out = p[TCP].sport
3767 self.assertEqual(data, p[Raw].load)
3768
3769 # out2in
3770 pkts = self.create_stream_frag(self.pg1,
3771 self.nat_addr,
3772 20,
3773 self.tcp_port_out,
3774 data)
3775 self.pg1.add_stream(pkts)
3776 self.pg_enable_capture(self.pg_interfaces)
3777 self.pg_start()
3778 frags = self.pg0.get_capture(len(pkts))
3779 p = self.reass_frags_and_verify(frags,
3780 self.pg1.remote_ip4,
3781 self.pg0.remote_ip4)
3782 self.assertEqual(p[TCP].sport, 20)
3783 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3784 self.assertEqual(data, p[Raw].load)
3785
3786 reass = self.vapi.nat_reass_dump()
3787 reass_n_end = len(reass)
3788
3789 self.assertEqual(reass_n_end - reass_n_start, 2)
3790
3791 def test_reass_hairpinning(self):
3792 """ NAT44 fragments hairpinning """
3793 host = self.pg0.remote_hosts[0]
3794 server = self.pg0.remote_hosts[1]
3795 host_in_port = random.randint(1025, 65535)
3796 host_out_port = 0
3797 server_in_port = random.randint(1025, 65535)
3798 server_out_port = random.randint(1025, 65535)
3799 data = "A" * 4 + "B" * 16 + "C" * 3
3800
3801 self.nat44_add_address(self.nat_addr)
3802 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3803 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3804 is_inside=0)
3805 # add static mapping for server
3806 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3807 server_in_port, server_out_port,
3808 proto=IP_PROTOS.tcp)
3809
3810 # send packet from host to server
3811 pkts = self.create_stream_frag(self.pg0,
3812 self.nat_addr,
3813 host_in_port,
3814 server_out_port,
3815 data)
3816 self.pg0.add_stream(pkts)
3817 self.pg_enable_capture(self.pg_interfaces)
3818 self.pg_start()
3819 frags = self.pg0.get_capture(len(pkts))
3820 p = self.reass_frags_and_verify(frags,
3821 self.nat_addr,
3822 server.ip4)
3823 self.assertNotEqual(p[TCP].sport, host_in_port)
3824 self.assertEqual(p[TCP].dport, server_in_port)
3825 self.assertEqual(data, p[Raw].load)
3826
3827 def test_frag_out_of_order(self):
3828 """ NAT44 translate fragments arriving out of order """
3829 self.nat44_add_address(self.nat_addr)
3830 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3831 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3832 is_inside=0)
3833
3834 data = "A" * 4 + "B" * 16 + "C" * 3
3835 random.randint(1025, 65535)
3836
3837 # in2out
3838 pkts = self.create_stream_frag(self.pg0,
3839 self.pg1.remote_ip4,
3840 self.tcp_port_in,
3841 20,
3842 data)
3843 pkts.reverse()
3844 self.pg0.add_stream(pkts)
3845 self.pg_enable_capture(self.pg_interfaces)
3846 self.pg_start()
3847 frags = self.pg1.get_capture(len(pkts))
3848 p = self.reass_frags_and_verify(frags,
3849 self.nat_addr,
3850 self.pg1.remote_ip4)
3851 self.assertEqual(p[TCP].dport, 20)
3852 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3853 self.tcp_port_out = p[TCP].sport
3854 self.assertEqual(data, p[Raw].load)
3855
3856 # out2in
3857 pkts = self.create_stream_frag(self.pg1,
3858 self.nat_addr,
3859 20,
3860 self.tcp_port_out,
3861 data)
3862 pkts.reverse()
3863 self.pg1.add_stream(pkts)
3864 self.pg_enable_capture(self.pg_interfaces)
3865 self.pg_start()
3866 frags = self.pg0.get_capture(len(pkts))
3867 p = self.reass_frags_and_verify(frags,
3868 self.pg1.remote_ip4,
3869 self.pg0.remote_ip4)
3870 self.assertEqual(p[TCP].sport, 20)
3871 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3872 self.assertEqual(data, p[Raw].load)
3873
Matus Fabian27697102017-11-09 01:43:47 -08003874 def test_port_restricted(self):
3875 """ Port restricted NAT44 (MAP-E CE) """
3876 self.nat44_add_address(self.nat_addr)
3877 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3878 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3879 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003880 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003881 "psid-offset 6 psid-len 6")
3882
3883 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3884 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3885 TCP(sport=4567, dport=22))
3886 self.pg0.add_stream(p)
3887 self.pg_enable_capture(self.pg_interfaces)
3888 self.pg_start()
3889 capture = self.pg1.get_capture(1)
3890 p = capture[0]
3891 try:
3892 ip = p[IP]
3893 tcp = p[TCP]
3894 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3895 self.assertEqual(ip.src, self.nat_addr)
3896 self.assertEqual(tcp.dport, 22)
3897 self.assertNotEqual(tcp.sport, 4567)
3898 self.assertEqual((tcp.sport >> 6) & 63, 10)
3899 self.check_tcp_checksum(p)
3900 self.check_ip_checksum(p)
3901 except:
3902 self.logger.error(ppp("Unexpected or invalid packet:", p))
3903 raise
3904
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003905 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
3906 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08003907 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003908
Matus Fabianb932d262017-12-18 05:38:24 -08003909 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003910 if lb:
3911 if not same_pg:
3912 port_in1 = port_in
3913 port_in2 = port_in
3914 else:
3915 port_in1 = port_in+1
3916 port_in2 = port_in+2
3917
Matus Fabianb932d262017-12-18 05:38:24 -08003918 port_out = 80
3919 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003920
3921 server1 = self.pg0.remote_hosts[0]
3922 server2 = self.pg0.remote_hosts[1]
3923 if lb and same_pg:
3924 server2 = server1
3925 if not lb:
3926 server = server1
3927
3928 pg0 = self.pg0
3929 if same_pg:
3930 pg1 = self.pg0
3931 else:
3932 pg1 = self.pg1
3933
3934 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
3935 client_id == 1)
3936
Matus Fabianb932d262017-12-18 05:38:24 -08003937 self.nat44_add_address(self.nat_addr)
3938 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003939 if not lb:
3940 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
3941 port_in, port_out,
3942 proto=IP_PROTOS.tcp,
3943 twice_nat=int(not self_twice_nat),
3944 self_twice_nat=int(self_twice_nat))
3945 else:
3946 locals = [{'addr': server1.ip4n,
3947 'port': port_in1,
3948 'probability': 50},
3949 {'addr': server2.ip4n,
3950 'port': port_in2,
3951 'probability': 50}]
3952 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3953 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
3954 port_out,
3955 IP_PROTOS.tcp,
3956 twice_nat=int(
3957 not self_twice_nat),
3958 self_twice_nat=int(
3959 self_twice_nat),
3960 local_num=len(locals),
3961 locals=locals)
3962 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
3963 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08003964 is_inside=0)
3965
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003966 if same_pg:
3967 if not lb:
3968 client = server
3969 else:
3970 assert client_id is not None
3971 if client_id == 1:
3972 client = self.pg0.remote_hosts[0]
3973 elif client_id == 2:
3974 client = self.pg0.remote_hosts[1]
3975 else:
3976 client = pg1.remote_hosts[0]
3977 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
3978 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08003979 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003980 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003981 self.pg_enable_capture(self.pg_interfaces)
3982 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003983 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003984 p = capture[0]
3985 try:
3986 ip = p[IP]
3987 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003988 if lb:
3989 if ip.dst == server1.ip4:
3990 server = server1
3991 port_in = port_in1
3992 else:
3993 server = server2
3994 port_in = port_in2
3995 self.assertEqual(ip.dst, server.ip4)
3996 if lb and same_pg:
3997 self.assertIn(tcp.dport, [port_in1, port_in2])
3998 else:
3999 self.assertEqual(tcp.dport, port_in)
4000 if eh_translate:
4001 self.assertEqual(ip.src, twice_nat_addr)
4002 self.assertNotEqual(tcp.sport, eh_port_out)
4003 else:
4004 self.assertEqual(ip.src, client.ip4)
4005 self.assertEqual(tcp.sport, eh_port_out)
4006 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004007 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004008 saved_port_in = tcp.dport
Matus Fabianb932d262017-12-18 05:38:24 -08004009 self.check_tcp_checksum(p)
4010 self.check_ip_checksum(p)
4011 except:
4012 self.logger.error(ppp("Unexpected or invalid packet:", p))
4013 raise
4014
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004015 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4016 IP(src=server.ip4, dst=eh_addr_in) /
4017 TCP(sport=saved_port_in, dport=eh_port_in))
4018 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004019 self.pg_enable_capture(self.pg_interfaces)
4020 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004021 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004022 p = capture[0]
4023 try:
4024 ip = p[IP]
4025 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004026 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004027 self.assertEqual(ip.src, self.nat_addr)
4028 self.assertEqual(tcp.dport, eh_port_out)
4029 self.assertEqual(tcp.sport, port_out)
4030 self.check_tcp_checksum(p)
4031 self.check_ip_checksum(p)
4032 except:
4033 self.logger.error(ppp("Unexpected or invalid packet:", p))
4034 raise
4035
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004036 def test_twice_nat(self):
4037 """ Twice NAT44 """
4038 self.twice_nat_common()
4039
4040 def test_self_twice_nat_positive(self):
4041 """ Self Twice NAT44 (positive test) """
4042 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4043
4044 def test_self_twice_nat_negative(self):
4045 """ Self Twice NAT44 (negative test) """
4046 self.twice_nat_common(self_twice_nat=True)
4047
Matus Fabianb932d262017-12-18 05:38:24 -08004048 def test_twice_nat_lb(self):
4049 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004050 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004051
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004052 def test_self_twice_nat_lb_positive(self):
4053 """ Self Twice NAT44 local service load balancing (positive test) """
4054 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4055 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004056
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004057 def test_self_twice_nat_lb_negative(self):
4058 """ Self Twice NAT44 local service load balancing (negative test) """
4059 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4060 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004061
4062 def test_twice_nat_interface_addr(self):
4063 """ Acquire twice NAT44 addresses from interface """
4064 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
4065
4066 # no address in NAT pool
4067 adresses = self.vapi.nat44_address_dump()
4068 self.assertEqual(0, len(adresses))
4069
4070 # configure interface address and check NAT address pool
4071 self.pg7.config_ip4()
4072 adresses = self.vapi.nat44_address_dump()
4073 self.assertEqual(1, len(adresses))
4074 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
4075 self.assertEqual(adresses[0].twice_nat, 1)
4076
4077 # remove interface address and check NAT address pool
4078 self.pg7.unconfig_ip4()
4079 adresses = self.vapi.nat44_address_dump()
4080 self.assertEqual(0, len(adresses))
4081
Matus Fabiana431ad12018-01-04 04:03:14 -08004082 def test_ipfix_max_frags(self):
4083 """ IPFIX logging maximum fragments pending reassembly exceeded """
4084 self.nat44_add_address(self.nat_addr)
4085 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4086 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4087 is_inside=0)
4088 self.vapi.nat_set_reass(max_frag=0)
4089 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4090 src_address=self.pg3.local_ip4n,
4091 path_mtu=512,
4092 template_interval=10)
4093 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4094 src_port=self.ipfix_src_port)
4095
4096 data = "A" * 4 + "B" * 16 + "C" * 3
4097 self.tcp_port_in = random.randint(1025, 65535)
4098 pkts = self.create_stream_frag(self.pg0,
4099 self.pg1.remote_ip4,
4100 self.tcp_port_in,
4101 20,
4102 data)
4103 self.pg0.add_stream(pkts[-1])
4104 self.pg_enable_capture(self.pg_interfaces)
4105 self.pg_start()
4106 frags = self.pg1.get_capture(0)
4107 self.vapi.cli("ipfix flush") # FIXME this should be an API call
4108 capture = self.pg3.get_capture(9)
4109 ipfix = IPFIXDecoder()
4110 # first load template
4111 for p in capture:
4112 self.assertTrue(p.haslayer(IPFIX))
4113 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4114 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4115 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4116 self.assertEqual(p[UDP].dport, 4739)
4117 self.assertEqual(p[IPFIX].observationDomainID,
4118 self.ipfix_domain_id)
4119 if p.haslayer(Template):
4120 ipfix.add_template(p.getlayer(Template))
4121 # verify events in data set
4122 for p in capture:
4123 if p.haslayer(Data):
4124 data = ipfix.decode_data_set(p.getlayer(Set))
4125 self.verify_ipfix_max_fragments_ip4(data, 0,
4126 self.pg0.remote_ip4n)
4127
Matus Fabianebdf1902018-05-04 03:57:42 -07004128 def test_tcp_session_close_in(self):
4129 """ Close TCP session from inside network """
4130 self.nat44_add_address(self.nat_addr)
4131 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4132 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4133 is_inside=0)
4134
4135 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4136 start_sessnum = len(sessions)
4137
4138 self.initiate_tcp_session(self.pg0, self.pg1)
4139
4140 # close the session from inside
4141 try:
4142 # FIN packet in -> out
4143 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4144 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4145 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4146 flags="FA"))
4147 self.pg0.add_stream(p)
4148 self.pg_enable_capture(self.pg_interfaces)
4149 self.pg_start()
4150 self.pg1.get_capture(1)
4151
4152 pkts = []
4153
4154 # ACK packet out -> in
4155 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4156 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4157 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4158 flags="A"))
4159 pkts.append(p)
4160
4161 # FIN packet out -> in
4162 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4163 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4164 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4165 flags="FA"))
4166 pkts.append(p)
4167
4168 self.pg1.add_stream(pkts)
4169 self.pg_enable_capture(self.pg_interfaces)
4170 self.pg_start()
4171 self.pg0.get_capture(2)
4172
4173 # ACK packet in -> out
4174 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4175 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4176 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4177 flags="A"))
4178 self.pg0.add_stream(p)
4179 self.pg_enable_capture(self.pg_interfaces)
4180 self.pg_start()
4181 self.pg1.get_capture(1)
4182
4183 self.initiate_tcp_session(self.pg0, self.pg1)
4184 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4185 0)
4186 self.assertEqual(len(sessions) - start_sessnum, 2)
4187 except:
4188 self.logger.error("TCP session termination failed")
4189 raise
4190
4191 def test_tcp_session_close_out(self):
4192 """ Close TCP session from outside network """
4193 self.nat44_add_address(self.nat_addr)
4194 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4195 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4196 is_inside=0)
4197
4198 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4199 start_sessnum = len(sessions)
4200
4201 self.initiate_tcp_session(self.pg0, self.pg1)
4202
4203 # close the session from outside
4204 try:
4205 # FIN packet out -> in
4206 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4207 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4208 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4209 flags="FA"))
4210 self.pg1.add_stream(p)
4211 self.pg_enable_capture(self.pg_interfaces)
4212 self.pg_start()
4213 self.pg0.get_capture(1)
4214
4215 pkts = []
4216
4217 # ACK packet in -> out
4218 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4219 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4220 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4221 flags="A"))
4222 pkts.append(p)
4223
4224 # ACK packet in -> out
4225 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4226 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4227 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4228 flags="FA"))
4229 pkts.append(p)
4230
4231 self.pg0.add_stream(pkts)
4232 self.pg_enable_capture(self.pg_interfaces)
4233 self.pg_start()
4234 self.pg1.get_capture(2)
4235
4236 # ACK packet out -> in
4237 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4238 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4239 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4240 flags="A"))
4241 self.pg1.add_stream(p)
4242 self.pg_enable_capture(self.pg_interfaces)
4243 self.pg_start()
4244 self.pg0.get_capture(1)
4245
4246 self.initiate_tcp_session(self.pg0, self.pg1)
4247 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4248 0)
4249 self.assertEqual(len(sessions) - start_sessnum, 2)
4250 except:
4251 self.logger.error("TCP session termination failed")
4252 raise
4253
4254 def test_tcp_session_close_simultaneous(self):
4255 """ Close TCP session from inside network """
4256 self.nat44_add_address(self.nat_addr)
4257 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4258 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4259 is_inside=0)
4260
4261 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4262 start_sessnum = len(sessions)
4263
4264 self.initiate_tcp_session(self.pg0, self.pg1)
4265
4266 # close the session from inside
4267 try:
4268 # FIN packet in -> out
4269 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4270 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4271 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4272 flags="FA"))
4273 self.pg0.add_stream(p)
4274 self.pg_enable_capture(self.pg_interfaces)
4275 self.pg_start()
4276 self.pg1.get_capture(1)
4277
4278 # FIN packet out -> in
4279 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4280 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4281 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4282 flags="FA"))
4283 self.pg1.add_stream(p)
4284 self.pg_enable_capture(self.pg_interfaces)
4285 self.pg_start()
4286 self.pg0.get_capture(1)
4287
4288 # ACK packet in -> out
4289 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4290 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4291 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4292 flags="A"))
4293 self.pg0.add_stream(p)
4294 self.pg_enable_capture(self.pg_interfaces)
4295 self.pg_start()
4296 self.pg1.get_capture(1)
4297
4298 # ACK packet out -> in
4299 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4300 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4301 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4302 flags="A"))
4303 self.pg1.add_stream(p)
4304 self.pg_enable_capture(self.pg_interfaces)
4305 self.pg_start()
4306 self.pg0.get_capture(1)
4307
4308 self.initiate_tcp_session(self.pg0, self.pg1)
4309 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4310 0)
4311 self.assertEqual(len(sessions) - start_sessnum, 2)
4312 except:
4313 self.logger.error("TCP session termination failed")
4314 raise
4315
Matus Fabiande886752016-12-07 03:38:19 -08004316 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004317 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004318 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004319 self.logger.info(self.vapi.cli("show nat44 addresses"))
4320 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4321 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4322 self.logger.info(self.vapi.cli("show nat44 interface address"))
4323 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004324 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004325 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004326 self.clear_nat44()
Matus Fabiande886752016-12-07 03:38:19 -08004327
Matus Fabianeea28d72017-01-13 04:15:54 -08004328
Juraj Slobodacba69362017-12-19 02:09:32 +01004329class TestNAT44Out2InDPO(MethodHolder):
4330 """ NAT44 Test Cases using out2in DPO """
4331
4332 @classmethod
4333 def setUpConstants(cls):
4334 super(TestNAT44Out2InDPO, cls).setUpConstants()
4335 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4336
4337 @classmethod
4338 def setUpClass(cls):
4339 super(TestNAT44Out2InDPO, cls).setUpClass()
4340
4341 try:
4342 cls.tcp_port_in = 6303
4343 cls.tcp_port_out = 6303
4344 cls.udp_port_in = 6304
4345 cls.udp_port_out = 6304
4346 cls.icmp_id_in = 6305
4347 cls.icmp_id_out = 6305
4348 cls.nat_addr = '10.0.0.3'
4349 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4350 cls.dst_ip4 = '192.168.70.1'
4351
4352 cls.create_pg_interfaces(range(2))
4353
4354 cls.pg0.admin_up()
4355 cls.pg0.config_ip4()
4356 cls.pg0.resolve_arp()
4357
4358 cls.pg1.admin_up()
4359 cls.pg1.config_ip6()
4360 cls.pg1.resolve_ndp()
4361
4362 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4363 dst_address_length=0,
4364 next_hop_address=cls.pg1.remote_ip6n,
4365 next_hop_sw_if_index=cls.pg1.sw_if_index)
4366
4367 except Exception:
4368 super(TestNAT44Out2InDPO, cls).tearDownClass()
4369 raise
4370
4371 def configure_xlat(self):
4372 self.dst_ip6_pfx = '1:2:3::'
4373 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4374 self.dst_ip6_pfx)
4375 self.dst_ip6_pfx_len = 96
4376 self.src_ip6_pfx = '4:5:6::'
4377 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4378 self.src_ip6_pfx)
4379 self.src_ip6_pfx_len = 96
4380 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4381 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4382 '\x00\x00\x00\x00', 0, is_translation=1,
4383 is_rfc6052=1)
4384
4385 def test_464xlat_ce(self):
4386 """ Test 464XLAT CE with NAT44 """
4387
4388 self.configure_xlat()
4389
4390 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4391 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4392
4393 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4394 self.dst_ip6_pfx_len)
4395 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4396 self.src_ip6_pfx_len)
4397
4398 try:
4399 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4400 self.pg0.add_stream(pkts)
4401 self.pg_enable_capture(self.pg_interfaces)
4402 self.pg_start()
4403 capture = self.pg1.get_capture(len(pkts))
4404 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4405 dst_ip=out_src_ip6)
4406
4407 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4408 out_dst_ip6)
4409 self.pg1.add_stream(pkts)
4410 self.pg_enable_capture(self.pg_interfaces)
4411 self.pg_start()
4412 capture = self.pg0.get_capture(len(pkts))
4413 self.verify_capture_in(capture, self.pg0)
4414 finally:
4415 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4416 is_add=0)
4417 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4418 self.nat_addr_n, is_add=0)
4419
4420 def test_464xlat_ce_no_nat(self):
4421 """ Test 464XLAT CE without NAT44 """
4422
4423 self.configure_xlat()
4424
4425 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4426 self.dst_ip6_pfx_len)
4427 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4428 self.src_ip6_pfx_len)
4429
4430 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4431 self.pg0.add_stream(pkts)
4432 self.pg_enable_capture(self.pg_interfaces)
4433 self.pg_start()
4434 capture = self.pg1.get_capture(len(pkts))
4435 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4436 nat_ip=out_dst_ip6, same_port=True)
4437
4438 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4439 self.pg1.add_stream(pkts)
4440 self.pg_enable_capture(self.pg_interfaces)
4441 self.pg_start()
4442 capture = self.pg0.get_capture(len(pkts))
4443 self.verify_capture_in(capture, self.pg0)
4444
4445
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004446class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004447 """ Deterministic NAT Test Cases """
4448
4449 @classmethod
4450 def setUpConstants(cls):
4451 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004452 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004453
4454 @classmethod
4455 def setUpClass(cls):
4456 super(TestDeterministicNAT, cls).setUpClass()
4457
4458 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004459 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004460 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004461 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004462 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004463 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004464 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004465
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004466 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004467 cls.interfaces = list(cls.pg_interfaces)
4468
4469 for i in cls.interfaces:
4470 i.admin_up()
4471 i.config_ip4()
4472 i.resolve_arp()
4473
Martin Gálik977c1cb2017-03-30 23:21:51 -07004474 cls.pg0.generate_remote_hosts(2)
4475 cls.pg0.configure_ipv4_neighbors()
4476
Matus Fabian066f0342017-02-10 03:48:01 -08004477 except Exception:
4478 super(TestDeterministicNAT, cls).tearDownClass()
4479 raise
4480
Martin Gálik977c1cb2017-03-30 23:21:51 -07004481 def create_stream_in(self, in_if, out_if, ttl=64):
4482 """
4483 Create packet stream for inside network
4484
4485 :param in_if: Inside interface
4486 :param out_if: Outside interface
4487 :param ttl: TTL of generated packets
4488 """
4489 pkts = []
4490 # TCP
4491 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4492 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004493 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004494 pkts.append(p)
4495
4496 # UDP
4497 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4498 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004499 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004500 pkts.append(p)
4501
4502 # ICMP
4503 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4504 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4505 ICMP(id=self.icmp_id_in, type='echo-request'))
4506 pkts.append(p)
4507
4508 return pkts
4509
4510 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4511 """
4512 Create packet stream for outside network
4513
4514 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004515 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004516 :param ttl: TTL of generated packets
4517 """
4518 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004519 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004520 pkts = []
4521 # TCP
4522 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4523 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004524 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004525 pkts.append(p)
4526
4527 # UDP
4528 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4529 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004530 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004531 pkts.append(p)
4532
4533 # ICMP
4534 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4535 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4536 ICMP(id=self.icmp_external_id, type='echo-reply'))
4537 pkts.append(p)
4538
4539 return pkts
4540
4541 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4542 """
4543 Verify captured packets on outside network
4544
4545 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004546 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004547 :param same_port: Sorce port number is not translated (Default False)
4548 :param packet_num: Expected number of packets (Default 3)
4549 """
4550 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004551 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004552 self.assertEqual(packet_num, len(capture))
4553 for packet in capture:
4554 try:
4555 self.assertEqual(packet[IP].src, nat_ip)
4556 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004557 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004558 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004559 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004560 else:
4561 self.icmp_external_id = packet[ICMP].id
4562 except:
4563 self.logger.error(ppp("Unexpected or invalid packet "
4564 "(outside network):", packet))
4565 raise
4566
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004567 def verify_ipfix_max_entries_per_user(self, data):
4568 """
4569 Verify IPFIX maximum entries per user exceeded event
4570
4571 :param data: Decoded IPFIX data records
4572 """
4573 self.assertEqual(1, len(data))
4574 record = data[0]
4575 # natEvent
4576 self.assertEqual(ord(record[230]), 13)
4577 # natQuotaExceededEvent
4578 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004579 # maxEntriesPerUser
4580 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004581 # sourceIPv4Address
4582 self.assertEqual(self.pg0.remote_ip4n, record[8])
4583
Matus Fabian066f0342017-02-10 03:48:01 -08004584 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004585 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004586 in_addr = '172.16.255.0'
4587 out_addr = '172.17.255.50'
4588 in_addr_t = '172.16.255.20'
4589 in_addr_n = socket.inet_aton(in_addr)
4590 out_addr_n = socket.inet_aton(out_addr)
4591 in_addr_t_n = socket.inet_aton(in_addr_t)
4592 in_plen = 24
4593 out_plen = 32
4594
Matus Fabian2ba92e32017-08-21 07:05:03 -07004595 nat_config = self.vapi.nat_show_config()
4596 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004597
Matus Fabian2ba92e32017-08-21 07:05:03 -07004598 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004599
Matus Fabian2ba92e32017-08-21 07:05:03 -07004600 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004601 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004602 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004603 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4604
Matus Fabian2ba92e32017-08-21 07:05:03 -07004605 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004606 self.assertEqual(len(deterministic_mappings), 1)
4607 dsm = deterministic_mappings[0]
4608 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4609 self.assertEqual(in_plen, dsm.in_plen)
4610 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4611 self.assertEqual(out_plen, dsm.out_plen)
4612
Matus Fabian2ba92e32017-08-21 07:05:03 -07004613 self.clear_nat_det()
4614 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004615 self.assertEqual(len(deterministic_mappings), 0)
4616
Matus Fabian6a0946f2017-04-12 03:36:13 -07004617 def test_set_timeouts(self):
4618 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004619 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004620
Matus Fabian2ba92e32017-08-21 07:05:03 -07004621 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4622 timeouts_before.tcp_established + 10,
4623 timeouts_before.tcp_transitory + 10,
4624 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004625
Matus Fabian2ba92e32017-08-21 07:05:03 -07004626 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004627
4628 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4629 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4630 self.assertNotEqual(timeouts_before.tcp_established,
4631 timeouts_after.tcp_established)
4632 self.assertNotEqual(timeouts_before.tcp_transitory,
4633 timeouts_after.tcp_transitory)
4634
Martin Gálik977c1cb2017-03-30 23:21:51 -07004635 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004636 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004637
4638 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004639
Matus Fabian2ba92e32017-08-21 07:05:03 -07004640 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4641 32,
4642 socket.inet_aton(nat_ip),
4643 32)
4644 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4645 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4646 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004647
4648 # in2out
4649 pkts = self.create_stream_in(self.pg0, self.pg1)
4650 self.pg0.add_stream(pkts)
4651 self.pg_enable_capture(self.pg_interfaces)
4652 self.pg_start()
4653 capture = self.pg1.get_capture(len(pkts))
4654 self.verify_capture_out(capture, nat_ip)
4655
4656 # out2in
4657 pkts = self.create_stream_out(self.pg1, nat_ip)
4658 self.pg1.add_stream(pkts)
4659 self.pg_enable_capture(self.pg_interfaces)
4660 self.pg_start()
4661 capture = self.pg0.get_capture(len(pkts))
4662 self.verify_capture_in(capture, self.pg0)
4663
Martin Gálik9806eae2017-04-25 01:25:08 -07004664 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004665 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004666 self.assertEqual(len(sessions), 3)
4667
4668 # TCP session
4669 s = sessions[0]
4670 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4671 self.assertEqual(s.in_port, self.tcp_port_in)
4672 self.assertEqual(s.out_port, self.tcp_port_out)
4673 self.assertEqual(s.ext_port, self.tcp_external_port)
4674
4675 # UDP session
4676 s = sessions[1]
4677 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4678 self.assertEqual(s.in_port, self.udp_port_in)
4679 self.assertEqual(s.out_port, self.udp_port_out)
4680 self.assertEqual(s.ext_port, self.udp_external_port)
4681
4682 # ICMP session
4683 s = sessions[2]
4684 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4685 self.assertEqual(s.in_port, self.icmp_id_in)
4686 self.assertEqual(s.out_port, self.icmp_external_id)
4687
Martin Gálik977c1cb2017-03-30 23:21:51 -07004688 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004689 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004690
4691 nat_ip = "10.0.0.10"
4692 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004693 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004694
4695 host0 = self.pg0.remote_hosts[0]
4696 host1 = self.pg0.remote_hosts[1]
4697
Matus Fabian2ba92e32017-08-21 07:05:03 -07004698 self.vapi.nat_det_add_del_map(host0.ip4n,
4699 24,
4700 socket.inet_aton(nat_ip),
4701 32)
4702 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4703 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4704 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004705
4706 # host0 to out
4707 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4708 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004709 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004710 self.pg0.add_stream(p)
4711 self.pg_enable_capture(self.pg_interfaces)
4712 self.pg_start()
4713 capture = self.pg1.get_capture(1)
4714 p = capture[0]
4715 try:
4716 ip = p[IP]
4717 tcp = p[TCP]
4718 self.assertEqual(ip.src, nat_ip)
4719 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004720 self.assertEqual(tcp.dport, external_port)
4721 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004722 except:
4723 self.logger.error(ppp("Unexpected or invalid packet:", p))
4724 raise
4725
4726 # host1 to out
4727 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4728 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004729 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004730 self.pg0.add_stream(p)
4731 self.pg_enable_capture(self.pg_interfaces)
4732 self.pg_start()
4733 capture = self.pg1.get_capture(1)
4734 p = capture[0]
4735 try:
4736 ip = p[IP]
4737 tcp = p[TCP]
4738 self.assertEqual(ip.src, nat_ip)
4739 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004740 self.assertEqual(tcp.dport, external_port)
4741 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004742 except:
4743 self.logger.error(ppp("Unexpected or invalid packet:", p))
4744 raise
4745
Matus Fabian2ba92e32017-08-21 07:05:03 -07004746 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004747 self.assertEqual(1, len(dms))
4748 self.assertEqual(2, dms[0].ses_num)
4749
4750 # out to host0
4751 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4752 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004753 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004754 self.pg1.add_stream(p)
4755 self.pg_enable_capture(self.pg_interfaces)
4756 self.pg_start()
4757 capture = self.pg0.get_capture(1)
4758 p = capture[0]
4759 try:
4760 ip = p[IP]
4761 tcp = p[TCP]
4762 self.assertEqual(ip.src, self.pg1.remote_ip4)
4763 self.assertEqual(ip.dst, host0.ip4)
4764 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004765 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004766 except:
4767 self.logger.error(ppp("Unexpected or invalid packet:", p))
4768 raise
4769
4770 # out to host1
4771 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4772 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004773 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004774 self.pg1.add_stream(p)
4775 self.pg_enable_capture(self.pg_interfaces)
4776 self.pg_start()
4777 capture = self.pg0.get_capture(1)
4778 p = capture[0]
4779 try:
4780 ip = p[IP]
4781 tcp = p[TCP]
4782 self.assertEqual(ip.src, self.pg1.remote_ip4)
4783 self.assertEqual(ip.dst, host1.ip4)
4784 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004785 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004786 except:
4787 self.logger.error(ppp("Unexpected or invalid packet", p))
4788 raise
4789
Martin Gálik6bc8c642017-04-19 01:12:27 -07004790 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004791 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4792 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004793 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004794 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004795 dms = self.vapi.nat_det_map_dump()
4796 self.assertEqual(dms[0].ses_num, 1)
4797
4798 self.vapi.nat_det_close_session_in(host0.ip4n,
4799 port_in,
4800 self.pg1.remote_ip4n,
4801 external_port)
4802 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004803 self.assertEqual(dms[0].ses_num, 0)
4804
Martin Gálik977c1cb2017-03-30 23:21:51 -07004805 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004806 """ Deterministic NAT TCP session close from inside network """
4807 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4808 32,
4809 socket.inet_aton(self.nat_addr),
4810 32)
4811 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4812 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4813 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004814
4815 self.initiate_tcp_session(self.pg0, self.pg1)
4816
4817 # close the session from inside
4818 try:
4819 # FIN packet in -> out
4820 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4821 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004822 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004823 flags="F"))
4824 self.pg0.add_stream(p)
4825 self.pg_enable_capture(self.pg_interfaces)
4826 self.pg_start()
4827 self.pg1.get_capture(1)
4828
4829 pkts = []
4830
4831 # ACK packet out -> in
4832 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004833 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004834 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004835 flags="A"))
4836 pkts.append(p)
4837
4838 # FIN packet out -> in
4839 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004840 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004841 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004842 flags="F"))
4843 pkts.append(p)
4844
4845 self.pg1.add_stream(pkts)
4846 self.pg_enable_capture(self.pg_interfaces)
4847 self.pg_start()
4848 self.pg0.get_capture(2)
4849
4850 # ACK packet in -> out
4851 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4852 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004853 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004854 flags="A"))
4855 self.pg0.add_stream(p)
4856 self.pg_enable_capture(self.pg_interfaces)
4857 self.pg_start()
4858 self.pg1.get_capture(1)
4859
Matus Fabian2ba92e32017-08-21 07:05:03 -07004860 # Check if deterministic NAT44 closed the session
4861 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004862 self.assertEqual(0, dms[0].ses_num)
4863 except:
4864 self.logger.error("TCP session termination failed")
4865 raise
4866
4867 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004868 """ Deterministic NAT TCP session close from outside network """
4869 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4870 32,
4871 socket.inet_aton(self.nat_addr),
4872 32)
4873 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4874 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4875 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004876
4877 self.initiate_tcp_session(self.pg0, self.pg1)
4878
4879 # close the session from outside
4880 try:
4881 # FIN packet out -> in
4882 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004883 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004884 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004885 flags="F"))
4886 self.pg1.add_stream(p)
4887 self.pg_enable_capture(self.pg_interfaces)
4888 self.pg_start()
4889 self.pg0.get_capture(1)
4890
4891 pkts = []
4892
4893 # ACK packet in -> out
4894 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4895 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004896 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004897 flags="A"))
4898 pkts.append(p)
4899
4900 # ACK packet in -> out
4901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4902 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004903 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004904 flags="F"))
4905 pkts.append(p)
4906
4907 self.pg0.add_stream(pkts)
4908 self.pg_enable_capture(self.pg_interfaces)
4909 self.pg_start()
4910 self.pg1.get_capture(2)
4911
4912 # ACK packet out -> in
4913 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004914 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004915 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004916 flags="A"))
4917 self.pg1.add_stream(p)
4918 self.pg_enable_capture(self.pg_interfaces)
4919 self.pg_start()
4920 self.pg0.get_capture(1)
4921
Matus Fabian2ba92e32017-08-21 07:05:03 -07004922 # Check if deterministic NAT44 closed the session
4923 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004924 self.assertEqual(0, dms[0].ses_num)
4925 except:
4926 self.logger.error("TCP session termination failed")
4927 raise
4928
4929 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4930 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004931 """ Deterministic NAT session timeouts """
4932 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4933 32,
4934 socket.inet_aton(self.nat_addr),
4935 32)
4936 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4937 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4938 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004939
4940 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004941 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004942 pkts = self.create_stream_in(self.pg0, self.pg1)
4943 self.pg0.add_stream(pkts)
4944 self.pg_enable_capture(self.pg_interfaces)
4945 self.pg_start()
4946 capture = self.pg1.get_capture(len(pkts))
4947 sleep(15)
4948
Matus Fabian2ba92e32017-08-21 07:05:03 -07004949 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004950 self.assertEqual(0, dms[0].ses_num)
4951
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004952 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004953 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004954 """ Deterministic NAT maximum sessions per user limit """
4955 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4956 32,
4957 socket.inet_aton(self.nat_addr),
4958 32)
4959 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4960 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4961 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004962 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4963 src_address=self.pg2.local_ip4n,
4964 path_mtu=512,
4965 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004966 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004967
4968 pkts = []
4969 for port in range(1025, 2025):
4970 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4971 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4972 UDP(sport=port, dport=port))
4973 pkts.append(p)
4974
4975 self.pg0.add_stream(pkts)
4976 self.pg_enable_capture(self.pg_interfaces)
4977 self.pg_start()
4978 capture = self.pg1.get_capture(len(pkts))
4979
4980 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4981 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07004982 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004983 self.pg0.add_stream(p)
4984 self.pg_enable_capture(self.pg_interfaces)
4985 self.pg_start()
4986 capture = self.pg1.assert_nothing_captured()
4987
Martin Gálikf7e655d2017-04-27 02:13:26 -07004988 # verify ICMP error packet
4989 capture = self.pg0.get_capture(1)
4990 p = capture[0]
4991 self.assertTrue(p.haslayer(ICMP))
4992 icmp = p[ICMP]
4993 self.assertEqual(icmp.type, 3)
4994 self.assertEqual(icmp.code, 1)
4995 self.assertTrue(icmp.haslayer(IPerror))
4996 inner_ip = icmp[IPerror]
4997 self.assertEqual(inner_ip[UDPerror].sport, 3001)
4998 self.assertEqual(inner_ip[UDPerror].dport, 3002)
4999
Matus Fabian2ba92e32017-08-21 07:05:03 -07005000 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005001
5002 self.assertEqual(1000, dms[0].ses_num)
5003
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005004 # verify IPFIX logging
5005 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005006 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005007 capture = self.pg2.get_capture(2)
5008 ipfix = IPFIXDecoder()
5009 # first load template
5010 for p in capture:
5011 self.assertTrue(p.haslayer(IPFIX))
5012 if p.haslayer(Template):
5013 ipfix.add_template(p.getlayer(Template))
5014 # verify events in data set
5015 for p in capture:
5016 if p.haslayer(Data):
5017 data = ipfix.decode_data_set(p.getlayer(Set))
5018 self.verify_ipfix_max_entries_per_user(data)
5019
Matus Fabian2ba92e32017-08-21 07:05:03 -07005020 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005021 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005022 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005023 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005024 self.vapi.nat_ipfix(enable=0)
5025 self.vapi.nat_det_set_timeouts()
5026 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005027 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005028 self.vapi.nat_det_add_del_map(dsm.in_addr,
5029 dsm.in_plen,
5030 dsm.out_addr,
5031 dsm.out_plen,
5032 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005033
Matus Fabian2ba92e32017-08-21 07:05:03 -07005034 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005035 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005036 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5037 intf.is_inside,
5038 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005039
Matus Fabian066f0342017-02-10 03:48:01 -08005040 def tearDown(self):
5041 super(TestDeterministicNAT, self).tearDown()
5042 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005043 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5044 self.logger.info(
5045 self.vapi.cli("show nat44 deterministic mappings"))
5046 self.logger.info(
5047 self.vapi.cli("show nat44 deterministic timeouts"))
5048 self.logger.info(
5049 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005050 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005051
Matus Fabian06596c52017-06-06 04:53:28 -07005052
5053class TestNAT64(MethodHolder):
5054 """ NAT64 Test Cases """
5055
5056 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005057 def setUpConstants(cls):
5058 super(TestNAT64, cls).setUpConstants()
5059 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5060 "nat64 st hash buckets 256", "}"])
5061
5062 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005063 def setUpClass(cls):
5064 super(TestNAT64, cls).setUpClass()
5065
5066 try:
5067 cls.tcp_port_in = 6303
5068 cls.tcp_port_out = 6303
5069 cls.udp_port_in = 6304
5070 cls.udp_port_out = 6304
5071 cls.icmp_id_in = 6305
5072 cls.icmp_id_out = 6305
5073 cls.nat_addr = '10.0.0.3'
5074 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005075 cls.vrf1_id = 10
5076 cls.vrf1_nat_addr = '10.0.10.3'
5077 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5078 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005079 cls.ipfix_src_port = 4739
5080 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005081
Matus Fabian0938dcf2017-11-08 01:59:38 -08005082 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07005083 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005084 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005085 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5086
Neale Ranns15002542017-09-10 04:39:11 -07005087 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5088
Matus Fabian029f3d22017-06-15 02:28:50 -07005089 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5090
5091 cls.pg0.generate_remote_hosts(2)
5092
Matus Fabian06596c52017-06-06 04:53:28 -07005093 for i in cls.ip6_interfaces:
5094 i.admin_up()
5095 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005096 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005097
5098 for i in cls.ip4_interfaces:
5099 i.admin_up()
5100 i.config_ip4()
5101 i.resolve_arp()
5102
Matus Fabian36ea2d62017-10-24 04:13:49 -07005103 cls.pg3.admin_up()
5104 cls.pg3.config_ip4()
5105 cls.pg3.resolve_arp()
5106 cls.pg3.config_ip6()
5107 cls.pg3.configure_ipv6_neighbors()
5108
Matus Fabian06596c52017-06-06 04:53:28 -07005109 except Exception:
5110 super(TestNAT64, cls).tearDownClass()
5111 raise
5112
5113 def test_pool(self):
5114 """ Add/delete address to NAT64 pool """
5115 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5116
5117 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5118
5119 addresses = self.vapi.nat64_pool_addr_dump()
5120 self.assertEqual(len(addresses), 1)
5121 self.assertEqual(addresses[0].address, nat_addr)
5122
5123 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5124
5125 addresses = self.vapi.nat64_pool_addr_dump()
5126 self.assertEqual(len(addresses), 0)
5127
5128 def test_interface(self):
5129 """ Enable/disable NAT64 feature on the interface """
5130 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5131 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5132
5133 interfaces = self.vapi.nat64_interface_dump()
5134 self.assertEqual(len(interfaces), 2)
5135 pg0_found = False
5136 pg1_found = False
5137 for intf in interfaces:
5138 if intf.sw_if_index == self.pg0.sw_if_index:
5139 self.assertEqual(intf.is_inside, 1)
5140 pg0_found = True
5141 elif intf.sw_if_index == self.pg1.sw_if_index:
5142 self.assertEqual(intf.is_inside, 0)
5143 pg1_found = True
5144 self.assertTrue(pg0_found)
5145 self.assertTrue(pg1_found)
5146
5147 features = self.vapi.cli("show interface features pg0")
5148 self.assertNotEqual(features.find('nat64-in2out'), -1)
5149 features = self.vapi.cli("show interface features pg1")
5150 self.assertNotEqual(features.find('nat64-out2in'), -1)
5151
5152 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5153 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5154
5155 interfaces = self.vapi.nat64_interface_dump()
5156 self.assertEqual(len(interfaces), 0)
5157
5158 def test_static_bib(self):
5159 """ Add/delete static BIB entry """
5160 in_addr = socket.inet_pton(socket.AF_INET6,
5161 '2001:db8:85a3::8a2e:370:7334')
5162 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5163 in_port = 1234
5164 out_port = 5678
5165 proto = IP_PROTOS.tcp
5166
5167 self.vapi.nat64_add_del_static_bib(in_addr,
5168 out_addr,
5169 in_port,
5170 out_port,
5171 proto)
5172 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5173 static_bib_num = 0
5174 for bibe in bib:
5175 if bibe.is_static:
5176 static_bib_num += 1
5177 self.assertEqual(bibe.i_addr, in_addr)
5178 self.assertEqual(bibe.o_addr, out_addr)
5179 self.assertEqual(bibe.i_port, in_port)
5180 self.assertEqual(bibe.o_port, out_port)
5181 self.assertEqual(static_bib_num, 1)
5182
5183 self.vapi.nat64_add_del_static_bib(in_addr,
5184 out_addr,
5185 in_port,
5186 out_port,
5187 proto,
5188 is_add=0)
5189 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5190 static_bib_num = 0
5191 for bibe in bib:
5192 if bibe.is_static:
5193 static_bib_num += 1
5194 self.assertEqual(static_bib_num, 0)
5195
5196 def test_set_timeouts(self):
5197 """ Set NAT64 timeouts """
5198 # verify default values
5199 timeouts = self.vapi.nat64_get_timeouts()
5200 self.assertEqual(timeouts.udp, 300)
5201 self.assertEqual(timeouts.icmp, 60)
5202 self.assertEqual(timeouts.tcp_trans, 240)
5203 self.assertEqual(timeouts.tcp_est, 7440)
5204 self.assertEqual(timeouts.tcp_incoming_syn, 6)
5205
5206 # set and verify custom values
5207 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5208 tcp_est=7450, tcp_incoming_syn=10)
5209 timeouts = self.vapi.nat64_get_timeouts()
5210 self.assertEqual(timeouts.udp, 200)
5211 self.assertEqual(timeouts.icmp, 30)
5212 self.assertEqual(timeouts.tcp_trans, 250)
5213 self.assertEqual(timeouts.tcp_est, 7450)
5214 self.assertEqual(timeouts.tcp_incoming_syn, 10)
5215
5216 def test_dynamic(self):
5217 """ NAT64 dynamic translation test """
5218 self.tcp_port_in = 6303
5219 self.udp_port_in = 6304
5220 self.icmp_id_in = 6305
5221
5222 ses_num_start = self.nat64_get_ses_num()
5223
5224 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5225 self.nat_addr_n)
5226 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5227 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5228
5229 # in2out
5230 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5231 self.pg0.add_stream(pkts)
5232 self.pg_enable_capture(self.pg_interfaces)
5233 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005234 capture = self.pg1.get_capture(len(pkts))
5235 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005236 dst_ip=self.pg1.remote_ip4)
5237
5238 # out2in
5239 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5240 self.pg1.add_stream(pkts)
5241 self.pg_enable_capture(self.pg_interfaces)
5242 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005243 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005244 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5245 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5246
5247 # in2out
5248 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5249 self.pg0.add_stream(pkts)
5250 self.pg_enable_capture(self.pg_interfaces)
5251 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005252 capture = self.pg1.get_capture(len(pkts))
5253 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005254 dst_ip=self.pg1.remote_ip4)
5255
5256 # out2in
5257 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5258 self.pg1.add_stream(pkts)
5259 self.pg_enable_capture(self.pg_interfaces)
5260 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005261 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005262 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5263
5264 ses_num_end = self.nat64_get_ses_num()
5265
5266 self.assertEqual(ses_num_end - ses_num_start, 3)
5267
Matus Fabian029f3d22017-06-15 02:28:50 -07005268 # tenant with specific VRF
5269 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5270 self.vrf1_nat_addr_n,
5271 vrf_id=self.vrf1_id)
5272 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5273
5274 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5275 self.pg2.add_stream(pkts)
5276 self.pg_enable_capture(self.pg_interfaces)
5277 self.pg_start()
5278 capture = self.pg1.get_capture(len(pkts))
5279 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5280 dst_ip=self.pg1.remote_ip4)
5281
5282 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5283 self.pg1.add_stream(pkts)
5284 self.pg_enable_capture(self.pg_interfaces)
5285 self.pg_start()
5286 capture = self.pg2.get_capture(len(pkts))
5287 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5288
Matus Fabian06596c52017-06-06 04:53:28 -07005289 def test_static(self):
5290 """ NAT64 static translation test """
5291 self.tcp_port_in = 60303
5292 self.udp_port_in = 60304
5293 self.icmp_id_in = 60305
5294 self.tcp_port_out = 60303
5295 self.udp_port_out = 60304
5296 self.icmp_id_out = 60305
5297
5298 ses_num_start = self.nat64_get_ses_num()
5299
5300 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5301 self.nat_addr_n)
5302 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5303 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5304
5305 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5306 self.nat_addr_n,
5307 self.tcp_port_in,
5308 self.tcp_port_out,
5309 IP_PROTOS.tcp)
5310 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5311 self.nat_addr_n,
5312 self.udp_port_in,
5313 self.udp_port_out,
5314 IP_PROTOS.udp)
5315 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5316 self.nat_addr_n,
5317 self.icmp_id_in,
5318 self.icmp_id_out,
5319 IP_PROTOS.icmp)
5320
5321 # in2out
5322 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5323 self.pg0.add_stream(pkts)
5324 self.pg_enable_capture(self.pg_interfaces)
5325 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005326 capture = self.pg1.get_capture(len(pkts))
5327 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005328 dst_ip=self.pg1.remote_ip4, same_port=True)
5329
5330 # out2in
5331 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5332 self.pg1.add_stream(pkts)
5333 self.pg_enable_capture(self.pg_interfaces)
5334 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005335 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005336 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5337 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5338
5339 ses_num_end = self.nat64_get_ses_num()
5340
5341 self.assertEqual(ses_num_end - ses_num_start, 3)
5342
5343 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5344 def test_session_timeout(self):
5345 """ NAT64 session timeout """
5346 self.icmp_id_in = 1234
5347 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5348 self.nat_addr_n)
5349 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5350 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5351 self.vapi.nat64_set_timeouts(icmp=5)
5352
5353 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5354 self.pg0.add_stream(pkts)
5355 self.pg_enable_capture(self.pg_interfaces)
5356 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005357 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005358
5359 ses_num_before_timeout = self.nat64_get_ses_num()
5360
5361 sleep(15)
5362
5363 # ICMP session after timeout
5364 ses_num_after_timeout = self.nat64_get_ses_num()
5365 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5366
Matus Fabian732036d2017-06-08 05:24:28 -07005367 def test_icmp_error(self):
5368 """ NAT64 ICMP Error message translation """
5369 self.tcp_port_in = 6303
5370 self.udp_port_in = 6304
5371 self.icmp_id_in = 6305
5372
5373 ses_num_start = self.nat64_get_ses_num()
5374
5375 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5376 self.nat_addr_n)
5377 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5378 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5379
5380 # send some packets to create sessions
5381 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5382 self.pg0.add_stream(pkts)
5383 self.pg_enable_capture(self.pg_interfaces)
5384 self.pg_start()
5385 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005386 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005387 nat_ip=self.nat_addr,
5388 dst_ip=self.pg1.remote_ip4)
5389
5390 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5391 self.pg1.add_stream(pkts)
5392 self.pg_enable_capture(self.pg_interfaces)
5393 self.pg_start()
5394 capture_ip6 = self.pg0.get_capture(len(pkts))
5395 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5396 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5397 self.pg0.remote_ip6)
5398
5399 # in2out
5400 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5401 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5402 ICMPv6DestUnreach(code=1) /
5403 packet[IPv6] for packet in capture_ip6]
5404 self.pg0.add_stream(pkts)
5405 self.pg_enable_capture(self.pg_interfaces)
5406 self.pg_start()
5407 capture = self.pg1.get_capture(len(pkts))
5408 for packet in capture:
5409 try:
5410 self.assertEqual(packet[IP].src, self.nat_addr)
5411 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5412 self.assertEqual(packet[ICMP].type, 3)
5413 self.assertEqual(packet[ICMP].code, 13)
5414 inner = packet[IPerror]
5415 self.assertEqual(inner.src, self.pg1.remote_ip4)
5416 self.assertEqual(inner.dst, self.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005417 self.check_icmp_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005418 if inner.haslayer(TCPerror):
5419 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5420 elif inner.haslayer(UDPerror):
5421 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5422 else:
5423 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5424 except:
5425 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5426 raise
5427
5428 # out2in
5429 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5430 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5431 ICMP(type=3, code=13) /
5432 packet[IP] for packet in capture_ip4]
5433 self.pg1.add_stream(pkts)
5434 self.pg_enable_capture(self.pg_interfaces)
5435 self.pg_start()
5436 capture = self.pg0.get_capture(len(pkts))
5437 for packet in capture:
5438 try:
5439 self.assertEqual(packet[IPv6].src, ip.src)
5440 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5441 icmp = packet[ICMPv6DestUnreach]
5442 self.assertEqual(icmp.code, 1)
5443 inner = icmp[IPerror6]
5444 self.assertEqual(inner.src, self.pg0.remote_ip6)
5445 self.assertEqual(inner.dst, ip.src)
Matus Fabian029f3d22017-06-15 02:28:50 -07005446 self.check_icmpv6_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005447 if inner.haslayer(TCPerror):
5448 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5449 elif inner.haslayer(UDPerror):
5450 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5451 else:
5452 self.assertEqual(inner[ICMPv6EchoRequest].id,
5453 self.icmp_id_in)
5454 except:
5455 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5456 raise
5457
Matus Fabian029f3d22017-06-15 02:28:50 -07005458 def test_hairpinning(self):
5459 """ NAT64 hairpinning """
5460
5461 client = self.pg0.remote_hosts[0]
5462 server = self.pg0.remote_hosts[1]
5463 server_tcp_in_port = 22
5464 server_tcp_out_port = 4022
5465 server_udp_in_port = 23
5466 server_udp_out_port = 4023
5467 client_tcp_in_port = 1234
5468 client_udp_in_port = 1235
5469 client_tcp_out_port = 0
5470 client_udp_out_port = 0
5471 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5472 nat_addr_ip6 = ip.src
5473
5474 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5475 self.nat_addr_n)
5476 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5477 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5478
5479 self.vapi.nat64_add_del_static_bib(server.ip6n,
5480 self.nat_addr_n,
5481 server_tcp_in_port,
5482 server_tcp_out_port,
5483 IP_PROTOS.tcp)
5484 self.vapi.nat64_add_del_static_bib(server.ip6n,
5485 self.nat_addr_n,
5486 server_udp_in_port,
5487 server_udp_out_port,
5488 IP_PROTOS.udp)
5489
5490 # client to server
5491 pkts = []
5492 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5493 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5494 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5495 pkts.append(p)
5496 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5497 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5498 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5499 pkts.append(p)
5500 self.pg0.add_stream(pkts)
5501 self.pg_enable_capture(self.pg_interfaces)
5502 self.pg_start()
5503 capture = self.pg0.get_capture(len(pkts))
5504 for packet in capture:
5505 try:
5506 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5507 self.assertEqual(packet[IPv6].dst, server.ip6)
5508 if packet.haslayer(TCP):
5509 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5510 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
5511 self.check_tcp_checksum(packet)
5512 client_tcp_out_port = packet[TCP].sport
5513 else:
5514 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5515 self.assertEqual(packet[UDP].dport, server_udp_in_port)
5516 self.check_udp_checksum(packet)
5517 client_udp_out_port = packet[UDP].sport
5518 except:
5519 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5520 raise
5521
5522 # server to client
5523 pkts = []
5524 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5525 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5526 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5527 pkts.append(p)
5528 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5529 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5530 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5531 pkts.append(p)
5532 self.pg0.add_stream(pkts)
5533 self.pg_enable_capture(self.pg_interfaces)
5534 self.pg_start()
5535 capture = self.pg0.get_capture(len(pkts))
5536 for packet in capture:
5537 try:
5538 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5539 self.assertEqual(packet[IPv6].dst, client.ip6)
5540 if packet.haslayer(TCP):
5541 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5542 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
5543 self.check_tcp_checksum(packet)
5544 else:
5545 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5546 self.assertEqual(packet[UDP].dport, client_udp_in_port)
5547 self.check_udp_checksum(packet)
5548 except:
5549 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5550 raise
5551
5552 # ICMP error
5553 pkts = []
5554 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5555 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5556 ICMPv6DestUnreach(code=1) /
5557 packet[IPv6] for packet in capture]
5558 self.pg0.add_stream(pkts)
5559 self.pg_enable_capture(self.pg_interfaces)
5560 self.pg_start()
5561 capture = self.pg0.get_capture(len(pkts))
5562 for packet in capture:
5563 try:
5564 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5565 self.assertEqual(packet[IPv6].dst, server.ip6)
5566 icmp = packet[ICMPv6DestUnreach]
5567 self.assertEqual(icmp.code, 1)
5568 inner = icmp[IPerror6]
5569 self.assertEqual(inner.src, server.ip6)
5570 self.assertEqual(inner.dst, nat_addr_ip6)
5571 self.check_icmpv6_checksum(packet)
5572 if inner.haslayer(TCPerror):
5573 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5574 self.assertEqual(inner[TCPerror].dport,
5575 client_tcp_out_port)
5576 else:
5577 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5578 self.assertEqual(inner[UDPerror].dport,
5579 client_udp_out_port)
5580 except:
5581 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5582 raise
5583
Matus Fabian428dc912017-06-21 06:15:18 -07005584 def test_prefix(self):
5585 """ NAT64 Network-Specific Prefix """
5586
5587 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5588 self.nat_addr_n)
5589 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5590 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5591 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5592 self.vrf1_nat_addr_n,
5593 vrf_id=self.vrf1_id)
5594 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5595
5596 # Add global prefix
5597 global_pref64 = "2001:db8::"
5598 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5599 global_pref64_len = 32
5600 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5601
5602 prefix = self.vapi.nat64_prefix_dump()
5603 self.assertEqual(len(prefix), 1)
5604 self.assertEqual(prefix[0].prefix, global_pref64_n)
5605 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5606 self.assertEqual(prefix[0].vrf_id, 0)
5607
5608 # Add tenant specific prefix
5609 vrf1_pref64 = "2001:db8:122:300::"
5610 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5611 vrf1_pref64_len = 56
5612 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5613 vrf1_pref64_len,
5614 vrf_id=self.vrf1_id)
5615 prefix = self.vapi.nat64_prefix_dump()
5616 self.assertEqual(len(prefix), 2)
5617
5618 # Global prefix
5619 pkts = self.create_stream_in_ip6(self.pg0,
5620 self.pg1,
5621 pref=global_pref64,
5622 plen=global_pref64_len)
5623 self.pg0.add_stream(pkts)
5624 self.pg_enable_capture(self.pg_interfaces)
5625 self.pg_start()
5626 capture = self.pg1.get_capture(len(pkts))
5627 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5628 dst_ip=self.pg1.remote_ip4)
5629
5630 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5631 self.pg1.add_stream(pkts)
5632 self.pg_enable_capture(self.pg_interfaces)
5633 self.pg_start()
5634 capture = self.pg0.get_capture(len(pkts))
5635 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5636 global_pref64,
5637 global_pref64_len)
5638 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5639
5640 # Tenant specific prefix
5641 pkts = self.create_stream_in_ip6(self.pg2,
5642 self.pg1,
5643 pref=vrf1_pref64,
5644 plen=vrf1_pref64_len)
5645 self.pg2.add_stream(pkts)
5646 self.pg_enable_capture(self.pg_interfaces)
5647 self.pg_start()
5648 capture = self.pg1.get_capture(len(pkts))
5649 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5650 dst_ip=self.pg1.remote_ip4)
5651
5652 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5653 self.pg1.add_stream(pkts)
5654 self.pg_enable_capture(self.pg_interfaces)
5655 self.pg_start()
5656 capture = self.pg2.get_capture(len(pkts))
5657 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5658 vrf1_pref64,
5659 vrf1_pref64_len)
5660 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5661
Matus Fabianf8cd5812017-07-11 03:55:02 -07005662 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005663 """ NAT64 translate packet with unknown protocol """
5664
5665 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5666 self.nat_addr_n)
5667 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5668 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5669 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5670
5671 # in2out
5672 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5673 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5674 TCP(sport=self.tcp_port_in, dport=20))
5675 self.pg0.add_stream(p)
5676 self.pg_enable_capture(self.pg_interfaces)
5677 self.pg_start()
5678 p = self.pg1.get_capture(1)
5679
5680 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005681 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005682 GRE() /
5683 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5684 TCP(sport=1234, dport=1234))
5685 self.pg0.add_stream(p)
5686 self.pg_enable_capture(self.pg_interfaces)
5687 self.pg_start()
5688 p = self.pg1.get_capture(1)
5689 packet = p[0]
5690 try:
5691 self.assertEqual(packet[IP].src, self.nat_addr)
5692 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5693 self.assertTrue(packet.haslayer(GRE))
5694 self.check_ip_checksum(packet)
5695 except:
5696 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5697 raise
5698
5699 # out2in
5700 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5701 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5702 GRE() /
5703 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5704 TCP(sport=1234, dport=1234))
5705 self.pg1.add_stream(p)
5706 self.pg_enable_capture(self.pg_interfaces)
5707 self.pg_start()
5708 p = self.pg0.get_capture(1)
5709 packet = p[0]
5710 try:
5711 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005712 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5713 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005714 except:
5715 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5716 raise
5717
Matus Fabianf8cd5812017-07-11 03:55:02 -07005718 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005719 """ NAT64 translate packet with unknown protocol - hairpinning """
5720
5721 client = self.pg0.remote_hosts[0]
5722 server = self.pg0.remote_hosts[1]
5723 server_tcp_in_port = 22
5724 server_tcp_out_port = 4022
5725 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005726 client_tcp_out_port = 1235
5727 server_nat_ip = "10.0.0.100"
5728 client_nat_ip = "10.0.0.110"
5729 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5730 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5731 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5732 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005733
Matus Fabianf8cd5812017-07-11 03:55:02 -07005734 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5735 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005736 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5737 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5738
5739 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005740 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005741 server_tcp_in_port,
5742 server_tcp_out_port,
5743 IP_PROTOS.tcp)
5744
Matus Fabianf8cd5812017-07-11 03:55:02 -07005745 self.vapi.nat64_add_del_static_bib(server.ip6n,
5746 server_nat_ip_n,
5747 0,
5748 0,
5749 IP_PROTOS.gre)
5750
5751 self.vapi.nat64_add_del_static_bib(client.ip6n,
5752 client_nat_ip_n,
5753 client_tcp_in_port,
5754 client_tcp_out_port,
5755 IP_PROTOS.tcp)
5756
Matus Fabian7968e6c2017-07-06 05:37:49 -07005757 # client to server
5758 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005759 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005760 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5761 self.pg0.add_stream(p)
5762 self.pg_enable_capture(self.pg_interfaces)
5763 self.pg_start()
5764 p = self.pg0.get_capture(1)
5765
5766 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005767 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005768 GRE() /
5769 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5770 TCP(sport=1234, dport=1234))
5771 self.pg0.add_stream(p)
5772 self.pg_enable_capture(self.pg_interfaces)
5773 self.pg_start()
5774 p = self.pg0.get_capture(1)
5775 packet = p[0]
5776 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005777 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005778 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005779 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005780 except:
5781 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5782 raise
5783
5784 # server to client
5785 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005786 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005787 GRE() /
5788 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5789 TCP(sport=1234, dport=1234))
5790 self.pg0.add_stream(p)
5791 self.pg_enable_capture(self.pg_interfaces)
5792 self.pg_start()
5793 p = self.pg0.get_capture(1)
5794 packet = p[0]
5795 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005796 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005797 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005798 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005799 except:
5800 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5801 raise
5802
Matus Fabian36ea2d62017-10-24 04:13:49 -07005803 def test_one_armed_nat64(self):
5804 """ One armed NAT64 """
5805 external_port = 0
5806 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5807 '64:ff9b::',
5808 96)
5809
5810 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5811 self.nat_addr_n)
5812 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5813 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5814
5815 # in2out
5816 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5817 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5818 TCP(sport=12345, dport=80))
5819 self.pg3.add_stream(p)
5820 self.pg_enable_capture(self.pg_interfaces)
5821 self.pg_start()
5822 capture = self.pg3.get_capture(1)
5823 p = capture[0]
5824 try:
5825 ip = p[IP]
5826 tcp = p[TCP]
5827 self.assertEqual(ip.src, self.nat_addr)
5828 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5829 self.assertNotEqual(tcp.sport, 12345)
5830 external_port = tcp.sport
5831 self.assertEqual(tcp.dport, 80)
5832 self.check_tcp_checksum(p)
5833 self.check_ip_checksum(p)
5834 except:
5835 self.logger.error(ppp("Unexpected or invalid packet:", p))
5836 raise
5837
5838 # out2in
5839 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5840 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5841 TCP(sport=80, dport=external_port))
5842 self.pg3.add_stream(p)
5843 self.pg_enable_capture(self.pg_interfaces)
5844 self.pg_start()
5845 capture = self.pg3.get_capture(1)
5846 p = capture[0]
5847 try:
5848 ip = p[IPv6]
5849 tcp = p[TCP]
5850 self.assertEqual(ip.src, remote_host_ip6)
5851 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5852 self.assertEqual(tcp.sport, 80)
5853 self.assertEqual(tcp.dport, 12345)
5854 self.check_tcp_checksum(p)
5855 except:
5856 self.logger.error(ppp("Unexpected or invalid packet:", p))
5857 raise
5858
Matus Fabianefcd1e92017-08-15 06:59:19 -07005859 def test_frag_in_order(self):
5860 """ NAT64 translate fragments arriving in order """
5861 self.tcp_port_in = random.randint(1025, 65535)
5862
5863 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5864 self.nat_addr_n)
5865 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5866 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5867
5868 reass = self.vapi.nat_reass_dump()
5869 reass_n_start = len(reass)
5870
5871 # in2out
5872 data = 'a' * 200
5873 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5874 self.tcp_port_in, 20, data)
5875 self.pg0.add_stream(pkts)
5876 self.pg_enable_capture(self.pg_interfaces)
5877 self.pg_start()
5878 frags = self.pg1.get_capture(len(pkts))
5879 p = self.reass_frags_and_verify(frags,
5880 self.nat_addr,
5881 self.pg1.remote_ip4)
5882 self.assertEqual(p[TCP].dport, 20)
5883 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5884 self.tcp_port_out = p[TCP].sport
5885 self.assertEqual(data, p[Raw].load)
5886
5887 # out2in
5888 data = "A" * 4 + "b" * 16 + "C" * 3
5889 pkts = self.create_stream_frag(self.pg1,
5890 self.nat_addr,
5891 20,
5892 self.tcp_port_out,
5893 data)
5894 self.pg1.add_stream(pkts)
5895 self.pg_enable_capture(self.pg_interfaces)
5896 self.pg_start()
5897 frags = self.pg0.get_capture(len(pkts))
5898 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5899 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5900 self.assertEqual(p[TCP].sport, 20)
5901 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5902 self.assertEqual(data, p[Raw].load)
5903
5904 reass = self.vapi.nat_reass_dump()
5905 reass_n_end = len(reass)
5906
5907 self.assertEqual(reass_n_end - reass_n_start, 2)
5908
5909 def test_reass_hairpinning(self):
5910 """ NAT64 fragments hairpinning """
5911 data = 'a' * 200
5912 client = self.pg0.remote_hosts[0]
5913 server = self.pg0.remote_hosts[1]
5914 server_in_port = random.randint(1025, 65535)
5915 server_out_port = random.randint(1025, 65535)
5916 client_in_port = random.randint(1025, 65535)
5917 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5918 nat_addr_ip6 = ip.src
5919
5920 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5921 self.nat_addr_n)
5922 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5923 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5924
5925 # add static BIB entry for server
5926 self.vapi.nat64_add_del_static_bib(server.ip6n,
5927 self.nat_addr_n,
5928 server_in_port,
5929 server_out_port,
5930 IP_PROTOS.tcp)
5931
5932 # send packet from host to server
5933 pkts = self.create_stream_frag_ip6(self.pg0,
5934 self.nat_addr,
5935 client_in_port,
5936 server_out_port,
5937 data)
5938 self.pg0.add_stream(pkts)
5939 self.pg_enable_capture(self.pg_interfaces)
5940 self.pg_start()
5941 frags = self.pg0.get_capture(len(pkts))
5942 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5943 self.assertNotEqual(p[TCP].sport, client_in_port)
5944 self.assertEqual(p[TCP].dport, server_in_port)
5945 self.assertEqual(data, p[Raw].load)
5946
5947 def test_frag_out_of_order(self):
5948 """ NAT64 translate fragments arriving out of order """
5949 self.tcp_port_in = random.randint(1025, 65535)
5950
5951 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5952 self.nat_addr_n)
5953 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5954 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5955
5956 # in2out
5957 data = 'a' * 200
5958 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5959 self.tcp_port_in, 20, data)
5960 pkts.reverse()
5961 self.pg0.add_stream(pkts)
5962 self.pg_enable_capture(self.pg_interfaces)
5963 self.pg_start()
5964 frags = self.pg1.get_capture(len(pkts))
5965 p = self.reass_frags_and_verify(frags,
5966 self.nat_addr,
5967 self.pg1.remote_ip4)
5968 self.assertEqual(p[TCP].dport, 20)
5969 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5970 self.tcp_port_out = p[TCP].sport
5971 self.assertEqual(data, p[Raw].load)
5972
5973 # out2in
5974 data = "A" * 4 + "B" * 16 + "C" * 3
5975 pkts = self.create_stream_frag(self.pg1,
5976 self.nat_addr,
5977 20,
5978 self.tcp_port_out,
5979 data)
5980 pkts.reverse()
5981 self.pg1.add_stream(pkts)
5982 self.pg_enable_capture(self.pg_interfaces)
5983 self.pg_start()
5984 frags = self.pg0.get_capture(len(pkts))
5985 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5986 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5987 self.assertEqual(p[TCP].sport, 20)
5988 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5989 self.assertEqual(data, p[Raw].load)
5990
Matus Fabian0938dcf2017-11-08 01:59:38 -08005991 def test_interface_addr(self):
5992 """ Acquire NAT64 pool addresses from interface """
5993 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5994
5995 # no address in NAT64 pool
5996 adresses = self.vapi.nat44_address_dump()
5997 self.assertEqual(0, len(adresses))
5998
5999 # configure interface address and check NAT64 address pool
6000 self.pg4.config_ip4()
6001 addresses = self.vapi.nat64_pool_addr_dump()
6002 self.assertEqual(len(addresses), 1)
6003 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6004
6005 # remove interface address and check NAT64 address pool
6006 self.pg4.unconfig_ip4()
6007 addresses = self.vapi.nat64_pool_addr_dump()
6008 self.assertEqual(0, len(adresses))
6009
Matus Fabiana431ad12018-01-04 04:03:14 -08006010 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6011 def test_ipfix_max_bibs_sessions(self):
6012 """ IPFIX logging maximum session and BIB entries exceeded """
6013 max_bibs = 1280
6014 max_sessions = 2560
6015 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6016 '64:ff9b::',
6017 96)
6018
6019 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6020 self.nat_addr_n)
6021 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6022 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6023
6024 pkts = []
6025 src = ""
6026 for i in range(0, max_bibs):
6027 src = "fd01:aa::%x" % (i)
6028 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6029 IPv6(src=src, dst=remote_host_ip6) /
6030 TCP(sport=12345, dport=80))
6031 pkts.append(p)
6032 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6033 IPv6(src=src, dst=remote_host_ip6) /
6034 TCP(sport=12345, dport=22))
6035 pkts.append(p)
6036 self.pg0.add_stream(pkts)
6037 self.pg_enable_capture(self.pg_interfaces)
6038 self.pg_start()
6039 self.pg1.get_capture(max_sessions)
6040
6041 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6042 src_address=self.pg3.local_ip4n,
6043 path_mtu=512,
6044 template_interval=10)
6045 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6046 src_port=self.ipfix_src_port)
6047
6048 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6049 IPv6(src=src, dst=remote_host_ip6) /
6050 TCP(sport=12345, dport=25))
6051 self.pg0.add_stream(p)
6052 self.pg_enable_capture(self.pg_interfaces)
6053 self.pg_start()
6054 self.pg1.get_capture(0)
6055 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6056 capture = self.pg3.get_capture(9)
6057 ipfix = IPFIXDecoder()
6058 # first load template
6059 for p in capture:
6060 self.assertTrue(p.haslayer(IPFIX))
6061 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6062 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6063 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6064 self.assertEqual(p[UDP].dport, 4739)
6065 self.assertEqual(p[IPFIX].observationDomainID,
6066 self.ipfix_domain_id)
6067 if p.haslayer(Template):
6068 ipfix.add_template(p.getlayer(Template))
6069 # verify events in data set
6070 for p in capture:
6071 if p.haslayer(Data):
6072 data = ipfix.decode_data_set(p.getlayer(Set))
6073 self.verify_ipfix_max_sessions(data, max_sessions)
6074
6075 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6076 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6077 TCP(sport=12345, dport=80))
6078 self.pg0.add_stream(p)
6079 self.pg_enable_capture(self.pg_interfaces)
6080 self.pg_start()
6081 self.pg1.get_capture(0)
6082 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6083 capture = self.pg3.get_capture(1)
6084 # verify events in data set
6085 for p in capture:
6086 self.assertTrue(p.haslayer(IPFIX))
6087 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6088 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6089 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6090 self.assertEqual(p[UDP].dport, 4739)
6091 self.assertEqual(p[IPFIX].observationDomainID,
6092 self.ipfix_domain_id)
6093 if p.haslayer(Data):
6094 data = ipfix.decode_data_set(p.getlayer(Set))
6095 self.verify_ipfix_max_bibs(data, max_bibs)
6096
6097 def test_ipfix_max_frags(self):
6098 """ IPFIX logging maximum fragments pending reassembly exceeded """
6099 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6100 self.nat_addr_n)
6101 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6102 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6103 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6104 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6105 src_address=self.pg3.local_ip4n,
6106 path_mtu=512,
6107 template_interval=10)
6108 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6109 src_port=self.ipfix_src_port)
6110
6111 data = 'a' * 200
6112 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6113 self.tcp_port_in, 20, data)
6114 self.pg0.add_stream(pkts[-1])
6115 self.pg_enable_capture(self.pg_interfaces)
6116 self.pg_start()
6117 self.pg1.get_capture(0)
6118 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6119 capture = self.pg3.get_capture(9)
6120 ipfix = IPFIXDecoder()
6121 # first load template
6122 for p in capture:
6123 self.assertTrue(p.haslayer(IPFIX))
6124 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6125 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6126 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6127 self.assertEqual(p[UDP].dport, 4739)
6128 self.assertEqual(p[IPFIX].observationDomainID,
6129 self.ipfix_domain_id)
6130 if p.haslayer(Template):
6131 ipfix.add_template(p.getlayer(Template))
6132 # verify events in data set
6133 for p in capture:
6134 if p.haslayer(Data):
6135 data = ipfix.decode_data_set(p.getlayer(Set))
6136 self.verify_ipfix_max_fragments_ip6(data, 0,
6137 self.pg0.remote_ip6n)
6138
6139 def test_ipfix_bib_ses(self):
6140 """ IPFIX logging NAT64 BIB/session create and delete events """
6141 self.tcp_port_in = random.randint(1025, 65535)
6142 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6143 '64:ff9b::',
6144 96)
6145
6146 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6147 self.nat_addr_n)
6148 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6149 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6150 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6151 src_address=self.pg3.local_ip4n,
6152 path_mtu=512,
6153 template_interval=10)
6154 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6155 src_port=self.ipfix_src_port)
6156
6157 # Create
6158 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6159 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6160 TCP(sport=self.tcp_port_in, dport=25))
6161 self.pg0.add_stream(p)
6162 self.pg_enable_capture(self.pg_interfaces)
6163 self.pg_start()
6164 p = self.pg1.get_capture(1)
6165 self.tcp_port_out = p[0][TCP].sport
6166 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6167 capture = self.pg3.get_capture(10)
6168 ipfix = IPFIXDecoder()
6169 # first load template
6170 for p in capture:
6171 self.assertTrue(p.haslayer(IPFIX))
6172 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6173 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6174 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6175 self.assertEqual(p[UDP].dport, 4739)
6176 self.assertEqual(p[IPFIX].observationDomainID,
6177 self.ipfix_domain_id)
6178 if p.haslayer(Template):
6179 ipfix.add_template(p.getlayer(Template))
6180 # verify events in data set
6181 for p in capture:
6182 if p.haslayer(Data):
6183 data = ipfix.decode_data_set(p.getlayer(Set))
6184 if ord(data[0][230]) == 10:
6185 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6186 elif ord(data[0][230]) == 6:
6187 self.verify_ipfix_nat64_ses(data,
6188 1,
6189 self.pg0.remote_ip6n,
6190 self.pg1.remote_ip4,
6191 25)
6192 else:
6193 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6194
6195 # Delete
6196 self.pg_enable_capture(self.pg_interfaces)
6197 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6198 self.nat_addr_n,
6199 is_add=0)
6200 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6201 capture = self.pg3.get_capture(2)
6202 # verify events in data set
6203 for p in capture:
6204 self.assertTrue(p.haslayer(IPFIX))
6205 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6206 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6207 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6208 self.assertEqual(p[UDP].dport, 4739)
6209 self.assertEqual(p[IPFIX].observationDomainID,
6210 self.ipfix_domain_id)
6211 if p.haslayer(Data):
6212 data = ipfix.decode_data_set(p.getlayer(Set))
6213 if ord(data[0][230]) == 11:
6214 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6215 elif ord(data[0][230]) == 7:
6216 self.verify_ipfix_nat64_ses(data,
6217 0,
6218 self.pg0.remote_ip6n,
6219 self.pg1.remote_ip4,
6220 25)
6221 else:
6222 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6223
Matus Fabian06596c52017-06-06 04:53:28 -07006224 def nat64_get_ses_num(self):
6225 """
6226 Return number of active NAT64 sessions.
6227 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006228 st = self.vapi.nat64_st_dump()
6229 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006230
6231 def clear_nat64(self):
6232 """
6233 Clear NAT64 configuration.
6234 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006235 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6236 domain_id=self.ipfix_domain_id)
6237 self.ipfix_src_port = 4739
6238 self.ipfix_domain_id = 1
6239
Matus Fabian06596c52017-06-06 04:53:28 -07006240 self.vapi.nat64_set_timeouts()
6241
6242 interfaces = self.vapi.nat64_interface_dump()
6243 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006244 if intf.is_inside > 1:
6245 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6246 0,
6247 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006248 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6249 intf.is_inside,
6250 is_add=0)
6251
Matus Fabiana431ad12018-01-04 04:03:14 -08006252 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006253 for bibe in bib:
6254 if bibe.is_static:
6255 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6256 bibe.o_addr,
6257 bibe.i_port,
6258 bibe.o_port,
6259 bibe.proto,
6260 bibe.vrf_id,
6261 is_add=0)
6262
6263 adresses = self.vapi.nat64_pool_addr_dump()
6264 for addr in adresses:
6265 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6266 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006267 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006268 is_add=0)
6269
Matus Fabian428dc912017-06-21 06:15:18 -07006270 prefixes = self.vapi.nat64_prefix_dump()
6271 for prefix in prefixes:
6272 self.vapi.nat64_add_del_prefix(prefix.prefix,
6273 prefix.prefix_len,
6274 vrf_id=prefix.vrf_id,
6275 is_add=0)
6276
Matus Fabian06596c52017-06-06 04:53:28 -07006277 def tearDown(self):
6278 super(TestNAT64, self).tearDown()
6279 if not self.vpp_dead:
6280 self.logger.info(self.vapi.cli("show nat64 pool"))
6281 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006282 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006283 self.logger.info(self.vapi.cli("show nat64 bib all"))
6284 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006285 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006286 self.clear_nat64()
6287
Matus Fabian8ebe6252017-11-06 05:04:53 -08006288
6289class TestDSlite(MethodHolder):
6290 """ DS-Lite Test Cases """
6291
6292 @classmethod
6293 def setUpClass(cls):
6294 super(TestDSlite, cls).setUpClass()
6295
6296 try:
6297 cls.nat_addr = '10.0.0.3'
6298 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6299
6300 cls.create_pg_interfaces(range(2))
6301 cls.pg0.admin_up()
6302 cls.pg0.config_ip4()
6303 cls.pg0.resolve_arp()
6304 cls.pg1.admin_up()
6305 cls.pg1.config_ip6()
6306 cls.pg1.generate_remote_hosts(2)
6307 cls.pg1.configure_ipv6_neighbors()
6308
6309 except Exception:
6310 super(TestDSlite, cls).tearDownClass()
6311 raise
6312
6313 def test_dslite(self):
6314 """ Test DS-Lite """
6315 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6316 self.nat_addr_n)
6317 aftr_ip4 = '192.0.0.1'
6318 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6319 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6320 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6321 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6322
6323 # UDP
6324 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6325 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6326 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6327 UDP(sport=20000, dport=10000))
6328 self.pg1.add_stream(p)
6329 self.pg_enable_capture(self.pg_interfaces)
6330 self.pg_start()
6331 capture = self.pg0.get_capture(1)
6332 capture = capture[0]
6333 self.assertFalse(capture.haslayer(IPv6))
6334 self.assertEqual(capture[IP].src, self.nat_addr)
6335 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6336 self.assertNotEqual(capture[UDP].sport, 20000)
6337 self.assertEqual(capture[UDP].dport, 10000)
6338 self.check_ip_checksum(capture)
6339 out_port = capture[UDP].sport
6340
6341 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6342 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6343 UDP(sport=10000, dport=out_port))
6344 self.pg0.add_stream(p)
6345 self.pg_enable_capture(self.pg_interfaces)
6346 self.pg_start()
6347 capture = self.pg1.get_capture(1)
6348 capture = capture[0]
6349 self.assertEqual(capture[IPv6].src, aftr_ip6)
6350 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6351 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6352 self.assertEqual(capture[IP].dst, '192.168.1.1')
6353 self.assertEqual(capture[UDP].sport, 10000)
6354 self.assertEqual(capture[UDP].dport, 20000)
6355 self.check_ip_checksum(capture)
6356
6357 # TCP
6358 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6359 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6360 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6361 TCP(sport=20001, dport=10001))
6362 self.pg1.add_stream(p)
6363 self.pg_enable_capture(self.pg_interfaces)
6364 self.pg_start()
6365 capture = self.pg0.get_capture(1)
6366 capture = capture[0]
6367 self.assertFalse(capture.haslayer(IPv6))
6368 self.assertEqual(capture[IP].src, self.nat_addr)
6369 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6370 self.assertNotEqual(capture[TCP].sport, 20001)
6371 self.assertEqual(capture[TCP].dport, 10001)
6372 self.check_ip_checksum(capture)
6373 self.check_tcp_checksum(capture)
6374 out_port = capture[TCP].sport
6375
6376 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6377 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6378 TCP(sport=10001, dport=out_port))
6379 self.pg0.add_stream(p)
6380 self.pg_enable_capture(self.pg_interfaces)
6381 self.pg_start()
6382 capture = self.pg1.get_capture(1)
6383 capture = capture[0]
6384 self.assertEqual(capture[IPv6].src, aftr_ip6)
6385 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6386 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6387 self.assertEqual(capture[IP].dst, '192.168.1.1')
6388 self.assertEqual(capture[TCP].sport, 10001)
6389 self.assertEqual(capture[TCP].dport, 20001)
6390 self.check_ip_checksum(capture)
6391 self.check_tcp_checksum(capture)
6392
6393 # ICMP
6394 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6395 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6396 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6397 ICMP(id=4000, type='echo-request'))
6398 self.pg1.add_stream(p)
6399 self.pg_enable_capture(self.pg_interfaces)
6400 self.pg_start()
6401 capture = self.pg0.get_capture(1)
6402 capture = capture[0]
6403 self.assertFalse(capture.haslayer(IPv6))
6404 self.assertEqual(capture[IP].src, self.nat_addr)
6405 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6406 self.assertNotEqual(capture[ICMP].id, 4000)
6407 self.check_ip_checksum(capture)
6408 self.check_icmp_checksum(capture)
6409 out_id = capture[ICMP].id
6410
6411 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6412 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6413 ICMP(id=out_id, type='echo-reply'))
6414 self.pg0.add_stream(p)
6415 self.pg_enable_capture(self.pg_interfaces)
6416 self.pg_start()
6417 capture = self.pg1.get_capture(1)
6418 capture = capture[0]
6419 self.assertEqual(capture[IPv6].src, aftr_ip6)
6420 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6421 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6422 self.assertEqual(capture[IP].dst, '192.168.1.1')
6423 self.assertEqual(capture[ICMP].id, 4000)
6424 self.check_ip_checksum(capture)
6425 self.check_icmp_checksum(capture)
6426
Matus Fabian331acc62017-12-08 03:38:51 -08006427 # ping DS-Lite AFTR tunnel endpoint address
6428 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6429 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6430 ICMPv6EchoRequest())
6431 self.pg1.add_stream(p)
6432 self.pg_enable_capture(self.pg_interfaces)
6433 self.pg_start()
6434 capture = self.pg1.get_capture(1)
6435 self.assertEqual(1, len(capture))
6436 capture = capture[0]
6437 self.assertEqual(capture[IPv6].src, aftr_ip6)
6438 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6439 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6440
Matus Fabian8ebe6252017-11-06 05:04:53 -08006441 def tearDown(self):
6442 super(TestDSlite, self).tearDown()
6443 if not self.vpp_dead:
6444 self.logger.info(self.vapi.cli("show dslite pool"))
6445 self.logger.info(
6446 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6447 self.logger.info(self.vapi.cli("show dslite sessions"))
6448
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006449
6450class TestDSliteCE(MethodHolder):
6451 """ DS-Lite CE Test Cases """
6452
6453 @classmethod
6454 def setUpConstants(cls):
6455 super(TestDSliteCE, cls).setUpConstants()
6456 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6457
6458 @classmethod
6459 def setUpClass(cls):
6460 super(TestDSliteCE, cls).setUpClass()
6461
6462 try:
6463 cls.create_pg_interfaces(range(2))
6464 cls.pg0.admin_up()
6465 cls.pg0.config_ip4()
6466 cls.pg0.resolve_arp()
6467 cls.pg1.admin_up()
6468 cls.pg1.config_ip6()
6469 cls.pg1.generate_remote_hosts(1)
6470 cls.pg1.configure_ipv6_neighbors()
6471
6472 except Exception:
6473 super(TestDSliteCE, cls).tearDownClass()
6474 raise
6475
6476 def test_dslite_ce(self):
6477 """ Test DS-Lite CE """
6478
6479 b4_ip4 = '192.0.0.2'
6480 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6481 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6482 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6483 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6484
6485 aftr_ip4 = '192.0.0.1'
6486 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6487 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6488 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6489 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6490
6491 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6492 dst_address_length=128,
6493 next_hop_address=self.pg1.remote_ip6n,
6494 next_hop_sw_if_index=self.pg1.sw_if_index,
6495 is_ipv6=1)
6496
6497 # UDP encapsulation
6498 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6499 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6500 UDP(sport=10000, dport=20000))
6501 self.pg0.add_stream(p)
6502 self.pg_enable_capture(self.pg_interfaces)
6503 self.pg_start()
6504 capture = self.pg1.get_capture(1)
6505 capture = capture[0]
6506 self.assertEqual(capture[IPv6].src, b4_ip6)
6507 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6508 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6509 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6510 self.assertEqual(capture[UDP].sport, 10000)
6511 self.assertEqual(capture[UDP].dport, 20000)
6512 self.check_ip_checksum(capture)
6513
6514 # UDP decapsulation
6515 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6516 IPv6(dst=b4_ip6, src=aftr_ip6) /
6517 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6518 UDP(sport=20000, dport=10000))
6519 self.pg1.add_stream(p)
6520 self.pg_enable_capture(self.pg_interfaces)
6521 self.pg_start()
6522 capture = self.pg0.get_capture(1)
6523 capture = capture[0]
6524 self.assertFalse(capture.haslayer(IPv6))
6525 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6526 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6527 self.assertEqual(capture[UDP].sport, 20000)
6528 self.assertEqual(capture[UDP].dport, 10000)
6529 self.check_ip_checksum(capture)
6530
6531 # ping DS-Lite B4 tunnel endpoint address
6532 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6533 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6534 ICMPv6EchoRequest())
6535 self.pg1.add_stream(p)
6536 self.pg_enable_capture(self.pg_interfaces)
6537 self.pg_start()
6538 capture = self.pg1.get_capture(1)
6539 self.assertEqual(1, len(capture))
6540 capture = capture[0]
6541 self.assertEqual(capture[IPv6].src, b4_ip6)
6542 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6543 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6544
6545 def tearDown(self):
6546 super(TestDSliteCE, self).tearDown()
6547 if not self.vpp_dead:
6548 self.logger.info(
6549 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6550 self.logger.info(
6551 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6552
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006553
6554class TestNAT66(MethodHolder):
6555 """ NAT66 Test Cases """
6556
6557 @classmethod
6558 def setUpClass(cls):
6559 super(TestNAT66, cls).setUpClass()
6560
6561 try:
6562 cls.nat_addr = 'fd01:ff::2'
6563 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6564
6565 cls.create_pg_interfaces(range(2))
6566 cls.interfaces = list(cls.pg_interfaces)
6567
6568 for i in cls.interfaces:
6569 i.admin_up()
6570 i.config_ip6()
6571 i.configure_ipv6_neighbors()
6572
6573 except Exception:
6574 super(TestNAT66, cls).tearDownClass()
6575 raise
6576
6577 def test_static(self):
6578 """ 1:1 NAT66 test """
6579 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6580 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6581 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6582 self.nat_addr_n)
6583
6584 # in2out
6585 pkts = []
6586 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6587 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6588 TCP())
6589 pkts.append(p)
6590 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6591 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6592 UDP())
6593 pkts.append(p)
6594 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6595 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6596 ICMPv6EchoRequest())
6597 pkts.append(p)
6598 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6599 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6600 GRE() / IP() / TCP())
6601 pkts.append(p)
6602 self.pg0.add_stream(pkts)
6603 self.pg_enable_capture(self.pg_interfaces)
6604 self.pg_start()
6605 capture = self.pg1.get_capture(len(pkts))
6606 for packet in capture:
6607 try:
6608 self.assertEqual(packet[IPv6].src, self.nat_addr)
6609 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6610 if packet.haslayer(TCP):
6611 self.check_tcp_checksum(packet)
6612 elif packet.haslayer(UDP):
6613 self.check_udp_checksum(packet)
6614 elif packet.haslayer(ICMPv6EchoRequest):
6615 self.check_icmpv6_checksum(packet)
6616 except:
6617 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6618 raise
6619
6620 # out2in
6621 pkts = []
6622 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6623 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6624 TCP())
6625 pkts.append(p)
6626 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6627 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6628 UDP())
6629 pkts.append(p)
6630 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6631 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6632 ICMPv6EchoReply())
6633 pkts.append(p)
6634 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6635 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6636 GRE() / IP() / TCP())
6637 pkts.append(p)
6638 self.pg1.add_stream(pkts)
6639 self.pg_enable_capture(self.pg_interfaces)
6640 self.pg_start()
6641 capture = self.pg0.get_capture(len(pkts))
6642 for packet in capture:
6643 try:
6644 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6645 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6646 if packet.haslayer(TCP):
6647 self.check_tcp_checksum(packet)
6648 elif packet.haslayer(UDP):
6649 self.check_udp_checksum(packet)
6650 elif packet.haslayer(ICMPv6EchoReply):
6651 self.check_icmpv6_checksum(packet)
6652 except:
6653 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6654 raise
6655
6656 sm = self.vapi.nat66_static_mapping_dump()
6657 self.assertEqual(len(sm), 1)
6658 self.assertEqual(sm[0].total_pkts, 8)
6659
Juraj Sloboda9341e342018-04-13 12:00:46 +02006660 def test_check_no_translate(self):
6661 """ NAT66 translate only when egress interface is outside interface """
6662 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6663 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6664 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6665 self.nat_addr_n)
6666
6667 # in2out
6668 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6669 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6670 UDP())
6671 self.pg0.add_stream([p])
6672 self.pg_enable_capture(self.pg_interfaces)
6673 self.pg_start()
6674 capture = self.pg1.get_capture(1)
6675 packet = capture[0]
6676 try:
6677 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6678 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6679 except:
6680 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6681 raise
6682
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006683 def clear_nat66(self):
6684 """
6685 Clear NAT66 configuration.
6686 """
6687 interfaces = self.vapi.nat66_interface_dump()
6688 for intf in interfaces:
6689 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6690 intf.is_inside,
6691 is_add=0)
6692
6693 static_mappings = self.vapi.nat66_static_mapping_dump()
6694 for sm in static_mappings:
6695 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6696 sm.external_ip_address,
6697 sm.vrf_id,
6698 is_add=0)
6699
6700 def tearDown(self):
6701 super(TestNAT66, self).tearDown()
6702 if not self.vpp_dead:
6703 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6704 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6705 self.clear_nat66()
6706
Matus Fabiande886752016-12-07 03:38:19 -08006707if __name__ == '__main__':
6708 unittest.main(testRunner=VppTestRunner)