Nagios plugin: check_snmp_ifstatus.pl

While looking around for a nagios plugin to monitor the ethernet interfaces on my equipment, I just could not find one that did exactly what I wanted. So… I did exactly what OSS was designed for.  I took a plugin that had similar functionality as a starting point and re-wrote it to operate the way I needed. This is the result of my re-write of check_iftraffic.pl found on NagiosExchange.

“check_snmp_ifstatus.pl” will take a host IP address and interface name and return the current status of the interface. The returned data includes the UP/DOWN status, the interface line speed, and the current RX/TX bps. This status is returned as both an OK/Warning/Critical description and performance data usable with rrdtool. I have also created a pnp4nagios template for use with the plugin so that the perfdata can be easily viewed.

# check_snmp_ifstatus.pl -H 10.0.0.1 -i "Ethernet0/0"
OK: Ethernet0/0 is UP at 10Mbps. RX=72.27Kbps (0.72%), TX=4.094Kbps (0.04%) | RXbps=72271;8500000;9800000;0;10000000 TXbps=4094;8500000;9800000;0;10000000 RXpct=0.72%;85;98;0;100 TXpct=0.04%;85;98;0;100 elapsed=30s;3435;;;

# check_snmp_ifstatus.pl --help
Usage: check_snmp_ifstatus.pl -H hostaddress -i "if_description" [-b if_max_bps] [-C snmp_community] [-v 1|2] [-p snmp_port] [-w warn] [-c crit]
Options:
-H --host STRING or IPADDRESS
IP Address of host to check. Required.
-i --interface STRING
Full name of the interface to check. Required.
Examples would be eth0 or FastEthernet0/1
-C --community STRING
SNMP Community string. Optional. Defaults to 'public'
-v --version INTEGER
SNMP Version ( 1 or 2 ). Optional. Defaults to 1
-p --port INTEGER
SNMP port. Optional. Defaults to 161
-b --bandwidth INTEGER
Interface maximum speed in bits per second. Optional.
Use this to override the value returned by SNMP if it lies about
the max speed of the interface.
-w --warning INTEGER
% of bandwidth usage necessary to result in warning status. Optional.
Defaults to 85%
-c --critical INTEGER
% of bandwidth usage necessary to result in critical status. Optional.
Defaults to 98%

You can download the files referenced below from here… check_snmp_ifstatus.tar.gz

To install and use the plugin, first create a file called “check_snmp_ifstatus.pl” in your nagios/plugins directory with the following content…

#!/usr/bin/perl -w
##################################
#
# check_snmp_ifstatus.pl
#
# Based on check_iftraffic.pl
#
# Use SNMP to get the current UP/DOWN status, max bandwidth, and current
# bandwidth usage of a given interface. Uses a /tmp file to store the data
# from the last check in order to calculate usage stats.
#
# Note: 32bit counters are used. A Gigabit interface operating at full speed
# will cause a counter overflow in 34 seconds. Therefore it is
# recommended to use a polling rate of 30 seconds or less on
# GBit interfaces with heavy traffic to ensure accuracy. A 100Mb
# interface would take over 5 minutes to overflow the counter.
#
##################################
use strict;
use Net::SNMP;
use Getopt::Long;
&Getopt::Long::config('bundling');
use Data::Dumper;

my $host_address;
my $if_number;
my $if_descr;
my $if_speed = 0;
my $opt_h;
my $units;
my $max_value;
my $max_if_speed;
my $admin_status;
my $oper_status;
my $in_bytes;
my $out_bytes;

my $warn_pct = 85;
my $crit_pct = 98;

my $session;
my $error;
my $port = 161;
my $snmp_version = 1;
my $community = “public”;

my $update_time = time;
my $max_counter32 = 2 ** 32;

my @snmpoids;

# SNMP OIDs for network traffic
my $snmpIfDescr = ‘1.3.6.1.2.1.2.2.1.2’;
my $snmpIfSpeed = ‘1.3.6.1.2.1.2.2.1.5’;
my $snmpIfAdminStatus = ‘1.3.6.1.2.1.2.2.1.7’;
my $snmpIfOperStatus = ‘1.3.6.1.2.1.2.2.1.8’;
my $snmpIfInOctets = ‘1.3.6.1.2.1.2.2.1.10’;
my $snmpIfOutOctets = ‘1.3.6.1.2.1.2.2.1.16’;
my $response;

# Path to tmp files
my $TRAFFIC_FILE = “/tmp/iftraffic”;

my %STATUS_CODE =
( ‘OK’ => ‘0’, ‘WARNING’ => ‘1’, ‘CRITICAL’ => ‘2’, ‘UNKNOWN’ => ‘3’ );

my $status = GetOptions(
“h|help” => \$opt_h,
“C|community=s” => \$community,
“v|version=i” => \$snmp_version,
“w|warning=s” => \$warn_pct,
“c|critical=s” => \$crit_pct,
“b|bandwidth=i” => \$if_speed,
“p|port=i” => \$port,
“i|interface=s” => \$if_descr,
“H|hostname=s” => \$host_address
);

if ( ( $status == 0 ) or ( !$host_address ) or ( !$if_descr ) ) {
print_usage();
exit $STATUS_CODE{‘UNKNOWN’};
}

if ( $snmp_version =~ /[12]/ ) {
( $session, $error ) = Net::SNMP->session(
-hostname => $host_address,
-community => $community,
-port => $port,
-version => $snmp_version
);
if ( !defined($session) ) {
print(“UNKNOWN: $error”);
exit $STATUS_CODE{‘UNKNOWN’};
}
}
else {
print(“UNKNOWN: No support for SNMP v$snmp_version \n”);
exit $STATUS_CODE{‘UNKNOWN’};
}

$if_number = fetch_ifdescr( $session, $if_descr );

push( @snmpoids, $snmpIfSpeed . “.” . $if_number );
push( @snmpoids, $snmpIfAdminStatus . “.” . $if_number );
push( @snmpoids, $snmpIfOperStatus . “.” . $if_number );
push( @snmpoids, $snmpIfInOctets . “.” . $if_number );
push( @snmpoids, $snmpIfOutOctets . “.” . $if_number );

if ( !defined( $response = $session->get_request(@snmpoids) ) ) {
my $answer = $session->error;
$session->close;
print(“WARNING: SNMP error: $answer\n”);
exit $STATUS_CODE{‘WARNING’};
}

$max_if_speed = $response->{ $snmpIfSpeed . “.” . $if_number };
$admin_status = $response->{ $snmpIfAdminStatus . “.” . $if_number };
$oper_status = $response->{ $snmpIfOperStatus . “.” . $if_number };
$in_bytes = $response->{ $snmpIfInOctets . “.” . $if_number };
$out_bytes = $response->{ $snmpIfOutOctets . “.” . $if_number };

$session->close;

if ( $if_speed == 0 ) {
$if_speed = $max_if_speed;
}

my $row;
my $old_update_time = $update_time – 1;
my $old_in_bytes = $in_bytes;
my $old_out_bytes = $out_bytes;

if ( open( FILE, “<” . $TRAFFIC_FILE . “_if” . $if_number . “_” . $host_address ) ) {
while ( $row = ) {
chomp($row);
( $old_update_time, $old_in_bytes, $old_out_bytes ) = split( “:”, $row );
}
close(FILE);
}

open( FILE, “>” . $TRAFFIC_FILE . “_if” . $if_number . “_” . $host_address )
or die “\nCan’t open $TRAFFIC_FILE for writing: $!”;
printf FILE ( “%s:%.0lu:%.0lu\n”, $update_time, $in_bytes, $out_bytes );
close(FILE);

my $time_diff = $update_time – $old_update_time;
if ( $time_diff < 1 ) {
$time_diff = $update_time;
$old_in_bytes = 0;
x
$old_out_bytes = 0;
}

$in_bytes = adjust_overflow( $in_bytes, $old_in_bytes, $max_counter32 );
$out_bytes = adjust_overflow( $out_bytes, $old_out_bytes, $max_counter32 );

my $RXbps = int( ( ( $in_bytes – $old_in_bytes ) / $time_diff ) * 8 );
my $TXbps = int( ( ( $out_bytes – $old_out_bytes ) / $time_diff ) * 8 );

my $RXpct = int($RXbps / $if_speed * 10000) / 100;
my $TXpct = int($TXbps / $if_speed * 10000) / 100;

my $RXunits = convert_units($RXbps);
my $TXunits = convert_units($TXbps);
my $IFunits = convert_units($if_speed);

my $warn_bps = $if_speed * $warn_pct / 100;
my $crit_bps = $if_speed * $crit_pct / 100;

my $warn_overflow = int($max_counter32 / ( $if_speed / 8 ));

my $perfdata = “\|RXbps=$RXbps;$warn_bps;$crit_bps;0;$if_speed TXbps=$TXbps;$warn_bps;$crit_bps;0;$if_speed RXpct=$RXpct%;$warn_pct;$crit_pct;0;100 TXpct=$TXpct%;$warn_pct;$crit_pct;0;100 elapsed=$time_diff” . “s;$warn_overflow;;;”;

if ( $admin_status == 0 ) {
print(“CRITICAL: $if_descr is administratively DOWN” . $perfdata);
exit $STATUS_CODE{‘CRITICAL’};
}
elsif ( $oper_status == 0 ) {
print(“CRITICAL: $if_descr is physically DOWN” . $perfdata);
exit $STATUS_CODE{‘CRITICAL’};
}
elsif (( $RXbps >= $crit_bps ) or ( $TXbps >= $crit_bps ) ) {
print(“CRITICAL: $if_descr is UP at $IFunits. RX=$RXunits ($RXpct%), TX=$TXunits ($TXpct%)” . $perfdata);
exit $STATUS_CODE{‘CRITICAL’};
}
elsif (( $RXbps >= $warn_bps ) or ( $TXbps >= $warn_bps ) ) {
print(“WARNING: $if_descr is UP at $IFunits. RX=$RXunits ($RXpct%), TX=$TXunits ($TXpct%)” . $perfdata);
exit $STATUS_CODE{‘WARNING’};
}
elsif ( $time_diff >= $warn_overflow ) {
print(“WARNING: Sample Rate too slow. Possible counter overflows. $if_descr is UP at $IFunits. RX=$RXunits ($RXpct%), TX=$TXunits ($TXpct%)” . $perfdata);
exit $STATUS_CODE{‘WARNING’};
}
else {
print(“OK: $if_descr is UP at $IFunits. RX=$RXunits ($RXpct%), TX=$TXunits ($TXpct%)” . $perfdata);
exit $STATUS_CODE{‘OK’};
}

exit $STATUS_CODE{‘UNKNOWN’};

##################################
#
# Subroutines
#
##################################

sub print_usage {
print <EOU

Usage: check_snmp_ifstatus.pl -H hostaddress -i “if_description” [-b if_max_bps] [-C snmp_community] [-v 1|2] [-p snmp_port] [-w warn] [-c crit]

Options:
-H –host STRING or IPADDRESS
IP Address of host to check. Required.
-i –interface STRING
Full name of the interface to check. Required.
Examples would be eth0 or FastEthernet0/1
-C –community STRING
SNMP Community string. Optional. Defaults to ‘public’
-v –version INTEGER
SNMP Version ( 1 or 2 ). Optional. Defaults to 1
-p –port INTEGER
SNMP port. Optional. Defaults to 161
-b –bandwidth INTEGER
Interface maximum speed in bits per second. Optional.
Use this to override the value returned by SNMP if it lies about
the max speed of the interface.
-w –warning INTEGER
% of bandwidth usage necessary to result in warning status. Optional.
Defaults to $warn_pct%
-c –critical INTEGER
% of bandwidth usage necessary to result in critical status. Optional.
Defaults to $crit_pct%

EOU

exit( $STATUS_CODE{“UNKNOWN”} );
}

sub fetch_ifdescr {
my $state;
my $response;
my $snmpkey;
my $answer;
my $key;

my ( $session, $ifdescr ) = @_;

if ( !defined( $response = $session->get_table($snmpIfDescr) ) ) {
$answer = $session->error;
$session->close;
$state = ‘CRITICAL’;
$session->close;
exit $STATUS_CODE{$state};
}

foreach $key ( keys %{$response} ) {
if ( $response->{$key} =~ /^$ifdescr$/ ) {
$key =~ /.*\.(\d+)$/;
$snmpkey = $1;
}
}
unless ( defined $snmpkey ) {
$session->close;
$state = ‘CRITICAL’;
printf “$state: Could not match $ifdescr \n”;
exit $STATUS_CODE{$state};
}
return $snmpkey;
}

# Test and adjust for a 32 bit counter overflow
sub adjust_overflow {
my ( $test_num, $last_num, $max_counter ) = @_;
$test_num += $max_counter if ( $test_num < $last_num );
return $test_num;
}

# Convert bps to G/M/Kbps
sub convert_units {
my ( $base ) = @_;
my $unit = “bps”;
if ($base >= 1000) {
$base = $base / 1000;
$unit = “Kbps”
}
if ($base >= 1000) {
$base = $base / 1000;
$unit = “Mbps”
}
if ($base >= 1000) {
$base = $base / 1000;
$unit = “Gbps”
}
$base = sprintf( “%.4g”, $base) . $unit;
return $base;
}

Add a command to reference the plugin in your “/etc/nagios/commands.cfg” file, like so…

define command {
command_name check_snmp_ifstatus
command_line /usr/bin/perl $USER1$/contrib/check_snmp_ifstatus.pl -H $HOSTADDRESS$ -i $ARG1$ -w $ARG2$ -c $ARG3$ $ARG4$
}

Add a service entry for each host you want to check in your “/etc/nagios/services.cfg” file, like so…

define service{
use basic-service
check_command check_snmp_ifstatus!"Ethernet0/0"!85!98
service_description Network Status: e0/0
normal_check_interval 5
retry_check_interval 1
contact_groups netadmins
host_name cisco1
}
define service{
use basic-service
check_command check_snmp_ifstatus!"eth0"!50!90!-b 1000000000
service_description Network Status: eth0
normal_check_interval 1
retry_check_interval 1
contact_groups netadmins
host_name linux1,linux2
}

Now verify that you haven’t made any mistakes in the nagios configuration files…

# nagios -v nagios.cfg

And restart the nagios service if all looks well…

# /sbin/service nagios restart

You should now see new service entries for your hosts listing the current interface status.

If you use pnp4nagios to graph your nagios performance data, then the following template may be of use to you. Name it “check_snmp_ifstatus.php” and copy it to your pnp/templates directory…

< ?php
# Plugin: check_snmp_ifstatus.pl
#
$ds_name[1] = "Interface Traffic (bps)";
$opt[1] = "--vertical-label \"Traffic\" -b 1024 --title \"Interface Traffic ($hostname)\" ";
$def[1] = "DEF:var1=$rrdfile:$DS[1]:AVERAGE " ;
$def[1] .= "DEF:var2=$rrdfile:$DS[2]:AVERAGE " ;
$def[1] .= "LINE1:var1#003300:\"RX\" " ;
$def[1] .= "GPRINT:var1:LAST:\"%7.2lf %Sb/s last\" " ;
$def[1] .= "GPRINT:var1:AVERAGE:\"%7.2lf %Sb/s avg\" " ;
$def[1] .= "GPRINT:var1:MAX:\"%7.2lf %Sb/s max\\n\" " ;
$def[1] .= "LINE1:var2#00ff00:\"TX\" " ;
$def[1] .= "GPRINT:var2:LAST:\"%7.2lf %Sb/s last\" " ;
$def[1] .= "GPRINT:var2:AVERAGE:\"%7.2lf %Sb/s avg\" " ;
$def[1] .= "GPRINT:var2:MAX:\"%7.2lf %Sb/s max\" ";
$ds_name[2] = "Interface Utilization (%)";
$opt[2] = "--vertical-label \"Traffic %\" --title \"Interface Utilization % ($hostname)\" ";
$def[2] = "DEF:var1=$rrdfile:$DS[3]:AVERAGE " ;
$def[2] .= "DEF:var2=$rrdfile:$DS[4]:AVERAGE " ;
$def[2] .= "LINE1:var1#003300:\"RX\" " ;
$def[2] .= "GPRINT:var1:LAST:\"%7.2lf %% last\" " ;
$def[2] .= "GPRINT:var1:AVERAGE:\"%7.2lf %% avg\" " ;
$def[2] .= "GPRINT:var1:MAX:\"%7.2lf %% max\\n\" " ;
$def[2] .= "LINE1:var2#00ff00:\"TX\" " ;
$def[2] .= "GPRINT:var2:LAST:\"%7.2lf %% last\" " ;
$def[2] .= "GPRINT:var2:AVERAGE:\"%7.2lf %% avg\" " ;
$def[2] .= "GPRINT:var2:MAX:\"%7.2lf %% max\" ";

$ds_name[3] = “Sample Rate (seconds)”;
$opt[3] = “–vertical-label \”Seconds\” –title \”Sample rate ($hostname)\” “;
$def[3] = “DEF:var1=$rrdfile:$DS[5]:AVERAGE ” ;
$def[3] .= “LINE1:var1#003300:\”Sample Rate \” “;
$def[3] .= “GPRINT:var1:LAST:\”%6.2lf $UNIT[5] last \” ” ;
$def[3] .= “GPRINT:var1:MAX:\”%6.2lf $UNIT[5] max \” ” ;
$def[3] .= “GPRINT:var1:AVERAGE:\”%6.2lf $UNIT[51] avg \\n\” ” ;
$def[3] .= “LINE1:var1#000000:\”\” ” ;
if($WARN[5] != “”){
$def[3] .= “HRULE:”.$WARN[5].”#FFFF00:\”Warning Level “.$WARN[5].” seconds \” ” ;
}
if($CRIT[5] != “”){
$def[3] .= “HRULE:”.$CRIT[5].”#FF0000:\”Critical Level “.$CRIT[5].” seconds \” ” ;
}
?>

Once the plugin has run enough times to gather some data, you should see some graphs similar to these…

pnp4nagios graphs

I hope you find this as useful as I have. Please let me know if you use it, and if you find any problems with it.

You can download the files referenced above from here… check_snmp_ifstatus.tar.gz

27 Responses to “Nagios plugin: check_snmp_ifstatus.pl”

  1. dhaval thakar says:

    hi,

    i am unable to use this plugin for windows.

    i have used following iterface strings
    Intel(R) PRO/1000 MT Network Connection
    MS TCP Loopback interface
    Ethernet Adapter Local Area Connection:
    Ethernet Adapter Local Area Connection
    Local Area Connection:
    Local Area Connection

    kindly guide me

  2. Shawn Flynn says:

    That is because Microsoft, in their infinite wisdom, decided to not fully implement RFC1213-MIB. If you do an snmpwalk of OID ‘1.3.6.1.2.1.2.2.1’ you will notice that RFC1213-MIB::ifDescr is missing. You are left to guess which interface is which when browsing the snmp tree. This script only supports interface lookups via ifDescr, so that means it will not work for Microsoft machines. At some point in the future I may add an option to specify an interface by index number rather than description, which would allow it to work with broken snmp implementations like this.

  3. Rick Payton says:

    Aloha Shawn, I just came across your plugin today. Using Nagios 3.0.5, I’m unable to make this work. When I run the perl script from the command line, it works great – here’s the output to confirm it:

    root@cacti:/usr/local/nagios/libexec# /usr/bin/perl check_snmp_ifstatus.pl -H 192.168.10.1 -i internal
    OK: internal is UP at 104.9Mbps. RX=7.161Kbps (0%), TX=31Kbps (0.02%)|RXbps=7161;89128960;102760448;0;104857600 TXbps=30996;89128960;102760448;0;104857600 RXpct=0%;85;98;0;100 TXpct=0.02%;85;98;0;100 elapsed=6s;327;;;

    Now, when Nagios runs it, I get hard errors. I’ve verified the /usr/bin/perl path, but I can’t figure out why it’s not returning any data to Nagios.

    The service commands, I changed from basic-service to generic-service, as I couldn’t find a basic-service template anywhere.

    Any thoughts?

  4. Shawn Flynn says:

    Aloha Rick. If it is working from the command line but not from within nagios, then my guess would be either a permissions or a pathing problem. Verify the nagios user has execute permissions for perl and the script, and check the nagios logs for any errors that might give a clue to the failure.

    Note that in the command definition you need to specify not only the full path to the perl interpretor (/usr/bin/perl) but also the full path to the script ($USER1$/contrib/check_snmp_ifstatus.pl). Change the $USER1$/contrib portion to whatever is relevant for your installation.

    Don’t worry about the basic-service vs generic-service difference. It won’t make a difference. I just have a slightly modified generic-service template (different retry attempts) in my setup that I named basic-service.

  5. Rick Payton says:

    I just relooked at it, and indeed it was the $USER1$/contrib path that tripped me up.

    Now that I’ve corrected that, eth0 on localhost reads fine, but my other 2 Linux VM’s still wont respond (going to have to take another look and re-verify snmp is enabled on them), and my router returns a new error code:

    (Return code of 13 is out of bounds)

    Here’s my command, and service definitions calling your script:

    # ‘check_snmp_ifstatus’ command definition
    define command{
    command_name check_snmp_ifstatus
    command_line /usr/bin/perl $USER1$/check_snmp_ifstatus.pl -H $HOSTADDRESS$ -i $ARG1$ -w $ARG2$ -c $ARG3$ $ARG4$
    }

    # Monitor bandwidth via SNMP & pnp4nagios

    define service{
    use generic-service,srv-pnp
    check_command check_snmp_ifstatus!”internal”!85!98
    service_description Network Status: internal
    normal_check_interval 5
    retry_check_interval 1
    #contact_groups netadmins
    process_perf_data 1
    host_name ft60
    }

    define service{
    use generic-service,srv-pnp
    check_command check_snmp_ifstatus!”eth0″!50!90!-b 1000000000
    service_description Network Status: eth0
    normal_check_interval 1
    retry_check_interval 1
    #contact_groups netadmins
    process_perf_data 1
    host_name localhost,mai-crm,mai-wiki
    }

    Thoughts?

    I’m actually pretty new at using Nagios, so please bear with me. Mahalo for your time!

  6. Shawn Flynn says:

    I usually see a (Return code of 13 is out of bounds) error when I have no connectivity to the device I’m trying to probe. Check that your nagios machine can do an snmpwalk of oid .1.3.6.1.2.1.2.2.1 on your router.

  7. Rick Payton says:

    Yes, it can, here partial output:


    root@cacti:~# snmpwalk -v 2c -c public 192.168.10.1 .1.3.6.1.2.1.2.2.1
    IF-MIB::ifIndex.1 = INTEGER: 1
    IF-MIB::ifIndex.2 = INTEGER: 2
    IF-MIB::ifIndex.3 = INTEGER: 3
    IF-MIB::ifIndex.4 = INTEGER: 4
    IF-MIB::ifIndex.5 = INTEGER: 5
    IF-MIB::ifIndex.6 = INTEGER: 6
    IF-MIB::ifIndex.7 = INTEGER: 7
    IF-MIB::ifDescr.1 = STRING: internal
    IF-MIB::ifDescr.2 = STRING: dmz
    IF-MIB::ifDescr.3 = STRING: wan1
    IF-MIB::ifDescr.4 = STRING: wan2
    IF-MIB::ifDescr.5 = STRING: modem
    IF-MIB::ifDescr.6 = STRING: ssl.root
    IF-MIB::ifDescr.7 = STRING: rickhome
    IF-MIB::ifType.1 = INTEGER: ethernetCsmacd(6)
    IF-MIB::ifType.2 = INTEGER: ethernetCsmacd(6)
    IF-MIB::ifType.3 = INTEGER: ethernetCsmacd(6)
    IF-MIB::ifType.4 = INTEGER: ethernetCsmacd(6)
    IF-MIB::ifType.5 = INTEGER: ethernetCsmacd(6)
    IF-MIB::ifType.6 = INTEGER: tunnel(131)
    IF-MIB::ifType.7 = INTEGER: tunnel(131)
    IF-MIB::ifMtu.1 = INTEGER: 1500
    IF-MIB::ifMtu.2 = INTEGER: 1500
    IF-MIB::ifMtu.3 = INTEGER: 1500
    IF-MIB::ifMtu.4 = INTEGER: 1500
    IF-MIB::ifMtu.5 = INTEGER: 1500
    IF-MIB::ifMtu.6 = INTEGER: 1500
    IF-MIB::ifMtu.7 = INTEGER: 1500
    IF-MIB::ifSpeed.1 = Gauge32: 104857600
    IF-MIB::ifSpeed.2 = Gauge32: 10485760
    IF-MIB::ifSpeed.3 = Gauge32: 10485760
    IF-MIB::ifSpeed.4 = Gauge32: 104857600
    IF-MIB::ifSpeed.5 = Gauge32: 0
    IF-MIB::ifSpeed.6 = Gauge32: 0
    IF-MIB::ifSpeed.7 = Gauge32: 10485760
    IF-MIB::ifPhysAddress.1 = STRING: 0:9:f:10:15:b4
    IF-MIB::ifPhysAddress.2 = STRING: 0:9:f:10:15:b5
    IF-MIB::ifPhysAddress.3 = STRING: 0:9:f:10:15:b6
    IF-MIB::ifPhysAddress.4 = STRING: 0:9:f:10:15:b7
    IF-MIB::ifPhysAddress.5 = STRING: 0:0:0:0:0:0
    IF-MIB::ifPhysAddress.6 = STRING:
    IF-MIB::ifPhysAddress.7 = STRING:
    IF-MIB::ifAdminStatus.1 = INTEGER: up(1)
    IF-MIB::ifAdminStatus.2 = INTEGER: down(2)
    IF-MIB::ifAdminStatus.3 = INTEGER: up(1)
    IF-MIB::ifAdminStatus.4 = INTEGER: up(1)
    IF-MIB::ifAdminStatus.5 = INTEGER: down(2)
    IF-MIB::ifAdminStatus.6 = INTEGER: up(1)
    IF-MIB::ifAdminStatus.7 = INTEGER: down(2)
    IF-MIB::ifOperStatus.1 = INTEGER: up(1)
    IF-MIB::ifOperStatus.2 = INTEGER: down(2)
    IF-MIB::ifOperStatus.3 = INTEGER: up(1)
    IF-MIB::ifOperStatus.4 = INTEGER: up(1)
    IF-MIB::ifOperStatus.5 = INTEGER: down(2)
    IF-MIB::ifOperStatus.6 = INTEGER: up(1)
    IF-MIB::ifOperStatus.7 = INTEGER: down(2)

    I really appreciate you taking the time with this. Mahalo!

  8. Rick Payton says:

    Ahhhh I just found it (well why the router won’t work). Seems I had a permissions problem with the nagios user writing to /tmp. I chowned the iftraffic_* to nagios.nagios, and now it’s graphing.

    Now, for the remote Linux systems. a snmpwalk doesn’t show any devices named eth0, which is probably why they’re “failing” in Nagios.

    Does snmp watch eth0 on remote systems?

  9. Userx says:

    The script work in Cisco Catalyst 2950, but don’t work in Cisco Catalyst 2960 and Cisco Catalyst 3750. The error is:
    ./check_snmp_ifstatus.pl -H -C -i “FastEthernet0/1”
    WARNING: SNMP error: Received noSuchName(2) error-status at error-index 6

    IfDescr OID are IfDescr.10001 to IfDescr.10048 for FastEthernet and IfDescr.10101 to IfDescr.10102 for GigabitEthernet.

  10. Jens Mickerts says:

    Hi Shawn,

    first of all, thank you very much for this very nice plugin. I have a small issue with it when I try to check GBit Interfaces on a Cisco 3750 Switch with it. I receive “WARNING: Sample Rate too slow. Possible counter overflows” as output. The plugin seems to want a sample rate of 34 seconds to work properly, but while this would be possible to achieve changing the default interval to less than 60 seconds, this seems a bit like overkill to me and it makes it hardly possible to graph a larger amount of interfaces. Do you have an other idea what I could do to solve this?

    Many thanks in advance and have a Merry Christmas.

    Regards,

    Jens

  11. Shawn Flynn says:

    Jens,
    The plugin only checks the 32bit snmp counter on the interface of the device, so on a gigabit interface at full speed, this counter will overflow within 34 seconds. On a 10G interface, you only get 3.4 seconds. The only option is to modify the code to check the 64bit counters if they are available for your device. I never bothered to add the code to do this since none of the devices I am checking have 64bit counters available.

  12. Mike says:

    Thank you for this plug-in!

  13. Mike says:

    I have the same problem as Jens Mickerts. When you where saying that we should change the code to check for 64 bit counters, you where referring to this variable: my $max_counter32 = 2 ** 32. I have changed this to $max_counter32 = 2 ** 64 but now the there is no RRD database so the graphics are not drawn.

  14. Shawn Flynn says:

    Mike: No. I meant that you would need to find an snmp oid on your device that returns the number of in/out bytes using a COUNTER64. The plugin currently uses “my $snmpIfInOctets = ‘1.3.6.1.2.1.2.2.1.10’;” and “my $snmpIfOutOctets = ‘1.3.6.1.2.1.2.2.1.16’;” which are COUNTER32 oids. Not all devices support COUNTER64 (none of mine do) so you’ll have to do some research to see what your device supports. Doing an snmpwalk of the device, you are looking for something like “IF-MIB::ifHCInOctets.138 = Counter64:xxxxx” which I pulled from a cisco 5510 at oid .1.3.6.1.2.1.31.1.1.1.6. Once you have the oids of the 64bit counters on your device, it should be fairly simple to rewrite the plugin to make use of them.

  15. Pavel says:

    Hi, Shawn!
    Thanks for nice plugins!
    I have a cisco 3750 with 1Gbit interface.
    I found COUNTER64
    ifHCInOctets = 1.3.6.1.2.1.31.1.1.1.6
    ifHCOutOctets = 1.3.6.1.2.1.31.1.1.1.10

    And i rewrite it in check_snmp_ifstatus.pl
    #my $snmpIfInOctets = ‘1.3.6.1.2.1.2.2.1.10’;
    #my $snmpIfOutOctets = ‘1.3.6.1.2.1.2.2.1.16’;
    #3750 – COUNTER64
    my $snmpIfInOctets = ‘1.3.6.1.2.1.31.1.1.1.6’;
    my $snmpIfOutOctets = ‘1.3.6.1.2.1.31.1.1.1.10’;

    But i recieve:
    ./check_snmp_ifstatus.pl -H x.x.x.x -i GigabitEthernet0/0 -C public -v 2
    CRITICAL: GigabitEthernet0/0 is UP at 1Gbps. RX=136.3Gbps (13625.49%), TX=128.4Gbps (12843.96%)
    |RXbps=136254930734;850000000;980000000;0;1000000000 TXbps=128439642483;850000000;980000000;0;1000000000
    RXpct=13625.49%;85;98;0;100 TXpct=12843.96%;85;98;0;100 elapsed=

    Whats wrong? Thank you!

    Informations from MIB:
    MIB IF-MIB
    Name ifHCInOctets
    iso.org.dod.internet.mgmt.mib-2.ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifHCInOctets
    OID 1.3.6.1.2.1.31.1.1.1.6
    Type Counter64
    Units
    Access read-only
    Status unknown
    The total number of octets received on the interface ,
    including framing characters. This object is a 64-bit
    version of ifInOctets.
    Discontinuities in the value of this counter can occur
    at re-initialization of the management system , and at
    other times as indicated by the value of
    ifCounterDiscontinuityTime.

    and
    MIB IF-MIB
    Name ifHCOutOctets
    iso.org.dod.internet.mgmt.mib-2.ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifHCOutOctets
    OID 1.3.6.1.2.1.31.1.1.1.10
    Type Counter64
    Units
    Access read-only
    Status unknown
    The total number of octets transmitted out of the
    interface , including framing characters. This object
    is a 64-bit version of ifOutOctets.
    Discontinuities in the value of this counter can occur
    at re-initialization of the management system , and at
    other times as indicated by the value of
    ifCounterDiscontinuityTime.

  16. Shawn Flynn says:

    Pavel: It looks like you didn’t update the ‘$max_counter32’ variable to reflect the change to 64 bit counters. Try changing the line that reads..
    my $max_counter32 = 2 ** 32;
    to…
    my $max_counter32 = 2 ** 64;

    I’m not sure if that’s the only change, as I don’t have any device to test it on. If I ever do get access to a device with HC counters on it, I fully intend to re-write this plugin to support it.

  17. Dan Kane says:

    props. and thanks for the script. i will do some researching for the 64bit oid’s.

    shoot me an email if you want to improve on this script. i may be able to provide access to some hardware.

  18. John Smith says:

    Many thanks for the plugin and assistance provided here.
    I have the plugin output to Nagios however I would like to graph this. I have installed pnp4nagios and the php template but I am not sure of the entries to be entered into Nagios to gather this data and display. I would be grateful for any assistance.

  19. Marco says:

    Is there an other way to prevent this message ?

    WARNING: Sample Rate too slow. Possible counter overflows. bge0 is UP at 1Gbps. RX=2.486Mbps (0.24%), TX=211.6Kbps (0.02%)

    I want to monitor a mOnOwall with this script but it has no counter64 values.

    thanx

  20. zimo says:

    Hi Shawn, thank you for the script, it’s work perfectly.

    I have only one question: if i do an snmpwalk IdDescr of a windows server (2003 SP2) i have an output back:

    root@server:~# snmpwalk -v 1 -c public 192.168.0.201 1.3.6.1.2.1.2.2.1
    IF-MIB::ifIndex.1 = INTEGER: 1
    IF-MIB::ifIndex.65539 = INTEGER: 65539
    IF-MIB::ifDescr.1 = STRING: MS TCP Loopback interface
    IF-MIB::ifDescr.65539 = STRING: Broadcom NetXtreme Gigabit Ethernet

    So i belive that i could execute the script over the server if i put the string “Broadcom NetXtreme Gigabit Ethernet” in the script… but…
    it’s don’t work again
    🙁

    @Marco
    The only thing that you can doing it’s put nagios check interval period to 30 seconds max.

  21. muellmaen says:

    great script, could be the thing I need …

    I just tried to get it working with an Netgear GS108T Switch, but I found out that this “switch” does not provide a ifDescr field. In one of the first mails you offered that you might rewrite your script .. Any news on that yet ?

  22. Shawn Flynn says:

    I’m glad you are finding the script useful. I’m quite surprised at the number of people that are using it. As for your question of news… you’ll be happy to know that I did indeed rewrite the script to clean up a few bugs and add the ability to pass an ifIndex number for the interface. I’ll do a bit of cleanup on the code, then make a new posting within the week. Stay tuned.

  23. Mark Taffar says:

    Thanks for the plugin here, works great after changing the max_counter to 64.

    FYI, there’s a typo in the PHP code, should be a 5 and not 51 on this line:

    $def[3] .= “GPRINT:var1:AVERAGE:\”%6.2lf $UNIT[51] avg \\n\” ” ;

  24. Shawn Flynn says:

    An updated version of this plugin has been uploaded. Check it out here… http://shawnflynn.com/2010/07/01/nagios-plugin-check_snmp_ifstatuspl-redux/

  25. Joe Gzesh says:

    Shawn,

    I took your wonderful perl script check_snmp_ifstatus and modified it to do some extra tricks with my minimal programming skills.

    1. It now can check the inverse of a port. This is handy on a switch that is not fully utilized. It will notify the admin if a port comes up and how much bandwidth is being used for it.

    2. It now checks the host to see if it is available. If not it returns a critical code and says host is down rather then null or unknown status.

    3. I also cleaned up the handeling of the 64 bit code. not sure if i wrote the line for writing to the file properly since the way you had it was not working with 64 bit.

    I would like to send you the code so you can look at it and possibly post it since i belive in the spirit of the gpl.

    Thank you and cheers.

  26. Hello. Thank for sharing this, I wanted for something like this in nagios and I didn’t find it.

    I just have to add something.

    I modified the file check_snmp_ifstatus.php a bit.

    I change this line:

    $def[3] .= “GPRINT:var1:AVERAGE:\”%6.2lf $UNIT[51] avg \\n\” ” ;

    For this one:

    $def[3] .= “GPRINT:var1:AVERAGE:\”%6.2lf $UNIT[5] avg \\n\” ” ;

    I’m not a php programmer, I just used my logic and I have got this plugin working. I just want to post this because it would be useful for someone else.

    Thanks you very much again and I’m sorry for my English :).

  27. Klaus says:

    Hi! I added 2 new features: ignore interface status and use absolute thresholds. Feel free to add it to your plugin. The diff is at: http://pastebin.com/hK5VtKqX

Leave a Reply

You must be logged in to post a comment.