Here is my code... It is VERY tuned to my particular
situation and doesn't have many (any?) comments...
Ozymandias, I haven't looked at your code recently, but one of the
things emphasized in mine is a strong logging capability
(via syslog).
One thing I'd like to add is "upstream failure detection"
where it will not restart the connection if the modem and
the next router "upstream to the internet" both respond to pings.
Also I'd like to add code to do error-checking of the
results of the "/etc/rc.d/init.d/pppoe start" command.
#!/usr/bin/perl -w
use strict;
use Device::SerialPort;
use ControlX10::CM11;
use Net::Ping;
use Net::Syslog;
use POSIX;
# DAEMON stuff
my $pid=fork;
exit if $pid;
die "Couldn't fork: $!" unless defined $pid;
POSIX::setsid() or die "Can't start a new session: $!";
# end DAEMON stuff
my $s=new Net::Syslog(Facility=>'local5', Priority=>'notice',
Name=>'dslmonitor');
$SIG{TERM}=sub {
$s->send('DSL monitoring stopping');
exit;
};
$s->send('DSL monitoring started');
my $i;
my $m;
my $ctr=0;
my $tdown;
while(1){
$m=is_modem_up();
if(!$m){
$s->send("modem not responding to ping");
}
$i=is_internet_up() if(($ctr==0)||(!$m));
if((!$i)||(!$m)){
$s->send('lost internet connection');
$tdown=time();
}
while((!$i)||(!$m)){
$s->send('stopping pppoe');
stop_pppoe();
$m=0;
while(!$m){
$s->send('power cycling DSL modem');
power_cycle_modem();
$s->send('power cycling complete, waiting for modem to respond t
+o ping');
my $b=time;
my $tdiff=time()-$b;
while(($tdiff<30)&&(!$m)){
sleep 1;
$m=is_modem_up();
$tdiff=time()-$b;
}
if($m){
$s->send("modem up $tdiff sec after cycle\n");
}else{
$s->send("modem not responding to pings $tdiff seconds after r
+eboot, power cycle modem again");
}
}
$s->send("waiting 30 seconds for modem DSL negotiation to occur");
sleep 30;
$s->send("starting pppoe");
start_pppoe();
$s->send("pppoe start complete, waiting 5 seconds");
sleep 5;
$s->send("probing for connectivity");
$i=is_internet_up();
$m=is_modem_up();
if(!$m){
$s->send("modem not responding to ping");
}
if(($i)&&($m)){
$tdown=time()-$tdown;
my $se=$tdown%60;
my $m=(int($tdown/(60)))%60;
my $h=(int($tdown/(60*60)))%24;
my $d=(int($tdown/(60*60*24)));
$s->send("internet connection restored after $d days, $h hours,
+$m minutes and $se seconds of downtime");
}else{
$s->send("pppoe negotiation failed");
}
}
sleep 30;
$ctr=($ctr+1)%10;
}
sub is_modem_up{
my $p=new Net::Ping("icmp");
for(my $c=0;$c<3;$c++){
my $i=$p->ping('10.0.0.1',2);;
return $i if($i);
}
return 0;
}
sub is_internet_up{
my $p=new Net::Ping("icmp");
my @inethosts=('192.5.5.241','202.12.27.33','128.63.2.53');
for(my $c=0;$c<3;$c++){
foreach(@inethosts){
my $i= $p->ping($_,5);
return $i if($i);
}
}
$s->send("internet not responding to ping");
return 0;
}
sub stop_pppoe{
system '/etc/rc.d/init.d/adsl stop >/dev/null 2>/dev/null';
}
sub start_pppoe{
system '/etc/rc.d/init.d/adsl start >/dev/null 2>/dev/null';
# checking output would be a good idea
}
sub power_cycle_modem{
#my $serial_port = new Device::SerialPort('/dev/x10');
my $serial_port = new Device::SerialPort('/dev/ttyS0');
if(!defined $serial_port){
die "error openign serial \"$!\"";
}
$serial_port->baudrate(4800);
$serial_port->databits(8);
$serial_port->parity('none');
$serial_port->stopbits(1);
$serial_port->handshake('none');
$serial_port->stty_echo(0);
$serial_port->read_const_time(5000);
$serial_port->read_char_time(5);
&ControlX10::CM11::send($serial_port, 'B1');
&ControlX10::CM11::send($serial_port, 'BK');
sleep 5;
&ControlX10::CM11::send($serial_port, 'B1');
&ControlX10::CM11::send($serial_port, 'BJ');
}
|