diff --git a/README.md b/README.md index 04ee96c..a2f1e5c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ Prerequisites - File::Find::Rule module (CPAN) - if using sFlow: the Net::sFlow module (CPAN) - web server with PHP 5 +- php-sqlite3 +- libdbd-sqlite3-perl - one or more routers than can generate NetFlow v8/v9 AS aggregation records or sFlow samples diff --git a/bin/rrd-extractstats.pl b/bin/rrd-extractstats.pl index 4cf278f..f134269 100755 --- a/bin/rrd-extractstats.pl +++ b/bin/rrd-extractstats.pl @@ -30,7 +30,7 @@ read_knownlinks(); my @links = values %knownlinks; # walk through all RRD files in the given path and extract stats for all links -# from them; write the stats to a text file, sorted by total traffic +# from them; write the stats to an sqlite database my @rrdfiles = File::Find::Rule->maxdepth(2)->file->in($rrdpath); @@ -51,45 +51,34 @@ foreach my $rrdfile (@rrdfiles) { } print "\n"; -# now sort the keys in order of descending total traffic -my @asorder = sort { - my $total_a = 0; - - foreach my $t (values %{$astraffic->{$a}}) { - $total_a += $t; - } - my $total_b = 0; - foreach my $t (values %{$astraffic->{$b}}) { - $total_b += $t; - } - return $total_b <=> $total_a; -} keys %$astraffic; - -open(STATSFILE, ">$statsfile.tmp"); - -# print header line -print STATSFILE "as"; +my $query = 'create table stats(asn int'; foreach my $link (@links) { - print STATSFILE "\t${link}_in\t${link}_out\t${link}_v6_in\t${link}_v6_out"; + $query .= ", ${link}_in int, ${link}_out int, ${link}_v6_in int, ${link}_v6_out int"; } -print STATSFILE "\n"; +$query .= ');'; + +use DBI; +my $db = DBI->connect("dbi:SQLite:dbname=$statsfile.tmp", '', ''); +$db->do('PRAGMA synchronous = OFF'); +$db->do('drop table if exists stats'); +$db->do($query); # print data -foreach my $as (@asorder) { - print STATSFILE "$as"; +foreach my $as (keys %{ $astraffic }) { + + $query = "insert into stats values('$as'"; foreach my $link (@links) { - 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"}); + $query .= ", '" . undefaszero($astraffic->{$as}->{"${link}_in"}) . "'"; + $query .= ", '" . undefaszero($astraffic->{$as}->{"${link}_out"}) . "'"; + $query .= ", '" . undefaszero($astraffic->{$as}->{"${link}_v6_in"}) . "'"; + $query .= ", '" . undefaszero($astraffic->{$as}->{"${link}_v6_out"}) . "'"; } - - print STATSFILE "\n"; + $query .= ');'; + $db->do($query); } -close(STATSFILE); - +$db->disconnect(); rename("$statsfile.tmp", $statsfile); sub undefaszero { diff --git a/www/config.inc b/www/config.inc index 4889397..ecb423d 100644 --- a/www/config.inc +++ b/www/config.inc @@ -17,7 +17,6 @@ $show95th = true; $ntop = 20; $showv6 = true; $showtitledetail = true; -$hidelinkusagename = true; # $showtitledetail will need to be true to allow this $vertical_label = true; # vertical IN/OUT label in graph $brighten_negative = true; # brighten the "negative" part of graphs diff --git a/www/config_defaults.inc b/www/config_defaults.inc index 26c6919..835faa7 100644 --- a/www/config_defaults.inc +++ b/www/config_defaults.inc @@ -10,10 +10,6 @@ $default_graph_height = 360; $top_graph_width = 600; $top_graph_height = 220; -/* Size of graphs on link usage page */ -$linkusage_graph_width = 600; -$linkusage_graph_height = 480; - /* Size of graphs on AS-Set page */ $asset_graph_width = 600; $asset_graph_height = 200; diff --git a/www/func.inc b/www/func.inc index b7890bf..4cbcd93 100644 --- a/www/func.inc +++ b/www/func.inc @@ -95,49 +95,52 @@ function getknownlinks() { return $knownlinks; } -function getasstats_top($ntop, $statfile) { - /* first step: walk the data for all ASes to determine the top 5 for the given link */ - $fd = fopen($statfile, "r"); - if (!$fd) +function getasstats_top($ntop, $statfile, $selected_links) { + try{ + $db = new SQLite3($statfile); + }catch(Exception $e){ return array(); - $cols = explode("\t", trim(fgets($fd))); - - /* read in up to $ntop AS stats, sum up columns */ - while (!feof($fd)) { - $line = trim(fgets($fd)); - if (!$line) - continue; - - $els = explode("\t", $line); - - /* first element is the AS */ - $as = $els[0]; + } + + if(sizeof($selected_links) == 0){ + $selected_links = array(); + foreach(getknownlinks() as $link) + $selected_links[] = $link['tag']; + } + + $nlinks = 0; + $query_total = '0'; + $query_links = ''; + foreach($selected_links as $tag){ + $query_links .= "${tag}_in, ${tag}_out, ${tag}_v6_in, ${tag}_v6_out, "; + $nlinks += 4; + $query_total .= " + ${tag}_in + ${tag}_out + ${tag}_v6_in + ${tag}_v6_out"; + } + $query = "select asn, $query_links $query_total as total from stats order by total desc limit $ntop"; + + $asn = $db->query($query); + $asstats = array(); + while($row = $asn->fetchArray()){ $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], "_v6_") !== false) - $tot_v6_in += $els[$i]; + foreach($row as $key => $value){ + if (strpos($key, '_in') !== false) { + if (strpos($key, '_v6_') !== false) + $tot_v6_in += $value; else - $tot_in += $els[$i]; - } else { - if (strpos($cols[$i], "_v6_") !== false) - $tot_v6_out += $els[$i]; + $tot_in += $value; + } else if (strpos($key, '_out') !== false) { + if (strpos($key, '_v6_') !== false) + $tot_v6_out += $value; else - $tot_out += $els[$i]; + $tot_out += $value; } } - - $asstats[$as] = array($tot_in, $tot_out, $tot_v6_in, $tot_v6_out); - - if (count($asstats) >= $ntop) - break; + + $asstats[$row['asn']] = array($tot_in, $tot_out, $tot_v6_in, $tot_v6_out); } - fclose($fd); - return $asstats; } @@ -224,14 +227,14 @@ function clearCacheFileASSET($asset) { } # return the html used in top.php : -function getHTMLUrl($as, $ipversion, $desc, $start, $end, $peerusage){ - $img = getHTMLImg($as, $ipversion, $desc, $start, $end, $peerusage, '', '', false); +function getHTMLUrl($as, $ipversion, $desc, $start, $end, $peerusage, $selected_links = array()){ + $img = getHTMLImg($as, $ipversion, $desc, $start, $end, $peerusage, '', '', false, $selected_links); $result = "$img"; return($result); } # return the html used in history.php (for example) : -function getHTMLImg($as, $ipversion, $desc, $start, $end, $peerusage, $alt, $class, $history = false){ +function getHTMLImg($as, $ipversion, $desc, $start, $end, $peerusage, $alt, $class, $history = false, $selected_links=array()){ global $top_graph_width; global $top_graph_height; @@ -240,6 +243,14 @@ function getHTMLImg($as, $ipversion, $desc, $start, $end, $peerusage, $alt, $cla $result = "$alt $link['color'], 'descr' => $link['descr']); + + $links = array(); + foreach(explode(',', $_GET['selected_links']) as $tag){ + $link = array('tag' => $tag, + 'color' => $reverse[$tag]['color'], + 'descr' => $reverse[$tag]['descr']); + $links[] = $link; + } + + $knownlinks = $links; +} + $rrdfile = getRRDFileForAS($as, $peerusage); if ($compat_rrdtool12) { diff --git a/www/headermenu.inc b/www/headermenu.inc index 0cebc10..58cd040 100644 --- a/www/headermenu.inc +++ b/www/headermenu.inc @@ -17,14 +17,6 @@ if($showpeeras == true){ endif; } -echo "Link usage: "; -foreach ($top_intervals as $interval) { - echo '' . $interval['label'] . ' | '; -} - if ($dpagename == "history"): ?>View an AS | for Monzoon Networks AG - */ - -require_once('func.inc'); - -$numtop = 10; -$ascolors = array("A6CEE3", "1F78B4", "B2DF8A", "33A02C", "FB9A99", "E31A1C", "FDBF6F", "FF7F00", "CAB2D6", "6A3D9A"); - -$link = $_GET['link']; -if (!preg_match("/^[0-9a-zA-Z][0-9a-zA-Z\-_]+$/", $link)) - die("Invalid link"); - -if (@$_GET['v'] == 6) - $link .= "_v6"; - -$hours = 24; -if (@$_GET['numhours']) - $hours = (int)$_GET['numhours']; - -/* first step: walk the data for all ASes to determine the top 5 for the given link */ -$statsfile = statsFileForHours($hours); -$fd = fopen($statsfile, "r"); -$cols = explode("\t", trim(fgets($fd))); -$asstats = array(); - -/* figure out which columns contain data for the links were's interested in */ -$incol = array_search("{$link}_in", $cols); -$outcol = array_search("{$link}_out", $cols); -if (!$incol || !$outcol) - die("Couldn't find columns"); - -/* read in all AS stats */ -while (!feof($fd)) { - $line = trim(fgets($fd)); - if (!$line) - continue; - - $els = explode("\t", $line); - - /* first element is the AS */ - $asstats[$els[0]] = $els[$incol] + $els[$outcol]; -} -fclose($fd); - -/* now sort the AS stats to find the top $numtop */ -arsort($asstats, SORT_NUMERIC); - -/* extract first $numtop and consolidate the rest */ -$topas = array_slice($asstats, 0, $numtop, true); - -for ($i = 0; $i < $numtop; $i++) - array_shift($asstats); - -$restdata = 0; -foreach ($asstats as $as => $totaldata) { - $restdata += $totaldata; -} - -/* now make a beautiful graph :) */ -header("Content-Type: image/png"); - -$width = $default_graph_width; -$height = $default_graph_height; -if (@$_GET['width']) - $width = (int)$_GET['width']; -if (@$_GET['height']) - $height = (int)$_GET['height']; - -$knownlinks = getknownlinks(); - -if ($compat_rrdtool12) { - /* cannot use full-size-mode - must estimate height/width */ - $height -= 205; - $width -= 81; -} - -$start = time() - $hours*3600; -$end = time(); - -$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 " . - "--start " . $start . " --end " . $end . " "; - -if (!$compat_rrdtool12) - $cmd .= "--full-size-mode "; - -if($showtitledetail && @$_GET['dname'] != "") - $cmd .= "--title " . escapeshellarg($_GET['dname']) . " "; -else - if (isset($_GET['v']) && is_numeric($_GET['v'])) - $cmd .= "--title IPv" . $_GET['v'] . " "; - -/* geneate RRD DEFs */ -foreach ($topas as $as => $traffic) { - $rrdfile = getRRDFileForAS($as); - $cmd .= "DEF:as{$as}_in=\"$rrdfile\":{$link}_in:AVERAGE "; - $cmd .= "DEF:as{$as}_out=\"$rrdfile\":{$link}_out:AVERAGE "; -} - -/* generate a CDEF for each DEF to multiply by 8 (bytes to bits), and reverse for outbound */ -foreach ($topas as $as => $traffic) { - if ($outispositive) { - $cmd .= "CDEF:as{$as}_in_bits=as{$as}_in,-8,* "; - $cmd .= "CDEF:as{$as}_out_bits=as{$as}_out,8,* "; - } else { - $cmd .= "CDEF:as{$as}_in_bits=as{$as}_in,8,* "; - $cmd .= "CDEF:as{$as}_out_bits=as{$as}_out,-8,* "; - } -} - -/* generate graph area/stack for inbound */ -$i = 0; -foreach ($topas as $as => $traffic) { - $asinfo = getASInfo($as); - $descr = str_replace(":", "\\:", utf8_decode($asinfo['descr'])); - - $cmd .= "AREA:as{$as}_in_bits#{$ascolors[$i]}:\"AS{$as} ({$descr})\\n\""; - if ($i > 0) - $cmd .= ":STACK"; - $cmd .= " "; - $i++; -} - -/* generate graph area/stack for outbound */ -$i = 0; -foreach ($topas as $as => $traffic) { - $cmd .= "AREA:as{$as}_out_bits#{$ascolors[$i]}:"; - if ($i > 0) - $cmd .= ":STACK"; - $cmd .= " "; - $i++; -} - -# zero line -$cmd .= "HRULE:0#00000080"; - -passthru($cmd); - -exit; - -?> diff --git a/www/linkusage.php b/www/linkusage.php deleted file mode 100644 index e19487e..0000000 --- a/www/linkusage.php +++ /dev/null @@ -1,63 +0,0 @@ - for Monzoon Networks AG - */ - -require_once('func.inc'); - -$knownlinks = getknownlinks(); - -$hours = 24; -if (@$_GET['numhours']) - $hours = (int)$_GET['numhours']; - -$label = statsLabelForHours($hours); - -?> - - - - - - Link usage (<?php echo $label ?>) - - - - - - -
Link usage - top 10 AS per link ()
- - - - - - - - - - - - -
-
- -
-
- - link graph" width="" height="" border="0" /> - link graph" width="" height="" border="0" /> - - link graph" width="" height="" border="0" /> - -
- - - - - diff --git a/www/top.php b/www/top.php index cd702ef..9269495 100644 --- a/www/top.php +++ b/www/top.php @@ -25,7 +25,15 @@ else { $statsfile = statsFileForHours($hours); } $label = statsLabelForHours($hours); -$topas = getasstats_top($ntop, $statsfile); + +$knownlinks = getknownlinks(); +$selected_links = array(); +foreach($knownlinks as $link){ + if(isset($_GET["link_${link['tag']}"])) + $selected_links[] = $link['tag']; +} + +$topas = getasstats_top($ntop, $statsfile, $selected_links); $start = time() - $hours*3600; $end = time(); @@ -98,9 +106,9 @@ echo join(" | ", $htmllinks); @@ -109,11 +117,20 @@ echo join(" | ", $htmllinks);
+
+ + \n"; + echo "\n"; } ?>
"; + $tag = "link_${link['tag']}"; + + echo "
"; echo ""; if ($brighten_negative) { @@ -124,10 +141,12 @@ foreach ($knownlinks as $link) { } echo "
"; - echo "
 " . $link['descr'] . "
+
+