#!/usr/bin/perl # -*- perl -*- =head1 NAME 2wire - Plugin to monitor 2Wire/Pace residential gateway =head1 CONFIGURATION [2wire] env.gatewayaddr http://192.168.1.254 env.drawline true env.monthline 250000000000 env.weekline 62500000000 env.dayline 8333333333 =head1 LICENSE GPLv2 =head1 AUTHOR Daniel Lee =head1 MAGICK MARKERS #%# family=network #%# capabilities=autoconf =cut use strict; use warnings; use POSIX; use WWW::Mechanize; use WWW::Mechanize::TreeBuilder; use Munin::Plugin; my $gatewayAddr = $ENV{'gatewayaddr'} || 'http://192.168.1.254'; my $drawLine = $ENV{'drawline'} || 'false'; my $monthLine = $ENV{'monthline'} || 250000000000; my $weekLine = $ENV{'weekline'} || 62500000000; my $dayLine = $ENV{'dayline'} || 8333333333; my $mech = WWW::Mechanize->new; WWW::Mechanize::TreeBuilder->meta->apply($mech); sub autoconf { my $url = $gatewayAddr."/xslt?PAGE=C_0_0"; $mech->get( $url ); if($mech->success()) { print "yes\n"; } else { print "no\n"; } exit 0; } sub config { print << "EOF"; multigraph 2wire_session_count graph_title 2wire NAT session count graph_args --base 1000 -l 0 #graph_vlabel number of sessions in (-) / out (+) graph_vlabel number of sessions graph_scale no graph_category network graph_total Total graph_printf %.0lf inboundSessions.label Inbound inboundSessions.draw AREASTACK #inboundSessions.graph no outboundSessions.label Outbound outboundSessions.draw AREASTACK #outboundSessions.negative inboundSessions #inboundSessions.line 512:ff0000:Inbound session limit outboundSessions.line 1024:ff0000:Session table limit multigraph 2wire_session_type graph_title 2wire NAT session type graph_args --base 1000 -l 0 graph_vlabel number of sessions graph_scale no graph_category network graph_total Total graph_printf %.0lf tcpSessions.label TCP tcpSessions.draw AREASTACK udpSessions.label UDP udpSessions.draw AREASTACK udpSessions.line 1024:ff0000:Session table limit multigraph 2wire_session_uptime graph_title 2wire session uptime graph_args --base 1000 -l 0 graph_vlabel Uptime in days graph_scale no graph_category network sessionUptime.label Uptime sessionUptime.draw AREA sessionUptime.cdef sessionUptime,86400,/ ### multigraph 2wire_dsl_power graph_title 2wire DSL output power graph_args --base 1000 graph_vlabel dBmV graph_scale no graph_category network powerDown.label Down #powerDown.graph no powerUp.label Up #powerUp.negative powerDown multigraph 2wire_dsl_details graph_title 2wire DSL details graph_args --base 1000 graph_vlabel dB graph_scale no graph_category network noiseM.label Noise margin attenuation.label Attenuation attenuation300.label Attenuation @ 300kHz gain.label Final Receive Gain multigraph 2wire_dsl_seconds graph_title 2wire Errors Time graph_args --base 1000 graph_vlabel s graph_scale no graph_category network cumSecErrors.label Cumulative Seconds w/Errors cumSecSevErrors.label Cumulative Seconds w/Severe Errors unavailable.label DSL Unavailable Seconds multigraph 2wire_dsl_blocks graph_title 2wire Block Correction graph_args --base 1000 graph_vlabel blocks/s graph_scale no graph_category network correctedBlocks.label Corrected Blocks correctedBlocks.type DERIVE correctedBlocks.min 0 uncorrectableBlocks.label Uncorrectable Blocks uncorrectableBlocks.type DERIVE uncorrectableBlocks.min 0 multigraph 2wire_dsl_traffic graph_title 2wire DSL traffic graph_args --base 1024 -l 0 graph_vlabel Bytes in (-) / out (+) per second graph_category network receive.label Bps receive.type DERIVE receive.min 0 receive.graph no transmit.label Bps transmit.type DERIVE transmit.min 0 transmit.negative receive #### multigraph 2wire_dsl_bandwidth_monthly graph_title 2wire DSL bandwidth usage (monthly) graph_args --base 1024 -l 0 -M graph_vlabel Bytes graph_category network down.label Down up.label Up total.label Total EOF if($drawLine eq 'true') { print "total.line ".$monthLine.":ff0000\n" } print << "EOF"; multigraph 2wire_dsl_bandwidth_weekly graph_title 2wire DSL bandwidth usage (weekly) graph_args --base 1024 -l 0 -M graph_vlabel Bytes graph_category network down.label Down up.label Up total.label Total EOF if($drawLine eq 'true') { print "total.line ".$weekLine.":ff0000\n" } print << "EOF"; multigraph 2wire_dsl_bandwidth_daily graph_title 2wire DSL bandwidth usage (daily) graph_args --base 1024 -l 0 -M graph_vlabel Bytes graph_category network down.label Down up.label Up total.label Total EOF if($drawLine eq 'true') { print "total.line ".$dayLine.":ff0000\n" } exit 0; } sub bandwidth_acc { my $date = shift; my $bandwidth = shift; my $str = shift; my $up = shift; my $down = shift; unless(exists $bandwidth->{$str}) { $bandwidth->{$str} = $date; $bandwidth->{$str.'_u_c'} = 0; $bandwidth->{$str.'_d_c'} = 0; $bandwidth->{$str.'_u_t'} = $up; $bandwidth->{$str.'_d_t'} = $down; } if($date != $bandwidth->{$str}) { $bandwidth->{$str} = $date; if($bandwidth->{$str.'_u_t'} <= $up || $bandwidth->{$str.'_d_t'} <= $down) { $bandwidth->{$str.'_u_c'} = $up - $bandwidth->{$str.'_u_t'}; $bandwidth->{$str.'_d_c'} = $down - $bandwidth->{$str.'_d_t'}; } else { $bandwidth->{$str.'_u_c'} = 0; $bandwidth->{$str.'_d_c'} = 0; } } elsif($bandwidth->{$str.'_u_t'} > $up || $bandwidth->{$str.'_d_t'} > $down) { $bandwidth->{$str.'_u_c'} += $up; $bandwidth->{$str.'_d_c'} += $down; } else { $bandwidth->{$str.'_u_c'} += $up - $bandwidth->{$str.'_u_t'}; $bandwidth->{$str.'_d_c'} += $down - $bandwidth->{$str.'_d_t'}; } $bandwidth->{$str.'_u_t'} = $up; $bandwidth->{$str.'_d_t'} = $down; } sub process_bandwidth { my $values = shift; my ($up,$down) = ($values->{'transmit'}, $values->{'receive'}); my ($day, $week, $month) = map(int, split(/ /, POSIX::strftime("%j %U %m", localtime))); $month = int(($week-1) / 4); my %bandwidth = restore_state(); my %bandwidth = (); bandwidth_acc($month,\%bandwidth,'month',$up,$down); bandwidth_acc($week,\%bandwidth,'week',$up,$down); bandwidth_acc($day,\%bandwidth,'day',$up,$down); save_state(%bandwidth); print "multigraph 2wire_dsl_bandwidth_monthly\n"; print "up.value ", $bandwidth{'month_u_c'},"\n"; print "down.value ", $bandwidth{'month_d_c'},"\n"; print "total.value ", $bandwidth{'month_u_c'}+$bandwidth{'month_d_c'},"\n"; print "\n"; print "multigraph 2wire_dsl_bandwidth_weekly\n"; print "up.value ", $bandwidth{'week_u_c'},"\n"; print "down.value ", $bandwidth{'week_d_c'},"\n"; print "total.value ", $bandwidth{'week_u_c'}+$bandwidth{'week_d_c'},"\n"; print "\n"; print "multigraph 2wire_dsl_bandwidth_daily\n"; print "up.value ", $bandwidth{'day_u_c'},"\n"; print "down.value ", $bandwidth{'day_d_c'},"\n"; print "total.value ", $bandwidth{'day_u_c'}+$bandwidth{'day_d_c'},"\n"; print "\n"; } sub process_values { my $values = shift; print << "EOF"; multigraph 2wire_dsl_power powerDown.value $values->{'power-down'} powerUp.value $values->{'power-up'} multigraph 2wire_dsl_details noiseM.value $values->{'noise-margin'} attenuation.value $values->{'attenuation'} attenuation300.value $values->{'attenuation300'} gain.value $values->{'gain'} multigraph 2wire_dsl_seconds cumSecErrors.value $values->{'cum-sec-errors'} cumSecSevErrors.value $values->{'cum-sec-sev-errors'} unavailable.value $values->{'sec-unavailable'} multigraph 2wire_dsl_blocks correctedBlocks.value $values->{'corrected-blocks'} uncorrectableBlocks.value $values->{'uncorrectable-blocks'} multigraph 2wire_dsl_traffic transmit.value $values->{'transmit'} receive.value $values->{'receive'} EOF } sub broadband_page { my $url = $gatewayAddr."/xslt?PAGE=C_1_0"; $mech->get( $url ); die unless $mech->success(); my (%values, $m); $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Noise Margin'}); $m->right()->as_text =~ /(\S+) dB/; $values{'noise-margin'} = $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Attenuation'}); $m->right()->as_text =~ /(\S+) dB/; $values{'attenuation'} = $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Output Power'}); $m->right()->as_text =~ /(\S+) dB/; $values{'power-down'} = $1; $m = $m->right(); $m->right()->as_text =~ /(\S+) dB/; $values{'power-up'} = $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Attenuation @ 300kHz'}); $m->right()->as_text =~ /(\S+) dB/; $values{'attenuation300'} = $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Final Receive Gain'}); $m->right()->as_text =~ /(\S+) dB/; $values{'gain'} = $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Transmit'}); $m->right()->as_text =~ /(\d+)/; $values{'transmit'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Receive'}); $m->right()->as_text =~ /(\d+)/; $values{'receive'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Receive'}); $m->right()->as_text =~ /(\d+)/; $values{'receive'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Link Retrains'}); $m->right()->as_text =~ /(\d+)/; $values{'link-retrains'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'DSL Training Errors'}); $m->right()->as_text =~ /(\d+)/; $values{'dsl-training-errors'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Training Timeouts'}); $m->right()->as_text =~ /(\d+)/; $values{'training-timeouts'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Cum. Seconds w/Errors'}); $m->right()->as_text =~ /(\d+)/; $values{'cum-sec-errors'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Cum. Sec. w/Severe Errors'}); $m->right()->as_text =~ /(\d+)/; $values{'cum-sec-sev-errors'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Corrected Blocks'}); $m->right()->as_text =~ /(\d+)/; $values{'corrected-blocks'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'Uncorrectable Blocks'}); $m->right()->as_text =~ /(\d+)/; $values{'uncorrectable-blocks'} = int $1; $m = $mech->look_down(_tag => 'td', sub { $_[0]->as_text eq 'DSL Unavailable Seconds'}); $m->right()->as_text =~ /(\d+)/; $values{'sec-unavailable'} = int $1; process_values(\%values); process_bandwidth(\%values); } sub nat_page { my $url = $gatewayAddr."/xslt?PAGE=C_5_5"; $mech->get( $url ); die unless $mech->success(); my (%sessions, $uptime); my ($m, $raw, @stext); $m = $mech->look_down(_tag => 'h2', sub { $_[0]->as_text eq 'Current NAT Sessions'}); $raw = $m->right()->as_text; $raw =~ s/^\n//; @stext = split("\n", $raw); $stext[0] =~ /boot: (\d+)/; $uptime = int $1; $stext[1] =~ /session table (\d+)\/(\d+) available, (\d+)\/\d+ used/; ($sessions{'used'}, $sessions{'inbound'}) = ($2 - $1, $3); $sessions{'outbound'} = $sessions{'used'} - $sessions{'inbound'}; my $i = 0; foreach (@stext) { $i += 1 if /proto: 6/; } ($sessions{'tcp'}, $sessions{'udp'}) = ($i, $sessions{'used'} - $i); print << "EOF"; multigraph 2wire_session_count inboundSessions.value $sessions{'inbound'} outboundSessions.value $sessions{'outbound'} multigraph 2wire_session_type tcpSessions.value $sessions{'tcp'} udpSessions.value $sessions{'udp'} multigraph 2wire_session_uptime sessionUptime.value $uptime EOF } if($ARGV[0] and $ARGV[0] eq "autoconf") { autoconf } elsif($ARGV[0] and $ARGV[0] eq "config") { config } else { broadband_page; nat_page; }