summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/helper-scripts/ipv6_tun
diff options
context:
space:
mode:
authorDeepak S <deepak.s@linux.intel.com>2017-07-13 21:26:50 -0700
committerDeepak S <deepak.s@linux.intel.com>2017-07-14 04:58:47 -0700
commit7286b2518ec8e4398b512ce95def9166a7af2e4a (patch)
treec93ef65d9e73e8893ccecb720152e16aae96a8b6 /VNFs/DPPD-PROX/helper-scripts/ipv6_tun
parentadcb79da90176b27224eeb1d00aa0e611ef85a9b (diff)
Adding PROX(Packet pROcessing eXecution engine) VNF to sampleVNF
JIRA: SAMPLEVNF-55 PROX is a DPDK-based application implementing Telco use-cases such as a simplified BRAS/BNG, light-weight AFTR... It also allows configuring finer grained network functions like QoS, Routing, load-balancing... (We are moving PROX version v039 to sampleVNF https://01.org/intel-data-plane-performance-demonstrators/prox-overview) Change-Id: Ia3cb02cf0e49ac5596e922c197ff7e010293d033 Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Diffstat (limited to 'VNFs/DPPD-PROX/helper-scripts/ipv6_tun')
-rwxr-xr-xVNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl271
-rwxr-xr-xVNFs/DPPD-PROX/helper-scripts/ipv6_tun/ipv6_tun_bindings.pl266
2 files changed, 537 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl b/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl
new file mode 100755
index 00000000..8e42eeba
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl
@@ -0,0 +1,271 @@
+#!/usr/bin/perl
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+
+use strict vars;
+use Getopt::Long;
+use Pod::Usage;
+use Net::Pcap;
+use Net::Frame::Layer;
+use Net::Frame::Layer::ETH qw(:consts);
+use Net::Frame::Layer::IPv6 qw(:consts);
+use Net::Frame::Layer::IPv4 qw(:consts);
+use Net::Frame::Layer::UDP;
+use Socket qw(AF_INET AF_INET6 inet_ntop inet_pton);
+
+use constant NUM_PACKETS => 30000;
+
+use constant ETHER_ADDR_LEN => 6;
+use constant ETHER_TYPE_LEN => 2;
+use constant ETHER_HDR_LEN => ( 2 * ETHER_ADDR_LEN ) + ETHER_TYPE_LEN;
+use constant ETHER_STATIC_MAC => "78acdddddddd";
+
+use constant UDP_HDR_LEN => 8;
+use constant UDP_STATIC_PORT => 0x6666;
+
+use constant IPv6_HOP_LIMIT => 4;
+use constant IPv6_STATIC_IP => "2222:2222:2222:2222:2222:2222:2222:2222";
+
+use constant IPv4_TIME_TO_LIVE => 32;
+use constant IPv4_STATIC_IP => "68.68.68.68";
+
+srand;
+
+my $type = 'tun';
+my $pkt_count = NUM_PACKETS;
+
+GetOptions(
+ 'inet' => sub { $type = 'inet'},
+ 'tun' => sub { $type = 'tun'},
+ 'count=i' => \$pkt_count,
+ 'in=s' => \(my $in = 'ip6_tun_bind.lua'),
+ 'out=s' => \(my $out = 'output.pcap'),
+ 'size=s' => \(my $size = 0)
+) or exit;
+
+my $pcap = pcap_open_dead( DLT_EN10MB, 65535 );
+my $dumper = pcap_dump_open($pcap, $out ) or die 'Could not create output file: ' . $out;
+
+if( $type eq 'inet' ) {
+ gen_inet_pcap( $in, $pkt_count );
+}
+if( $type eq 'tun' ) {
+ gen_tun_pcap( $in, $pkt_count );
+}
+
+pcap_close( $pcap );
+
+# Trim string
+sub trim {
+ my ( $str ) = @_;
+
+ $str =~ s/^\s+|\s+$//g;
+
+ return $str;
+}
+
+# Generate random port based on $port and $port_mask
+sub rand_port {
+ my ( $port, $port_mask ) = @_;
+
+ return ( $port | int( rand( 0xFFFF ) & $port_mask ) );
+}
+
+# Generate packet originating from CPE
+sub gen_tun_packet {
+ my ( $sz, $ether, $ipv6, $ipv4, $udp ) = @_;
+
+ my $hdr_ether = Net::Frame::Layer::ETH->new(
+ src => $ether->{'src'},
+ dst => $ether->{'dst'},
+ type => NF_ETH_TYPE_IPv6
+ )->pack;
+
+ my $hdr_ipv6 = Net::Frame::Layer::IPv6->new(
+ nextHeader => NF_IPv6_PROTOCOL_IPIP,
+ hopLimit => IPv6_HOP_LIMIT,
+ src => $ipv6->{'src'},
+ dst => $ipv6->{'dst'},
+ payloadLength => $sz + NF_IPv4_HDR_LEN + UDP_HDR_LEN
+ )->pack;
+
+ my $hdr_ipv4 = Net::Frame::Layer::IPv4->new(
+ length => $sz + UDP_HDR_LEN + NF_IPv4_HDR_LEN,
+ ttl => IPv4_TIME_TO_LIVE,
+ protocol => NF_IPv4_PROTOCOL_UDP,
+ src => $ipv4->{'src'},
+ dst => $ipv4->{'dst'}
+ )->pack;
+
+ my $hdr_udp = Net::Frame::Layer::UDP->new(
+ src => $udp->{'src'},
+ dst => $udp->{'dst'},
+ length => $sz + UDP_HDR_LEN
+ )->pack;
+
+ my $pkt = pack( "H*", "de" x $sz );
+ $pkt = $hdr_ether . $hdr_ipv6 . $hdr_ipv4 . $hdr_udp . $pkt;
+
+ my $pkt_size = length( $pkt );
+
+ my $hdr = {
+ tv_sec => 0,
+ tv_usec => 0,
+ len => $pkt_size,
+ caplen => $pkt_size
+ };
+
+ return ( $hdr, $pkt );
+}
+
+# Generate packet originating from the internet
+sub gen_inet_packet {
+ my ( $sz, $ether, $ipv4, $udp ) = @_;
+
+ my $hdr_ether = Net::Frame::Layer::ETH->new(
+ src => $ether->{'src'},
+ dst => $ether->{'dst'},
+ type => NF_ETH_TYPE_IPv4
+ )->pack;
+
+ my $hdr_ipv4 = Net::Frame::Layer::IPv4->new(
+ length => $sz + UDP_HDR_LEN + NF_IPv4_HDR_LEN,
+ ttl => IPv4_TIME_TO_LIVE,
+ protocol => NF_IPv4_PROTOCOL_UDP,
+ src => $ipv4->{'src'},
+ dst => $ipv4->{'dst'}
+ )->pack;
+
+ my $hdr_udp = Net::Frame::Layer::UDP->new(
+ src => $udp->{'src'},
+ dst => $udp->{'dst'},
+ length => $sz + UDP_HDR_LEN
+ )->pack;
+
+ my $pkt = pack( "H*", "de" x $sz );
+ $pkt = $hdr_ether . $hdr_ipv4 . $hdr_udp . $pkt;
+
+ my $pkt_size = length( $pkt );
+
+ my $hdr = {
+ tv_sec => 0,
+ tv_usec => 0,
+ len => $pkt_size,
+ caplen => $pkt_size
+ };
+
+ return ( $hdr, $pkt );
+}
+
+# Read bindings file
+sub read_bindings {
+ my ( $file ) = @_;
+
+ print "Reading bindings file...\n";
+
+ my @rows;
+
+ open my $fh, "<:encoding(utf8)", $file or die $file . ": $!";
+LINE: while ( my $line = <$fh> ) {
+ next if ($line =~ /^--.*/); # Skip comments
+
+ my ($ip6, $mac, $ip4, $port);
+ if ($line =~ /\s*\{.*\},\s*$/) { # Weak check for a data line...
+
+ $line =~ /ip6\s*=\s*ip6\("([^\)]*)"\)/ && do { $ip6 = trim($1); };
+ unless ( inet_pton( AF_INET6, $ip6 ) ) { print "ERROR - Invalid ipv6: $ip6\n"; next LINE; }
+
+ $line =~ /ip\s*=\s*ip\("([^\)]*)"\)/ && do { $ip4 = trim($1); };
+ unless ( inet_pton( AF_INET, $ip4 ) ) { print "ERROR - Invalid ipv4: $ip4\n"; next LINE; }
+
+ $line =~ /mac\s*=\s*mac\("([^\)]*)"\)/ && do { $mac = trim($1); };
+ unless ( $mac =~ /^([0-9a-f]{2}([:-]|$)){6}$/i ) { print "ERROR - Invalid mac: $mac\n"; next LINE; }
+
+ $line =~ /port\s*=\s*([0-9]*)/ && do { $port = trim($1); };
+ unless ( int($port) ) { print "ERROR - Invalid port number: $port\n"; next LINE; }
+
+ push @rows, {
+ ipv6 => $ip6,
+ mac => $mac,
+ ipv4 => $ip4,
+ port => $port
+ }
+ }
+ }
+ close $fh;
+
+ return @rows;
+}
+
+# Generate packets originating from CPE
+sub gen_tun_pcap {
+ my ( $binding_file, $pkt_count ) = @_;
+ my @bind = read_bindings($binding_file);
+ my $idx = 0;
+ my $row;
+ my $public_port = 0;
+
+ print "Generating $pkt_count Tunnel packets...\n";
+
+ my $max = @bind;
+ for( my $i=0; $i<$pkt_count; $i++ ) {
+
+ $idx = rand $max;
+ $row = @bind[$idx];
+
+ $public_port = rand_port( $row->{port}, 0x3f );
+
+ my ( $hdr, $pkt ) = gen_tun_packet(
+ $size,
+ { src => $row->{mac}, dst => ETHER_STATIC_MAC },
+ { src => $row->{ipv6}, dst => IPv6_STATIC_IP },
+ { src => $row->{ipv4}, dst => IPv4_STATIC_IP },
+ { src => $public_port, dst => UDP_STATIC_PORT }
+ );
+
+ pcap_dump( $dumper, $hdr, $pkt );
+ }
+}
+
+# Generate packets originating from the internet
+sub gen_inet_pcap {
+ my ( $binding_file, $pkt_count ) = @_;
+ my @bind = read_bindings($binding_file);
+ my $idx = 0;
+ my $row;
+ my $public_port = 0;
+
+ print "Generating $pkt_count Internet packets...\n";
+
+ my $max = @bind;
+ for( my $i=0; $i<$pkt_count; $i++ ) {
+
+ $idx = rand $max;
+ $row = @bind[$idx];
+
+ $public_port = rand_port( $row->{port}, 0x3f );
+
+ my ( $hdr, $pkt ) = gen_inet_packet(
+ $size,
+ { src => ETHER_STATIC_MAC, dst => $row->{mac} },
+ { src => IPv4_STATIC_IP, dst => $row->{ipv4} },
+ { src => UDP_STATIC_PORT, dst => $public_port }
+ );
+
+ pcap_dump( $dumper, $hdr, $pkt );
+ }
+}
diff --git a/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/ipv6_tun_bindings.pl b/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/ipv6_tun_bindings.pl
new file mode 100755
index 00000000..02af5103
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/ipv6_tun_bindings.pl
@@ -0,0 +1,266 @@
+#!/usr/bin/perl
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+
+=head1 NAME
+
+ipv6_tun_bindings.pl
+
+=head1 SYNOPSIS
+
+ ipv6_tun_bindings.pl [-n <num_entries>] [-tun_ip <ipv6>] [-mac <next_hop_mac>]
+ [-pub_ip <ipv4>] [-port <begin>-<end>] [-set <num_ports>]
+ [-suffix <suffix>] [-test <num_entries>] [-sym|-nosym]
+ [-help]
+
+=head1 DESCRIPTION
+
+This script can be used to generate a binding table for the IPv6 Tunnel
+task implemented in PROX (ipv6_encap and ipv6_decap).
+The entries in this table bind a specific tunnel endpoint (lwB4 in lw4over6
+architecture) to a public IPv4 address and port set.
+The port set is actually derived from the port specified in the table
+and a port bitmask in the PROX task configuration ("lookup port mask").
+
+The ipv6_encap task uses the binding table to know where to tunnel IPv4
+traffic to. The ipv6_decap task uses the table to verify tunnel packets
+have a valid public IPv4 and port combination for the originating tunnel.
+
+The table uses the Lua syntax so it can be loaded into PROX. Example:
+return {
+ {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},
+ {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},
+ {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},
+ {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},
+}
+
+The script generates consecutive entries, starting from a given IP address
+and assigning ports within a given range, increasing the port number by a
+fixed amount which should correspond to the port lookup mask being used.
+
+UDF table: In addition to the binding table itself, the script can optionally
+generate accompanying UDF tables for generating test traffic matching the
+binding table. Such UDF tables can then be used in a traffic generation tool.
+
+=head1 OPTIONS
+
+=over 22
+
+=item -n <num_entries>
+
+How many entries in the binding table
+
+=item -tun_ip <ipv6>
+
+Starting tunnel endpoint IPv6 address (will be incremented)
+
+=item -mac <next_hop_mac>
+
+MAC address of the next hop to reach the tunnel endpoints
+
+=item -pub_ip <ipv4>
+
+Starting public IPv4 address
+
+=item -port <begin>-<end>
+
+Range of ports where to assign Port Sets
+
+=item -set <num_ports>
+
+Number of ports in set (should be a power of 2 because bitmasking is used
+in lwAFTR)
+
+=item -suffix <suffix>
+
+Filename suffix to use for the generated file(s)
+
+=item -test <num_entries>
+
+Number of random entries to put into test UDF table
+
+=item -sym
+
+Whether the same random entry from the table should be inserted into both
+traffic sides or if different entries should be used
+
+=item -help
+
+Shows the full script documentation.
+
+=back
+
+=head1 AUTHOR
+
+ Copyright(c) 2010-2017 Intel Corporation.
+ All rights reserved.
+
+=cut
+
+
+use strict vars;
+use Getopt::Long;
+use Pod::Usage;
+use Socket qw(AF_INET AF_INET6 inet_ntop inet_pton);
+
+sub parse_ip
+{
+ my ($str, $ip_ref, $family) = @_;
+
+ my $packed = inet_pton($family, $str);
+ return 0 if (!defined($packed));
+
+ if ($family == AF_INET6) {
+ #print unpack("H*", $packed). "\n";
+ my @w = unpack("NNNN", $packed);
+ my ($high, $low) = (($w[0] << 32) | $w[1], ($w[2] << 32) | $w[3]);
+ @$ip_ref = ($high, $low);
+ }
+ else {
+ $$ip_ref = unpack("N", $packed);
+ }
+ return 1;
+}
+
+sub ntop6
+{
+ my ($in) = @_;
+ my $packed = pack('NNNN', $in->[0] >> 32, $in->[0] & 0xffffffff,
+ $in->[1] >> 32, $in->[1] & 0xffffffff);
+ return inet_ntop(AF_INET6, $packed);
+}
+
+sub ntop6_expanded
+{
+ my ($in) = @_;
+ return sprintf('%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x',
+ ($in->[0] >> 48) & 0xffff, ($in->[0] >> 32) & 0xffff,
+ ($in->[0] >> 16) & 0xffff, ($in->[0] ) & 0xffff,
+ ($in->[1] >> 48) & 0xffff, ($in->[1] >> 32) & 0xffff,
+ ($in->[1] >> 16) & 0xffff, ($in->[1] ) & 0xffff);
+}
+
+my ($tun_ip_str, $pub_ip_str, $ports_str);
+
+GetOptions(
+ 'help' => sub () { Pod::Usage::pod2usage( -verbose => 2 ); exit; },
+ 'n=i' => \(my $num_B4s = 10),
+ 'tun_ip=s' => \(my $tun_ip_str = 'fe80:0000:0000:0000:0200:00ff:0000:0000'),
+ 'pub_ip=s' => \(my $pub_ip_str = '171.205.239.1'),
+ 'mac=s' => \(my $next_hop_mac = 'fe:80:00:00:00:00'),
+ 'port=s' => \(my $ports_str='4608-11968'),
+ 'set=n' => \(my $port_set_sz = 64),
+ 'suffix=s' => \(my $suffix = ''),
+ 'test=n' => \(my $num_test_lines = 200000),
+ 'sym!' => \(my $symmetric_traffic = TRUE),
+) or pod2usage(-verbose => 1) && exit;
+
+my @tun_ip;
+parse_ip($tun_ip_str, \@tun_ip, AF_INET6) or print("Invalid starting tunnel IP: $tun_ip_str\n") && pod2usage(-verbose => 1) && exit;
+parse_ip($pub_ip_str, \(my $pub_ip), AF_INET) or print("Invalid starting public IP: $pub_ip_str\n") && pod2usage(-verbose => 1) && exit;
+my @port_range;
+if ($ports_str =~ /^([^d]+)\s*\-\s*([^d]+)$/) {
+ @port_range = ($1, $2);
+}
+else { print "Invalid port range: $ports_str\n"; pod2usage(-verbose => 1); exit }
+
+# Summary of input data
+print "File suffix: $suffix\n" if ($suffix);
+print "Starting Tunnel IP: " . ntop6(\@tun_ip) . "\n";
+print "Starting Public IP: ".inet_ntop(AF_INET, pack("N", $pub_ip)) . "\n";
+print "Public Port Range: $port_range[0]-$port_range[1] by blocks of $port_set_sz\n";
+
+my @data; # Holds generated binding table, so we can later generate test traffic for it
+
+# Binding table for PROX IPv6 Tunnel
+my $filename = 'ip6_tun_bind'.$suffix.'.lua';
+print "\nGenerating binding table with $num_B4s entries into $filename ... ";
+open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
+print $fh "-- Bindings for lwaftr: lwB4 IPv6 address, next hop MAC address\n";
+print $fh "-- towards lwB4, IPv4 Public address, IPv4 Public Port Set\n";
+print $fh "\n";
+print $fh "return {" . "\n";
+my $port = $port_range[0];
+for (my $B4_id = 0; $B4_id < $num_B4s; $B4_id++) {
+ $data[$B4_id]{'b4_ipv6'} = ntop6_expanded(\@tun_ip);
+ $data[$B4_id]{'pub_ipv4'} = "" . (($pub_ip >> 24) & 0xff) . "." . (($pub_ip >> 16) & 0xff) . "." . (($pub_ip >> 8) & 0xff) . "." . ($pub_ip & 0xff);
+ $data[$B4_id]{'pub_port'} = $port;
+ $data[$B4_id]{'next_hop_mac'} = $next_hop_mac;
+
+ print $fh " {";
+ print $fh "ip6 = ip6(\"" . $data[$B4_id]{'b4_ipv6'} . "\")";
+ print $fh ", mac = mac(\"" . $data[$B4_id]{'next_hop_mac'} . "\")";
+ print $fh ", ip = ip(\"" . $data[$B4_id]{'pub_ipv4'} . "\")";
+ print $fh ", port = " . $data[$B4_id]{'pub_port'};
+ print $fh "},\n";
+
+ $port += $port_set_sz;
+ if ($port > $port_range[1]) {
+ $pub_ip++;
+ $port = $port_range[0];
+ }
+
+ # Move to next Tunnel address
+ if (@tun_ip[1] < 0xffffffffffffffff) {
+ @tun_ip[1]++;
+ } else {
+ @tun_ip[0]++;
+ @tun_ip[1] = 0;
+ }
+}
+print $fh "}" . "\n";
+close $fh;
+print "[DONE]\n";
+
+# Test traffic "UDF Tables"
+if ($num_test_lines) {
+ print "Generating $num_test_lines lines of test UDF table into lwAFTR_tun|inet".$suffix.".csv ... ";
+
+ # Tunnel Packets from B4 to lwAFTR
+ my $filename = 'lwAFTR_tun' . $suffix . '.csv';
+ open(my $fh_tun, '>', $filename) or die "Could not open file '$filename' $!";
+ print $fh_tun "b4_ip,pub_ip,pub_port\n";
+ print $fh_tun "22,66,74\n"; # Offsets
+ print $fh_tun "16,4,2\n"; # Sizes
+ print $fh_tun "6,5,3\n"; # Format (IPv6, IPv4, Decimal)
+ print $fh_tun ",,\n";
+
+ # Internet Packets towards the lwAFTR, to be sent to corresp lwB4 over tunnel
+ my $filename = 'lwAFTR_inet' . $suffix . '.csv';
+ open(my $fh_inet, '>', $filename) or die "Could not open file '$filename' $!";
+ print $fh_inet "pub_ip,pub_port\n";
+ print $fh_inet "30,36\n"; # Offsets
+ print $fh_inet "4,2\n"; # Sizes
+ print $fh_inet "5,3\n"; # Format (IPv6, IPv4, Decimal)
+ print $fh_inet ",,\n";
+
+ for (my $i = 0; $i < $num_test_lines; $i++) {
+ my $B4_id = int(rand($num_B4s));
+ my $port = $data[$B4_id]{'pub_port'} + int(rand($port_set_sz));
+ printf $fh_tun $data[$B4_id]{'b4_ipv6'} . "," . $data[$B4_id]{'pub_ipv4'} . "," . $port . "\n";
+
+ if (! $symmetric_traffic) {
+ $B4_id = int(rand($num_B4s));
+ $port = $data[$B4_id]{'pub_port'} + int(rand($port_set_sz));
+ }
+ printf $fh_inet $data[$B4_id]{'pub_ipv4'} . "," . $port . "\n";
+ }
+
+ close $fh_tun;
+ close $fh_inet;
+ print "[DONE]\n";
+}