#!/usr/bin/perl -w # # GEL2-SW8 Switch Stats 0.1 - switch_stats.pl [2010-01-16] # Copyright (C) 2010 Damian Pasternok # This code is free software under the GPLv3+. # For more information see . # # Requirements: RRDtool 1.3.x; Perl: Math::Round, RRDs # configuration $ipaddr="192.168.1.210"; # switch IP address $graphname="switch_stats"; # name of graph $tmpfile="/tmp/$graphname.tmp"; # temporary file that stores previous values read over SNMP $workdir="/var/www/switch_stats"; # work directory in which all data could be stored $graphdir="$workdir/img"; # chart images dir $rrddir="$workdir/rrd"; # rrd database dir $devname="Repotec RP-G0802L"; # switch description # port descriptions, e.g. device names @portdesc = ("port 1", "port 2", "port 2", "port 3", "port 3", "port 6", "port 7", "port 8"); # code - do not change anything below here use Math::Round; use RRDs; # get snmp values and return them as an array sub get_snmp { my $inout_traffic = `snmpwalk -v 1 -c public $ipaddr IF-MIB::ifInOctets | awk '{ print \$4 }'`; $inout_traffic .= `snmpwalk -v 1 -c public $ipaddr IF-MIB::ifOutOctets | awk '{ print \$4 }'`; return split(" ", $inout_traffic); } # write array of values into tmpfile as a single string separated by comas sub update_tmp { open TMPFILE, ">", $tmpfile or die $!; print TMPFILE join(",", @_); close TMPFILE; } # compare snmp values with old from tmpfile; update tmpfile; return the difference between them sub get_values { my @inout_traffic = &get_snmp; if(! -e $tmpfile) { &update_tmp(@inout_traffic); } open TMPFILE, "<", $tmpfile or die $!; my @old_inout_traffic = split(",", ); close TMPFILE; &update_tmp(@inout_traffic); my @data; for(my $i = 0; $i < @inout_traffic; $i++) { # if device was reseted count from 0 if($inout_traffic[$i] < $old_inout_traffic[$i]) { # outgoing traffic has negative values if($i >= @inout_traffic / 2) { # convert bytes into bits and divide by interval push(@data, -$inout_traffic[$i] * 8 / $_[0]); } else { push(@data, $inout_traffic[$i] * 8 / $_[0]); } } else { if($i >= @inout_traffic / 2) { push(@data, round(-($inout_traffic[$i] - $old_inout_traffic[$i]) * 8 / $_[0])); } else { push(@data, round(($inout_traffic[$i] - $old_inout_traffic[$i]) * 8 / $_[0])); } } } return @data; } # create new rrd database if doesn't exist sub create_rrd { if(! -e "$rrddir/$graphname.rrd") { if(! -e $rrddir) { mkdir $rrddir; } RRDs::create "$rrddir/$graphname.rrd", "-s $_[0]", "DS:in_port1:GAUGE:600:-28000000:28000000", "DS:in_port2:GAUGE:600:-28000000:28000000", "DS:in_port3:GAUGE:600:-28000000:28000000", "DS:in_port4:GAUGE:600:-28000000:28000000", "DS:in_port5:GAUGE:600:-28000000:28000000", "DS:in_port6:GAUGE:600:-28000000:28000000", "DS:in_port7:GAUGE:600:-28000000:28000000", "DS:in_port8:GAUGE:600:-28000000:28000000", "DS:out_port1:GAUGE:600:-28000000:28000000", "DS:out_port2:GAUGE:600:-28000000:28000000", "DS:out_port3:GAUGE:600:-28000000:28000000", "DS:out_port4:GAUGE:600:-28000000:28000000", "DS:out_port5:GAUGE:600:-28000000:28000000", "DS:out_port6:GAUGE:600:-28000000:28000000", "DS:out_port7:GAUGE:600:-28000000:28000000", "DS:out_port8:GAUGE:600:-28000000:28000000", "RRA:AVERAGE:0.5:1:576", "RRA:AVERAGE:0.5:6:672", "RRA:AVERAGE:0.5:24:732", "RRA:AVERAGE:0.5:144:1460"; if ($ERROR = RRDs::error) { print "$graphname: unable to generate graph: $ERROR\n"; } } } # update rrd database sub update_rrd { for (my $i = 0; $i < @portdesc; $i++) { print "$portdesc[$i]\r\t\tRX: $_[$i]\r\t\t\t\t\tTX: $_[$i+8]\n"; } RRDs::update "$rrddir/$graphname.rrd", "-t", "in_port1:in_port2:in_port3:in_port4:in_port5:in_port6:in_port7:in_port8:out_port1:out_port2:out_port3:out_port4:out_port5:out_port6:out_port7:out_port8", "N:$_[0]:$_[1]:$_[2]:$_[3]:$_[4]:$_[5]:$_[6]:$_[7]:$_[8]:$_[9]:$_[10]:$_[11]:$_[12]:$_[13]:$_[14]:$_[15]"; if ($ERROR = RRDs::error) { print "$graphname: unable to generate graph: $ERROR\n"; } } # create png graph sub create_graph { if(! -e $graphdir) { mkdir $graphdir; } RRDs::graph "$graphdir/$graphname-$_[0].png", "-z", "-s -1$_[0]", "-t $devname Switch Traffic (+ RX - TX)", "-h", "136", "-w", "517", "-a", "PNG", "-v bits per second", "-c", "BACK#000000", "-c", "CANVAS#000000", "-c", "FONT#f0f0f0", "-n", "DEFAULT:0:glispbold", "DEF:in_port1=$rrddir/$graphname.rrd:in_port1:AVERAGE", "DEF:in_port2=$rrddir/$graphname.rrd:in_port2:AVERAGE", "DEF:in_port3=$rrddir/$graphname.rrd:in_port3:AVERAGE", "DEF:in_port4=$rrddir/$graphname.rrd:in_port4:AVERAGE", "DEF:in_port5=$rrddir/$graphname.rrd:in_port5:AVERAGE", "DEF:in_port6=$rrddir/$graphname.rrd:in_port6:AVERAGE", "DEF:in_port7=$rrddir/$graphname.rrd:in_port7:AVERAGE", "DEF:in_port8=$rrddir/$graphname.rrd:in_port8:AVERAGE", "DEF:out_port1=$rrddir/$graphname.rrd:out_port1:AVERAGE", "DEF:out_port2=$rrddir/$graphname.rrd:out_port2:AVERAGE", "DEF:out_port3=$rrddir/$graphname.rrd:out_port3:AVERAGE", "DEF:out_port4=$rrddir/$graphname.rrd:out_port4:AVERAGE", "DEF:out_port5=$rrddir/$graphname.rrd:out_port5:AVERAGE", "DEF:out_port6=$rrddir/$graphname.rrd:out_port6:AVERAGE", "DEF:out_port7=$rrddir/$graphname.rrd:out_port7:AVERAGE", "DEF:out_port8=$rrddir/$graphname.rrd:out_port8:AVERAGE", "AREA:in_port1#f0f0f0:$_[1]", "AREA:in_port2#a0f0f0:$_[2]:STACK", "AREA:in_port3#00d0f0:$_[3]:STACK", "AREA:in_port4#00a0f0:$_[4]:STACK", "AREA:in_port5#0070f0:$_[5]:STACK", "AREA:in_port6#0040f0:$_[6]:STACK", "AREA:in_port7#0010f0:$_[7]:STACK", "AREA:in_port8#0000c0:$_[8]:STACK", "AREA:out_port1#f0f0f0", "AREA:out_port2#a0f0f0::STACK", "AREA:out_port3#00d0f0::STACK", "AREA:out_port4#00a0f0::STACK", "AREA:out_port5#0070f0::STACK", "AREA:out_port6#0040f0::STACK", "AREA:out_port7#0010f0::STACK", "AREA:out_port8#0000c0::STACK"; if ($ERROR = RRDs::error) { print "$graphname: unable to generate graph: $ERROR\n"; } } &create_rrd(300); &update_rrd(get_values(300)); &create_graph("day", @portdesc); &create_graph("week", @portdesc); &create_graph("month", @portdesc); &create_graph("year", @portdesc);