* add support for NetFlow v9

* add support for IPv6
* add support for 4-byte ASNs
This commit is contained in:
Manuel Kasper 2013-01-21 15:12:01 +00:00
parent 436fe23352
commit 3ff7930189
15 changed files with 7677 additions and 10859 deletions

21
README
View File

@ -1,11 +1,23 @@
AS-Stats v1.36 (2012-07-25)
AS-Stats v1.40 (2012-11-23)
a simple tool to generate per-AS traffic graphs from NetFlow/sFlow records
by Manuel Kasper, Monzoon Networks AG <mkasper@monzoon.net>
--------------------------------------------------------------------
Changes
-------
vx.xx Add links to PeeringDB and robtex
v1.40 Add support for NetFlow v9 to netflow-asstatd.pl
(sponsored by Xplornet Communications Inc.)
Add support for IPv6 (for NetFlow v9 and sFlow). Note: existing
RRDs need to be upgraded (new data sources added for v6) for
this to work. Enable $showv6 in www/config.inc to see separate
graphs for IPv6.
Add support for 4-byte ASNs (NetFlow v9 and sFlow). Needs testing.
Add RRA for 1 month at 4 hour resolution to newly created RRD files.
Add links to PeeringDB and robtex
(suggested by Steve Glendinning)
Fix AS-SET lookup on systems where the whois command returns
@ -188,8 +200,9 @@ sFlow data.
will reach the machine running xx-asstatd.pl (firewall etc.).
- NetFlow only:
Have your router(s) send NetFlow v8 AS aggregation records to your machine.
This is typically done with commands like the following (Cisco IOS):
Have your router(s) send NetFlow v8 or v9 AS aggregation records to
your machine. This is typically done with commands like the following
(Cisco IOS):
ip flow-cache timeout active 5

View File

@ -21,9 +21,11 @@ my $ascache_flush_number = 0;
my $server_port = 9000;
my $MAXREAD = 8192;
my $header_len = 28;
my $flowrec_len = 28;
my $v8_header_len = 28;
my $v8_flowrec_len = 28;
my $v9_header_len = 20;
my $childrunning = 0;
my $v9_templates = {};
use vars qw/ %opt /;
getopts('r:p:k:s:', \%opt);
@ -85,34 +87,186 @@ while (1) {
my ($port, $ipaddr) = sockaddr_in($server->peername);
my ($version) = unpack("n", $datagram);
if ($version == 8) {
parse_netflow_v8($datagram, $ipaddr);
} elsif ($version == 9) {
parse_netflow_v9($datagram, $ipaddr);
} else {
print "unknown NetFlow version: $version\n";
}
}
sub parse_netflow_v8 {
my $datagram = shift;
my $ipaddr = shift;
my ($version, $count, $sysuptime, $unix_secs, $unix_nsecs,
$flow_sequence, $engine_type, $engine_id, $aggregation,
$agg_version) = unpack("nnNNNNCCCC", $datagram);
if ($version != 8 || $aggregation != 1 || ($agg_version != 0 && $agg_version != 2)) {
if ($aggregation != 1 || ($agg_version != 0 && $agg_version != 2)) {
print "unknown version: $version/$aggregation/$agg_version\n";
next;
return;
}
my $flowrecs = substr($datagram, $header_len);
my $flowrecs = substr($datagram, $v8_header_len);
for (my $i = 0; $i < $count; $i++) {
my $flowrec = substr($datagram, $header_len + ($i*$flowrec_len), $flowrec_len);
my $flowrec = substr($datagram, $v8_header_len + ($i*$v8_flowrec_len), $v8_flowrec_len);
my @flowdata = unpack("NNNNNnnnn", $flowrec);
handleflow($ipaddr, @flowdata);
handleflow($ipaddr, $flowdata[2], $flowdata[5], $flowdata[6], $flowdata[7], $flowdata[8], 4);
}
}
sub parse_netflow_v9 {
my $datagram = shift;
my $ipaddr = shift;
# Parse packet
my ($version, $count, $sysuptime, $unix_secs, $seqno, $source_id, @flowsets) = unpack("nnNNNN(nnX4/a)*", $datagram);
# Loop through FlowSets and take appropriate action
for (my $i = 0; $i < scalar @flowsets; $i += 2) {
my $flowsetid = $flowsets[$i];
my $flowsetdata = substr($flowsets[$i+1], 4); # chop off id/length
if ($flowsetid == 0) {
# 0 = Template FlowSet
parse_netflow_v9_template_flowset($flowsetdata, $ipaddr, $source_id);
} elsif ($flowsetid == 1) {
# 1 - Options Template FlowSet
} elsif ($flowsetid > 255) {
# > 255: Data FlowSet
parse_netflow_v9_data_flowset($flowsetid, $flowsetdata, $ipaddr, $source_id);
} else {
# reserved FlowSet
print "Unknown FlowSet ID $flowsetid found\n";
}
}
}
sub parse_netflow_v9_template_flowset {
my $templatedata = shift;
my $ipaddr = shift;
my $source_id = shift;
# Note: there may be multiple templates in a Template FlowSet
my @template_ints = unpack("n*", $templatedata);
my $i = 0;
while ($i < scalar @template_ints) {
my $template_id = $template_ints[$i];
my $fldcount = $template_ints[$i+1];
last if (!defined($template_id) || !defined($fldcount));
#print "Updated template ID $template_id (source ID $source_id, from " . inet_ntoa($ipaddr) . ")\n";
my $template = [@template_ints[($i+2) .. ($i+2+$fldcount*2-1)]];
$v9_templates->{$ipaddr}->{$source_id}->{$template_id}->{'template'} = $template;
# Calculate total length of template data
my $totallen = 0;
for (my $j = 1; $j < scalar @$template; $j += 2) {
$totallen += $template->[$j];
}
$v9_templates->{$ipaddr}->{$source_id}->{$template_id}->{'len'} = $totallen;
$i += (2 + $fldcount*2);
}
}
sub parse_netflow_v9_data_flowset {
my $flowsetid = shift;
my $flowsetdata = shift;
my $ipaddr = shift;
my $source_id = shift;
my $template = $v9_templates->{$ipaddr}->{$source_id}->{$flowsetid}->{'template'};
if (!defined($template)) {
#print "Template ID $flowsetid from $source_id/" . inet_ntoa($ipaddr) . " does not (yet) exist\n";
return;
}
my $len = $v9_templates->{$ipaddr}->{$source_id}->{$flowsetid}->{'len'};
my $ofs = 0;
my $datalen = length($flowsetdata);
while (($ofs + $len) <= $datalen) {
# Interpret values according to template
my ($inoctets, $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
$inoctets = 0;
$outoctets = 0;
$ipversion = 4;
for (my $i = 0; $i < scalar @$template; $i += 2) {
my $cur_fldtype = $template->[$i];
my $cur_fldlen = $template->[$i+1];
my $cur_fldval = substr($flowsetdata, $ofs, $cur_fldlen);
$ofs += $cur_fldlen;
if ($cur_fldtype == 16) { # SRC_AS
if ($cur_fldlen == 2) {
$srcas = unpack("n", $cur_fldval);
} elsif ($cur_fldlen == 4) {
$srcas = unpack("N", $cur_fldval);
}
} elsif ($cur_fldtype == 17) { # DST_AS
if ($cur_fldlen == 2) {
$dstas = unpack("n", $cur_fldval);
} elsif ($cur_fldlen == 4) {
$dstas = unpack("N", $cur_fldval);
}
} elsif ($cur_fldtype == 10) { # INPUT_SNMP
if ($cur_fldlen == 2) {
$snmpin = unpack("n", $cur_fldval);
} elsif ($cur_fldlen == 4) {
$snmpin = unpack("N", $cur_fldval);
}
} elsif ($cur_fldtype == 14) { # OUTPUT_SNMP
if ($cur_fldlen == 2) {
$snmpout = unpack("n", $cur_fldval);
} elsif ($cur_fldlen == 4) {
$snmpout = unpack("N", $cur_fldval);
}
} elsif ($cur_fldtype == 1) { # IN_BYTES
if ($cur_fldlen == 4) {
$inoctets = unpack("N", $cur_fldval);
} elsif ($cur_fldlen == 8) {
$inoctets = unpack("Q", $cur_fldval);
}
} elsif ($cur_fldtype == 23) { # OUT_BYTES
if ($cur_fldlen == 4) {
$outoctets = unpack("N", $cur_fldval);
} elsif ($cur_fldlen == 8) {
$outoctets = unpack("Q", $cur_fldval);
}
} elsif ($cur_fldtype == 60) { # IP_PROTOCOL_VERSION
$ipversion = unpack("C", $cur_fldval);
} elsif ($cur_fldtype == 27 || $cur_fldtype == 28) { # IPV6_SRC_ADDR/IPV6_DST_ADDR
$ipversion = 6;
}
}
if (defined($srcas) && defined($dstas) && defined($snmpin) && defined($snmpout)) {
handleflow($ipaddr, $inoctets + $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
}
}
}
sub handleflow {
my ($routerip, $nflows, $npackets, $noctets, $firstts, $lastts,
$srcas, $dstas, $snmpin, $snmpout) = @_;
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion) = @_;
if ($srcas == 0 && $dstas == 0) {
# don't care about internal traffic
return;
}
#print "$srcas => $dstas ($noctets octets)\n";
#print "$srcas => $dstas ($noctets octets, version $ipversion, snmpin $snmpin, snmpout $snmpout)\n";
# determine direction and interface alias name (if known)
my $direction;
@ -128,10 +282,8 @@ sub handleflow {
$direction = "in";
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpin};
} else {
handleflow($routerip, $nflows, $npackets, $noctets, $firstts, $lastts,
$srcas, 0, $snmpin, $snmpout);
handleflow($routerip, $nflows, $npackets, $noctets, $firstts, $lastts,
0, $dstas, $snmpin, $snmpout);
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout, $ipversion);
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout, $ipversion);
return;
}
@ -140,7 +292,12 @@ sub handleflow {
return;
}
my $dsname = "${ifalias}_${direction}";
my $dsname;
if ($ipversion == 6) {
$dsname = "${ifalias}_v6_${direction}";
} else {
$dsname = "${ifalias}_${direction}";
}
# put it into the cache
if (!$ascache->{$as}) {
@ -238,9 +395,12 @@ sub getrrdfile {
foreach my $alias (keys %links) {
push(@args, "DS:${alias}_in:ABSOLUTE:300:U:U");
push(@args, "DS:${alias}_out:ABSOLUTE:300:U:U");
push(@args, "DS:${alias}_v6_in:ABSOLUTE:300:U:U");
push(@args, "DS:${alias}_v6_out:ABSOLUTE:300:U:U");
}
push(@args, "RRA:AVERAGE:0.99999:1:576"); # 48 hours at 5 minute resolution
push(@args, "RRA:AVERAGE:0.99999:12:168"); # 1 week at 1 hour resolution
push(@args, "RRA:AVERAGE:0.99999:48:180"); # 1 month at 4 hour resolution
push(@args, "RRA:AVERAGE:0.99999:288:366"); # 1 year at 1 day resolution
RRDs::create($rrdfile, "--start", $startts, @args);

View File

@ -69,7 +69,7 @@ open(STATSFILE, ">$statsfile.tmp");
# print header line
print STATSFILE "as";
foreach my $link (@links) {
print STATSFILE "\t${link}_in\t${link}_out";
print STATSFILE "\t${link}_in\t${link}_out\t${link}_v6_in\t${link}_v6_out";
}
print STATSFILE "\n";
@ -78,8 +78,10 @@ foreach my $as (@asorder) {
print STATSFILE "$as";
foreach my $link (@links) {
print STATSFILE "\t" . $astraffic->{$as}->{"${link}_in"};
print STATSFILE "\t" . $astraffic->{$as}->{"${link}_out"};
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_in"});
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_out"});
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_v6_in"});
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_v6_out"});
}
print STATSFILE "\n";
@ -89,6 +91,15 @@ close(STATSFILE);
rename("$statsfile.tmp", $statsfile);
sub undefaszero {
my $val = shift;
if (!defined($val)) {
return 0;
} else {
return $val;
}
}
sub gettraffic {
my $as = shift;
@ -103,11 +114,16 @@ sub gettraffic {
my $rrdfile = "$dirname/$as.rrd";
# get list of available DS
my $have_v6 = 0;
my $availableds = {};
my $rrdinfo = RRDs::info($rrdfile);
foreach my $ri (keys %$rrdinfo) {
if ($ri =~ /^ds\[(.+)\]\.type$/) {
$availableds->{$1} = 1;
if ($1 =~ /_v6_/) {
$have_v6 = 1;
}
}
}
@ -118,8 +134,21 @@ sub gettraffic {
push(@cmd, "DEF:${link}_out=$rrdfile:${link}_out:AVERAGE");
push(@cmd, "VDEF:${link}_in_v=${link}_in,TOTAL");
push(@cmd, "VDEF:${link}_out_v=${link}_out,TOTAL");
if ($have_v6) {
push(@cmd, "DEF:${link}_v6_in=$rrdfile:${link}_v6_in:AVERAGE");
push(@cmd, "DEF:${link}_v6_out=$rrdfile:${link}_v6_out:AVERAGE");
push(@cmd, "VDEF:${link}_v6_in_v=${link}_v6_in,TOTAL");
push(@cmd, "VDEF:${link}_v6_out_v=${link}_v6_out,TOTAL");
}
push(@cmd, "PRINT:${link}_in_v:%lf");
push(@cmd, "PRINT:${link}_out_v:%lf");
if ($have_v6) {
push(@cmd, "PRINT:${link}_v6_in_v:%lf");
push(@cmd, "PRINT:${link}_v6_out_v:%lf");
}
}
my @res = RRDs::graph(@cmd);
@ -131,20 +160,24 @@ sub gettraffic {
my $lines = $res[0];
for (my $i = 0; $i < scalar(@links); $i++) {
my $in = $lines->[$i*2];
chomp($in);
if (isnan($in)) {
$in = 0;
my @vals;
my $numds = ($have_v6 ? 4 : 2);
for (my $j = 0; $j < $numds; $j++) {
$vals[$j] = $lines->[$i*$numds+$j];
chomp($vals[$j]);
if (isnan($vals[$j])) {
$vals[$j] = 0;
}
}
my $out = $lines->[$i*2+1];
chomp($out);
if (isnan($out)) {
$out = 0;
}
$retdata->{$links[$i] . '_in'} = $vals[0];
$retdata->{$links[$i] . '_out'} = $vals[1];
$retdata->{$links[$i] . '_in'} = $in;
$retdata->{$links[$i] . '_out'} = $out;
if ($have_v6) {
$retdata->{$links[$i] . '_v6_in'} = $vals[2];
$retdata->{$links[$i] . '_v6_out'} = $vals[3];
}
}
return $retdata;

View File

@ -102,6 +102,8 @@ while (1) {
}
foreach my $sFlowSample (@{$sFlowSamplesRef}) {
my $ipversion = 4;
# only process standard structures
next if ($sFlowSample->{'sampleTypeEnterprise'} != 0);
@ -121,6 +123,9 @@ while (1) {
my $noctets;
if ($sFlowSample->{'IPv4Packetlength'}) {
$noctets = $sFlowSample->{'IPv4Packetlength'};
} elsif ($sFlowSample->{'IPv6Packetlength'}) {
$noctets = $sFlowSample->{'IPv6Packetlength'};
$ipversion = 6;
} else {
$noctets = $sFlowSample->{'HeaderFrameLength'} - 14;
}
@ -152,12 +157,12 @@ while (1) {
$dstas = 0;
}
handleflow($ipaddr, $noctets, $srcas, $dstas, $snmpin, $snmpout);
handleflow($ipaddr, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
}
}
sub handleflow {
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout) = @_;
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion) = @_;
if ($srcas == 0 && $dstas == 0) {
# don't care about internal traffic
@ -180,8 +185,8 @@ sub handleflow {
$direction = "in";
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpin};
} else {
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout);
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout);
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout, $ipversion);
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout, $ipversion);
return;
}
@ -190,7 +195,12 @@ sub handleflow {
return;
}
my $dsname = "${ifalias}_${direction}";
my $dsname;
if ($ipversion == 6) {
$dsname = "${ifalias}_v6_${direction}";
} else {
$dsname = "${ifalias}_${direction}";
}
# put it into the cache
if (!$ascache->{$as}) {
@ -285,9 +295,12 @@ sub getrrdfile {
while (my ($key, $alias) = each(%knownlinks)) {
push(@args, "DS:${alias}_in:ABSOLUTE:300:U:U");
push(@args, "DS:${alias}_out:ABSOLUTE:300:U:U");
push(@args, "DS:${alias}_v6_in:ABSOLUTE:300:U:U");
push(@args, "DS:${alias}_v6_out:ABSOLUTE:300:U:U");
}
push(@args, "RRA:AVERAGE:0.99999:1:576"); # 48 hours at 5 minute resolution
push(@args, "RRA:AVERAGE:0.99999:12:168"); # 1 week at 1 hour resolution
push(@args, "RRA:AVERAGE:0.99999:48:180"); # 1 month at 4 hour resolution
push(@args, "RRA:AVERAGE:0.99999:288:366"); # 1 year at 1 day resolution
RRDs::create($rrdfile, "--start", $startts, @args);

File diff suppressed because it is too large Load Diff

View File

@ -153,14 +153,7 @@ AS-SET: <input type="text" name="asset" size="20" />
<?php endif; ?>
<div id="footer">
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
<?php if ($outispositive): ?>
Outbound traffic: positive / Inbound traffic: negative
<?php else: ?>
Inbound traffic: positive / Outbound traffic: negative
<?php endif; ?>
</div>
<?php include('footer.inc'); ?>
</body>
</html>

View File

@ -11,6 +11,7 @@ $knownlinksfile = "/data/knownlinks";
$outispositive = true;
$ntop = 20;
$showv6 = true;
$whois = "/usr/bin/whois";
$assetpath = "asset";

8
www/footer.inc Normal file
View File

@ -0,0 +1,8 @@
<div id="footer">
AS-Stats v1.40 written by Manuel Kasper, Monzoon Networks AG.<br/>
<?php if ($outispositive): ?>
Outbound traffic: positive / Inbound traffic: negative
<?php else: ?>
Inbound traffic: positive / Outbound traffic: negative
<?php endif; ?>
</div>

View File

@ -115,15 +115,22 @@ function getasstats_top($ntop) {
$as = $els[0];
$tot_in = 0;
$tot_out = 0;
$tot_v6_in = 0;
$tot_v6_out = 0;
for ($i = 1; $i < count($els); $i++) {
if (strpos($cols[$i], "_in") !== false)
if (strpos($cols[$i], "_in") !== false) {
$tot_in += $els[$i];
else
if (strpos($cols[$i], "_v6_") !== false)
$tot_v6_in += $els[$i];
} else {
$tot_out += $els[$i];
if (strpos($cols[$i], "_v6_") !== false)
$tot_v6_out += $els[$i];
}
}
$asstats[$as] = array($tot_in, $tot_out);
$asstats[$as] = array($tot_in, $tot_out, $tot_v6_in, $tot_v6_out);
if (count($asstats) >= $ntop)
break;

View File

@ -19,6 +19,9 @@ if (isset($_GET['width']))
$width = (int)$_GET['width'];
if (isset($_GET['height']))
$height = (int)$_GET['height'];
$v6_el = "";
if (@$_GET['v'] == 6)
$v6_el = "v6_";
$knownlinks = getknownlinks();
$rrdfile = getRRDFileForAS($as);
@ -27,6 +30,9 @@ $cmd = "$rrdtool graph - " .
"--slope-mode --alt-autoscale -u 0 -l 0 --imgformat=PNG --base=1000 --height=$height --width=$width " .
"--color BACK#ffffff00 --color SHADEA#ffffff00 --color SHADEB#ffffff00 ";
if (@$_GET['v'])
$cmd .= "--title IPv" . $_GET['v'] . " ";
if (isset($_GET['nolegend']))
$cmd .= "--no-legend ";
@ -38,18 +44,18 @@ if (isset($_GET['end']) && is_numeric($_GET['end']))
/* geneate RRD DEFs */
foreach ($knownlinks as $link) {
$cmd .= "DEF:{$link['tag']}_in=\"$rrdfile\":{$link['tag']}_in:AVERAGE ";
$cmd .= "DEF:{$link['tag']}_out=\"$rrdfile\":{$link['tag']}_out:AVERAGE ";
$cmd .= "DEF:{$link['tag']}_{$v6_el}in=\"$rrdfile\":{$link['tag']}_{$v6_el}in:AVERAGE ";
$cmd .= "DEF:{$link['tag']}_{$v6_el}out=\"$rrdfile\":{$link['tag']}_{$v6_el}out:AVERAGE ";
}
/* generate a CDEF for each DEF to multiply by 8 (bytes to bits), and reverse for outbound */
foreach ($knownlinks as $link) {
if ($outispositive) {
$cmd .= "CDEF:{$link['tag']}_in_bits={$link['tag']}_in,-8,* ";
$cmd .= "CDEF:{$link['tag']}_out_bits={$link['tag']}_out,8,* ";
$cmd .= "CDEF:{$link['tag']}_{$v6_el}in_bits={$link['tag']}_{$v6_el}in,-8,* ";
$cmd .= "CDEF:{$link['tag']}_{$v6_el}out_bits={$link['tag']}_{$v6_el}out,8,* ";
} else {
$cmd .= "CDEF:{$link['tag']}_in_bits={$link['tag']}_in,8,* ";
$cmd .= "CDEF:{$link['tag']}_out_bits={$link['tag']}_out,-8,* ";
$cmd .= "CDEF:{$link['tag']}_{$v6_el}in_bits={$link['tag']}_{$v6_el}in,8,* ";
$cmd .= "CDEF:{$link['tag']}_{$v6_el}out_bits={$link['tag']}_{$v6_el}out,-8,* ";
}
}
@ -60,7 +66,7 @@ foreach ($knownlinks as $link) {
$col = $link['color'] . "BB";
else
$col = $link['color'];
$cmd .= "AREA:{$link['tag']}_in_bits#{$col}:\"{$link['descr']}\"";
$cmd .= "AREA:{$link['tag']}_{$v6_el}in_bits#{$col}:\"{$link['descr']}\"";
if ($i > 0)
$cmd .= ":STACK";
$cmd .= " ";
@ -74,7 +80,7 @@ foreach ($knownlinks as $link) {
$col = $link['color'];
else
$col = $link['color'] . "BB";
$cmd .= "AREA:{$link['tag']}_out_bits#{$col}:";
$cmd .= "AREA:{$link['tag']}_{$v6_el}out_bits#{$col}:";
if ($i > 0)
$cmd .= ":STACK";
$cmd .= " ";

View File

@ -37,16 +37,36 @@ $rrdfile = getRRDFileForAS($as);
<p>No data found for AS <?php echo $as; ?></p>
<?php else: ?>
<div class="title">Daily</div>
<?php if ($showv6): ?>
<img class="detailgraph" src="gengraph.php?v=4&amp;as=<?php echo $as; ?>" alt="daily graph" />
<img class="detailgraph2" src="gengraph.php?v=6&amp;as=<?php echo $as; ?>" alt="daily graph" />
<?php else: ?>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>" alt="daily graph" />
<?php endif; ?>
<div class="title">Weekly</div>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 7*86400);?>&end=<?php echo time(); ?>" alt="weekly graph" />
<?php if ($showv6): ?>
<img class="detailgraph" src="gengraph.php?v=4&amp;as=<?php echo $as; ?>&amp;start=<?php echo (time() - 7*86400);?>&amp;end=<?php echo time(); ?>" alt="weekly graph" />
<img class="detailgraph2" src="gengraph.php?v=6&amp;as=<?php echo $as; ?>&amp;start=<?php echo (time() - 7*86400);?>&amp;end=<?php echo time(); ?>" alt="weekly graph" />
<?php else: ?>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&amp;start=<?php echo (time() - 7*86400);?>&amp;end=<?php echo time(); ?>" alt="weekly graph" />
<?php endif; ?>
<div class="title">Monthly</div>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 30*86400);?>&end=<?php echo time(); ?>" alt="monthly graph" />
<?php if ($showv6): ?>
<img class="detailgraph" src="gengraph.php?v=4&amp;as=<?php echo $as; ?>&amp;start=<?php echo (time() - 30*86400);?>&amp;end=<?php echo time(); ?>" alt="monthly graph" />
<img class="detailgraph2" src="gengraph.php?v=6&amp;as=<?php echo $as; ?>&amp;start=<?php echo (time() - 30*86400);?>&amp;end=<?php echo time(); ?>" alt="monthly graph" />
<?php else: ?>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&amp;start=<?php echo (time() - 30*86400);?>&amp;end=<?php echo time(); ?>" alt="monthly graph" />
<?php endif; ?>
<div class="title">Yearly</div>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 365*86400);?>&end=<?php echo time(); ?>" alt="yearly graph" />
<?php if ($showv6): ?>
<img class="detailgraph" src="gengraph.php?v=4&amp;as=<?php echo $as; ?>&amp;start=<?php echo (time() - 365*86400);?>&amp;end=<?php echo time(); ?>" alt="yearly graph" />
<img class="detailgraph2" src="gengraph.php?v=6&amp;as=<?php echo $as; ?>&amp;start=<?php echo (time() - 365*86400);?>&amp;end=<?php echo time(); ?>" alt="yearly graph" />
<?php else: ?>
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&amp;start=<?php echo (time() - 365*86400);?>&amp;end=<?php echo time(); ?>" alt="yearly graph" />
<?php endif; ?>
<?php endif; ?>
<?php else: ?>
@ -58,14 +78,7 @@ AS: <input type="text" name="as" size="6" />
</form>
<?php endif; ?>
<div id="footer">
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
<?php if ($outispositive): ?>
Outbound traffic: positive / Inbound traffic: negative
<?php else: ?>
Inbound traffic: positive / Outbound traffic: negative
<?php endif; ?>
</div>
<?php include('footer.inc'); ?>
</body>
</html>

View File

@ -14,6 +14,9 @@ $link = $_GET['link'];
if (!preg_match("/^[0-9a-zA-Z][0-9a-zA-Z\-]+$/", $link))
die("Invalid link");
if (@$_GET['v'] == 6)
$link .= "_v6";
/* first step: walk the data for all ASes to determine the top 5 for the given link */
$fd = fopen($daystatsfile, "r");
$cols = explode("\t", trim(fgets($fd)));
@ -68,6 +71,9 @@ $cmd = "$rrdtool graph - " .
"--slope-mode --alt-autoscale -u 0 -l 0 --imgformat=PNG --base=1000 --height=$height --width=$width " .
"--color BACK#ffffff00 --color SHADEA#ffffff00 --color SHADEB#ffffff00 ";
if (@$_GET['v'])
$cmd .= "--title IPv" . $_GET['v'] . " ";
/* geneate RRD DEFs */
foreach ($topas as $as => $traffic) {
$rrdfile = getRRDFileForAS($as);

View File

@ -37,21 +37,19 @@ $class = (($i % 2) == 0) ? "even" : "odd";
</div>
</th>
<td>
<?php if ($showv6): ?>
<img alt="link graph" src="linkgraph.php?link=<?php echo $link['tag']; ?>&amp;width=500&amp;height=300&amp;v=4" width="581" height="505" border="0" />
<img alt="link graph" src="linkgraph.php?link=<?php echo $link['tag']; ?>&amp;width=500&amp;height=300&amp;v=6" width="581" height="505" border="0" />
<?php else: ?>
<img alt="link graph" src="linkgraph.php?link=<?php echo $link['tag']; ?>&amp;width=500&amp;height=300" width="581" height="494" border="0" />
<?php endif; ?>
</td>
</tr>
<?php $i++; endforeach; ?>
</table>
<div id="footer">
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
<?php if ($outispositive): ?>
Outbound traffic: positive / Inbound traffic: negative
<?php else: ?>
Inbound traffic: positive / Outbound traffic: negative
<?php endif; ?>
</div>
<?php include('footer.inc'); ?>
</body>
</html>

View File

@ -30,6 +30,10 @@
font-size: 0.9em;
}
.vsmall {
font-size: 0.85em;
}
.rank {
font-size: 2em;
font-weight: bold;
@ -71,13 +75,17 @@ table.astable th {
width: 25em;
}
.detailgraph {
.detailgraph, .detailgraph2 {
border: 1px solid #aaa;
margin-bottom: 1.5em;
margin-top: 0.8em;
background-color: #eeeeee;
}
.detailgraph2 {
margin-left: 2em;
}
div#legend {
position: fixed;
right: 20px;

View File

@ -56,6 +56,10 @@ $class = (($i % 2) == 0) ? "even" : "odd";
</div>
<div class="small">~ <?php echo format_bytes($nbytes[0]); ?> in /
<?php echo format_bytes($nbytes[1]); ?> out in the last 24 hours</div>
<?php if ($showv6): ?>
<div class="vsmall">IPv6: ~ <?php echo format_bytes($nbytes[2]); ?> in /
<?php echo format_bytes($nbytes[3]); ?> out</div>
<?php endif; ?>
<?php if (!empty($customlinks)): ?>
<div class="customlinks">
@ -75,7 +79,12 @@ echo join(" | ", $htmllinks);
</div>
</th>
<td>
<a href="history.php?as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&width=500&height=150&nolegend=1" width="581" height="204" border="0" /></a>
<?php if ($showv6): ?>
<a href="history.php?v=4&amp;as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&amp;width=500&amp;height=150&amp;v=4&amp;nolegend=1" width="581" height="215" border="0" /></a>
<a href="history.php?v=6&amp;as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&amp;width=500&amp;height=150&amp;v=6&amp;nolegend=1" width="581" height="215" border="0" /></a>
<?php else: ?>
<a href="history.php?as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&amp;width=500&amp;height=150&amp;nolegend=1" width="581" height="204" border="0" /></a>
<?php endif; ?>
</td>
</tr>
<?php $i++; endforeach; ?>
@ -100,14 +109,7 @@ foreach ($knownlinks as $link) {
</table>
</div>
<div id="footer">
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
<?php if ($outispositive): ?>
Outbound traffic: positive / Inbound traffic: negative
<?php else: ?>
Inbound traffic: positive / Outbound traffic: negative
<?php endif; ?>
</div>
<?php include('footer.inc'); ?>
</body>
</html>