Increase the default number of rx and tx descriptors to 2K
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / ipv6_tun / ipv6_tun_bindings.pl
1 #!/usr/bin/perl
2
3 ##
4 ## Copyright (c) 2010-2017 Intel Corporation
5 ##
6 ## Licensed under the Apache License, Version 2.0 (the "License");
7 ## you may not use this file except in compliance with the License.
8 ## You may obtain a copy of the License at
9 ##
10 ##     http://www.apache.org/licenses/LICENSE-2.0
11 ##
12 ## Unless required by applicable law or agreed to in writing, software
13 ## distributed under the License is distributed on an "AS IS" BASIS,
14 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ## See the License for the specific language governing permissions and
16 ## limitations under the License.
17 ##
18
19 =head1 NAME
20
21 ipv6_tun_bindings.pl
22
23 =head1 SYNOPSIS
24
25  ipv6_tun_bindings.pl [-n <num_entries>] [-tun_ip <ipv6>] [-mac <next_hop_mac>] 
26                       [-pub_ip <ipv4>] [-port <begin>-<end>] [-set <num_ports>]
27                       [-suffix <suffix>] [-test <num_entries>] [-sym|-nosym]
28                       [-help]
29
30 =head1 DESCRIPTION
31
32 This script can be used to generate a binding table for the IPv6 Tunnel
33 task implemented in PROX (ipv6_encap and ipv6_decap).
34 The entries in this table bind a specific tunnel endpoint (lwB4 in lw4over6
35 architecture) to a public IPv4 address and port set.
36 The port set is actually derived from the port specified in the table
37 and a port bitmask in the PROX task configuration ("lookup port mask").
38
39 The ipv6_encap task uses the binding table to know where to tunnel IPv4
40 traffic to. The ipv6_decap task uses the table to verify tunnel packets
41 have a valid public IPv4 and port combination for the originating tunnel.   
42
43 The table uses the Lua syntax so it can be loaded into PROX. Example:
44 return {
45    {ip6 = ip6("fe80:0000:0000:0000:0200:00ff:fe00:0000"), mac = mac("fe:80:00:00:00:00"), ip = ip("171.205.239.1"), port = 4608},
46    {ip6 = ip6("fe80:0000:0000:0000:0200:00ff:fe00:0001"), mac = mac("fe:80:00:00:00:00"), ip = ip("171.205.239.1"), port = 4672},
47    {ip6 = ip6("fe80:0000:0000:0000:0200:00ff:fe00:0002"), mac = mac("fe:80:00:00:00:00"), ip = ip("171.205.239.1"), port = 4736},
48    {ip6 = ip6("fe80:0000:0000:0000:0200:00ff:fe00:0003"), mac = mac("fe:80:00:00:00:00"), ip = ip("171.205.239.1"), port = 4800},
49 }
50
51 The script generates consecutive entries, starting from a given IP address
52 and assigning ports within a given range, increasing the port number by a
53 fixed amount which should correspond to the port lookup mask being used.
54
55 UDF table: In addition to the binding table itself, the script can optionally
56 generate accompanying UDF tables for generating test traffic matching the
57 binding table. Such UDF tables can then be used in a traffic generation tool.  
58
59 =head1 OPTIONS
60
61 =over 22
62
63 =item -n <num_entries>
64
65 How many entries in the binding table
66
67 =item -tun_ip <ipv6>
68
69 Starting tunnel endpoint IPv6 address (will be incremented)
70
71 =item -mac <next_hop_mac>
72
73 MAC address of the next hop to reach the tunnel endpoints
74
75 =item -pub_ip <ipv4>
76
77 Starting public IPv4 address 
78
79 =item -port <begin>-<end>
80
81 Range of ports where to assign Port Sets
82
83 =item -set <num_ports>
84
85 Number of ports in set (should be a power of 2 because bitmasking is used
86 in lwAFTR)
87
88 =item -suffix <suffix>
89
90 Filename suffix to use for the generated file(s)
91
92 =item -test <num_entries>
93
94 Number of random entries to put into test UDF table
95
96 =item -sym
97
98 Whether the same random entry from the table should be inserted into both
99 traffic sides or if different entries should be used
100
101 =item -help
102
103 Shows the full script documentation.
104
105 =back
106
107 =head1 AUTHOR
108
109  Copyright(c) 2010-2017 Intel Corporation.
110  All rights reserved.
111
112 =cut
113
114
115 use strict vars;
116 use Getopt::Long;
117 use Pod::Usage;
118 use Socket qw(AF_INET AF_INET6 inet_ntop inet_pton);
119
120 sub parse_ip
121 {
122         my ($str, $ip_ref, $family) = @_;
123
124         my $packed = inet_pton($family, $str);
125         return 0 if (!defined($packed));
126
127         if ($family == AF_INET6) {
128                 #print unpack("H*", $packed). "\n";
129                 my @w = unpack("NNNN", $packed);
130                 my ($high, $low) = (($w[0] << 32) | $w[1], ($w[2] << 32) | $w[3]);
131                 @$ip_ref = ($high, $low);
132         }
133         else {
134                 $$ip_ref = unpack("N", $packed);
135         }
136         return 1;
137 }
138
139 sub ntop6
140 {
141         my ($in) = @_;
142         my $packed = pack('NNNN', $in->[0] >> 32, $in->[0] & 0xffffffff,
143                                   $in->[1] >> 32, $in->[1] & 0xffffffff);
144         return inet_ntop(AF_INET6, $packed);
145 }
146
147 sub ntop6_expanded
148 {
149         my ($in) = @_;
150         return sprintf('%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x',
151                         ($in->[0] >> 48) & 0xffff, ($in->[0] >> 32) & 0xffff,
152                         ($in->[0] >> 16) & 0xffff, ($in->[0]      ) & 0xffff,
153                         ($in->[1] >> 48) & 0xffff, ($in->[1] >> 32) & 0xffff,
154                         ($in->[1] >> 16) & 0xffff, ($in->[1]      ) & 0xffff);
155 }
156
157 my ($tun_ip_str, $pub_ip_str, $ports_str);
158
159 GetOptions(
160         'help'     => sub () { Pod::Usage::pod2usage( -verbose => 2 ); exit; },
161         'n=i'      => \(my $num_B4s = 10),
162         'tun_ip=s' => \(my $tun_ip_str = 'fe80:0000:0000:0000:0200:00ff:0000:0000'),
163         'pub_ip=s' => \(my $pub_ip_str = '171.205.239.1'),
164         'mac=s'    => \(my $next_hop_mac = 'fe:80:00:00:00:00'),
165         'port=s'   => \(my $ports_str='4608-11968'),
166         'set=n'    => \(my $port_set_sz = 64),
167         'suffix=s' => \(my $suffix = ''),
168         'test=n'   => \(my $num_test_lines = 200000),
169         'sym!'     => \(my $symmetric_traffic = TRUE),
170 ) or pod2usage(-verbose => 1) && exit;
171
172 my @tun_ip;
173 parse_ip($tun_ip_str, \@tun_ip, AF_INET6) or print("Invalid starting tunnel IP: $tun_ip_str\n") && pod2usage(-verbose => 1) && exit;
174 parse_ip($pub_ip_str, \(my $pub_ip), AF_INET) or print("Invalid starting public IP: $pub_ip_str\n") && pod2usage(-verbose => 1) && exit;
175 my @port_range;
176 if ($ports_str =~ /^([^d]+)\s*\-\s*([^d]+)$/) {
177         @port_range = ($1, $2);
178 }
179 else { print "Invalid port range: $ports_str\n"; pod2usage(-verbose => 1); exit }
180
181 # Summary of input data
182 print "File suffix: $suffix\n" if ($suffix);
183 print "Starting Tunnel IP: " . ntop6(\@tun_ip) . "\n";
184 print "Starting Public IP: ".inet_ntop(AF_INET, pack("N", $pub_ip)) . "\n";
185 print "Public Port Range: $port_range[0]-$port_range[1] by blocks of $port_set_sz\n";
186
187 my @data;  # Holds generated binding table, so we can later generate test traffic for it
188
189 # Binding table for PROX IPv6 Tunnel
190 my $filename = 'ip6_tun_bind'.$suffix.'.lua';
191 print "\nGenerating binding table with $num_B4s entries into $filename ... ";
192 open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
193 print $fh "-- Bindings for lwaftr: lwB4 IPv6 address, next hop MAC address\n";
194 print $fh "-- towards lwB4, IPv4 Public address, IPv4 Public Port Set\n";
195 print $fh "\n";
196 print $fh "return {" . "\n";
197 my $port = $port_range[0];
198 for (my $B4_id = 0; $B4_id < $num_B4s; $B4_id++) {
199         $data[$B4_id]{'b4_ipv6'} = ntop6_expanded(\@tun_ip);
200         $data[$B4_id]{'pub_ipv4'} = "" . (($pub_ip >> 24) & 0xff) . "." . (($pub_ip >> 16) & 0xff) . "." . (($pub_ip >> 8) & 0xff) . "." . ($pub_ip & 0xff);
201         $data[$B4_id]{'pub_port'} = $port;
202         $data[$B4_id]{'next_hop_mac'} = $next_hop_mac;
203
204         print $fh "   {";
205         print $fh "ip6 = ip6(\"" . $data[$B4_id]{'b4_ipv6'} . "\")";
206         print $fh ", mac = mac(\"" . $data[$B4_id]{'next_hop_mac'} . "\")";
207         print $fh ", ip = ip(\"" . $data[$B4_id]{'pub_ipv4'} . "\")";
208         print $fh ", port = " . $data[$B4_id]{'pub_port'};
209         print $fh "},\n";
210
211         $port += $port_set_sz;
212         if ($port > $port_range[1]) {
213                 $pub_ip++;
214                 $port = $port_range[0];
215         }
216         
217         # Move to next Tunnel address
218         if (@tun_ip[1] < 0xffffffffffffffff) {
219                 @tun_ip[1]++;
220         } else {
221                 @tun_ip[0]++;
222                 @tun_ip[1] = 0;
223         }
224 }
225 print $fh "}" . "\n";
226 close $fh;
227 print "[DONE]\n";
228
229 # Test traffic "UDF Tables"
230 if ($num_test_lines) {
231         print "Generating $num_test_lines lines of test UDF table into lwAFTR_tun|inet".$suffix.".csv ... ";
232
233         # Tunnel Packets from B4 to lwAFTR 
234         my $filename = 'lwAFTR_tun' . $suffix . '.csv';
235         open(my $fh_tun, '>', $filename) or die "Could not open file '$filename' $!";
236         print $fh_tun "b4_ip,pub_ip,pub_port\n";
237         print $fh_tun "22,66,74\n";  # Offsets
238         print $fh_tun "16,4,2\n";    # Sizes
239         print $fh_tun "6,5,3\n";     # Format (IPv6, IPv4, Decimal)
240         print $fh_tun ",,\n";
241         
242         # Internet Packets towards the lwAFTR, to be sent to corresp lwB4 over tunnel 
243         my $filename = 'lwAFTR_inet' . $suffix . '.csv';
244         open(my $fh_inet, '>', $filename) or die "Could not open file '$filename' $!";
245         print $fh_inet "pub_ip,pub_port\n";
246         print $fh_inet "30,36\n";  # Offsets
247         print $fh_inet "4,2\n";    # Sizes
248         print $fh_inet "5,3\n";     # Format (IPv6, IPv4, Decimal)
249         print $fh_inet ",,\n";
250
251         for (my $i = 0; $i < $num_test_lines; $i++) {
252                 my $B4_id = int(rand($num_B4s));
253                 my $port = $data[$B4_id]{'pub_port'} + int(rand($port_set_sz)); 
254                 printf $fh_tun $data[$B4_id]{'b4_ipv6'} . "," . $data[$B4_id]{'pub_ipv4'} . "," . $port . "\n";
255                 
256                 if (! $symmetric_traffic) {
257                         $B4_id = int(rand($num_B4s));
258                         $port = $data[$B4_id]{'pub_port'} + int(rand($port_set_sz)); 
259                 }
260                 printf $fh_inet $data[$B4_id]{'pub_ipv4'} . "," . $port . "\n";
261         }
262         
263         close $fh_tun;
264         close $fh_inet;
265         print "[DONE]\n";
266 }