Archivi tag: noise margin

check_noise_margin e check_attenuation: script Nagios per verificare la qualità della nostra linea ADSL

Premessa

Vi sono numerosi fattori che possono influenzare negativamente o positivamente la qualità della nostra linea ADSL, ma i più importanti sono sicuramente il rapporto segnale rumore (SNR o noise margin) e l’attenuazione.

In particolare, nel primo caso un valore elevato indica una qualità migliore; viceversa, nel secondo caso, un valore elevato indica una qualità peggiore. Inoltre, i valori di attenuazione sono molto influenzati dalla distanza che intercorre tra la nostra abitazione e la centrale di zona dell’ISP (va da se che maggiore sarà questa distanza, maggiore sarà l’attenuazione).

Esistono comunque dei valori di massima (sia per l’SNR che per l’attenuazione) sui quali ci si può basare per fare una stima qualitativa del nostro collegamento ADSL. Li riporto di seguito:

SNR

1) <= 6dB : pessimo, numerosi errori si sincronizzazione con la portante;
2) tra i 7dB ed i 10dB: scarso;
3) tra gli 11dB ed i 20dB: buono;
4) tra i 20dB ed i 28dB: eccellente;
5) >= 29dB: eccezionale.

 Attenuazione

1) < = 20dB: eccezionale;
2) tra i 20dB ed i 30dB: eccellente:
3) tra i 30dB ed i 40dB: molto buona;
4) tra i 40dB ed i 50dB: buona;
5) tra i 50dB ed i 60dB: scarsa, con diversi errori di connessione.
6) >= 60dB: pessima, con numerosi errori di connessione.

Tenendo conto dei suddetti valori, ho deciso di realizzare 2 scrip bash (da integrare a Nagios), in modo da tenere traccia dei valori di SNR ed attenuazione relativi alla mia linea ADSL. Il router di riferimento è un Cisco 877.

Entrambi gli scrip in questione (check_noise_margin e check_attenuation), si basano su un ulteriore scrip expect (get_dsl_info) che esegue la query sul router, lanciando il comando sh dsl int atm0.

Il contenuto di tale scrip è il seguente:

#!/usr/bin/expect

set ip [lindex $argv 0]
set password1 [lindex $argv 1]
set password2 [lindex $argv 2]

spawn ssh -l nightfly "$ip"
expect "*?assword:*"
send "$password1\r"
expect ">"
send "ena\r"
expect "Password:"
send "$password2\r"
expect "#"
send "sh dsl int atm0\r"
send " "
expect "#"
send "exit\r"
expect eof

L’output da esso generato verrà quindi dato in pasto ed elaborato da check_noise_margin e da check_attenuation. Il loro contenuto è molto simile ed è (rispettivamente):

#!/bin/bash

host=$1
password1=$2
password2=$3
warning=$4
critical=$5

usage="check_noise_margin <host> <password1> <password2> <warning> <critical>"

if [ -n "$host" ]; then

        if [ -n "$password1" ];then

                if [ -n "$password2" ];then

                        if [ -n "$warning" ];then

                                if [ -n "$critical" ];then

                                        if [ "$critical" -gt "$warning" ];then

                                                echo "UNKNOWN: critical has to be less than warning"
                                                exit 3;

                                        else

                                                output=`/usr/lib64/nagios/plugins/get_dsl_info $1 $2 $3 | grep "Noise"  | awk -F " " '{print $3,$5}'`
                                                output1=`echo $output | awk '{print $1}'`
                                                output2=`echo $output | awk '{print $2}'`
                                                unit="db"
                                        fi

                                        if [ -n "$output" ];then

                                                if [ $(echo "$output1 < $critical" | bc) -eq 1 -o $(echo "$output2 < $critical" | bc) -eq 1 ];then

                                                        echo "CRITICAL: downstream noise margin is $output1 db, upstream noise margin is $output2 db | downstream_noise_margin=$output1$unit;$warning;$critical upstream_noise_margin=$output2$unit;$warning;$critical";
                                                        exit 2;

                                                elif [ $(echo "$output1 > $critical" | bc) -eq 1 -a  $(echo "$output1 < $warning" | bc) -eq 1 -o $(echo "$output2 > $critical" | bc) -eq 1 -a $(echo "$output2 < $warning"  |bc) -eq 1 ];then

                                                        echo "WARNING: downstream noise margin is $output1 db, upstream noise margin is $output2 db| downstream_noise_margin=$output1$unit;$warning;$critical upstream_noise_margin=$output2$unit;$warning;$critical" ;
                                                        exit 1;

                                                else

                                                        echo "OK: downstream noise margin is $output1 db, upstream noise margin is $output2 db | downstream_noise_margin=$output1$unit;$warning;$critical upstream_noise_margin=$output2$unit;$warning;$critical";
                                                        exit 0;

                                                fi
                                        else

                                                echo "UNKNOWN: output is null"
                                                exit 3;

                                        fi

                                else

                                        echo "$usage"
                                        exit 3;
                                fi

                        else

                                echo "$usage"
                                exit 3;
                        fi

                else

                        echo "$usage"
                        exit 3;
                fi
        else

                echo "$usage"
                exit 3;
        fi

else

        echo "$usage"
        exit 3;

fi

per check_noise_margin, e:

#!/bin/bash

host=$1
password1=$2
password2=$3
warning=$4
critical=$5

usage="check_attenuation <host> <password1> <password2> <warning> <critical>"

if [ -n "$host" ]; then

        if [ -n "$password1" ];then

                if [ -n "$password2" ];then

                        if [ -n "$warning" ];then

                                if [ -n "$critical" ];then

                                        if [ "$critical" -lt "$warning" ];then

                                                echo "UNKNOWN: critical has to be greater than warning"
                                                exit 3;

                                        else

                                                output=`/usr/lib64/nagios/plugins/get_dsl_info $1 $2 $3 | grep "Attenuation"  | awk -F " " '{print $2, $4}'`

                                                output1=`echo $output | awk '{print $1}'`
                                                output2=`echo $output | awk '{print $2}'`
                                                unit="db"
                                        fi

                                        if [ -n "$output" ];then

                                                if [ $(echo "$output1 > $critical" | bc) -eq 1 -o $(echo "$output2 > $critical" | bc) -eq 1 ];then

                                                        echo "CRITICAL: downstream attenuation is $output1 db, upstream attenuation is $output2 db | downstream_attenuation=$output1$unit;$warning;$critical upstream_attenuation=$output2$unit;warning;$critical";
                                                        exit 2;

                                                elif [ $(echo "$output1 < $critical" | bc) -eq 1 -a  $(echo "$output1 > $warning" | bc) -eq 1 -o $(echo "$output2 < $critical" | bc) -eq 1 -a  $(echo "$output2 > $warning" | bc) -eq 1 ];then

                                                        echo "WARNING: downstream attenuation is $output1 db, upstream attenuation is $output2 db | downstream_attenuation=$output1$unit;$warning;$critical upstream_attenuation=$output2$unit;$warning;$critical";
                                                        exit 1;

                                                else

                                                        echo "OK: downstream attenuation is $output1 db, upstream attenuation is $output2 db | downstream_attenuation=$output1$unit;$warning;$critical upstream_attenuation=$output2$unit;$warning;$critical";
                                                        exit 0;

                                                fi
                                        else

                                                echo "UNKNOWN: output is null"
                                                exit 3;

                                        fi

                                else

                                        echo "$usage"
                                        exit 3;
                                fi

                        else

                                echo "$usage"
                                exit 3;
                        fi

                else

                        echo "$usage"
                        exit 3;
                fi
        else

                echo "$usage"
                exit 3;
        fi

else

        echo "$usage"
        exit 3;

fi

per check_attenuation.

Da notare che in entrambi i casi ho aggiunto le perfdata da dare in pasto a pnp4nagios. Inoltre, poichè i valori restituiti possono contenere dei decimali, ho dovuto utilizzare il comando bc per i calcoli aritmetici. Ciò si è reso necessario poichè bash tratta nativamente le variabili come stringhe.

Una volta fatto ciò, ho semplicemente creato i comandi per Nagios:

# 'check_noise_margin' command definition
 define command{
 command_name    check_noise_margin
 command_line    $USER1$/check_noise_margin $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$ $ARG4$
 }
# 'check_attenuation' command definition
 define command{
 command_name    check_attenuation
 command_line    $USER1$/check_attenuation $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$ $ARG4$
 }

collegandoli, successivamente, ai servizi del router Cisco:

define service{
 use                             local-service         ; Name of service template to use
 host_name                       router
 service_descripion             Noise Margin
 check_command                   check_noise_margin!pass1!pass2!10!6
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       router
 service_descripion             Attenuation
 check_command                   check_attenuation!pass1!pass2!51!61
 }

Infine, ho lanciato un reload del servizio:

[root@nightbox objects]# service nagios reload

e finalmente la qualità della mia linea ADSL è sotto monitoraggio.

Alla prossima.

PS: per chi le preferisse, ecco le varianti in Perl dei suddetti scrip:

#!/usr/bin/perl

use strict;
use warnings;

my $host=$ARGV[0];
my $password1=$ARGV[1];
my $password2=$ARGV[2];
my $warning=$ARGV[3];
my $critical=$ARGV[4];

my $usage="check_noise_margin.pl <host> <password1> <password2> <warning> <critical>";

if ($host ne "") {
        if ($password1 ne "")
        {
                if ($password2 ne "")
                {
                        if ($warning ne "")
                        {
                                if ($critical ne "")
                                {
                                        if ($critical > $warning)
                                        {
                                                print "UNKNOWN: critical has to be less than warning";
                                                exit 3;
                                        }
                                        else
                                        {
                                                my $output=`/usr/lib64/nagios/plugins/get_dsl_info $host $password1 $password2 | /bin/grep "Noise"`;

                                                if($output ne "")
                                                {

                                                        my @columns = split /\s+/, $output;
                                                        my $downstream = $columns[2];
                                                        my $upstream = $columns[4];
                                                        my $unit = "db";

                                                        if ($downstream < $critical || $upstream < $critical)
                                                        {
                                                                print "CRITICAL: downstream noise margin is $downstream db; upstream noise margin is $upstream db | downstream_noise_margin=$downstream$unit;$warning;$critical upstream_noise_margin=$upstream$unit;$warning;$critical\n";
                                                                exit 2;
                                                        }
                                                        elsif ($downstream > $critical && $downstream < $warning || $upstream > $critical && $upstream < $warning)
                                                        {
                                                                print "WARNING: downstream noise margin is $downstream db; upstream noise margin is $upstream db | downstream_noise_margin=$downstream$unit;$warning;$critical upstream_noise_margin=$upstream$unit;$warning;$critical\n";
                                                                exit 1;
                                                        }
                                                        else
                                                        {
                                                                print "OK: downstream noise margin is $downstream db, upstream noise margin is $upstream db | downstream_noise_margin=$downstream$unit;$warning;$critical upstream_noise_margin=$upstream$unit;$warning;$critical\n";
                                                                exit 0;
                                                        }
                                                }
                                                else
                                                {
                                                                print "UNKNOWN: output is null";
                                                                exit 3;
                                                }
                                        }
                                }
                                else
                                {
                                        print "$usage";
                                        exit 3;
                                }
                        }
                        else
                        {
                                print "$usage";
                                exit 3;
                        }
                }
                else
                {
                        print "$usage";
                        exit 3;
                }
        }
        else
        {
                print "$usage";
                exit 3;
        }
}
else
{
        print "$usage";
        exit 3;
}

e

#!/usr/bin/perl

use strict;
use warnings;

my $host=$ARGV[0];
my $password1=$ARGV[1];
my $password2=$ARGV[2];
my $warning=$ARGV[3];
my $critical=$ARGV[4];

my $usage="check_attenuation.pl <host> <password1> <password2> <warning> <critical>";

if ($host ne "") {
        if ($password1 ne "")
        {
                if ($password2 ne "")
                {
                        if ($warning ne "")
                        {
                                if ($critical ne "")
                                {
                                        if ($critical < $warning)
                                        {
                                                print "UNKNOWN: critical has to be more than warning";
                                                exit 3;
                                        }
                                        else
                                        {
                                                my $output=`/usr/lib64/nagios/plugins/get_dsl_info $host $password1 $password2 | /bin/grep "Attenuation"`;

                                                if($output ne "")
                                                {

                                                        my @columns = split /\s+/, $output;
                                                        my $downstream = $columns[1];
                                                        my $upstream = $columns[3];
                                                        my $unit = "db";

                                                        if ($downstream > $critical || $upstream > $critical)
                                                        {
                                                                print "CRITICAL: downstream attenuation is $downstream db; upstream attenuation is $upstream db | downstream_attenuation=$downstream$unit;$warning;$critical upstream_attenuation=$upstream$unit;$warning;$critical\n";
                                                                exit 2;
                                                        }
                                                        elsif ($downstream < $critical && $downstream > $warning || $upstream < $critical && $upstream > $warning)
                                                        {
                                                                print "WARNING: downstream attenuation is $downstream db; upstream attenuation is $upstream db | downstream_attenuation=$downstream$unit;$warning;$critical upstream_attenuation=$upstream$unit;$warning;$critical\n";
                                                                exit 1;
                                                        }
                                                        else
                                                        {
                                                                print "OK: downstream attenuation is $downstream db, upstream attenuation is $upstream db | downstream_attenuation=$downstream$unit;$warning;$critical upstream_attenuation=$upstream$unit;$warning;$critical\n";
                                                                exit 0;
                                                        }
                                                }
                                                else
                                                {
                                                                print "UNKNOWN: output is null";
                                                                exit 3;
                                                }
                                        }
                                }
                                else
                                {
                                        print "$usage";
                                        exit 3;
                                }
                        }
                        else
                        {
                                print "$usage";
                                exit 3;
                        }
                }
                else
                {
                        print "$usage";
                        exit 3;
                }
        }
        else
        {
                print "$usage";
                exit 3;
        }
}
else
{
        print "$usage";
        exit 3;
}

PPS: se sul vostro router è stato abilitato il protocollo SNMP, gli OID che consentono di monitorare SNR ed attenuazione sono i seguenti:

.1.3.6.1.2.1.10.94.1.1.3.1.5.11 = downstream attenuation 
.1.3.6.1.2.1.10.94.1.1.2.1.5.11 = upstream attenuation 
.1.3.6.1.2.1.10.94.1.1.3.1.4.11 = downstream noise margin
.1.3.6.1.2.1.10.94.1.1.2.1.4.11 = upstream noise margin

In particolare, l’ultima parte dell’OID (.11) si riferisce all’Interface Index della Dialer (nel mio caso si tratta della Dialer0).