Thursday, March 5, 2015

Nagios Check Bandwidth on Router Interface

Nagios Check Bandwidth on Router Interface


When you are using Nagios monitoring, Sometime you might also want to monitoring bandwidth on your router interface. 

And here is the HowTo:

1. Download the perl script (check_bw_router_intf.pl)
2. Create a contacts 
3. Create contactgroup
4. Create template
5. Add the command into your Nagios
6. Add the Router Interface that you want to monitor

Let Start .....

1. Download the perl script check_bw_router_intf.pl
You can this script with the below this article (Red high light content)
and put into the Nagios plugin directory:
In this example,   /usr/lib64/nagios/plugins/ 

2. Create a contacts 
vi /etc/nagios/contact.cfg

define contact {
        contact_name                    checkbw-email
        alias                                   NOC Email
        contactgroups                   checkbw
        service_notification_period     24x7
        host_notification_period        24x7
        service_notification_options    w,c,r
        host_notification_options       d,r
        service_notification_commands   notify-by-email
        host_notification_commands      host-notify-by-email
        email                           noc@company-name.cm
        }

3. Create contactgroup
vi /etc/nagios/contactgroup.cfg

define contactgroup{
        contactgroup_name       checkbw
        alias                               NOC Email BW
        }

4. Create template 
vi /etc/template.cfg

define host{
        name                    basic-host-router
        use                       generic-host
        check_command           check-host-alive
        check_period            24x7
        max_check_attempts      5
        notification_interval   20
        notification_period     24x7
        notification_options    d,r
        contact_groups          checkbw
        register                0
        }

define service{
        use                     generic-service
        name                    basic-port-router
        is_volatile             0
        check_period            24x7
        max_check_attempts      5
        normal_check_interval   5
        retry_check_interval    1
        notification_interval   20
        notification_period     24x7
        notification_options    w,u,c,r
        contact_groups          checkbw
        register                0
        }

5. Add the command into your Nagios

define command{
        command_name    check_bw_router_intf
        command_line    /usr/lib64/nagios/plugins/check_bw_router_intf.pl -H $HOSTADDRESS$ -C $ARG1$ -i $ARG2$ -b $ARG3$ -B -I $ARG4$ -O $ARG5$ -u m -w $ARG6$ -c $ARG7$
        }

We run it manually to check if it work or not by:

/usr/lib64/nagios/plugins/check_bw_router_intf.pl -H r-01-pnh-noc1 -C C0MmunityString -i GigabitEthernet0/0/1.101" -b 500 -B -I 500 -O 500 -u m -w 90 -c 95

Type this command all in one line, In this example will check on Banwidth on Router interface 0/0/1.101 with the bandwidth 500 MB for in and out. and it will be warning when it reach 90% and Critical at 95%. 

6. Add the Router Interface that you want to monitor

define host{
        use                   basic-host-router
        host_name       r-01-pnh-noc1
        address            123.123.123.123
        hostgroups       router-pnh
        parents             s-01-pnh-noc1
}

define service{
    use                                 basic-port-router
    host_name                   r-01-pnh-noc1
   service_description    Bandwidth Interface GigabitEthernet0/0/1.101
   check_command         check_bw_router_intf!C0MmunityString!GigabitEthernet0/0/1.101!500!500!500!90!95
        }


Download the perl script check_bw_router_intf.pl (Red Hight Light)

#!/usr/bin/perl -w
#
# check_iftraffic.pl - Nagios(r) network traffic monitor plugin
# Copyright (C) 2004 Gerd Mueller / Netways GmbH
# $Id: check_iftraffic.pl 1119 2006-02-09 10:30:09Z gmueller $
# Version: .73
#
# mw = Markus Werner mw+nagios@wobcom.de
# Remarks (mw):
#
#       I adopted as much as possible the programming style of the origin code.
#
#       There should be a function to exit this program,
#       instead of calling print and exit statements all over the place.
#
# minor changes by mw
#       The snmp if_counters on net devices can have overflows.
#       I wrote this code to address this situation.
#       It has no automatic detection and which point the overflow
#       occurs but it will generate a warning state and you
#       can set the max value by calling this script with an additional
#       arg.
#
# minor cosmetic changes by mw
#       Sorry but I couldn't sustain to clean up some things.
#
# gj = Greg Frater gregATfraterfactory.com
# Remarks (gj):
# minor (gj):
#
#       * fixed the performance data, formating was not to spec
#       * Added a check of the interfaces status (up/down).
#         If interface is down the check returns a critical status.
#       * Support both textual or the numeric index values.
#       * If the interface speed is not specified on the command line
#         it gets it automatically from IfHighSpeed (or ifSpeed if IfHighSpeed
#         counter is not available)
#       * Added option to specify a second Speed parameter to allow for
#         asymetrcal links such as a DSL line or cable modem where the
#         download and upload speeds are different
#       * Added -B option to display results in bits/sec instead of Bytes/sec
#       * Added the current usage in Bytes/s (or bit/s) to the perfdata output
#       * Added ability for plugin to determine interface to query by matching IP
#         address of host with entry in ipAdEntIfIndex (.1.3.6.1.2.1.4.20.1.2)
#       * Added -L flag to list entries found in the ipAdEntIfIndex table
#         Otherwise, it works as before.
#       * resorted options in help
#       * Added auto detection mode (now the default), tries 64 bit counters first then uses 32
#         bit if 64 bit values are not available
#       * Added force flag to force 64 or 32 bit only mode (disables auto detection)
#       * Reworked the status output, tried to make it a little more readable
#       * Cleaned up logic of Units designator inside script
#       * Added checks for bad interface speed values (zero, error, etc.)
#       * 12_09_2014 Fixed unit label issue (thanks Gerhard Mourani for catching it)
#       * 12_09_2014 Changed labels from index -> interface on output when interface is not up
#       * 12_09_2014 Removed spurious '
' from output
#       * 12_09_2014 Changed the $suffix from 'Bs' or 'bs' to 'B' or 'b'
#       * 12_10_2014 Fixed issue when using string description for interface printing extra line with
#       * interface name and OID
#
# based on check_traffic from Adrian Wieczorek,
#
# Send us bug reports, questions and comments about this plugin.
# Latest version of this software: http://www.nagiosexchange.org
#
#
# 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

# Set Perl environ
use strict;
use Data::Dumper;
use Net::SNMP;
use Getopt::Long;
&Getopt::Long::config('bundling');
#use Data::Dumper;

# Set script parameters
my $error;
my $host_address;
my $host_ip;
my $iface_descr;
my $iface_number;
my $iface_speed;
my $iface_speedOut;
my $ifspeed64;
my $ifspeed32;
my $inbytes64;
my $inbytes32;
my $outbytes64;
my $outbytes32;
my $in_ave      = 0;
my $in_tot      = 0;
my $index_list;
my $max_value; #added 20050614 by mw
my $max_bytes;
my $opt_h;
my $out_ave     = 0;
my $port        = 161;
my $out_tot     = 0;
my $response;
my $session;
my @snmpoids;
my $units;

# SNMP OIDs for Traffic
my $snmpIfOperStatus    = '1.3.6.1.2.1.2.2.1.8';        # Operational state of interface (i.e. 1-up, 2-down, etc.)
my $snmpIfInOctets32    = '1.3.6.1.2.1.2.2.1.10';       # Total Octets entering interface (in) - 32 bit counter
my $snmpIfOutOctets32   = '1.3.6.1.2.1.2.2.1.16';       # Total Octets leaving interface (out) - 32 bit counter
my $snmpIfInOctets      = '1.3.6.1.2.1.31.1.1.1.6';     # Total Octets entering interface (in) - 64 bit counter
my $snmpIfOutOctets     = '1.3.6.1.2.1.31.1.1.1.10';    # Total Octets leaving interface (out) - 64 bit counter
my $snmpIfDescr         = '1.3.6.1.2.1.2.2.1.2';        # Textual string describing interface
my $snmpIfSpeed32       = '1.3.6.1.2.1.2.2.1.5';        # bits per second
my $snmpIfSpeed         = '1.3.6.1.2.1.31.1.1.1.15';    # Mbits per second
my $snmpIPAdEntIfIndex  = '1.3.6.1.2.1.4.20.1.2';       # Index of interface using hosts IP addr


# Path to  tmp files
my $TRAFFIC_FILE = "/usr/local/nagios/libexec/traffic/";

# Create tmp file location if it does not exist
if ( ! -d $TRAFFIC_FILE ) {
        mkdir $TRAFFIC_FILE;
}

# changes sos 20090717 UNKNOWN must be 3
# Set status codes
my %STATUS_CODE =
  ( 'UNKNOWN' => '3', 'OK' => '0', 'WARNING' => '1', 'CRITICAL' => '2' );

#default values;
my $bits        = undef;
my $COMMUNITY   = "public";
my $crit_usage  = 98;
my $debug       = 0;
my $force       = undef;
my $if_status   = '4';
my ( $in_bytes, $out_bytes, $in_bytes32, $out_bytes32 ) = 0;
my $label       = "";
my $output      = "";
my $snmp_version = 2;
my $state       = "UNKNOWN";
my $suffix      = "B";
my $thirtytwo   = undef;
my $use_reg     =  undef;  # Use Regexp for name
my $warn_usage  = 85;


#cosmetic changes 20050614 by mw, see old versions for detail
# Added options for bits and second max ifspeed 20100202 by gj
# Added options for specific IP addr to match 20100405 by gj
my $status = GetOptions(
        "h|help"        => \$opt_h,
        'B'             => \$bits,
        'bits'          => \$bits,
        "C|community=s" => \$COMMUNITY,
        "w|warning=s"   => \$warn_usage,
        "c|critical=s"  => \$crit_usage,
        "b|bandwidth|I|inBandwidth=i" => \$iface_speed,
        "O|outBandwidth=i" => \$iface_speedOut,
        'f|force'       => \$force, #added 20130429 by gjf
        'r'             => \$use_reg,
        'noregexp'      => \$use_reg,
        "p|port=i"      => \$port,
        "u|units=s"     => \$units,
        "i|interface=s" => \$iface_descr,
        "A|address=s"   => \$host_ip,
        "H|hostname=s"  => \$host_address,
        'L'             => \$index_list,
        "d|debug=i"     => \$debug,
        'list'          => \$index_list,
        "v|Version=s"   => \$snmp_version,
        "M|max=i"       => \$max_value, #added 20050614 by mw
        "32|32bit"      => \$thirtytwo #added 20101104 by gjf
);

# Print help if no options given
if ( $status == 0 ) {
        print_help();
        exit $STATUS_CODE{'OK'};
}

debugout ("DEBUG ENABLED at level: $debug", "1");
debugout ("INTERFACE DESCR: $iface_descr", "2"), if ( defined($iface_descr) );

# Changed 20091214 gj
# Check for missing options
if ( !$host_address )  {
        print  "\nMissing host address!\n\n";
        stop(print_usage(),"OK");
} elsif ( ( $iface_speed ) and ( !$units ) ){
        print "\nMissing units!\n\n";
        stop(print_usage(),"OK");
} elsif ( ( $units ) and ( ( !$iface_speed ) and  ( !$iface_speedOut ) ) ) {
        print "\nMissing (-I or -O) interface maximum speed!\n\n";
        stop(print_usage(),"OK");
} elsif ( ( $iface_speedOut ) and ( !$units ) ) {
        print "\nMissing units (-u) for Out maximum speed!\n\n";
        stop(print_usage(),"OK");
} elsif ( ( $max_value ) and ( !$units ) ) {
        print "\nMissing units (-u) for maximum counter!\n\n";
        stop(print_usage(),"OK");
}

# Set default units if undefined
if ( !defined($units) ){
        #bits
        $units = "b";
}

# Switch output from Bytes to bits if necessary
if ($bits) {
        $suffix = "b"
}

#if ( !$iface_speed ) {
        # Do nothing
#} else {
if ( $iface_speed ) {
        #change 20050414 by mw
        # Added iface_speedOut 20100202 by gj
        # Convert interface speed to Bytes
        debugout("UNIT: $units","3");
        $iface_speed = bits2bytes( $iface_speed, $units );
        if ( $iface_speedOut ) {
                $iface_speedOut = bits2bytes( $iface_speedOut, $units );
        }
}

if ( !$max_value ) {

        # If no -M Parameter was set, set it to 64Bit Overflow
        $max_bytes = 18446744073709600000;    # the value is (2^64)

        if ( defined($thirtytwo) ){
                # If using 32bit counters set to 32bit overflow
                $max_bytes = 4294967296;    # the value is (2^32)
        }
} else {
        # Max value specified, used given value, convert to Bytes
        $max_bytes = unit2bytes( $max_value, $units );
}

debugout ("BYTE COUNTER max_value: $max_bytes", "2");

####### Can only be set after interface 'speed in' and 'out' and 'max bytes' have all been converted to Bytes
# Bytes
$units = "B";

# Check snmp version, set snmp parameters
if ( $snmp_version =~ /[12]/ ) {
        ( $session, $error ) = Net::SNMP->session(
                -hostname  => $host_address,
                -community => $COMMUNITY,
                -port      => $port,
                -version   => $snmp_version
        );

        if ( !defined($session) ) {
                stop("UNKNOWN: $error","UNKNOWN");
        }
} elsif ( $snmp_version =~ /3/ ) {
        $state = 'UNKNOWN';
        stop("$state: No support for SNMP v3 yet\n",$state);
} else {
        $state = 'UNKNOWN';
        stop("$state: No support for SNMP v$snmp_version yet\n",$state);
}

debugout("SNMP:\n\tver: $snmp_version\n\tcommunity: $COMMUNITY\n\tport: $port", "3");

# Neither Interface Index nor Host IP address were specified
if ( !$iface_descr ) {
        if ( !$host_ip ){
                # try to resolve host name and find index from ip addr
                debugout("DETECT INTERFACE start with hostname", "1");
                $iface_descr = fetch_Ip2IfIndex( $session, $host_address );
        } else {
                # Use ip addr to find index
                debugout("DETECT INTERFACE start with IP addr","1");
                $iface_descr = fetch_Ip2IfIndex( $session, $host_ip );
        }
}

# Added 20091209 gj
# Detect if a string description was given or a numberic interface index number
if ( $iface_descr =~ /[^0123456789]+/ ) {
        $iface_number = fetch_ifdescr( $session, $iface_descr );
        debugout("INTERFACE from text string","1");
} else {
        $iface_number = $iface_descr;
}

debugout("USING INT#: $iface_number", "2");
debugout("OID's:","2");
debugout("\tIfOperStatus: $snmpIfOperStatus.$iface_number","2");
debugout("\tIfSpeed: $snmpIfSpeed.$iface_number","2");
debugout("\tIfSpeed32: $snmpIfSpeed32.$iface_number","2");
debugout("\tInOctets: $snmpIfInOctets.$iface_number","2");
debugout("\tInOctets32: $snmpIfInOctets32.$iface_number","2");
debugout("\tOutOctets: $snmpIfOutOctets.$iface_number","2");
debugout("\tOutOctets32: $snmpIfOutOctets32.$iface_number","2");

# Get SNMP values, flag errors
debugout("RESULTS:","3");
my $res_status    = $session->get_request(-varbindlist => [ $snmpIfOperStatus . "." . $iface_number ],);
if ( defined $res_status ){
        $if_status  = $res_status->{ $snmpIfOperStatus . "." . $iface_number };
        debugout("\tOperational Status: $if_status","3");
} else {
        $if_status = "DNE - " . $session->error();
        debugout("\tOperational Status not defined!: $if_status","2");
}
my $res_ifspeed64 = $session->get_request(-varbindlist => [ $snmpIfSpeed . "." . $iface_number ],);
if ( defined $res_ifspeed64 ){
        $ifspeed64  = $res_ifspeed64->{ $snmpIfSpeed . "." . $iface_number };
        debugout("\tInterface Speed (64bit): $ifspeed64 Mbits","3");
} else {
        $ifspeed64 = "DNE - " . $session->error();
        debugout("\tInterface Speed (64bit) not defined or bad value!: $ifspeed64","2");
}
my $res_ifspeed32 = $session->get_request(-varbindlist => [ $snmpIfSpeed32 . "." . $iface_number ],);
if ( defined $res_ifspeed32 ){
        $ifspeed32  = $res_ifspeed32->{ $snmpIfSpeed32 . "." . $iface_number };
        debugout("\tInterface Speed (32bit): $ifspeed32 bits","3");
} else {
        $ifspeed32 = "DNE - " . $session->error();
        debugout("\tInterface Speed (32bit) not defined!: $ifspeed32","2");
}
my $res_inbytes64 = $session->get_request(-varbindlist => [ $snmpIfInOctets . "." . $iface_number ],);
if ( defined $res_inbytes64 ){
        $inbytes64  = $res_inbytes64->{ $snmpIfInOctets . "." . $iface_number };
        debugout("\tIn Bytes (64bit): $inbytes64","2");
} else {
        $inbytes64 = "DNE - " . $session->error();
        debugout("\tIn Bytes (64bit) not defined!: $inbytes64","2");
}
my $res_inbytes32  = $session->get_request(-varbindlist => [ $snmpIfInOctets32 . "." . $iface_number ],);
if ( defined $res_inbytes32 ){
        $inbytes32  = $res_inbytes32->{ $snmpIfInOctets32 . "." . $iface_number };
        debugout("\tIn Bytes (32bit): $inbytes32","3");
} else {
        $inbytes32 = "DNE - " . $session->error();
        debugout("\tIn Bytes (32bit) not defined!: $inbytes32","2");
}
my $res_outbytes64 = $session->get_request(-varbindlist => [ $snmpIfOutOctets . "." . $iface_number ],);
if ( defined $res_outbytes64 ){
        $outbytes64  = $res_outbytes64->{ $snmpIfOutOctets . "." . $iface_number };
        debugout("\tOut Bytes (64bit): $outbytes64","3");
} else {
        $outbytes64 = "DNE - " . $session->error();
        debugout("\tOut Bytes (64bit) not defined!: $outbytes64","2");
}
my $res_outbytes32 = $session->get_request(-varbindlist => [ $snmpIfOutOctets32 . "." . $iface_number ],);
if ( defined $res_outbytes32 ){
        $outbytes32  = $res_outbytes32->{ $snmpIfOutOctets32 . "." . $iface_number };
        debugout("\tOut Bytes (32bit): $outbytes32","3");
} else {
        $outbytes32 = "DNE - " . $session->error();
        debugout("\tOut Bytes (32bit) not defined!: $outbytes32","2");
}

# Check interface status, quit check if interface status is error or not '1'.
if ( defined $res_status ){
        if ( $if_status =~ /^DNE -|error|noSuchObject|noSuchInstance/i ) {
                debugout("if_status is not a number\n","4");
                $state = 'UNKNOWN';
                stop("$state: Improper interface status, status received: " . $if_status . "\n",$state);
        } elsif ( $if_status == 1 ) {
                # No action necessary, continue on!
        } elsif ($if_status == 2 ) {
                # Quit, interface is down
                $state = 'CRITICAL';
                stop("$state: Interface is \'down\' (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        } elsif ($if_status == 3 ) {
                # Quit, interface is testing
                $state = 'CRITICAL';
                stop("$state: Interface is reporting \'testing\' (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        } elsif ($if_status == 4 ) {
                # Quit, interface is unknown
                $state = 'CRITICAL';
                stop("$state: Interface is reporting \'unknown\' (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        } elsif ($if_status == 5 ) {
                # Quit, interface is dormant
                $state = 'CRITICAL';
                stop("$state: Interface is reporting \'dormant\' (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        } elsif ($if_status == 6 ) {
                # Quit, interface is notPresent
                $state = 'CRITICAL';
                stop("$state: Interface is reporting \'notPresent\' (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        } elsif ($if_status == 7 ) {
                # Quit, interface is lowerLayerDown
                $state = 'CRITICAL';
                stop("$state: Interface is reporting \'lowerLayerDown\' (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        } else {
                # Interface is in an unknown state
                $state = 'UNKNOWN';
                stop("$state: Interface is reporting unknown status (interface: " . $iface_number . " status: " . $if_status . ")\n",$state);
        }
} else {
        $state = 'UNKNOWN';
        stop("$state: Improper interface status, status received: " . $if_status . "\n",$state);
}

# Determine which values to use
if ( !defined($force) and !defined($thirtytwo) ){
        #default - use 64 then 32 bit values
        debugout("USING 64 THEN 32 bit VALUES:","4");

        # Speed test
        if ( !$iface_speed ) {
                debugout("\t(Interface speed not provided on command line, determine from host)","4");
                if ( $ifspeed64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i or $ifspeed64 < 1 ){
                        debugout("\t\tBad 64bit speed value: $ifspeed64","3");
                        if ( $ifspeed32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i or $ifspeed32 < 1 or $ifspeed32 > 4294967295 ){
                                debugout("\t\tBad 32bit speed value: $ifspeed32","3");
                                $state = 'UNKNOWN';
                                stop("$state: No usable interface speed available 64: $ifspeed64 32: $ifspeed32\n",$state);
                        } else {
                                debugout("\tUsing 32bit speed value: $ifspeed32","3");
#                               $iface_speed = $ifspeed32;
                                $iface_speed = bits2bytes( $ifspeed32, "b" );
                        }
                } else {
                        debugout("\tUsing 64bit speed value: $ifspeed64","3");
                        # Convert Mbits to bits, bits to Bytes
                        $iface_speed = $ifspeed64 * 1000 * 1000;
                        $iface_speed = bits2bytes( $iface_speed, "b" );
                }
        }

        # InBytes test
        if ( $inbytes64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 64bit in bytes value: $inbytes64","3");
                if ( $inbytes32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                        debugout("\t\tBad 32bit in bytes value: $inbytes32","3");
                        $state = 'UNKNOWN';
                        stop("$state: No in bytes available 64: $inbytes64 32: $inbytes32\n",$state);
                } else {
                        debugout("\tUsing 32bit in bytes value: $inbytes32","3");
                        $in_bytes = $inbytes32;
                }
        } else {
                debugout("\tUsing 64bit in bytes value: $inbytes64","3");
                $in_bytes = $inbytes64;
        }

        # OutBytes test
        if ( $outbytes64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 64bit out bytes value: $outbytes64","3");
                if ( $outbytes32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                        debugout("\t\tBad 32bit out bytes value: $outbytes32","3");
                        $state = 'UNKNOWN';
                        stop("$state: No out bytes available 64: $outbytes64 32: $outbytes32\n",$state);
                } else {
                        debugout("\tUsing 32bit out bytes value: $outbytes32","3");
                        $out_bytes = $outbytes32;
                }
        } else {
                debugout("\tUsing 64bit out bytes value: $outbytes64","3");
                $out_bytes = $outbytes64;
        }

} elsif ( !defined($force) and defined($thirtytwo) ){
        debugout("USING 32 THEN 64 bit VALUES:","4");

        # Speed test
        if ( !$iface_speed ) {
                debugout("\t(Interface speed not provided on command line, determine from host)","4");
                if ( $ifspeed32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i or $ifspeed32 < 1 or $ifspeed32 >= 4294967295 ){
                        debugout("\t\tBad 32bit speed value: $ifspeed32","3");
                        if ( $ifspeed64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i or $ifspeed64 < 1 ){
                                debugout("\t\tBad 64bit speed value: $ifspeed64","3");
                                $state = 'UNKNOWN';
                                stop("$state: No usable interface speed available 64: $ifspeed64 32: $ifspeed32\n",$state);
                        } else {
                                debugout("\tUsing 64bit speed value: $ifspeed64","3");
                                # Convert Mbits to bits, bits to Bytes
                                $iface_speed = $ifspeed64 * 1000 * 1000;
                                $iface_speed = bits2bytes( $iface_speed, "b" );
                        }
                } else {
                        debugout("\tUsing 32bit speed value: $ifspeed32","3");
#                       $iface_speed = $ifspeed32;
                        $iface_speed = bits2bytes( $ifspeed32, "b" );
                }
        }

        # InBytes test
        if ( $inbytes32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 32bit in bytes value: $inbytes32","3");
                if ( $inbytes64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                        debugout("\t\tBad 64bit in bytes value: $inbytes64","3");
                        $state = 'UNKNOWN';
                        stop("$state: No in bytes available 64: $inbytes64 32: $inbytes32\n",$state);
                } else {
                        debugout("\tUsing 64bit in bytes value: $inbytes64","3");
                        $in_bytes = $inbytes64;
                }
        } else {
                debugout("\tUsing 32bit in bytes value: $inbytes32","3");
                $in_bytes = $inbytes32;
        }

        # OutBytes test
        if ( $outbytes32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 32bit out bytes value: $outbytes32","3");
                if ( $outbytes64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                        debugout("\t\tBad 64bit out bytes value: $outbytes64","3");
                        $state = 'UNKNOWN';
                        stop("$state: No out bytes available 64: $outbytes64 32: $outbytes32\n",$state);
                } else {
                        debugout("\tUsing 64bit out bytes value: $outbytes64","3");
                        $out_bytes = $outbytes64;
                }
        } else {
                debugout("\tUsing 32bit out bytes value: $outbytes32","3");
                $out_bytes = $outbytes32;
        }

} elsif ( defined($force) and defined($thirtytwo) ){
        debugout("USING 32 bit VALUES ONLY:","4");

        # Speed test
        if ( !$iface_speed ) {
                debugout("\t(Interface speed not provided on command line, determine from host)","4");
                if ( $ifspeed32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i or $ifspeed32 < 1 or $ifspeed32 > 4294967295 ){
                        debugout("\t\tBad 32bit speed value: $ifspeed32","3");
                        $state = 'UNKNOWN';
                        stop("$state: No usable interface speed available: $ifspeed32\n",$state);
                } else {
                        debugout("\tUsing 32bit speed value: $ifspeed32","3");
#                       $iface_speed = $ifspeed32;
                        $iface_speed = bits2bytes( $ifspeed32, "b" );
                }
        }

        # InBytes test
        if ( $inbytes32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 32bit in bytes value: $inbytes32","3");
                $state = 'UNKNOWN';
                stop("$state: No in bytes available: $inbytes32\n",$state);
        } else {
                debugout("\tUsing 32bit in bytes value: $inbytes32","3");
                $in_bytes = $inbytes32;
        }

        # OutBytes test
        if ( $outbytes32 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 32bit out bytes value: $outbytes32","3");
                $state = 'UNKNOWN';
                stop("$state: No out bytes available: $outbytes32\n",$state);
        } else {
                debugout("\tUsing 32bit out bytes value: $outbytes32","3");
                $out_bytes = $outbytes32;
        }

} elsif ( defined($force) and !defined($thirtytwo) ){
        debugout("USING 64 bit ONLY:","4");

        # Speed test
        if ( !$iface_speed ) {
                debugout("\t(Interface speed not provided on command line, determine from host)","4");
                if ( $ifspeed64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i or $ifspeed64 < 1 ){
                        debugout("\t\tBad 64bit speed value: $ifspeed64","3");
                        $state = 'UNKNOWN';
                        stop("$state: No usable interface speed available: $ifspeed64\n",$state);
                } else {
                        debugout("\tUsing 64bit speed value: $ifspeed64","3");
                        # Convert Mbits to bits, bits to Bytes
                        $iface_speed = $ifspeed64 * 1000 * 1000;
                        $iface_speed = bits2bytes( $iface_speed, "b" );
                }
        }

        # InBytes test
        if ( $inbytes64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 64bit in bytes value: $inbytes64","3");
                $state = 'UNKNOWN';
                stop("$state: No in bytes available: $inbytes64\n",$state);
        } else {
                debugout("\tUsing 64bit in bytes value: $inbytes64","3");
                $in_bytes = $inbytes64;
        }

        # OutBytes test
        if ( $outbytes64 =~ /^DNE -|error|noSuchObject|noSuchInstance/i ){
                debugout("\t\tBad 64bit out bytes value: $outbytes64","3");
                $state = 'UNKNOWN';
                stop("$state: No out bytes available: $outbytes64\n",$state);
        } else {
                debugout("\tUsing 64bit out bytes value: $outbytes64","3");
                $out_bytes = $outbytes64;
        }

}

#if ( !$iface_speed ) {
#       debugout("Convert speed from bits to Bytes","4");
#       $iface_speed = bits2bytes( $iface_speed, $units );
#       $units = "b";
#}

# Added 20100201 gj
# Check if Out max speed was provided, use same IF speed for both if not
if (!$iface_speedOut) {
        $iface_speedOut = $iface_speed;
}

debugout ("UNITS: $units", "2");
debugout ("Interface speed calculated as: $iface_speed $units", "1");
debugout ("Interface speed OUT: $iface_speedOut $units", "4");

# close SNMP
$session->close;

my $row;
my $last_check_time = time - 1;
my $last_in_bytes   = $in_bytes;
my $last_out_bytes  = $out_bytes;

if (
        open( FILE,
                "<" . $TRAFFIC_FILE . $host_address . "_if-" . $iface_number
        )
  )
{
        while ( $row = ) {

                ( $last_check_time, $last_in_bytes, $last_out_bytes ) =
                  split( ":", $row );

                ### by sos 17.07.2009 check for last_bytes
                if ( ! $last_in_bytes  ) { $last_in_bytes=$in_bytes;  }
                if ( ! $last_out_bytes ) { $last_out_bytes=$out_bytes; }

                if ($last_in_bytes !~ m/\d/) { $last_in_bytes=$in_bytes; }
                if ($last_out_bytes !~ m/\d/) { $last_out_bytes=$out_bytes; }
        }
        close(FILE);
}

my $update_time = time;
debugout ("CURRENT timestamp: $update_time", "1");
debugout ("FILE PATH: $TRAFFIC_FILE" . $host_address . "_if-" . $iface_number, "1");
debugout("READ FROM FILE:\n\tlast time: $last_check_time\n\tlast in bytes: $last_in_bytes\n\tlast out bytes: $last_out_bytes","4");

open( FILE, ">" . $TRAFFIC_FILE . $host_address . "_if-" . $iface_number )
  or die "Can't open $TRAFFIC_FILE for writing: $!";

printf FILE ( "%s:%.0ld:%.0ld\n", $update_time, $in_bytes, $out_bytes );
close(FILE);

debugout("WRITTEN TO FILE:\n\ttime: $update_time\n\tin_bytes: $in_bytes\n\tout bytes: $out_bytes","4");

#added 20050614 by mw
#Check for and correct counter overflow (if possible).
#See function counter_overflow.
$in_bytes  = counter_overflow( $in_bytes,  $last_in_bytes,  $max_bytes );
$out_bytes = counter_overflow( $out_bytes, $last_out_bytes, $max_bytes );

# Calculate traffic since last check (RX\TX)
my $in_traffic = sprintf( "%.2lf",
        ( $in_bytes - $last_in_bytes ) / ( time - $last_check_time ) );
my $out_traffic = sprintf( "%.2lf",
        ( $out_bytes - $last_out_bytes ) / ( time - $last_check_time ) );

debugout("in_traffic: $in_traffic\nout_traffic: $out_traffic","1");
# sos 20090717 changed because rrdtool needs bytes
my $in_bytes_abs  = $in_bytes;
my $out_bytes_abs = $out_bytes;

debugout("iface_speed: $iface_speed $units\nin_traffic: $in_traffic\nout_traffic: $out_traffic", "1");

# Calculate usage percentages
my $in_ave_pct  = sprintf( "%.2f", ( 1.0 * $in_traffic * 100 ) / $iface_speed );
my $out_ave_pct = sprintf( "%.2f", ( 1.0 * $out_traffic * 100 ) / $iface_speedOut );

if ($bits) {
        # Convert output from Bytes to bits
        $label = "bits";
        $in_tot = $in_bytes * 8;
        $out_tot = $out_bytes * 8;
        $in_ave = $in_traffic * 8;
        $out_ave = $out_traffic * 8;
} else {
        $label = "Bytes";
        $in_tot = $in_bytes;
        $out_tot = $out_bytes;
        $in_ave = $in_traffic;
        $out_ave = $out_traffic;
}

debugout("OUTPUT:\n\tlabel: $label", "4");
debugout("\tin_tot: $in_tot\n\tout_tot: $out_tot\n\tin_ave: $in_ave\n\tout_ave: $out_ave", "4");
debugout("\tin_ave_pct: $in_ave_pct\n\tout_ave_pct: $out_ave_pct\n\tin_bytes_abs: $in_bytes_abs\n\tout_bytes_abs: $out_bytes_abs", "4");

# Scale ave and tot for output
$in_tot = unit2scale($in_tot);
$out_tot = unit2scale($out_tot);
$in_ave = unit2scale($in_ave);
$out_ave = unit2scale($out_ave);

# Convert from Bytes/bits to megaBytes/bits
$in_bytes  = sprintf( "%.2f", $in_bytes / (1024 * 1000) );
$out_bytes = sprintf( "%.2f", $out_bytes / (1024 * 1000) );

# Changed 20091209 gj, updated 20130424 gj
# Check/Set state of service check
#if ( ( $in_ave_pct > $crit_usage ) or ( $out_ave_pct > $crit_usage ) or ( $if_status != 1 ) ) {
if ( ( $in_ave_pct < $warn_usage ) and ( $out_ave_pct < $warn_usage ) ) {
        $state = 'OK';
        $output =
        "$state - Average IN: "
          . $in_ave . $suffix . " (" . $in_ave_pct . "%), "
        #  . "Average OUT: " . $out_ave . $suffix . " (" . $out_ave_pct . "%)
";
          . "Average OUT: " . $out_ave . $suffix . " (" . $out_ave_pct . "%)";
        $output .= "Total RX: $in_tot" . "$label, Total TX: $out_tot" . "$label";
} elsif ( $in_ave_pct > $crit_usage ) {
        $state = 'CRITICAL';
        $output = "$state - IN bandwidth ($in_ave_pct%) too high";
} elsif ( $out_ave_pct > $crit_usage ) {
        $state = 'CRITICAL';
        $output = "$state - OUT bandwidth ($out_ave_pct%) too high";
} elsif ( $in_ave_pct > $warn_usage ) {
        $state = 'WARNING';
        $output = "$state - IN bandwidth ($in_ave_pct%) too high";
} elsif ( $out_ave_pct > $warn_usage ) {
        $state = 'WARNING';
        $output = "$state - OUT bandwidth ($out_ave_pct%) too high";
}

# Changed 20091214 gj - commas should have been semi colons
$output .=
"|inUsage=$in_ave_pct%;$warn_usage;$crit_usage outUsage=$out_ave_pct%;$warn_usage;$crit_usage"
  . " inBandwidth=" . $in_ave . $suffix . " outBandwidth=" . $out_ave . $suffix
  . " inAbsolut=$in_bytes_abs" . "B" . " outAbsolut=$out_bytes_abs" . "B";

debugout ("",1);
stop($output, $state);

sub fetch_Ip2IfIndex {
        my $state;
        my $response;

        my $snmpkey;
        my $answer;
        my $key;

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

        # Determine if we have a host name or IP addr
        if ( $host =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ ){
                #debugout("I found an IP address: $host","3");
        } else {
                debugout("RESOLVING hostname $host","3");
                $host = get_ip ( $host );
                debugout("HOSTNAME RESOLVED to IP addr: $host","3");
        }

        # Quit if results not found
        if ( !defined( $response = $session->get_table($snmpIPAdEntIfIndex) ) ) {
                $answer = $session->error;
                $session->close;
                $state = 'CRITICAL';
                stop ("$state: Interface index not detected ERROR: $answer",$state);
        }

        my %resp = %{$response};

        if ( $index_list ){
                print ("\nInterfaces found:\n");
                print ("  IP Addr\tIndex\n");
                print ("------------------------\n");
        }
        # Check each returned value
        foreach $key ( keys %resp ) {

                if ( $index_list ){
                        my $index_addr = substr $key, 21;
                        print ($index_addr,"\t ",$resp{$key},"\n");
                }

                # Check for ip address match in returned index results
                if ( $key =~ /$host$/ ) {
                        $snmpkey = $resp{$key};
                }
        }
        unless ( defined $snmpkey ) {
                $session->close;
                $state = 'CRITICAL';
                stop("$state: Could not find index matching $host",$state);
        }
        return $snmpkey;
}

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';
                exit $STATUS_CODE{$state};
        }

        foreach $key ( keys %{$response} ) {

                # added 20070816 by oer: remove trailing 0 Byte for Windows :-(
                my $resp=$response->{$key};
                $resp =~ s/\x00//;


                my $test = defined($use_reg)
                      ? $resp =~ /$ifdescr/
                      : $resp eq $ifdescr;

                if ($test) {

                ###if ( $resp =~ /^$ifdescr$/ ) {
                ###if ( $resp =~ /$ifdescr/ ) {
                ### print "$resp  \n";
                ###if ( $response->{$key} =~ /^$ifdescr$/ ) {

                        $key =~ /.*\.(\d+)$/;
                        $snmpkey = $1;

                        debugout("\t$ifdescr = $key / $snmpkey","2");
                }
        }
        unless ( defined $snmpkey ) {
                $session->close;
                $state = 'CRITICAL';
                printf "$state: Could not match $ifdescr \n";
                exit $STATUS_CODE{$state};
        }
        return $snmpkey;
}

#added 20050416 by mw
#Converts an input value to value in bits
sub bits2bytes {
        return unit2bytes(@_) / 8;
}

#added 20050416 by mw
#Converts an input value to value in bytes
sub unit2bytes {
        my ( $value, $unit ) = @_;

        if ( $unit eq "g" ) {
                return $value * 1000 * 1000 * 1000;
        }
        elsif ( $unit eq "m" ) {
                return $value * 1000 * 1000;
        }
        elsif ( $unit eq "k" ) {
                return $value * 1000;
        }
        elsif ( $unit eq "b" ) {
                return $value * 1;
        }
        else {
                print "You have to supply a supported unit (g,m,k,b)\n";
                exit $STATUS_CODE{'UNKNOWN'};
        }
}

sub unit2scale {
        # Scale output, expecting Bits\Bytes input
        my ($val) = @_;
        my $prefix = "";

        # I'm not sure which should be used here 1024 or 1000 but 1000 is easier on the
        # eye when looking at the plug-in output
        #if ( $val > 1024 ) {
        if ( $val > 1000 ) {
        #       $val = sprintf( "%.2f", $val / 1024 );
                $val = sprintf( "%.2f", $val / 1000 );
                $prefix = "K";
        }
        if ( $val > 1000 ) {
                $val = sprintf( "%.2f", $val / 1000 );
                $prefix = "M";
        }
        if ( $val > 1000 ) {
                $val = sprintf( "%.2f", $val / 1000 );
                $prefix = "G";
        }
        return $val . $prefix;
}

# Convert from Bytes/bits to megaBytes/bits
#added 20050414 by mw
#This function detects if an overflow occurs. If so, it returns
#a computed value for $bytes.
#If there is no counter overflow it simply returns the origin value of $bytes.
#IF there is a Counter reboot wrap, just use previous output.
sub counter_overflow {
        my ( $bytes, $last_bytes, $max_bytes ) = @_;

        $bytes += $max_bytes if ( $bytes < $last_bytes );
        $bytes = $last_bytes  if ( $bytes < $last_bytes );
        return $bytes;
}

# Added 20100202 by gj
# Print results and exit script
sub stop {
        my $result = shift;
        my $exit_code = shift;
        print $result . "\n";
        exit ( $STATUS_CODE{$exit_code} );
}

# Added 20100405 by gj
# Lookup hosts ip address
sub get_ip {
        use Net::DNS;

        my ( $host_name ) = @_;

        my $res = Net::DNS::Resolver->new;
        my $query = $res->search($host_name);

        if ($query) {
                foreach my $rr ($query->answer) {
                        next unless $rr->type eq "A";
                        return $rr->address;
                }
        } else {

                stop("Error: IP address not resolved","UNKNOWN");
        }
}

sub debugout {

        my ( $text, $level ) = @_;

        if ( $level <= $debug) {
                print "$text\n";
        }
}

#cosmetic changes 20050614 by mw
#Couldn't sustain "HERE";-), either.
sub print_usage {
        print <
    Usage: check_iftraffic64.pl -H host [ -C community_string ] [ -i if_index|if_descr ] [ -r ] [ -b if_max_speed_in | -I if_max_speed_in ] [ -O if_max_speed_out ] [ -u ] [ -B ] [ --32bit ] [ -f ] [ -A IP Address ] [ -L ] [ -M ] [ -w warn ] [ -c crit ]

    Example 1: check_iftraffic64.pl -H host1 -C sneaky
    Example 2: check_iftraffic64.pl -H host1 -C sneaky -i "Intel Pro" -r -B
    Example 3: check_iftraffic64.pl -H host1 -C sneaky -i 5
    Example 4: check_iftraffic64.pl -H host1 -C sneaky -i 5 -B -b 100 -u m --32bit
    Example 5: check_iftraffic64.pl -H host1 -C sneaky -i 5 -B -I 20 -O 5 -u m
    Example 6: check_iftraffic64.pl -H host1 -C sneaky -A 192.168.1.1 -B -b 100 -u m
    Example 7: check_iftraffic64.pl -H host1 -C sneaky -A 192.168.1.1 --force --32bit

    Options:


    -b, --bandwidth INTEGER
    -I, --inBandwidth INTEGER
        Interface maximum speed in kilo/mega/giga/bits per second. Applied to
        both IN and OUT if out (-O) max speed is not provided. Requires -u.
    -O, --outBandwidth INTEGER
        Interface maximum speed in kilo/mega/giga/bits per second. Applied to
        OUT traffic.  Uses the same units value given for -b. Requires -u.
    -i, --interface STRING
        Interface Name
    -M, --max INTEGER
        Max Counter Value (in bits) of net devices in giga/mega/kilo/bits. Requires -u.
    -r, --regexp
        Use regexp to match NAME in description OID
    -u, --units STRING
        g=gigabits/s,m=megabits/s,k=kilobits/s,b=bits/s. Required if -b, -I, -M,
        or -O are used.

    -A, --address STRING (IP Address)
        IP Address to use when determining the interface index to use. Can be
        used when the index changes frequently or as in the case of Windows
        servers the index is different depending on the NIC installed.
    -C, --community STRING
        SNMP Community.
    -H, --host STRING or IPADDRESS
        Check interface on the indicated host.
    -c, --critical INTEGER
        % of bandwidth usage necessary to result in critical status (default: 98%)
    -w, --warning INTEGER
        % of bandwidth usage necessary to result in warning status (default: 85%)

    --32bit FLAG
        Set to use 32 bit counters instead of 64 bit (default: 64 bit).
    -B, --bits FLAG
        Display results in bits per second b/s (default: Bytes/s)
    -f, --force FLAG
        Set to force either 64 bit or 32 bit only checking (32 bit requires --32bit flag).
    -d, --debug INTEGER
        Output some debug info, not supported inside of Nagios but may be useful
        from the command line.  Levels 1-4 can be specified, 4 being the most information.
    -h, --help
        Displays this help text
    -L, --list FLAG (on/off)
        Tell plugin to list available interfaces. This is not supported inside
        of Nagios but may be useful from the command line.
    -v, --Version STRING
        Set SNMP version (defaults to 2).  Version 2 required for 64 bit counters.
        Version 3 not supported.
EOU

}


Done,

#Nagios #Monitoring #Bandwidth #BW #Script #Tool