blob: 7c1261990725210160ff7be61f8bd46fe367b2d8 [file] [log] [blame]
Matus Fabiande886752016-12-07 03:38:19 -08001#!/usr/bin/env python
2
3import socket
4import unittest
Matus Fabianeea28d72017-01-13 04:15:54 -08005import struct
Matus Fabianefcd1e92017-08-15 06:59:19 -07006import StringIO
7import random
Matus Fabiande886752016-12-07 03:38:19 -08008
Martin Gálik977c1cb2017-03-30 23:21:51 -07009from framework import VppTestCase, VppTestRunner, running_extended_tests
Matus Fabian8ebe6252017-11-06 05:04:53 -080010from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
Matus Fabiande886752016-12-07 03:38:19 -080011from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080012from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Matus Fabian06596c52017-06-06 04:53:28 -070013from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
Matus Fabianefcd1e92017-08-15 06:59:19 -070014from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070015from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080016from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070017from scapy.packet import bind_layers, Raw
18from scapy.all import fragment6
Klement Sekera9225dee2016-12-12 08:36:58 +010019from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080020from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070021from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070022from util import ip4_range
Ole Troan895b6e82017-10-20 13:28:20 +020023from util import mactobinary
Matus Fabiande886752016-12-07 03:38:19 -080024
25
Martin Gálikd7f75cd2017-03-27 06:02:47 -070026class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070027 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080028
29 @classmethod
30 def setUpClass(cls):
Martin Gálikd7f75cd2017-03-27 06:02:47 -070031 super(MethodHolder, cls).setUpClass()
Matus Fabiande886752016-12-07 03:38:19 -080032
Martin Gálikd7f75cd2017-03-27 06:02:47 -070033 def tearDown(self):
34 super(MethodHolder, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -080035
Matus Fabian029f3d22017-06-15 02:28:50 -070036 def check_ip_checksum(self, pkt):
37 """
38 Check IP checksum of the packet
39
40 :param pkt: Packet to check IP checksum
41 """
42 new = pkt.__class__(str(pkt))
43 del new['IP'].chksum
44 new = new.__class__(str(new))
45 self.assertEqual(new['IP'].chksum, pkt['IP'].chksum)
46
Matus Fabian4b30ceb2017-06-09 02:33:30 -070047 def check_tcp_checksum(self, pkt):
48 """
49 Check TCP checksum in IP packet
50
51 :param pkt: Packet to check TCP checksum
52 """
53 new = pkt.__class__(str(pkt))
54 del new['TCP'].chksum
55 new = new.__class__(str(new))
56 self.assertEqual(new['TCP'].chksum, pkt['TCP'].chksum)
57
Matus Fabian029f3d22017-06-15 02:28:50 -070058 def check_udp_checksum(self, pkt):
59 """
60 Check UDP checksum in IP packet
61
62 :param pkt: Packet to check UDP checksum
63 """
64 new = pkt.__class__(str(pkt))
65 del new['UDP'].chksum
66 new = new.__class__(str(new))
67 self.assertEqual(new['UDP'].chksum, pkt['UDP'].chksum)
68
69 def check_icmp_errror_embedded(self, pkt):
70 """
71 Check ICMP error embeded packet checksum
72
73 :param pkt: Packet to check ICMP error embeded packet checksum
74 """
75 if pkt.haslayer(IPerror):
76 new = pkt.__class__(str(pkt))
77 del new['IPerror'].chksum
78 new = new.__class__(str(new))
79 self.assertEqual(new['IPerror'].chksum, pkt['IPerror'].chksum)
80
81 if pkt.haslayer(TCPerror):
82 new = pkt.__class__(str(pkt))
83 del new['TCPerror'].chksum
84 new = new.__class__(str(new))
85 self.assertEqual(new['TCPerror'].chksum, pkt['TCPerror'].chksum)
86
87 if pkt.haslayer(UDPerror):
88 if pkt['UDPerror'].chksum != 0:
89 new = pkt.__class__(str(pkt))
90 del new['UDPerror'].chksum
91 new = new.__class__(str(new))
92 self.assertEqual(new['UDPerror'].chksum,
93 pkt['UDPerror'].chksum)
94
95 if pkt.haslayer(ICMPerror):
96 del new['ICMPerror'].chksum
97 new = new.__class__(str(new))
98 self.assertEqual(new['ICMPerror'].chksum, pkt['ICMPerror'].chksum)
99
100 def check_icmp_checksum(self, pkt):
101 """
102 Check ICMP checksum in IPv4 packet
103
104 :param pkt: Packet to check ICMP checksum
105 """
106 new = pkt.__class__(str(pkt))
107 del new['ICMP'].chksum
108 new = new.__class__(str(new))
109 self.assertEqual(new['ICMP'].chksum, pkt['ICMP'].chksum)
110 if pkt.haslayer(IPerror):
111 self.check_icmp_errror_embedded(pkt)
112
113 def check_icmpv6_checksum(self, pkt):
114 """
115 Check ICMPv6 checksum in IPv4 packet
116
117 :param pkt: Packet to check ICMPv6 checksum
118 """
119 new = pkt.__class__(str(pkt))
120 if pkt.haslayer(ICMPv6DestUnreach):
121 del new['ICMPv6DestUnreach'].cksum
122 new = new.__class__(str(new))
123 self.assertEqual(new['ICMPv6DestUnreach'].cksum,
124 pkt['ICMPv6DestUnreach'].cksum)
125 self.check_icmp_errror_embedded(pkt)
126 if pkt.haslayer(ICMPv6EchoRequest):
127 del new['ICMPv6EchoRequest'].cksum
128 new = new.__class__(str(new))
129 self.assertEqual(new['ICMPv6EchoRequest'].cksum,
130 pkt['ICMPv6EchoRequest'].cksum)
131 if pkt.haslayer(ICMPv6EchoReply):
132 del new['ICMPv6EchoReply'].cksum
133 new = new.__class__(str(new))
134 self.assertEqual(new['ICMPv6EchoReply'].cksum,
135 pkt['ICMPv6EchoReply'].cksum)
136
Juraj Slobodacba69362017-12-19 02:09:32 +0100137 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800138 """
139 Create packet stream for inside network
140
141 :param in_if: Inside interface
142 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100143 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800144 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800145 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100146 if dst_ip is None:
147 dst_ip = out_if.remote_ip4
148
Matus Fabiande886752016-12-07 03:38:19 -0800149 pkts = []
150 # TCP
151 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100152 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700153 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800154 pkts.append(p)
155
156 # UDP
157 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100158 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700159 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800160 pkts.append(p)
161
162 # ICMP
163 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100164 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800165 ICMP(id=self.icmp_id_in, type='echo-request'))
166 pkts.append(p)
167
168 return pkts
169
Matus Fabian428dc912017-06-21 06:15:18 -0700170 def compose_ip6(self, ip4, pref, plen):
171 """
172 Compose IPv4-embedded IPv6 addresses
173
174 :param ip4: IPv4 address
175 :param pref: IPv6 prefix
176 :param plen: IPv6 prefix length
177 :returns: IPv4-embedded IPv6 addresses
178 """
179 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
180 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
181 if plen == 32:
182 pref_n[4] = ip4_n[0]
183 pref_n[5] = ip4_n[1]
184 pref_n[6] = ip4_n[2]
185 pref_n[7] = ip4_n[3]
186 elif plen == 40:
187 pref_n[5] = ip4_n[0]
188 pref_n[6] = ip4_n[1]
189 pref_n[7] = ip4_n[2]
190 pref_n[9] = ip4_n[3]
191 elif plen == 48:
192 pref_n[6] = ip4_n[0]
193 pref_n[7] = ip4_n[1]
194 pref_n[9] = ip4_n[2]
195 pref_n[10] = ip4_n[3]
196 elif plen == 56:
197 pref_n[7] = ip4_n[0]
198 pref_n[9] = ip4_n[1]
199 pref_n[10] = ip4_n[2]
200 pref_n[11] = ip4_n[3]
201 elif plen == 64:
202 pref_n[9] = ip4_n[0]
203 pref_n[10] = ip4_n[1]
204 pref_n[11] = ip4_n[2]
205 pref_n[12] = ip4_n[3]
206 elif plen == 96:
207 pref_n[12] = ip4_n[0]
208 pref_n[13] = ip4_n[1]
209 pref_n[14] = ip4_n[2]
210 pref_n[15] = ip4_n[3]
211 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
212
Juraj Slobodacba69362017-12-19 02:09:32 +0100213 def extract_ip4(self, ip6, plen):
214 """
215 Extract IPv4 address embedded in IPv6 addresses
216
217 :param ip6: IPv6 address
218 :param plen: IPv6 prefix length
219 :returns: extracted IPv4 address
220 """
221 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
222 ip4_n = [None] * 4
223 if plen == 32:
224 ip4_n[0] = ip6_n[4]
225 ip4_n[1] = ip6_n[5]
226 ip4_n[2] = ip6_n[6]
227 ip4_n[3] = ip6_n[7]
228 elif plen == 40:
229 ip4_n[0] = ip6_n[5]
230 ip4_n[1] = ip6_n[6]
231 ip4_n[2] = ip6_n[7]
232 ip4_n[3] = ip6_n[9]
233 elif plen == 48:
234 ip4_n[0] = ip6_n[6]
235 ip4_n[1] = ip6_n[7]
236 ip4_n[2] = ip6_n[9]
237 ip4_n[3] = ip6_n[10]
238 elif plen == 56:
239 ip4_n[0] = ip6_n[7]
240 ip4_n[1] = ip6_n[9]
241 ip4_n[2] = ip6_n[10]
242 ip4_n[3] = ip6_n[11]
243 elif plen == 64:
244 ip4_n[0] = ip6_n[9]
245 ip4_n[1] = ip6_n[10]
246 ip4_n[2] = ip6_n[11]
247 ip4_n[3] = ip6_n[12]
248 elif plen == 96:
249 ip4_n[0] = ip6_n[12]
250 ip4_n[1] = ip6_n[13]
251 ip4_n[2] = ip6_n[14]
252 ip4_n[3] = ip6_n[15]
253 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
254
Matus Fabian428dc912017-06-21 06:15:18 -0700255 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700256 """
257 Create IPv6 packet stream for inside network
258
259 :param in_if: Inside interface
260 :param out_if: Outside interface
261 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700262 :param pref: NAT64 prefix
263 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700264 """
265 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700266 if pref is None:
267 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
268 else:
269 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
270
Matus Fabian06596c52017-06-06 04:53:28 -0700271 # TCP
272 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
273 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
274 TCP(sport=self.tcp_port_in, dport=20))
275 pkts.append(p)
276
277 # UDP
278 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
279 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
280 UDP(sport=self.udp_port_in, dport=20))
281 pkts.append(p)
282
283 # ICMP
284 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
285 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
286 ICMPv6EchoRequest(id=self.icmp_id_in))
287 pkts.append(p)
288
289 return pkts
290
Juraj Sloboda7b929792017-11-23 13:20:48 +0100291 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
292 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800293 """
294 Create packet stream for outside network
295
296 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700297 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800298 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100299 :param use_inside_ports: Use inside NAT ports as destination ports
300 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800301 """
302 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700303 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100304 if not use_inside_ports:
305 tcp_port = self.tcp_port_out
306 udp_port = self.udp_port_out
307 icmp_id = self.icmp_id_out
308 else:
309 tcp_port = self.tcp_port_in
310 udp_port = self.udp_port_in
311 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800312 pkts = []
313 # TCP
314 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800315 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100316 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800317 pkts.append(p)
318
319 # UDP
320 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800321 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100322 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800323 pkts.append(p)
324
325 # ICMP
326 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800327 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100328 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800329 pkts.append(p)
330
331 return pkts
332
Juraj Slobodacba69362017-12-19 02:09:32 +0100333 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
334 """
335 Create packet stream for outside network
336
337 :param out_if: Outside interface
338 :param dst_ip: Destination IP address (Default use global NAT address)
339 :param hl: HL of generated packets
340 """
341 pkts = []
342 # TCP
343 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
344 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
345 TCP(dport=self.tcp_port_out, sport=20))
346 pkts.append(p)
347
348 # UDP
349 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
350 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
351 UDP(dport=self.udp_port_out, sport=20))
352 pkts.append(p)
353
354 # ICMP
355 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
356 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
357 ICMPv6EchoReply(id=self.icmp_id_out))
358 pkts.append(p)
359
360 return pkts
361
Matus Fabiande886752016-12-07 03:38:19 -0800362 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Juraj Slobodacba69362017-12-19 02:09:32 +0100363 packet_num=3, dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800364 """
365 Verify captured packets on outside network
366
367 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700368 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800369 :param same_port: Sorce port number is not translated (Default False)
370 :param packet_num: Expected number of packets (Default 3)
Matus Fabian06596c52017-06-06 04:53:28 -0700371 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100372 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800373 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100374 if is_ip6:
375 IP46 = IPv6
376 ICMP46 = ICMPv6EchoRequest
377 else:
378 IP46 = IP
379 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800380 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700381 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800382 self.assertEqual(packet_num, len(capture))
383 for packet in capture:
384 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100385 if not is_ip6:
386 self.check_ip_checksum(packet)
387 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700388 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100389 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800390 if packet.haslayer(TCP):
391 if same_port:
392 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
393 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100394 self.assertNotEqual(
395 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800396 self.tcp_port_out = packet[TCP].sport
Matus Fabian029f3d22017-06-15 02:28:50 -0700397 self.check_tcp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800398 elif packet.haslayer(UDP):
399 if same_port:
400 self.assertEqual(packet[UDP].sport, self.udp_port_in)
401 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100402 self.assertNotEqual(
403 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800404 self.udp_port_out = packet[UDP].sport
405 else:
406 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100407 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800408 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100409 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
410 self.icmp_id_out = packet[ICMP46].id
411 if is_ip6:
412 self.check_icmpv6_checksum(packet)
413 else:
414 self.check_icmp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800415 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100416 self.logger.error(ppp("Unexpected or invalid packet "
417 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800418 raise
419
Juraj Slobodacba69362017-12-19 02:09:32 +0100420 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
421 packet_num=3, dst_ip=None):
422 """
423 Verify captured packets on outside network
424
425 :param capture: Captured packets
426 :param nat_ip: Translated IP address
427 :param same_port: Sorce port number is not translated (Default False)
428 :param packet_num: Expected number of packets (Default 3)
429 :param dst_ip: Destination IP address (Default do not verify)
430 """
431 return self.verify_capture_out(capture, nat_ip, same_port, packet_num,
432 dst_ip, True)
433
Matus Fabiande886752016-12-07 03:38:19 -0800434 def verify_capture_in(self, capture, in_if, packet_num=3):
435 """
436 Verify captured packets on inside network
437
438 :param capture: Captured packets
439 :param in_if: Inside interface
440 :param packet_num: Expected number of packets (Default 3)
441 """
442 self.assertEqual(packet_num, len(capture))
443 for packet in capture:
444 try:
Matus Fabian029f3d22017-06-15 02:28:50 -0700445 self.check_ip_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800446 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
447 if packet.haslayer(TCP):
448 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700449 self.check_tcp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800450 elif packet.haslayer(UDP):
451 self.assertEqual(packet[UDP].dport, self.udp_port_in)
452 else:
453 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700454 self.check_icmp_checksum(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800455 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100456 self.logger.error(ppp("Unexpected or invalid packet "
457 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800458 raise
459
Matus Fabian06596c52017-06-06 04:53:28 -0700460 def verify_capture_in_ip6(self, capture, src_ip, dst_ip, packet_num=3):
461 """
462 Verify captured IPv6 packets on inside network
463
464 :param capture: Captured packets
465 :param src_ip: Source IP
466 :param dst_ip: Destination IP address
467 :param packet_num: Expected number of packets (Default 3)
468 """
469 self.assertEqual(packet_num, len(capture))
470 for packet in capture:
471 try:
472 self.assertEqual(packet[IPv6].src, src_ip)
473 self.assertEqual(packet[IPv6].dst, dst_ip)
474 if packet.haslayer(TCP):
475 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700476 self.check_tcp_checksum(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700477 elif packet.haslayer(UDP):
478 self.assertEqual(packet[UDP].dport, self.udp_port_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700479 self.check_udp_checksum(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700480 else:
481 self.assertEqual(packet[ICMPv6EchoReply].id,
482 self.icmp_id_in)
Matus Fabian029f3d22017-06-15 02:28:50 -0700483 self.check_icmpv6_checksum(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700484 except:
485 self.logger.error(ppp("Unexpected or invalid packet "
486 "(inside network):", packet))
487 raise
488
Matus Fabian675a69c2017-01-18 01:46:01 -0800489 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
490 """
491 Verify captured packet that don't have to be translated
492
493 :param capture: Captured packets
494 :param ingress_if: Ingress interface
495 :param egress_if: Egress interface
496 """
497 for packet in capture:
498 try:
499 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
500 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
501 if packet.haslayer(TCP):
502 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
503 elif packet.haslayer(UDP):
504 self.assertEqual(packet[UDP].sport, self.udp_port_in)
505 else:
506 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
507 except:
508 self.logger.error(ppp("Unexpected or invalid packet "
509 "(inside network):", packet))
510 raise
511
Juraj Slobodab33f4132017-02-08 23:54:21 -0800512 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
513 packet_num=3, icmp_type=11):
514 """
515 Verify captured packets with ICMP errors on outside network
516
517 :param capture: Captured packets
518 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700519 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800520 :param packet_num: Expected number of packets (Default 3)
521 :param icmp_type: Type of error ICMP packet
522 we are expecting (Default 11)
523 """
524 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700525 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800526 self.assertEqual(packet_num, len(capture))
527 for packet in capture:
528 try:
529 self.assertEqual(packet[IP].src, src_ip)
530 self.assertTrue(packet.haslayer(ICMP))
531 icmp = packet[ICMP]
532 self.assertEqual(icmp.type, icmp_type)
533 self.assertTrue(icmp.haslayer(IPerror))
534 inner_ip = icmp[IPerror]
535 if inner_ip.haslayer(TCPerror):
536 self.assertEqual(inner_ip[TCPerror].dport,
537 self.tcp_port_out)
538 elif inner_ip.haslayer(UDPerror):
539 self.assertEqual(inner_ip[UDPerror].dport,
540 self.udp_port_out)
541 else:
542 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
543 except:
544 self.logger.error(ppp("Unexpected or invalid packet "
545 "(outside network):", packet))
546 raise
547
548 def verify_capture_in_with_icmp_errors(self, capture, in_if, packet_num=3,
549 icmp_type=11):
550 """
551 Verify captured packets with ICMP errors on inside network
552
553 :param capture: Captured packets
554 :param in_if: Inside interface
555 :param packet_num: Expected number of packets (Default 3)
556 :param icmp_type: Type of error ICMP packet
557 we are expecting (Default 11)
558 """
559 self.assertEqual(packet_num, len(capture))
560 for packet in capture:
561 try:
562 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
563 self.assertTrue(packet.haslayer(ICMP))
564 icmp = packet[ICMP]
565 self.assertEqual(icmp.type, icmp_type)
566 self.assertTrue(icmp.haslayer(IPerror))
567 inner_ip = icmp[IPerror]
568 if inner_ip.haslayer(TCPerror):
569 self.assertEqual(inner_ip[TCPerror].sport,
570 self.tcp_port_in)
571 elif inner_ip.haslayer(UDPerror):
572 self.assertEqual(inner_ip[UDPerror].sport,
573 self.udp_port_in)
574 else:
575 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
576 except:
577 self.logger.error(ppp("Unexpected or invalid packet "
578 "(inside network):", packet))
579 raise
580
Matus Fabianefcd1e92017-08-15 06:59:19 -0700581 def create_stream_frag(self, src_if, dst, sport, dport, data):
582 """
583 Create fragmented packet stream
584
585 :param src_if: Source interface
586 :param dst: Destination IPv4 address
587 :param sport: Source TCP port
588 :param dport: Destination TCP port
589 :param data: Payload data
590 :returns: Fragmets
591 """
592 id = random.randint(0, 65535)
593 p = (IP(src=src_if.remote_ip4, dst=dst) /
594 TCP(sport=sport, dport=dport) /
595 Raw(data))
596 p = p.__class__(str(p))
597 chksum = p['TCP'].chksum
598 pkts = []
599 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
600 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
601 TCP(sport=sport, dport=dport, chksum=chksum) /
602 Raw(data[0:4]))
603 pkts.append(p)
604 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
605 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
606 proto=IP_PROTOS.tcp) /
607 Raw(data[4:20]))
608 pkts.append(p)
609 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
610 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
611 id=id) /
612 Raw(data[20:]))
613 pkts.append(p)
614 return pkts
615
616 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
617 pref=None, plen=0, frag_size=128):
618 """
619 Create fragmented packet stream
620
621 :param src_if: Source interface
622 :param dst: Destination IPv4 address
623 :param sport: Source TCP port
624 :param dport: Destination TCP port
625 :param data: Payload data
626 :param pref: NAT64 prefix
627 :param plen: NAT64 prefix length
628 :param fragsize: size of fragments
629 :returns: Fragmets
630 """
631 if pref is None:
632 dst_ip6 = ''.join(['64:ff9b::', dst])
633 else:
634 dst_ip6 = self.compose_ip6(dst, pref, plen)
635
636 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
637 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
638 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
639 TCP(sport=sport, dport=dport) /
640 Raw(data))
641
642 return fragment6(p, frag_size)
643
644 def reass_frags_and_verify(self, frags, src, dst):
645 """
646 Reassemble and verify fragmented packet
647
648 :param frags: Captured fragments
649 :param src: Source IPv4 address to verify
650 :param dst: Destination IPv4 address to verify
651
652 :returns: Reassembled IPv4 packet
653 """
654 buffer = StringIO.StringIO()
655 for p in frags:
656 self.assertEqual(p[IP].src, src)
657 self.assertEqual(p[IP].dst, dst)
658 self.check_ip_checksum(p)
659 buffer.seek(p[IP].frag * 8)
660 buffer.write(p[IP].payload)
661 ip = frags[0].getlayer(IP)
662 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
663 proto=frags[0][IP].proto)
664 if ip.proto == IP_PROTOS.tcp:
665 p = (ip / TCP(buffer.getvalue()))
666 self.check_tcp_checksum(p)
667 elif ip.proto == IP_PROTOS.udp:
668 p = (ip / UDP(buffer.getvalue()))
669 return p
670
671 def reass_frags_and_verify_ip6(self, frags, src, dst):
672 """
673 Reassemble and verify fragmented packet
674
675 :param frags: Captured fragments
676 :param src: Source IPv6 address to verify
677 :param dst: Destination IPv6 address to verify
678
679 :returns: Reassembled IPv6 packet
680 """
681 buffer = StringIO.StringIO()
682 for p in frags:
683 self.assertEqual(p[IPv6].src, src)
684 self.assertEqual(p[IPv6].dst, dst)
685 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
686 buffer.write(p[IPv6ExtHdrFragment].payload)
687 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
688 nh=frags[0][IPv6ExtHdrFragment].nh)
689 if ip.nh == IP_PROTOS.tcp:
690 p = (ip / TCP(buffer.getvalue()))
691 self.check_tcp_checksum(p)
692 elif ip.nh == IP_PROTOS.udp:
693 p = (ip / UDP(buffer.getvalue()))
694 return p
695
Matus Fabianeea28d72017-01-13 04:15:54 -0800696 def verify_ipfix_nat44_ses(self, data):
697 """
698 Verify IPFIX NAT44 session create/delete event
699
700 :param data: Decoded IPFIX data records
701 """
702 nat44_ses_create_num = 0
703 nat44_ses_delete_num = 0
704 self.assertEqual(6, len(data))
705 for record in data:
706 # natEvent
707 self.assertIn(ord(record[230]), [4, 5])
708 if ord(record[230]) == 4:
709 nat44_ses_create_num += 1
710 else:
711 nat44_ses_delete_num += 1
712 # sourceIPv4Address
713 self.assertEqual(self.pg0.remote_ip4n, record[8])
714 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700715 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800716 record[225])
717 # ingressVRFID
718 self.assertEqual(struct.pack("!I", 0), record[234])
719 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
720 if IP_PROTOS.icmp == ord(record[4]):
721 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
722 self.assertEqual(struct.pack("!H", self.icmp_id_out),
723 record[227])
724 elif IP_PROTOS.tcp == ord(record[4]):
725 self.assertEqual(struct.pack("!H", self.tcp_port_in),
726 record[7])
727 self.assertEqual(struct.pack("!H", self.tcp_port_out),
728 record[227])
729 elif IP_PROTOS.udp == ord(record[4]):
730 self.assertEqual(struct.pack("!H", self.udp_port_in),
731 record[7])
732 self.assertEqual(struct.pack("!H", self.udp_port_out),
733 record[227])
734 else:
735 self.fail("Invalid protocol")
736 self.assertEqual(3, nat44_ses_create_num)
737 self.assertEqual(3, nat44_ses_delete_num)
738
739 def verify_ipfix_addr_exhausted(self, data):
740 """
741 Verify IPFIX NAT addresses event
742
743 :param data: Decoded IPFIX data records
744 """
745 self.assertEqual(1, len(data))
746 record = data[0]
747 # natEvent
748 self.assertEqual(ord(record[230]), 3)
749 # natPoolID
750 self.assertEqual(struct.pack("!I", 0), record[283])
751
Matus Fabiana431ad12018-01-04 04:03:14 -0800752 def verify_ipfix_max_sessions(self, data, limit):
753 """
754 Verify IPFIX maximum session entries exceeded event
755
756 :param data: Decoded IPFIX data records
757 :param limit: Number of maximum session entries that can be created.
758 """
759 self.assertEqual(1, len(data))
760 record = data[0]
761 # natEvent
762 self.assertEqual(ord(record[230]), 13)
763 # natQuotaExceededEvent
764 self.assertEqual(struct.pack("I", 1), record[466])
765 # maxSessionEntries
766 self.assertEqual(struct.pack("I", limit), record[471])
767
768 def verify_ipfix_max_bibs(self, data, limit):
769 """
770 Verify IPFIX maximum BIB entries exceeded event
771
772 :param data: Decoded IPFIX data records
773 :param limit: Number of maximum BIB entries that can be created.
774 """
775 self.assertEqual(1, len(data))
776 record = data[0]
777 # natEvent
778 self.assertEqual(ord(record[230]), 13)
779 # natQuotaExceededEvent
780 self.assertEqual(struct.pack("I", 2), record[466])
781 # maxBIBEntries
782 self.assertEqual(struct.pack("I", limit), record[472])
783
784 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
785 """
786 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
787
788 :param data: Decoded IPFIX data records
789 :param limit: Number of maximum fragments pending reassembly
790 :param src_addr: IPv6 source address
791 """
792 self.assertEqual(1, len(data))
793 record = data[0]
794 # natEvent
795 self.assertEqual(ord(record[230]), 13)
796 # natQuotaExceededEvent
797 self.assertEqual(struct.pack("I", 5), record[466])
798 # maxFragmentsPendingReassembly
799 self.assertEqual(struct.pack("I", limit), record[475])
800 # sourceIPv6Address
801 self.assertEqual(src_addr, record[27])
802
803 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
804 """
805 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
806
807 :param data: Decoded IPFIX data records
808 :param limit: Number of maximum fragments pending reassembly
809 :param src_addr: IPv4 source address
810 """
811 self.assertEqual(1, len(data))
812 record = data[0]
813 # natEvent
814 self.assertEqual(ord(record[230]), 13)
815 # natQuotaExceededEvent
816 self.assertEqual(struct.pack("I", 5), record[466])
817 # maxFragmentsPendingReassembly
818 self.assertEqual(struct.pack("I", limit), record[475])
819 # sourceIPv4Address
820 self.assertEqual(src_addr, record[8])
821
822 def verify_ipfix_bib(self, data, is_create, src_addr):
823 """
824 Verify IPFIX NAT64 BIB create and delete events
825
826 :param data: Decoded IPFIX data records
827 :param is_create: Create event if nonzero value otherwise delete event
828 :param src_addr: IPv6 source address
829 """
830 self.assertEqual(1, len(data))
831 record = data[0]
832 # natEvent
833 if is_create:
834 self.assertEqual(ord(record[230]), 10)
835 else:
836 self.assertEqual(ord(record[230]), 11)
837 # sourceIPv6Address
838 self.assertEqual(src_addr, record[27])
839 # postNATSourceIPv4Address
840 self.assertEqual(self.nat_addr_n, record[225])
841 # protocolIdentifier
842 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
843 # ingressVRFID
844 self.assertEqual(struct.pack("!I", 0), record[234])
845 # sourceTransportPort
846 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
847 # postNAPTSourceTransportPort
848 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
849
850 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
851 dst_port):
852 """
853 Verify IPFIX NAT64 session create and delete events
854
855 :param data: Decoded IPFIX data records
856 :param is_create: Create event if nonzero value otherwise delete event
857 :param src_addr: IPv6 source address
858 :param dst_addr: IPv4 destination address
859 :param dst_port: destination TCP port
860 """
861 self.assertEqual(1, len(data))
862 record = data[0]
863 # natEvent
864 if is_create:
865 self.assertEqual(ord(record[230]), 6)
866 else:
867 self.assertEqual(ord(record[230]), 7)
868 # sourceIPv6Address
869 self.assertEqual(src_addr, record[27])
870 # destinationIPv6Address
871 self.assertEqual(socket.inet_pton(socket.AF_INET6,
872 self.compose_ip6(dst_addr,
873 '64:ff9b::',
874 96)),
875 record[28])
876 # postNATSourceIPv4Address
877 self.assertEqual(self.nat_addr_n, record[225])
878 # postNATDestinationIPv4Address
879 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
880 record[226])
881 # protocolIdentifier
882 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
883 # ingressVRFID
884 self.assertEqual(struct.pack("!I", 0), record[234])
885 # sourceTransportPort
886 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
887 # postNAPTSourceTransportPort
888 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
889 # destinationTransportPort
890 self.assertEqual(struct.pack("!H", dst_port), record[11])
891 # postNAPTDestinationTransportPort
892 self.assertEqual(struct.pack("!H", dst_port), record[228])
893
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700894
Matus Fabian2ba92e32017-08-21 07:05:03 -0700895class TestNAT44(MethodHolder):
896 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700897
898 @classmethod
899 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -0700900 super(TestNAT44, cls).setUpClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700901
902 try:
903 cls.tcp_port_in = 6303
904 cls.tcp_port_out = 6303
905 cls.udp_port_in = 6304
906 cls.udp_port_out = 6304
907 cls.icmp_id_in = 6305
908 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -0700909 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +0100910 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700911 cls.ipfix_src_port = 4739
912 cls.ipfix_domain_id = 1
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700913
Matus Fabian36ea2d62017-10-24 04:13:49 -0700914 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700915 cls.interfaces = list(cls.pg_interfaces[0:4])
916
917 for i in cls.interfaces:
918 i.admin_up()
919 i.config_ip4()
920 i.resolve_arp()
921
Matus Fabian6fa74c62017-06-05 05:55:48 -0700922 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700923 cls.pg0.configure_ipv4_neighbors()
924
925 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -0700926 cls.vapi.ip_table_add_del(10, is_add=1)
927 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700928
929 cls.pg4._local_ip4 = "172.16.255.1"
930 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
931 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
932 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -0700933 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700934 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -0700935 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700936 cls.pg5.set_table_ip4(10)
937 cls.pg6._local_ip4 = "172.16.255.1"
938 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
939 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
940 cls.pg6.set_table_ip4(20)
941 for i in cls.overlapping_interfaces:
942 i.config_ip4()
943 i.admin_up()
944 i.resolve_arp()
945
946 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -0700947 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700948
Matus Fabian36ea2d62017-10-24 04:13:49 -0700949 cls.pg9.generate_remote_hosts(2)
950 cls.pg9.config_ip4()
951 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
952 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
953 ip_addr_n,
954 24)
955 cls.pg9.admin_up()
956 cls.pg9.resolve_arp()
957 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
958 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
959 cls.pg9.resolve_arp()
960
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700961 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700962 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700963 raise
964
Matus Fabian2ba92e32017-08-21 07:05:03 -0700965 def clear_nat44(self):
Matus Fabiande886752016-12-07 03:38:19 -0800966 """
Matus Fabian2ba92e32017-08-21 07:05:03 -0700967 Clear NAT44 configuration.
Matus Fabiande886752016-12-07 03:38:19 -0800968 """
Martin Gálik406eb1d2017-05-04 04:35:04 -0700969 # I found no elegant way to do this
970 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
971 dst_address_length=32,
972 next_hop_address=self.pg7.remote_ip4n,
973 next_hop_sw_if_index=self.pg7.sw_if_index,
974 is_add=0)
975 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
976 dst_address_length=32,
977 next_hop_address=self.pg8.remote_ip4n,
978 next_hop_sw_if_index=self.pg8.sw_if_index,
979 is_add=0)
980
981 for intf in [self.pg7, self.pg8]:
982 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
983 for n in neighbors:
984 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
985 n.mac_address,
986 n.ip_address,
987 is_add=0)
988
Matus Fabian36532bd2017-01-23 23:42:28 -0800989 if self.pg7.has_ip4_config:
990 self.pg7.unconfig_ip4()
991
Matus Fabian240b5ef2018-01-11 04:09:17 -0800992 self.vapi.nat44_forwarding_enable_disable(0)
993
Matus Fabian2ba92e32017-08-21 07:05:03 -0700994 interfaces = self.vapi.nat44_interface_addr_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -0800995 for intf in interfaces:
Matus Fabianb932d262017-12-18 05:38:24 -0800996 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
997 twice_nat=intf.twice_nat,
998 is_add=0)
Matus Fabian8bf68e82017-01-12 04:24:35 -0800999
Matus Fabian2ba92e32017-08-21 07:05:03 -07001000 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
1001 domain_id=self.ipfix_domain_id)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001002 self.ipfix_src_port = 4739
1003 self.ipfix_domain_id = 1
Matus Fabianeea28d72017-01-13 04:15:54 -08001004
Matus Fabian2ba92e32017-08-21 07:05:03 -07001005 interfaces = self.vapi.nat44_interface_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001006 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07001007 if intf.is_inside > 1:
1008 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
1009 0,
1010 is_add=0)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001011 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
1012 intf.is_inside,
1013 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001014
Matus Fabian2ba92e32017-08-21 07:05:03 -07001015 interfaces = self.vapi.nat44_interface_output_feature_dump()
Matus Fabian93d84c92017-07-19 08:06:01 -07001016 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001017 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
1018 intf.is_inside,
1019 is_add=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07001020
Matus Fabian2ba92e32017-08-21 07:05:03 -07001021 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001022 for sm in static_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001023 self.vapi.nat44_add_del_static_mapping(
1024 sm.local_ip_address,
1025 sm.external_ip_address,
1026 local_port=sm.local_port,
1027 external_port=sm.external_port,
1028 addr_only=sm.addr_only,
1029 vrf_id=sm.vrf_id,
1030 protocol=sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001031 twice_nat=sm.twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001032 out2in_only=sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001033 tag=sm.tag,
Matus Fabianea2600a2018-03-28 04:06:26 -07001034 external_sw_if_index=sm.external_sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001035 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001036
Matus Fabian704018c2017-09-04 02:17:18 -07001037 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
1038 for lb_sm in lb_static_mappings:
1039 self.vapi.nat44_add_del_lb_static_mapping(
1040 lb_sm.external_addr,
1041 lb_sm.external_port,
1042 lb_sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001043 vrf_id=lb_sm.vrf_id,
1044 twice_nat=lb_sm.twice_nat,
Matus Fabian240b5ef2018-01-11 04:09:17 -08001045 out2in_only=lb_sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001046 tag=lb_sm.tag,
Ole Troan895b6e82017-10-20 13:28:20 +02001047 is_add=0,
1048 local_num=0,
1049 locals=[])
Matus Fabian704018c2017-09-04 02:17:18 -07001050
Matus Fabianab7a8052017-11-28 04:29:41 -08001051 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1052 for id_m in identity_mappings:
1053 self.vapi.nat44_add_del_identity_mapping(
1054 addr_only=id_m.addr_only,
1055 ip=id_m.ip_address,
1056 port=id_m.port,
1057 sw_if_index=id_m.sw_if_index,
1058 vrf_id=id_m.vrf_id,
1059 protocol=id_m.protocol,
1060 is_add=0)
1061
Matus Fabian2ba92e32017-08-21 07:05:03 -07001062 adresses = self.vapi.nat44_address_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001063 for addr in adresses:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001064 self.vapi.nat44_add_del_address_range(addr.ip_address,
1065 addr.ip_address,
Matus Fabianb932d262017-12-18 05:38:24 -08001066 twice_nat=addr.twice_nat,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001067 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001068
Matus Fabianefcd1e92017-08-15 06:59:19 -07001069 self.vapi.nat_set_reass()
1070 self.vapi.nat_set_reass(is_ip6=1)
1071
Matus Fabian2ba92e32017-08-21 07:05:03 -07001072 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1073 local_port=0, external_port=0, vrf_id=0,
1074 is_add=1, external_sw_if_index=0xFFFFFFFF,
Matus Fabian5f224992018-01-25 21:59:16 -08001075 proto=0, twice_nat=0, out2in_only=0, tag=""):
Matus Fabiande886752016-12-07 03:38:19 -08001076 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001077 Add/delete NAT44 static mapping
Matus Fabiande886752016-12-07 03:38:19 -08001078
1079 :param local_ip: Local IP address
1080 :param external_ip: External IP address
1081 :param local_port: Local port number (Optional)
1082 :param external_port: External port number (Optional)
1083 :param vrf_id: VRF ID (Default 0)
1084 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabian36532bd2017-01-23 23:42:28 -08001085 :param external_sw_if_index: External interface instead of IP address
Matus Fabian09d96f42017-02-02 01:43:00 -08001086 :param proto: IP protocol (Mandatory if port specified)
Matus Fabianb932d262017-12-18 05:38:24 -08001087 :param twice_nat: 1 if translate external host address and port
Matus Fabiane82488f2018-01-18 03:38:45 -08001088 :param out2in_only: if 1 rule is matching only out2in direction
Matus Fabian5f224992018-01-25 21:59:16 -08001089 :param tag: Opaque string tag
Matus Fabiande886752016-12-07 03:38:19 -08001090 """
1091 addr_only = 1
1092 if local_port and external_port:
1093 addr_only = 0
1094 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1095 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001096 self.vapi.nat44_add_del_static_mapping(
Klement Sekerada505f62017-01-04 12:58:53 +01001097 l_ip,
1098 e_ip,
Matus Fabian36532bd2017-01-23 23:42:28 -08001099 external_sw_if_index,
Klement Sekerada505f62017-01-04 12:58:53 +01001100 local_port,
1101 external_port,
1102 addr_only,
1103 vrf_id,
Matus Fabian09d96f42017-02-02 01:43:00 -08001104 proto,
Matus Fabianb932d262017-12-18 05:38:24 -08001105 twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001106 out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001107 tag,
Klement Sekerada505f62017-01-04 12:58:53 +01001108 is_add)
Matus Fabiande886752016-12-07 03:38:19 -08001109
Matus Fabianb932d262017-12-18 05:38:24 -08001110 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
Matus Fabiande886752016-12-07 03:38:19 -08001111 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001112 Add/delete NAT44 address
Matus Fabiande886752016-12-07 03:38:19 -08001113
1114 :param ip: IP address
1115 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabianb932d262017-12-18 05:38:24 -08001116 :param twice_nat: twice NAT address for extenal hosts
Matus Fabiande886752016-12-07 03:38:19 -08001117 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001118 nat_addr = socket.inet_pton(socket.AF_INET, ip)
1119 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
Matus Fabianb932d262017-12-18 05:38:24 -08001120 vrf_id=vrf_id,
1121 twice_nat=twice_nat)
Matus Fabiande886752016-12-07 03:38:19 -08001122
1123 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001124 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001125
Matus Fabian2ba92e32017-08-21 07:05:03 -07001126 self.nat44_add_address(self.nat_addr)
1127 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1128 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1129 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001130
1131 # in2out
1132 pkts = self.create_stream_in(self.pg0, self.pg1)
1133 self.pg0.add_stream(pkts)
1134 self.pg_enable_capture(self.pg_interfaces)
1135 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001136 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001137 self.verify_capture_out(capture)
1138
1139 # out2in
1140 pkts = self.create_stream_out(self.pg1)
1141 self.pg1.add_stream(pkts)
1142 self.pg_enable_capture(self.pg_interfaces)
1143 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001144 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001145 self.verify_capture_in(capture, self.pg0)
1146
Juraj Slobodab33f4132017-02-08 23:54:21 -08001147 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001148 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001149
Matus Fabian2ba92e32017-08-21 07:05:03 -07001150 self.nat44_add_address(self.nat_addr)
1151 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1152 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1153 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001154
1155 # Client side - generate traffic
1156 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1157 self.pg0.add_stream(pkts)
1158 self.pg_enable_capture(self.pg_interfaces)
1159 self.pg_start()
1160
1161 # Client side - verify ICMP type 11 packets
1162 capture = self.pg0.get_capture(len(pkts))
1163 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1164
1165 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001166 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001167
Matus Fabian2ba92e32017-08-21 07:05:03 -07001168 self.nat44_add_address(self.nat_addr)
1169 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1170 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1171 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001172
1173 # Client side - create sessions
1174 pkts = self.create_stream_in(self.pg0, self.pg1)
1175 self.pg0.add_stream(pkts)
1176 self.pg_enable_capture(self.pg_interfaces)
1177 self.pg_start()
1178
1179 # Server side - generate traffic
1180 capture = self.pg1.get_capture(len(pkts))
1181 self.verify_capture_out(capture)
1182 pkts = self.create_stream_out(self.pg1, ttl=1)
1183 self.pg1.add_stream(pkts)
1184 self.pg_enable_capture(self.pg_interfaces)
1185 self.pg_start()
1186
1187 # Server side - verify ICMP type 11 packets
1188 capture = self.pg1.get_capture(len(pkts))
1189 self.verify_capture_out_with_icmp_errors(capture,
1190 src_ip=self.pg1.local_ip4)
1191
1192 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001193 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001194
Matus Fabian2ba92e32017-08-21 07:05:03 -07001195 self.nat44_add_address(self.nat_addr)
1196 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1197 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1198 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001199
1200 # Client side - generate traffic
1201 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1202 self.pg0.add_stream(pkts)
1203 self.pg_enable_capture(self.pg_interfaces)
1204 self.pg_start()
1205
1206 # Server side - simulate ICMP type 11 response
1207 capture = self.pg1.get_capture(len(pkts))
1208 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001209 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001210 ICMP(type=11) / packet[IP] for packet in capture]
1211 self.pg1.add_stream(pkts)
1212 self.pg_enable_capture(self.pg_interfaces)
1213 self.pg_start()
1214
1215 # Client side - verify ICMP type 11 packets
1216 capture = self.pg0.get_capture(len(pkts))
1217 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1218
1219 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001220 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001221
Matus Fabian2ba92e32017-08-21 07:05:03 -07001222 self.nat44_add_address(self.nat_addr)
1223 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1224 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1225 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001226
1227 # Client side - create sessions
1228 pkts = self.create_stream_in(self.pg0, self.pg1)
1229 self.pg0.add_stream(pkts)
1230 self.pg_enable_capture(self.pg_interfaces)
1231 self.pg_start()
1232
1233 # Server side - generate traffic
1234 capture = self.pg1.get_capture(len(pkts))
1235 self.verify_capture_out(capture)
1236 pkts = self.create_stream_out(self.pg1, ttl=2)
1237 self.pg1.add_stream(pkts)
1238 self.pg_enable_capture(self.pg_interfaces)
1239 self.pg_start()
1240
1241 # Client side - simulate ICMP type 11 response
1242 capture = self.pg0.get_capture(len(pkts))
1243 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1244 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1245 ICMP(type=11) / packet[IP] for packet in capture]
1246 self.pg0.add_stream(pkts)
1247 self.pg_enable_capture(self.pg_interfaces)
1248 self.pg_start()
1249
1250 # Server side - verify ICMP type 11 packets
1251 capture = self.pg1.get_capture(len(pkts))
1252 self.verify_capture_out_with_icmp_errors(capture)
1253
Juraj Sloboda665e4822017-02-16 17:17:19 -08001254 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001255 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001256
Matus Fabian2ba92e32017-08-21 07:05:03 -07001257 self.nat44_add_address(self.nat_addr)
1258 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1259 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1260 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001261
1262 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1263 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1264 ICMP(id=self.icmp_id_out, type='echo-request'))
1265 pkts = [p]
1266 self.pg1.add_stream(pkts)
1267 self.pg_enable_capture(self.pg_interfaces)
1268 self.pg_start()
1269 capture = self.pg1.get_capture(len(pkts))
1270 self.assertEqual(1, len(capture))
1271 packet = capture[0]
1272 try:
1273 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1274 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1275 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1276 self.assertEqual(packet[ICMP].type, 0) # echo reply
1277 except:
1278 self.logger.error(ppp("Unexpected or invalid packet "
1279 "(outside network):", packet))
1280 raise
1281
Juraj Slobodad3677682017-04-14 03:24:45 +02001282 def test_ping_internal_host_from_outside(self):
1283 """ Ping internal host from outside network """
1284
Matus Fabian2ba92e32017-08-21 07:05:03 -07001285 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1286 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1287 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1288 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001289
1290 # out2in
1291 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001292 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001293 ICMP(id=self.icmp_id_out, type='echo-request'))
1294 self.pg1.add_stream(pkt)
1295 self.pg_enable_capture(self.pg_interfaces)
1296 self.pg_start()
1297 capture = self.pg0.get_capture(1)
1298 self.verify_capture_in(capture, self.pg0, packet_num=1)
1299 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1300
1301 # in2out
1302 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1303 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1304 ICMP(id=self.icmp_id_in, type='echo-reply'))
1305 self.pg0.add_stream(pkt)
1306 self.pg_enable_capture(self.pg_interfaces)
1307 self.pg_start()
1308 capture = self.pg1.get_capture(1)
1309 self.verify_capture_out(capture, same_port=True, packet_num=1)
1310 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1311
Juraj Sloboda7b929792017-11-23 13:20:48 +01001312 def test_forwarding(self):
1313 """ NAT44 forwarding test """
1314
1315 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1316 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1317 is_inside=0)
1318 self.vapi.nat44_forwarding_enable_disable(1)
1319
1320 real_ip = self.pg0.remote_ip4n
1321 alias_ip = self.nat_addr_n
1322 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1323 external_ip=alias_ip)
1324
1325 try:
1326 # in2out - static mapping match
1327
1328 pkts = self.create_stream_out(self.pg1)
1329 self.pg1.add_stream(pkts)
1330 self.pg_enable_capture(self.pg_interfaces)
1331 self.pg_start()
1332 capture = self.pg0.get_capture(len(pkts))
1333 self.verify_capture_in(capture, self.pg0)
1334
1335 pkts = self.create_stream_in(self.pg0, self.pg1)
1336 self.pg0.add_stream(pkts)
1337 self.pg_enable_capture(self.pg_interfaces)
1338 self.pg_start()
1339 capture = self.pg1.get_capture(len(pkts))
1340 self.verify_capture_out(capture, same_port=True)
1341
1342 # in2out - no static mapping match
1343
1344 host0 = self.pg0.remote_hosts[0]
1345 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1346 try:
1347 pkts = self.create_stream_out(self.pg1,
1348 dst_ip=self.pg0.remote_ip4,
1349 use_inside_ports=True)
1350 self.pg1.add_stream(pkts)
1351 self.pg_enable_capture(self.pg_interfaces)
1352 self.pg_start()
1353 capture = self.pg0.get_capture(len(pkts))
1354 self.verify_capture_in(capture, self.pg0)
1355
1356 pkts = self.create_stream_in(self.pg0, self.pg1)
1357 self.pg0.add_stream(pkts)
1358 self.pg_enable_capture(self.pg_interfaces)
1359 self.pg_start()
1360 capture = self.pg1.get_capture(len(pkts))
1361 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1362 same_port=True)
1363 finally:
1364 self.pg0.remote_hosts[0] = host0
1365
1366 finally:
1367 self.vapi.nat44_forwarding_enable_disable(0)
1368 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1369 external_ip=alias_ip,
1370 is_add=0)
1371
Matus Fabiande886752016-12-07 03:38:19 -08001372 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001373 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001374
1375 nat_ip = "10.0.0.10"
1376 self.tcp_port_out = 6303
1377 self.udp_port_out = 6304
1378 self.icmp_id_out = 6305
1379
Matus Fabian2ba92e32017-08-21 07:05:03 -07001380 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1381 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1382 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1383 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001384 sm = self.vapi.nat44_static_mapping_dump()
1385 self.assertEqual(len(sm), 1)
1386 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001387 self.assertEqual(sm[0].protocol, 0)
1388 self.assertEqual(sm[0].local_port, 0)
1389 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001390
1391 # in2out
1392 pkts = self.create_stream_in(self.pg0, self.pg1)
1393 self.pg0.add_stream(pkts)
1394 self.pg_enable_capture(self.pg_interfaces)
1395 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001396 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001397 self.verify_capture_out(capture, nat_ip, True)
1398
1399 # out2in
1400 pkts = self.create_stream_out(self.pg1, nat_ip)
1401 self.pg1.add_stream(pkts)
1402 self.pg_enable_capture(self.pg_interfaces)
1403 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001404 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001405 self.verify_capture_in(capture, self.pg0)
1406
1407 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001408 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001409
1410 nat_ip = "10.0.0.20"
1411 self.tcp_port_out = 6303
1412 self.udp_port_out = 6304
1413 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001414 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001415
Matus Fabian5f224992018-01-25 21:59:16 -08001416 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001417 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1418 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1419 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001420 sm = self.vapi.nat44_static_mapping_dump()
1421 self.assertEqual(len(sm), 1)
1422 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001423
1424 # out2in
1425 pkts = self.create_stream_out(self.pg1, nat_ip)
1426 self.pg1.add_stream(pkts)
1427 self.pg_enable_capture(self.pg_interfaces)
1428 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001429 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001430 self.verify_capture_in(capture, self.pg0)
1431
1432 # in2out
1433 pkts = self.create_stream_in(self.pg0, self.pg1)
1434 self.pg0.add_stream(pkts)
1435 self.pg_enable_capture(self.pg_interfaces)
1436 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001437 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001438 self.verify_capture_out(capture, nat_ip, True)
1439
1440 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001441 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001442
1443 self.tcp_port_out = 3606
1444 self.udp_port_out = 3607
1445 self.icmp_id_out = 3608
1446
Matus Fabian2ba92e32017-08-21 07:05:03 -07001447 self.nat44_add_address(self.nat_addr)
1448 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1449 self.tcp_port_in, self.tcp_port_out,
1450 proto=IP_PROTOS.tcp)
1451 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1452 self.udp_port_in, self.udp_port_out,
1453 proto=IP_PROTOS.udp)
1454 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1455 self.icmp_id_in, self.icmp_id_out,
1456 proto=IP_PROTOS.icmp)
1457 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1458 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1459 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001460
1461 # in2out
1462 pkts = self.create_stream_in(self.pg0, self.pg1)
1463 self.pg0.add_stream(pkts)
1464 self.pg_enable_capture(self.pg_interfaces)
1465 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001466 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001467 self.verify_capture_out(capture)
1468
1469 # out2in
1470 pkts = self.create_stream_out(self.pg1)
1471 self.pg1.add_stream(pkts)
1472 self.pg_enable_capture(self.pg_interfaces)
1473 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001474 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001475 self.verify_capture_in(capture, self.pg0)
1476
1477 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001478 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001479
1480 self.tcp_port_out = 30606
1481 self.udp_port_out = 30607
1482 self.icmp_id_out = 30608
1483
Matus Fabian2ba92e32017-08-21 07:05:03 -07001484 self.nat44_add_address(self.nat_addr)
1485 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1486 self.tcp_port_in, self.tcp_port_out,
1487 proto=IP_PROTOS.tcp)
1488 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1489 self.udp_port_in, self.udp_port_out,
1490 proto=IP_PROTOS.udp)
1491 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1492 self.icmp_id_in, self.icmp_id_out,
1493 proto=IP_PROTOS.icmp)
1494 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1495 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1496 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001497
1498 # out2in
1499 pkts = self.create_stream_out(self.pg1)
1500 self.pg1.add_stream(pkts)
1501 self.pg_enable_capture(self.pg_interfaces)
1502 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001503 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001504 self.verify_capture_in(capture, self.pg0)
1505
1506 # in2out
1507 pkts = self.create_stream_in(self.pg0, self.pg1)
1508 self.pg0.add_stream(pkts)
1509 self.pg_enable_capture(self.pg_interfaces)
1510 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001511 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001512 self.verify_capture_out(capture)
1513
Matus Fabiane82488f2018-01-18 03:38:45 -08001514 def test_static_with_port_out2(self):
1515 """ 1:1 NAPT symmetrical rule """
1516
1517 external_port = 80
1518 local_port = 8080
1519
1520 self.vapi.nat44_forwarding_enable_disable(1)
1521 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1522 local_port, external_port,
1523 proto=IP_PROTOS.tcp, out2in_only=1)
1524 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1525 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1526 is_inside=0)
1527
1528 # from client to service
1529 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1530 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1531 TCP(sport=12345, dport=external_port))
1532 self.pg1.add_stream(p)
1533 self.pg_enable_capture(self.pg_interfaces)
1534 self.pg_start()
1535 capture = self.pg0.get_capture(1)
1536 p = capture[0]
1537 server = None
1538 try:
1539 ip = p[IP]
1540 tcp = p[TCP]
1541 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1542 self.assertEqual(tcp.dport, local_port)
1543 self.check_tcp_checksum(p)
1544 self.check_ip_checksum(p)
1545 except:
1546 self.logger.error(ppp("Unexpected or invalid packet:", p))
1547 raise
1548
Matus Fabian87233b52018-01-26 03:17:01 -08001549 # ICMP error
1550 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1551 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1552 ICMP(type=11) / capture[0][IP])
1553 self.pg0.add_stream(p)
1554 self.pg_enable_capture(self.pg_interfaces)
1555 self.pg_start()
1556 capture = self.pg1.get_capture(1)
1557 p = capture[0]
1558 try:
1559 self.assertEqual(p[IP].src, self.nat_addr)
1560 inner = p[IPerror]
1561 self.assertEqual(inner.dst, self.nat_addr)
1562 self.assertEqual(inner[TCPerror].dport, external_port)
1563 except:
1564 self.logger.error(ppp("Unexpected or invalid packet:", p))
1565 raise
1566
Matus Fabiane82488f2018-01-18 03:38:45 -08001567 # from service back to client
1568 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1569 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1570 TCP(sport=local_port, dport=12345))
1571 self.pg0.add_stream(p)
1572 self.pg_enable_capture(self.pg_interfaces)
1573 self.pg_start()
1574 capture = self.pg1.get_capture(1)
1575 p = capture[0]
1576 try:
1577 ip = p[IP]
1578 tcp = p[TCP]
1579 self.assertEqual(ip.src, self.nat_addr)
1580 self.assertEqual(tcp.sport, external_port)
1581 self.check_tcp_checksum(p)
1582 self.check_ip_checksum(p)
1583 except:
1584 self.logger.error(ppp("Unexpected or invalid packet:", p))
1585 raise
1586
Matus Fabian87233b52018-01-26 03:17:01 -08001587 # ICMP error
1588 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1589 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1590 ICMP(type=11) / capture[0][IP])
1591 self.pg1.add_stream(p)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
1594 capture = self.pg0.get_capture(1)
1595 p = capture[0]
1596 try:
1597 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1598 inner = p[IPerror]
1599 self.assertEqual(inner.src, self.pg0.remote_ip4)
1600 self.assertEqual(inner[TCPerror].sport, local_port)
1601 except:
1602 self.logger.error(ppp("Unexpected or invalid packet:", p))
1603 raise
1604
Matus Fabiane82488f2018-01-18 03:38:45 -08001605 # from client to server (no translation)
1606 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1607 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1608 TCP(sport=12346, dport=local_port))
1609 self.pg1.add_stream(p)
1610 self.pg_enable_capture(self.pg_interfaces)
1611 self.pg_start()
1612 capture = self.pg0.get_capture(1)
1613 p = capture[0]
1614 server = None
1615 try:
1616 ip = p[IP]
1617 tcp = p[TCP]
1618 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1619 self.assertEqual(tcp.dport, local_port)
1620 self.check_tcp_checksum(p)
1621 self.check_ip_checksum(p)
1622 except:
1623 self.logger.error(ppp("Unexpected or invalid packet:", p))
1624 raise
1625
1626 # from service back to client (no translation)
1627 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1628 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1629 TCP(sport=local_port, dport=12346))
1630 self.pg0.add_stream(p)
1631 self.pg_enable_capture(self.pg_interfaces)
1632 self.pg_start()
1633 capture = self.pg1.get_capture(1)
1634 p = capture[0]
1635 try:
1636 ip = p[IP]
1637 tcp = p[TCP]
1638 self.assertEqual(ip.src, self.pg0.remote_ip4)
1639 self.assertEqual(tcp.sport, local_port)
1640 self.check_tcp_checksum(p)
1641 self.check_ip_checksum(p)
1642 except:
1643 self.logger.error(ppp("Unexpected or invalid packet:", p))
1644 raise
1645
Matus Fabiande886752016-12-07 03:38:19 -08001646 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001647 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001648
1649 nat_ip1 = "10.0.0.30"
1650 nat_ip2 = "10.0.0.40"
1651 self.tcp_port_out = 6303
1652 self.udp_port_out = 6304
1653 self.icmp_id_out = 6305
1654
Matus Fabian2ba92e32017-08-21 07:05:03 -07001655 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1656 vrf_id=10)
1657 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1658 vrf_id=10)
1659 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1660 is_inside=0)
1661 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1662 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001663
Matus Fabian2ba92e32017-08-21 07:05:03 -07001664 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001665 pkts = self.create_stream_in(self.pg4, self.pg3)
1666 self.pg4.add_stream(pkts)
1667 self.pg_enable_capture(self.pg_interfaces)
1668 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001669 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001670 self.verify_capture_out(capture, nat_ip1, True)
1671
Matus Fabian2ba92e32017-08-21 07:05:03 -07001672 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001673 # are dropped)
1674 pkts = self.create_stream_in(self.pg0, self.pg3)
1675 self.pg0.add_stream(pkts)
1676 self.pg_enable_capture(self.pg_interfaces)
1677 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001678 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001679
Matus Fabianb793d092018-01-31 05:50:21 -08001680 def test_dynamic_to_static(self):
1681 """ Switch from dynamic translation to 1:1NAT """
1682 nat_ip = "10.0.0.10"
1683 self.tcp_port_out = 6303
1684 self.udp_port_out = 6304
1685 self.icmp_id_out = 6305
1686
1687 self.nat44_add_address(self.nat_addr)
1688 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1689 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1690 is_inside=0)
1691
1692 # dynamic
1693 pkts = self.create_stream_in(self.pg0, self.pg1)
1694 self.pg0.add_stream(pkts)
1695 self.pg_enable_capture(self.pg_interfaces)
1696 self.pg_start()
1697 capture = self.pg1.get_capture(len(pkts))
1698 self.verify_capture_out(capture)
1699
1700 # 1:1NAT
1701 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1702 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1703 self.assertEqual(len(sessions), 0)
1704 pkts = self.create_stream_in(self.pg0, self.pg1)
1705 self.pg0.add_stream(pkts)
1706 self.pg_enable_capture(self.pg_interfaces)
1707 self.pg_start()
1708 capture = self.pg1.get_capture(len(pkts))
1709 self.verify_capture_out(capture, nat_ip, True)
1710
Matus Fabianab7a8052017-11-28 04:29:41 -08001711 def test_identity_nat(self):
1712 """ Identity NAT """
1713
1714 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1715 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1716 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1717 is_inside=0)
1718
1719 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1720 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1721 TCP(sport=12345, dport=56789))
1722 self.pg1.add_stream(p)
1723 self.pg_enable_capture(self.pg_interfaces)
1724 self.pg_start()
1725 capture = self.pg0.get_capture(1)
1726 p = capture[0]
1727 try:
1728 ip = p[IP]
1729 tcp = p[TCP]
1730 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1731 self.assertEqual(ip.src, self.pg1.remote_ip4)
1732 self.assertEqual(tcp.dport, 56789)
1733 self.assertEqual(tcp.sport, 12345)
1734 self.check_tcp_checksum(p)
1735 self.check_ip_checksum(p)
1736 except:
1737 self.logger.error(ppp("Unexpected or invalid packet:", p))
1738 raise
1739
Matus Fabian704018c2017-09-04 02:17:18 -07001740 def test_static_lb(self):
1741 """ NAT44 local service load balancing """
1742 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1743 external_port = 80
1744 local_port = 8080
1745 server1 = self.pg0.remote_hosts[0]
1746 server2 = self.pg0.remote_hosts[1]
1747
1748 locals = [{'addr': server1.ip4n,
1749 'port': local_port,
1750 'probability': 70},
1751 {'addr': server2.ip4n,
1752 'port': local_port,
1753 'probability': 30}]
1754
1755 self.nat44_add_address(self.nat_addr)
1756 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1757 external_port,
1758 IP_PROTOS.tcp,
1759 local_num=len(locals),
1760 locals=locals)
1761 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1762 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1763 is_inside=0)
1764
1765 # from client to service
1766 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1767 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1768 TCP(sport=12345, dport=external_port))
1769 self.pg1.add_stream(p)
1770 self.pg_enable_capture(self.pg_interfaces)
1771 self.pg_start()
1772 capture = self.pg0.get_capture(1)
1773 p = capture[0]
1774 server = None
1775 try:
1776 ip = p[IP]
1777 tcp = p[TCP]
1778 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1779 if ip.dst == server1.ip4:
1780 server = server1
1781 else:
1782 server = server2
1783 self.assertEqual(tcp.dport, local_port)
1784 self.check_tcp_checksum(p)
1785 self.check_ip_checksum(p)
1786 except:
1787 self.logger.error(ppp("Unexpected or invalid packet:", p))
1788 raise
1789
1790 # from service back to client
1791 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1792 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1793 TCP(sport=local_port, dport=12345))
1794 self.pg0.add_stream(p)
1795 self.pg_enable_capture(self.pg_interfaces)
1796 self.pg_start()
1797 capture = self.pg1.get_capture(1)
1798 p = capture[0]
1799 try:
1800 ip = p[IP]
1801 tcp = p[TCP]
1802 self.assertEqual(ip.src, self.nat_addr)
1803 self.assertEqual(tcp.sport, external_port)
1804 self.check_tcp_checksum(p)
1805 self.check_ip_checksum(p)
1806 except:
1807 self.logger.error(ppp("Unexpected or invalid packet:", p))
1808 raise
1809
Matus Fabian2aad8762018-03-07 04:57:22 -08001810 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1811 def test_static_lb_multi_clients(self):
1812 """ NAT44 local service load balancing - multiple clients"""
1813
1814 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1815 external_port = 80
1816 local_port = 8080
1817 server1 = self.pg0.remote_hosts[0]
1818 server2 = self.pg0.remote_hosts[1]
1819
1820 locals = [{'addr': server1.ip4n,
1821 'port': local_port,
1822 'probability': 90},
1823 {'addr': server2.ip4n,
1824 'port': local_port,
1825 'probability': 10}]
1826
1827 self.nat44_add_address(self.nat_addr)
1828 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1829 external_port,
1830 IP_PROTOS.tcp,
1831 local_num=len(locals),
1832 locals=locals)
1833 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1834 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1835 is_inside=0)
1836
Matus Fabian704018c2017-09-04 02:17:18 -07001837 server1_n = 0
1838 server2_n = 0
Matus Fabian2aad8762018-03-07 04:57:22 -08001839 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
Matus Fabian704018c2017-09-04 02:17:18 -07001840 pkts = []
1841 for client in clients:
1842 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1843 IP(src=client, dst=self.nat_addr) /
1844 TCP(sport=12345, dport=external_port))
1845 pkts.append(p)
1846 self.pg1.add_stream(pkts)
1847 self.pg_enable_capture(self.pg_interfaces)
1848 self.pg_start()
1849 capture = self.pg0.get_capture(len(pkts))
1850 for p in capture:
1851 if p[IP].dst == server1.ip4:
1852 server1_n += 1
1853 else:
1854 server2_n += 1
1855 self.assertTrue(server1_n > server2_n)
1856
Matus Fabian240b5ef2018-01-11 04:09:17 -08001857 def test_static_lb_2(self):
1858 """ NAT44 local service load balancing (asymmetrical rule) """
1859 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1860 external_port = 80
1861 local_port = 8080
1862 server1 = self.pg0.remote_hosts[0]
1863 server2 = self.pg0.remote_hosts[1]
1864
1865 locals = [{'addr': server1.ip4n,
1866 'port': local_port,
1867 'probability': 70},
1868 {'addr': server2.ip4n,
1869 'port': local_port,
1870 'probability': 30}]
1871
1872 self.vapi.nat44_forwarding_enable_disable(1)
1873 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1874 external_port,
1875 IP_PROTOS.tcp,
1876 out2in_only=1,
1877 local_num=len(locals),
1878 locals=locals)
1879 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1880 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1881 is_inside=0)
1882
1883 # from client to service
1884 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1885 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1886 TCP(sport=12345, dport=external_port))
1887 self.pg1.add_stream(p)
1888 self.pg_enable_capture(self.pg_interfaces)
1889 self.pg_start()
1890 capture = self.pg0.get_capture(1)
1891 p = capture[0]
1892 server = None
1893 try:
1894 ip = p[IP]
1895 tcp = p[TCP]
1896 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1897 if ip.dst == server1.ip4:
1898 server = server1
1899 else:
1900 server = server2
1901 self.assertEqual(tcp.dport, local_port)
1902 self.check_tcp_checksum(p)
1903 self.check_ip_checksum(p)
1904 except:
1905 self.logger.error(ppp("Unexpected or invalid packet:", p))
1906 raise
1907
1908 # from service back to client
1909 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1910 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1911 TCP(sport=local_port, dport=12345))
1912 self.pg0.add_stream(p)
1913 self.pg_enable_capture(self.pg_interfaces)
1914 self.pg_start()
1915 capture = self.pg1.get_capture(1)
1916 p = capture[0]
1917 try:
1918 ip = p[IP]
1919 tcp = p[TCP]
1920 self.assertEqual(ip.src, self.nat_addr)
1921 self.assertEqual(tcp.sport, external_port)
1922 self.check_tcp_checksum(p)
1923 self.check_ip_checksum(p)
1924 except:
1925 self.logger.error(ppp("Unexpected or invalid packet:", p))
1926 raise
1927
1928 # from client to server (no translation)
1929 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1930 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1931 TCP(sport=12346, dport=local_port))
1932 self.pg1.add_stream(p)
1933 self.pg_enable_capture(self.pg_interfaces)
1934 self.pg_start()
1935 capture = self.pg0.get_capture(1)
1936 p = capture[0]
1937 server = None
1938 try:
1939 ip = p[IP]
1940 tcp = p[TCP]
1941 self.assertEqual(ip.dst, server1.ip4)
1942 self.assertEqual(tcp.dport, local_port)
1943 self.check_tcp_checksum(p)
1944 self.check_ip_checksum(p)
1945 except:
1946 self.logger.error(ppp("Unexpected or invalid packet:", p))
1947 raise
1948
1949 # from service back to client (no translation)
1950 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1951 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1952 TCP(sport=local_port, dport=12346))
1953 self.pg0.add_stream(p)
1954 self.pg_enable_capture(self.pg_interfaces)
1955 self.pg_start()
1956 capture = self.pg1.get_capture(1)
1957 p = capture[0]
1958 try:
1959 ip = p[IP]
1960 tcp = p[TCP]
1961 self.assertEqual(ip.src, server1.ip4)
1962 self.assertEqual(tcp.sport, local_port)
1963 self.check_tcp_checksum(p)
1964 self.check_ip_checksum(p)
1965 except:
1966 self.logger.error(ppp("Unexpected or invalid packet:", p))
1967 raise
1968
Matus Fabiande886752016-12-07 03:38:19 -08001969 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001970 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001971
Matus Fabian2ba92e32017-08-21 07:05:03 -07001972 self.nat44_add_address(self.nat_addr)
1973 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1974 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1975 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1976 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001977
Matus Fabian2ba92e32017-08-21 07:05:03 -07001978 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001979 pkts = self.create_stream_in(self.pg0, self.pg1)
1980 self.pg0.add_stream(pkts)
1981 self.pg_enable_capture(self.pg_interfaces)
1982 self.pg_start()
1983 capture = self.pg1.get_capture(len(pkts))
1984 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1985
Matus Fabian2ba92e32017-08-21 07:05:03 -07001986 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001987 pkts = self.create_stream_in(self.pg0, self.pg2)
1988 self.pg0.add_stream(pkts)
1989 self.pg_enable_capture(self.pg_interfaces)
1990 self.pg_start()
1991 capture = self.pg2.get_capture(len(pkts))
1992 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1993
Matus Fabiande886752016-12-07 03:38:19 -08001994 # in2out 1st interface
1995 pkts = self.create_stream_in(self.pg0, self.pg3)
1996 self.pg0.add_stream(pkts)
1997 self.pg_enable_capture(self.pg_interfaces)
1998 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001999 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002000 self.verify_capture_out(capture)
2001
2002 # out2in 1st interface
2003 pkts = self.create_stream_out(self.pg3)
2004 self.pg3.add_stream(pkts)
2005 self.pg_enable_capture(self.pg_interfaces)
2006 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002007 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002008 self.verify_capture_in(capture, self.pg0)
2009
2010 # in2out 2nd interface
2011 pkts = self.create_stream_in(self.pg1, self.pg3)
2012 self.pg1.add_stream(pkts)
2013 self.pg_enable_capture(self.pg_interfaces)
2014 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002015 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002016 self.verify_capture_out(capture)
2017
2018 # out2in 2nd interface
2019 pkts = self.create_stream_out(self.pg3)
2020 self.pg3.add_stream(pkts)
2021 self.pg_enable_capture(self.pg_interfaces)
2022 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002023 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002024 self.verify_capture_in(capture, self.pg1)
2025
Matus Fabiande886752016-12-07 03:38:19 -08002026 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002027 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002028
Matus Fabian675a69c2017-01-18 01:46:01 -08002029 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002030 self.nat44_add_address(self.nat_addr)
2031 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2032 is_inside=0)
2033 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2034 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2035 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2036 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2037 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002038
Matus Fabian2ba92e32017-08-21 07:05:03 -07002039 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002040 pkts = self.create_stream_in(self.pg4, self.pg5)
2041 self.pg4.add_stream(pkts)
2042 self.pg_enable_capture(self.pg_interfaces)
2043 self.pg_start()
2044 capture = self.pg5.get_capture(len(pkts))
2045 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2046
Matus Fabian2ba92e32017-08-21 07:05:03 -07002047 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002048 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2049 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2050 TCP(sport=1234, dport=5678))
2051 self.pg4.add_stream(p)
2052 self.pg_enable_capture(self.pg_interfaces)
2053 self.pg_start()
2054 capture = self.pg6.get_capture(1)
2055 p = capture[0]
2056 try:
2057 ip = p[IP]
2058 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002059 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002060 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2061 self.assertNotEqual(tcp.sport, 1234)
2062 self.assertEqual(tcp.dport, 5678)
2063 except:
2064 self.logger.error(ppp("Unexpected or invalid packet:", p))
2065 raise
Matus Fabiande886752016-12-07 03:38:19 -08002066
2067 # in2out 1st interface
2068 pkts = self.create_stream_in(self.pg4, self.pg3)
2069 self.pg4.add_stream(pkts)
2070 self.pg_enable_capture(self.pg_interfaces)
2071 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002072 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002073 self.verify_capture_out(capture)
2074
2075 # out2in 1st interface
2076 pkts = self.create_stream_out(self.pg3)
2077 self.pg3.add_stream(pkts)
2078 self.pg_enable_capture(self.pg_interfaces)
2079 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002080 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002081 self.verify_capture_in(capture, self.pg4)
2082
2083 # in2out 2nd interface
2084 pkts = self.create_stream_in(self.pg5, self.pg3)
2085 self.pg5.add_stream(pkts)
2086 self.pg_enable_capture(self.pg_interfaces)
2087 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002088 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002089 self.verify_capture_out(capture)
2090
2091 # out2in 2nd interface
2092 pkts = self.create_stream_out(self.pg3)
2093 self.pg3.add_stream(pkts)
2094 self.pg_enable_capture(self.pg_interfaces)
2095 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002096 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002097 self.verify_capture_in(capture, self.pg5)
2098
magalik23caa882017-02-08 23:25:45 -08002099 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002100 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002101 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002102 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002103 self.assertEqual(len(sessions), 3)
2104 for session in sessions:
2105 self.assertFalse(session.is_static)
2106 self.assertEqual(session.inside_ip_address[0:4],
2107 self.pg5.remote_ip4n)
2108 self.assertEqual(session.outside_ip_address,
2109 addresses[0].ip_address)
2110 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2111 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2112 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2113 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2114 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2115 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2116 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2117 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2118 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2119
Matus Fabiande886752016-12-07 03:38:19 -08002120 # in2out 3rd interface
2121 pkts = self.create_stream_in(self.pg6, self.pg3)
2122 self.pg6.add_stream(pkts)
2123 self.pg_enable_capture(self.pg_interfaces)
2124 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002125 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002126 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002127
2128 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002129 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002130 self.pg3.add_stream(pkts)
2131 self.pg_enable_capture(self.pg_interfaces)
2132 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002133 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002134 self.verify_capture_in(capture, self.pg6)
2135
magalik23caa882017-02-08 23:25:45 -08002136 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002137 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002138 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002139 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002140 self.assertEqual(len(addresses), 1)
2141 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002142 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2143 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002144 for session in sessions:
2145 self.assertEqual(user.ip_address, session.inside_ip_address)
2146 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2147 self.assertTrue(session.protocol in
2148 [IP_PROTOS.tcp, IP_PROTOS.udp,
2149 IP_PROTOS.icmp])
2150
2151 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002152 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002153 self.assertTrue(len(sessions) >= 4)
2154 for session in sessions:
2155 self.assertFalse(session.is_static)
2156 self.assertEqual(session.inside_ip_address[0:4],
2157 self.pg4.remote_ip4n)
2158 self.assertEqual(session.outside_ip_address,
2159 addresses[0].ip_address)
2160
2161 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002162 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002163 self.assertTrue(len(sessions) >= 3)
2164 for session in sessions:
2165 self.assertTrue(session.is_static)
2166 self.assertEqual(session.inside_ip_address[0:4],
2167 self.pg6.remote_ip4n)
2168 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2169 map(int, static_nat_ip.split('.')))
2170 self.assertTrue(session.inside_port in
2171 [self.tcp_port_in, self.udp_port_in,
2172 self.icmp_id_in])
2173
Matus Fabianf78a70d2016-12-12 04:30:39 -08002174 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002175 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002176
2177 host = self.pg0.remote_hosts[0]
2178 server = self.pg0.remote_hosts[1]
2179 host_in_port = 1234
2180 host_out_port = 0
2181 server_in_port = 5678
2182 server_out_port = 8765
2183
Matus Fabian2ba92e32017-08-21 07:05:03 -07002184 self.nat44_add_address(self.nat_addr)
2185 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2186 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2187 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002188 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002189 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2190 server_in_port, server_out_port,
2191 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002192
2193 # send packet from host to server
2194 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002195 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002196 TCP(sport=host_in_port, dport=server_out_port))
2197 self.pg0.add_stream(p)
2198 self.pg_enable_capture(self.pg_interfaces)
2199 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002200 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002201 p = capture[0]
2202 try:
2203 ip = p[IP]
2204 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002205 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002206 self.assertEqual(ip.dst, server.ip4)
2207 self.assertNotEqual(tcp.sport, host_in_port)
2208 self.assertEqual(tcp.dport, server_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002209 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002210 host_out_port = tcp.sport
2211 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002212 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002213 raise
2214
2215 # send reply from server to host
2216 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002217 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002218 TCP(sport=server_in_port, dport=host_out_port))
2219 self.pg0.add_stream(p)
2220 self.pg_enable_capture(self.pg_interfaces)
2221 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002222 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002223 p = capture[0]
2224 try:
2225 ip = p[IP]
2226 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002227 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002228 self.assertEqual(ip.dst, host.ip4)
2229 self.assertEqual(tcp.sport, server_out_port)
2230 self.assertEqual(tcp.dport, host_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002231 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002232 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002233 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002234 raise
2235
Matus Fabian6fa74c62017-06-05 05:55:48 -07002236 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002237 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002238
2239 server1_nat_ip = "10.0.0.10"
2240 server2_nat_ip = "10.0.0.11"
2241 host = self.pg0.remote_hosts[0]
2242 server1 = self.pg0.remote_hosts[1]
2243 server2 = self.pg0.remote_hosts[2]
2244 server_tcp_port = 22
2245 server_udp_port = 20
2246
Matus Fabian2ba92e32017-08-21 07:05:03 -07002247 self.nat44_add_address(self.nat_addr)
2248 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2249 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2250 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002251
2252 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002253 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2254 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002255
2256 # host to server1
2257 pkts = []
2258 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2259 IP(src=host.ip4, dst=server1_nat_ip) /
2260 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2261 pkts.append(p)
2262 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2263 IP(src=host.ip4, dst=server1_nat_ip) /
2264 UDP(sport=self.udp_port_in, dport=server_udp_port))
2265 pkts.append(p)
2266 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2267 IP(src=host.ip4, dst=server1_nat_ip) /
2268 ICMP(id=self.icmp_id_in, type='echo-request'))
2269 pkts.append(p)
2270 self.pg0.add_stream(pkts)
2271 self.pg_enable_capture(self.pg_interfaces)
2272 self.pg_start()
2273 capture = self.pg0.get_capture(len(pkts))
2274 for packet in capture:
2275 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002276 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002277 self.assertEqual(packet[IP].dst, server1.ip4)
2278 if packet.haslayer(TCP):
2279 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2280 self.assertEqual(packet[TCP].dport, server_tcp_port)
2281 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002282 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002283 elif packet.haslayer(UDP):
2284 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2285 self.assertEqual(packet[UDP].dport, server_udp_port)
2286 self.udp_port_out = packet[UDP].sport
2287 else:
2288 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2289 self.icmp_id_out = packet[ICMP].id
2290 except:
2291 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2292 raise
2293
2294 # server1 to host
2295 pkts = []
2296 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002297 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002298 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2299 pkts.append(p)
2300 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002301 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002302 UDP(sport=server_udp_port, dport=self.udp_port_out))
2303 pkts.append(p)
2304 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002305 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002306 ICMP(id=self.icmp_id_out, type='echo-reply'))
2307 pkts.append(p)
2308 self.pg0.add_stream(pkts)
2309 self.pg_enable_capture(self.pg_interfaces)
2310 self.pg_start()
2311 capture = self.pg0.get_capture(len(pkts))
2312 for packet in capture:
2313 try:
2314 self.assertEqual(packet[IP].src, server1_nat_ip)
2315 self.assertEqual(packet[IP].dst, host.ip4)
2316 if packet.haslayer(TCP):
2317 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2318 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002319 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002320 elif packet.haslayer(UDP):
2321 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2322 self.assertEqual(packet[UDP].sport, server_udp_port)
2323 else:
2324 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2325 except:
2326 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2327 raise
2328
2329 # server2 to server1
2330 pkts = []
2331 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2332 IP(src=server2.ip4, dst=server1_nat_ip) /
2333 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2334 pkts.append(p)
2335 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2336 IP(src=server2.ip4, dst=server1_nat_ip) /
2337 UDP(sport=self.udp_port_in, dport=server_udp_port))
2338 pkts.append(p)
2339 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2340 IP(src=server2.ip4, dst=server1_nat_ip) /
2341 ICMP(id=self.icmp_id_in, type='echo-request'))
2342 pkts.append(p)
2343 self.pg0.add_stream(pkts)
2344 self.pg_enable_capture(self.pg_interfaces)
2345 self.pg_start()
2346 capture = self.pg0.get_capture(len(pkts))
2347 for packet in capture:
2348 try:
2349 self.assertEqual(packet[IP].src, server2_nat_ip)
2350 self.assertEqual(packet[IP].dst, server1.ip4)
2351 if packet.haslayer(TCP):
2352 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2353 self.assertEqual(packet[TCP].dport, server_tcp_port)
2354 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002355 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002356 elif packet.haslayer(UDP):
2357 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2358 self.assertEqual(packet[UDP].dport, server_udp_port)
2359 self.udp_port_out = packet[UDP].sport
2360 else:
2361 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2362 self.icmp_id_out = packet[ICMP].id
2363 except:
2364 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2365 raise
2366
2367 # server1 to server2
2368 pkts = []
2369 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2370 IP(src=server1.ip4, dst=server2_nat_ip) /
2371 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2372 pkts.append(p)
2373 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2374 IP(src=server1.ip4, dst=server2_nat_ip) /
2375 UDP(sport=server_udp_port, dport=self.udp_port_out))
2376 pkts.append(p)
2377 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2378 IP(src=server1.ip4, dst=server2_nat_ip) /
2379 ICMP(id=self.icmp_id_out, type='echo-reply'))
2380 pkts.append(p)
2381 self.pg0.add_stream(pkts)
2382 self.pg_enable_capture(self.pg_interfaces)
2383 self.pg_start()
2384 capture = self.pg0.get_capture(len(pkts))
2385 for packet in capture:
2386 try:
2387 self.assertEqual(packet[IP].src, server1_nat_ip)
2388 self.assertEqual(packet[IP].dst, server2.ip4)
2389 if packet.haslayer(TCP):
2390 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2391 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002392 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002393 elif packet.haslayer(UDP):
2394 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2395 self.assertEqual(packet[UDP].sport, server_udp_port)
2396 else:
2397 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2398 except:
2399 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2400 raise
2401
Matus Fabian9902fcd2016-12-21 23:58:46 -08002402 def test_max_translations_per_user(self):
2403 """ MAX translations per user - recycle the least recently used """
2404
Matus Fabian2ba92e32017-08-21 07:05:03 -07002405 self.nat44_add_address(self.nat_addr)
2406 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2407 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2408 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002409
2410 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002411 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002412
2413 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002414 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002415 pkts = []
2416 for port in range(0, pkts_num):
2417 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2418 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2419 TCP(sport=1025 + port))
2420 pkts.append(p)
2421 self.pg0.add_stream(pkts)
2422 self.pg_enable_capture(self.pg_interfaces)
2423 self.pg_start()
2424
2425 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002426 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002427
Matus Fabian8bf68e82017-01-12 04:24:35 -08002428 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002429 """ Acquire NAT44 addresses from interface """
2430 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002431
2432 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002433 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002434 self.assertEqual(0, len(adresses))
2435
2436 # configure interface address and check NAT address pool
2437 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002438 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002439 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002440 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002441
2442 # remove interface address and check NAT address pool
2443 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002444 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002445 self.assertEqual(0, len(adresses))
2446
Matus Fabian36532bd2017-01-23 23:42:28 -08002447 def test_interface_addr_static_mapping(self):
2448 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002449 tag = "testTAG"
2450
Matus Fabian2ba92e32017-08-21 07:05:03 -07002451 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2452 self.nat44_add_static_mapping(
2453 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002454 external_sw_if_index=self.pg7.sw_if_index,
2455 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002456
Matus Fabiane22e5462017-02-14 23:33:43 -08002457 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002458 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002459 self.assertEqual(1, len(static_mappings))
2460 self.assertEqual(self.pg7.sw_if_index,
2461 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002462 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002463
2464 # configure interface address and check static mappings
2465 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002466 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002467 self.assertEqual(2, len(static_mappings))
2468 resolved = False
2469 for sm in static_mappings:
2470 if sm.external_sw_if_index == 0xFFFFFFFF:
2471 self.assertEqual(sm.external_ip_address[0:4],
2472 self.pg7.local_ip4n)
2473 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2474 resolved = True
2475 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002476
2477 # remove interface address and check static mappings
2478 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002479 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002480 self.assertEqual(1, len(static_mappings))
2481 self.assertEqual(self.pg7.sw_if_index,
2482 static_mappings[0].external_sw_if_index)
2483 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2484
2485 # configure interface address again and check static mappings
2486 self.pg7.config_ip4()
2487 static_mappings = self.vapi.nat44_static_mapping_dump()
2488 self.assertEqual(2, len(static_mappings))
2489 resolved = False
2490 for sm in static_mappings:
2491 if sm.external_sw_if_index == 0xFFFFFFFF:
2492 self.assertEqual(sm.external_ip_address[0:4],
2493 self.pg7.local_ip4n)
2494 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2495 resolved = True
2496 self.assertTrue(resolved)
2497
2498 # remove static mapping
2499 self.nat44_add_static_mapping(
2500 '1.2.3.4',
2501 external_sw_if_index=self.pg7.sw_if_index,
2502 tag=tag,
2503 is_add=0)
2504 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002505 self.assertEqual(0, len(static_mappings))
2506
Matus Fabianab7a8052017-11-28 04:29:41 -08002507 def test_interface_addr_identity_nat(self):
2508 """ Identity NAT with addresses from interface """
2509
2510 port = 53053
2511 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2512 self.vapi.nat44_add_del_identity_mapping(
2513 sw_if_index=self.pg7.sw_if_index,
2514 port=port,
2515 protocol=IP_PROTOS.tcp,
2516 addr_only=0)
2517
2518 # identity mappings with external interface
2519 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2520 self.assertEqual(1, len(identity_mappings))
2521 self.assertEqual(self.pg7.sw_if_index,
2522 identity_mappings[0].sw_if_index)
2523
2524 # configure interface address and check identity mappings
2525 self.pg7.config_ip4()
2526 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002527 resolved = False
2528 self.assertEqual(2, len(identity_mappings))
2529 for sm in identity_mappings:
2530 if sm.sw_if_index == 0xFFFFFFFF:
2531 self.assertEqual(identity_mappings[0].ip_address,
2532 self.pg7.local_ip4n)
2533 self.assertEqual(port, identity_mappings[0].port)
2534 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2535 resolved = True
2536 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002537
2538 # remove interface address and check identity mappings
2539 self.pg7.unconfig_ip4()
2540 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002541 self.assertEqual(1, len(identity_mappings))
2542 self.assertEqual(self.pg7.sw_if_index,
2543 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002544
Matus Fabianeea28d72017-01-13 04:15:54 -08002545 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002546 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002547 self.ipfix_domain_id = 10
2548 self.ipfix_src_port = 20202
2549 colector_port = 30303
2550 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002551 self.nat44_add_address(self.nat_addr)
2552 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2553 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2554 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002555 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2556 src_address=self.pg3.local_ip4n,
2557 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002558 template_interval=10,
2559 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002560 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2561 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002562
2563 pkts = self.create_stream_in(self.pg0, self.pg1)
2564 self.pg0.add_stream(pkts)
2565 self.pg_enable_capture(self.pg_interfaces)
2566 self.pg_start()
2567 capture = self.pg1.get_capture(len(pkts))
2568 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002569 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002570 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002571 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002572 ipfix = IPFIXDecoder()
2573 # first load template
2574 for p in capture:
2575 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002576 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2577 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2578 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2579 self.assertEqual(p[UDP].dport, colector_port)
2580 self.assertEqual(p[IPFIX].observationDomainID,
2581 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002582 if p.haslayer(Template):
2583 ipfix.add_template(p.getlayer(Template))
2584 # verify events in data set
2585 for p in capture:
2586 if p.haslayer(Data):
2587 data = ipfix.decode_data_set(p.getlayer(Set))
2588 self.verify_ipfix_nat44_ses(data)
2589
2590 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002591 """ IPFIX logging NAT addresses exhausted """
2592 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2593 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2594 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002595 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2596 src_address=self.pg3.local_ip4n,
2597 path_mtu=512,
2598 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002599 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2600 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002601
2602 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2603 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2604 TCP(sport=3025))
2605 self.pg0.add_stream(p)
2606 self.pg_enable_capture(self.pg_interfaces)
2607 self.pg_start()
2608 capture = self.pg1.get_capture(0)
2609 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002610 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002611 ipfix = IPFIXDecoder()
2612 # first load template
2613 for p in capture:
2614 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002615 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2616 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2617 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2618 self.assertEqual(p[UDP].dport, 4739)
2619 self.assertEqual(p[IPFIX].observationDomainID,
2620 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002621 if p.haslayer(Template):
2622 ipfix.add_template(p.getlayer(Template))
2623 # verify events in data set
2624 for p in capture:
2625 if p.haslayer(Data):
2626 data = ipfix.decode_data_set(p.getlayer(Set))
2627 self.verify_ipfix_addr_exhausted(data)
2628
Matus Fabiana431ad12018-01-04 04:03:14 -08002629 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2630 def test_ipfix_max_sessions(self):
2631 """ IPFIX logging maximum session entries exceeded """
2632 self.nat44_add_address(self.nat_addr)
2633 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2634 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2635 is_inside=0)
2636
2637 nat44_config = self.vapi.nat_show_config()
2638 max_sessions = 10 * nat44_config.translation_buckets
2639
2640 pkts = []
2641 for i in range(0, max_sessions):
2642 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2643 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2644 IP(src=src, dst=self.pg1.remote_ip4) /
2645 TCP(sport=1025))
2646 pkts.append(p)
2647 self.pg0.add_stream(pkts)
2648 self.pg_enable_capture(self.pg_interfaces)
2649 self.pg_start()
2650
2651 self.pg1.get_capture(max_sessions)
2652 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2653 src_address=self.pg3.local_ip4n,
2654 path_mtu=512,
2655 template_interval=10)
2656 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2657 src_port=self.ipfix_src_port)
2658
2659 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2660 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2661 TCP(sport=1025))
2662 self.pg0.add_stream(p)
2663 self.pg_enable_capture(self.pg_interfaces)
2664 self.pg_start()
2665 self.pg1.get_capture(0)
2666 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2667 capture = self.pg3.get_capture(9)
2668 ipfix = IPFIXDecoder()
2669 # first load template
2670 for p in capture:
2671 self.assertTrue(p.haslayer(IPFIX))
2672 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2673 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2674 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2675 self.assertEqual(p[UDP].dport, 4739)
2676 self.assertEqual(p[IPFIX].observationDomainID,
2677 self.ipfix_domain_id)
2678 if p.haslayer(Template):
2679 ipfix.add_template(p.getlayer(Template))
2680 # verify events in data set
2681 for p in capture:
2682 if p.haslayer(Data):
2683 data = ipfix.decode_data_set(p.getlayer(Set))
2684 self.verify_ipfix_max_sessions(data, max_sessions)
2685
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002686 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002687 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002688 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002689 self.nat44_add_address(self.nat_addr)
2690 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2691 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2692 is_inside=0)
2693 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002694
Matus Fabian2ba92e32017-08-21 07:05:03 -07002695 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002696 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002697 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002698 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2699 self.pg1.add_stream(p)
2700 self.pg_enable_capture(self.pg_interfaces)
2701 self.pg_start()
2702 capture = self.pg1.get_capture(1)
2703 self.assertTrue(capture[0].haslayer(ARP))
2704 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2705
2706 # 1:1 NAT address
2707 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2708 ARP(op=ARP.who_has, pdst=static_addr,
2709 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2710 self.pg1.add_stream(p)
2711 self.pg_enable_capture(self.pg_interfaces)
2712 self.pg_start()
2713 capture = self.pg1.get_capture(1)
2714 self.assertTrue(capture[0].haslayer(ARP))
2715 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2716
Matus Fabian2ba92e32017-08-21 07:05:03 -07002717 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002718 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002719 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002720 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2721 self.pg2.add_stream(p)
2722 self.pg_enable_capture(self.pg_interfaces)
2723 self.pg_start()
2724 capture = self.pg1.get_capture(0)
2725
2726 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002727 self.nat44_add_address(self.nat_addr, is_add=0)
2728 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2729 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002730
2731 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002732 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002733 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2734 self.pg1.add_stream(p)
2735 self.pg_enable_capture(self.pg_interfaces)
2736 self.pg_start()
2737 capture = self.pg1.get_capture(0)
2738
2739 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2740 ARP(op=ARP.who_has, pdst=static_addr,
2741 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2742 self.pg1.add_stream(p)
2743 self.pg_enable_capture(self.pg_interfaces)
2744 self.pg_start()
2745 capture = self.pg1.get_capture(0)
2746
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002747 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002748 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002749
2750 vrf_id1 = 1
2751 vrf_id2 = 2
2752 nat_ip1 = "10.0.0.10"
2753 nat_ip2 = "10.0.0.11"
2754
2755 self.pg0.unconfig_ip4()
2756 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002757 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2758 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002759 self.pg0.set_table_ip4(vrf_id1)
2760 self.pg1.set_table_ip4(vrf_id2)
2761 self.pg0.config_ip4()
2762 self.pg1.config_ip4()
2763
Matus Fabian2ba92e32017-08-21 07:05:03 -07002764 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2765 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2766 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2767 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2768 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2769 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002770
2771 # first VRF
2772 pkts = self.create_stream_in(self.pg0, self.pg2)
2773 self.pg0.add_stream(pkts)
2774 self.pg_enable_capture(self.pg_interfaces)
2775 self.pg_start()
2776 capture = self.pg2.get_capture(len(pkts))
2777 self.verify_capture_out(capture, nat_ip1)
2778
2779 # second VRF
2780 pkts = self.create_stream_in(self.pg1, self.pg2)
2781 self.pg1.add_stream(pkts)
2782 self.pg_enable_capture(self.pg_interfaces)
2783 self.pg_start()
2784 capture = self.pg2.get_capture(len(pkts))
2785 self.verify_capture_out(capture, nat_ip2)
2786
Neale Ranns15002542017-09-10 04:39:11 -07002787 self.pg0.unconfig_ip4()
2788 self.pg1.unconfig_ip4()
2789 self.pg0.set_table_ip4(0)
2790 self.pg1.set_table_ip4(0)
2791 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2792 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2793
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002794 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002795 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002796
2797 nat_ip1 = "10.0.0.10"
2798 nat_ip2 = "10.0.0.11"
2799
Matus Fabian2ba92e32017-08-21 07:05:03 -07002800 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002801 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002802 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2803 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2804 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2805 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002806
2807 # first VRF
2808 pkts = self.create_stream_in(self.pg0, self.pg2)
2809 self.pg0.add_stream(pkts)
2810 self.pg_enable_capture(self.pg_interfaces)
2811 self.pg_start()
2812 capture = self.pg2.get_capture(len(pkts))
2813 self.verify_capture_out(capture, nat_ip1)
2814
2815 # second VRF
2816 pkts = self.create_stream_in(self.pg1, self.pg2)
2817 self.pg1.add_stream(pkts)
2818 self.pg_enable_capture(self.pg_interfaces)
2819 self.pg_start()
2820 capture = self.pg2.get_capture(len(pkts))
2821 self.verify_capture_out(capture, nat_ip1)
2822
Martin Gálik406eb1d2017-05-04 04:35:04 -07002823 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002824 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002825
2826 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002827 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002828 self.pg7.remote_ip4n,
2829 is_static=1)
2830 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002831 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002832 self.pg8.remote_ip4n,
2833 is_static=1)
2834
2835 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2836 dst_address_length=32,
2837 next_hop_address=self.pg7.remote_ip4n,
2838 next_hop_sw_if_index=self.pg7.sw_if_index)
2839 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2840 dst_address_length=32,
2841 next_hop_address=self.pg8.remote_ip4n,
2842 next_hop_sw_if_index=self.pg8.sw_if_index)
2843
Matus Fabian2ba92e32017-08-21 07:05:03 -07002844 self.nat44_add_address(self.nat_addr)
2845 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2846 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2847 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002848
2849 # in2out
2850 pkts = self.create_stream_in(self.pg7, self.pg8)
2851 self.pg7.add_stream(pkts)
2852 self.pg_enable_capture(self.pg_interfaces)
2853 self.pg_start()
2854 capture = self.pg8.get_capture(len(pkts))
2855 self.verify_capture_out(capture)
2856
2857 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002858 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002859 self.pg8.add_stream(pkts)
2860 self.pg_enable_capture(self.pg_interfaces)
2861 self.pg_start()
2862 capture = self.pg7.get_capture(len(pkts))
2863 self.verify_capture_in(capture, self.pg7)
2864
2865 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002866 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002867
2868 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002869 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002870 self.pg7.remote_ip4n,
2871 is_static=1)
2872 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002873 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002874 self.pg8.remote_ip4n,
2875 is_static=1)
2876
2877 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2878 dst_address_length=32,
2879 next_hop_address=self.pg7.remote_ip4n,
2880 next_hop_sw_if_index=self.pg7.sw_if_index)
2881 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2882 dst_address_length=32,
2883 next_hop_address=self.pg8.remote_ip4n,
2884 next_hop_sw_if_index=self.pg8.sw_if_index)
2885
Matus Fabian2ba92e32017-08-21 07:05:03 -07002886 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2887 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2888 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2889 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002890
2891 # out2in
2892 pkts = self.create_stream_out(self.pg8)
2893 self.pg8.add_stream(pkts)
2894 self.pg_enable_capture(self.pg_interfaces)
2895 self.pg_start()
2896 capture = self.pg7.get_capture(len(pkts))
2897 self.verify_capture_in(capture, self.pg7)
2898
2899 # in2out
2900 pkts = self.create_stream_in(self.pg7, self.pg8)
2901 self.pg7.add_stream(pkts)
2902 self.pg_enable_capture(self.pg_interfaces)
2903 self.pg_start()
2904 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002905 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002906
2907 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002908 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002909
2910 self.tcp_port_out = 30606
2911 self.udp_port_out = 30607
2912 self.icmp_id_out = 30608
2913
2914 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002915 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002916 self.pg7.remote_ip4n,
2917 is_static=1)
2918 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002919 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002920 self.pg8.remote_ip4n,
2921 is_static=1)
2922
2923 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2924 dst_address_length=32,
2925 next_hop_address=self.pg7.remote_ip4n,
2926 next_hop_sw_if_index=self.pg7.sw_if_index)
2927 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2928 dst_address_length=32,
2929 next_hop_address=self.pg8.remote_ip4n,
2930 next_hop_sw_if_index=self.pg8.sw_if_index)
2931
Matus Fabian2ba92e32017-08-21 07:05:03 -07002932 self.nat44_add_address(self.nat_addr)
2933 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2934 self.tcp_port_in, self.tcp_port_out,
2935 proto=IP_PROTOS.tcp)
2936 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2937 self.udp_port_in, self.udp_port_out,
2938 proto=IP_PROTOS.udp)
2939 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2940 self.icmp_id_in, self.icmp_id_out,
2941 proto=IP_PROTOS.icmp)
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))
2960 self.verify_capture_out(capture)
2961
Matus Fabian328dbc82017-06-19 04:28:04 -07002962 def test_static_unknown_proto(self):
2963 """ 1:1 NAT translate packet with unknown protocol """
2964 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002965 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2966 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2967 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2968 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002969
2970 # in2out
2971 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2972 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2973 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002974 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002975 TCP(sport=1234, dport=1234))
2976 self.pg0.add_stream(p)
2977 self.pg_enable_capture(self.pg_interfaces)
2978 self.pg_start()
2979 p = self.pg1.get_capture(1)
2980 packet = p[0]
2981 try:
2982 self.assertEqual(packet[IP].src, nat_ip)
2983 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2984 self.assertTrue(packet.haslayer(GRE))
2985 self.check_ip_checksum(packet)
2986 except:
2987 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2988 raise
2989
2990 # out2in
2991 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2992 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2993 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002994 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002995 TCP(sport=1234, dport=1234))
2996 self.pg1.add_stream(p)
2997 self.pg_enable_capture(self.pg_interfaces)
2998 self.pg_start()
2999 p = self.pg0.get_capture(1)
3000 packet = p[0]
3001 try:
3002 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3003 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3004 self.assertTrue(packet.haslayer(GRE))
3005 self.check_ip_checksum(packet)
3006 except:
3007 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3008 raise
3009
Matus Fabian7968e6c2017-07-06 05:37:49 -07003010 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003011 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3012
3013 host = self.pg0.remote_hosts[0]
3014 server = self.pg0.remote_hosts[1]
3015
3016 host_nat_ip = "10.0.0.10"
3017 server_nat_ip = "10.0.0.11"
3018
Matus Fabian2ba92e32017-08-21 07:05:03 -07003019 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3020 self.nat44_add_static_mapping(server.ip4, server_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 Fabian1e8db5f2017-06-20 01:45:49 -07003024
3025 # host to server
3026 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3027 IP(src=host.ip4, dst=server_nat_ip) /
3028 GRE() /
3029 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3030 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.pg0.get_capture(1)
3035 packet = p[0]
3036 try:
3037 self.assertEqual(packet[IP].src, host_nat_ip)
3038 self.assertEqual(packet[IP].dst, server.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 # server to host
3046 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3047 IP(src=server.ip4, dst=host_nat_ip) /
3048 GRE() /
3049 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3050 TCP(sport=1234, dport=1234))
3051 self.pg0.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, server_nat_ip)
3058 self.assertEqual(packet[IP].dst, host.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_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003066 """ NAT44 translate packet with unknown protocol """
3067 self.nat44_add_address(self.nat_addr)
3068 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3069 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3070 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003071
3072 # in2out
3073 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3074 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3075 TCP(sport=self.tcp_port_in, dport=20))
3076 self.pg0.add_stream(p)
3077 self.pg_enable_capture(self.pg_interfaces)
3078 self.pg_start()
3079 p = self.pg1.get_capture(1)
3080
3081 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3082 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
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.pg1.get_capture(1)
3090 packet = p[0]
3091 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003092 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003093 self.assertEqual(packet[IP].dst, self.pg1.remote_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 # out2in
3101 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003102 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003103 GRE() /
3104 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3105 TCP(sport=1234, dport=1234))
3106 self.pg1.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, self.pg1.remote_ip4)
3113 self.assertEqual(packet[IP].dst, self.pg0.remote_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
3120 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003121 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003122 host = self.pg0.remote_hosts[0]
3123 server = self.pg0.remote_hosts[1]
3124 host_in_port = 1234
3125 host_out_port = 0
3126 server_in_port = 5678
3127 server_out_port = 8765
3128 server_nat_ip = "10.0.0.11"
3129
Matus Fabian2ba92e32017-08-21 07:05:03 -07003130 self.nat44_add_address(self.nat_addr)
3131 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3132 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3133 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003134
3135 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003136 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003137
3138 # host to server
3139 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3140 IP(src=host.ip4, dst=server_nat_ip) /
3141 TCP(sport=host_in_port, dport=server_out_port))
3142 self.pg0.add_stream(p)
3143 self.pg_enable_capture(self.pg_interfaces)
3144 self.pg_start()
3145 capture = self.pg0.get_capture(1)
3146
3147 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3148 IP(src=host.ip4, dst=server_nat_ip) /
3149 GRE() /
3150 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3151 TCP(sport=1234, dport=1234))
3152 self.pg0.add_stream(p)
3153 self.pg_enable_capture(self.pg_interfaces)
3154 self.pg_start()
3155 p = self.pg0.get_capture(1)
3156 packet = p[0]
3157 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003158 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003159 self.assertEqual(packet[IP].dst, server.ip4)
3160 self.assertTrue(packet.haslayer(GRE))
3161 self.check_ip_checksum(packet)
3162 except:
3163 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3164 raise
3165
3166 # server to host
3167 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003168 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003169 GRE() /
3170 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3171 TCP(sport=1234, dport=1234))
3172 self.pg0.add_stream(p)
3173 self.pg_enable_capture(self.pg_interfaces)
3174 self.pg_start()
3175 p = self.pg0.get_capture(1)
3176 packet = p[0]
3177 try:
3178 self.assertEqual(packet[IP].src, server_nat_ip)
3179 self.assertEqual(packet[IP].dst, host.ip4)
3180 self.assertTrue(packet.haslayer(GRE))
3181 self.check_ip_checksum(packet)
3182 except:
3183 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3184 raise
3185
Matus Fabian93d84c92017-07-19 08:06:01 -07003186 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003187 """ NAT44 interface output feature (in2out postrouting) """
3188 self.nat44_add_address(self.nat_addr)
3189 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003190 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3191 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003192 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003193
3194 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003195 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003196 self.pg0.add_stream(pkts)
3197 self.pg_enable_capture(self.pg_interfaces)
3198 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003199 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003200 self.verify_capture_out(capture)
3201
3202 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003203 pkts = self.create_stream_out(self.pg3)
3204 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003205 self.pg_enable_capture(self.pg_interfaces)
3206 self.pg_start()
3207 capture = self.pg0.get_capture(len(pkts))
3208 self.verify_capture_in(capture, self.pg0)
3209
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003210 # from non-NAT interface to NAT inside interface
3211 pkts = self.create_stream_in(self.pg2, self.pg0)
3212 self.pg2.add_stream(pkts)
3213 self.pg_enable_capture(self.pg_interfaces)
3214 self.pg_start()
3215 capture = self.pg0.get_capture(len(pkts))
3216 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3217
Matus Fabian93d84c92017-07-19 08:06:01 -07003218 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003219 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003220 nat_ip_vrf10 = "10.0.0.10"
3221 nat_ip_vrf20 = "10.0.0.20"
3222
3223 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3224 dst_address_length=32,
3225 next_hop_address=self.pg3.remote_ip4n,
3226 next_hop_sw_if_index=self.pg3.sw_if_index,
3227 table_id=10)
3228 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3229 dst_address_length=32,
3230 next_hop_address=self.pg3.remote_ip4n,
3231 next_hop_sw_if_index=self.pg3.sw_if_index,
3232 table_id=20)
3233
Matus Fabian2ba92e32017-08-21 07:05:03 -07003234 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3235 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3236 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3237 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3238 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3239 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003240
3241 # in2out VRF 10
3242 pkts = self.create_stream_in(self.pg4, self.pg3)
3243 self.pg4.add_stream(pkts)
3244 self.pg_enable_capture(self.pg_interfaces)
3245 self.pg_start()
3246 capture = self.pg3.get_capture(len(pkts))
3247 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3248
3249 # out2in VRF 10
3250 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3251 self.pg3.add_stream(pkts)
3252 self.pg_enable_capture(self.pg_interfaces)
3253 self.pg_start()
3254 capture = self.pg4.get_capture(len(pkts))
3255 self.verify_capture_in(capture, self.pg4)
3256
3257 # in2out VRF 20
3258 pkts = self.create_stream_in(self.pg6, self.pg3)
3259 self.pg6.add_stream(pkts)
3260 self.pg_enable_capture(self.pg_interfaces)
3261 self.pg_start()
3262 capture = self.pg3.get_capture(len(pkts))
3263 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3264
3265 # out2in VRF 20
3266 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3267 self.pg3.add_stream(pkts)
3268 self.pg_enable_capture(self.pg_interfaces)
3269 self.pg_start()
3270 capture = self.pg6.get_capture(len(pkts))
3271 self.verify_capture_in(capture, self.pg6)
3272
Matus Fabian161c59c2017-07-21 03:46:03 -07003273 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003274 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003275 host = self.pg0.remote_hosts[0]
3276 server = self.pg0.remote_hosts[1]
3277 host_in_port = 1234
3278 host_out_port = 0
3279 server_in_port = 5678
3280 server_out_port = 8765
3281
Matus Fabian2ba92e32017-08-21 07:05:03 -07003282 self.nat44_add_address(self.nat_addr)
3283 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3284 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3285 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003286
3287 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003288 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3289 server_in_port, server_out_port,
3290 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003291
3292 # send packet from host to server
3293 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003294 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003295 TCP(sport=host_in_port, dport=server_out_port))
3296 self.pg0.add_stream(p)
3297 self.pg_enable_capture(self.pg_interfaces)
3298 self.pg_start()
3299 capture = self.pg0.get_capture(1)
3300 p = capture[0]
3301 try:
3302 ip = p[IP]
3303 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003304 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003305 self.assertEqual(ip.dst, server.ip4)
3306 self.assertNotEqual(tcp.sport, host_in_port)
3307 self.assertEqual(tcp.dport, server_in_port)
3308 self.check_tcp_checksum(p)
3309 host_out_port = tcp.sport
3310 except:
3311 self.logger.error(ppp("Unexpected or invalid packet:", p))
3312 raise
3313
3314 # send reply from server to host
3315 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003316 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003317 TCP(sport=server_in_port, dport=host_out_port))
3318 self.pg0.add_stream(p)
3319 self.pg_enable_capture(self.pg_interfaces)
3320 self.pg_start()
3321 capture = self.pg0.get_capture(1)
3322 p = capture[0]
3323 try:
3324 ip = p[IP]
3325 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003326 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003327 self.assertEqual(ip.dst, host.ip4)
3328 self.assertEqual(tcp.sport, server_out_port)
3329 self.assertEqual(tcp.dport, host_in_port)
3330 self.check_tcp_checksum(p)
3331 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003332 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003333 raise
3334
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003335 def test_output_feature_and_service(self):
3336 """ NAT44 interface output feature and services """
3337 external_addr = '1.2.3.4'
3338 external_port = 80
3339 local_port = 8080
3340
3341 self.vapi.nat44_forwarding_enable_disable(1)
3342 self.nat44_add_address(self.nat_addr)
3343 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3344 local_port, external_port,
3345 proto=IP_PROTOS.tcp, out2in_only=1)
3346 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3347 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3348 is_inside=0)
3349
3350 # from client to service
3351 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3352 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3353 TCP(sport=12345, dport=external_port))
3354 self.pg1.add_stream(p)
3355 self.pg_enable_capture(self.pg_interfaces)
3356 self.pg_start()
3357 capture = self.pg0.get_capture(1)
3358 p = capture[0]
3359 server = None
3360 try:
3361 ip = p[IP]
3362 tcp = p[TCP]
3363 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3364 self.assertEqual(tcp.dport, local_port)
3365 self.check_tcp_checksum(p)
3366 self.check_ip_checksum(p)
3367 except:
3368 self.logger.error(ppp("Unexpected or invalid packet:", p))
3369 raise
3370
3371 # from service back to client
3372 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3373 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3374 TCP(sport=local_port, dport=12345))
3375 self.pg0.add_stream(p)
3376 self.pg_enable_capture(self.pg_interfaces)
3377 self.pg_start()
3378 capture = self.pg1.get_capture(1)
3379 p = capture[0]
3380 try:
3381 ip = p[IP]
3382 tcp = p[TCP]
3383 self.assertEqual(ip.src, external_addr)
3384 self.assertEqual(tcp.sport, external_port)
3385 self.check_tcp_checksum(p)
3386 self.check_ip_checksum(p)
3387 except:
3388 self.logger.error(ppp("Unexpected or invalid packet:", p))
3389 raise
3390
3391 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003392 pkts = self.create_stream_in(self.pg0, self.pg1)
3393 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003394 self.pg_enable_capture(self.pg_interfaces)
3395 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003396 capture = self.pg1.get_capture(len(pkts))
3397 self.verify_capture_out(capture)
3398 pkts = self.create_stream_in(self.pg0, self.pg1)
3399 self.pg0.add_stream(pkts)
3400 self.pg_enable_capture(self.pg_interfaces)
3401 self.pg_start()
3402 capture = self.pg1.get_capture(len(pkts))
3403 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003404
3405 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003406 pkts = self.create_stream_out(self.pg1)
3407 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003408 self.pg_enable_capture(self.pg_interfaces)
3409 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003410 capture = self.pg0.get_capture(len(pkts))
3411 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003412
Matus Fabian204591d2018-03-01 04:48:33 -08003413 def test_output_feature_and_service2(self):
3414 """ NAT44 interface output feature and service host direct access """
3415 self.vapi.nat44_forwarding_enable_disable(1)
3416 self.nat44_add_address(self.nat_addr)
3417 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3418 is_inside=0)
3419
3420 # session initiaded from service host - translate
3421 pkts = self.create_stream_in(self.pg0, self.pg1)
3422 self.pg0.add_stream(pkts)
3423 self.pg_enable_capture(self.pg_interfaces)
3424 self.pg_start()
3425 capture = self.pg1.get_capture(len(pkts))
3426 self.verify_capture_out(capture)
3427
3428 pkts = self.create_stream_out(self.pg1)
3429 self.pg1.add_stream(pkts)
3430 self.pg_enable_capture(self.pg_interfaces)
3431 self.pg_start()
3432 capture = self.pg0.get_capture(len(pkts))
3433 self.verify_capture_in(capture, self.pg0)
3434
3435 tcp_port_out = self.tcp_port_out
3436 udp_port_out = self.udp_port_out
3437 icmp_id_out = self.icmp_id_out
3438
3439 # session initiaded from remote host - do not translate
3440 pkts = self.create_stream_out(self.pg1,
3441 self.pg0.remote_ip4,
3442 use_inside_ports=True)
3443 self.pg1.add_stream(pkts)
3444 self.pg_enable_capture(self.pg_interfaces)
3445 self.pg_start()
3446 capture = self.pg0.get_capture(len(pkts))
3447 self.verify_capture_in(capture, self.pg0)
3448
3449 pkts = self.create_stream_in(self.pg0, self.pg1)
3450 self.pg0.add_stream(pkts)
3451 self.pg_enable_capture(self.pg_interfaces)
3452 self.pg_start()
3453 capture = self.pg1.get_capture(len(pkts))
3454 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3455 same_port=True)
3456
Matus Fabian4d023c82018-03-22 05:50:47 -07003457 def test_output_feature_and_service3(self):
3458 """ NAT44 interface output feature and DST NAT """
3459 external_addr = '1.2.3.4'
3460 external_port = 80
3461 local_port = 8080
3462
3463 self.vapi.nat44_forwarding_enable_disable(1)
3464 self.nat44_add_address(self.nat_addr)
3465 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3466 local_port, external_port,
3467 proto=IP_PROTOS.tcp, out2in_only=1)
3468 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3469 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3470 is_inside=0)
3471 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3472 is_inside=0)
3473
3474 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3475 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3476 TCP(sport=12345, dport=external_port))
3477 self.pg0.add_stream(p)
3478 self.pg_enable_capture(self.pg_interfaces)
3479 self.pg_start()
3480 capture = self.pg1.get_capture(1)
3481 p = capture[0]
3482 try:
3483 ip = p[IP]
3484 tcp = p[TCP]
3485 self.assertEqual(ip.src, self.pg0.remote_ip4)
3486 self.assertEqual(tcp.sport, 12345)
3487 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3488 self.assertEqual(tcp.dport, local_port)
3489 self.check_tcp_checksum(p)
3490 self.check_ip_checksum(p)
3491 except:
3492 self.logger.error(ppp("Unexpected or invalid packet:", p))
3493 raise
3494
3495 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3496 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3497 TCP(sport=local_port, dport=12345))
3498 self.pg1.add_stream(p)
3499 self.pg_enable_capture(self.pg_interfaces)
3500 self.pg_start()
3501 capture = self.pg0.get_capture(1)
3502 p = capture[0]
3503 try:
3504 ip = p[IP]
3505 tcp = p[TCP]
3506 self.assertEqual(ip.src, external_addr)
3507 self.assertEqual(tcp.sport, external_port)
3508 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3509 self.assertEqual(tcp.dport, 12345)
3510 self.check_tcp_checksum(p)
3511 self.check_ip_checksum(p)
3512 except:
3513 self.logger.error(ppp("Unexpected or invalid packet:", p))
3514 raise
3515
Matus Fabian36ea2d62017-10-24 04:13:49 -07003516 def test_one_armed_nat44(self):
3517 """ One armed NAT44 """
3518 remote_host = self.pg9.remote_hosts[0]
3519 local_host = self.pg9.remote_hosts[1]
3520 external_port = 0
3521
3522 self.nat44_add_address(self.nat_addr)
3523 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3524 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3525 is_inside=0)
3526
3527 # in2out
3528 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3529 IP(src=local_host.ip4, dst=remote_host.ip4) /
3530 TCP(sport=12345, dport=80))
3531 self.pg9.add_stream(p)
3532 self.pg_enable_capture(self.pg_interfaces)
3533 self.pg_start()
3534 capture = self.pg9.get_capture(1)
3535 p = capture[0]
3536 try:
3537 ip = p[IP]
3538 tcp = p[TCP]
3539 self.assertEqual(ip.src, self.nat_addr)
3540 self.assertEqual(ip.dst, remote_host.ip4)
3541 self.assertNotEqual(tcp.sport, 12345)
3542 external_port = tcp.sport
3543 self.assertEqual(tcp.dport, 80)
3544 self.check_tcp_checksum(p)
3545 self.check_ip_checksum(p)
3546 except:
3547 self.logger.error(ppp("Unexpected or invalid packet:", p))
3548 raise
3549
3550 # out2in
3551 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3552 IP(src=remote_host.ip4, dst=self.nat_addr) /
3553 TCP(sport=80, dport=external_port))
3554 self.pg9.add_stream(p)
3555 self.pg_enable_capture(self.pg_interfaces)
3556 self.pg_start()
3557 capture = self.pg9.get_capture(1)
3558 p = capture[0]
3559 try:
3560 ip = p[IP]
3561 tcp = p[TCP]
3562 self.assertEqual(ip.src, remote_host.ip4)
3563 self.assertEqual(ip.dst, local_host.ip4)
3564 self.assertEqual(tcp.sport, 80)
3565 self.assertEqual(tcp.dport, 12345)
3566 self.check_tcp_checksum(p)
3567 self.check_ip_checksum(p)
3568 except:
3569 self.logger.error(ppp("Unexpected or invalid packet:", p))
3570 raise
3571
Matus Fabiand95c39e2018-01-23 06:07:01 -08003572 def test_one_armed_nat44_static(self):
3573 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3574 remote_host = self.pg9.remote_hosts[0]
3575 local_host = self.pg9.remote_hosts[1]
3576 external_port = 80
3577 local_port = 8080
3578 eh_port_in = 0
3579
3580 self.vapi.nat44_forwarding_enable_disable(1)
3581 self.nat44_add_address(self.nat_addr, twice_nat=1)
3582 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3583 local_port, external_port,
3584 proto=IP_PROTOS.tcp, out2in_only=1,
3585 twice_nat=1)
3586 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3587 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3588 is_inside=0)
3589
3590 # from client to service
3591 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3592 IP(src=remote_host.ip4, dst=self.nat_addr) /
3593 TCP(sport=12345, dport=external_port))
3594 self.pg9.add_stream(p)
3595 self.pg_enable_capture(self.pg_interfaces)
3596 self.pg_start()
3597 capture = self.pg9.get_capture(1)
3598 p = capture[0]
3599 server = None
3600 try:
3601 ip = p[IP]
3602 tcp = p[TCP]
3603 self.assertEqual(ip.dst, local_host.ip4)
3604 self.assertEqual(ip.src, self.nat_addr)
3605 self.assertEqual(tcp.dport, local_port)
3606 self.assertNotEqual(tcp.sport, 12345)
3607 eh_port_in = tcp.sport
3608 self.check_tcp_checksum(p)
3609 self.check_ip_checksum(p)
3610 except:
3611 self.logger.error(ppp("Unexpected or invalid packet:", p))
3612 raise
3613
3614 # from service back to client
3615 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3616 IP(src=local_host.ip4, dst=self.nat_addr) /
3617 TCP(sport=local_port, dport=eh_port_in))
3618 self.pg9.add_stream(p)
3619 self.pg_enable_capture(self.pg_interfaces)
3620 self.pg_start()
3621 capture = self.pg9.get_capture(1)
3622 p = capture[0]
3623 try:
3624 ip = p[IP]
3625 tcp = p[TCP]
3626 self.assertEqual(ip.src, self.nat_addr)
3627 self.assertEqual(ip.dst, remote_host.ip4)
3628 self.assertEqual(tcp.sport, external_port)
3629 self.assertEqual(tcp.dport, 12345)
3630 self.check_tcp_checksum(p)
3631 self.check_ip_checksum(p)
3632 except:
3633 self.logger.error(ppp("Unexpected or invalid packet:", p))
3634 raise
3635
Matus Fabian5ba86f72017-10-26 03:37:38 -07003636 def test_del_session(self):
3637 """ Delete NAT44 session """
3638 self.nat44_add_address(self.nat_addr)
3639 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3640 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3641 is_inside=0)
3642
3643 pkts = self.create_stream_in(self.pg0, self.pg1)
3644 self.pg0.add_stream(pkts)
3645 self.pg_enable_capture(self.pg_interfaces)
3646 self.pg_start()
3647 capture = self.pg1.get_capture(len(pkts))
3648
3649 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3650 nsessions = len(sessions)
3651
3652 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3653 sessions[0].inside_port,
3654 sessions[0].protocol)
3655 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3656 sessions[1].outside_port,
3657 sessions[1].protocol,
3658 is_in=0)
3659
3660 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3661 self.assertEqual(nsessions - len(sessions), 2)
3662
Matus Fabianefcd1e92017-08-15 06:59:19 -07003663 def test_set_get_reass(self):
3664 """ NAT44 set/get virtual fragmentation reassembly """
3665 reas_cfg1 = self.vapi.nat_get_reass()
3666
3667 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3668 max_reass=reas_cfg1.ip4_max_reass * 2,
3669 max_frag=reas_cfg1.ip4_max_frag * 2)
3670
3671 reas_cfg2 = self.vapi.nat_get_reass()
3672
3673 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3674 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3675 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3676
3677 self.vapi.nat_set_reass(drop_frag=1)
3678 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3679
3680 def test_frag_in_order(self):
3681 """ NAT44 translate fragments arriving in order """
3682 self.nat44_add_address(self.nat_addr)
3683 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3684 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3685 is_inside=0)
3686
3687 data = "A" * 4 + "B" * 16 + "C" * 3
3688 self.tcp_port_in = random.randint(1025, 65535)
3689
3690 reass = self.vapi.nat_reass_dump()
3691 reass_n_start = len(reass)
3692
3693 # in2out
3694 pkts = self.create_stream_frag(self.pg0,
3695 self.pg1.remote_ip4,
3696 self.tcp_port_in,
3697 20,
3698 data)
3699 self.pg0.add_stream(pkts)
3700 self.pg_enable_capture(self.pg_interfaces)
3701 self.pg_start()
3702 frags = self.pg1.get_capture(len(pkts))
3703 p = self.reass_frags_and_verify(frags,
3704 self.nat_addr,
3705 self.pg1.remote_ip4)
3706 self.assertEqual(p[TCP].dport, 20)
3707 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3708 self.tcp_port_out = p[TCP].sport
3709 self.assertEqual(data, p[Raw].load)
3710
3711 # out2in
3712 pkts = self.create_stream_frag(self.pg1,
3713 self.nat_addr,
3714 20,
3715 self.tcp_port_out,
3716 data)
3717 self.pg1.add_stream(pkts)
3718 self.pg_enable_capture(self.pg_interfaces)
3719 self.pg_start()
3720 frags = self.pg0.get_capture(len(pkts))
3721 p = self.reass_frags_and_verify(frags,
3722 self.pg1.remote_ip4,
3723 self.pg0.remote_ip4)
3724 self.assertEqual(p[TCP].sport, 20)
3725 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3726 self.assertEqual(data, p[Raw].load)
3727
3728 reass = self.vapi.nat_reass_dump()
3729 reass_n_end = len(reass)
3730
3731 self.assertEqual(reass_n_end - reass_n_start, 2)
3732
3733 def test_reass_hairpinning(self):
3734 """ NAT44 fragments hairpinning """
3735 host = self.pg0.remote_hosts[0]
3736 server = self.pg0.remote_hosts[1]
3737 host_in_port = random.randint(1025, 65535)
3738 host_out_port = 0
3739 server_in_port = random.randint(1025, 65535)
3740 server_out_port = random.randint(1025, 65535)
3741 data = "A" * 4 + "B" * 16 + "C" * 3
3742
3743 self.nat44_add_address(self.nat_addr)
3744 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3745 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3746 is_inside=0)
3747 # add static mapping for server
3748 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3749 server_in_port, server_out_port,
3750 proto=IP_PROTOS.tcp)
3751
3752 # send packet from host to server
3753 pkts = self.create_stream_frag(self.pg0,
3754 self.nat_addr,
3755 host_in_port,
3756 server_out_port,
3757 data)
3758 self.pg0.add_stream(pkts)
3759 self.pg_enable_capture(self.pg_interfaces)
3760 self.pg_start()
3761 frags = self.pg0.get_capture(len(pkts))
3762 p = self.reass_frags_and_verify(frags,
3763 self.nat_addr,
3764 server.ip4)
3765 self.assertNotEqual(p[TCP].sport, host_in_port)
3766 self.assertEqual(p[TCP].dport, server_in_port)
3767 self.assertEqual(data, p[Raw].load)
3768
3769 def test_frag_out_of_order(self):
3770 """ NAT44 translate fragments arriving out of order """
3771 self.nat44_add_address(self.nat_addr)
3772 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3773 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3774 is_inside=0)
3775
3776 data = "A" * 4 + "B" * 16 + "C" * 3
3777 random.randint(1025, 65535)
3778
3779 # in2out
3780 pkts = self.create_stream_frag(self.pg0,
3781 self.pg1.remote_ip4,
3782 self.tcp_port_in,
3783 20,
3784 data)
3785 pkts.reverse()
3786 self.pg0.add_stream(pkts)
3787 self.pg_enable_capture(self.pg_interfaces)
3788 self.pg_start()
3789 frags = self.pg1.get_capture(len(pkts))
3790 p = self.reass_frags_and_verify(frags,
3791 self.nat_addr,
3792 self.pg1.remote_ip4)
3793 self.assertEqual(p[TCP].dport, 20)
3794 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3795 self.tcp_port_out = p[TCP].sport
3796 self.assertEqual(data, p[Raw].load)
3797
3798 # out2in
3799 pkts = self.create_stream_frag(self.pg1,
3800 self.nat_addr,
3801 20,
3802 self.tcp_port_out,
3803 data)
3804 pkts.reverse()
3805 self.pg1.add_stream(pkts)
3806 self.pg_enable_capture(self.pg_interfaces)
3807 self.pg_start()
3808 frags = self.pg0.get_capture(len(pkts))
3809 p = self.reass_frags_and_verify(frags,
3810 self.pg1.remote_ip4,
3811 self.pg0.remote_ip4)
3812 self.assertEqual(p[TCP].sport, 20)
3813 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3814 self.assertEqual(data, p[Raw].load)
3815
Matus Fabian27697102017-11-09 01:43:47 -08003816 def test_port_restricted(self):
3817 """ Port restricted NAT44 (MAP-E CE) """
3818 self.nat44_add_address(self.nat_addr)
3819 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3820 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3821 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003822 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003823 "psid-offset 6 psid-len 6")
3824
3825 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3826 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3827 TCP(sport=4567, dport=22))
3828 self.pg0.add_stream(p)
3829 self.pg_enable_capture(self.pg_interfaces)
3830 self.pg_start()
3831 capture = self.pg1.get_capture(1)
3832 p = capture[0]
3833 try:
3834 ip = p[IP]
3835 tcp = p[TCP]
3836 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3837 self.assertEqual(ip.src, self.nat_addr)
3838 self.assertEqual(tcp.dport, 22)
3839 self.assertNotEqual(tcp.sport, 4567)
3840 self.assertEqual((tcp.sport >> 6) & 63, 10)
3841 self.check_tcp_checksum(p)
3842 self.check_ip_checksum(p)
3843 except:
3844 self.logger.error(ppp("Unexpected or invalid packet:", p))
3845 raise
3846
Matus Fabianb932d262017-12-18 05:38:24 -08003847 def test_twice_nat(self):
3848 """ Twice NAT44 """
3849 twice_nat_addr = '10.0.1.3'
3850 port_in = 8080
3851 port_out = 80
3852 eh_port_out = 4567
3853 eh_port_in = 0
3854 self.nat44_add_address(self.nat_addr)
3855 self.nat44_add_address(twice_nat_addr, twice_nat=1)
3856 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3857 port_in, port_out, proto=IP_PROTOS.tcp,
3858 twice_nat=1)
3859 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3860 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3861 is_inside=0)
3862
3863 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3864 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3865 TCP(sport=eh_port_out, dport=port_out))
3866 self.pg1.add_stream(p)
3867 self.pg_enable_capture(self.pg_interfaces)
3868 self.pg_start()
3869 capture = self.pg0.get_capture(1)
3870 p = capture[0]
3871 try:
3872 ip = p[IP]
3873 tcp = p[TCP]
3874 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3875 self.assertEqual(ip.src, twice_nat_addr)
3876 self.assertEqual(tcp.dport, port_in)
3877 self.assertNotEqual(tcp.sport, eh_port_out)
3878 eh_port_in = tcp.sport
3879 self.check_tcp_checksum(p)
3880 self.check_ip_checksum(p)
3881 except:
3882 self.logger.error(ppp("Unexpected or invalid packet:", p))
3883 raise
3884
3885 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3886 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3887 TCP(sport=port_in, dport=eh_port_in))
3888 self.pg0.add_stream(p)
3889 self.pg_enable_capture(self.pg_interfaces)
3890 self.pg_start()
3891 capture = self.pg1.get_capture(1)
3892 p = capture[0]
3893 try:
3894 ip = p[IP]
3895 tcp = p[TCP]
3896 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3897 self.assertEqual(ip.src, self.nat_addr)
3898 self.assertEqual(tcp.dport, eh_port_out)
3899 self.assertEqual(tcp.sport, port_out)
3900 self.check_tcp_checksum(p)
3901 self.check_ip_checksum(p)
3902 except:
3903 self.logger.error(ppp("Unexpected or invalid packet:", p))
3904 raise
3905
3906 def test_twice_nat_lb(self):
3907 """ Twice NAT44 local service load balancing """
3908 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3909 twice_nat_addr = '10.0.1.3'
3910 local_port = 8080
3911 external_port = 80
3912 eh_port_out = 4567
3913 eh_port_in = 0
3914 server1 = self.pg0.remote_hosts[0]
3915 server2 = self.pg0.remote_hosts[1]
3916
3917 locals = [{'addr': server1.ip4n,
3918 'port': local_port,
3919 'probability': 50},
3920 {'addr': server2.ip4n,
3921 'port': local_port,
3922 'probability': 50}]
3923
3924 self.nat44_add_address(self.nat_addr)
3925 self.nat44_add_address(twice_nat_addr, twice_nat=1)
3926
3927 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3928 external_port,
3929 IP_PROTOS.tcp,
3930 twice_nat=1,
3931 local_num=len(locals),
3932 locals=locals)
3933 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3934 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3935 is_inside=0)
3936
3937 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3938 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3939 TCP(sport=eh_port_out, dport=external_port))
3940 self.pg1.add_stream(p)
3941 self.pg_enable_capture(self.pg_interfaces)
3942 self.pg_start()
3943 capture = self.pg0.get_capture(1)
3944 p = capture[0]
3945 server = None
3946 try:
3947 ip = p[IP]
3948 tcp = p[TCP]
3949 self.assertEqual(ip.src, twice_nat_addr)
3950 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3951 if ip.dst == server1.ip4:
3952 server = server1
3953 else:
3954 server = server2
3955 self.assertNotEqual(tcp.sport, eh_port_out)
3956 eh_port_in = tcp.sport
3957 self.assertEqual(tcp.dport, local_port)
3958 self.check_tcp_checksum(p)
3959 self.check_ip_checksum(p)
3960 except:
3961 self.logger.error(ppp("Unexpected or invalid packet:", p))
3962 raise
3963
3964 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3965 IP(src=server.ip4, dst=twice_nat_addr) /
3966 TCP(sport=local_port, dport=eh_port_in))
3967 self.pg0.add_stream(p)
3968 self.pg_enable_capture(self.pg_interfaces)
3969 self.pg_start()
3970 capture = self.pg1.get_capture(1)
3971 p = capture[0]
3972 try:
3973 ip = p[IP]
3974 tcp = p[TCP]
3975 self.assertEqual(ip.src, self.nat_addr)
3976 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3977 self.assertEqual(tcp.sport, external_port)
3978 self.assertEqual(tcp.dport, eh_port_out)
3979 self.check_tcp_checksum(p)
3980 self.check_ip_checksum(p)
3981 except:
3982 self.logger.error(ppp("Unexpected or invalid packet:", p))
3983 raise
3984
3985 def test_twice_nat_interface_addr(self):
3986 """ Acquire twice NAT44 addresses from interface """
3987 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
3988
3989 # no address in NAT pool
3990 adresses = self.vapi.nat44_address_dump()
3991 self.assertEqual(0, len(adresses))
3992
3993 # configure interface address and check NAT address pool
3994 self.pg7.config_ip4()
3995 adresses = self.vapi.nat44_address_dump()
3996 self.assertEqual(1, len(adresses))
3997 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
3998 self.assertEqual(adresses[0].twice_nat, 1)
3999
4000 # remove interface address and check NAT address pool
4001 self.pg7.unconfig_ip4()
4002 adresses = self.vapi.nat44_address_dump()
4003 self.assertEqual(0, len(adresses))
4004
Matus Fabiana431ad12018-01-04 04:03:14 -08004005 def test_ipfix_max_frags(self):
4006 """ IPFIX logging maximum fragments pending reassembly exceeded """
4007 self.nat44_add_address(self.nat_addr)
4008 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4009 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4010 is_inside=0)
4011 self.vapi.nat_set_reass(max_frag=0)
4012 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4013 src_address=self.pg3.local_ip4n,
4014 path_mtu=512,
4015 template_interval=10)
4016 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4017 src_port=self.ipfix_src_port)
4018
4019 data = "A" * 4 + "B" * 16 + "C" * 3
4020 self.tcp_port_in = random.randint(1025, 65535)
4021 pkts = self.create_stream_frag(self.pg0,
4022 self.pg1.remote_ip4,
4023 self.tcp_port_in,
4024 20,
4025 data)
4026 self.pg0.add_stream(pkts[-1])
4027 self.pg_enable_capture(self.pg_interfaces)
4028 self.pg_start()
4029 frags = self.pg1.get_capture(0)
4030 self.vapi.cli("ipfix flush") # FIXME this should be an API call
4031 capture = self.pg3.get_capture(9)
4032 ipfix = IPFIXDecoder()
4033 # first load template
4034 for p in capture:
4035 self.assertTrue(p.haslayer(IPFIX))
4036 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4037 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4038 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4039 self.assertEqual(p[UDP].dport, 4739)
4040 self.assertEqual(p[IPFIX].observationDomainID,
4041 self.ipfix_domain_id)
4042 if p.haslayer(Template):
4043 ipfix.add_template(p.getlayer(Template))
4044 # verify events in data set
4045 for p in capture:
4046 if p.haslayer(Data):
4047 data = ipfix.decode_data_set(p.getlayer(Set))
4048 self.verify_ipfix_max_fragments_ip4(data, 0,
4049 self.pg0.remote_ip4n)
4050
Matus Fabiande886752016-12-07 03:38:19 -08004051 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004052 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004053 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004054 self.logger.info(self.vapi.cli("show nat44 addresses"))
4055 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4056 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4057 self.logger.info(self.vapi.cli("show nat44 interface address"))
4058 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004059 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004060 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004061 self.clear_nat44()
Matus Fabiande886752016-12-07 03:38:19 -08004062
Matus Fabianeea28d72017-01-13 04:15:54 -08004063
Juraj Slobodacba69362017-12-19 02:09:32 +01004064class TestNAT44Out2InDPO(MethodHolder):
4065 """ NAT44 Test Cases using out2in DPO """
4066
4067 @classmethod
4068 def setUpConstants(cls):
4069 super(TestNAT44Out2InDPO, cls).setUpConstants()
4070 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4071
4072 @classmethod
4073 def setUpClass(cls):
4074 super(TestNAT44Out2InDPO, cls).setUpClass()
4075
4076 try:
4077 cls.tcp_port_in = 6303
4078 cls.tcp_port_out = 6303
4079 cls.udp_port_in = 6304
4080 cls.udp_port_out = 6304
4081 cls.icmp_id_in = 6305
4082 cls.icmp_id_out = 6305
4083 cls.nat_addr = '10.0.0.3'
4084 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4085 cls.dst_ip4 = '192.168.70.1'
4086
4087 cls.create_pg_interfaces(range(2))
4088
4089 cls.pg0.admin_up()
4090 cls.pg0.config_ip4()
4091 cls.pg0.resolve_arp()
4092
4093 cls.pg1.admin_up()
4094 cls.pg1.config_ip6()
4095 cls.pg1.resolve_ndp()
4096
4097 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4098 dst_address_length=0,
4099 next_hop_address=cls.pg1.remote_ip6n,
4100 next_hop_sw_if_index=cls.pg1.sw_if_index)
4101
4102 except Exception:
4103 super(TestNAT44Out2InDPO, cls).tearDownClass()
4104 raise
4105
4106 def configure_xlat(self):
4107 self.dst_ip6_pfx = '1:2:3::'
4108 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4109 self.dst_ip6_pfx)
4110 self.dst_ip6_pfx_len = 96
4111 self.src_ip6_pfx = '4:5:6::'
4112 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4113 self.src_ip6_pfx)
4114 self.src_ip6_pfx_len = 96
4115 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4116 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4117 '\x00\x00\x00\x00', 0, is_translation=1,
4118 is_rfc6052=1)
4119
4120 def test_464xlat_ce(self):
4121 """ Test 464XLAT CE with NAT44 """
4122
4123 self.configure_xlat()
4124
4125 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4126 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4127
4128 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4129 self.dst_ip6_pfx_len)
4130 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4131 self.src_ip6_pfx_len)
4132
4133 try:
4134 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4135 self.pg0.add_stream(pkts)
4136 self.pg_enable_capture(self.pg_interfaces)
4137 self.pg_start()
4138 capture = self.pg1.get_capture(len(pkts))
4139 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4140 dst_ip=out_src_ip6)
4141
4142 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4143 out_dst_ip6)
4144 self.pg1.add_stream(pkts)
4145 self.pg_enable_capture(self.pg_interfaces)
4146 self.pg_start()
4147 capture = self.pg0.get_capture(len(pkts))
4148 self.verify_capture_in(capture, self.pg0)
4149 finally:
4150 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4151 is_add=0)
4152 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4153 self.nat_addr_n, is_add=0)
4154
4155 def test_464xlat_ce_no_nat(self):
4156 """ Test 464XLAT CE without NAT44 """
4157
4158 self.configure_xlat()
4159
4160 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4161 self.dst_ip6_pfx_len)
4162 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4163 self.src_ip6_pfx_len)
4164
4165 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4166 self.pg0.add_stream(pkts)
4167 self.pg_enable_capture(self.pg_interfaces)
4168 self.pg_start()
4169 capture = self.pg1.get_capture(len(pkts))
4170 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4171 nat_ip=out_dst_ip6, same_port=True)
4172
4173 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4174 self.pg1.add_stream(pkts)
4175 self.pg_enable_capture(self.pg_interfaces)
4176 self.pg_start()
4177 capture = self.pg0.get_capture(len(pkts))
4178 self.verify_capture_in(capture, self.pg0)
4179
4180
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004181class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004182 """ Deterministic NAT Test Cases """
4183
4184 @classmethod
4185 def setUpConstants(cls):
4186 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004187 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004188
4189 @classmethod
4190 def setUpClass(cls):
4191 super(TestDeterministicNAT, cls).setUpClass()
4192
4193 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004194 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004195 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004196 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004197 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004198 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004199 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004200
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004201 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004202 cls.interfaces = list(cls.pg_interfaces)
4203
4204 for i in cls.interfaces:
4205 i.admin_up()
4206 i.config_ip4()
4207 i.resolve_arp()
4208
Martin Gálik977c1cb2017-03-30 23:21:51 -07004209 cls.pg0.generate_remote_hosts(2)
4210 cls.pg0.configure_ipv4_neighbors()
4211
Matus Fabian066f0342017-02-10 03:48:01 -08004212 except Exception:
4213 super(TestDeterministicNAT, cls).tearDownClass()
4214 raise
4215
Martin Gálik977c1cb2017-03-30 23:21:51 -07004216 def create_stream_in(self, in_if, out_if, ttl=64):
4217 """
4218 Create packet stream for inside network
4219
4220 :param in_if: Inside interface
4221 :param out_if: Outside interface
4222 :param ttl: TTL of generated packets
4223 """
4224 pkts = []
4225 # TCP
4226 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4227 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004228 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004229 pkts.append(p)
4230
4231 # UDP
4232 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4233 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004234 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004235 pkts.append(p)
4236
4237 # ICMP
4238 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4239 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4240 ICMP(id=self.icmp_id_in, type='echo-request'))
4241 pkts.append(p)
4242
4243 return pkts
4244
4245 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4246 """
4247 Create packet stream for outside network
4248
4249 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004250 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004251 :param ttl: TTL of generated packets
4252 """
4253 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004254 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004255 pkts = []
4256 # TCP
4257 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4258 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004259 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004260 pkts.append(p)
4261
4262 # UDP
4263 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4264 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004265 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004266 pkts.append(p)
4267
4268 # ICMP
4269 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4270 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4271 ICMP(id=self.icmp_external_id, type='echo-reply'))
4272 pkts.append(p)
4273
4274 return pkts
4275
4276 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4277 """
4278 Verify captured packets on outside network
4279
4280 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004281 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004282 :param same_port: Sorce port number is not translated (Default False)
4283 :param packet_num: Expected number of packets (Default 3)
4284 """
4285 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004286 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004287 self.assertEqual(packet_num, len(capture))
4288 for packet in capture:
4289 try:
4290 self.assertEqual(packet[IP].src, nat_ip)
4291 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004292 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004293 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004294 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004295 else:
4296 self.icmp_external_id = packet[ICMP].id
4297 except:
4298 self.logger.error(ppp("Unexpected or invalid packet "
4299 "(outside network):", packet))
4300 raise
4301
4302 def initiate_tcp_session(self, in_if, out_if):
4303 """
4304 Initiates TCP session
4305
4306 :param in_if: Inside interface
4307 :param out_if: Outside interface
4308 """
4309 try:
4310 # SYN packet in->out
4311 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
4312 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004313 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004314 flags="S"))
4315 in_if.add_stream(p)
4316 self.pg_enable_capture(self.pg_interfaces)
4317 self.pg_start()
4318 capture = out_if.get_capture(1)
4319 p = capture[0]
Martin Gálik9806eae2017-04-25 01:25:08 -07004320 self.tcp_port_out = p[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004321
4322 # SYN + ACK packet out->in
4323 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004324 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004325 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004326 flags="SA"))
4327 out_if.add_stream(p)
4328 self.pg_enable_capture(self.pg_interfaces)
4329 self.pg_start()
4330 in_if.get_capture(1)
4331
4332 # ACK packet in->out
4333 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
4334 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004335 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004336 flags="A"))
4337 in_if.add_stream(p)
4338 self.pg_enable_capture(self.pg_interfaces)
4339 self.pg_start()
4340 out_if.get_capture(1)
4341
4342 except:
4343 self.logger.error("TCP 3 way handshake failed")
4344 raise
4345
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004346 def verify_ipfix_max_entries_per_user(self, data):
4347 """
4348 Verify IPFIX maximum entries per user exceeded event
4349
4350 :param data: Decoded IPFIX data records
4351 """
4352 self.assertEqual(1, len(data))
4353 record = data[0]
4354 # natEvent
4355 self.assertEqual(ord(record[230]), 13)
4356 # natQuotaExceededEvent
4357 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004358 # maxEntriesPerUser
4359 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004360 # sourceIPv4Address
4361 self.assertEqual(self.pg0.remote_ip4n, record[8])
4362
Matus Fabian066f0342017-02-10 03:48:01 -08004363 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004364 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004365 in_addr = '172.16.255.0'
4366 out_addr = '172.17.255.50'
4367 in_addr_t = '172.16.255.20'
4368 in_addr_n = socket.inet_aton(in_addr)
4369 out_addr_n = socket.inet_aton(out_addr)
4370 in_addr_t_n = socket.inet_aton(in_addr_t)
4371 in_plen = 24
4372 out_plen = 32
4373
Matus Fabian2ba92e32017-08-21 07:05:03 -07004374 nat_config = self.vapi.nat_show_config()
4375 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004376
Matus Fabian2ba92e32017-08-21 07:05:03 -07004377 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004378
Matus Fabian2ba92e32017-08-21 07:05:03 -07004379 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004380 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004381 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004382 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4383
Matus Fabian2ba92e32017-08-21 07:05:03 -07004384 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004385 self.assertEqual(len(deterministic_mappings), 1)
4386 dsm = deterministic_mappings[0]
4387 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4388 self.assertEqual(in_plen, dsm.in_plen)
4389 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4390 self.assertEqual(out_plen, dsm.out_plen)
4391
Matus Fabian2ba92e32017-08-21 07:05:03 -07004392 self.clear_nat_det()
4393 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004394 self.assertEqual(len(deterministic_mappings), 0)
4395
Matus Fabian6a0946f2017-04-12 03:36:13 -07004396 def test_set_timeouts(self):
4397 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004398 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004399
Matus Fabian2ba92e32017-08-21 07:05:03 -07004400 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4401 timeouts_before.tcp_established + 10,
4402 timeouts_before.tcp_transitory + 10,
4403 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004404
Matus Fabian2ba92e32017-08-21 07:05:03 -07004405 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004406
4407 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4408 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4409 self.assertNotEqual(timeouts_before.tcp_established,
4410 timeouts_after.tcp_established)
4411 self.assertNotEqual(timeouts_before.tcp_transitory,
4412 timeouts_after.tcp_transitory)
4413
Martin Gálik977c1cb2017-03-30 23:21:51 -07004414 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004415 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004416
4417 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004418
Matus Fabian2ba92e32017-08-21 07:05:03 -07004419 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4420 32,
4421 socket.inet_aton(nat_ip),
4422 32)
4423 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4424 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4425 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004426
4427 # in2out
4428 pkts = self.create_stream_in(self.pg0, self.pg1)
4429 self.pg0.add_stream(pkts)
4430 self.pg_enable_capture(self.pg_interfaces)
4431 self.pg_start()
4432 capture = self.pg1.get_capture(len(pkts))
4433 self.verify_capture_out(capture, nat_ip)
4434
4435 # out2in
4436 pkts = self.create_stream_out(self.pg1, nat_ip)
4437 self.pg1.add_stream(pkts)
4438 self.pg_enable_capture(self.pg_interfaces)
4439 self.pg_start()
4440 capture = self.pg0.get_capture(len(pkts))
4441 self.verify_capture_in(capture, self.pg0)
4442
Martin Gálik9806eae2017-04-25 01:25:08 -07004443 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004444 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004445 self.assertEqual(len(sessions), 3)
4446
4447 # TCP session
4448 s = sessions[0]
4449 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4450 self.assertEqual(s.in_port, self.tcp_port_in)
4451 self.assertEqual(s.out_port, self.tcp_port_out)
4452 self.assertEqual(s.ext_port, self.tcp_external_port)
4453
4454 # UDP session
4455 s = sessions[1]
4456 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4457 self.assertEqual(s.in_port, self.udp_port_in)
4458 self.assertEqual(s.out_port, self.udp_port_out)
4459 self.assertEqual(s.ext_port, self.udp_external_port)
4460
4461 # ICMP session
4462 s = sessions[2]
4463 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4464 self.assertEqual(s.in_port, self.icmp_id_in)
4465 self.assertEqual(s.out_port, self.icmp_external_id)
4466
Martin Gálik977c1cb2017-03-30 23:21:51 -07004467 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004468 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004469
4470 nat_ip = "10.0.0.10"
4471 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004472 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004473
4474 host0 = self.pg0.remote_hosts[0]
4475 host1 = self.pg0.remote_hosts[1]
4476
Matus Fabian2ba92e32017-08-21 07:05:03 -07004477 self.vapi.nat_det_add_del_map(host0.ip4n,
4478 24,
4479 socket.inet_aton(nat_ip),
4480 32)
4481 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4482 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4483 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004484
4485 # host0 to out
4486 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4487 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004488 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004489 self.pg0.add_stream(p)
4490 self.pg_enable_capture(self.pg_interfaces)
4491 self.pg_start()
4492 capture = self.pg1.get_capture(1)
4493 p = capture[0]
4494 try:
4495 ip = p[IP]
4496 tcp = p[TCP]
4497 self.assertEqual(ip.src, nat_ip)
4498 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004499 self.assertEqual(tcp.dport, external_port)
4500 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004501 except:
4502 self.logger.error(ppp("Unexpected or invalid packet:", p))
4503 raise
4504
4505 # host1 to out
4506 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4507 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004508 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004509 self.pg0.add_stream(p)
4510 self.pg_enable_capture(self.pg_interfaces)
4511 self.pg_start()
4512 capture = self.pg1.get_capture(1)
4513 p = capture[0]
4514 try:
4515 ip = p[IP]
4516 tcp = p[TCP]
4517 self.assertEqual(ip.src, nat_ip)
4518 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004519 self.assertEqual(tcp.dport, external_port)
4520 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004521 except:
4522 self.logger.error(ppp("Unexpected or invalid packet:", p))
4523 raise
4524
Matus Fabian2ba92e32017-08-21 07:05:03 -07004525 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004526 self.assertEqual(1, len(dms))
4527 self.assertEqual(2, dms[0].ses_num)
4528
4529 # out to host0
4530 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4531 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004532 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004533 self.pg1.add_stream(p)
4534 self.pg_enable_capture(self.pg_interfaces)
4535 self.pg_start()
4536 capture = self.pg0.get_capture(1)
4537 p = capture[0]
4538 try:
4539 ip = p[IP]
4540 tcp = p[TCP]
4541 self.assertEqual(ip.src, self.pg1.remote_ip4)
4542 self.assertEqual(ip.dst, host0.ip4)
4543 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004544 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004545 except:
4546 self.logger.error(ppp("Unexpected or invalid packet:", p))
4547 raise
4548
4549 # out to host1
4550 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4551 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004552 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004553 self.pg1.add_stream(p)
4554 self.pg_enable_capture(self.pg_interfaces)
4555 self.pg_start()
4556 capture = self.pg0.get_capture(1)
4557 p = capture[0]
4558 try:
4559 ip = p[IP]
4560 tcp = p[TCP]
4561 self.assertEqual(ip.src, self.pg1.remote_ip4)
4562 self.assertEqual(ip.dst, host1.ip4)
4563 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004564 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004565 except:
4566 self.logger.error(ppp("Unexpected or invalid packet", p))
4567 raise
4568
Martin Gálik6bc8c642017-04-19 01:12:27 -07004569 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004570 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4571 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004572 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004573 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004574 dms = self.vapi.nat_det_map_dump()
4575 self.assertEqual(dms[0].ses_num, 1)
4576
4577 self.vapi.nat_det_close_session_in(host0.ip4n,
4578 port_in,
4579 self.pg1.remote_ip4n,
4580 external_port)
4581 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004582 self.assertEqual(dms[0].ses_num, 0)
4583
Martin Gálik977c1cb2017-03-30 23:21:51 -07004584 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004585 """ Deterministic NAT TCP session close from inside network """
4586 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4587 32,
4588 socket.inet_aton(self.nat_addr),
4589 32)
4590 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4591 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4592 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004593
4594 self.initiate_tcp_session(self.pg0, self.pg1)
4595
4596 # close the session from inside
4597 try:
4598 # FIN packet in -> out
4599 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4600 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004601 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004602 flags="F"))
4603 self.pg0.add_stream(p)
4604 self.pg_enable_capture(self.pg_interfaces)
4605 self.pg_start()
4606 self.pg1.get_capture(1)
4607
4608 pkts = []
4609
4610 # ACK packet out -> in
4611 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004612 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004613 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004614 flags="A"))
4615 pkts.append(p)
4616
4617 # FIN packet out -> in
4618 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004619 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004620 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004621 flags="F"))
4622 pkts.append(p)
4623
4624 self.pg1.add_stream(pkts)
4625 self.pg_enable_capture(self.pg_interfaces)
4626 self.pg_start()
4627 self.pg0.get_capture(2)
4628
4629 # ACK packet in -> out
4630 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4631 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004632 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004633 flags="A"))
4634 self.pg0.add_stream(p)
4635 self.pg_enable_capture(self.pg_interfaces)
4636 self.pg_start()
4637 self.pg1.get_capture(1)
4638
Matus Fabian2ba92e32017-08-21 07:05:03 -07004639 # Check if deterministic NAT44 closed the session
4640 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004641 self.assertEqual(0, dms[0].ses_num)
4642 except:
4643 self.logger.error("TCP session termination failed")
4644 raise
4645
4646 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004647 """ Deterministic NAT TCP session close from outside network """
4648 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4649 32,
4650 socket.inet_aton(self.nat_addr),
4651 32)
4652 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4653 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4654 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004655
4656 self.initiate_tcp_session(self.pg0, self.pg1)
4657
4658 # close the session from outside
4659 try:
4660 # FIN packet out -> in
4661 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004662 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004663 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004664 flags="F"))
4665 self.pg1.add_stream(p)
4666 self.pg_enable_capture(self.pg_interfaces)
4667 self.pg_start()
4668 self.pg0.get_capture(1)
4669
4670 pkts = []
4671
4672 # ACK packet in -> out
4673 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4674 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004675 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004676 flags="A"))
4677 pkts.append(p)
4678
4679 # ACK packet in -> out
4680 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4681 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004682 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004683 flags="F"))
4684 pkts.append(p)
4685
4686 self.pg0.add_stream(pkts)
4687 self.pg_enable_capture(self.pg_interfaces)
4688 self.pg_start()
4689 self.pg1.get_capture(2)
4690
4691 # ACK packet out -> in
4692 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004693 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004694 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004695 flags="A"))
4696 self.pg1.add_stream(p)
4697 self.pg_enable_capture(self.pg_interfaces)
4698 self.pg_start()
4699 self.pg0.get_capture(1)
4700
Matus Fabian2ba92e32017-08-21 07:05:03 -07004701 # Check if deterministic NAT44 closed the session
4702 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004703 self.assertEqual(0, dms[0].ses_num)
4704 except:
4705 self.logger.error("TCP session termination failed")
4706 raise
4707
4708 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4709 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004710 """ Deterministic NAT session timeouts """
4711 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4712 32,
4713 socket.inet_aton(self.nat_addr),
4714 32)
4715 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4716 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4717 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004718
4719 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004720 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004721 pkts = self.create_stream_in(self.pg0, self.pg1)
4722 self.pg0.add_stream(pkts)
4723 self.pg_enable_capture(self.pg_interfaces)
4724 self.pg_start()
4725 capture = self.pg1.get_capture(len(pkts))
4726 sleep(15)
4727
Matus Fabian2ba92e32017-08-21 07:05:03 -07004728 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004729 self.assertEqual(0, dms[0].ses_num)
4730
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004731 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004732 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004733 """ Deterministic NAT maximum sessions per user limit """
4734 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4735 32,
4736 socket.inet_aton(self.nat_addr),
4737 32)
4738 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4739 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4740 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004741 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4742 src_address=self.pg2.local_ip4n,
4743 path_mtu=512,
4744 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004745 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004746
4747 pkts = []
4748 for port in range(1025, 2025):
4749 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4750 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4751 UDP(sport=port, dport=port))
4752 pkts.append(p)
4753
4754 self.pg0.add_stream(pkts)
4755 self.pg_enable_capture(self.pg_interfaces)
4756 self.pg_start()
4757 capture = self.pg1.get_capture(len(pkts))
4758
4759 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4760 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07004761 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004762 self.pg0.add_stream(p)
4763 self.pg_enable_capture(self.pg_interfaces)
4764 self.pg_start()
4765 capture = self.pg1.assert_nothing_captured()
4766
Martin Gálikf7e655d2017-04-27 02:13:26 -07004767 # verify ICMP error packet
4768 capture = self.pg0.get_capture(1)
4769 p = capture[0]
4770 self.assertTrue(p.haslayer(ICMP))
4771 icmp = p[ICMP]
4772 self.assertEqual(icmp.type, 3)
4773 self.assertEqual(icmp.code, 1)
4774 self.assertTrue(icmp.haslayer(IPerror))
4775 inner_ip = icmp[IPerror]
4776 self.assertEqual(inner_ip[UDPerror].sport, 3001)
4777 self.assertEqual(inner_ip[UDPerror].dport, 3002)
4778
Matus Fabian2ba92e32017-08-21 07:05:03 -07004779 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004780
4781 self.assertEqual(1000, dms[0].ses_num)
4782
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004783 # verify IPFIX logging
4784 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004785 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004786 capture = self.pg2.get_capture(2)
4787 ipfix = IPFIXDecoder()
4788 # first load template
4789 for p in capture:
4790 self.assertTrue(p.haslayer(IPFIX))
4791 if p.haslayer(Template):
4792 ipfix.add_template(p.getlayer(Template))
4793 # verify events in data set
4794 for p in capture:
4795 if p.haslayer(Data):
4796 data = ipfix.decode_data_set(p.getlayer(Set))
4797 self.verify_ipfix_max_entries_per_user(data)
4798
Matus Fabian2ba92e32017-08-21 07:05:03 -07004799 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08004800 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004801 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08004802 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004803 self.vapi.nat_ipfix(enable=0)
4804 self.vapi.nat_det_set_timeouts()
4805 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004806 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004807 self.vapi.nat_det_add_del_map(dsm.in_addr,
4808 dsm.in_plen,
4809 dsm.out_addr,
4810 dsm.out_plen,
4811 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08004812
Matus Fabian2ba92e32017-08-21 07:05:03 -07004813 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004814 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004815 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
4816 intf.is_inside,
4817 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004818
Matus Fabian066f0342017-02-10 03:48:01 -08004819 def tearDown(self):
4820 super(TestDeterministicNAT, self).tearDown()
4821 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004822 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4823 self.logger.info(
4824 self.vapi.cli("show nat44 deterministic mappings"))
4825 self.logger.info(
4826 self.vapi.cli("show nat44 deterministic timeouts"))
4827 self.logger.info(
4828 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07004829 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08004830
Matus Fabian06596c52017-06-06 04:53:28 -07004831
4832class TestNAT64(MethodHolder):
4833 """ NAT64 Test Cases """
4834
4835 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08004836 def setUpConstants(cls):
4837 super(TestNAT64, cls).setUpConstants()
4838 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
4839 "nat64 st hash buckets 256", "}"])
4840
4841 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07004842 def setUpClass(cls):
4843 super(TestNAT64, cls).setUpClass()
4844
4845 try:
4846 cls.tcp_port_in = 6303
4847 cls.tcp_port_out = 6303
4848 cls.udp_port_in = 6304
4849 cls.udp_port_out = 6304
4850 cls.icmp_id_in = 6305
4851 cls.icmp_id_out = 6305
4852 cls.nat_addr = '10.0.0.3'
4853 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07004854 cls.vrf1_id = 10
4855 cls.vrf1_nat_addr = '10.0.10.3'
4856 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
4857 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08004858 cls.ipfix_src_port = 4739
4859 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07004860
Matus Fabian0938dcf2017-11-08 01:59:38 -08004861 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07004862 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07004863 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07004864 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
4865
Neale Ranns15002542017-09-10 04:39:11 -07004866 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
4867
Matus Fabian029f3d22017-06-15 02:28:50 -07004868 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
4869
4870 cls.pg0.generate_remote_hosts(2)
4871
Matus Fabian06596c52017-06-06 04:53:28 -07004872 for i in cls.ip6_interfaces:
4873 i.admin_up()
4874 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07004875 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07004876
4877 for i in cls.ip4_interfaces:
4878 i.admin_up()
4879 i.config_ip4()
4880 i.resolve_arp()
4881
Matus Fabian36ea2d62017-10-24 04:13:49 -07004882 cls.pg3.admin_up()
4883 cls.pg3.config_ip4()
4884 cls.pg3.resolve_arp()
4885 cls.pg3.config_ip6()
4886 cls.pg3.configure_ipv6_neighbors()
4887
Matus Fabian06596c52017-06-06 04:53:28 -07004888 except Exception:
4889 super(TestNAT64, cls).tearDownClass()
4890 raise
4891
4892 def test_pool(self):
4893 """ Add/delete address to NAT64 pool """
4894 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
4895
4896 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
4897
4898 addresses = self.vapi.nat64_pool_addr_dump()
4899 self.assertEqual(len(addresses), 1)
4900 self.assertEqual(addresses[0].address, nat_addr)
4901
4902 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
4903
4904 addresses = self.vapi.nat64_pool_addr_dump()
4905 self.assertEqual(len(addresses), 0)
4906
4907 def test_interface(self):
4908 """ Enable/disable NAT64 feature on the interface """
4909 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
4910 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
4911
4912 interfaces = self.vapi.nat64_interface_dump()
4913 self.assertEqual(len(interfaces), 2)
4914 pg0_found = False
4915 pg1_found = False
4916 for intf in interfaces:
4917 if intf.sw_if_index == self.pg0.sw_if_index:
4918 self.assertEqual(intf.is_inside, 1)
4919 pg0_found = True
4920 elif intf.sw_if_index == self.pg1.sw_if_index:
4921 self.assertEqual(intf.is_inside, 0)
4922 pg1_found = True
4923 self.assertTrue(pg0_found)
4924 self.assertTrue(pg1_found)
4925
4926 features = self.vapi.cli("show interface features pg0")
4927 self.assertNotEqual(features.find('nat64-in2out'), -1)
4928 features = self.vapi.cli("show interface features pg1")
4929 self.assertNotEqual(features.find('nat64-out2in'), -1)
4930
4931 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
4932 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
4933
4934 interfaces = self.vapi.nat64_interface_dump()
4935 self.assertEqual(len(interfaces), 0)
4936
4937 def test_static_bib(self):
4938 """ Add/delete static BIB entry """
4939 in_addr = socket.inet_pton(socket.AF_INET6,
4940 '2001:db8:85a3::8a2e:370:7334')
4941 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
4942 in_port = 1234
4943 out_port = 5678
4944 proto = IP_PROTOS.tcp
4945
4946 self.vapi.nat64_add_del_static_bib(in_addr,
4947 out_addr,
4948 in_port,
4949 out_port,
4950 proto)
4951 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
4952 static_bib_num = 0
4953 for bibe in bib:
4954 if bibe.is_static:
4955 static_bib_num += 1
4956 self.assertEqual(bibe.i_addr, in_addr)
4957 self.assertEqual(bibe.o_addr, out_addr)
4958 self.assertEqual(bibe.i_port, in_port)
4959 self.assertEqual(bibe.o_port, out_port)
4960 self.assertEqual(static_bib_num, 1)
4961
4962 self.vapi.nat64_add_del_static_bib(in_addr,
4963 out_addr,
4964 in_port,
4965 out_port,
4966 proto,
4967 is_add=0)
4968 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
4969 static_bib_num = 0
4970 for bibe in bib:
4971 if bibe.is_static:
4972 static_bib_num += 1
4973 self.assertEqual(static_bib_num, 0)
4974
4975 def test_set_timeouts(self):
4976 """ Set NAT64 timeouts """
4977 # verify default values
4978 timeouts = self.vapi.nat64_get_timeouts()
4979 self.assertEqual(timeouts.udp, 300)
4980 self.assertEqual(timeouts.icmp, 60)
4981 self.assertEqual(timeouts.tcp_trans, 240)
4982 self.assertEqual(timeouts.tcp_est, 7440)
4983 self.assertEqual(timeouts.tcp_incoming_syn, 6)
4984
4985 # set and verify custom values
4986 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
4987 tcp_est=7450, tcp_incoming_syn=10)
4988 timeouts = self.vapi.nat64_get_timeouts()
4989 self.assertEqual(timeouts.udp, 200)
4990 self.assertEqual(timeouts.icmp, 30)
4991 self.assertEqual(timeouts.tcp_trans, 250)
4992 self.assertEqual(timeouts.tcp_est, 7450)
4993 self.assertEqual(timeouts.tcp_incoming_syn, 10)
4994
4995 def test_dynamic(self):
4996 """ NAT64 dynamic translation test """
4997 self.tcp_port_in = 6303
4998 self.udp_port_in = 6304
4999 self.icmp_id_in = 6305
5000
5001 ses_num_start = self.nat64_get_ses_num()
5002
5003 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5004 self.nat_addr_n)
5005 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5006 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5007
5008 # in2out
5009 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5010 self.pg0.add_stream(pkts)
5011 self.pg_enable_capture(self.pg_interfaces)
5012 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005013 capture = self.pg1.get_capture(len(pkts))
5014 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005015 dst_ip=self.pg1.remote_ip4)
5016
5017 # out2in
5018 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5019 self.pg1.add_stream(pkts)
5020 self.pg_enable_capture(self.pg_interfaces)
5021 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005022 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005023 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5024 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5025
5026 # in2out
5027 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5028 self.pg0.add_stream(pkts)
5029 self.pg_enable_capture(self.pg_interfaces)
5030 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005031 capture = self.pg1.get_capture(len(pkts))
5032 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005033 dst_ip=self.pg1.remote_ip4)
5034
5035 # out2in
5036 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5037 self.pg1.add_stream(pkts)
5038 self.pg_enable_capture(self.pg_interfaces)
5039 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005040 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005041 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5042
5043 ses_num_end = self.nat64_get_ses_num()
5044
5045 self.assertEqual(ses_num_end - ses_num_start, 3)
5046
Matus Fabian029f3d22017-06-15 02:28:50 -07005047 # tenant with specific VRF
5048 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5049 self.vrf1_nat_addr_n,
5050 vrf_id=self.vrf1_id)
5051 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5052
5053 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5054 self.pg2.add_stream(pkts)
5055 self.pg_enable_capture(self.pg_interfaces)
5056 self.pg_start()
5057 capture = self.pg1.get_capture(len(pkts))
5058 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5059 dst_ip=self.pg1.remote_ip4)
5060
5061 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5062 self.pg1.add_stream(pkts)
5063 self.pg_enable_capture(self.pg_interfaces)
5064 self.pg_start()
5065 capture = self.pg2.get_capture(len(pkts))
5066 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5067
Matus Fabian06596c52017-06-06 04:53:28 -07005068 def test_static(self):
5069 """ NAT64 static translation test """
5070 self.tcp_port_in = 60303
5071 self.udp_port_in = 60304
5072 self.icmp_id_in = 60305
5073 self.tcp_port_out = 60303
5074 self.udp_port_out = 60304
5075 self.icmp_id_out = 60305
5076
5077 ses_num_start = self.nat64_get_ses_num()
5078
5079 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5080 self.nat_addr_n)
5081 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5082 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5083
5084 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5085 self.nat_addr_n,
5086 self.tcp_port_in,
5087 self.tcp_port_out,
5088 IP_PROTOS.tcp)
5089 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5090 self.nat_addr_n,
5091 self.udp_port_in,
5092 self.udp_port_out,
5093 IP_PROTOS.udp)
5094 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5095 self.nat_addr_n,
5096 self.icmp_id_in,
5097 self.icmp_id_out,
5098 IP_PROTOS.icmp)
5099
5100 # in2out
5101 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5102 self.pg0.add_stream(pkts)
5103 self.pg_enable_capture(self.pg_interfaces)
5104 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005105 capture = self.pg1.get_capture(len(pkts))
5106 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005107 dst_ip=self.pg1.remote_ip4, same_port=True)
5108
5109 # out2in
5110 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5111 self.pg1.add_stream(pkts)
5112 self.pg_enable_capture(self.pg_interfaces)
5113 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005114 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005115 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5116 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5117
5118 ses_num_end = self.nat64_get_ses_num()
5119
5120 self.assertEqual(ses_num_end - ses_num_start, 3)
5121
5122 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5123 def test_session_timeout(self):
5124 """ NAT64 session timeout """
5125 self.icmp_id_in = 1234
5126 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5127 self.nat_addr_n)
5128 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5129 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5130 self.vapi.nat64_set_timeouts(icmp=5)
5131
5132 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5133 self.pg0.add_stream(pkts)
5134 self.pg_enable_capture(self.pg_interfaces)
5135 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005136 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005137
5138 ses_num_before_timeout = self.nat64_get_ses_num()
5139
5140 sleep(15)
5141
5142 # ICMP session after timeout
5143 ses_num_after_timeout = self.nat64_get_ses_num()
5144 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5145
Matus Fabian732036d2017-06-08 05:24:28 -07005146 def test_icmp_error(self):
5147 """ NAT64 ICMP Error message translation """
5148 self.tcp_port_in = 6303
5149 self.udp_port_in = 6304
5150 self.icmp_id_in = 6305
5151
5152 ses_num_start = self.nat64_get_ses_num()
5153
5154 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5155 self.nat_addr_n)
5156 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5157 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5158
5159 # send some packets to create sessions
5160 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5161 self.pg0.add_stream(pkts)
5162 self.pg_enable_capture(self.pg_interfaces)
5163 self.pg_start()
5164 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005165 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005166 nat_ip=self.nat_addr,
5167 dst_ip=self.pg1.remote_ip4)
5168
5169 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5170 self.pg1.add_stream(pkts)
5171 self.pg_enable_capture(self.pg_interfaces)
5172 self.pg_start()
5173 capture_ip6 = self.pg0.get_capture(len(pkts))
5174 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5175 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5176 self.pg0.remote_ip6)
5177
5178 # in2out
5179 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5180 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5181 ICMPv6DestUnreach(code=1) /
5182 packet[IPv6] for packet in capture_ip6]
5183 self.pg0.add_stream(pkts)
5184 self.pg_enable_capture(self.pg_interfaces)
5185 self.pg_start()
5186 capture = self.pg1.get_capture(len(pkts))
5187 for packet in capture:
5188 try:
5189 self.assertEqual(packet[IP].src, self.nat_addr)
5190 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5191 self.assertEqual(packet[ICMP].type, 3)
5192 self.assertEqual(packet[ICMP].code, 13)
5193 inner = packet[IPerror]
5194 self.assertEqual(inner.src, self.pg1.remote_ip4)
5195 self.assertEqual(inner.dst, self.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005196 self.check_icmp_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005197 if inner.haslayer(TCPerror):
5198 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5199 elif inner.haslayer(UDPerror):
5200 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5201 else:
5202 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5203 except:
5204 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5205 raise
5206
5207 # out2in
5208 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5209 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5210 ICMP(type=3, code=13) /
5211 packet[IP] for packet in capture_ip4]
5212 self.pg1.add_stream(pkts)
5213 self.pg_enable_capture(self.pg_interfaces)
5214 self.pg_start()
5215 capture = self.pg0.get_capture(len(pkts))
5216 for packet in capture:
5217 try:
5218 self.assertEqual(packet[IPv6].src, ip.src)
5219 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5220 icmp = packet[ICMPv6DestUnreach]
5221 self.assertEqual(icmp.code, 1)
5222 inner = icmp[IPerror6]
5223 self.assertEqual(inner.src, self.pg0.remote_ip6)
5224 self.assertEqual(inner.dst, ip.src)
Matus Fabian029f3d22017-06-15 02:28:50 -07005225 self.check_icmpv6_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005226 if inner.haslayer(TCPerror):
5227 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5228 elif inner.haslayer(UDPerror):
5229 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5230 else:
5231 self.assertEqual(inner[ICMPv6EchoRequest].id,
5232 self.icmp_id_in)
5233 except:
5234 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5235 raise
5236
Matus Fabian029f3d22017-06-15 02:28:50 -07005237 def test_hairpinning(self):
5238 """ NAT64 hairpinning """
5239
5240 client = self.pg0.remote_hosts[0]
5241 server = self.pg0.remote_hosts[1]
5242 server_tcp_in_port = 22
5243 server_tcp_out_port = 4022
5244 server_udp_in_port = 23
5245 server_udp_out_port = 4023
5246 client_tcp_in_port = 1234
5247 client_udp_in_port = 1235
5248 client_tcp_out_port = 0
5249 client_udp_out_port = 0
5250 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5251 nat_addr_ip6 = ip.src
5252
5253 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5254 self.nat_addr_n)
5255 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5256 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5257
5258 self.vapi.nat64_add_del_static_bib(server.ip6n,
5259 self.nat_addr_n,
5260 server_tcp_in_port,
5261 server_tcp_out_port,
5262 IP_PROTOS.tcp)
5263 self.vapi.nat64_add_del_static_bib(server.ip6n,
5264 self.nat_addr_n,
5265 server_udp_in_port,
5266 server_udp_out_port,
5267 IP_PROTOS.udp)
5268
5269 # client to server
5270 pkts = []
5271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5272 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5273 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5274 pkts.append(p)
5275 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5276 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5277 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5278 pkts.append(p)
5279 self.pg0.add_stream(pkts)
5280 self.pg_enable_capture(self.pg_interfaces)
5281 self.pg_start()
5282 capture = self.pg0.get_capture(len(pkts))
5283 for packet in capture:
5284 try:
5285 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5286 self.assertEqual(packet[IPv6].dst, server.ip6)
5287 if packet.haslayer(TCP):
5288 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5289 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
5290 self.check_tcp_checksum(packet)
5291 client_tcp_out_port = packet[TCP].sport
5292 else:
5293 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5294 self.assertEqual(packet[UDP].dport, server_udp_in_port)
5295 self.check_udp_checksum(packet)
5296 client_udp_out_port = packet[UDP].sport
5297 except:
5298 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5299 raise
5300
5301 # server to client
5302 pkts = []
5303 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5304 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5305 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5306 pkts.append(p)
5307 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5308 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5309 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5310 pkts.append(p)
5311 self.pg0.add_stream(pkts)
5312 self.pg_enable_capture(self.pg_interfaces)
5313 self.pg_start()
5314 capture = self.pg0.get_capture(len(pkts))
5315 for packet in capture:
5316 try:
5317 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5318 self.assertEqual(packet[IPv6].dst, client.ip6)
5319 if packet.haslayer(TCP):
5320 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5321 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
5322 self.check_tcp_checksum(packet)
5323 else:
5324 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5325 self.assertEqual(packet[UDP].dport, client_udp_in_port)
5326 self.check_udp_checksum(packet)
5327 except:
5328 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5329 raise
5330
5331 # ICMP error
5332 pkts = []
5333 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5334 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5335 ICMPv6DestUnreach(code=1) /
5336 packet[IPv6] for packet in capture]
5337 self.pg0.add_stream(pkts)
5338 self.pg_enable_capture(self.pg_interfaces)
5339 self.pg_start()
5340 capture = self.pg0.get_capture(len(pkts))
5341 for packet in capture:
5342 try:
5343 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5344 self.assertEqual(packet[IPv6].dst, server.ip6)
5345 icmp = packet[ICMPv6DestUnreach]
5346 self.assertEqual(icmp.code, 1)
5347 inner = icmp[IPerror6]
5348 self.assertEqual(inner.src, server.ip6)
5349 self.assertEqual(inner.dst, nat_addr_ip6)
5350 self.check_icmpv6_checksum(packet)
5351 if inner.haslayer(TCPerror):
5352 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5353 self.assertEqual(inner[TCPerror].dport,
5354 client_tcp_out_port)
5355 else:
5356 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5357 self.assertEqual(inner[UDPerror].dport,
5358 client_udp_out_port)
5359 except:
5360 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5361 raise
5362
Matus Fabian428dc912017-06-21 06:15:18 -07005363 def test_prefix(self):
5364 """ NAT64 Network-Specific Prefix """
5365
5366 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5367 self.nat_addr_n)
5368 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5369 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5370 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5371 self.vrf1_nat_addr_n,
5372 vrf_id=self.vrf1_id)
5373 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5374
5375 # Add global prefix
5376 global_pref64 = "2001:db8::"
5377 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5378 global_pref64_len = 32
5379 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5380
5381 prefix = self.vapi.nat64_prefix_dump()
5382 self.assertEqual(len(prefix), 1)
5383 self.assertEqual(prefix[0].prefix, global_pref64_n)
5384 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5385 self.assertEqual(prefix[0].vrf_id, 0)
5386
5387 # Add tenant specific prefix
5388 vrf1_pref64 = "2001:db8:122:300::"
5389 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5390 vrf1_pref64_len = 56
5391 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5392 vrf1_pref64_len,
5393 vrf_id=self.vrf1_id)
5394 prefix = self.vapi.nat64_prefix_dump()
5395 self.assertEqual(len(prefix), 2)
5396
5397 # Global prefix
5398 pkts = self.create_stream_in_ip6(self.pg0,
5399 self.pg1,
5400 pref=global_pref64,
5401 plen=global_pref64_len)
5402 self.pg0.add_stream(pkts)
5403 self.pg_enable_capture(self.pg_interfaces)
5404 self.pg_start()
5405 capture = self.pg1.get_capture(len(pkts))
5406 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5407 dst_ip=self.pg1.remote_ip4)
5408
5409 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5410 self.pg1.add_stream(pkts)
5411 self.pg_enable_capture(self.pg_interfaces)
5412 self.pg_start()
5413 capture = self.pg0.get_capture(len(pkts))
5414 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5415 global_pref64,
5416 global_pref64_len)
5417 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5418
5419 # Tenant specific prefix
5420 pkts = self.create_stream_in_ip6(self.pg2,
5421 self.pg1,
5422 pref=vrf1_pref64,
5423 plen=vrf1_pref64_len)
5424 self.pg2.add_stream(pkts)
5425 self.pg_enable_capture(self.pg_interfaces)
5426 self.pg_start()
5427 capture = self.pg1.get_capture(len(pkts))
5428 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5429 dst_ip=self.pg1.remote_ip4)
5430
5431 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5432 self.pg1.add_stream(pkts)
5433 self.pg_enable_capture(self.pg_interfaces)
5434 self.pg_start()
5435 capture = self.pg2.get_capture(len(pkts))
5436 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5437 vrf1_pref64,
5438 vrf1_pref64_len)
5439 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5440
Matus Fabianf8cd5812017-07-11 03:55:02 -07005441 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005442 """ NAT64 translate packet with unknown protocol """
5443
5444 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5445 self.nat_addr_n)
5446 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5447 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5448 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5449
5450 # in2out
5451 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5452 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5453 TCP(sport=self.tcp_port_in, dport=20))
5454 self.pg0.add_stream(p)
5455 self.pg_enable_capture(self.pg_interfaces)
5456 self.pg_start()
5457 p = self.pg1.get_capture(1)
5458
5459 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005460 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005461 GRE() /
5462 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5463 TCP(sport=1234, dport=1234))
5464 self.pg0.add_stream(p)
5465 self.pg_enable_capture(self.pg_interfaces)
5466 self.pg_start()
5467 p = self.pg1.get_capture(1)
5468 packet = p[0]
5469 try:
5470 self.assertEqual(packet[IP].src, self.nat_addr)
5471 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5472 self.assertTrue(packet.haslayer(GRE))
5473 self.check_ip_checksum(packet)
5474 except:
5475 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5476 raise
5477
5478 # out2in
5479 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5480 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5481 GRE() /
5482 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5483 TCP(sport=1234, dport=1234))
5484 self.pg1.add_stream(p)
5485 self.pg_enable_capture(self.pg_interfaces)
5486 self.pg_start()
5487 p = self.pg0.get_capture(1)
5488 packet = p[0]
5489 try:
5490 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005491 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5492 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005493 except:
5494 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5495 raise
5496
Matus Fabianf8cd5812017-07-11 03:55:02 -07005497 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005498 """ NAT64 translate packet with unknown protocol - hairpinning """
5499
5500 client = self.pg0.remote_hosts[0]
5501 server = self.pg0.remote_hosts[1]
5502 server_tcp_in_port = 22
5503 server_tcp_out_port = 4022
5504 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005505 client_tcp_out_port = 1235
5506 server_nat_ip = "10.0.0.100"
5507 client_nat_ip = "10.0.0.110"
5508 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5509 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5510 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5511 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005512
Matus Fabianf8cd5812017-07-11 03:55:02 -07005513 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5514 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005515 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5516 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5517
5518 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005519 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005520 server_tcp_in_port,
5521 server_tcp_out_port,
5522 IP_PROTOS.tcp)
5523
Matus Fabianf8cd5812017-07-11 03:55:02 -07005524 self.vapi.nat64_add_del_static_bib(server.ip6n,
5525 server_nat_ip_n,
5526 0,
5527 0,
5528 IP_PROTOS.gre)
5529
5530 self.vapi.nat64_add_del_static_bib(client.ip6n,
5531 client_nat_ip_n,
5532 client_tcp_in_port,
5533 client_tcp_out_port,
5534 IP_PROTOS.tcp)
5535
Matus Fabian7968e6c2017-07-06 05:37:49 -07005536 # client to server
5537 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005538 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005539 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5540 self.pg0.add_stream(p)
5541 self.pg_enable_capture(self.pg_interfaces)
5542 self.pg_start()
5543 p = self.pg0.get_capture(1)
5544
5545 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005546 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005547 GRE() /
5548 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5549 TCP(sport=1234, dport=1234))
5550 self.pg0.add_stream(p)
5551 self.pg_enable_capture(self.pg_interfaces)
5552 self.pg_start()
5553 p = self.pg0.get_capture(1)
5554 packet = p[0]
5555 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005556 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005557 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005558 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005559 except:
5560 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5561 raise
5562
5563 # server to client
5564 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005565 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005566 GRE() /
5567 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5568 TCP(sport=1234, dport=1234))
5569 self.pg0.add_stream(p)
5570 self.pg_enable_capture(self.pg_interfaces)
5571 self.pg_start()
5572 p = self.pg0.get_capture(1)
5573 packet = p[0]
5574 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005575 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005576 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005577 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005578 except:
5579 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5580 raise
5581
Matus Fabian36ea2d62017-10-24 04:13:49 -07005582 def test_one_armed_nat64(self):
5583 """ One armed NAT64 """
5584 external_port = 0
5585 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5586 '64:ff9b::',
5587 96)
5588
5589 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5590 self.nat_addr_n)
5591 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5592 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5593
5594 # in2out
5595 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5596 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5597 TCP(sport=12345, dport=80))
5598 self.pg3.add_stream(p)
5599 self.pg_enable_capture(self.pg_interfaces)
5600 self.pg_start()
5601 capture = self.pg3.get_capture(1)
5602 p = capture[0]
5603 try:
5604 ip = p[IP]
5605 tcp = p[TCP]
5606 self.assertEqual(ip.src, self.nat_addr)
5607 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5608 self.assertNotEqual(tcp.sport, 12345)
5609 external_port = tcp.sport
5610 self.assertEqual(tcp.dport, 80)
5611 self.check_tcp_checksum(p)
5612 self.check_ip_checksum(p)
5613 except:
5614 self.logger.error(ppp("Unexpected or invalid packet:", p))
5615 raise
5616
5617 # out2in
5618 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5619 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5620 TCP(sport=80, dport=external_port))
5621 self.pg3.add_stream(p)
5622 self.pg_enable_capture(self.pg_interfaces)
5623 self.pg_start()
5624 capture = self.pg3.get_capture(1)
5625 p = capture[0]
5626 try:
5627 ip = p[IPv6]
5628 tcp = p[TCP]
5629 self.assertEqual(ip.src, remote_host_ip6)
5630 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5631 self.assertEqual(tcp.sport, 80)
5632 self.assertEqual(tcp.dport, 12345)
5633 self.check_tcp_checksum(p)
5634 except:
5635 self.logger.error(ppp("Unexpected or invalid packet:", p))
5636 raise
5637
Matus Fabianefcd1e92017-08-15 06:59:19 -07005638 def test_frag_in_order(self):
5639 """ NAT64 translate fragments arriving in order """
5640 self.tcp_port_in = random.randint(1025, 65535)
5641
5642 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5643 self.nat_addr_n)
5644 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5645 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5646
5647 reass = self.vapi.nat_reass_dump()
5648 reass_n_start = len(reass)
5649
5650 # in2out
5651 data = 'a' * 200
5652 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5653 self.tcp_port_in, 20, data)
5654 self.pg0.add_stream(pkts)
5655 self.pg_enable_capture(self.pg_interfaces)
5656 self.pg_start()
5657 frags = self.pg1.get_capture(len(pkts))
5658 p = self.reass_frags_and_verify(frags,
5659 self.nat_addr,
5660 self.pg1.remote_ip4)
5661 self.assertEqual(p[TCP].dport, 20)
5662 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5663 self.tcp_port_out = p[TCP].sport
5664 self.assertEqual(data, p[Raw].load)
5665
5666 # out2in
5667 data = "A" * 4 + "b" * 16 + "C" * 3
5668 pkts = self.create_stream_frag(self.pg1,
5669 self.nat_addr,
5670 20,
5671 self.tcp_port_out,
5672 data)
5673 self.pg1.add_stream(pkts)
5674 self.pg_enable_capture(self.pg_interfaces)
5675 self.pg_start()
5676 frags = self.pg0.get_capture(len(pkts))
5677 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5678 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5679 self.assertEqual(p[TCP].sport, 20)
5680 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5681 self.assertEqual(data, p[Raw].load)
5682
5683 reass = self.vapi.nat_reass_dump()
5684 reass_n_end = len(reass)
5685
5686 self.assertEqual(reass_n_end - reass_n_start, 2)
5687
5688 def test_reass_hairpinning(self):
5689 """ NAT64 fragments hairpinning """
5690 data = 'a' * 200
5691 client = self.pg0.remote_hosts[0]
5692 server = self.pg0.remote_hosts[1]
5693 server_in_port = random.randint(1025, 65535)
5694 server_out_port = random.randint(1025, 65535)
5695 client_in_port = random.randint(1025, 65535)
5696 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5697 nat_addr_ip6 = ip.src
5698
5699 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5700 self.nat_addr_n)
5701 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5702 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5703
5704 # add static BIB entry for server
5705 self.vapi.nat64_add_del_static_bib(server.ip6n,
5706 self.nat_addr_n,
5707 server_in_port,
5708 server_out_port,
5709 IP_PROTOS.tcp)
5710
5711 # send packet from host to server
5712 pkts = self.create_stream_frag_ip6(self.pg0,
5713 self.nat_addr,
5714 client_in_port,
5715 server_out_port,
5716 data)
5717 self.pg0.add_stream(pkts)
5718 self.pg_enable_capture(self.pg_interfaces)
5719 self.pg_start()
5720 frags = self.pg0.get_capture(len(pkts))
5721 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5722 self.assertNotEqual(p[TCP].sport, client_in_port)
5723 self.assertEqual(p[TCP].dport, server_in_port)
5724 self.assertEqual(data, p[Raw].load)
5725
5726 def test_frag_out_of_order(self):
5727 """ NAT64 translate fragments arriving out of order """
5728 self.tcp_port_in = random.randint(1025, 65535)
5729
5730 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5731 self.nat_addr_n)
5732 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5733 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5734
5735 # in2out
5736 data = 'a' * 200
5737 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5738 self.tcp_port_in, 20, data)
5739 pkts.reverse()
5740 self.pg0.add_stream(pkts)
5741 self.pg_enable_capture(self.pg_interfaces)
5742 self.pg_start()
5743 frags = self.pg1.get_capture(len(pkts))
5744 p = self.reass_frags_and_verify(frags,
5745 self.nat_addr,
5746 self.pg1.remote_ip4)
5747 self.assertEqual(p[TCP].dport, 20)
5748 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5749 self.tcp_port_out = p[TCP].sport
5750 self.assertEqual(data, p[Raw].load)
5751
5752 # out2in
5753 data = "A" * 4 + "B" * 16 + "C" * 3
5754 pkts = self.create_stream_frag(self.pg1,
5755 self.nat_addr,
5756 20,
5757 self.tcp_port_out,
5758 data)
5759 pkts.reverse()
5760 self.pg1.add_stream(pkts)
5761 self.pg_enable_capture(self.pg_interfaces)
5762 self.pg_start()
5763 frags = self.pg0.get_capture(len(pkts))
5764 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5765 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5766 self.assertEqual(p[TCP].sport, 20)
5767 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5768 self.assertEqual(data, p[Raw].load)
5769
Matus Fabian0938dcf2017-11-08 01:59:38 -08005770 def test_interface_addr(self):
5771 """ Acquire NAT64 pool addresses from interface """
5772 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5773
5774 # no address in NAT64 pool
5775 adresses = self.vapi.nat44_address_dump()
5776 self.assertEqual(0, len(adresses))
5777
5778 # configure interface address and check NAT64 address pool
5779 self.pg4.config_ip4()
5780 addresses = self.vapi.nat64_pool_addr_dump()
5781 self.assertEqual(len(addresses), 1)
5782 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
5783
5784 # remove interface address and check NAT64 address pool
5785 self.pg4.unconfig_ip4()
5786 addresses = self.vapi.nat64_pool_addr_dump()
5787 self.assertEqual(0, len(adresses))
5788
Matus Fabiana431ad12018-01-04 04:03:14 -08005789 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5790 def test_ipfix_max_bibs_sessions(self):
5791 """ IPFIX logging maximum session and BIB entries exceeded """
5792 max_bibs = 1280
5793 max_sessions = 2560
5794 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5795 '64:ff9b::',
5796 96)
5797
5798 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5799 self.nat_addr_n)
5800 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5801 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5802
5803 pkts = []
5804 src = ""
5805 for i in range(0, max_bibs):
5806 src = "fd01:aa::%x" % (i)
5807 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5808 IPv6(src=src, dst=remote_host_ip6) /
5809 TCP(sport=12345, dport=80))
5810 pkts.append(p)
5811 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5812 IPv6(src=src, dst=remote_host_ip6) /
5813 TCP(sport=12345, dport=22))
5814 pkts.append(p)
5815 self.pg0.add_stream(pkts)
5816 self.pg_enable_capture(self.pg_interfaces)
5817 self.pg_start()
5818 self.pg1.get_capture(max_sessions)
5819
5820 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5821 src_address=self.pg3.local_ip4n,
5822 path_mtu=512,
5823 template_interval=10)
5824 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5825 src_port=self.ipfix_src_port)
5826
5827 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5828 IPv6(src=src, dst=remote_host_ip6) /
5829 TCP(sport=12345, dport=25))
5830 self.pg0.add_stream(p)
5831 self.pg_enable_capture(self.pg_interfaces)
5832 self.pg_start()
5833 self.pg1.get_capture(0)
5834 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5835 capture = self.pg3.get_capture(9)
5836 ipfix = IPFIXDecoder()
5837 # first load template
5838 for p in capture:
5839 self.assertTrue(p.haslayer(IPFIX))
5840 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5841 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5842 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5843 self.assertEqual(p[UDP].dport, 4739)
5844 self.assertEqual(p[IPFIX].observationDomainID,
5845 self.ipfix_domain_id)
5846 if p.haslayer(Template):
5847 ipfix.add_template(p.getlayer(Template))
5848 # verify events in data set
5849 for p in capture:
5850 if p.haslayer(Data):
5851 data = ipfix.decode_data_set(p.getlayer(Set))
5852 self.verify_ipfix_max_sessions(data, max_sessions)
5853
5854 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5855 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5856 TCP(sport=12345, dport=80))
5857 self.pg0.add_stream(p)
5858 self.pg_enable_capture(self.pg_interfaces)
5859 self.pg_start()
5860 self.pg1.get_capture(0)
5861 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5862 capture = self.pg3.get_capture(1)
5863 # verify events in data set
5864 for p in capture:
5865 self.assertTrue(p.haslayer(IPFIX))
5866 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5867 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5868 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5869 self.assertEqual(p[UDP].dport, 4739)
5870 self.assertEqual(p[IPFIX].observationDomainID,
5871 self.ipfix_domain_id)
5872 if p.haslayer(Data):
5873 data = ipfix.decode_data_set(p.getlayer(Set))
5874 self.verify_ipfix_max_bibs(data, max_bibs)
5875
5876 def test_ipfix_max_frags(self):
5877 """ IPFIX logging maximum fragments pending reassembly exceeded """
5878 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5879 self.nat_addr_n)
5880 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5881 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5882 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
5883 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5884 src_address=self.pg3.local_ip4n,
5885 path_mtu=512,
5886 template_interval=10)
5887 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5888 src_port=self.ipfix_src_port)
5889
5890 data = 'a' * 200
5891 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5892 self.tcp_port_in, 20, data)
5893 self.pg0.add_stream(pkts[-1])
5894 self.pg_enable_capture(self.pg_interfaces)
5895 self.pg_start()
5896 self.pg1.get_capture(0)
5897 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5898 capture = self.pg3.get_capture(9)
5899 ipfix = IPFIXDecoder()
5900 # first load template
5901 for p in capture:
5902 self.assertTrue(p.haslayer(IPFIX))
5903 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5904 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5905 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5906 self.assertEqual(p[UDP].dport, 4739)
5907 self.assertEqual(p[IPFIX].observationDomainID,
5908 self.ipfix_domain_id)
5909 if p.haslayer(Template):
5910 ipfix.add_template(p.getlayer(Template))
5911 # verify events in data set
5912 for p in capture:
5913 if p.haslayer(Data):
5914 data = ipfix.decode_data_set(p.getlayer(Set))
5915 self.verify_ipfix_max_fragments_ip6(data, 0,
5916 self.pg0.remote_ip6n)
5917
5918 def test_ipfix_bib_ses(self):
5919 """ IPFIX logging NAT64 BIB/session create and delete events """
5920 self.tcp_port_in = random.randint(1025, 65535)
5921 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5922 '64:ff9b::',
5923 96)
5924
5925 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5926 self.nat_addr_n)
5927 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5928 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5929 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5930 src_address=self.pg3.local_ip4n,
5931 path_mtu=512,
5932 template_interval=10)
5933 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5934 src_port=self.ipfix_src_port)
5935
5936 # Create
5937 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5938 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5939 TCP(sport=self.tcp_port_in, dport=25))
5940 self.pg0.add_stream(p)
5941 self.pg_enable_capture(self.pg_interfaces)
5942 self.pg_start()
5943 p = self.pg1.get_capture(1)
5944 self.tcp_port_out = p[0][TCP].sport
5945 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5946 capture = self.pg3.get_capture(10)
5947 ipfix = IPFIXDecoder()
5948 # first load template
5949 for p in capture:
5950 self.assertTrue(p.haslayer(IPFIX))
5951 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5952 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5953 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5954 self.assertEqual(p[UDP].dport, 4739)
5955 self.assertEqual(p[IPFIX].observationDomainID,
5956 self.ipfix_domain_id)
5957 if p.haslayer(Template):
5958 ipfix.add_template(p.getlayer(Template))
5959 # verify events in data set
5960 for p in capture:
5961 if p.haslayer(Data):
5962 data = ipfix.decode_data_set(p.getlayer(Set))
5963 if ord(data[0][230]) == 10:
5964 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
5965 elif ord(data[0][230]) == 6:
5966 self.verify_ipfix_nat64_ses(data,
5967 1,
5968 self.pg0.remote_ip6n,
5969 self.pg1.remote_ip4,
5970 25)
5971 else:
5972 self.logger.error(ppp("Unexpected or invalid packet: ", p))
5973
5974 # Delete
5975 self.pg_enable_capture(self.pg_interfaces)
5976 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5977 self.nat_addr_n,
5978 is_add=0)
5979 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5980 capture = self.pg3.get_capture(2)
5981 # verify events in data set
5982 for p in capture:
5983 self.assertTrue(p.haslayer(IPFIX))
5984 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5985 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5986 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5987 self.assertEqual(p[UDP].dport, 4739)
5988 self.assertEqual(p[IPFIX].observationDomainID,
5989 self.ipfix_domain_id)
5990 if p.haslayer(Data):
5991 data = ipfix.decode_data_set(p.getlayer(Set))
5992 if ord(data[0][230]) == 11:
5993 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
5994 elif ord(data[0][230]) == 7:
5995 self.verify_ipfix_nat64_ses(data,
5996 0,
5997 self.pg0.remote_ip6n,
5998 self.pg1.remote_ip4,
5999 25)
6000 else:
6001 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6002
Matus Fabian06596c52017-06-06 04:53:28 -07006003 def nat64_get_ses_num(self):
6004 """
6005 Return number of active NAT64 sessions.
6006 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006007 st = self.vapi.nat64_st_dump()
6008 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006009
6010 def clear_nat64(self):
6011 """
6012 Clear NAT64 configuration.
6013 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006014 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6015 domain_id=self.ipfix_domain_id)
6016 self.ipfix_src_port = 4739
6017 self.ipfix_domain_id = 1
6018
Matus Fabian06596c52017-06-06 04:53:28 -07006019 self.vapi.nat64_set_timeouts()
6020
6021 interfaces = self.vapi.nat64_interface_dump()
6022 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006023 if intf.is_inside > 1:
6024 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6025 0,
6026 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006027 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6028 intf.is_inside,
6029 is_add=0)
6030
Matus Fabiana431ad12018-01-04 04:03:14 -08006031 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006032 for bibe in bib:
6033 if bibe.is_static:
6034 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6035 bibe.o_addr,
6036 bibe.i_port,
6037 bibe.o_port,
6038 bibe.proto,
6039 bibe.vrf_id,
6040 is_add=0)
6041
6042 adresses = self.vapi.nat64_pool_addr_dump()
6043 for addr in adresses:
6044 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6045 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006046 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006047 is_add=0)
6048
Matus Fabian428dc912017-06-21 06:15:18 -07006049 prefixes = self.vapi.nat64_prefix_dump()
6050 for prefix in prefixes:
6051 self.vapi.nat64_add_del_prefix(prefix.prefix,
6052 prefix.prefix_len,
6053 vrf_id=prefix.vrf_id,
6054 is_add=0)
6055
Matus Fabian06596c52017-06-06 04:53:28 -07006056 def tearDown(self):
6057 super(TestNAT64, self).tearDown()
6058 if not self.vpp_dead:
6059 self.logger.info(self.vapi.cli("show nat64 pool"))
6060 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006061 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006062 self.logger.info(self.vapi.cli("show nat64 bib all"))
6063 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006064 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006065 self.clear_nat64()
6066
Matus Fabian8ebe6252017-11-06 05:04:53 -08006067
6068class TestDSlite(MethodHolder):
6069 """ DS-Lite Test Cases """
6070
6071 @classmethod
6072 def setUpClass(cls):
6073 super(TestDSlite, cls).setUpClass()
6074
6075 try:
6076 cls.nat_addr = '10.0.0.3'
6077 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6078
6079 cls.create_pg_interfaces(range(2))
6080 cls.pg0.admin_up()
6081 cls.pg0.config_ip4()
6082 cls.pg0.resolve_arp()
6083 cls.pg1.admin_up()
6084 cls.pg1.config_ip6()
6085 cls.pg1.generate_remote_hosts(2)
6086 cls.pg1.configure_ipv6_neighbors()
6087
6088 except Exception:
6089 super(TestDSlite, cls).tearDownClass()
6090 raise
6091
6092 def test_dslite(self):
6093 """ Test DS-Lite """
6094 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6095 self.nat_addr_n)
6096 aftr_ip4 = '192.0.0.1'
6097 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6098 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6099 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6100 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6101
6102 # UDP
6103 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6104 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6105 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6106 UDP(sport=20000, dport=10000))
6107 self.pg1.add_stream(p)
6108 self.pg_enable_capture(self.pg_interfaces)
6109 self.pg_start()
6110 capture = self.pg0.get_capture(1)
6111 capture = capture[0]
6112 self.assertFalse(capture.haslayer(IPv6))
6113 self.assertEqual(capture[IP].src, self.nat_addr)
6114 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6115 self.assertNotEqual(capture[UDP].sport, 20000)
6116 self.assertEqual(capture[UDP].dport, 10000)
6117 self.check_ip_checksum(capture)
6118 out_port = capture[UDP].sport
6119
6120 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6121 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6122 UDP(sport=10000, dport=out_port))
6123 self.pg0.add_stream(p)
6124 self.pg_enable_capture(self.pg_interfaces)
6125 self.pg_start()
6126 capture = self.pg1.get_capture(1)
6127 capture = capture[0]
6128 self.assertEqual(capture[IPv6].src, aftr_ip6)
6129 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6130 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6131 self.assertEqual(capture[IP].dst, '192.168.1.1')
6132 self.assertEqual(capture[UDP].sport, 10000)
6133 self.assertEqual(capture[UDP].dport, 20000)
6134 self.check_ip_checksum(capture)
6135
6136 # TCP
6137 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6138 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6139 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6140 TCP(sport=20001, dport=10001))
6141 self.pg1.add_stream(p)
6142 self.pg_enable_capture(self.pg_interfaces)
6143 self.pg_start()
6144 capture = self.pg0.get_capture(1)
6145 capture = capture[0]
6146 self.assertFalse(capture.haslayer(IPv6))
6147 self.assertEqual(capture[IP].src, self.nat_addr)
6148 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6149 self.assertNotEqual(capture[TCP].sport, 20001)
6150 self.assertEqual(capture[TCP].dport, 10001)
6151 self.check_ip_checksum(capture)
6152 self.check_tcp_checksum(capture)
6153 out_port = capture[TCP].sport
6154
6155 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6156 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6157 TCP(sport=10001, dport=out_port))
6158 self.pg0.add_stream(p)
6159 self.pg_enable_capture(self.pg_interfaces)
6160 self.pg_start()
6161 capture = self.pg1.get_capture(1)
6162 capture = capture[0]
6163 self.assertEqual(capture[IPv6].src, aftr_ip6)
6164 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6165 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6166 self.assertEqual(capture[IP].dst, '192.168.1.1')
6167 self.assertEqual(capture[TCP].sport, 10001)
6168 self.assertEqual(capture[TCP].dport, 20001)
6169 self.check_ip_checksum(capture)
6170 self.check_tcp_checksum(capture)
6171
6172 # ICMP
6173 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6174 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6175 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6176 ICMP(id=4000, type='echo-request'))
6177 self.pg1.add_stream(p)
6178 self.pg_enable_capture(self.pg_interfaces)
6179 self.pg_start()
6180 capture = self.pg0.get_capture(1)
6181 capture = capture[0]
6182 self.assertFalse(capture.haslayer(IPv6))
6183 self.assertEqual(capture[IP].src, self.nat_addr)
6184 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6185 self.assertNotEqual(capture[ICMP].id, 4000)
6186 self.check_ip_checksum(capture)
6187 self.check_icmp_checksum(capture)
6188 out_id = capture[ICMP].id
6189
6190 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6191 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6192 ICMP(id=out_id, type='echo-reply'))
6193 self.pg0.add_stream(p)
6194 self.pg_enable_capture(self.pg_interfaces)
6195 self.pg_start()
6196 capture = self.pg1.get_capture(1)
6197 capture = capture[0]
6198 self.assertEqual(capture[IPv6].src, aftr_ip6)
6199 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6200 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6201 self.assertEqual(capture[IP].dst, '192.168.1.1')
6202 self.assertEqual(capture[ICMP].id, 4000)
6203 self.check_ip_checksum(capture)
6204 self.check_icmp_checksum(capture)
6205
Matus Fabian331acc62017-12-08 03:38:51 -08006206 # ping DS-Lite AFTR tunnel endpoint address
6207 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6208 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6209 ICMPv6EchoRequest())
6210 self.pg1.add_stream(p)
6211 self.pg_enable_capture(self.pg_interfaces)
6212 self.pg_start()
6213 capture = self.pg1.get_capture(1)
6214 self.assertEqual(1, len(capture))
6215 capture = capture[0]
6216 self.assertEqual(capture[IPv6].src, aftr_ip6)
6217 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6218 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6219
Matus Fabian8ebe6252017-11-06 05:04:53 -08006220 def tearDown(self):
6221 super(TestDSlite, self).tearDown()
6222 if not self.vpp_dead:
6223 self.logger.info(self.vapi.cli("show dslite pool"))
6224 self.logger.info(
6225 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6226 self.logger.info(self.vapi.cli("show dslite sessions"))
6227
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006228
6229class TestDSliteCE(MethodHolder):
6230 """ DS-Lite CE Test Cases """
6231
6232 @classmethod
6233 def setUpConstants(cls):
6234 super(TestDSliteCE, cls).setUpConstants()
6235 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6236
6237 @classmethod
6238 def setUpClass(cls):
6239 super(TestDSliteCE, cls).setUpClass()
6240
6241 try:
6242 cls.create_pg_interfaces(range(2))
6243 cls.pg0.admin_up()
6244 cls.pg0.config_ip4()
6245 cls.pg0.resolve_arp()
6246 cls.pg1.admin_up()
6247 cls.pg1.config_ip6()
6248 cls.pg1.generate_remote_hosts(1)
6249 cls.pg1.configure_ipv6_neighbors()
6250
6251 except Exception:
6252 super(TestDSliteCE, cls).tearDownClass()
6253 raise
6254
6255 def test_dslite_ce(self):
6256 """ Test DS-Lite CE """
6257
6258 b4_ip4 = '192.0.0.2'
6259 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6260 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6261 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6262 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6263
6264 aftr_ip4 = '192.0.0.1'
6265 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6266 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6267 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6268 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6269
6270 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6271 dst_address_length=128,
6272 next_hop_address=self.pg1.remote_ip6n,
6273 next_hop_sw_if_index=self.pg1.sw_if_index,
6274 is_ipv6=1)
6275
6276 # UDP encapsulation
6277 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6278 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6279 UDP(sport=10000, dport=20000))
6280 self.pg0.add_stream(p)
6281 self.pg_enable_capture(self.pg_interfaces)
6282 self.pg_start()
6283 capture = self.pg1.get_capture(1)
6284 capture = capture[0]
6285 self.assertEqual(capture[IPv6].src, b4_ip6)
6286 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6287 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6288 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6289 self.assertEqual(capture[UDP].sport, 10000)
6290 self.assertEqual(capture[UDP].dport, 20000)
6291 self.check_ip_checksum(capture)
6292
6293 # UDP decapsulation
6294 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6295 IPv6(dst=b4_ip6, src=aftr_ip6) /
6296 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6297 UDP(sport=20000, dport=10000))
6298 self.pg1.add_stream(p)
6299 self.pg_enable_capture(self.pg_interfaces)
6300 self.pg_start()
6301 capture = self.pg0.get_capture(1)
6302 capture = capture[0]
6303 self.assertFalse(capture.haslayer(IPv6))
6304 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6305 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6306 self.assertEqual(capture[UDP].sport, 20000)
6307 self.assertEqual(capture[UDP].dport, 10000)
6308 self.check_ip_checksum(capture)
6309
6310 # ping DS-Lite B4 tunnel endpoint address
6311 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6312 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6313 ICMPv6EchoRequest())
6314 self.pg1.add_stream(p)
6315 self.pg_enable_capture(self.pg_interfaces)
6316 self.pg_start()
6317 capture = self.pg1.get_capture(1)
6318 self.assertEqual(1, len(capture))
6319 capture = capture[0]
6320 self.assertEqual(capture[IPv6].src, b4_ip6)
6321 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6322 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6323
6324 def tearDown(self):
6325 super(TestDSliteCE, self).tearDown()
6326 if not self.vpp_dead:
6327 self.logger.info(
6328 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6329 self.logger.info(
6330 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6331
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006332
6333class TestNAT66(MethodHolder):
6334 """ NAT66 Test Cases """
6335
6336 @classmethod
6337 def setUpClass(cls):
6338 super(TestNAT66, cls).setUpClass()
6339
6340 try:
6341 cls.nat_addr = 'fd01:ff::2'
6342 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6343
6344 cls.create_pg_interfaces(range(2))
6345 cls.interfaces = list(cls.pg_interfaces)
6346
6347 for i in cls.interfaces:
6348 i.admin_up()
6349 i.config_ip6()
6350 i.configure_ipv6_neighbors()
6351
6352 except Exception:
6353 super(TestNAT66, cls).tearDownClass()
6354 raise
6355
6356 def test_static(self):
6357 """ 1:1 NAT66 test """
6358 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6359 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6360 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6361 self.nat_addr_n)
6362
6363 # in2out
6364 pkts = []
6365 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6366 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6367 TCP())
6368 pkts.append(p)
6369 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6370 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6371 UDP())
6372 pkts.append(p)
6373 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6374 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6375 ICMPv6EchoRequest())
6376 pkts.append(p)
6377 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6378 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6379 GRE() / IP() / TCP())
6380 pkts.append(p)
6381 self.pg0.add_stream(pkts)
6382 self.pg_enable_capture(self.pg_interfaces)
6383 self.pg_start()
6384 capture = self.pg1.get_capture(len(pkts))
6385 for packet in capture:
6386 try:
6387 self.assertEqual(packet[IPv6].src, self.nat_addr)
6388 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6389 if packet.haslayer(TCP):
6390 self.check_tcp_checksum(packet)
6391 elif packet.haslayer(UDP):
6392 self.check_udp_checksum(packet)
6393 elif packet.haslayer(ICMPv6EchoRequest):
6394 self.check_icmpv6_checksum(packet)
6395 except:
6396 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6397 raise
6398
6399 # out2in
6400 pkts = []
6401 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6402 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6403 TCP())
6404 pkts.append(p)
6405 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6406 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6407 UDP())
6408 pkts.append(p)
6409 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6410 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6411 ICMPv6EchoReply())
6412 pkts.append(p)
6413 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6414 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6415 GRE() / IP() / TCP())
6416 pkts.append(p)
6417 self.pg1.add_stream(pkts)
6418 self.pg_enable_capture(self.pg_interfaces)
6419 self.pg_start()
6420 capture = self.pg0.get_capture(len(pkts))
6421 for packet in capture:
6422 try:
6423 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6424 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6425 if packet.haslayer(TCP):
6426 self.check_tcp_checksum(packet)
6427 elif packet.haslayer(UDP):
6428 self.check_udp_checksum(packet)
6429 elif packet.haslayer(ICMPv6EchoReply):
6430 self.check_icmpv6_checksum(packet)
6431 except:
6432 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6433 raise
6434
6435 sm = self.vapi.nat66_static_mapping_dump()
6436 self.assertEqual(len(sm), 1)
6437 self.assertEqual(sm[0].total_pkts, 8)
6438
Juraj Sloboda9341e342018-04-13 12:00:46 +02006439 def test_check_no_translate(self):
6440 """ NAT66 translate only when egress interface is outside interface """
6441 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6442 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6443 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6444 self.nat_addr_n)
6445
6446 # in2out
6447 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6448 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6449 UDP())
6450 self.pg0.add_stream([p])
6451 self.pg_enable_capture(self.pg_interfaces)
6452 self.pg_start()
6453 capture = self.pg1.get_capture(1)
6454 packet = capture[0]
6455 try:
6456 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6457 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6458 except:
6459 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6460 raise
6461
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006462 def clear_nat66(self):
6463 """
6464 Clear NAT66 configuration.
6465 """
6466 interfaces = self.vapi.nat66_interface_dump()
6467 for intf in interfaces:
6468 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6469 intf.is_inside,
6470 is_add=0)
6471
6472 static_mappings = self.vapi.nat66_static_mapping_dump()
6473 for sm in static_mappings:
6474 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6475 sm.external_ip_address,
6476 sm.vrf_id,
6477 is_add=0)
6478
6479 def tearDown(self):
6480 super(TestNAT66, self).tearDown()
6481 if not self.vpp_dead:
6482 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6483 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6484 self.clear_nat66()
6485
Matus Fabiande886752016-12-07 03:38:19 -08006486if __name__ == '__main__':
6487 unittest.main(testRunner=VppTestRunner)