#!/usr/bin/perl # # loadnet - print network load (errors due to saturation). Solaris 8+. # # This Perl program uses the Sun::Solaris::Kstat library to fetch values. # # 24-Apr-2005, ver 0.81 (check for new versions, http://www.brendangregg.com) # # # USAGE: loadnet [-h] | [interval [count]] # loadnet # print a 1 second sample # loadnet -h # print help # loadnet 1 # print continually, every 1 second # loadnet 1 5 # print 5 times, every 1 second # # The load averages are based on the number of send and receive buffer # errors for all the network interfaces (generated when the interfaces # are running at saturation), averaged across the interval and divided # by a factor. A consistant load average of 1.00 would indicate there # was a moderate amount of saturation across the network interfaces # (usually this is bad). A load average of 8.00 would indicate heavy # saturation (due to heavy demand) on the network interfaces. # # A load of 0.00 indicates the interface is not saturated (still may be # utilised). # # The total number of network interfaces needs to be taken into acocunt. # A consistant load of 4.00 on a single interface server is probably a # problem, but on a server with eight interfaces it may be sporadic activity # spread across the interfaces (still possibly a problem). Further # investigation with netstat may be required. # # NOTE: If you have an unusual network interface, check it's instance name # is listed in this code (a few lines beneath this comment block). # # # SEE ALSO: kstat -n hme0 [interval [count]] # or qfe0, ... # netstat -iI hme0 [interval [count]] # nicstat [interval [count]] # % Utilisation # se netstat.se [interval] # SE Toolkit # se nx.se [interval] # SE Toolkit # # COPYRIGHT: Copyright (c) 2004 Brendan Gregg. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # (http://www.gnu.org/copyleft/gpl.html) # # Author: Brendan Gregg [Sydney, Australia] # # 22-Mar-2004 Brendan Gregg Created this. use Sun::Solaris::Kstat; my $Kstat = Sun::Solaris::Kstat->new(); # # Network card instance names # @Network = qw(be bge ce ci dmfe e1000g el eri elxl fa ge hme ipdptp iprb lane le nf ppp qe qfe rtls sppp vge); # # --- Process command line args --- # if ($ARGV[0] eq "-h" || $ARGV[0] eq "--help" || $ARGV[0] eq "0") { &usage(); } $sleep = $ARGV[0]; $loop = $ARGV[1]; if ($sleep eq "") { $sleep = 1; $loop = 1; } elsif ($loop eq "") { $loop = 2**32; } $PAGESIZE = 20; # max lines per header $lines = $PAGESIZE; # counter for lines printed $| = 1; $Network{$_} = 1 foreach (@Network); # # --- Main --- # while (1) { if ($lines++ >= $PAGESIZE) { $lines = 0; printf("%8s %6s %6s %6s %6s %6s %6s\n", "Net Time","1sec","5sec","15sec","1min","5min","15min"); } # # Store old and get new values # unshift(@Error,$error); unshift(@Update,$update); ($error,$update) = fetch(); # # Calculate load averages # $sec1 = ratio($error,$Error[0],$update,$Update[0]); $sec5 = ratio($error,$Error[4],$update,$Update[4]); $sec15 = ratio($error,$Error[14],$update,$Update[14]); $min1 = ratio($error,$Error[59],$update,$Update[59]); $min5 = ratio($error,$Error[299],$update,$Update[299]); $min15 = ratio($error,$Error[899],$update,$Update[899]); # # Print load averages # if ($sec1 ne "" && (($count % $sleep) == 0)) { @Time = localtime(); printf("%02d:%02d:%02d %6s %6s %6s %6s %6s %6s\n",$Time[2], $Time[1],$Time[0],$sec1,$sec5,$sec15,$min1,$min5,$min15); ### Check for end last if ++$printed == $loop; } $count++; ### Interval sleep (1); ### Memory cleanup pop(@Error) if $count > 901; pop(@Update) if $count > 901; } # # --- Subroutines --- # # fetch - fetch KStat values for the network interfaces. The values used # are defer, nocanput, norcvbuf and noxmtbuf. # sub fetch { my ($error,$time,$driver,$instance,$category); my (%Driver,%Instance,%Category); $error = 0; $Kstat->update(); foreach $driver (keys(%$Kstat)) { ### Check that this is a disk structure, next unless $Network{$driver}; $Driver = $Kstat->{$driver}; foreach $instance (keys(%$Driver)) { $Instance = $Driver->{$instance}; foreach $category (keys(%$Instance)) { $Category = $Instance->{$category}; if (defined $$Category{nocanput} || defined $$Category{norcvbuf}) { $error += $$Category{defer}; $error += $$Category{nocanput}; $error += $$Category{norcvbuf}; $error += $$Category{noxmtbuf}; # use the last wlastupdate value found, $time = $$Category{snaptime}; } } } } # # Divide errors by 200. This gives more sensible load averages, # such as 4.00 meaning heavily saturated rather than 800.00. # Future versions of this program may use a more elegant technique # rather than a factor of 200. # $error = $error / 200; return ($error,$time); } # ratio - calculate the ratio of the count delta over time delta; # given count and oldcount, time and oldtime. Returns a string # of the value, or a null string if not enough data was given. # sub ratio { my ($count,$oldcount,$time,$oldtime) = @_; return "" unless defined $oldtime; $countd = $count - $oldcount; $timed = $time - $oldtime; if ($timed > 0) { $ratio = $countd / $timed; } else { $ratio = 0; } return sprintf("%.2f",$ratio); } # usage - print usage and exit. # sub usage { print STDERR <