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