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).