blob: 695014fe587839e8d53a5c32e98c57fe0bb88182 [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 Fabian2ba92e32017-08-21 07:05:03 -07001034 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001035
Matus Fabian704018c2017-09-04 02:17:18 -07001036 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
1037 for lb_sm in lb_static_mappings:
1038 self.vapi.nat44_add_del_lb_static_mapping(
1039 lb_sm.external_addr,
1040 lb_sm.external_port,
1041 lb_sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -08001042 vrf_id=lb_sm.vrf_id,
1043 twice_nat=lb_sm.twice_nat,
Matus Fabian240b5ef2018-01-11 04:09:17 -08001044 out2in_only=lb_sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001045 tag=lb_sm.tag,
Ole Troan895b6e82017-10-20 13:28:20 +02001046 is_add=0,
1047 local_num=0,
1048 locals=[])
Matus Fabian704018c2017-09-04 02:17:18 -07001049
Matus Fabianab7a8052017-11-28 04:29:41 -08001050 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1051 for id_m in identity_mappings:
1052 self.vapi.nat44_add_del_identity_mapping(
1053 addr_only=id_m.addr_only,
1054 ip=id_m.ip_address,
1055 port=id_m.port,
1056 sw_if_index=id_m.sw_if_index,
1057 vrf_id=id_m.vrf_id,
1058 protocol=id_m.protocol,
1059 is_add=0)
1060
Matus Fabian2ba92e32017-08-21 07:05:03 -07001061 adresses = self.vapi.nat44_address_dump()
Matus Fabiande886752016-12-07 03:38:19 -08001062 for addr in adresses:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001063 self.vapi.nat44_add_del_address_range(addr.ip_address,
1064 addr.ip_address,
Matus Fabianb932d262017-12-18 05:38:24 -08001065 twice_nat=addr.twice_nat,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001066 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001067
Matus Fabianefcd1e92017-08-15 06:59:19 -07001068 self.vapi.nat_set_reass()
1069 self.vapi.nat_set_reass(is_ip6=1)
1070
Matus Fabian2ba92e32017-08-21 07:05:03 -07001071 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1072 local_port=0, external_port=0, vrf_id=0,
1073 is_add=1, external_sw_if_index=0xFFFFFFFF,
Matus Fabian5f224992018-01-25 21:59:16 -08001074 proto=0, twice_nat=0, out2in_only=0, tag=""):
Matus Fabiande886752016-12-07 03:38:19 -08001075 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001076 Add/delete NAT44 static mapping
Matus Fabiande886752016-12-07 03:38:19 -08001077
1078 :param local_ip: Local IP address
1079 :param external_ip: External IP address
1080 :param local_port: Local port number (Optional)
1081 :param external_port: External port number (Optional)
1082 :param vrf_id: VRF ID (Default 0)
1083 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabian36532bd2017-01-23 23:42:28 -08001084 :param external_sw_if_index: External interface instead of IP address
Matus Fabian09d96f42017-02-02 01:43:00 -08001085 :param proto: IP protocol (Mandatory if port specified)
Matus Fabianb932d262017-12-18 05:38:24 -08001086 :param twice_nat: 1 if translate external host address and port
Matus Fabiane82488f2018-01-18 03:38:45 -08001087 :param out2in_only: if 1 rule is matching only out2in direction
Matus Fabian5f224992018-01-25 21:59:16 -08001088 :param tag: Opaque string tag
Matus Fabiande886752016-12-07 03:38:19 -08001089 """
1090 addr_only = 1
1091 if local_port and external_port:
1092 addr_only = 0
1093 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1094 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001095 self.vapi.nat44_add_del_static_mapping(
Klement Sekerada505f62017-01-04 12:58:53 +01001096 l_ip,
1097 e_ip,
Matus Fabian36532bd2017-01-23 23:42:28 -08001098 external_sw_if_index,
Klement Sekerada505f62017-01-04 12:58:53 +01001099 local_port,
1100 external_port,
1101 addr_only,
1102 vrf_id,
Matus Fabian09d96f42017-02-02 01:43:00 -08001103 proto,
Matus Fabianb932d262017-12-18 05:38:24 -08001104 twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001105 out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001106 tag,
Klement Sekerada505f62017-01-04 12:58:53 +01001107 is_add)
Matus Fabiande886752016-12-07 03:38:19 -08001108
Matus Fabianb932d262017-12-18 05:38:24 -08001109 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
Matus Fabiande886752016-12-07 03:38:19 -08001110 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001111 Add/delete NAT44 address
Matus Fabiande886752016-12-07 03:38:19 -08001112
1113 :param ip: IP address
1114 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabianb932d262017-12-18 05:38:24 -08001115 :param twice_nat: twice NAT address for extenal hosts
Matus Fabiande886752016-12-07 03:38:19 -08001116 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001117 nat_addr = socket.inet_pton(socket.AF_INET, ip)
1118 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
Matus Fabianb932d262017-12-18 05:38:24 -08001119 vrf_id=vrf_id,
1120 twice_nat=twice_nat)
Matus Fabiande886752016-12-07 03:38:19 -08001121
1122 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001123 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001124
Matus Fabian2ba92e32017-08-21 07:05:03 -07001125 self.nat44_add_address(self.nat_addr)
1126 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1127 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1128 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001129
1130 # in2out
1131 pkts = self.create_stream_in(self.pg0, self.pg1)
1132 self.pg0.add_stream(pkts)
1133 self.pg_enable_capture(self.pg_interfaces)
1134 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001135 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001136 self.verify_capture_out(capture)
1137
1138 # out2in
1139 pkts = self.create_stream_out(self.pg1)
1140 self.pg1.add_stream(pkts)
1141 self.pg_enable_capture(self.pg_interfaces)
1142 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001143 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001144 self.verify_capture_in(capture, self.pg0)
1145
Juraj Slobodab33f4132017-02-08 23:54:21 -08001146 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001147 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001148
Matus Fabian2ba92e32017-08-21 07:05:03 -07001149 self.nat44_add_address(self.nat_addr)
1150 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1151 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1152 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001153
1154 # Client side - generate traffic
1155 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1156 self.pg0.add_stream(pkts)
1157 self.pg_enable_capture(self.pg_interfaces)
1158 self.pg_start()
1159
1160 # Client side - verify ICMP type 11 packets
1161 capture = self.pg0.get_capture(len(pkts))
1162 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1163
1164 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001165 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001166
Matus Fabian2ba92e32017-08-21 07:05:03 -07001167 self.nat44_add_address(self.nat_addr)
1168 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1169 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1170 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001171
1172 # Client side - create sessions
1173 pkts = self.create_stream_in(self.pg0, self.pg1)
1174 self.pg0.add_stream(pkts)
1175 self.pg_enable_capture(self.pg_interfaces)
1176 self.pg_start()
1177
1178 # Server side - generate traffic
1179 capture = self.pg1.get_capture(len(pkts))
1180 self.verify_capture_out(capture)
1181 pkts = self.create_stream_out(self.pg1, ttl=1)
1182 self.pg1.add_stream(pkts)
1183 self.pg_enable_capture(self.pg_interfaces)
1184 self.pg_start()
1185
1186 # Server side - verify ICMP type 11 packets
1187 capture = self.pg1.get_capture(len(pkts))
1188 self.verify_capture_out_with_icmp_errors(capture,
1189 src_ip=self.pg1.local_ip4)
1190
1191 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001192 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001193
Matus Fabian2ba92e32017-08-21 07:05:03 -07001194 self.nat44_add_address(self.nat_addr)
1195 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1196 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1197 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001198
1199 # Client side - generate traffic
1200 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1201 self.pg0.add_stream(pkts)
1202 self.pg_enable_capture(self.pg_interfaces)
1203 self.pg_start()
1204
1205 # Server side - simulate ICMP type 11 response
1206 capture = self.pg1.get_capture(len(pkts))
1207 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001208 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001209 ICMP(type=11) / packet[IP] for packet in capture]
1210 self.pg1.add_stream(pkts)
1211 self.pg_enable_capture(self.pg_interfaces)
1212 self.pg_start()
1213
1214 # Client side - verify ICMP type 11 packets
1215 capture = self.pg0.get_capture(len(pkts))
1216 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1217
1218 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001219 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001220
Matus Fabian2ba92e32017-08-21 07:05:03 -07001221 self.nat44_add_address(self.nat_addr)
1222 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1223 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1224 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001225
1226 # Client side - create sessions
1227 pkts = self.create_stream_in(self.pg0, self.pg1)
1228 self.pg0.add_stream(pkts)
1229 self.pg_enable_capture(self.pg_interfaces)
1230 self.pg_start()
1231
1232 # Server side - generate traffic
1233 capture = self.pg1.get_capture(len(pkts))
1234 self.verify_capture_out(capture)
1235 pkts = self.create_stream_out(self.pg1, ttl=2)
1236 self.pg1.add_stream(pkts)
1237 self.pg_enable_capture(self.pg_interfaces)
1238 self.pg_start()
1239
1240 # Client side - simulate ICMP type 11 response
1241 capture = self.pg0.get_capture(len(pkts))
1242 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1243 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1244 ICMP(type=11) / packet[IP] for packet in capture]
1245 self.pg0.add_stream(pkts)
1246 self.pg_enable_capture(self.pg_interfaces)
1247 self.pg_start()
1248
1249 # Server side - verify ICMP type 11 packets
1250 capture = self.pg1.get_capture(len(pkts))
1251 self.verify_capture_out_with_icmp_errors(capture)
1252
Juraj Sloboda665e4822017-02-16 17:17:19 -08001253 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001254 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001255
Matus Fabian2ba92e32017-08-21 07:05:03 -07001256 self.nat44_add_address(self.nat_addr)
1257 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1258 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1259 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001260
1261 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1262 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1263 ICMP(id=self.icmp_id_out, type='echo-request'))
1264 pkts = [p]
1265 self.pg1.add_stream(pkts)
1266 self.pg_enable_capture(self.pg_interfaces)
1267 self.pg_start()
1268 capture = self.pg1.get_capture(len(pkts))
1269 self.assertEqual(1, len(capture))
1270 packet = capture[0]
1271 try:
1272 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1273 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1274 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1275 self.assertEqual(packet[ICMP].type, 0) # echo reply
1276 except:
1277 self.logger.error(ppp("Unexpected or invalid packet "
1278 "(outside network):", packet))
1279 raise
1280
Juraj Slobodad3677682017-04-14 03:24:45 +02001281 def test_ping_internal_host_from_outside(self):
1282 """ Ping internal host from outside network """
1283
Matus Fabian2ba92e32017-08-21 07:05:03 -07001284 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1285 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1286 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1287 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001288
1289 # out2in
1290 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001291 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001292 ICMP(id=self.icmp_id_out, type='echo-request'))
1293 self.pg1.add_stream(pkt)
1294 self.pg_enable_capture(self.pg_interfaces)
1295 self.pg_start()
1296 capture = self.pg0.get_capture(1)
1297 self.verify_capture_in(capture, self.pg0, packet_num=1)
1298 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1299
1300 # in2out
1301 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1302 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1303 ICMP(id=self.icmp_id_in, type='echo-reply'))
1304 self.pg0.add_stream(pkt)
1305 self.pg_enable_capture(self.pg_interfaces)
1306 self.pg_start()
1307 capture = self.pg1.get_capture(1)
1308 self.verify_capture_out(capture, same_port=True, packet_num=1)
1309 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1310
Juraj Sloboda7b929792017-11-23 13:20:48 +01001311 def test_forwarding(self):
1312 """ NAT44 forwarding test """
1313
1314 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1315 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1316 is_inside=0)
1317 self.vapi.nat44_forwarding_enable_disable(1)
1318
1319 real_ip = self.pg0.remote_ip4n
1320 alias_ip = self.nat_addr_n
1321 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1322 external_ip=alias_ip)
1323
1324 try:
1325 # in2out - static mapping match
1326
1327 pkts = self.create_stream_out(self.pg1)
1328 self.pg1.add_stream(pkts)
1329 self.pg_enable_capture(self.pg_interfaces)
1330 self.pg_start()
1331 capture = self.pg0.get_capture(len(pkts))
1332 self.verify_capture_in(capture, self.pg0)
1333
1334 pkts = self.create_stream_in(self.pg0, self.pg1)
1335 self.pg0.add_stream(pkts)
1336 self.pg_enable_capture(self.pg_interfaces)
1337 self.pg_start()
1338 capture = self.pg1.get_capture(len(pkts))
1339 self.verify_capture_out(capture, same_port=True)
1340
1341 # in2out - no static mapping match
1342
1343 host0 = self.pg0.remote_hosts[0]
1344 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1345 try:
1346 pkts = self.create_stream_out(self.pg1,
1347 dst_ip=self.pg0.remote_ip4,
1348 use_inside_ports=True)
1349 self.pg1.add_stream(pkts)
1350 self.pg_enable_capture(self.pg_interfaces)
1351 self.pg_start()
1352 capture = self.pg0.get_capture(len(pkts))
1353 self.verify_capture_in(capture, self.pg0)
1354
1355 pkts = self.create_stream_in(self.pg0, self.pg1)
1356 self.pg0.add_stream(pkts)
1357 self.pg_enable_capture(self.pg_interfaces)
1358 self.pg_start()
1359 capture = self.pg1.get_capture(len(pkts))
1360 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1361 same_port=True)
1362 finally:
1363 self.pg0.remote_hosts[0] = host0
1364
1365 finally:
1366 self.vapi.nat44_forwarding_enable_disable(0)
1367 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1368 external_ip=alias_ip,
1369 is_add=0)
1370
Matus Fabiande886752016-12-07 03:38:19 -08001371 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001372 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001373
1374 nat_ip = "10.0.0.10"
1375 self.tcp_port_out = 6303
1376 self.udp_port_out = 6304
1377 self.icmp_id_out = 6305
1378
Matus Fabian2ba92e32017-08-21 07:05:03 -07001379 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1380 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1381 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1382 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001383 sm = self.vapi.nat44_static_mapping_dump()
1384 self.assertEqual(len(sm), 1)
1385 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001386 self.assertEqual(sm[0].protocol, 0)
1387 self.assertEqual(sm[0].local_port, 0)
1388 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001389
1390 # in2out
1391 pkts = self.create_stream_in(self.pg0, self.pg1)
1392 self.pg0.add_stream(pkts)
1393 self.pg_enable_capture(self.pg_interfaces)
1394 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001395 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001396 self.verify_capture_out(capture, nat_ip, True)
1397
1398 # out2in
1399 pkts = self.create_stream_out(self.pg1, nat_ip)
1400 self.pg1.add_stream(pkts)
1401 self.pg_enable_capture(self.pg_interfaces)
1402 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001403 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001404 self.verify_capture_in(capture, self.pg0)
1405
1406 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001407 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001408
1409 nat_ip = "10.0.0.20"
1410 self.tcp_port_out = 6303
1411 self.udp_port_out = 6304
1412 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001413 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001414
Matus Fabian5f224992018-01-25 21:59:16 -08001415 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001416 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1417 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1418 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001419 sm = self.vapi.nat44_static_mapping_dump()
1420 self.assertEqual(len(sm), 1)
1421 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001422
1423 # out2in
1424 pkts = self.create_stream_out(self.pg1, nat_ip)
1425 self.pg1.add_stream(pkts)
1426 self.pg_enable_capture(self.pg_interfaces)
1427 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001428 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001429 self.verify_capture_in(capture, self.pg0)
1430
1431 # in2out
1432 pkts = self.create_stream_in(self.pg0, self.pg1)
1433 self.pg0.add_stream(pkts)
1434 self.pg_enable_capture(self.pg_interfaces)
1435 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001436 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001437 self.verify_capture_out(capture, nat_ip, True)
1438
1439 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001440 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001441
1442 self.tcp_port_out = 3606
1443 self.udp_port_out = 3607
1444 self.icmp_id_out = 3608
1445
Matus Fabian2ba92e32017-08-21 07:05:03 -07001446 self.nat44_add_address(self.nat_addr)
1447 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1448 self.tcp_port_in, self.tcp_port_out,
1449 proto=IP_PROTOS.tcp)
1450 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1451 self.udp_port_in, self.udp_port_out,
1452 proto=IP_PROTOS.udp)
1453 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1454 self.icmp_id_in, self.icmp_id_out,
1455 proto=IP_PROTOS.icmp)
1456 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1457 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1458 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001459
1460 # in2out
1461 pkts = self.create_stream_in(self.pg0, self.pg1)
1462 self.pg0.add_stream(pkts)
1463 self.pg_enable_capture(self.pg_interfaces)
1464 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001465 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001466 self.verify_capture_out(capture)
1467
1468 # out2in
1469 pkts = self.create_stream_out(self.pg1)
1470 self.pg1.add_stream(pkts)
1471 self.pg_enable_capture(self.pg_interfaces)
1472 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001473 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001474 self.verify_capture_in(capture, self.pg0)
1475
1476 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001477 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001478
1479 self.tcp_port_out = 30606
1480 self.udp_port_out = 30607
1481 self.icmp_id_out = 30608
1482
Matus Fabian2ba92e32017-08-21 07:05:03 -07001483 self.nat44_add_address(self.nat_addr)
1484 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1485 self.tcp_port_in, self.tcp_port_out,
1486 proto=IP_PROTOS.tcp)
1487 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1488 self.udp_port_in, self.udp_port_out,
1489 proto=IP_PROTOS.udp)
1490 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1491 self.icmp_id_in, self.icmp_id_out,
1492 proto=IP_PROTOS.icmp)
1493 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1494 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1495 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001496
1497 # out2in
1498 pkts = self.create_stream_out(self.pg1)
1499 self.pg1.add_stream(pkts)
1500 self.pg_enable_capture(self.pg_interfaces)
1501 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001502 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001503 self.verify_capture_in(capture, self.pg0)
1504
1505 # in2out
1506 pkts = self.create_stream_in(self.pg0, self.pg1)
1507 self.pg0.add_stream(pkts)
1508 self.pg_enable_capture(self.pg_interfaces)
1509 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001510 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001511 self.verify_capture_out(capture)
1512
Matus Fabiane82488f2018-01-18 03:38:45 -08001513 def test_static_with_port_out2(self):
1514 """ 1:1 NAPT symmetrical rule """
1515
1516 external_port = 80
1517 local_port = 8080
1518
1519 self.vapi.nat44_forwarding_enable_disable(1)
1520 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1521 local_port, external_port,
1522 proto=IP_PROTOS.tcp, out2in_only=1)
1523 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1524 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1525 is_inside=0)
1526
1527 # from client to service
1528 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1529 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1530 TCP(sport=12345, dport=external_port))
1531 self.pg1.add_stream(p)
1532 self.pg_enable_capture(self.pg_interfaces)
1533 self.pg_start()
1534 capture = self.pg0.get_capture(1)
1535 p = capture[0]
1536 server = None
1537 try:
1538 ip = p[IP]
1539 tcp = p[TCP]
1540 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1541 self.assertEqual(tcp.dport, local_port)
1542 self.check_tcp_checksum(p)
1543 self.check_ip_checksum(p)
1544 except:
1545 self.logger.error(ppp("Unexpected or invalid packet:", p))
1546 raise
1547
Matus Fabian87233b52018-01-26 03:17:01 -08001548 # ICMP error
1549 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1550 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1551 ICMP(type=11) / capture[0][IP])
1552 self.pg0.add_stream(p)
1553 self.pg_enable_capture(self.pg_interfaces)
1554 self.pg_start()
1555 capture = self.pg1.get_capture(1)
1556 p = capture[0]
1557 try:
1558 self.assertEqual(p[IP].src, self.nat_addr)
1559 inner = p[IPerror]
1560 self.assertEqual(inner.dst, self.nat_addr)
1561 self.assertEqual(inner[TCPerror].dport, external_port)
1562 except:
1563 self.logger.error(ppp("Unexpected or invalid packet:", p))
1564 raise
1565
Matus Fabiane82488f2018-01-18 03:38:45 -08001566 # from service back to client
1567 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1568 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1569 TCP(sport=local_port, dport=12345))
1570 self.pg0.add_stream(p)
1571 self.pg_enable_capture(self.pg_interfaces)
1572 self.pg_start()
1573 capture = self.pg1.get_capture(1)
1574 p = capture[0]
1575 try:
1576 ip = p[IP]
1577 tcp = p[TCP]
1578 self.assertEqual(ip.src, self.nat_addr)
1579 self.assertEqual(tcp.sport, external_port)
1580 self.check_tcp_checksum(p)
1581 self.check_ip_checksum(p)
1582 except:
1583 self.logger.error(ppp("Unexpected or invalid packet:", p))
1584 raise
1585
Matus Fabian87233b52018-01-26 03:17:01 -08001586 # ICMP error
1587 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1588 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1589 ICMP(type=11) / capture[0][IP])
1590 self.pg1.add_stream(p)
1591 self.pg_enable_capture(self.pg_interfaces)
1592 self.pg_start()
1593 capture = self.pg0.get_capture(1)
1594 p = capture[0]
1595 try:
1596 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1597 inner = p[IPerror]
1598 self.assertEqual(inner.src, self.pg0.remote_ip4)
1599 self.assertEqual(inner[TCPerror].sport, local_port)
1600 except:
1601 self.logger.error(ppp("Unexpected or invalid packet:", p))
1602 raise
1603
Matus Fabiane82488f2018-01-18 03:38:45 -08001604 # from client to server (no translation)
1605 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1606 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1607 TCP(sport=12346, dport=local_port))
1608 self.pg1.add_stream(p)
1609 self.pg_enable_capture(self.pg_interfaces)
1610 self.pg_start()
1611 capture = self.pg0.get_capture(1)
1612 p = capture[0]
1613 server = None
1614 try:
1615 ip = p[IP]
1616 tcp = p[TCP]
1617 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1618 self.assertEqual(tcp.dport, local_port)
1619 self.check_tcp_checksum(p)
1620 self.check_ip_checksum(p)
1621 except:
1622 self.logger.error(ppp("Unexpected or invalid packet:", p))
1623 raise
1624
1625 # from service back to client (no translation)
1626 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1627 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1628 TCP(sport=local_port, dport=12346))
1629 self.pg0.add_stream(p)
1630 self.pg_enable_capture(self.pg_interfaces)
1631 self.pg_start()
1632 capture = self.pg1.get_capture(1)
1633 p = capture[0]
1634 try:
1635 ip = p[IP]
1636 tcp = p[TCP]
1637 self.assertEqual(ip.src, self.pg0.remote_ip4)
1638 self.assertEqual(tcp.sport, local_port)
1639 self.check_tcp_checksum(p)
1640 self.check_ip_checksum(p)
1641 except:
1642 self.logger.error(ppp("Unexpected or invalid packet:", p))
1643 raise
1644
Matus Fabiande886752016-12-07 03:38:19 -08001645 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001646 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001647
1648 nat_ip1 = "10.0.0.30"
1649 nat_ip2 = "10.0.0.40"
1650 self.tcp_port_out = 6303
1651 self.udp_port_out = 6304
1652 self.icmp_id_out = 6305
1653
Matus Fabian2ba92e32017-08-21 07:05:03 -07001654 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1655 vrf_id=10)
1656 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1657 vrf_id=10)
1658 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1659 is_inside=0)
1660 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1661 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001662
Matus Fabian2ba92e32017-08-21 07:05:03 -07001663 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001664 pkts = self.create_stream_in(self.pg4, self.pg3)
1665 self.pg4.add_stream(pkts)
1666 self.pg_enable_capture(self.pg_interfaces)
1667 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001668 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001669 self.verify_capture_out(capture, nat_ip1, True)
1670
Matus Fabian2ba92e32017-08-21 07:05:03 -07001671 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001672 # are dropped)
1673 pkts = self.create_stream_in(self.pg0, self.pg3)
1674 self.pg0.add_stream(pkts)
1675 self.pg_enable_capture(self.pg_interfaces)
1676 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001677 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001678
Matus Fabianb793d092018-01-31 05:50:21 -08001679 def test_dynamic_to_static(self):
1680 """ Switch from dynamic translation to 1:1NAT """
1681 nat_ip = "10.0.0.10"
1682 self.tcp_port_out = 6303
1683 self.udp_port_out = 6304
1684 self.icmp_id_out = 6305
1685
1686 self.nat44_add_address(self.nat_addr)
1687 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1688 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1689 is_inside=0)
1690
1691 # dynamic
1692 pkts = self.create_stream_in(self.pg0, self.pg1)
1693 self.pg0.add_stream(pkts)
1694 self.pg_enable_capture(self.pg_interfaces)
1695 self.pg_start()
1696 capture = self.pg1.get_capture(len(pkts))
1697 self.verify_capture_out(capture)
1698
1699 # 1:1NAT
1700 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1701 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1702 self.assertEqual(len(sessions), 0)
1703 pkts = self.create_stream_in(self.pg0, self.pg1)
1704 self.pg0.add_stream(pkts)
1705 self.pg_enable_capture(self.pg_interfaces)
1706 self.pg_start()
1707 capture = self.pg1.get_capture(len(pkts))
1708 self.verify_capture_out(capture, nat_ip, True)
1709
Matus Fabianab7a8052017-11-28 04:29:41 -08001710 def test_identity_nat(self):
1711 """ Identity NAT """
1712
1713 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1714 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1715 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1716 is_inside=0)
1717
1718 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1719 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1720 TCP(sport=12345, dport=56789))
1721 self.pg1.add_stream(p)
1722 self.pg_enable_capture(self.pg_interfaces)
1723 self.pg_start()
1724 capture = self.pg0.get_capture(1)
1725 p = capture[0]
1726 try:
1727 ip = p[IP]
1728 tcp = p[TCP]
1729 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1730 self.assertEqual(ip.src, self.pg1.remote_ip4)
1731 self.assertEqual(tcp.dport, 56789)
1732 self.assertEqual(tcp.sport, 12345)
1733 self.check_tcp_checksum(p)
1734 self.check_ip_checksum(p)
1735 except:
1736 self.logger.error(ppp("Unexpected or invalid packet:", p))
1737 raise
1738
Matus Fabian704018c2017-09-04 02:17:18 -07001739 def test_static_lb(self):
1740 """ NAT44 local service load balancing """
1741 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1742 external_port = 80
1743 local_port = 8080
1744 server1 = self.pg0.remote_hosts[0]
1745 server2 = self.pg0.remote_hosts[1]
1746
1747 locals = [{'addr': server1.ip4n,
1748 'port': local_port,
1749 'probability': 70},
1750 {'addr': server2.ip4n,
1751 'port': local_port,
1752 'probability': 30}]
1753
1754 self.nat44_add_address(self.nat_addr)
1755 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1756 external_port,
1757 IP_PROTOS.tcp,
1758 local_num=len(locals),
1759 locals=locals)
1760 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1761 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1762 is_inside=0)
1763
1764 # from client to service
1765 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1766 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1767 TCP(sport=12345, dport=external_port))
1768 self.pg1.add_stream(p)
1769 self.pg_enable_capture(self.pg_interfaces)
1770 self.pg_start()
1771 capture = self.pg0.get_capture(1)
1772 p = capture[0]
1773 server = None
1774 try:
1775 ip = p[IP]
1776 tcp = p[TCP]
1777 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1778 if ip.dst == server1.ip4:
1779 server = server1
1780 else:
1781 server = server2
1782 self.assertEqual(tcp.dport, local_port)
1783 self.check_tcp_checksum(p)
1784 self.check_ip_checksum(p)
1785 except:
1786 self.logger.error(ppp("Unexpected or invalid packet:", p))
1787 raise
1788
1789 # from service back to client
1790 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1791 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1792 TCP(sport=local_port, dport=12345))
1793 self.pg0.add_stream(p)
1794 self.pg_enable_capture(self.pg_interfaces)
1795 self.pg_start()
1796 capture = self.pg1.get_capture(1)
1797 p = capture[0]
1798 try:
1799 ip = p[IP]
1800 tcp = p[TCP]
1801 self.assertEqual(ip.src, self.nat_addr)
1802 self.assertEqual(tcp.sport, external_port)
1803 self.check_tcp_checksum(p)
1804 self.check_ip_checksum(p)
1805 except:
1806 self.logger.error(ppp("Unexpected or invalid packet:", p))
1807 raise
1808
Matus Fabian2aad8762018-03-07 04:57:22 -08001809 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1810 def test_static_lb_multi_clients(self):
1811 """ NAT44 local service load balancing - multiple clients"""
1812
1813 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1814 external_port = 80
1815 local_port = 8080
1816 server1 = self.pg0.remote_hosts[0]
1817 server2 = self.pg0.remote_hosts[1]
1818
1819 locals = [{'addr': server1.ip4n,
1820 'port': local_port,
1821 'probability': 90},
1822 {'addr': server2.ip4n,
1823 'port': local_port,
1824 'probability': 10}]
1825
1826 self.nat44_add_address(self.nat_addr)
1827 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1828 external_port,
1829 IP_PROTOS.tcp,
1830 local_num=len(locals),
1831 locals=locals)
1832 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1833 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1834 is_inside=0)
1835
Matus Fabian704018c2017-09-04 02:17:18 -07001836 server1_n = 0
1837 server2_n = 0
Matus Fabian2aad8762018-03-07 04:57:22 -08001838 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
Matus Fabian704018c2017-09-04 02:17:18 -07001839 pkts = []
1840 for client in clients:
1841 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1842 IP(src=client, dst=self.nat_addr) /
1843 TCP(sport=12345, dport=external_port))
1844 pkts.append(p)
1845 self.pg1.add_stream(pkts)
1846 self.pg_enable_capture(self.pg_interfaces)
1847 self.pg_start()
1848 capture = self.pg0.get_capture(len(pkts))
1849 for p in capture:
1850 if p[IP].dst == server1.ip4:
1851 server1_n += 1
1852 else:
1853 server2_n += 1
1854 self.assertTrue(server1_n > server2_n)
1855
Matus Fabian240b5ef2018-01-11 04:09:17 -08001856 def test_static_lb_2(self):
1857 """ NAT44 local service load balancing (asymmetrical rule) """
1858 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1859 external_port = 80
1860 local_port = 8080
1861 server1 = self.pg0.remote_hosts[0]
1862 server2 = self.pg0.remote_hosts[1]
1863
1864 locals = [{'addr': server1.ip4n,
1865 'port': local_port,
1866 'probability': 70},
1867 {'addr': server2.ip4n,
1868 'port': local_port,
1869 'probability': 30}]
1870
1871 self.vapi.nat44_forwarding_enable_disable(1)
1872 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1873 external_port,
1874 IP_PROTOS.tcp,
1875 out2in_only=1,
1876 local_num=len(locals),
1877 locals=locals)
1878 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1879 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1880 is_inside=0)
1881
1882 # from client to service
1883 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1884 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1885 TCP(sport=12345, dport=external_port))
1886 self.pg1.add_stream(p)
1887 self.pg_enable_capture(self.pg_interfaces)
1888 self.pg_start()
1889 capture = self.pg0.get_capture(1)
1890 p = capture[0]
1891 server = None
1892 try:
1893 ip = p[IP]
1894 tcp = p[TCP]
1895 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1896 if ip.dst == server1.ip4:
1897 server = server1
1898 else:
1899 server = server2
1900 self.assertEqual(tcp.dport, local_port)
1901 self.check_tcp_checksum(p)
1902 self.check_ip_checksum(p)
1903 except:
1904 self.logger.error(ppp("Unexpected or invalid packet:", p))
1905 raise
1906
1907 # from service back to client
1908 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1909 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1910 TCP(sport=local_port, dport=12345))
1911 self.pg0.add_stream(p)
1912 self.pg_enable_capture(self.pg_interfaces)
1913 self.pg_start()
1914 capture = self.pg1.get_capture(1)
1915 p = capture[0]
1916 try:
1917 ip = p[IP]
1918 tcp = p[TCP]
1919 self.assertEqual(ip.src, self.nat_addr)
1920 self.assertEqual(tcp.sport, external_port)
1921 self.check_tcp_checksum(p)
1922 self.check_ip_checksum(p)
1923 except:
1924 self.logger.error(ppp("Unexpected or invalid packet:", p))
1925 raise
1926
1927 # from client to server (no translation)
1928 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1929 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1930 TCP(sport=12346, dport=local_port))
1931 self.pg1.add_stream(p)
1932 self.pg_enable_capture(self.pg_interfaces)
1933 self.pg_start()
1934 capture = self.pg0.get_capture(1)
1935 p = capture[0]
1936 server = None
1937 try:
1938 ip = p[IP]
1939 tcp = p[TCP]
1940 self.assertEqual(ip.dst, server1.ip4)
1941 self.assertEqual(tcp.dport, local_port)
1942 self.check_tcp_checksum(p)
1943 self.check_ip_checksum(p)
1944 except:
1945 self.logger.error(ppp("Unexpected or invalid packet:", p))
1946 raise
1947
1948 # from service back to client (no translation)
1949 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1950 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1951 TCP(sport=local_port, dport=12346))
1952 self.pg0.add_stream(p)
1953 self.pg_enable_capture(self.pg_interfaces)
1954 self.pg_start()
1955 capture = self.pg1.get_capture(1)
1956 p = capture[0]
1957 try:
1958 ip = p[IP]
1959 tcp = p[TCP]
1960 self.assertEqual(ip.src, server1.ip4)
1961 self.assertEqual(tcp.sport, local_port)
1962 self.check_tcp_checksum(p)
1963 self.check_ip_checksum(p)
1964 except:
1965 self.logger.error(ppp("Unexpected or invalid packet:", p))
1966 raise
1967
Matus Fabiande886752016-12-07 03:38:19 -08001968 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001969 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001970
Matus Fabian2ba92e32017-08-21 07:05:03 -07001971 self.nat44_add_address(self.nat_addr)
1972 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1973 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1974 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1975 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001976
Matus Fabian2ba92e32017-08-21 07:05:03 -07001977 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001978 pkts = self.create_stream_in(self.pg0, self.pg1)
1979 self.pg0.add_stream(pkts)
1980 self.pg_enable_capture(self.pg_interfaces)
1981 self.pg_start()
1982 capture = self.pg1.get_capture(len(pkts))
1983 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1984
Matus Fabian2ba92e32017-08-21 07:05:03 -07001985 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001986 pkts = self.create_stream_in(self.pg0, self.pg2)
1987 self.pg0.add_stream(pkts)
1988 self.pg_enable_capture(self.pg_interfaces)
1989 self.pg_start()
1990 capture = self.pg2.get_capture(len(pkts))
1991 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1992
Matus Fabiande886752016-12-07 03:38:19 -08001993 # in2out 1st interface
1994 pkts = self.create_stream_in(self.pg0, self.pg3)
1995 self.pg0.add_stream(pkts)
1996 self.pg_enable_capture(self.pg_interfaces)
1997 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001998 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001999 self.verify_capture_out(capture)
2000
2001 # out2in 1st interface
2002 pkts = self.create_stream_out(self.pg3)
2003 self.pg3.add_stream(pkts)
2004 self.pg_enable_capture(self.pg_interfaces)
2005 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002006 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002007 self.verify_capture_in(capture, self.pg0)
2008
2009 # in2out 2nd interface
2010 pkts = self.create_stream_in(self.pg1, self.pg3)
2011 self.pg1.add_stream(pkts)
2012 self.pg_enable_capture(self.pg_interfaces)
2013 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002014 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002015 self.verify_capture_out(capture)
2016
2017 # out2in 2nd interface
2018 pkts = self.create_stream_out(self.pg3)
2019 self.pg3.add_stream(pkts)
2020 self.pg_enable_capture(self.pg_interfaces)
2021 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002022 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002023 self.verify_capture_in(capture, self.pg1)
2024
Matus Fabiande886752016-12-07 03:38:19 -08002025 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002026 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002027
Matus Fabian675a69c2017-01-18 01:46:01 -08002028 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002029 self.nat44_add_address(self.nat_addr)
2030 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2031 is_inside=0)
2032 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2033 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2034 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2035 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2036 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002037
Matus Fabian2ba92e32017-08-21 07:05:03 -07002038 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002039 pkts = self.create_stream_in(self.pg4, self.pg5)
2040 self.pg4.add_stream(pkts)
2041 self.pg_enable_capture(self.pg_interfaces)
2042 self.pg_start()
2043 capture = self.pg5.get_capture(len(pkts))
2044 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2045
Matus Fabian2ba92e32017-08-21 07:05:03 -07002046 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002047 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2048 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2049 TCP(sport=1234, dport=5678))
2050 self.pg4.add_stream(p)
2051 self.pg_enable_capture(self.pg_interfaces)
2052 self.pg_start()
2053 capture = self.pg6.get_capture(1)
2054 p = capture[0]
2055 try:
2056 ip = p[IP]
2057 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002058 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002059 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2060 self.assertNotEqual(tcp.sport, 1234)
2061 self.assertEqual(tcp.dport, 5678)
2062 except:
2063 self.logger.error(ppp("Unexpected or invalid packet:", p))
2064 raise
Matus Fabiande886752016-12-07 03:38:19 -08002065
2066 # in2out 1st interface
2067 pkts = self.create_stream_in(self.pg4, self.pg3)
2068 self.pg4.add_stream(pkts)
2069 self.pg_enable_capture(self.pg_interfaces)
2070 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002071 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002072 self.verify_capture_out(capture)
2073
2074 # out2in 1st interface
2075 pkts = self.create_stream_out(self.pg3)
2076 self.pg3.add_stream(pkts)
2077 self.pg_enable_capture(self.pg_interfaces)
2078 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002079 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002080 self.verify_capture_in(capture, self.pg4)
2081
2082 # in2out 2nd interface
2083 pkts = self.create_stream_in(self.pg5, self.pg3)
2084 self.pg5.add_stream(pkts)
2085 self.pg_enable_capture(self.pg_interfaces)
2086 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002087 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002088 self.verify_capture_out(capture)
2089
2090 # out2in 2nd interface
2091 pkts = self.create_stream_out(self.pg3)
2092 self.pg3.add_stream(pkts)
2093 self.pg_enable_capture(self.pg_interfaces)
2094 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002095 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002096 self.verify_capture_in(capture, self.pg5)
2097
magalik23caa882017-02-08 23:25:45 -08002098 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002099 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002100 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002101 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002102 self.assertEqual(len(sessions), 3)
2103 for session in sessions:
2104 self.assertFalse(session.is_static)
2105 self.assertEqual(session.inside_ip_address[0:4],
2106 self.pg5.remote_ip4n)
2107 self.assertEqual(session.outside_ip_address,
2108 addresses[0].ip_address)
2109 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2110 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2111 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2112 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2113 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2114 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2115 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2116 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2117 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2118
Matus Fabiande886752016-12-07 03:38:19 -08002119 # in2out 3rd interface
2120 pkts = self.create_stream_in(self.pg6, self.pg3)
2121 self.pg6.add_stream(pkts)
2122 self.pg_enable_capture(self.pg_interfaces)
2123 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002124 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002125 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002126
2127 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002128 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002129 self.pg3.add_stream(pkts)
2130 self.pg_enable_capture(self.pg_interfaces)
2131 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002132 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002133 self.verify_capture_in(capture, self.pg6)
2134
magalik23caa882017-02-08 23:25:45 -08002135 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002136 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002137 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002138 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002139 self.assertEqual(len(addresses), 1)
2140 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002141 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2142 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002143 for session in sessions:
2144 self.assertEqual(user.ip_address, session.inside_ip_address)
2145 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2146 self.assertTrue(session.protocol in
2147 [IP_PROTOS.tcp, IP_PROTOS.udp,
2148 IP_PROTOS.icmp])
2149
2150 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002151 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002152 self.assertTrue(len(sessions) >= 4)
2153 for session in sessions:
2154 self.assertFalse(session.is_static)
2155 self.assertEqual(session.inside_ip_address[0:4],
2156 self.pg4.remote_ip4n)
2157 self.assertEqual(session.outside_ip_address,
2158 addresses[0].ip_address)
2159
2160 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002161 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002162 self.assertTrue(len(sessions) >= 3)
2163 for session in sessions:
2164 self.assertTrue(session.is_static)
2165 self.assertEqual(session.inside_ip_address[0:4],
2166 self.pg6.remote_ip4n)
2167 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2168 map(int, static_nat_ip.split('.')))
2169 self.assertTrue(session.inside_port in
2170 [self.tcp_port_in, self.udp_port_in,
2171 self.icmp_id_in])
2172
Matus Fabianf78a70d2016-12-12 04:30:39 -08002173 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002174 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002175
2176 host = self.pg0.remote_hosts[0]
2177 server = self.pg0.remote_hosts[1]
2178 host_in_port = 1234
2179 host_out_port = 0
2180 server_in_port = 5678
2181 server_out_port = 8765
2182
Matus Fabian2ba92e32017-08-21 07:05:03 -07002183 self.nat44_add_address(self.nat_addr)
2184 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2185 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2186 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002187 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002188 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2189 server_in_port, server_out_port,
2190 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002191
2192 # send packet from host to server
2193 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002194 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002195 TCP(sport=host_in_port, dport=server_out_port))
2196 self.pg0.add_stream(p)
2197 self.pg_enable_capture(self.pg_interfaces)
2198 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002199 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002200 p = capture[0]
2201 try:
2202 ip = p[IP]
2203 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002204 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002205 self.assertEqual(ip.dst, server.ip4)
2206 self.assertNotEqual(tcp.sport, host_in_port)
2207 self.assertEqual(tcp.dport, server_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002208 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002209 host_out_port = tcp.sport
2210 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002211 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002212 raise
2213
2214 # send reply from server to host
2215 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002216 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002217 TCP(sport=server_in_port, dport=host_out_port))
2218 self.pg0.add_stream(p)
2219 self.pg_enable_capture(self.pg_interfaces)
2220 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002221 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002222 p = capture[0]
2223 try:
2224 ip = p[IP]
2225 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002226 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002227 self.assertEqual(ip.dst, host.ip4)
2228 self.assertEqual(tcp.sport, server_out_port)
2229 self.assertEqual(tcp.dport, host_in_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002230 self.check_tcp_checksum(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002231 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002232 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002233 raise
2234
Matus Fabian6fa74c62017-06-05 05:55:48 -07002235 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002236 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002237
2238 server1_nat_ip = "10.0.0.10"
2239 server2_nat_ip = "10.0.0.11"
2240 host = self.pg0.remote_hosts[0]
2241 server1 = self.pg0.remote_hosts[1]
2242 server2 = self.pg0.remote_hosts[2]
2243 server_tcp_port = 22
2244 server_udp_port = 20
2245
Matus Fabian2ba92e32017-08-21 07:05:03 -07002246 self.nat44_add_address(self.nat_addr)
2247 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2248 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2249 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002250
2251 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002252 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2253 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002254
2255 # host to server1
2256 pkts = []
2257 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2258 IP(src=host.ip4, dst=server1_nat_ip) /
2259 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2260 pkts.append(p)
2261 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2262 IP(src=host.ip4, dst=server1_nat_ip) /
2263 UDP(sport=self.udp_port_in, dport=server_udp_port))
2264 pkts.append(p)
2265 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2266 IP(src=host.ip4, dst=server1_nat_ip) /
2267 ICMP(id=self.icmp_id_in, type='echo-request'))
2268 pkts.append(p)
2269 self.pg0.add_stream(pkts)
2270 self.pg_enable_capture(self.pg_interfaces)
2271 self.pg_start()
2272 capture = self.pg0.get_capture(len(pkts))
2273 for packet in capture:
2274 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002275 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002276 self.assertEqual(packet[IP].dst, server1.ip4)
2277 if packet.haslayer(TCP):
2278 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2279 self.assertEqual(packet[TCP].dport, server_tcp_port)
2280 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002281 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002282 elif packet.haslayer(UDP):
2283 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2284 self.assertEqual(packet[UDP].dport, server_udp_port)
2285 self.udp_port_out = packet[UDP].sport
2286 else:
2287 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2288 self.icmp_id_out = packet[ICMP].id
2289 except:
2290 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2291 raise
2292
2293 # server1 to host
2294 pkts = []
2295 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002296 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002297 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2298 pkts.append(p)
2299 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002300 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002301 UDP(sport=server_udp_port, dport=self.udp_port_out))
2302 pkts.append(p)
2303 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002304 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002305 ICMP(id=self.icmp_id_out, type='echo-reply'))
2306 pkts.append(p)
2307 self.pg0.add_stream(pkts)
2308 self.pg_enable_capture(self.pg_interfaces)
2309 self.pg_start()
2310 capture = self.pg0.get_capture(len(pkts))
2311 for packet in capture:
2312 try:
2313 self.assertEqual(packet[IP].src, server1_nat_ip)
2314 self.assertEqual(packet[IP].dst, host.ip4)
2315 if packet.haslayer(TCP):
2316 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2317 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002318 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002319 elif packet.haslayer(UDP):
2320 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2321 self.assertEqual(packet[UDP].sport, server_udp_port)
2322 else:
2323 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2324 except:
2325 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2326 raise
2327
2328 # server2 to server1
2329 pkts = []
2330 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2331 IP(src=server2.ip4, dst=server1_nat_ip) /
2332 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2333 pkts.append(p)
2334 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2335 IP(src=server2.ip4, dst=server1_nat_ip) /
2336 UDP(sport=self.udp_port_in, dport=server_udp_port))
2337 pkts.append(p)
2338 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2339 IP(src=server2.ip4, dst=server1_nat_ip) /
2340 ICMP(id=self.icmp_id_in, type='echo-request'))
2341 pkts.append(p)
2342 self.pg0.add_stream(pkts)
2343 self.pg_enable_capture(self.pg_interfaces)
2344 self.pg_start()
2345 capture = self.pg0.get_capture(len(pkts))
2346 for packet in capture:
2347 try:
2348 self.assertEqual(packet[IP].src, server2_nat_ip)
2349 self.assertEqual(packet[IP].dst, server1.ip4)
2350 if packet.haslayer(TCP):
2351 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2352 self.assertEqual(packet[TCP].dport, server_tcp_port)
2353 self.tcp_port_out = packet[TCP].sport
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002354 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002355 elif packet.haslayer(UDP):
2356 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2357 self.assertEqual(packet[UDP].dport, server_udp_port)
2358 self.udp_port_out = packet[UDP].sport
2359 else:
2360 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2361 self.icmp_id_out = packet[ICMP].id
2362 except:
2363 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2364 raise
2365
2366 # server1 to server2
2367 pkts = []
2368 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2369 IP(src=server1.ip4, dst=server2_nat_ip) /
2370 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2371 pkts.append(p)
2372 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2373 IP(src=server1.ip4, dst=server2_nat_ip) /
2374 UDP(sport=server_udp_port, dport=self.udp_port_out))
2375 pkts.append(p)
2376 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2377 IP(src=server1.ip4, dst=server2_nat_ip) /
2378 ICMP(id=self.icmp_id_out, type='echo-reply'))
2379 pkts.append(p)
2380 self.pg0.add_stream(pkts)
2381 self.pg_enable_capture(self.pg_interfaces)
2382 self.pg_start()
2383 capture = self.pg0.get_capture(len(pkts))
2384 for packet in capture:
2385 try:
2386 self.assertEqual(packet[IP].src, server1_nat_ip)
2387 self.assertEqual(packet[IP].dst, server2.ip4)
2388 if packet.haslayer(TCP):
2389 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2390 self.assertEqual(packet[TCP].sport, server_tcp_port)
Matus Fabian4b30ceb2017-06-09 02:33:30 -07002391 self.check_tcp_checksum(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002392 elif packet.haslayer(UDP):
2393 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2394 self.assertEqual(packet[UDP].sport, server_udp_port)
2395 else:
2396 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2397 except:
2398 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2399 raise
2400
Matus Fabian9902fcd2016-12-21 23:58:46 -08002401 def test_max_translations_per_user(self):
2402 """ MAX translations per user - recycle the least recently used """
2403
Matus Fabian2ba92e32017-08-21 07:05:03 -07002404 self.nat44_add_address(self.nat_addr)
2405 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2406 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2407 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002408
2409 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002410 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002411
2412 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002413 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002414 pkts = []
2415 for port in range(0, pkts_num):
2416 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2417 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2418 TCP(sport=1025 + port))
2419 pkts.append(p)
2420 self.pg0.add_stream(pkts)
2421 self.pg_enable_capture(self.pg_interfaces)
2422 self.pg_start()
2423
2424 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002425 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002426
Matus Fabian8bf68e82017-01-12 04:24:35 -08002427 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002428 """ Acquire NAT44 addresses from interface """
2429 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002430
2431 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002432 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002433 self.assertEqual(0, len(adresses))
2434
2435 # configure interface address and check NAT address pool
2436 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002437 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002438 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002439 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002440
2441 # remove interface address and check NAT address pool
2442 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002443 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002444 self.assertEqual(0, len(adresses))
2445
Matus Fabian36532bd2017-01-23 23:42:28 -08002446 def test_interface_addr_static_mapping(self):
2447 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002448 tag = "testTAG"
2449
Matus Fabian2ba92e32017-08-21 07:05:03 -07002450 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2451 self.nat44_add_static_mapping(
2452 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002453 external_sw_if_index=self.pg7.sw_if_index,
2454 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002455
Matus Fabiane22e5462017-02-14 23:33:43 -08002456 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002457 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002458 self.assertEqual(1, len(static_mappings))
2459 self.assertEqual(self.pg7.sw_if_index,
2460 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002461 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002462
2463 # configure interface address and check static mappings
2464 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002465 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002466 self.assertEqual(1, len(static_mappings))
2467 self.assertEqual(static_mappings[0].external_ip_address[0:4],
2468 self.pg7.local_ip4n)
Matus Fabiane22e5462017-02-14 23:33:43 -08002469 self.assertEqual(0xFFFFFFFF, static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002470 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002471
2472 # remove interface address and check static mappings
2473 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002474 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002475 self.assertEqual(0, len(static_mappings))
2476
Matus Fabianab7a8052017-11-28 04:29:41 -08002477 def test_interface_addr_identity_nat(self):
2478 """ Identity NAT with addresses from interface """
2479
2480 port = 53053
2481 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2482 self.vapi.nat44_add_del_identity_mapping(
2483 sw_if_index=self.pg7.sw_if_index,
2484 port=port,
2485 protocol=IP_PROTOS.tcp,
2486 addr_only=0)
2487
2488 # identity mappings with external interface
2489 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2490 self.assertEqual(1, len(identity_mappings))
2491 self.assertEqual(self.pg7.sw_if_index,
2492 identity_mappings[0].sw_if_index)
2493
2494 # configure interface address and check identity mappings
2495 self.pg7.config_ip4()
2496 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2497 self.assertEqual(1, len(identity_mappings))
2498 self.assertEqual(identity_mappings[0].ip_address,
2499 self.pg7.local_ip4n)
2500 self.assertEqual(0xFFFFFFFF, identity_mappings[0].sw_if_index)
2501 self.assertEqual(port, identity_mappings[0].port)
2502 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2503
2504 # remove interface address and check identity mappings
2505 self.pg7.unconfig_ip4()
2506 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2507 self.assertEqual(0, len(identity_mappings))
2508
Matus Fabianeea28d72017-01-13 04:15:54 -08002509 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002510 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002511 self.ipfix_domain_id = 10
2512 self.ipfix_src_port = 20202
2513 colector_port = 30303
2514 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002515 self.nat44_add_address(self.nat_addr)
2516 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2517 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2518 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002519 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2520 src_address=self.pg3.local_ip4n,
2521 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002522 template_interval=10,
2523 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002524 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2525 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002526
2527 pkts = self.create_stream_in(self.pg0, self.pg1)
2528 self.pg0.add_stream(pkts)
2529 self.pg_enable_capture(self.pg_interfaces)
2530 self.pg_start()
2531 capture = self.pg1.get_capture(len(pkts))
2532 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002533 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002534 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002535 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002536 ipfix = IPFIXDecoder()
2537 # first load template
2538 for p in capture:
2539 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002540 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2541 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2542 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2543 self.assertEqual(p[UDP].dport, colector_port)
2544 self.assertEqual(p[IPFIX].observationDomainID,
2545 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002546 if p.haslayer(Template):
2547 ipfix.add_template(p.getlayer(Template))
2548 # verify events in data set
2549 for p in capture:
2550 if p.haslayer(Data):
2551 data = ipfix.decode_data_set(p.getlayer(Set))
2552 self.verify_ipfix_nat44_ses(data)
2553
2554 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002555 """ IPFIX logging NAT addresses exhausted """
2556 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2557 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2558 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002559 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2560 src_address=self.pg3.local_ip4n,
2561 path_mtu=512,
2562 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002563 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2564 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002565
2566 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2567 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2568 TCP(sport=3025))
2569 self.pg0.add_stream(p)
2570 self.pg_enable_capture(self.pg_interfaces)
2571 self.pg_start()
2572 capture = self.pg1.get_capture(0)
2573 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002574 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002575 ipfix = IPFIXDecoder()
2576 # first load template
2577 for p in capture:
2578 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002579 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2580 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2581 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2582 self.assertEqual(p[UDP].dport, 4739)
2583 self.assertEqual(p[IPFIX].observationDomainID,
2584 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002585 if p.haslayer(Template):
2586 ipfix.add_template(p.getlayer(Template))
2587 # verify events in data set
2588 for p in capture:
2589 if p.haslayer(Data):
2590 data = ipfix.decode_data_set(p.getlayer(Set))
2591 self.verify_ipfix_addr_exhausted(data)
2592
Matus Fabiana431ad12018-01-04 04:03:14 -08002593 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2594 def test_ipfix_max_sessions(self):
2595 """ IPFIX logging maximum session entries exceeded """
2596 self.nat44_add_address(self.nat_addr)
2597 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2598 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2599 is_inside=0)
2600
2601 nat44_config = self.vapi.nat_show_config()
2602 max_sessions = 10 * nat44_config.translation_buckets
2603
2604 pkts = []
2605 for i in range(0, max_sessions):
2606 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2607 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2608 IP(src=src, dst=self.pg1.remote_ip4) /
2609 TCP(sport=1025))
2610 pkts.append(p)
2611 self.pg0.add_stream(pkts)
2612 self.pg_enable_capture(self.pg_interfaces)
2613 self.pg_start()
2614
2615 self.pg1.get_capture(max_sessions)
2616 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2617 src_address=self.pg3.local_ip4n,
2618 path_mtu=512,
2619 template_interval=10)
2620 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2621 src_port=self.ipfix_src_port)
2622
2623 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2624 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2625 TCP(sport=1025))
2626 self.pg0.add_stream(p)
2627 self.pg_enable_capture(self.pg_interfaces)
2628 self.pg_start()
2629 self.pg1.get_capture(0)
2630 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2631 capture = self.pg3.get_capture(9)
2632 ipfix = IPFIXDecoder()
2633 # first load template
2634 for p in capture:
2635 self.assertTrue(p.haslayer(IPFIX))
2636 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2637 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2638 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2639 self.assertEqual(p[UDP].dport, 4739)
2640 self.assertEqual(p[IPFIX].observationDomainID,
2641 self.ipfix_domain_id)
2642 if p.haslayer(Template):
2643 ipfix.add_template(p.getlayer(Template))
2644 # verify events in data set
2645 for p in capture:
2646 if p.haslayer(Data):
2647 data = ipfix.decode_data_set(p.getlayer(Set))
2648 self.verify_ipfix_max_sessions(data, max_sessions)
2649
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002650 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002651 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002652 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002653 self.nat44_add_address(self.nat_addr)
2654 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2655 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2656 is_inside=0)
2657 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002658
Matus Fabian2ba92e32017-08-21 07:05:03 -07002659 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002660 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002661 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002662 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2663 self.pg1.add_stream(p)
2664 self.pg_enable_capture(self.pg_interfaces)
2665 self.pg_start()
2666 capture = self.pg1.get_capture(1)
2667 self.assertTrue(capture[0].haslayer(ARP))
2668 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2669
2670 # 1:1 NAT address
2671 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2672 ARP(op=ARP.who_has, pdst=static_addr,
2673 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2674 self.pg1.add_stream(p)
2675 self.pg_enable_capture(self.pg_interfaces)
2676 self.pg_start()
2677 capture = self.pg1.get_capture(1)
2678 self.assertTrue(capture[0].haslayer(ARP))
2679 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2680
Matus Fabian2ba92e32017-08-21 07:05:03 -07002681 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002682 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002683 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002684 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2685 self.pg2.add_stream(p)
2686 self.pg_enable_capture(self.pg_interfaces)
2687 self.pg_start()
2688 capture = self.pg1.get_capture(0)
2689
2690 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002691 self.nat44_add_address(self.nat_addr, is_add=0)
2692 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2693 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002694
2695 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002696 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002697 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2698 self.pg1.add_stream(p)
2699 self.pg_enable_capture(self.pg_interfaces)
2700 self.pg_start()
2701 capture = self.pg1.get_capture(0)
2702
2703 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2704 ARP(op=ARP.who_has, pdst=static_addr,
2705 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2706 self.pg1.add_stream(p)
2707 self.pg_enable_capture(self.pg_interfaces)
2708 self.pg_start()
2709 capture = self.pg1.get_capture(0)
2710
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002711 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002712 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002713
2714 vrf_id1 = 1
2715 vrf_id2 = 2
2716 nat_ip1 = "10.0.0.10"
2717 nat_ip2 = "10.0.0.11"
2718
2719 self.pg0.unconfig_ip4()
2720 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002721 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2722 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002723 self.pg0.set_table_ip4(vrf_id1)
2724 self.pg1.set_table_ip4(vrf_id2)
2725 self.pg0.config_ip4()
2726 self.pg1.config_ip4()
2727
Matus Fabian2ba92e32017-08-21 07:05:03 -07002728 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2729 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2730 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2731 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2732 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2733 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002734
2735 # first VRF
2736 pkts = self.create_stream_in(self.pg0, self.pg2)
2737 self.pg0.add_stream(pkts)
2738 self.pg_enable_capture(self.pg_interfaces)
2739 self.pg_start()
2740 capture = self.pg2.get_capture(len(pkts))
2741 self.verify_capture_out(capture, nat_ip1)
2742
2743 # second VRF
2744 pkts = self.create_stream_in(self.pg1, self.pg2)
2745 self.pg1.add_stream(pkts)
2746 self.pg_enable_capture(self.pg_interfaces)
2747 self.pg_start()
2748 capture = self.pg2.get_capture(len(pkts))
2749 self.verify_capture_out(capture, nat_ip2)
2750
Neale Ranns15002542017-09-10 04:39:11 -07002751 self.pg0.unconfig_ip4()
2752 self.pg1.unconfig_ip4()
2753 self.pg0.set_table_ip4(0)
2754 self.pg1.set_table_ip4(0)
2755 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2756 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2757
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002758 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002759 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002760
2761 nat_ip1 = "10.0.0.10"
2762 nat_ip2 = "10.0.0.11"
2763
Matus Fabian2ba92e32017-08-21 07:05:03 -07002764 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002765 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002766 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_ip1)
2786
Martin Gálik406eb1d2017-05-04 04:35:04 -07002787 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002788 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002789
2790 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002791 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002792 self.pg7.remote_ip4n,
2793 is_static=1)
2794 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002795 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002796 self.pg8.remote_ip4n,
2797 is_static=1)
2798
2799 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2800 dst_address_length=32,
2801 next_hop_address=self.pg7.remote_ip4n,
2802 next_hop_sw_if_index=self.pg7.sw_if_index)
2803 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2804 dst_address_length=32,
2805 next_hop_address=self.pg8.remote_ip4n,
2806 next_hop_sw_if_index=self.pg8.sw_if_index)
2807
Matus Fabian2ba92e32017-08-21 07:05:03 -07002808 self.nat44_add_address(self.nat_addr)
2809 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2810 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2811 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002812
2813 # in2out
2814 pkts = self.create_stream_in(self.pg7, self.pg8)
2815 self.pg7.add_stream(pkts)
2816 self.pg_enable_capture(self.pg_interfaces)
2817 self.pg_start()
2818 capture = self.pg8.get_capture(len(pkts))
2819 self.verify_capture_out(capture)
2820
2821 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002822 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002823 self.pg8.add_stream(pkts)
2824 self.pg_enable_capture(self.pg_interfaces)
2825 self.pg_start()
2826 capture = self.pg7.get_capture(len(pkts))
2827 self.verify_capture_in(capture, self.pg7)
2828
2829 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002830 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002831
2832 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002833 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002834 self.pg7.remote_ip4n,
2835 is_static=1)
2836 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002837 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002838 self.pg8.remote_ip4n,
2839 is_static=1)
2840
2841 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2842 dst_address_length=32,
2843 next_hop_address=self.pg7.remote_ip4n,
2844 next_hop_sw_if_index=self.pg7.sw_if_index)
2845 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2846 dst_address_length=32,
2847 next_hop_address=self.pg8.remote_ip4n,
2848 next_hop_sw_if_index=self.pg8.sw_if_index)
2849
Matus Fabian2ba92e32017-08-21 07:05:03 -07002850 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2851 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2852 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2853 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002854
2855 # out2in
2856 pkts = self.create_stream_out(self.pg8)
2857 self.pg8.add_stream(pkts)
2858 self.pg_enable_capture(self.pg_interfaces)
2859 self.pg_start()
2860 capture = self.pg7.get_capture(len(pkts))
2861 self.verify_capture_in(capture, self.pg7)
2862
2863 # in2out
2864 pkts = self.create_stream_in(self.pg7, self.pg8)
2865 self.pg7.add_stream(pkts)
2866 self.pg_enable_capture(self.pg_interfaces)
2867 self.pg_start()
2868 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002869 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002870
2871 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002872 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002873
2874 self.tcp_port_out = 30606
2875 self.udp_port_out = 30607
2876 self.icmp_id_out = 30608
2877
2878 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002879 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002880 self.pg7.remote_ip4n,
2881 is_static=1)
2882 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002883 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002884 self.pg8.remote_ip4n,
2885 is_static=1)
2886
2887 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2888 dst_address_length=32,
2889 next_hop_address=self.pg7.remote_ip4n,
2890 next_hop_sw_if_index=self.pg7.sw_if_index)
2891 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2892 dst_address_length=32,
2893 next_hop_address=self.pg8.remote_ip4n,
2894 next_hop_sw_if_index=self.pg8.sw_if_index)
2895
Matus Fabian2ba92e32017-08-21 07:05:03 -07002896 self.nat44_add_address(self.nat_addr)
2897 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2898 self.tcp_port_in, self.tcp_port_out,
2899 proto=IP_PROTOS.tcp)
2900 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2901 self.udp_port_in, self.udp_port_out,
2902 proto=IP_PROTOS.udp)
2903 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2904 self.icmp_id_in, self.icmp_id_out,
2905 proto=IP_PROTOS.icmp)
2906 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2907 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2908 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002909
2910 # out2in
2911 pkts = self.create_stream_out(self.pg8)
2912 self.pg8.add_stream(pkts)
2913 self.pg_enable_capture(self.pg_interfaces)
2914 self.pg_start()
2915 capture = self.pg7.get_capture(len(pkts))
2916 self.verify_capture_in(capture, self.pg7)
2917
2918 # in2out
2919 pkts = self.create_stream_in(self.pg7, self.pg8)
2920 self.pg7.add_stream(pkts)
2921 self.pg_enable_capture(self.pg_interfaces)
2922 self.pg_start()
2923 capture = self.pg8.get_capture(len(pkts))
2924 self.verify_capture_out(capture)
2925
Matus Fabian328dbc82017-06-19 04:28:04 -07002926 def test_static_unknown_proto(self):
2927 """ 1:1 NAT translate packet with unknown protocol """
2928 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002929 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2930 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2931 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2932 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002933
2934 # in2out
2935 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2936 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2937 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002938 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002939 TCP(sport=1234, dport=1234))
2940 self.pg0.add_stream(p)
2941 self.pg_enable_capture(self.pg_interfaces)
2942 self.pg_start()
2943 p = self.pg1.get_capture(1)
2944 packet = p[0]
2945 try:
2946 self.assertEqual(packet[IP].src, nat_ip)
2947 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2948 self.assertTrue(packet.haslayer(GRE))
2949 self.check_ip_checksum(packet)
2950 except:
2951 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2952 raise
2953
2954 # out2in
2955 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2956 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2957 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002958 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002959 TCP(sport=1234, dport=1234))
2960 self.pg1.add_stream(p)
2961 self.pg_enable_capture(self.pg_interfaces)
2962 self.pg_start()
2963 p = self.pg0.get_capture(1)
2964 packet = p[0]
2965 try:
2966 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2967 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2968 self.assertTrue(packet.haslayer(GRE))
2969 self.check_ip_checksum(packet)
2970 except:
2971 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2972 raise
2973
Matus Fabian7968e6c2017-07-06 05:37:49 -07002974 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002975 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2976
2977 host = self.pg0.remote_hosts[0]
2978 server = self.pg0.remote_hosts[1]
2979
2980 host_nat_ip = "10.0.0.10"
2981 server_nat_ip = "10.0.0.11"
2982
Matus Fabian2ba92e32017-08-21 07:05:03 -07002983 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2984 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2985 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2986 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2987 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002988
2989 # host to server
2990 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2991 IP(src=host.ip4, dst=server_nat_ip) /
2992 GRE() /
2993 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2994 TCP(sport=1234, dport=1234))
2995 self.pg0.add_stream(p)
2996 self.pg_enable_capture(self.pg_interfaces)
2997 self.pg_start()
2998 p = self.pg0.get_capture(1)
2999 packet = p[0]
3000 try:
3001 self.assertEqual(packet[IP].src, host_nat_ip)
3002 self.assertEqual(packet[IP].dst, server.ip4)
3003 self.assertTrue(packet.haslayer(GRE))
3004 self.check_ip_checksum(packet)
3005 except:
3006 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3007 raise
3008
3009 # server to host
3010 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3011 IP(src=server.ip4, dst=host_nat_ip) /
3012 GRE() /
3013 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3014 TCP(sport=1234, dport=1234))
3015 self.pg0.add_stream(p)
3016 self.pg_enable_capture(self.pg_interfaces)
3017 self.pg_start()
3018 p = self.pg0.get_capture(1)
3019 packet = p[0]
3020 try:
3021 self.assertEqual(packet[IP].src, server_nat_ip)
3022 self.assertEqual(packet[IP].dst, host.ip4)
3023 self.assertTrue(packet.haslayer(GRE))
3024 self.check_ip_checksum(packet)
3025 except:
3026 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3027 raise
3028
Matus Fabian7968e6c2017-07-06 05:37:49 -07003029 def test_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003030 """ NAT44 translate packet with unknown protocol """
3031 self.nat44_add_address(self.nat_addr)
3032 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3033 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3034 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003035
3036 # in2out
3037 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3038 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3039 TCP(sport=self.tcp_port_in, dport=20))
3040 self.pg0.add_stream(p)
3041 self.pg_enable_capture(self.pg_interfaces)
3042 self.pg_start()
3043 p = self.pg1.get_capture(1)
3044
3045 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3046 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3047 GRE() /
3048 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3049 TCP(sport=1234, dport=1234))
3050 self.pg0.add_stream(p)
3051 self.pg_enable_capture(self.pg_interfaces)
3052 self.pg_start()
3053 p = self.pg1.get_capture(1)
3054 packet = p[0]
3055 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003056 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003057 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3058 self.assertTrue(packet.haslayer(GRE))
3059 self.check_ip_checksum(packet)
3060 except:
3061 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3062 raise
3063
3064 # out2in
3065 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003066 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003067 GRE() /
3068 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3069 TCP(sport=1234, dport=1234))
3070 self.pg1.add_stream(p)
3071 self.pg_enable_capture(self.pg_interfaces)
3072 self.pg_start()
3073 p = self.pg0.get_capture(1)
3074 packet = p[0]
3075 try:
3076 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3077 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3078 self.assertTrue(packet.haslayer(GRE))
3079 self.check_ip_checksum(packet)
3080 except:
3081 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3082 raise
3083
3084 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003085 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003086 host = self.pg0.remote_hosts[0]
3087 server = self.pg0.remote_hosts[1]
3088 host_in_port = 1234
3089 host_out_port = 0
3090 server_in_port = 5678
3091 server_out_port = 8765
3092 server_nat_ip = "10.0.0.11"
3093
Matus Fabian2ba92e32017-08-21 07:05:03 -07003094 self.nat44_add_address(self.nat_addr)
3095 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3096 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3097 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003098
3099 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003100 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003101
3102 # host to server
3103 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3104 IP(src=host.ip4, dst=server_nat_ip) /
3105 TCP(sport=host_in_port, dport=server_out_port))
3106 self.pg0.add_stream(p)
3107 self.pg_enable_capture(self.pg_interfaces)
3108 self.pg_start()
3109 capture = self.pg0.get_capture(1)
3110
3111 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3112 IP(src=host.ip4, dst=server_nat_ip) /
3113 GRE() /
3114 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3115 TCP(sport=1234, dport=1234))
3116 self.pg0.add_stream(p)
3117 self.pg_enable_capture(self.pg_interfaces)
3118 self.pg_start()
3119 p = self.pg0.get_capture(1)
3120 packet = p[0]
3121 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003122 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003123 self.assertEqual(packet[IP].dst, server.ip4)
3124 self.assertTrue(packet.haslayer(GRE))
3125 self.check_ip_checksum(packet)
3126 except:
3127 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3128 raise
3129
3130 # server to host
3131 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003132 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003133 GRE() /
3134 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3135 TCP(sport=1234, dport=1234))
3136 self.pg0.add_stream(p)
3137 self.pg_enable_capture(self.pg_interfaces)
3138 self.pg_start()
3139 p = self.pg0.get_capture(1)
3140 packet = p[0]
3141 try:
3142 self.assertEqual(packet[IP].src, server_nat_ip)
3143 self.assertEqual(packet[IP].dst, host.ip4)
3144 self.assertTrue(packet.haslayer(GRE))
3145 self.check_ip_checksum(packet)
3146 except:
3147 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3148 raise
3149
Matus Fabian93d84c92017-07-19 08:06:01 -07003150 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003151 """ NAT44 interface output feature (in2out postrouting) """
3152 self.nat44_add_address(self.nat_addr)
3153 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003154 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3155 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003156 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003157
3158 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003159 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003160 self.pg0.add_stream(pkts)
3161 self.pg_enable_capture(self.pg_interfaces)
3162 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003163 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003164 self.verify_capture_out(capture)
3165
3166 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003167 pkts = self.create_stream_out(self.pg3)
3168 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003169 self.pg_enable_capture(self.pg_interfaces)
3170 self.pg_start()
3171 capture = self.pg0.get_capture(len(pkts))
3172 self.verify_capture_in(capture, self.pg0)
3173
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003174 # from non-NAT interface to NAT inside interface
3175 pkts = self.create_stream_in(self.pg2, self.pg0)
3176 self.pg2.add_stream(pkts)
3177 self.pg_enable_capture(self.pg_interfaces)
3178 self.pg_start()
3179 capture = self.pg0.get_capture(len(pkts))
3180 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3181
Matus Fabian93d84c92017-07-19 08:06:01 -07003182 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003183 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003184 nat_ip_vrf10 = "10.0.0.10"
3185 nat_ip_vrf20 = "10.0.0.20"
3186
3187 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3188 dst_address_length=32,
3189 next_hop_address=self.pg3.remote_ip4n,
3190 next_hop_sw_if_index=self.pg3.sw_if_index,
3191 table_id=10)
3192 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3193 dst_address_length=32,
3194 next_hop_address=self.pg3.remote_ip4n,
3195 next_hop_sw_if_index=self.pg3.sw_if_index,
3196 table_id=20)
3197
Matus Fabian2ba92e32017-08-21 07:05:03 -07003198 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3199 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3200 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3201 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3202 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3203 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003204
3205 # in2out VRF 10
3206 pkts = self.create_stream_in(self.pg4, self.pg3)
3207 self.pg4.add_stream(pkts)
3208 self.pg_enable_capture(self.pg_interfaces)
3209 self.pg_start()
3210 capture = self.pg3.get_capture(len(pkts))
3211 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3212
3213 # out2in VRF 10
3214 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3215 self.pg3.add_stream(pkts)
3216 self.pg_enable_capture(self.pg_interfaces)
3217 self.pg_start()
3218 capture = self.pg4.get_capture(len(pkts))
3219 self.verify_capture_in(capture, self.pg4)
3220
3221 # in2out VRF 20
3222 pkts = self.create_stream_in(self.pg6, self.pg3)
3223 self.pg6.add_stream(pkts)
3224 self.pg_enable_capture(self.pg_interfaces)
3225 self.pg_start()
3226 capture = self.pg3.get_capture(len(pkts))
3227 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3228
3229 # out2in VRF 20
3230 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3231 self.pg3.add_stream(pkts)
3232 self.pg_enable_capture(self.pg_interfaces)
3233 self.pg_start()
3234 capture = self.pg6.get_capture(len(pkts))
3235 self.verify_capture_in(capture, self.pg6)
3236
Matus Fabian161c59c2017-07-21 03:46:03 -07003237 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003238 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003239 host = self.pg0.remote_hosts[0]
3240 server = self.pg0.remote_hosts[1]
3241 host_in_port = 1234
3242 host_out_port = 0
3243 server_in_port = 5678
3244 server_out_port = 8765
3245
Matus Fabian2ba92e32017-08-21 07:05:03 -07003246 self.nat44_add_address(self.nat_addr)
3247 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3248 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3249 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003250
3251 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003252 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3253 server_in_port, server_out_port,
3254 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003255
3256 # send packet from host to server
3257 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003258 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003259 TCP(sport=host_in_port, dport=server_out_port))
3260 self.pg0.add_stream(p)
3261 self.pg_enable_capture(self.pg_interfaces)
3262 self.pg_start()
3263 capture = self.pg0.get_capture(1)
3264 p = capture[0]
3265 try:
3266 ip = p[IP]
3267 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003268 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003269 self.assertEqual(ip.dst, server.ip4)
3270 self.assertNotEqual(tcp.sport, host_in_port)
3271 self.assertEqual(tcp.dport, server_in_port)
3272 self.check_tcp_checksum(p)
3273 host_out_port = tcp.sport
3274 except:
3275 self.logger.error(ppp("Unexpected or invalid packet:", p))
3276 raise
3277
3278 # send reply from server to host
3279 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003280 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003281 TCP(sport=server_in_port, dport=host_out_port))
3282 self.pg0.add_stream(p)
3283 self.pg_enable_capture(self.pg_interfaces)
3284 self.pg_start()
3285 capture = self.pg0.get_capture(1)
3286 p = capture[0]
3287 try:
3288 ip = p[IP]
3289 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003290 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003291 self.assertEqual(ip.dst, host.ip4)
3292 self.assertEqual(tcp.sport, server_out_port)
3293 self.assertEqual(tcp.dport, host_in_port)
3294 self.check_tcp_checksum(p)
3295 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003296 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003297 raise
3298
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003299 def test_output_feature_and_service(self):
3300 """ NAT44 interface output feature and services """
3301 external_addr = '1.2.3.4'
3302 external_port = 80
3303 local_port = 8080
3304
3305 self.vapi.nat44_forwarding_enable_disable(1)
3306 self.nat44_add_address(self.nat_addr)
3307 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3308 local_port, external_port,
3309 proto=IP_PROTOS.tcp, out2in_only=1)
3310 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3311 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3312 is_inside=0)
3313
3314 # from client to service
3315 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3316 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3317 TCP(sport=12345, dport=external_port))
3318 self.pg1.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 server = None
3324 try:
3325 ip = p[IP]
3326 tcp = p[TCP]
3327 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3328 self.assertEqual(tcp.dport, local_port)
3329 self.check_tcp_checksum(p)
3330 self.check_ip_checksum(p)
3331 except:
3332 self.logger.error(ppp("Unexpected or invalid packet:", p))
3333 raise
3334
3335 # from service back to client
3336 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3337 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3338 TCP(sport=local_port, dport=12345))
3339 self.pg0.add_stream(p)
3340 self.pg_enable_capture(self.pg_interfaces)
3341 self.pg_start()
3342 capture = self.pg1.get_capture(1)
3343 p = capture[0]
3344 try:
3345 ip = p[IP]
3346 tcp = p[TCP]
3347 self.assertEqual(ip.src, external_addr)
3348 self.assertEqual(tcp.sport, external_port)
3349 self.check_tcp_checksum(p)
3350 self.check_ip_checksum(p)
3351 except:
3352 self.logger.error(ppp("Unexpected or invalid packet:", p))
3353 raise
3354
3355 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003356 pkts = self.create_stream_in(self.pg0, self.pg1)
3357 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003358 self.pg_enable_capture(self.pg_interfaces)
3359 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003360 capture = self.pg1.get_capture(len(pkts))
3361 self.verify_capture_out(capture)
3362 pkts = self.create_stream_in(self.pg0, self.pg1)
3363 self.pg0.add_stream(pkts)
3364 self.pg_enable_capture(self.pg_interfaces)
3365 self.pg_start()
3366 capture = self.pg1.get_capture(len(pkts))
3367 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003368
3369 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003370 pkts = self.create_stream_out(self.pg1)
3371 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003372 self.pg_enable_capture(self.pg_interfaces)
3373 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003374 capture = self.pg0.get_capture(len(pkts))
3375 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003376
Matus Fabian204591d2018-03-01 04:48:33 -08003377 def test_output_feature_and_service2(self):
3378 """ NAT44 interface output feature and service host direct access """
3379 self.vapi.nat44_forwarding_enable_disable(1)
3380 self.nat44_add_address(self.nat_addr)
3381 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3382 is_inside=0)
3383
3384 # session initiaded from service host - translate
3385 pkts = self.create_stream_in(self.pg0, self.pg1)
3386 self.pg0.add_stream(pkts)
3387 self.pg_enable_capture(self.pg_interfaces)
3388 self.pg_start()
3389 capture = self.pg1.get_capture(len(pkts))
3390 self.verify_capture_out(capture)
3391
3392 pkts = self.create_stream_out(self.pg1)
3393 self.pg1.add_stream(pkts)
3394 self.pg_enable_capture(self.pg_interfaces)
3395 self.pg_start()
3396 capture = self.pg0.get_capture(len(pkts))
3397 self.verify_capture_in(capture, self.pg0)
3398
3399 tcp_port_out = self.tcp_port_out
3400 udp_port_out = self.udp_port_out
3401 icmp_id_out = self.icmp_id_out
3402
3403 # session initiaded from remote host - do not translate
3404 pkts = self.create_stream_out(self.pg1,
3405 self.pg0.remote_ip4,
3406 use_inside_ports=True)
3407 self.pg1.add_stream(pkts)
3408 self.pg_enable_capture(self.pg_interfaces)
3409 self.pg_start()
3410 capture = self.pg0.get_capture(len(pkts))
3411 self.verify_capture_in(capture, self.pg0)
3412
3413 pkts = self.create_stream_in(self.pg0, self.pg1)
3414 self.pg0.add_stream(pkts)
3415 self.pg_enable_capture(self.pg_interfaces)
3416 self.pg_start()
3417 capture = self.pg1.get_capture(len(pkts))
3418 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3419 same_port=True)
3420
Matus Fabian4d023c82018-03-22 05:50:47 -07003421 def test_output_feature_and_service3(self):
3422 """ NAT44 interface output feature and DST NAT """
3423 external_addr = '1.2.3.4'
3424 external_port = 80
3425 local_port = 8080
3426
3427 self.vapi.nat44_forwarding_enable_disable(1)
3428 self.nat44_add_address(self.nat_addr)
3429 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3430 local_port, external_port,
3431 proto=IP_PROTOS.tcp, out2in_only=1)
3432 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3433 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3434 is_inside=0)
3435 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3436 is_inside=0)
3437
3438 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3439 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3440 TCP(sport=12345, dport=external_port))
3441 self.pg0.add_stream(p)
3442 self.pg_enable_capture(self.pg_interfaces)
3443 self.pg_start()
3444 capture = self.pg1.get_capture(1)
3445 p = capture[0]
3446 try:
3447 ip = p[IP]
3448 tcp = p[TCP]
3449 self.assertEqual(ip.src, self.pg0.remote_ip4)
3450 self.assertEqual(tcp.sport, 12345)
3451 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3452 self.assertEqual(tcp.dport, local_port)
3453 self.check_tcp_checksum(p)
3454 self.check_ip_checksum(p)
3455 except:
3456 self.logger.error(ppp("Unexpected or invalid packet:", p))
3457 raise
3458
3459 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3460 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3461 TCP(sport=local_port, dport=12345))
3462 self.pg1.add_stream(p)
3463 self.pg_enable_capture(self.pg_interfaces)
3464 self.pg_start()
3465 capture = self.pg0.get_capture(1)
3466 p = capture[0]
3467 try:
3468 ip = p[IP]
3469 tcp = p[TCP]
3470 self.assertEqual(ip.src, external_addr)
3471 self.assertEqual(tcp.sport, external_port)
3472 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3473 self.assertEqual(tcp.dport, 12345)
3474 self.check_tcp_checksum(p)
3475 self.check_ip_checksum(p)
3476 except:
3477 self.logger.error(ppp("Unexpected or invalid packet:", p))
3478 raise
3479
Matus Fabian36ea2d62017-10-24 04:13:49 -07003480 def test_one_armed_nat44(self):
3481 """ One armed NAT44 """
3482 remote_host = self.pg9.remote_hosts[0]
3483 local_host = self.pg9.remote_hosts[1]
3484 external_port = 0
3485
3486 self.nat44_add_address(self.nat_addr)
3487 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3488 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3489 is_inside=0)
3490
3491 # in2out
3492 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3493 IP(src=local_host.ip4, dst=remote_host.ip4) /
3494 TCP(sport=12345, dport=80))
3495 self.pg9.add_stream(p)
3496 self.pg_enable_capture(self.pg_interfaces)
3497 self.pg_start()
3498 capture = self.pg9.get_capture(1)
3499 p = capture[0]
3500 try:
3501 ip = p[IP]
3502 tcp = p[TCP]
3503 self.assertEqual(ip.src, self.nat_addr)
3504 self.assertEqual(ip.dst, remote_host.ip4)
3505 self.assertNotEqual(tcp.sport, 12345)
3506 external_port = tcp.sport
3507 self.assertEqual(tcp.dport, 80)
3508 self.check_tcp_checksum(p)
3509 self.check_ip_checksum(p)
3510 except:
3511 self.logger.error(ppp("Unexpected or invalid packet:", p))
3512 raise
3513
3514 # out2in
3515 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3516 IP(src=remote_host.ip4, dst=self.nat_addr) /
3517 TCP(sport=80, dport=external_port))
3518 self.pg9.add_stream(p)
3519 self.pg_enable_capture(self.pg_interfaces)
3520 self.pg_start()
3521 capture = self.pg9.get_capture(1)
3522 p = capture[0]
3523 try:
3524 ip = p[IP]
3525 tcp = p[TCP]
3526 self.assertEqual(ip.src, remote_host.ip4)
3527 self.assertEqual(ip.dst, local_host.ip4)
3528 self.assertEqual(tcp.sport, 80)
3529 self.assertEqual(tcp.dport, 12345)
3530 self.check_tcp_checksum(p)
3531 self.check_ip_checksum(p)
3532 except:
3533 self.logger.error(ppp("Unexpected or invalid packet:", p))
3534 raise
3535
Matus Fabiand95c39e2018-01-23 06:07:01 -08003536 def test_one_armed_nat44_static(self):
3537 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3538 remote_host = self.pg9.remote_hosts[0]
3539 local_host = self.pg9.remote_hosts[1]
3540 external_port = 80
3541 local_port = 8080
3542 eh_port_in = 0
3543
3544 self.vapi.nat44_forwarding_enable_disable(1)
3545 self.nat44_add_address(self.nat_addr, twice_nat=1)
3546 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3547 local_port, external_port,
3548 proto=IP_PROTOS.tcp, out2in_only=1,
3549 twice_nat=1)
3550 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3551 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3552 is_inside=0)
3553
3554 # from client to service
3555 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3556 IP(src=remote_host.ip4, dst=self.nat_addr) /
3557 TCP(sport=12345, dport=external_port))
3558 self.pg9.add_stream(p)
3559 self.pg_enable_capture(self.pg_interfaces)
3560 self.pg_start()
3561 capture = self.pg9.get_capture(1)
3562 p = capture[0]
3563 server = None
3564 try:
3565 ip = p[IP]
3566 tcp = p[TCP]
3567 self.assertEqual(ip.dst, local_host.ip4)
3568 self.assertEqual(ip.src, self.nat_addr)
3569 self.assertEqual(tcp.dport, local_port)
3570 self.assertNotEqual(tcp.sport, 12345)
3571 eh_port_in = tcp.sport
3572 self.check_tcp_checksum(p)
3573 self.check_ip_checksum(p)
3574 except:
3575 self.logger.error(ppp("Unexpected or invalid packet:", p))
3576 raise
3577
3578 # from service back to client
3579 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3580 IP(src=local_host.ip4, dst=self.nat_addr) /
3581 TCP(sport=local_port, dport=eh_port_in))
3582 self.pg9.add_stream(p)
3583 self.pg_enable_capture(self.pg_interfaces)
3584 self.pg_start()
3585 capture = self.pg9.get_capture(1)
3586 p = capture[0]
3587 try:
3588 ip = p[IP]
3589 tcp = p[TCP]
3590 self.assertEqual(ip.src, self.nat_addr)
3591 self.assertEqual(ip.dst, remote_host.ip4)
3592 self.assertEqual(tcp.sport, external_port)
3593 self.assertEqual(tcp.dport, 12345)
3594 self.check_tcp_checksum(p)
3595 self.check_ip_checksum(p)
3596 except:
3597 self.logger.error(ppp("Unexpected or invalid packet:", p))
3598 raise
3599
Matus Fabian5ba86f72017-10-26 03:37:38 -07003600 def test_del_session(self):
3601 """ Delete NAT44 session """
3602 self.nat44_add_address(self.nat_addr)
3603 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3604 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3605 is_inside=0)
3606
3607 pkts = self.create_stream_in(self.pg0, self.pg1)
3608 self.pg0.add_stream(pkts)
3609 self.pg_enable_capture(self.pg_interfaces)
3610 self.pg_start()
3611 capture = self.pg1.get_capture(len(pkts))
3612
3613 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3614 nsessions = len(sessions)
3615
3616 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3617 sessions[0].inside_port,
3618 sessions[0].protocol)
3619 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3620 sessions[1].outside_port,
3621 sessions[1].protocol,
3622 is_in=0)
3623
3624 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3625 self.assertEqual(nsessions - len(sessions), 2)
3626
Matus Fabianefcd1e92017-08-15 06:59:19 -07003627 def test_set_get_reass(self):
3628 """ NAT44 set/get virtual fragmentation reassembly """
3629 reas_cfg1 = self.vapi.nat_get_reass()
3630
3631 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3632 max_reass=reas_cfg1.ip4_max_reass * 2,
3633 max_frag=reas_cfg1.ip4_max_frag * 2)
3634
3635 reas_cfg2 = self.vapi.nat_get_reass()
3636
3637 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3638 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3639 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3640
3641 self.vapi.nat_set_reass(drop_frag=1)
3642 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3643
3644 def test_frag_in_order(self):
3645 """ NAT44 translate fragments arriving in order """
3646 self.nat44_add_address(self.nat_addr)
3647 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3648 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3649 is_inside=0)
3650
3651 data = "A" * 4 + "B" * 16 + "C" * 3
3652 self.tcp_port_in = random.randint(1025, 65535)
3653
3654 reass = self.vapi.nat_reass_dump()
3655 reass_n_start = len(reass)
3656
3657 # in2out
3658 pkts = self.create_stream_frag(self.pg0,
3659 self.pg1.remote_ip4,
3660 self.tcp_port_in,
3661 20,
3662 data)
3663 self.pg0.add_stream(pkts)
3664 self.pg_enable_capture(self.pg_interfaces)
3665 self.pg_start()
3666 frags = self.pg1.get_capture(len(pkts))
3667 p = self.reass_frags_and_verify(frags,
3668 self.nat_addr,
3669 self.pg1.remote_ip4)
3670 self.assertEqual(p[TCP].dport, 20)
3671 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3672 self.tcp_port_out = p[TCP].sport
3673 self.assertEqual(data, p[Raw].load)
3674
3675 # out2in
3676 pkts = self.create_stream_frag(self.pg1,
3677 self.nat_addr,
3678 20,
3679 self.tcp_port_out,
3680 data)
3681 self.pg1.add_stream(pkts)
3682 self.pg_enable_capture(self.pg_interfaces)
3683 self.pg_start()
3684 frags = self.pg0.get_capture(len(pkts))
3685 p = self.reass_frags_and_verify(frags,
3686 self.pg1.remote_ip4,
3687 self.pg0.remote_ip4)
3688 self.assertEqual(p[TCP].sport, 20)
3689 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3690 self.assertEqual(data, p[Raw].load)
3691
3692 reass = self.vapi.nat_reass_dump()
3693 reass_n_end = len(reass)
3694
3695 self.assertEqual(reass_n_end - reass_n_start, 2)
3696
3697 def test_reass_hairpinning(self):
3698 """ NAT44 fragments hairpinning """
3699 host = self.pg0.remote_hosts[0]
3700 server = self.pg0.remote_hosts[1]
3701 host_in_port = random.randint(1025, 65535)
3702 host_out_port = 0
3703 server_in_port = random.randint(1025, 65535)
3704 server_out_port = random.randint(1025, 65535)
3705 data = "A" * 4 + "B" * 16 + "C" * 3
3706
3707 self.nat44_add_address(self.nat_addr)
3708 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3709 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3710 is_inside=0)
3711 # add static mapping for server
3712 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3713 server_in_port, server_out_port,
3714 proto=IP_PROTOS.tcp)
3715
3716 # send packet from host to server
3717 pkts = self.create_stream_frag(self.pg0,
3718 self.nat_addr,
3719 host_in_port,
3720 server_out_port,
3721 data)
3722 self.pg0.add_stream(pkts)
3723 self.pg_enable_capture(self.pg_interfaces)
3724 self.pg_start()
3725 frags = self.pg0.get_capture(len(pkts))
3726 p = self.reass_frags_and_verify(frags,
3727 self.nat_addr,
3728 server.ip4)
3729 self.assertNotEqual(p[TCP].sport, host_in_port)
3730 self.assertEqual(p[TCP].dport, server_in_port)
3731 self.assertEqual(data, p[Raw].load)
3732
3733 def test_frag_out_of_order(self):
3734 """ NAT44 translate fragments arriving out of order """
3735 self.nat44_add_address(self.nat_addr)
3736 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3737 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3738 is_inside=0)
3739
3740 data = "A" * 4 + "B" * 16 + "C" * 3
3741 random.randint(1025, 65535)
3742
3743 # in2out
3744 pkts = self.create_stream_frag(self.pg0,
3745 self.pg1.remote_ip4,
3746 self.tcp_port_in,
3747 20,
3748 data)
3749 pkts.reverse()
3750 self.pg0.add_stream(pkts)
3751 self.pg_enable_capture(self.pg_interfaces)
3752 self.pg_start()
3753 frags = self.pg1.get_capture(len(pkts))
3754 p = self.reass_frags_and_verify(frags,
3755 self.nat_addr,
3756 self.pg1.remote_ip4)
3757 self.assertEqual(p[TCP].dport, 20)
3758 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3759 self.tcp_port_out = p[TCP].sport
3760 self.assertEqual(data, p[Raw].load)
3761
3762 # out2in
3763 pkts = self.create_stream_frag(self.pg1,
3764 self.nat_addr,
3765 20,
3766 self.tcp_port_out,
3767 data)
3768 pkts.reverse()
3769 self.pg1.add_stream(pkts)
3770 self.pg_enable_capture(self.pg_interfaces)
3771 self.pg_start()
3772 frags = self.pg0.get_capture(len(pkts))
3773 p = self.reass_frags_and_verify(frags,
3774 self.pg1.remote_ip4,
3775 self.pg0.remote_ip4)
3776 self.assertEqual(p[TCP].sport, 20)
3777 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3778 self.assertEqual(data, p[Raw].load)
3779
Matus Fabian27697102017-11-09 01:43:47 -08003780 def test_port_restricted(self):
3781 """ Port restricted NAT44 (MAP-E CE) """
3782 self.nat44_add_address(self.nat_addr)
3783 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3784 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3785 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003786 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003787 "psid-offset 6 psid-len 6")
3788
3789 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3790 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3791 TCP(sport=4567, dport=22))
3792 self.pg0.add_stream(p)
3793 self.pg_enable_capture(self.pg_interfaces)
3794 self.pg_start()
3795 capture = self.pg1.get_capture(1)
3796 p = capture[0]
3797 try:
3798 ip = p[IP]
3799 tcp = p[TCP]
3800 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3801 self.assertEqual(ip.src, self.nat_addr)
3802 self.assertEqual(tcp.dport, 22)
3803 self.assertNotEqual(tcp.sport, 4567)
3804 self.assertEqual((tcp.sport >> 6) & 63, 10)
3805 self.check_tcp_checksum(p)
3806 self.check_ip_checksum(p)
3807 except:
3808 self.logger.error(ppp("Unexpected or invalid packet:", p))
3809 raise
3810
Matus Fabianb932d262017-12-18 05:38:24 -08003811 def test_twice_nat(self):
3812 """ Twice NAT44 """
3813 twice_nat_addr = '10.0.1.3'
3814 port_in = 8080
3815 port_out = 80
3816 eh_port_out = 4567
3817 eh_port_in = 0
3818 self.nat44_add_address(self.nat_addr)
3819 self.nat44_add_address(twice_nat_addr, twice_nat=1)
3820 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3821 port_in, port_out, proto=IP_PROTOS.tcp,
3822 twice_nat=1)
3823 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3824 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3825 is_inside=0)
3826
3827 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3828 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3829 TCP(sport=eh_port_out, dport=port_out))
3830 self.pg1.add_stream(p)
3831 self.pg_enable_capture(self.pg_interfaces)
3832 self.pg_start()
3833 capture = self.pg0.get_capture(1)
3834 p = capture[0]
3835 try:
3836 ip = p[IP]
3837 tcp = p[TCP]
3838 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3839 self.assertEqual(ip.src, twice_nat_addr)
3840 self.assertEqual(tcp.dport, port_in)
3841 self.assertNotEqual(tcp.sport, eh_port_out)
3842 eh_port_in = tcp.sport
3843 self.check_tcp_checksum(p)
3844 self.check_ip_checksum(p)
3845 except:
3846 self.logger.error(ppp("Unexpected or invalid packet:", p))
3847 raise
3848
3849 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3850 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3851 TCP(sport=port_in, dport=eh_port_in))
3852 self.pg0.add_stream(p)
3853 self.pg_enable_capture(self.pg_interfaces)
3854 self.pg_start()
3855 capture = self.pg1.get_capture(1)
3856 p = capture[0]
3857 try:
3858 ip = p[IP]
3859 tcp = p[TCP]
3860 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3861 self.assertEqual(ip.src, self.nat_addr)
3862 self.assertEqual(tcp.dport, eh_port_out)
3863 self.assertEqual(tcp.sport, port_out)
3864 self.check_tcp_checksum(p)
3865 self.check_ip_checksum(p)
3866 except:
3867 self.logger.error(ppp("Unexpected or invalid packet:", p))
3868 raise
3869
3870 def test_twice_nat_lb(self):
3871 """ Twice NAT44 local service load balancing """
3872 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3873 twice_nat_addr = '10.0.1.3'
3874 local_port = 8080
3875 external_port = 80
3876 eh_port_out = 4567
3877 eh_port_in = 0
3878 server1 = self.pg0.remote_hosts[0]
3879 server2 = self.pg0.remote_hosts[1]
3880
3881 locals = [{'addr': server1.ip4n,
3882 'port': local_port,
3883 'probability': 50},
3884 {'addr': server2.ip4n,
3885 'port': local_port,
3886 'probability': 50}]
3887
3888 self.nat44_add_address(self.nat_addr)
3889 self.nat44_add_address(twice_nat_addr, twice_nat=1)
3890
3891 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3892 external_port,
3893 IP_PROTOS.tcp,
3894 twice_nat=1,
3895 local_num=len(locals),
3896 locals=locals)
3897 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3898 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3899 is_inside=0)
3900
3901 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3902 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3903 TCP(sport=eh_port_out, dport=external_port))
3904 self.pg1.add_stream(p)
3905 self.pg_enable_capture(self.pg_interfaces)
3906 self.pg_start()
3907 capture = self.pg0.get_capture(1)
3908 p = capture[0]
3909 server = None
3910 try:
3911 ip = p[IP]
3912 tcp = p[TCP]
3913 self.assertEqual(ip.src, twice_nat_addr)
3914 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3915 if ip.dst == server1.ip4:
3916 server = server1
3917 else:
3918 server = server2
3919 self.assertNotEqual(tcp.sport, eh_port_out)
3920 eh_port_in = tcp.sport
3921 self.assertEqual(tcp.dport, local_port)
3922 self.check_tcp_checksum(p)
3923 self.check_ip_checksum(p)
3924 except:
3925 self.logger.error(ppp("Unexpected or invalid packet:", p))
3926 raise
3927
3928 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3929 IP(src=server.ip4, dst=twice_nat_addr) /
3930 TCP(sport=local_port, dport=eh_port_in))
3931 self.pg0.add_stream(p)
3932 self.pg_enable_capture(self.pg_interfaces)
3933 self.pg_start()
3934 capture = self.pg1.get_capture(1)
3935 p = capture[0]
3936 try:
3937 ip = p[IP]
3938 tcp = p[TCP]
3939 self.assertEqual(ip.src, self.nat_addr)
3940 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3941 self.assertEqual(tcp.sport, external_port)
3942 self.assertEqual(tcp.dport, eh_port_out)
3943 self.check_tcp_checksum(p)
3944 self.check_ip_checksum(p)
3945 except:
3946 self.logger.error(ppp("Unexpected or invalid packet:", p))
3947 raise
3948
3949 def test_twice_nat_interface_addr(self):
3950 """ Acquire twice NAT44 addresses from interface """
3951 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
3952
3953 # no address in NAT pool
3954 adresses = self.vapi.nat44_address_dump()
3955 self.assertEqual(0, len(adresses))
3956
3957 # configure interface address and check NAT address pool
3958 self.pg7.config_ip4()
3959 adresses = self.vapi.nat44_address_dump()
3960 self.assertEqual(1, len(adresses))
3961 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
3962 self.assertEqual(adresses[0].twice_nat, 1)
3963
3964 # remove interface address and check NAT address pool
3965 self.pg7.unconfig_ip4()
3966 adresses = self.vapi.nat44_address_dump()
3967 self.assertEqual(0, len(adresses))
3968
Matus Fabiana431ad12018-01-04 04:03:14 -08003969 def test_ipfix_max_frags(self):
3970 """ IPFIX logging maximum fragments pending reassembly exceeded """
3971 self.nat44_add_address(self.nat_addr)
3972 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3973 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3974 is_inside=0)
3975 self.vapi.nat_set_reass(max_frag=0)
3976 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3977 src_address=self.pg3.local_ip4n,
3978 path_mtu=512,
3979 template_interval=10)
3980 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3981 src_port=self.ipfix_src_port)
3982
3983 data = "A" * 4 + "B" * 16 + "C" * 3
3984 self.tcp_port_in = random.randint(1025, 65535)
3985 pkts = self.create_stream_frag(self.pg0,
3986 self.pg1.remote_ip4,
3987 self.tcp_port_in,
3988 20,
3989 data)
3990 self.pg0.add_stream(pkts[-1])
3991 self.pg_enable_capture(self.pg_interfaces)
3992 self.pg_start()
3993 frags = self.pg1.get_capture(0)
3994 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3995 capture = self.pg3.get_capture(9)
3996 ipfix = IPFIXDecoder()
3997 # first load template
3998 for p in capture:
3999 self.assertTrue(p.haslayer(IPFIX))
4000 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4001 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4002 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4003 self.assertEqual(p[UDP].dport, 4739)
4004 self.assertEqual(p[IPFIX].observationDomainID,
4005 self.ipfix_domain_id)
4006 if p.haslayer(Template):
4007 ipfix.add_template(p.getlayer(Template))
4008 # verify events in data set
4009 for p in capture:
4010 if p.haslayer(Data):
4011 data = ipfix.decode_data_set(p.getlayer(Set))
4012 self.verify_ipfix_max_fragments_ip4(data, 0,
4013 self.pg0.remote_ip4n)
4014
Matus Fabiande886752016-12-07 03:38:19 -08004015 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004016 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004017 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004018 self.logger.info(self.vapi.cli("show nat44 addresses"))
4019 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4020 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4021 self.logger.info(self.vapi.cli("show nat44 interface address"))
4022 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004023 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004024 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004025 self.clear_nat44()
Matus Fabiande886752016-12-07 03:38:19 -08004026
Matus Fabianeea28d72017-01-13 04:15:54 -08004027
Juraj Slobodacba69362017-12-19 02:09:32 +01004028class TestNAT44Out2InDPO(MethodHolder):
4029 """ NAT44 Test Cases using out2in DPO """
4030
4031 @classmethod
4032 def setUpConstants(cls):
4033 super(TestNAT44Out2InDPO, cls).setUpConstants()
4034 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4035
4036 @classmethod
4037 def setUpClass(cls):
4038 super(TestNAT44Out2InDPO, cls).setUpClass()
4039
4040 try:
4041 cls.tcp_port_in = 6303
4042 cls.tcp_port_out = 6303
4043 cls.udp_port_in = 6304
4044 cls.udp_port_out = 6304
4045 cls.icmp_id_in = 6305
4046 cls.icmp_id_out = 6305
4047 cls.nat_addr = '10.0.0.3'
4048 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4049 cls.dst_ip4 = '192.168.70.1'
4050
4051 cls.create_pg_interfaces(range(2))
4052
4053 cls.pg0.admin_up()
4054 cls.pg0.config_ip4()
4055 cls.pg0.resolve_arp()
4056
4057 cls.pg1.admin_up()
4058 cls.pg1.config_ip6()
4059 cls.pg1.resolve_ndp()
4060
4061 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4062 dst_address_length=0,
4063 next_hop_address=cls.pg1.remote_ip6n,
4064 next_hop_sw_if_index=cls.pg1.sw_if_index)
4065
4066 except Exception:
4067 super(TestNAT44Out2InDPO, cls).tearDownClass()
4068 raise
4069
4070 def configure_xlat(self):
4071 self.dst_ip6_pfx = '1:2:3::'
4072 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4073 self.dst_ip6_pfx)
4074 self.dst_ip6_pfx_len = 96
4075 self.src_ip6_pfx = '4:5:6::'
4076 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4077 self.src_ip6_pfx)
4078 self.src_ip6_pfx_len = 96
4079 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4080 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4081 '\x00\x00\x00\x00', 0, is_translation=1,
4082 is_rfc6052=1)
4083
4084 def test_464xlat_ce(self):
4085 """ Test 464XLAT CE with NAT44 """
4086
4087 self.configure_xlat()
4088
4089 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4090 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4091
4092 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4093 self.dst_ip6_pfx_len)
4094 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4095 self.src_ip6_pfx_len)
4096
4097 try:
4098 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4099 self.pg0.add_stream(pkts)
4100 self.pg_enable_capture(self.pg_interfaces)
4101 self.pg_start()
4102 capture = self.pg1.get_capture(len(pkts))
4103 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4104 dst_ip=out_src_ip6)
4105
4106 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4107 out_dst_ip6)
4108 self.pg1.add_stream(pkts)
4109 self.pg_enable_capture(self.pg_interfaces)
4110 self.pg_start()
4111 capture = self.pg0.get_capture(len(pkts))
4112 self.verify_capture_in(capture, self.pg0)
4113 finally:
4114 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4115 is_add=0)
4116 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4117 self.nat_addr_n, is_add=0)
4118
4119 def test_464xlat_ce_no_nat(self):
4120 """ Test 464XLAT CE without NAT44 """
4121
4122 self.configure_xlat()
4123
4124 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4125 self.dst_ip6_pfx_len)
4126 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4127 self.src_ip6_pfx_len)
4128
4129 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4130 self.pg0.add_stream(pkts)
4131 self.pg_enable_capture(self.pg_interfaces)
4132 self.pg_start()
4133 capture = self.pg1.get_capture(len(pkts))
4134 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4135 nat_ip=out_dst_ip6, same_port=True)
4136
4137 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4138 self.pg1.add_stream(pkts)
4139 self.pg_enable_capture(self.pg_interfaces)
4140 self.pg_start()
4141 capture = self.pg0.get_capture(len(pkts))
4142 self.verify_capture_in(capture, self.pg0)
4143
4144
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004145class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004146 """ Deterministic NAT Test Cases """
4147
4148 @classmethod
4149 def setUpConstants(cls):
4150 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004151 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004152
4153 @classmethod
4154 def setUpClass(cls):
4155 super(TestDeterministicNAT, cls).setUpClass()
4156
4157 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004158 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004159 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004160 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004161 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004162 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004163 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004164
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004165 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004166 cls.interfaces = list(cls.pg_interfaces)
4167
4168 for i in cls.interfaces:
4169 i.admin_up()
4170 i.config_ip4()
4171 i.resolve_arp()
4172
Martin Gálik977c1cb2017-03-30 23:21:51 -07004173 cls.pg0.generate_remote_hosts(2)
4174 cls.pg0.configure_ipv4_neighbors()
4175
Matus Fabian066f0342017-02-10 03:48:01 -08004176 except Exception:
4177 super(TestDeterministicNAT, cls).tearDownClass()
4178 raise
4179
Martin Gálik977c1cb2017-03-30 23:21:51 -07004180 def create_stream_in(self, in_if, out_if, ttl=64):
4181 """
4182 Create packet stream for inside network
4183
4184 :param in_if: Inside interface
4185 :param out_if: Outside interface
4186 :param ttl: TTL of generated packets
4187 """
4188 pkts = []
4189 # TCP
4190 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4191 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004192 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004193 pkts.append(p)
4194
4195 # UDP
4196 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4197 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004198 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004199 pkts.append(p)
4200
4201 # ICMP
4202 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4203 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4204 ICMP(id=self.icmp_id_in, type='echo-request'))
4205 pkts.append(p)
4206
4207 return pkts
4208
4209 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4210 """
4211 Create packet stream for outside network
4212
4213 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004214 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004215 :param ttl: TTL of generated packets
4216 """
4217 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004218 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004219 pkts = []
4220 # TCP
4221 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4222 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004223 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004224 pkts.append(p)
4225
4226 # UDP
4227 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4228 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004229 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004230 pkts.append(p)
4231
4232 # ICMP
4233 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4234 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4235 ICMP(id=self.icmp_external_id, type='echo-reply'))
4236 pkts.append(p)
4237
4238 return pkts
4239
4240 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4241 """
4242 Verify captured packets on outside network
4243
4244 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004245 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004246 :param same_port: Sorce port number is not translated (Default False)
4247 :param packet_num: Expected number of packets (Default 3)
4248 """
4249 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004250 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004251 self.assertEqual(packet_num, len(capture))
4252 for packet in capture:
4253 try:
4254 self.assertEqual(packet[IP].src, nat_ip)
4255 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004256 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004257 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004258 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004259 else:
4260 self.icmp_external_id = packet[ICMP].id
4261 except:
4262 self.logger.error(ppp("Unexpected or invalid packet "
4263 "(outside network):", packet))
4264 raise
4265
4266 def initiate_tcp_session(self, in_if, out_if):
4267 """
4268 Initiates TCP session
4269
4270 :param in_if: Inside interface
4271 :param out_if: Outside interface
4272 """
4273 try:
4274 # SYN packet in->out
4275 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
4276 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004277 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004278 flags="S"))
4279 in_if.add_stream(p)
4280 self.pg_enable_capture(self.pg_interfaces)
4281 self.pg_start()
4282 capture = out_if.get_capture(1)
4283 p = capture[0]
Martin Gálik9806eae2017-04-25 01:25:08 -07004284 self.tcp_port_out = p[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004285
4286 # SYN + ACK packet out->in
4287 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004288 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004289 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004290 flags="SA"))
4291 out_if.add_stream(p)
4292 self.pg_enable_capture(self.pg_interfaces)
4293 self.pg_start()
4294 in_if.get_capture(1)
4295
4296 # ACK packet in->out
4297 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
4298 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004299 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004300 flags="A"))
4301 in_if.add_stream(p)
4302 self.pg_enable_capture(self.pg_interfaces)
4303 self.pg_start()
4304 out_if.get_capture(1)
4305
4306 except:
4307 self.logger.error("TCP 3 way handshake failed")
4308 raise
4309
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004310 def verify_ipfix_max_entries_per_user(self, data):
4311 """
4312 Verify IPFIX maximum entries per user exceeded event
4313
4314 :param data: Decoded IPFIX data records
4315 """
4316 self.assertEqual(1, len(data))
4317 record = data[0]
4318 # natEvent
4319 self.assertEqual(ord(record[230]), 13)
4320 # natQuotaExceededEvent
4321 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004322 # maxEntriesPerUser
4323 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004324 # sourceIPv4Address
4325 self.assertEqual(self.pg0.remote_ip4n, record[8])
4326
Matus Fabian066f0342017-02-10 03:48:01 -08004327 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004328 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004329 in_addr = '172.16.255.0'
4330 out_addr = '172.17.255.50'
4331 in_addr_t = '172.16.255.20'
4332 in_addr_n = socket.inet_aton(in_addr)
4333 out_addr_n = socket.inet_aton(out_addr)
4334 in_addr_t_n = socket.inet_aton(in_addr_t)
4335 in_plen = 24
4336 out_plen = 32
4337
Matus Fabian2ba92e32017-08-21 07:05:03 -07004338 nat_config = self.vapi.nat_show_config()
4339 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004340
Matus Fabian2ba92e32017-08-21 07:05:03 -07004341 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004342
Matus Fabian2ba92e32017-08-21 07:05:03 -07004343 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004344 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004345 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004346 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4347
Matus Fabian2ba92e32017-08-21 07:05:03 -07004348 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004349 self.assertEqual(len(deterministic_mappings), 1)
4350 dsm = deterministic_mappings[0]
4351 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4352 self.assertEqual(in_plen, dsm.in_plen)
4353 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4354 self.assertEqual(out_plen, dsm.out_plen)
4355
Matus Fabian2ba92e32017-08-21 07:05:03 -07004356 self.clear_nat_det()
4357 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004358 self.assertEqual(len(deterministic_mappings), 0)
4359
Matus Fabian6a0946f2017-04-12 03:36:13 -07004360 def test_set_timeouts(self):
4361 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004362 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004363
Matus Fabian2ba92e32017-08-21 07:05:03 -07004364 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4365 timeouts_before.tcp_established + 10,
4366 timeouts_before.tcp_transitory + 10,
4367 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004368
Matus Fabian2ba92e32017-08-21 07:05:03 -07004369 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004370
4371 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4372 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4373 self.assertNotEqual(timeouts_before.tcp_established,
4374 timeouts_after.tcp_established)
4375 self.assertNotEqual(timeouts_before.tcp_transitory,
4376 timeouts_after.tcp_transitory)
4377
Martin Gálik977c1cb2017-03-30 23:21:51 -07004378 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004379 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004380
4381 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004382
Matus Fabian2ba92e32017-08-21 07:05:03 -07004383 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4384 32,
4385 socket.inet_aton(nat_ip),
4386 32)
4387 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4388 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4389 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004390
4391 # in2out
4392 pkts = self.create_stream_in(self.pg0, self.pg1)
4393 self.pg0.add_stream(pkts)
4394 self.pg_enable_capture(self.pg_interfaces)
4395 self.pg_start()
4396 capture = self.pg1.get_capture(len(pkts))
4397 self.verify_capture_out(capture, nat_ip)
4398
4399 # out2in
4400 pkts = self.create_stream_out(self.pg1, nat_ip)
4401 self.pg1.add_stream(pkts)
4402 self.pg_enable_capture(self.pg_interfaces)
4403 self.pg_start()
4404 capture = self.pg0.get_capture(len(pkts))
4405 self.verify_capture_in(capture, self.pg0)
4406
Martin Gálik9806eae2017-04-25 01:25:08 -07004407 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004408 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004409 self.assertEqual(len(sessions), 3)
4410
4411 # TCP session
4412 s = sessions[0]
4413 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4414 self.assertEqual(s.in_port, self.tcp_port_in)
4415 self.assertEqual(s.out_port, self.tcp_port_out)
4416 self.assertEqual(s.ext_port, self.tcp_external_port)
4417
4418 # UDP session
4419 s = sessions[1]
4420 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4421 self.assertEqual(s.in_port, self.udp_port_in)
4422 self.assertEqual(s.out_port, self.udp_port_out)
4423 self.assertEqual(s.ext_port, self.udp_external_port)
4424
4425 # ICMP session
4426 s = sessions[2]
4427 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4428 self.assertEqual(s.in_port, self.icmp_id_in)
4429 self.assertEqual(s.out_port, self.icmp_external_id)
4430
Martin Gálik977c1cb2017-03-30 23:21:51 -07004431 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004432 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004433
4434 nat_ip = "10.0.0.10"
4435 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004436 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004437
4438 host0 = self.pg0.remote_hosts[0]
4439 host1 = self.pg0.remote_hosts[1]
4440
Matus Fabian2ba92e32017-08-21 07:05:03 -07004441 self.vapi.nat_det_add_del_map(host0.ip4n,
4442 24,
4443 socket.inet_aton(nat_ip),
4444 32)
4445 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4446 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4447 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004448
4449 # host0 to out
4450 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4451 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004452 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004453 self.pg0.add_stream(p)
4454 self.pg_enable_capture(self.pg_interfaces)
4455 self.pg_start()
4456 capture = self.pg1.get_capture(1)
4457 p = capture[0]
4458 try:
4459 ip = p[IP]
4460 tcp = p[TCP]
4461 self.assertEqual(ip.src, nat_ip)
4462 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004463 self.assertEqual(tcp.dport, external_port)
4464 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004465 except:
4466 self.logger.error(ppp("Unexpected or invalid packet:", p))
4467 raise
4468
4469 # host1 to out
4470 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4471 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004472 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004473 self.pg0.add_stream(p)
4474 self.pg_enable_capture(self.pg_interfaces)
4475 self.pg_start()
4476 capture = self.pg1.get_capture(1)
4477 p = capture[0]
4478 try:
4479 ip = p[IP]
4480 tcp = p[TCP]
4481 self.assertEqual(ip.src, nat_ip)
4482 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004483 self.assertEqual(tcp.dport, external_port)
4484 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004485 except:
4486 self.logger.error(ppp("Unexpected or invalid packet:", p))
4487 raise
4488
Matus Fabian2ba92e32017-08-21 07:05:03 -07004489 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004490 self.assertEqual(1, len(dms))
4491 self.assertEqual(2, dms[0].ses_num)
4492
4493 # out to host0
4494 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4495 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004496 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004497 self.pg1.add_stream(p)
4498 self.pg_enable_capture(self.pg_interfaces)
4499 self.pg_start()
4500 capture = self.pg0.get_capture(1)
4501 p = capture[0]
4502 try:
4503 ip = p[IP]
4504 tcp = p[TCP]
4505 self.assertEqual(ip.src, self.pg1.remote_ip4)
4506 self.assertEqual(ip.dst, host0.ip4)
4507 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004508 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004509 except:
4510 self.logger.error(ppp("Unexpected or invalid packet:", p))
4511 raise
4512
4513 # out to host1
4514 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4515 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004516 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004517 self.pg1.add_stream(p)
4518 self.pg_enable_capture(self.pg_interfaces)
4519 self.pg_start()
4520 capture = self.pg0.get_capture(1)
4521 p = capture[0]
4522 try:
4523 ip = p[IP]
4524 tcp = p[TCP]
4525 self.assertEqual(ip.src, self.pg1.remote_ip4)
4526 self.assertEqual(ip.dst, host1.ip4)
4527 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004528 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004529 except:
4530 self.logger.error(ppp("Unexpected or invalid packet", p))
4531 raise
4532
Martin Gálik6bc8c642017-04-19 01:12:27 -07004533 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004534 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4535 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004536 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004537 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004538 dms = self.vapi.nat_det_map_dump()
4539 self.assertEqual(dms[0].ses_num, 1)
4540
4541 self.vapi.nat_det_close_session_in(host0.ip4n,
4542 port_in,
4543 self.pg1.remote_ip4n,
4544 external_port)
4545 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004546 self.assertEqual(dms[0].ses_num, 0)
4547
Martin Gálik977c1cb2017-03-30 23:21:51 -07004548 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004549 """ Deterministic NAT TCP session close from inside network """
4550 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4551 32,
4552 socket.inet_aton(self.nat_addr),
4553 32)
4554 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4555 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4556 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004557
4558 self.initiate_tcp_session(self.pg0, self.pg1)
4559
4560 # close the session from inside
4561 try:
4562 # FIN packet in -> out
4563 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4564 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004565 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004566 flags="F"))
4567 self.pg0.add_stream(p)
4568 self.pg_enable_capture(self.pg_interfaces)
4569 self.pg_start()
4570 self.pg1.get_capture(1)
4571
4572 pkts = []
4573
4574 # ACK packet out -> in
4575 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004576 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004577 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004578 flags="A"))
4579 pkts.append(p)
4580
4581 # FIN packet out -> in
4582 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004583 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004584 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004585 flags="F"))
4586 pkts.append(p)
4587
4588 self.pg1.add_stream(pkts)
4589 self.pg_enable_capture(self.pg_interfaces)
4590 self.pg_start()
4591 self.pg0.get_capture(2)
4592
4593 # ACK packet in -> out
4594 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4595 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004596 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004597 flags="A"))
4598 self.pg0.add_stream(p)
4599 self.pg_enable_capture(self.pg_interfaces)
4600 self.pg_start()
4601 self.pg1.get_capture(1)
4602
Matus Fabian2ba92e32017-08-21 07:05:03 -07004603 # Check if deterministic NAT44 closed the session
4604 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004605 self.assertEqual(0, dms[0].ses_num)
4606 except:
4607 self.logger.error("TCP session termination failed")
4608 raise
4609
4610 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004611 """ Deterministic NAT TCP session close from outside network """
4612 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4613 32,
4614 socket.inet_aton(self.nat_addr),
4615 32)
4616 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4617 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4618 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004619
4620 self.initiate_tcp_session(self.pg0, self.pg1)
4621
4622 # close the session from outside
4623 try:
4624 # FIN packet out -> in
4625 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004626 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004627 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004628 flags="F"))
4629 self.pg1.add_stream(p)
4630 self.pg_enable_capture(self.pg_interfaces)
4631 self.pg_start()
4632 self.pg0.get_capture(1)
4633
4634 pkts = []
4635
4636 # ACK packet in -> out
4637 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4638 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004639 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004640 flags="A"))
4641 pkts.append(p)
4642
4643 # ACK packet in -> out
4644 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4645 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004646 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004647 flags="F"))
4648 pkts.append(p)
4649
4650 self.pg0.add_stream(pkts)
4651 self.pg_enable_capture(self.pg_interfaces)
4652 self.pg_start()
4653 self.pg1.get_capture(2)
4654
4655 # ACK packet out -> in
4656 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004657 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004658 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004659 flags="A"))
4660 self.pg1.add_stream(p)
4661 self.pg_enable_capture(self.pg_interfaces)
4662 self.pg_start()
4663 self.pg0.get_capture(1)
4664
Matus Fabian2ba92e32017-08-21 07:05:03 -07004665 # Check if deterministic NAT44 closed the session
4666 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004667 self.assertEqual(0, dms[0].ses_num)
4668 except:
4669 self.logger.error("TCP session termination failed")
4670 raise
4671
4672 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4673 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004674 """ Deterministic NAT session timeouts """
4675 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4676 32,
4677 socket.inet_aton(self.nat_addr),
4678 32)
4679 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4680 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4681 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004682
4683 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004684 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004685 pkts = self.create_stream_in(self.pg0, self.pg1)
4686 self.pg0.add_stream(pkts)
4687 self.pg_enable_capture(self.pg_interfaces)
4688 self.pg_start()
4689 capture = self.pg1.get_capture(len(pkts))
4690 sleep(15)
4691
Matus Fabian2ba92e32017-08-21 07:05:03 -07004692 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004693 self.assertEqual(0, dms[0].ses_num)
4694
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004695 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004696 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004697 """ Deterministic NAT maximum sessions per user limit """
4698 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4699 32,
4700 socket.inet_aton(self.nat_addr),
4701 32)
4702 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4703 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4704 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004705 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4706 src_address=self.pg2.local_ip4n,
4707 path_mtu=512,
4708 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004709 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004710
4711 pkts = []
4712 for port in range(1025, 2025):
4713 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4714 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4715 UDP(sport=port, dport=port))
4716 pkts.append(p)
4717
4718 self.pg0.add_stream(pkts)
4719 self.pg_enable_capture(self.pg_interfaces)
4720 self.pg_start()
4721 capture = self.pg1.get_capture(len(pkts))
4722
4723 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4724 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07004725 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004726 self.pg0.add_stream(p)
4727 self.pg_enable_capture(self.pg_interfaces)
4728 self.pg_start()
4729 capture = self.pg1.assert_nothing_captured()
4730
Martin Gálikf7e655d2017-04-27 02:13:26 -07004731 # verify ICMP error packet
4732 capture = self.pg0.get_capture(1)
4733 p = capture[0]
4734 self.assertTrue(p.haslayer(ICMP))
4735 icmp = p[ICMP]
4736 self.assertEqual(icmp.type, 3)
4737 self.assertEqual(icmp.code, 1)
4738 self.assertTrue(icmp.haslayer(IPerror))
4739 inner_ip = icmp[IPerror]
4740 self.assertEqual(inner_ip[UDPerror].sport, 3001)
4741 self.assertEqual(inner_ip[UDPerror].dport, 3002)
4742
Matus Fabian2ba92e32017-08-21 07:05:03 -07004743 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004744
4745 self.assertEqual(1000, dms[0].ses_num)
4746
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004747 # verify IPFIX logging
4748 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004749 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004750 capture = self.pg2.get_capture(2)
4751 ipfix = IPFIXDecoder()
4752 # first load template
4753 for p in capture:
4754 self.assertTrue(p.haslayer(IPFIX))
4755 if p.haslayer(Template):
4756 ipfix.add_template(p.getlayer(Template))
4757 # verify events in data set
4758 for p in capture:
4759 if p.haslayer(Data):
4760 data = ipfix.decode_data_set(p.getlayer(Set))
4761 self.verify_ipfix_max_entries_per_user(data)
4762
Matus Fabian2ba92e32017-08-21 07:05:03 -07004763 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08004764 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004765 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08004766 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004767 self.vapi.nat_ipfix(enable=0)
4768 self.vapi.nat_det_set_timeouts()
4769 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004770 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004771 self.vapi.nat_det_add_del_map(dsm.in_addr,
4772 dsm.in_plen,
4773 dsm.out_addr,
4774 dsm.out_plen,
4775 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08004776
Matus Fabian2ba92e32017-08-21 07:05:03 -07004777 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004778 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004779 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
4780 intf.is_inside,
4781 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004782
Matus Fabian066f0342017-02-10 03:48:01 -08004783 def tearDown(self):
4784 super(TestDeterministicNAT, self).tearDown()
4785 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004786 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4787 self.logger.info(
4788 self.vapi.cli("show nat44 deterministic mappings"))
4789 self.logger.info(
4790 self.vapi.cli("show nat44 deterministic timeouts"))
4791 self.logger.info(
4792 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07004793 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08004794
Matus Fabian06596c52017-06-06 04:53:28 -07004795
4796class TestNAT64(MethodHolder):
4797 """ NAT64 Test Cases """
4798
4799 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08004800 def setUpConstants(cls):
4801 super(TestNAT64, cls).setUpConstants()
4802 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
4803 "nat64 st hash buckets 256", "}"])
4804
4805 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07004806 def setUpClass(cls):
4807 super(TestNAT64, cls).setUpClass()
4808
4809 try:
4810 cls.tcp_port_in = 6303
4811 cls.tcp_port_out = 6303
4812 cls.udp_port_in = 6304
4813 cls.udp_port_out = 6304
4814 cls.icmp_id_in = 6305
4815 cls.icmp_id_out = 6305
4816 cls.nat_addr = '10.0.0.3'
4817 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07004818 cls.vrf1_id = 10
4819 cls.vrf1_nat_addr = '10.0.10.3'
4820 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
4821 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08004822 cls.ipfix_src_port = 4739
4823 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07004824
Matus Fabian0938dcf2017-11-08 01:59:38 -08004825 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07004826 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07004827 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07004828 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
4829
Neale Ranns15002542017-09-10 04:39:11 -07004830 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
4831
Matus Fabian029f3d22017-06-15 02:28:50 -07004832 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
4833
4834 cls.pg0.generate_remote_hosts(2)
4835
Matus Fabian06596c52017-06-06 04:53:28 -07004836 for i in cls.ip6_interfaces:
4837 i.admin_up()
4838 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07004839 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07004840
4841 for i in cls.ip4_interfaces:
4842 i.admin_up()
4843 i.config_ip4()
4844 i.resolve_arp()
4845
Matus Fabian36ea2d62017-10-24 04:13:49 -07004846 cls.pg3.admin_up()
4847 cls.pg3.config_ip4()
4848 cls.pg3.resolve_arp()
4849 cls.pg3.config_ip6()
4850 cls.pg3.configure_ipv6_neighbors()
4851
Matus Fabian06596c52017-06-06 04:53:28 -07004852 except Exception:
4853 super(TestNAT64, cls).tearDownClass()
4854 raise
4855
4856 def test_pool(self):
4857 """ Add/delete address to NAT64 pool """
4858 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
4859
4860 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
4861
4862 addresses = self.vapi.nat64_pool_addr_dump()
4863 self.assertEqual(len(addresses), 1)
4864 self.assertEqual(addresses[0].address, nat_addr)
4865
4866 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
4867
4868 addresses = self.vapi.nat64_pool_addr_dump()
4869 self.assertEqual(len(addresses), 0)
4870
4871 def test_interface(self):
4872 """ Enable/disable NAT64 feature on the interface """
4873 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
4874 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
4875
4876 interfaces = self.vapi.nat64_interface_dump()
4877 self.assertEqual(len(interfaces), 2)
4878 pg0_found = False
4879 pg1_found = False
4880 for intf in interfaces:
4881 if intf.sw_if_index == self.pg0.sw_if_index:
4882 self.assertEqual(intf.is_inside, 1)
4883 pg0_found = True
4884 elif intf.sw_if_index == self.pg1.sw_if_index:
4885 self.assertEqual(intf.is_inside, 0)
4886 pg1_found = True
4887 self.assertTrue(pg0_found)
4888 self.assertTrue(pg1_found)
4889
4890 features = self.vapi.cli("show interface features pg0")
4891 self.assertNotEqual(features.find('nat64-in2out'), -1)
4892 features = self.vapi.cli("show interface features pg1")
4893 self.assertNotEqual(features.find('nat64-out2in'), -1)
4894
4895 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
4896 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
4897
4898 interfaces = self.vapi.nat64_interface_dump()
4899 self.assertEqual(len(interfaces), 0)
4900
4901 def test_static_bib(self):
4902 """ Add/delete static BIB entry """
4903 in_addr = socket.inet_pton(socket.AF_INET6,
4904 '2001:db8:85a3::8a2e:370:7334')
4905 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
4906 in_port = 1234
4907 out_port = 5678
4908 proto = IP_PROTOS.tcp
4909
4910 self.vapi.nat64_add_del_static_bib(in_addr,
4911 out_addr,
4912 in_port,
4913 out_port,
4914 proto)
4915 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
4916 static_bib_num = 0
4917 for bibe in bib:
4918 if bibe.is_static:
4919 static_bib_num += 1
4920 self.assertEqual(bibe.i_addr, in_addr)
4921 self.assertEqual(bibe.o_addr, out_addr)
4922 self.assertEqual(bibe.i_port, in_port)
4923 self.assertEqual(bibe.o_port, out_port)
4924 self.assertEqual(static_bib_num, 1)
4925
4926 self.vapi.nat64_add_del_static_bib(in_addr,
4927 out_addr,
4928 in_port,
4929 out_port,
4930 proto,
4931 is_add=0)
4932 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
4933 static_bib_num = 0
4934 for bibe in bib:
4935 if bibe.is_static:
4936 static_bib_num += 1
4937 self.assertEqual(static_bib_num, 0)
4938
4939 def test_set_timeouts(self):
4940 """ Set NAT64 timeouts """
4941 # verify default values
4942 timeouts = self.vapi.nat64_get_timeouts()
4943 self.assertEqual(timeouts.udp, 300)
4944 self.assertEqual(timeouts.icmp, 60)
4945 self.assertEqual(timeouts.tcp_trans, 240)
4946 self.assertEqual(timeouts.tcp_est, 7440)
4947 self.assertEqual(timeouts.tcp_incoming_syn, 6)
4948
4949 # set and verify custom values
4950 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
4951 tcp_est=7450, tcp_incoming_syn=10)
4952 timeouts = self.vapi.nat64_get_timeouts()
4953 self.assertEqual(timeouts.udp, 200)
4954 self.assertEqual(timeouts.icmp, 30)
4955 self.assertEqual(timeouts.tcp_trans, 250)
4956 self.assertEqual(timeouts.tcp_est, 7450)
4957 self.assertEqual(timeouts.tcp_incoming_syn, 10)
4958
4959 def test_dynamic(self):
4960 """ NAT64 dynamic translation test """
4961 self.tcp_port_in = 6303
4962 self.udp_port_in = 6304
4963 self.icmp_id_in = 6305
4964
4965 ses_num_start = self.nat64_get_ses_num()
4966
4967 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
4968 self.nat_addr_n)
4969 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
4970 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
4971
4972 # in2out
4973 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
4974 self.pg0.add_stream(pkts)
4975 self.pg_enable_capture(self.pg_interfaces)
4976 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07004977 capture = self.pg1.get_capture(len(pkts))
4978 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07004979 dst_ip=self.pg1.remote_ip4)
4980
4981 # out2in
4982 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
4983 self.pg1.add_stream(pkts)
4984 self.pg_enable_capture(self.pg_interfaces)
4985 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07004986 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07004987 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
4988 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
4989
4990 # in2out
4991 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
4992 self.pg0.add_stream(pkts)
4993 self.pg_enable_capture(self.pg_interfaces)
4994 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07004995 capture = self.pg1.get_capture(len(pkts))
4996 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07004997 dst_ip=self.pg1.remote_ip4)
4998
4999 # out2in
5000 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5001 self.pg1.add_stream(pkts)
5002 self.pg_enable_capture(self.pg_interfaces)
5003 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005004 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005005 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5006
5007 ses_num_end = self.nat64_get_ses_num()
5008
5009 self.assertEqual(ses_num_end - ses_num_start, 3)
5010
Matus Fabian029f3d22017-06-15 02:28:50 -07005011 # tenant with specific VRF
5012 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5013 self.vrf1_nat_addr_n,
5014 vrf_id=self.vrf1_id)
5015 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5016
5017 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5018 self.pg2.add_stream(pkts)
5019 self.pg_enable_capture(self.pg_interfaces)
5020 self.pg_start()
5021 capture = self.pg1.get_capture(len(pkts))
5022 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5023 dst_ip=self.pg1.remote_ip4)
5024
5025 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5026 self.pg1.add_stream(pkts)
5027 self.pg_enable_capture(self.pg_interfaces)
5028 self.pg_start()
5029 capture = self.pg2.get_capture(len(pkts))
5030 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5031
Matus Fabian06596c52017-06-06 04:53:28 -07005032 def test_static(self):
5033 """ NAT64 static translation test """
5034 self.tcp_port_in = 60303
5035 self.udp_port_in = 60304
5036 self.icmp_id_in = 60305
5037 self.tcp_port_out = 60303
5038 self.udp_port_out = 60304
5039 self.icmp_id_out = 60305
5040
5041 ses_num_start = self.nat64_get_ses_num()
5042
5043 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5044 self.nat_addr_n)
5045 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5046 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5047
5048 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5049 self.nat_addr_n,
5050 self.tcp_port_in,
5051 self.tcp_port_out,
5052 IP_PROTOS.tcp)
5053 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5054 self.nat_addr_n,
5055 self.udp_port_in,
5056 self.udp_port_out,
5057 IP_PROTOS.udp)
5058 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5059 self.nat_addr_n,
5060 self.icmp_id_in,
5061 self.icmp_id_out,
5062 IP_PROTOS.icmp)
5063
5064 # in2out
5065 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5066 self.pg0.add_stream(pkts)
5067 self.pg_enable_capture(self.pg_interfaces)
5068 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005069 capture = self.pg1.get_capture(len(pkts))
5070 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005071 dst_ip=self.pg1.remote_ip4, same_port=True)
5072
5073 # out2in
5074 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5075 self.pg1.add_stream(pkts)
5076 self.pg_enable_capture(self.pg_interfaces)
5077 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005078 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005079 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5080 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5081
5082 ses_num_end = self.nat64_get_ses_num()
5083
5084 self.assertEqual(ses_num_end - ses_num_start, 3)
5085
5086 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5087 def test_session_timeout(self):
5088 """ NAT64 session timeout """
5089 self.icmp_id_in = 1234
5090 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5091 self.nat_addr_n)
5092 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5093 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5094 self.vapi.nat64_set_timeouts(icmp=5)
5095
5096 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5097 self.pg0.add_stream(pkts)
5098 self.pg_enable_capture(self.pg_interfaces)
5099 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005100 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005101
5102 ses_num_before_timeout = self.nat64_get_ses_num()
5103
5104 sleep(15)
5105
5106 # ICMP session after timeout
5107 ses_num_after_timeout = self.nat64_get_ses_num()
5108 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5109
Matus Fabian732036d2017-06-08 05:24:28 -07005110 def test_icmp_error(self):
5111 """ NAT64 ICMP Error message translation """
5112 self.tcp_port_in = 6303
5113 self.udp_port_in = 6304
5114 self.icmp_id_in = 6305
5115
5116 ses_num_start = self.nat64_get_ses_num()
5117
5118 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5119 self.nat_addr_n)
5120 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5121 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5122
5123 # send some packets to create sessions
5124 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5125 self.pg0.add_stream(pkts)
5126 self.pg_enable_capture(self.pg_interfaces)
5127 self.pg_start()
5128 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005129 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005130 nat_ip=self.nat_addr,
5131 dst_ip=self.pg1.remote_ip4)
5132
5133 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5134 self.pg1.add_stream(pkts)
5135 self.pg_enable_capture(self.pg_interfaces)
5136 self.pg_start()
5137 capture_ip6 = self.pg0.get_capture(len(pkts))
5138 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5139 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5140 self.pg0.remote_ip6)
5141
5142 # in2out
5143 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5144 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5145 ICMPv6DestUnreach(code=1) /
5146 packet[IPv6] for packet in capture_ip6]
5147 self.pg0.add_stream(pkts)
5148 self.pg_enable_capture(self.pg_interfaces)
5149 self.pg_start()
5150 capture = self.pg1.get_capture(len(pkts))
5151 for packet in capture:
5152 try:
5153 self.assertEqual(packet[IP].src, self.nat_addr)
5154 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5155 self.assertEqual(packet[ICMP].type, 3)
5156 self.assertEqual(packet[ICMP].code, 13)
5157 inner = packet[IPerror]
5158 self.assertEqual(inner.src, self.pg1.remote_ip4)
5159 self.assertEqual(inner.dst, self.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005160 self.check_icmp_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005161 if inner.haslayer(TCPerror):
5162 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5163 elif inner.haslayer(UDPerror):
5164 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5165 else:
5166 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5167 except:
5168 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5169 raise
5170
5171 # out2in
5172 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5173 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5174 ICMP(type=3, code=13) /
5175 packet[IP] for packet in capture_ip4]
5176 self.pg1.add_stream(pkts)
5177 self.pg_enable_capture(self.pg_interfaces)
5178 self.pg_start()
5179 capture = self.pg0.get_capture(len(pkts))
5180 for packet in capture:
5181 try:
5182 self.assertEqual(packet[IPv6].src, ip.src)
5183 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5184 icmp = packet[ICMPv6DestUnreach]
5185 self.assertEqual(icmp.code, 1)
5186 inner = icmp[IPerror6]
5187 self.assertEqual(inner.src, self.pg0.remote_ip6)
5188 self.assertEqual(inner.dst, ip.src)
Matus Fabian029f3d22017-06-15 02:28:50 -07005189 self.check_icmpv6_checksum(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005190 if inner.haslayer(TCPerror):
5191 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5192 elif inner.haslayer(UDPerror):
5193 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5194 else:
5195 self.assertEqual(inner[ICMPv6EchoRequest].id,
5196 self.icmp_id_in)
5197 except:
5198 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5199 raise
5200
Matus Fabian029f3d22017-06-15 02:28:50 -07005201 def test_hairpinning(self):
5202 """ NAT64 hairpinning """
5203
5204 client = self.pg0.remote_hosts[0]
5205 server = self.pg0.remote_hosts[1]
5206 server_tcp_in_port = 22
5207 server_tcp_out_port = 4022
5208 server_udp_in_port = 23
5209 server_udp_out_port = 4023
5210 client_tcp_in_port = 1234
5211 client_udp_in_port = 1235
5212 client_tcp_out_port = 0
5213 client_udp_out_port = 0
5214 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5215 nat_addr_ip6 = ip.src
5216
5217 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5218 self.nat_addr_n)
5219 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5220 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5221
5222 self.vapi.nat64_add_del_static_bib(server.ip6n,
5223 self.nat_addr_n,
5224 server_tcp_in_port,
5225 server_tcp_out_port,
5226 IP_PROTOS.tcp)
5227 self.vapi.nat64_add_del_static_bib(server.ip6n,
5228 self.nat_addr_n,
5229 server_udp_in_port,
5230 server_udp_out_port,
5231 IP_PROTOS.udp)
5232
5233 # client to server
5234 pkts = []
5235 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5236 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5237 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5238 pkts.append(p)
5239 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5240 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5241 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5242 pkts.append(p)
5243 self.pg0.add_stream(pkts)
5244 self.pg_enable_capture(self.pg_interfaces)
5245 self.pg_start()
5246 capture = self.pg0.get_capture(len(pkts))
5247 for packet in capture:
5248 try:
5249 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5250 self.assertEqual(packet[IPv6].dst, server.ip6)
5251 if packet.haslayer(TCP):
5252 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5253 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
5254 self.check_tcp_checksum(packet)
5255 client_tcp_out_port = packet[TCP].sport
5256 else:
5257 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5258 self.assertEqual(packet[UDP].dport, server_udp_in_port)
5259 self.check_udp_checksum(packet)
5260 client_udp_out_port = packet[UDP].sport
5261 except:
5262 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5263 raise
5264
5265 # server to client
5266 pkts = []
5267 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5268 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5269 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5270 pkts.append(p)
5271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5272 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5273 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5274 pkts.append(p)
5275 self.pg0.add_stream(pkts)
5276 self.pg_enable_capture(self.pg_interfaces)
5277 self.pg_start()
5278 capture = self.pg0.get_capture(len(pkts))
5279 for packet in capture:
5280 try:
5281 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5282 self.assertEqual(packet[IPv6].dst, client.ip6)
5283 if packet.haslayer(TCP):
5284 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5285 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
5286 self.check_tcp_checksum(packet)
5287 else:
5288 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5289 self.assertEqual(packet[UDP].dport, client_udp_in_port)
5290 self.check_udp_checksum(packet)
5291 except:
5292 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5293 raise
5294
5295 # ICMP error
5296 pkts = []
5297 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5298 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5299 ICMPv6DestUnreach(code=1) /
5300 packet[IPv6] for packet in capture]
5301 self.pg0.add_stream(pkts)
5302 self.pg_enable_capture(self.pg_interfaces)
5303 self.pg_start()
5304 capture = self.pg0.get_capture(len(pkts))
5305 for packet in capture:
5306 try:
5307 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5308 self.assertEqual(packet[IPv6].dst, server.ip6)
5309 icmp = packet[ICMPv6DestUnreach]
5310 self.assertEqual(icmp.code, 1)
5311 inner = icmp[IPerror6]
5312 self.assertEqual(inner.src, server.ip6)
5313 self.assertEqual(inner.dst, nat_addr_ip6)
5314 self.check_icmpv6_checksum(packet)
5315 if inner.haslayer(TCPerror):
5316 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5317 self.assertEqual(inner[TCPerror].dport,
5318 client_tcp_out_port)
5319 else:
5320 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5321 self.assertEqual(inner[UDPerror].dport,
5322 client_udp_out_port)
5323 except:
5324 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5325 raise
5326
Matus Fabian428dc912017-06-21 06:15:18 -07005327 def test_prefix(self):
5328 """ NAT64 Network-Specific Prefix """
5329
5330 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5331 self.nat_addr_n)
5332 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5333 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5334 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5335 self.vrf1_nat_addr_n,
5336 vrf_id=self.vrf1_id)
5337 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5338
5339 # Add global prefix
5340 global_pref64 = "2001:db8::"
5341 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5342 global_pref64_len = 32
5343 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5344
5345 prefix = self.vapi.nat64_prefix_dump()
5346 self.assertEqual(len(prefix), 1)
5347 self.assertEqual(prefix[0].prefix, global_pref64_n)
5348 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5349 self.assertEqual(prefix[0].vrf_id, 0)
5350
5351 # Add tenant specific prefix
5352 vrf1_pref64 = "2001:db8:122:300::"
5353 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5354 vrf1_pref64_len = 56
5355 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5356 vrf1_pref64_len,
5357 vrf_id=self.vrf1_id)
5358 prefix = self.vapi.nat64_prefix_dump()
5359 self.assertEqual(len(prefix), 2)
5360
5361 # Global prefix
5362 pkts = self.create_stream_in_ip6(self.pg0,
5363 self.pg1,
5364 pref=global_pref64,
5365 plen=global_pref64_len)
5366 self.pg0.add_stream(pkts)
5367 self.pg_enable_capture(self.pg_interfaces)
5368 self.pg_start()
5369 capture = self.pg1.get_capture(len(pkts))
5370 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5371 dst_ip=self.pg1.remote_ip4)
5372
5373 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5374 self.pg1.add_stream(pkts)
5375 self.pg_enable_capture(self.pg_interfaces)
5376 self.pg_start()
5377 capture = self.pg0.get_capture(len(pkts))
5378 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5379 global_pref64,
5380 global_pref64_len)
5381 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5382
5383 # Tenant specific prefix
5384 pkts = self.create_stream_in_ip6(self.pg2,
5385 self.pg1,
5386 pref=vrf1_pref64,
5387 plen=vrf1_pref64_len)
5388 self.pg2.add_stream(pkts)
5389 self.pg_enable_capture(self.pg_interfaces)
5390 self.pg_start()
5391 capture = self.pg1.get_capture(len(pkts))
5392 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5393 dst_ip=self.pg1.remote_ip4)
5394
5395 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5396 self.pg1.add_stream(pkts)
5397 self.pg_enable_capture(self.pg_interfaces)
5398 self.pg_start()
5399 capture = self.pg2.get_capture(len(pkts))
5400 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5401 vrf1_pref64,
5402 vrf1_pref64_len)
5403 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5404
Matus Fabianf8cd5812017-07-11 03:55:02 -07005405 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005406 """ NAT64 translate packet with unknown protocol """
5407
5408 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5409 self.nat_addr_n)
5410 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5411 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5412 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5413
5414 # in2out
5415 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5416 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5417 TCP(sport=self.tcp_port_in, dport=20))
5418 self.pg0.add_stream(p)
5419 self.pg_enable_capture(self.pg_interfaces)
5420 self.pg_start()
5421 p = self.pg1.get_capture(1)
5422
5423 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005424 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005425 GRE() /
5426 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5427 TCP(sport=1234, dport=1234))
5428 self.pg0.add_stream(p)
5429 self.pg_enable_capture(self.pg_interfaces)
5430 self.pg_start()
5431 p = self.pg1.get_capture(1)
5432 packet = p[0]
5433 try:
5434 self.assertEqual(packet[IP].src, self.nat_addr)
5435 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5436 self.assertTrue(packet.haslayer(GRE))
5437 self.check_ip_checksum(packet)
5438 except:
5439 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5440 raise
5441
5442 # out2in
5443 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5444 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5445 GRE() /
5446 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5447 TCP(sport=1234, dport=1234))
5448 self.pg1.add_stream(p)
5449 self.pg_enable_capture(self.pg_interfaces)
5450 self.pg_start()
5451 p = self.pg0.get_capture(1)
5452 packet = p[0]
5453 try:
5454 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005455 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5456 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005457 except:
5458 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5459 raise
5460
Matus Fabianf8cd5812017-07-11 03:55:02 -07005461 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005462 """ NAT64 translate packet with unknown protocol - hairpinning """
5463
5464 client = self.pg0.remote_hosts[0]
5465 server = self.pg0.remote_hosts[1]
5466 server_tcp_in_port = 22
5467 server_tcp_out_port = 4022
5468 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005469 client_tcp_out_port = 1235
5470 server_nat_ip = "10.0.0.100"
5471 client_nat_ip = "10.0.0.110"
5472 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5473 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5474 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5475 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005476
Matus Fabianf8cd5812017-07-11 03:55:02 -07005477 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5478 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005479 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5480 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5481
5482 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005483 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005484 server_tcp_in_port,
5485 server_tcp_out_port,
5486 IP_PROTOS.tcp)
5487
Matus Fabianf8cd5812017-07-11 03:55:02 -07005488 self.vapi.nat64_add_del_static_bib(server.ip6n,
5489 server_nat_ip_n,
5490 0,
5491 0,
5492 IP_PROTOS.gre)
5493
5494 self.vapi.nat64_add_del_static_bib(client.ip6n,
5495 client_nat_ip_n,
5496 client_tcp_in_port,
5497 client_tcp_out_port,
5498 IP_PROTOS.tcp)
5499
Matus Fabian7968e6c2017-07-06 05:37:49 -07005500 # client to server
5501 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005502 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005503 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5504 self.pg0.add_stream(p)
5505 self.pg_enable_capture(self.pg_interfaces)
5506 self.pg_start()
5507 p = self.pg0.get_capture(1)
5508
5509 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005510 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005511 GRE() /
5512 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5513 TCP(sport=1234, dport=1234))
5514 self.pg0.add_stream(p)
5515 self.pg_enable_capture(self.pg_interfaces)
5516 self.pg_start()
5517 p = self.pg0.get_capture(1)
5518 packet = p[0]
5519 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005520 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005521 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005522 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005523 except:
5524 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5525 raise
5526
5527 # server to client
5528 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005529 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005530 GRE() /
5531 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5532 TCP(sport=1234, dport=1234))
5533 self.pg0.add_stream(p)
5534 self.pg_enable_capture(self.pg_interfaces)
5535 self.pg_start()
5536 p = self.pg0.get_capture(1)
5537 packet = p[0]
5538 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005539 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005540 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005541 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005542 except:
5543 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5544 raise
5545
Matus Fabian36ea2d62017-10-24 04:13:49 -07005546 def test_one_armed_nat64(self):
5547 """ One armed NAT64 """
5548 external_port = 0
5549 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5550 '64:ff9b::',
5551 96)
5552
5553 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5554 self.nat_addr_n)
5555 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5556 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5557
5558 # in2out
5559 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5560 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5561 TCP(sport=12345, dport=80))
5562 self.pg3.add_stream(p)
5563 self.pg_enable_capture(self.pg_interfaces)
5564 self.pg_start()
5565 capture = self.pg3.get_capture(1)
5566 p = capture[0]
5567 try:
5568 ip = p[IP]
5569 tcp = p[TCP]
5570 self.assertEqual(ip.src, self.nat_addr)
5571 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5572 self.assertNotEqual(tcp.sport, 12345)
5573 external_port = tcp.sport
5574 self.assertEqual(tcp.dport, 80)
5575 self.check_tcp_checksum(p)
5576 self.check_ip_checksum(p)
5577 except:
5578 self.logger.error(ppp("Unexpected or invalid packet:", p))
5579 raise
5580
5581 # out2in
5582 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5583 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5584 TCP(sport=80, dport=external_port))
5585 self.pg3.add_stream(p)
5586 self.pg_enable_capture(self.pg_interfaces)
5587 self.pg_start()
5588 capture = self.pg3.get_capture(1)
5589 p = capture[0]
5590 try:
5591 ip = p[IPv6]
5592 tcp = p[TCP]
5593 self.assertEqual(ip.src, remote_host_ip6)
5594 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5595 self.assertEqual(tcp.sport, 80)
5596 self.assertEqual(tcp.dport, 12345)
5597 self.check_tcp_checksum(p)
5598 except:
5599 self.logger.error(ppp("Unexpected or invalid packet:", p))
5600 raise
5601
Matus Fabianefcd1e92017-08-15 06:59:19 -07005602 def test_frag_in_order(self):
5603 """ NAT64 translate fragments arriving in order """
5604 self.tcp_port_in = random.randint(1025, 65535)
5605
5606 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5607 self.nat_addr_n)
5608 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5609 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5610
5611 reass = self.vapi.nat_reass_dump()
5612 reass_n_start = len(reass)
5613
5614 # in2out
5615 data = 'a' * 200
5616 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5617 self.tcp_port_in, 20, data)
5618 self.pg0.add_stream(pkts)
5619 self.pg_enable_capture(self.pg_interfaces)
5620 self.pg_start()
5621 frags = self.pg1.get_capture(len(pkts))
5622 p = self.reass_frags_and_verify(frags,
5623 self.nat_addr,
5624 self.pg1.remote_ip4)
5625 self.assertEqual(p[TCP].dport, 20)
5626 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5627 self.tcp_port_out = p[TCP].sport
5628 self.assertEqual(data, p[Raw].load)
5629
5630 # out2in
5631 data = "A" * 4 + "b" * 16 + "C" * 3
5632 pkts = self.create_stream_frag(self.pg1,
5633 self.nat_addr,
5634 20,
5635 self.tcp_port_out,
5636 data)
5637 self.pg1.add_stream(pkts)
5638 self.pg_enable_capture(self.pg_interfaces)
5639 self.pg_start()
5640 frags = self.pg0.get_capture(len(pkts))
5641 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5642 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5643 self.assertEqual(p[TCP].sport, 20)
5644 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5645 self.assertEqual(data, p[Raw].load)
5646
5647 reass = self.vapi.nat_reass_dump()
5648 reass_n_end = len(reass)
5649
5650 self.assertEqual(reass_n_end - reass_n_start, 2)
5651
5652 def test_reass_hairpinning(self):
5653 """ NAT64 fragments hairpinning """
5654 data = 'a' * 200
5655 client = self.pg0.remote_hosts[0]
5656 server = self.pg0.remote_hosts[1]
5657 server_in_port = random.randint(1025, 65535)
5658 server_out_port = random.randint(1025, 65535)
5659 client_in_port = random.randint(1025, 65535)
5660 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5661 nat_addr_ip6 = ip.src
5662
5663 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5664 self.nat_addr_n)
5665 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5666 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5667
5668 # add static BIB entry for server
5669 self.vapi.nat64_add_del_static_bib(server.ip6n,
5670 self.nat_addr_n,
5671 server_in_port,
5672 server_out_port,
5673 IP_PROTOS.tcp)
5674
5675 # send packet from host to server
5676 pkts = self.create_stream_frag_ip6(self.pg0,
5677 self.nat_addr,
5678 client_in_port,
5679 server_out_port,
5680 data)
5681 self.pg0.add_stream(pkts)
5682 self.pg_enable_capture(self.pg_interfaces)
5683 self.pg_start()
5684 frags = self.pg0.get_capture(len(pkts))
5685 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5686 self.assertNotEqual(p[TCP].sport, client_in_port)
5687 self.assertEqual(p[TCP].dport, server_in_port)
5688 self.assertEqual(data, p[Raw].load)
5689
5690 def test_frag_out_of_order(self):
5691 """ NAT64 translate fragments arriving out of order """
5692 self.tcp_port_in = random.randint(1025, 65535)
5693
5694 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5695 self.nat_addr_n)
5696 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5697 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5698
5699 # in2out
5700 data = 'a' * 200
5701 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5702 self.tcp_port_in, 20, data)
5703 pkts.reverse()
5704 self.pg0.add_stream(pkts)
5705 self.pg_enable_capture(self.pg_interfaces)
5706 self.pg_start()
5707 frags = self.pg1.get_capture(len(pkts))
5708 p = self.reass_frags_and_verify(frags,
5709 self.nat_addr,
5710 self.pg1.remote_ip4)
5711 self.assertEqual(p[TCP].dport, 20)
5712 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5713 self.tcp_port_out = p[TCP].sport
5714 self.assertEqual(data, p[Raw].load)
5715
5716 # out2in
5717 data = "A" * 4 + "B" * 16 + "C" * 3
5718 pkts = self.create_stream_frag(self.pg1,
5719 self.nat_addr,
5720 20,
5721 self.tcp_port_out,
5722 data)
5723 pkts.reverse()
5724 self.pg1.add_stream(pkts)
5725 self.pg_enable_capture(self.pg_interfaces)
5726 self.pg_start()
5727 frags = self.pg0.get_capture(len(pkts))
5728 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5729 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5730 self.assertEqual(p[TCP].sport, 20)
5731 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5732 self.assertEqual(data, p[Raw].load)
5733
Matus Fabian0938dcf2017-11-08 01:59:38 -08005734 def test_interface_addr(self):
5735 """ Acquire NAT64 pool addresses from interface """
5736 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5737
5738 # no address in NAT64 pool
5739 adresses = self.vapi.nat44_address_dump()
5740 self.assertEqual(0, len(adresses))
5741
5742 # configure interface address and check NAT64 address pool
5743 self.pg4.config_ip4()
5744 addresses = self.vapi.nat64_pool_addr_dump()
5745 self.assertEqual(len(addresses), 1)
5746 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
5747
5748 # remove interface address and check NAT64 address pool
5749 self.pg4.unconfig_ip4()
5750 addresses = self.vapi.nat64_pool_addr_dump()
5751 self.assertEqual(0, len(adresses))
5752
Matus Fabiana431ad12018-01-04 04:03:14 -08005753 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5754 def test_ipfix_max_bibs_sessions(self):
5755 """ IPFIX logging maximum session and BIB entries exceeded """
5756 max_bibs = 1280
5757 max_sessions = 2560
5758 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5759 '64:ff9b::',
5760 96)
5761
5762 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5763 self.nat_addr_n)
5764 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5765 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5766
5767 pkts = []
5768 src = ""
5769 for i in range(0, max_bibs):
5770 src = "fd01:aa::%x" % (i)
5771 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5772 IPv6(src=src, dst=remote_host_ip6) /
5773 TCP(sport=12345, dport=80))
5774 pkts.append(p)
5775 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5776 IPv6(src=src, dst=remote_host_ip6) /
5777 TCP(sport=12345, dport=22))
5778 pkts.append(p)
5779 self.pg0.add_stream(pkts)
5780 self.pg_enable_capture(self.pg_interfaces)
5781 self.pg_start()
5782 self.pg1.get_capture(max_sessions)
5783
5784 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5785 src_address=self.pg3.local_ip4n,
5786 path_mtu=512,
5787 template_interval=10)
5788 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5789 src_port=self.ipfix_src_port)
5790
5791 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5792 IPv6(src=src, dst=remote_host_ip6) /
5793 TCP(sport=12345, dport=25))
5794 self.pg0.add_stream(p)
5795 self.pg_enable_capture(self.pg_interfaces)
5796 self.pg_start()
5797 self.pg1.get_capture(0)
5798 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5799 capture = self.pg3.get_capture(9)
5800 ipfix = IPFIXDecoder()
5801 # first load template
5802 for p in capture:
5803 self.assertTrue(p.haslayer(IPFIX))
5804 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5805 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5806 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5807 self.assertEqual(p[UDP].dport, 4739)
5808 self.assertEqual(p[IPFIX].observationDomainID,
5809 self.ipfix_domain_id)
5810 if p.haslayer(Template):
5811 ipfix.add_template(p.getlayer(Template))
5812 # verify events in data set
5813 for p in capture:
5814 if p.haslayer(Data):
5815 data = ipfix.decode_data_set(p.getlayer(Set))
5816 self.verify_ipfix_max_sessions(data, max_sessions)
5817
5818 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5819 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5820 TCP(sport=12345, dport=80))
5821 self.pg0.add_stream(p)
5822 self.pg_enable_capture(self.pg_interfaces)
5823 self.pg_start()
5824 self.pg1.get_capture(0)
5825 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5826 capture = self.pg3.get_capture(1)
5827 # verify events in data set
5828 for p in capture:
5829 self.assertTrue(p.haslayer(IPFIX))
5830 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5831 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5832 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5833 self.assertEqual(p[UDP].dport, 4739)
5834 self.assertEqual(p[IPFIX].observationDomainID,
5835 self.ipfix_domain_id)
5836 if p.haslayer(Data):
5837 data = ipfix.decode_data_set(p.getlayer(Set))
5838 self.verify_ipfix_max_bibs(data, max_bibs)
5839
5840 def test_ipfix_max_frags(self):
5841 """ IPFIX logging maximum fragments pending reassembly exceeded """
5842 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5843 self.nat_addr_n)
5844 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5845 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5846 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
5847 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5848 src_address=self.pg3.local_ip4n,
5849 path_mtu=512,
5850 template_interval=10)
5851 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5852 src_port=self.ipfix_src_port)
5853
5854 data = 'a' * 200
5855 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5856 self.tcp_port_in, 20, data)
5857 self.pg0.add_stream(pkts[-1])
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(9)
5863 ipfix = IPFIXDecoder()
5864 # first load template
5865 for p in capture:
5866 self.assertTrue(p.haslayer(IPFIX))
5867 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5868 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5869 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5870 self.assertEqual(p[UDP].dport, 4739)
5871 self.assertEqual(p[IPFIX].observationDomainID,
5872 self.ipfix_domain_id)
5873 if p.haslayer(Template):
5874 ipfix.add_template(p.getlayer(Template))
5875 # verify events in data set
5876 for p in capture:
5877 if p.haslayer(Data):
5878 data = ipfix.decode_data_set(p.getlayer(Set))
5879 self.verify_ipfix_max_fragments_ip6(data, 0,
5880 self.pg0.remote_ip6n)
5881
5882 def test_ipfix_bib_ses(self):
5883 """ IPFIX logging NAT64 BIB/session create and delete events """
5884 self.tcp_port_in = random.randint(1025, 65535)
5885 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5886 '64:ff9b::',
5887 96)
5888
5889 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5890 self.nat_addr_n)
5891 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5892 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5893 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5894 src_address=self.pg3.local_ip4n,
5895 path_mtu=512,
5896 template_interval=10)
5897 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5898 src_port=self.ipfix_src_port)
5899
5900 # Create
5901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5902 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5903 TCP(sport=self.tcp_port_in, dport=25))
5904 self.pg0.add_stream(p)
5905 self.pg_enable_capture(self.pg_interfaces)
5906 self.pg_start()
5907 p = self.pg1.get_capture(1)
5908 self.tcp_port_out = p[0][TCP].sport
5909 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5910 capture = self.pg3.get_capture(10)
5911 ipfix = IPFIXDecoder()
5912 # first load template
5913 for p in capture:
5914 self.assertTrue(p.haslayer(IPFIX))
5915 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5916 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5917 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5918 self.assertEqual(p[UDP].dport, 4739)
5919 self.assertEqual(p[IPFIX].observationDomainID,
5920 self.ipfix_domain_id)
5921 if p.haslayer(Template):
5922 ipfix.add_template(p.getlayer(Template))
5923 # verify events in data set
5924 for p in capture:
5925 if p.haslayer(Data):
5926 data = ipfix.decode_data_set(p.getlayer(Set))
5927 if ord(data[0][230]) == 10:
5928 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
5929 elif ord(data[0][230]) == 6:
5930 self.verify_ipfix_nat64_ses(data,
5931 1,
5932 self.pg0.remote_ip6n,
5933 self.pg1.remote_ip4,
5934 25)
5935 else:
5936 self.logger.error(ppp("Unexpected or invalid packet: ", p))
5937
5938 # Delete
5939 self.pg_enable_capture(self.pg_interfaces)
5940 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5941 self.nat_addr_n,
5942 is_add=0)
5943 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5944 capture = self.pg3.get_capture(2)
5945 # verify events in data set
5946 for p in capture:
5947 self.assertTrue(p.haslayer(IPFIX))
5948 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5949 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5950 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5951 self.assertEqual(p[UDP].dport, 4739)
5952 self.assertEqual(p[IPFIX].observationDomainID,
5953 self.ipfix_domain_id)
5954 if p.haslayer(Data):
5955 data = ipfix.decode_data_set(p.getlayer(Set))
5956 if ord(data[0][230]) == 11:
5957 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
5958 elif ord(data[0][230]) == 7:
5959 self.verify_ipfix_nat64_ses(data,
5960 0,
5961 self.pg0.remote_ip6n,
5962 self.pg1.remote_ip4,
5963 25)
5964 else:
5965 self.logger.error(ppp("Unexpected or invalid packet: ", p))
5966
Matus Fabian06596c52017-06-06 04:53:28 -07005967 def nat64_get_ses_num(self):
5968 """
5969 Return number of active NAT64 sessions.
5970 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07005971 st = self.vapi.nat64_st_dump()
5972 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07005973
5974 def clear_nat64(self):
5975 """
5976 Clear NAT64 configuration.
5977 """
Matus Fabiana431ad12018-01-04 04:03:14 -08005978 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
5979 domain_id=self.ipfix_domain_id)
5980 self.ipfix_src_port = 4739
5981 self.ipfix_domain_id = 1
5982
Matus Fabian06596c52017-06-06 04:53:28 -07005983 self.vapi.nat64_set_timeouts()
5984
5985 interfaces = self.vapi.nat64_interface_dump()
5986 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07005987 if intf.is_inside > 1:
5988 self.vapi.nat64_add_del_interface(intf.sw_if_index,
5989 0,
5990 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07005991 self.vapi.nat64_add_del_interface(intf.sw_if_index,
5992 intf.is_inside,
5993 is_add=0)
5994
Matus Fabiana431ad12018-01-04 04:03:14 -08005995 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07005996 for bibe in bib:
5997 if bibe.is_static:
5998 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
5999 bibe.o_addr,
6000 bibe.i_port,
6001 bibe.o_port,
6002 bibe.proto,
6003 bibe.vrf_id,
6004 is_add=0)
6005
6006 adresses = self.vapi.nat64_pool_addr_dump()
6007 for addr in adresses:
6008 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6009 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006010 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006011 is_add=0)
6012
Matus Fabian428dc912017-06-21 06:15:18 -07006013 prefixes = self.vapi.nat64_prefix_dump()
6014 for prefix in prefixes:
6015 self.vapi.nat64_add_del_prefix(prefix.prefix,
6016 prefix.prefix_len,
6017 vrf_id=prefix.vrf_id,
6018 is_add=0)
6019
Matus Fabian06596c52017-06-06 04:53:28 -07006020 def tearDown(self):
6021 super(TestNAT64, self).tearDown()
6022 if not self.vpp_dead:
6023 self.logger.info(self.vapi.cli("show nat64 pool"))
6024 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006025 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006026 self.logger.info(self.vapi.cli("show nat64 bib all"))
6027 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006028 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006029 self.clear_nat64()
6030
Matus Fabian8ebe6252017-11-06 05:04:53 -08006031
6032class TestDSlite(MethodHolder):
6033 """ DS-Lite Test Cases """
6034
6035 @classmethod
6036 def setUpClass(cls):
6037 super(TestDSlite, cls).setUpClass()
6038
6039 try:
6040 cls.nat_addr = '10.0.0.3'
6041 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6042
6043 cls.create_pg_interfaces(range(2))
6044 cls.pg0.admin_up()
6045 cls.pg0.config_ip4()
6046 cls.pg0.resolve_arp()
6047 cls.pg1.admin_up()
6048 cls.pg1.config_ip6()
6049 cls.pg1.generate_remote_hosts(2)
6050 cls.pg1.configure_ipv6_neighbors()
6051
6052 except Exception:
6053 super(TestDSlite, cls).tearDownClass()
6054 raise
6055
6056 def test_dslite(self):
6057 """ Test DS-Lite """
6058 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6059 self.nat_addr_n)
6060 aftr_ip4 = '192.0.0.1'
6061 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6062 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6063 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6064 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6065
6066 # UDP
6067 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6068 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6069 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6070 UDP(sport=20000, dport=10000))
6071 self.pg1.add_stream(p)
6072 self.pg_enable_capture(self.pg_interfaces)
6073 self.pg_start()
6074 capture = self.pg0.get_capture(1)
6075 capture = capture[0]
6076 self.assertFalse(capture.haslayer(IPv6))
6077 self.assertEqual(capture[IP].src, self.nat_addr)
6078 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6079 self.assertNotEqual(capture[UDP].sport, 20000)
6080 self.assertEqual(capture[UDP].dport, 10000)
6081 self.check_ip_checksum(capture)
6082 out_port = capture[UDP].sport
6083
6084 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6085 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6086 UDP(sport=10000, dport=out_port))
6087 self.pg0.add_stream(p)
6088 self.pg_enable_capture(self.pg_interfaces)
6089 self.pg_start()
6090 capture = self.pg1.get_capture(1)
6091 capture = capture[0]
6092 self.assertEqual(capture[IPv6].src, aftr_ip6)
6093 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6094 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6095 self.assertEqual(capture[IP].dst, '192.168.1.1')
6096 self.assertEqual(capture[UDP].sport, 10000)
6097 self.assertEqual(capture[UDP].dport, 20000)
6098 self.check_ip_checksum(capture)
6099
6100 # TCP
6101 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6102 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6103 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6104 TCP(sport=20001, dport=10001))
6105 self.pg1.add_stream(p)
6106 self.pg_enable_capture(self.pg_interfaces)
6107 self.pg_start()
6108 capture = self.pg0.get_capture(1)
6109 capture = capture[0]
6110 self.assertFalse(capture.haslayer(IPv6))
6111 self.assertEqual(capture[IP].src, self.nat_addr)
6112 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6113 self.assertNotEqual(capture[TCP].sport, 20001)
6114 self.assertEqual(capture[TCP].dport, 10001)
6115 self.check_ip_checksum(capture)
6116 self.check_tcp_checksum(capture)
6117 out_port = capture[TCP].sport
6118
6119 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6120 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6121 TCP(sport=10001, dport=out_port))
6122 self.pg0.add_stream(p)
6123 self.pg_enable_capture(self.pg_interfaces)
6124 self.pg_start()
6125 capture = self.pg1.get_capture(1)
6126 capture = capture[0]
6127 self.assertEqual(capture[IPv6].src, aftr_ip6)
6128 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6129 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6130 self.assertEqual(capture[IP].dst, '192.168.1.1')
6131 self.assertEqual(capture[TCP].sport, 10001)
6132 self.assertEqual(capture[TCP].dport, 20001)
6133 self.check_ip_checksum(capture)
6134 self.check_tcp_checksum(capture)
6135
6136 # ICMP
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 ICMP(id=4000, type='echo-request'))
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[ICMP].id, 4000)
6150 self.check_ip_checksum(capture)
6151 self.check_icmp_checksum(capture)
6152 out_id = capture[ICMP].id
6153
6154 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6155 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6156 ICMP(id=out_id, type='echo-reply'))
6157 self.pg0.add_stream(p)
6158 self.pg_enable_capture(self.pg_interfaces)
6159 self.pg_start()
6160 capture = self.pg1.get_capture(1)
6161 capture = capture[0]
6162 self.assertEqual(capture[IPv6].src, aftr_ip6)
6163 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6164 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6165 self.assertEqual(capture[IP].dst, '192.168.1.1')
6166 self.assertEqual(capture[ICMP].id, 4000)
6167 self.check_ip_checksum(capture)
6168 self.check_icmp_checksum(capture)
6169
Matus Fabian331acc62017-12-08 03:38:51 -08006170 # ping DS-Lite AFTR tunnel endpoint address
6171 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6172 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6173 ICMPv6EchoRequest())
6174 self.pg1.add_stream(p)
6175 self.pg_enable_capture(self.pg_interfaces)
6176 self.pg_start()
6177 capture = self.pg1.get_capture(1)
6178 self.assertEqual(1, len(capture))
6179 capture = capture[0]
6180 self.assertEqual(capture[IPv6].src, aftr_ip6)
6181 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6182 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6183
Matus Fabian8ebe6252017-11-06 05:04:53 -08006184 def tearDown(self):
6185 super(TestDSlite, self).tearDown()
6186 if not self.vpp_dead:
6187 self.logger.info(self.vapi.cli("show dslite pool"))
6188 self.logger.info(
6189 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6190 self.logger.info(self.vapi.cli("show dslite sessions"))
6191
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006192
6193class TestDSliteCE(MethodHolder):
6194 """ DS-Lite CE Test Cases """
6195
6196 @classmethod
6197 def setUpConstants(cls):
6198 super(TestDSliteCE, cls).setUpConstants()
6199 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6200
6201 @classmethod
6202 def setUpClass(cls):
6203 super(TestDSliteCE, cls).setUpClass()
6204
6205 try:
6206 cls.create_pg_interfaces(range(2))
6207 cls.pg0.admin_up()
6208 cls.pg0.config_ip4()
6209 cls.pg0.resolve_arp()
6210 cls.pg1.admin_up()
6211 cls.pg1.config_ip6()
6212 cls.pg1.generate_remote_hosts(1)
6213 cls.pg1.configure_ipv6_neighbors()
6214
6215 except Exception:
6216 super(TestDSliteCE, cls).tearDownClass()
6217 raise
6218
6219 def test_dslite_ce(self):
6220 """ Test DS-Lite CE """
6221
6222 b4_ip4 = '192.0.0.2'
6223 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6224 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6225 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6226 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6227
6228 aftr_ip4 = '192.0.0.1'
6229 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6230 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6231 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6232 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6233
6234 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6235 dst_address_length=128,
6236 next_hop_address=self.pg1.remote_ip6n,
6237 next_hop_sw_if_index=self.pg1.sw_if_index,
6238 is_ipv6=1)
6239
6240 # UDP encapsulation
6241 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6242 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6243 UDP(sport=10000, dport=20000))
6244 self.pg0.add_stream(p)
6245 self.pg_enable_capture(self.pg_interfaces)
6246 self.pg_start()
6247 capture = self.pg1.get_capture(1)
6248 capture = capture[0]
6249 self.assertEqual(capture[IPv6].src, b4_ip6)
6250 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6251 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6252 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6253 self.assertEqual(capture[UDP].sport, 10000)
6254 self.assertEqual(capture[UDP].dport, 20000)
6255 self.check_ip_checksum(capture)
6256
6257 # UDP decapsulation
6258 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6259 IPv6(dst=b4_ip6, src=aftr_ip6) /
6260 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6261 UDP(sport=20000, dport=10000))
6262 self.pg1.add_stream(p)
6263 self.pg_enable_capture(self.pg_interfaces)
6264 self.pg_start()
6265 capture = self.pg0.get_capture(1)
6266 capture = capture[0]
6267 self.assertFalse(capture.haslayer(IPv6))
6268 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6269 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6270 self.assertEqual(capture[UDP].sport, 20000)
6271 self.assertEqual(capture[UDP].dport, 10000)
6272 self.check_ip_checksum(capture)
6273
6274 # ping DS-Lite B4 tunnel endpoint address
6275 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6276 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6277 ICMPv6EchoRequest())
6278 self.pg1.add_stream(p)
6279 self.pg_enable_capture(self.pg_interfaces)
6280 self.pg_start()
6281 capture = self.pg1.get_capture(1)
6282 self.assertEqual(1, len(capture))
6283 capture = capture[0]
6284 self.assertEqual(capture[IPv6].src, b4_ip6)
6285 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6286 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6287
6288 def tearDown(self):
6289 super(TestDSliteCE, self).tearDown()
6290 if not self.vpp_dead:
6291 self.logger.info(
6292 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6293 self.logger.info(
6294 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6295
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006296
6297class TestNAT66(MethodHolder):
6298 """ NAT66 Test Cases """
6299
6300 @classmethod
6301 def setUpClass(cls):
6302 super(TestNAT66, cls).setUpClass()
6303
6304 try:
6305 cls.nat_addr = 'fd01:ff::2'
6306 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6307
6308 cls.create_pg_interfaces(range(2))
6309 cls.interfaces = list(cls.pg_interfaces)
6310
6311 for i in cls.interfaces:
6312 i.admin_up()
6313 i.config_ip6()
6314 i.configure_ipv6_neighbors()
6315
6316 except Exception:
6317 super(TestNAT66, cls).tearDownClass()
6318 raise
6319
6320 def test_static(self):
6321 """ 1:1 NAT66 test """
6322 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6323 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6324 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6325 self.nat_addr_n)
6326
6327 # in2out
6328 pkts = []
6329 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6330 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6331 TCP())
6332 pkts.append(p)
6333 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6334 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6335 UDP())
6336 pkts.append(p)
6337 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6338 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6339 ICMPv6EchoRequest())
6340 pkts.append(p)
6341 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6342 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6343 GRE() / IP() / TCP())
6344 pkts.append(p)
6345 self.pg0.add_stream(pkts)
6346 self.pg_enable_capture(self.pg_interfaces)
6347 self.pg_start()
6348 capture = self.pg1.get_capture(len(pkts))
6349 for packet in capture:
6350 try:
6351 self.assertEqual(packet[IPv6].src, self.nat_addr)
6352 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6353 if packet.haslayer(TCP):
6354 self.check_tcp_checksum(packet)
6355 elif packet.haslayer(UDP):
6356 self.check_udp_checksum(packet)
6357 elif packet.haslayer(ICMPv6EchoRequest):
6358 self.check_icmpv6_checksum(packet)
6359 except:
6360 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6361 raise
6362
6363 # out2in
6364 pkts = []
6365 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6366 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6367 TCP())
6368 pkts.append(p)
6369 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6370 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6371 UDP())
6372 pkts.append(p)
6373 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6374 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6375 ICMPv6EchoReply())
6376 pkts.append(p)
6377 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6378 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6379 GRE() / IP() / TCP())
6380 pkts.append(p)
6381 self.pg1.add_stream(pkts)
6382 self.pg_enable_capture(self.pg_interfaces)
6383 self.pg_start()
6384 capture = self.pg0.get_capture(len(pkts))
6385 for packet in capture:
6386 try:
6387 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6388 self.assertEqual(packet[IPv6].dst, self.pg0.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(ICMPv6EchoReply):
6394 self.check_icmpv6_checksum(packet)
6395 except:
6396 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6397 raise
6398
6399 sm = self.vapi.nat66_static_mapping_dump()
6400 self.assertEqual(len(sm), 1)
6401 self.assertEqual(sm[0].total_pkts, 8)
6402
6403 def clear_nat66(self):
6404 """
6405 Clear NAT66 configuration.
6406 """
6407 interfaces = self.vapi.nat66_interface_dump()
6408 for intf in interfaces:
6409 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6410 intf.is_inside,
6411 is_add=0)
6412
6413 static_mappings = self.vapi.nat66_static_mapping_dump()
6414 for sm in static_mappings:
6415 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6416 sm.external_ip_address,
6417 sm.vrf_id,
6418 is_add=0)
6419
6420 def tearDown(self):
6421 super(TestNAT66, self).tearDown()
6422 if not self.vpp_dead:
6423 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6424 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6425 self.clear_nat66()
6426
Matus Fabiande886752016-12-07 03:38:19 -08006427if __name__ == '__main__':
6428 unittest.main(testRunner=VppTestRunner)