Add support for multiple VLANs per ifIndex

sFlow and Netflow v9/v10 may provide VLAN information in flows, so
one can distinguish between different logical links on the same
physical connection (e.g. transit via private VLAN over IXP).
This commit is contained in:
Andre Grueneberg 2014-06-14 20:16:05 +02:00
parent 3a44e2448d
commit 5c84c03765
4 changed files with 40 additions and 12 deletions

View File

@ -1,3 +1,10 @@
## post 1.5
* Added support for multiple links on one ifIndex, based on VLANs. Only
sFlow, Netflow v9 and v10 (IPFIX) support this. Obviously your router
needs to provide the information. Just add "/<vlan>" to the ifIndex in
your knownlinks file.
## 1.5
* Merged netflow-asstatd.pl and sflow-asstatd.pl into one script so

View File

@ -30,7 +30,7 @@ scripts.
Prerequisites
-------------
- Perl 5.8
- Perl 5.10
- RRDtool 1.2 (with Perl "RRDs" library)
- if using sFlow: the Net::sFlow module (CPAN)
- web server with PHP 5

View File

@ -6,6 +6,7 @@
# cli params/rrd storage/sampling mods Steve Colam <steve@colam.co.uk>
use strict;
use 5.010;
use IO::Select;
use IO::Socket;
use RRDs;
@ -259,7 +260,7 @@ sub parse_netflow_v9_data_flowset {
my $datalen = length($flowsetdata);
while (($ofs + $len) <= $datalen) {
# Interpret values according to template
my ($inoctets, $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
my ($inoctets, $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, $vlanin, $vlanout);
$inoctets = 0;
$outoctets = 0;
@ -312,11 +313,15 @@ sub parse_netflow_v9_data_flowset {
$ipversion = unpack("C", $cur_fldval);
} elsif ($cur_fldtype == 27 || $cur_fldtype == 28) { # IPV6_SRC_ADDR/IPV6_DST_ADDR
$ipversion = 6;
} elsif ($cur_fldtype == 58) { # SRC_VLAN
$vlanin = unpack("n", $cur_fldval);
} elsif ($cur_fldtype == 59) { # SRC_VLAN
$vlanout = unpack("n", $cur_fldval);
}
}
if (defined($srcas) && defined($dstas) && defined($snmpin) && defined($snmpout)) {
handleflow($ipaddr, $inoctets + $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, 'netflow');
handleflow($ipaddr, $inoctets + $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, 'netflow', $vlanin, $vlanout);
}
}
}
@ -400,7 +405,7 @@ sub parse_netflow_v10_data_flowset {
my $datalen = length($flowsetdata);
while (($ofs + $len) <= $datalen) {
# Interpret values according to template
my ($inoctets, $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
my ($inoctets, $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, $vlanin, $vlanout);
$inoctets = 0;
$outoctets = 0;
@ -453,11 +458,15 @@ sub parse_netflow_v10_data_flowset {
$ipversion = unpack("C", $cur_fldval);
} elsif ($cur_fldtype == 27 || $cur_fldtype == 28) { # IPV6_SRC_ADDR/IPV6_DST_ADDR
$ipversion = 6;
} elsif ($cur_fldtype == 58) { # SRC_VLAN
$vlanin = unpack("n", $cur_fldval);
} elsif ($cur_fldtype == 59) { # SRC_VLAN
$vlanout = unpack("n", $cur_fldval);
}
}
if (defined($srcas) && defined($dstas) && defined($snmpin) && defined($snmpout)) {
handleflow($ipaddr, $inoctets + $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, 'netflow');
handleflow($ipaddr, $inoctets + $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, 'netflow', $vlanin, $vlanout);
}
}
}
@ -541,13 +550,22 @@ sub parse_sflow {
if ($dstas == $myas) {
$dstas = 0;
}
# Extract VLAN information
my ($vlanin, $vlanout);
if ($sFlowSample->{'SwitchSrcVlan'}) {
$vlanin = $sFlowSample->{'SwitchSrcVlan'};
}
if ($sFlowSample->{'SwitchDestVlan'}) {
$vlanout = $sFlowSample->{'SwitchDestVlan'};
}
handleflow($ipaddr, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, 'sflow');
handleflow($ipaddr, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, 'sflow', $vlanin, $vlanout);
}
}
sub handleflow {
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion) = @_;
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion, $vlanin, $vlanout) = @_;
if ($srcas == 0 && $dstas == 0) {
# don't care about internal traffic
@ -564,14 +582,16 @@ sub handleflow {
if ($srcas == 0) {
$as = $dstas;
$direction = "out";
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpout};
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpout . '/' . $vlanout};
$ifalias //= $knownlinks{inet_ntoa($routerip) . '_' . $snmpout};
} elsif ($dstas == 0) {
$as = $srcas;
$direction = "in";
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpin};
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpin . '/' . $vlanin};
$ifalias //= $knownlinks{inet_ntoa($routerip) . '_' . $snmpin};
} else {
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout, $ipversion);
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout, $ipversion);
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout, $ipversion, $vlanin, $vlanout);
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout, $ipversion, $vlanin, $vlanout);
return;
}

View File

@ -1,4 +1,4 @@
# Router IP SNMP ifindex tag description color samplingrate
# Router IP SNMP ifindex[/VLAN] tag description color samplingrate
# note: tabs must be used to separate fields (not spaces)
# max. length for tag is 12 characters; allowed characters: a-z A-Z 0-9 _
192.0.2.1 15 uplink1 Uplink 1 A6CEE3 1
@ -8,3 +8,4 @@
192.0.2.2 42 peering1 IXP 1 FB9A99 1
192.0.2.2 45 peering2 IXP 2 E31A1C 1
192.0.2.3 6 peering3 IXP 3 FDBF6F 2048
192.0.2.3 6/42 uplink5 Uplink 5 via VLAN 42 F86FFD 2048