Binary Talks

UDP Packet Loss Check Plugin for Nagios

logo_nagiosI just needed to rewrite a small check plugin I’ve written a few months ago to check possible UDP data loss on a host which serves an application that constantly has to process tens of thousand UDP packets at a time. Otherwise we just wouldn’t know in time when the application or the host’s network stack become somewhat limited because of UDP’s stateless nature and that’s what you better wanna know for sure if the transmitted data is valuable for the company.

The script

As always, the script is downloadable from NagiosExchange, via svn directly from here or the copy’n'paste way below.

user@host ~ $ svn co https://svn.matejunkie.com/svn/nagios-plugins/stable/check_udp-packet-loss/ check_udp-packet-loss/

It makes use of netstat to check for packets received to an unknown port or receive errors and to monitor the overall count of UDP packets received. This information is being put into a file in a temporary directory which is not being used at all for now, I must confess. The idea behind that is to rather monitor UDP packet receive errors over a period of time instead of its total count, but since there’s other heavy stuff going on at the moment, I just don’t have the time to finish this at the moment. I’ll do this within the next weeks.
The script checks by itselfs whether the file grows over 32K, then deletes and re-creates it. So no worries about broken hard drives here.

The term “packets to unknown port received” is explained as the following: “Displays the total number of UDP datagrams received for which there was no application at the destination port” which means that e.g. those will increase when you’d temporarily shutdown your application. “packet receive errors” will mostly occur when the host’s buffer is bursting. For additional information I’d suggest reading “UDP Buffer sizing” at 29west.com and UDP’s man page at kernel.org.

#!/bin/sh
 
#   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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
PROGNAME=`basename $0`
VERSION="Version 1.0,"
AUTHOR="2009, Mike Adolphs (http://www.matejunkie.com/)"
 
ST_OK=0
ST_WR=1
ST_CR=2
ST_UK=3
 
path_tmp="/tmp"
 
print_version() {
    echo "$VERSION $AUTHOR"
}
 
print_help() {
    print_version $PROGNAME $VERSION
    echo ""
    echo "$PROGNAME is a Nagios plugin to monitor the UDP packet loss via"
    echo "netstat."
    echo ""
    echo "$PROGNAME check_udp-packet-loss.sh"
    echo ""
    echo "Options:"
    echo "  --warning|-w)"
    echo "    Sets a warning level for packet receive errors. Default is:"
    echo "    off"
    echo "  --critical|-c)"
    echo "    Sets a critical level for packet receive errors. Default is:"
    echo "    off"
    echo "  --path-tmp|-t)"
    echo "    Sets the path for the temporary file. Default is: /tmp"
    exit $ST_UK
}
 
while test -n "$1"; do
    case "$1" in
        --help|-h)
            print_help
            exit $ST_UK
            ;;
        --version|-v)
            print_version $PROGNAME $VERSION
            exit $ST_UK
            ;;
        --path-tmp|-t)
            path_tmp=$2
            shift
            ;;
        --warning|-w)
            warn=$2
            shift
            ;;
        --critical|-c)
            crit=$2
            shift
            ;;
        *)
            echo "Unknown argument: $1"
            print_help
            exit $ST_UK
            ;;
    esac
    shift
done
 
check_filesize() {
    if [ -f $path_tmp/check_udp-packet-errors.log ]
    then
        size=`du $path_tmp/check_udp-packet-errors.log | awk '{print $1}'`
	if [ $size -gt 32 ]
        then
            rm $path_tmp/check_udp-packet-errors.log
            touch $path_tmp/check_udp-packet-errors.log
        fi
    else
        touch $path_tmp/check_udp-packet-errors.log
    fi
}
 
check_packet_loss() {
    p_receive=`netstat -us|grep 'packets received'|awk '{print $1}'`
    echo "Received: $p_receive" >> $path_tmp/check_udp-packet-errors.log
    p_unknown=`netstat -us|grep 'to unknown port'|awk '{print $1}'`
    echo "Unknown: $p_unknown" >> $path_tmp/check_udp-packet-errors.log
    p_errors=`netstat -us|grep 'packet receive errors'|awk '{print $1}'`
    echo "Errors: $p_errors" >> $path_tmp/check_udp-packet-errors.log
}
 
val_wcdiff() {
    if [ ${warn} -gt ${crit} ]
    then
        wcdiff=1
    fi
}
 
check_filesize
check_packet_loss
 
if [ -n "$warn" -a -n "$crit" ]
then
    val_wcdiff
    if [ "$wcdiff" = 1 ]
    then
        echo "The warning level should be lower than the critical level. Please adjust them."
        exit $ST_UK
    fi
fi
 
if [ -n "$warn" -a -n "$crit" ]
then
    if [ "$p_unknown" -ge "$warn" -a "$p_unknown" -lt "$crit" ]
    then
        echo "WARNING - $p_receive total packets received, $p_unknown went to unknown port, $p_errors receive errors! | 'received'=$p_receive 'unknown_port'=$p_unknown 'errors'=$p_errors"
        exit $ST_WR
    elif [ "$p_unknown" -ge "$crit" ]
    then
        echo "CRITICAL - $p_receive total packets received, $p_unknown went to unknown port, $p_errors receive errors! | 'received'=$p_receive 'unknown_port'=$p_unknown 'errors'=$p_errors"
        exit $ST_CR
    else
        echo "OK - $p_receive total packets received, $p_unknown went to unknown port, $p_errors receive errors! | 'received'=$p_receive 'unknown_port'=$p_unknown 'errors'=$p_errors"
        exit $ST_OK
    fi
else
    echo "OK - $p_receive total packets received, $p_unknown went to unknown port, $p_errors receive errors! | 'received'=$p_receive 'unknown_port'=$p_unknown 'errors'=$p_errors"
    exit $ST_OK
fi

The License

As always this little script is ment to be sh-compliant and released under the terms of the GPL Version 2 only. Feel free to subscribe via rss to get updates on this one. More options will be added in the future.

Share and Enjoy:
  • del.icio.us
  • Digg
  • Slashdot
  • Google Bookmarks
  • LinkedIn
  • StumbleUpon
  • Reddit
  • Yigg
  • Netvibes
  • MisterWong
  • Facebook
  • HackerNews
  • Identi.ca
  • FriendFeed
  • NewsVine

speak up

Add your comment below, or trackback from your own site.

Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

*Required Fields