Increase the default number of rx and tx descriptors to 2K
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / ipv6_tun / gen_4over6.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 use strict vars;
20 use Getopt::Long;
21 use Pod::Usage;
22 use Net::Pcap;
23 use Net::Frame::Layer;
24 use Net::Frame::Layer::ETH qw(:consts);
25 use Net::Frame::Layer::IPv6 qw(:consts);
26 use Net::Frame::Layer::IPv4 qw(:consts);
27 use Net::Frame::Layer::UDP;
28 use Socket qw(AF_INET AF_INET6 inet_ntop inet_pton);
29
30 use constant NUM_PACKETS => 30000;
31
32 use constant ETHER_ADDR_LEN => 6;
33 use constant ETHER_TYPE_LEN => 2;
34 use constant ETHER_HDR_LEN => ( 2 * ETHER_ADDR_LEN ) + ETHER_TYPE_LEN;
35 use constant ETHER_STATIC_MAC => "78acdddddddd";
36
37 use constant UDP_HDR_LEN => 8;
38 use constant UDP_STATIC_PORT => 0x6666;
39
40 use constant IPv6_HOP_LIMIT => 4;
41 use constant IPv6_STATIC_IP => "2222:2222:2222:2222:2222:2222:2222:2222";
42
43 use constant IPv4_TIME_TO_LIVE => 32;
44 use constant IPv4_STATIC_IP => "68.68.68.68";
45
46 srand;
47
48 my $type = 'tun';
49 my $pkt_count = NUM_PACKETS;
50
51 GetOptions(
52         'inet' => sub { $type = 'inet'},
53         'tun' => sub { $type = 'tun'},
54         'count=i'      => \$pkt_count,
55         'in=s' => \(my $in = 'ip6_tun_bind.lua'),
56         'out=s' => \(my $out = 'output.pcap'),
57         'size=s' => \(my $size = 0)
58 ) or exit;
59
60 my $pcap = pcap_open_dead( DLT_EN10MB, 65535 );
61 my $dumper = pcap_dump_open($pcap, $out ) or die 'Could not create output file: ' . $out;
62
63 if( $type eq 'inet' ) {
64         gen_inet_pcap( $in, $pkt_count );
65 }
66 if( $type eq 'tun' ) {
67         gen_tun_pcap( $in, $pkt_count );
68 }
69
70 pcap_close( $pcap );
71
72 # Trim string
73 sub trim {
74         my ( $str ) = @_;
75
76         $str =~ s/^\s+|\s+$//g;
77
78         return $str;
79 }
80
81 # Generate random port based on $port and $port_mask
82 sub rand_port {
83         my ( $port, $port_mask ) = @_;
84
85         return ( $port | int( rand( 0xFFFF ) & $port_mask ) );
86 }
87
88 # Generate packet originating from CPE
89 sub gen_tun_packet {
90         my ( $sz, $ether, $ipv6, $ipv4, $udp ) = @_;
91
92         my $hdr_ether = Net::Frame::Layer::ETH->new(
93                 src => $ether->{'src'},
94                 dst => $ether->{'dst'},
95                 type => NF_ETH_TYPE_IPv6
96         )->pack;
97
98         my $hdr_ipv6 = Net::Frame::Layer::IPv6->new(
99                 nextHeader => NF_IPv6_PROTOCOL_IPIP,
100                 hopLimit => IPv6_HOP_LIMIT,
101                 src => $ipv6->{'src'},
102                 dst => $ipv6->{'dst'},
103                 payloadLength => $sz + NF_IPv4_HDR_LEN + UDP_HDR_LEN
104         )->pack;
105
106         my $hdr_ipv4 = Net::Frame::Layer::IPv4->new(
107                 length => $sz + UDP_HDR_LEN + NF_IPv4_HDR_LEN,
108                 ttl => IPv4_TIME_TO_LIVE,
109                 protocol => NF_IPv4_PROTOCOL_UDP,
110                 src => $ipv4->{'src'},
111                 dst => $ipv4->{'dst'}
112         )->pack;
113
114         my $hdr_udp = Net::Frame::Layer::UDP->new(
115                 src => $udp->{'src'},
116                 dst => $udp->{'dst'},
117                 length => $sz + UDP_HDR_LEN
118         )->pack;
119         
120         my $pkt = pack( "H*", "de" x $sz );
121         $pkt = $hdr_ether . $hdr_ipv6 . $hdr_ipv4 . $hdr_udp . $pkt;
122
123         my $pkt_size = length( $pkt );
124
125         my $hdr = {
126                 tv_sec => 0,
127                 tv_usec => 0,
128                 len => $pkt_size,
129                 caplen => $pkt_size
130         };
131
132         return ( $hdr, $pkt );
133 }
134
135 # Generate packet originating from the internet
136 sub gen_inet_packet {
137         my ( $sz, $ether, $ipv4, $udp ) = @_;
138
139         my $hdr_ether = Net::Frame::Layer::ETH->new(
140                 src => $ether->{'src'},
141                 dst => $ether->{'dst'},
142                 type => NF_ETH_TYPE_IPv4
143         )->pack;
144
145         my $hdr_ipv4 = Net::Frame::Layer::IPv4->new(
146                 length => $sz + UDP_HDR_LEN + NF_IPv4_HDR_LEN,
147                 ttl => IPv4_TIME_TO_LIVE,
148                 protocol => NF_IPv4_PROTOCOL_UDP,
149                 src => $ipv4->{'src'},
150                 dst => $ipv4->{'dst'}
151         )->pack;
152
153         my $hdr_udp = Net::Frame::Layer::UDP->new(
154                 src => $udp->{'src'},
155                 dst => $udp->{'dst'},
156                 length => $sz + UDP_HDR_LEN
157         )->pack;
158         
159         my $pkt = pack( "H*", "de" x $sz );
160         $pkt = $hdr_ether . $hdr_ipv4 . $hdr_udp . $pkt;
161
162         my $pkt_size = length( $pkt );
163
164         my $hdr = {
165                 tv_sec => 0,
166                 tv_usec => 0,
167                 len => $pkt_size,
168                 caplen => $pkt_size
169         };
170
171         return ( $hdr, $pkt );
172 }
173
174 # Read bindings file
175 sub read_bindings {
176         my ( $file ) = @_;
177
178         print "Reading bindings file...\n";
179
180         my @rows;
181
182         open my $fh, "<:encoding(utf8)", $file or die $file . ": $!";
183 LINE:   while ( my $line = <$fh> ) {
184                 next if ($line =~ /^--.*/);  # Skip comments
185                 
186                 my ($ip6, $mac, $ip4, $port);
187                 if ($line =~ /\s*\{.*\},\s*$/) {  # Weak check for a data line...
188
189                         $line =~ /ip6\s*=\s*ip6\("([^\)]*)"\)/ && do { $ip6 = trim($1); };
190                         unless ( inet_pton( AF_INET6, $ip6 ) ) { print "ERROR - Invalid ipv6: $ip6\n"; next LINE; }
191
192                         $line =~ /ip\s*=\s*ip\("([^\)]*)"\)/ && do { $ip4 = trim($1); };
193                         unless ( inet_pton( AF_INET, $ip4 ) ) { print "ERROR - Invalid ipv4: $ip4\n"; next LINE; }
194
195                         $line =~ /mac\s*=\s*mac\("([^\)]*)"\)/ && do { $mac = trim($1); };
196                         unless ( $mac =~ /^([0-9a-f]{2}([:-]|$)){6}$/i ) { print "ERROR - Invalid mac: $mac\n"; next LINE; }
197
198                         $line =~ /port\s*=\s*([0-9]*)/ && do { $port = trim($1); };
199                         unless ( int($port) ) { print "ERROR - Invalid port number: $port\n"; next LINE; }
200
201                         push @rows, {
202                                 ipv6 => $ip6,
203                                 mac => $mac,
204                                 ipv4 => $ip4,
205                                 port => $port
206                         }
207                 }
208         }
209         close $fh;
210
211         return @rows;
212 }
213
214 # Generate packets originating from CPE
215 sub gen_tun_pcap {
216         my ( $binding_file, $pkt_count ) = @_;
217         my @bind = read_bindings($binding_file);
218         my $idx = 0;
219         my $row;
220         my $public_port = 0;
221
222         print "Generating $pkt_count Tunnel packets...\n";
223
224         my $max = @bind;
225         for( my $i=0; $i<$pkt_count; $i++ ) {
226
227                 $idx = rand $max;
228                 $row = @bind[$idx];
229
230                 $public_port = rand_port( $row->{port}, 0x3f );
231
232                 my ( $hdr, $pkt ) = gen_tun_packet(
233                         $size,
234                         { src => $row->{mac}, dst => ETHER_STATIC_MAC },
235                         { src => $row->{ipv6}, dst => IPv6_STATIC_IP },
236                         { src => $row->{ipv4}, dst => IPv4_STATIC_IP },
237                         { src => $public_port, dst => UDP_STATIC_PORT }
238                 );
239
240                 pcap_dump( $dumper, $hdr, $pkt );
241         }
242 }
243
244 # Generate packets originating from the internet
245 sub gen_inet_pcap {
246         my ( $binding_file, $pkt_count ) = @_;
247         my @bind = read_bindings($binding_file);
248         my $idx = 0;
249         my $row;
250         my $public_port = 0;
251
252         print "Generating $pkt_count Internet packets...\n";
253
254         my $max = @bind;
255         for( my $i=0; $i<$pkt_count; $i++ ) {
256
257                 $idx = rand $max;
258                 $row = @bind[$idx];
259
260                 $public_port = rand_port( $row->{port}, 0x3f );
261
262                 my ( $hdr, $pkt ) = gen_inet_packet(
263                         $size,
264                         { src => ETHER_STATIC_MAC, dst => $row->{mac} },
265                         { src => IPv4_STATIC_IP, dst => $row->{ipv4} },
266                         { src => UDP_STATIC_PORT, dst => $public_port }
267                 );
268
269                 pcap_dump( $dumper, $hdr, $pkt );
270         }
271 }