Section D.3. A Network Statistics Utility


D.3. A Network Statistics Utility

#!/usr/bin/perl -w # # nicstat - print network traffic, Kb/s read and written. #           Solaris 8+, Perl (Sun::Solaris::Kstat). # # "netstat -i" only gives a packet count, this program gives Kbytes. # # 23-Jan-2006, ver 0.98 # # USAGE:    nicstat [-hsz] [-i int[,int...]] | [interval [count]] #           -h              # help #           -s              # print summary output #           -z              # skip zero lines #           -i int[,int...] # print these instances only #   eg, #           nicstat         # print summary since boot #           nicstat 1       # print continually, every 1 second #           nicstat 1 5     # print 5 times, every 1 second #           nicstat -i hme0 # only examine hme0 # # This prints out the Kb/s transferred for all the network cards (NICs), # including packet counts and average sizes. The first line is the summary # data since boot. # # FIELDS: #           Int         Interface #           rKb/s       read Kbytes/s #           wKb/s       write Kbytes/s #           rPk/s       read Packets/s #           wPk/s       write Packets/s #           rAvs        read Average size, bytes #           wAvs        write Average size, bytes #           %Util       %Utilisation (r+w/ifspeed) #           Sat         Saturation (defer, nocanput, norecvbuf, noxmtbuf) # # Author: Brendan Gregg  [Sydney, Australia] # use strict; use Getopt::Std; use Sun::Solaris::Kstat; my $Kstat = Sun::Solaris::Kstat->new(); # #  Process command line args # usage() if defined $ARGV[0] and $ARGV[0] eq "--help"; getopts('hi:sz') or usage(); usage() if defined $main::opt_h; my $STYLE  = defined $main::opt_s ? $main::opt_s : 0; my $SKIPZERO  = defined $main::opt_z ? $main::opt_z : 0; # process [interval [count]], my ($interval, $loop_max); if (defined $ARGV[0]) {     $interval = $ARGV[0];     $loop_max = defined $ARGV[1] ? $ARGV[1] : 2**32;     usage() if $interval == 0; } else {     $interval = 1;     $loop_max = 1; } # check for -i, my %NetworkOnly;             # network interfaces to print my $NETWORKONLY = 0;         # match on network interfaces if (defined $main::opt_i) {     foreach my $net (split /,/, $main::opt_i) {         $NetworkOnly{$net} = 1;     }     $NETWORKONLY = 1; } # globals, my $loop = 0;                # current loop number my $PAGESIZE = 20;           # max lines per header my $line = $PAGESIZE;        # counter for lines printed my %NetworkNames;            # Kstat network interfaces my %NetworkData;             # network interface data my %NetworkDataOld;          # network interface data $main::opt_h = 0; $| = 1;                      # autoflush ### Determine network interfaces unless (find_nets()) {     if ($NETWORKONLY) {         print STDERR "ERROR1: $main::opt_i matched no network interfaces.\n";     }     else {         print STDERR "ERROR1: No network interfaces found!\n";     }     exit 1; } # #  Main # while (1) {     ### Print Header     if ($line >= $PAGESIZE) {         if ($STYLE == 0) {             printf "%8s %5s %7s %7s %7s %7s %7s %7s %7s %7s\n",                    "Time", "Int", "rKb/s", "wKb/s", "rPk/s", "wPk/s", "rAvs",                    "wAvs", "%Util", "Sat";         }         elsif ($STYLE == 1) {             printf "%8s %8s %14s %14s\n", "Time", "Int", "rKb/s", "wKb/s";         }         $line = 0;     }     ### Get new data     my (@NetworkData) = fetch_net_data();     foreach my $network_data (@NetworkData) {         ### Extract values         my ($int, $rbytes, $wbytes, $rpackets, $wpackets, $speed, $sat, $time)             = split /:/, $network_data;         ### Retrieve old values         my ($old_rbytes, $old_wbytes, $old_rpackets, $old_wpackets, $old_sat,             $old_time);         if (defined $NetworkDataOld{$int}) {             ($old_rbytes, $old_wbytes, $old_rpackets, $old_wpackets,              $old_sat, $old_time) = split /:/, $NetworkDataOld{$int};         }         else {             $old_rbytes = $old_wbytes = $old_rpackets = $old_wpackets                 = $old_sat = $old_time = 0;         }         #         #  Calculate statistics         #         # delta time         my $tdiff = $time - $old_time;         # per second values         my $rbps = ($rbytes - $old_rbytes) / $tdiff;         my $wbps = ($wbytes - $old_wbytes) / $tdiff;         my $rkps = $rbps / 1024;         my $wkps = $wbps / 1024;         my $rpps = ($rpackets - $old_rpackets) / $tdiff;         my $wpps = ($wpackets - $old_wpackets) / $tdiff;         my $ravs = $rpps > 0 ? $rbps / $rpps : 0;         my $wavs = $wpps > 0 ? $wbps / $wpps : 0;         # skip zero lines if asked         next if $SKIPZERO and ($rbps + $wbps) == 0;         # % utilisation         my $util;         if ($speed > 0) {             # the following has a mysterious "800", it is 100             # for the % conversion, and 8 for bytes2bits.             $util = ($rbps + $wbps) * 800 / $speed;             $util = 100 if $util > 100;         }         else {             $util = 0;         }         # saturation per sec         my $sats = ($sat - $old_sat) / $tdiff;         #         #  Print statistics         #         if ($rbps ne "") {             my @Time = localtime();             if ($STYLE == 0) {                 printf "%02d:%02d:%02d %5s " .                        "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",                        $Time[2], $Time[1], $Time[0], $int, $rkps, $wkps,                        $rpps, $wpps, $ravs, $wavs, $util, $sats;             }             elsif ($STYLE == 1) {                 printf "%02d:%02d:%02d %8s %14.3f %14.3f\n",                        $Time[2], $Time[1], $Time[0], $int, $rkps, $wkps;             }             $line++;             # for multiple interfaces, always print the header             $line += $PAGESIZE if @NetworkData > 1;         }         ### Store old values         $NetworkDataOld{$int}             = "$rbytes:$wbytes:$rpackets:$wpackets:$sat:$time";     }     ### Check for end     last if ++$loop == $loop_max;     ### Interval     sleep $interval; } # find_nets - walk Kstat to discover network interfaces. # # This walks %Kstat and populates a %NetworkNames with discovered # network interfaces. # sub find_nets {     my $found = 0;     ### Loop over all Kstat modules     foreach my $module (keys %$Kstat) {         my $Modules = $Kstat->{$module};         foreach my $instance (keys %$Modules) {             my $Instances = $Modules->{$instance};             foreach my $name (keys %$Instances) {                 ### Skip interface if asked                 if ($NETWORKONLY) {                     next unless $NetworkOnly{$name};                 }                 my $Names = $Instances->{$name};                 # Check this is a network device.                 # Matching on ifspeed has been more reliable than "class"                 if (defined $$Names{ifspeed} and $$Names{ifspeed}) {                     ### Save network interface                     $NetworkNames{$name} = $Names;                     $found++;                 }             }         }     }     return $found; } # fetch - fetch Kstat data for the network interfaces. # # This uses the interfaces in %NetworkNames and returns useful Kstat data. # The Kstat values used are rbytes64, obytes64, ipackets64, opackets64 # (or the 32 bit versions if the 64 bit values are not there). # sub fetch_net_data {     my ($rbytes, $wbytes, $rpackets, $wpackets, $speed, $time);     my @NetworkData = ();     $Kstat->update();     ### Loop over previously found network interfaces     foreach my $name (keys %NetworkNames) {         my $Names = $NetworkNames{$name};         if (defined $$Names{obytes} or defined $$Names{obytes64}) {             ### Fetch write bytes             if (defined $$Names{obytes64}) {                 $rbytes = $$Names{rbytes64};                 $wbytes = $$Names{obytes64};             }             else {                 $rbytes = $$Names{rbytes};                 $wbytes = $$Names{obytes};             }             ### Fetch read bytes             if (defined $$Names{opackets64}) {                 $rpackets = $$Names{ipackets64};                 $wpackets = $$Names{opackets64};             }             else {                 $rpackets = $$Names{ipackets};                 $wpackets = $$Names{opackets};             }             ### Fetch interface speed             if (defined $$Names{ifspeed}) {                 $speed = $$Names{ifspeed};             }             else {                 # if we can't fetch the speed, print the                 # %Util as 0.0 . To do this we,                 $speed = 2 ** 48;             }             ### Determine saturation value             my $sat = 0;             if (defined $$Names{nocanput} or defined $$Names{norcvbuf}) {                 $sat += defined $$Names{defer} ? $$Names{defer} : 0;                 $sat += defined $$Names{nocanput} ? $$Names{nocanput} : 0;                 $sat += defined $$Names{norcvbuf} ? $$Names{norcvbuf} : 0;                 $sat += defined $$Names{noxmtbuf} ? $$Names{noxmtbuf} : 0;             }             ### use the last snaptime value,             $time = $$Names{snaptime};             ### store data             push @NetworkData, "$name:$rbytes:$wbytes:" .              "$rpackets:$wpackets:$speed:$sat:$time";         }     }     return @NetworkData; } # usage - print usage and exit. # sub usage {         print STDERR <<END; USAGE: nicstat [-hsz] [-i int[,int...]] | [interval [count]]    eg, nicstat               # print summary since boot        nicstat 1             # print continually every 1 second        nicstat 1 5           # print 5 times, every 1 second        nicstat -s            # summary output        nicstat -i hme0       # print hme0 only END         exit 1; } 





Solaris Performance and Tools(c) Dtrace and Mdb Techniques for Solaris 10 and Opensolaris
Solaris Performance and Tools: DTrace and MDB Techniques for Solaris 10 and OpenSolaris
ISBN: 0131568191
EAN: 2147483647
Year: 2007
Pages: 180

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net