Previous page: Link Quality v1
Next page: Bandwidth

Link Quality v2

Version 2.0.2

Inspired by moving to ipcop version 2 and a move of ISPs, I decided to improve my link quality graphs with extra information such as line noise and speed.  My ISP (Sky) provided a router that allowed, via http, the line speed and noise to be seen.  So my challenge was to present this on an ipcop graph.  The aim being this:

In the graph above, the green is my downstream speed (ie 10 meg) although my measured throughput is somewhat less using a downloading speed checker - but I guess this is normal.  The noise at 3.8db (above) is graphed at times 2000 to ensure it is visible on the speed scale.  It does provide, I think a useful, visual indication of my line quality.

Where as in the earlier version I collected the data within the file /usr/local/bin/makegraphs I decided this time to script up my collection and to collect the data via cron. So here's that bit

1. Write an appropriate script file that will get the speed and noise data from your router.  As mine uses a webpage, I had to install wget on top of ipcop v2.  Here's my script (/root/allan/get-router-info)


#!/bin/bash
#
# sky router
#-----------------------
wget --tries=2 -T 30 -S -w 1 --http-user=admin --http-passwd=*** -O /root/allan/info.html http://192.168.8.8/sky_system.html
sed -f /root/allan/sedcmd-speed /root/allan/info.html > /root/allan/routerspeed.txt
sed -f /root/allan/sedcmd-noise /root/allan/info.html > /root/allan/routernoise.txt
rm /root/allan/info.html

if you need help with the sed scripts (it's not easy!), here are mine, but google is also your friend! sedcmd-speed sedcmd-noise and to put that in context sample info.html, routerspeed.txt and routernoise.txt (not necessarily all from the same time)

2. Then amend the root cron file at /var/spool/cron/root.orig :


....
# Aggregate traffic data (every 5 minutes)
*/5 * * * *    /usr/local/bin/aggregatetraffic.pl > /dev/null

# Run traffic monitoring (every 5 minutes)
*/5 * * * *    /usr/local/bin/monitorTraffic.pl > /dev/null

# get router information (every 5 minutes)
*/5 * * * *    /root/allan/get-router-info > /dev/null

 

3. Apply these changes by running fcrontab -u root -z. The process above produces two small files that have the router speed (ie 10000) and noise (ie 4.54) followed by a new line.

4. Next we add our new procedures to /usr/local/bin/makegraphs . First to build the rrd data:


# ---------------------------------------------
# Added for line quality graphs               |
# Creates and updates a line quality database |
# ---------------------------------------------
sub updateln {
if ( ! -e "$rrdlog/ln.rrd") {
RRDs::create ("$rrdlog/ln.rrd", "--step=300",
"DS:speed:GAUGE:600:0:12000",
"DS:noise:GAUGE:600:0:150",
"RRA:AVERAGE:0.5:1:576",
"RRA:AVERAGE:0.5:6:672",
"RRA:AVERAGE:0.5:24:732",
"RRA:AVERAGE:0.5:144:1460");
$ERROR = RRDs::error;
print "Error in RRD::create for line quality: $ERROR\n" if $ERROR;
}

my $sspeed = `cat /root/allan/routerspeed.txt | tr -d "\r\n"`;
my $snoise = `cat /root/allan/routernoise.txt | tr -d "\r\n"`;

RRDs::update("$rrdlog/ln.rrd", "-t", "speed:noise", "N:$sspeed:$snoise");
$ERROR = RRDs::error;
print "Error in RRD::update for line quality: $ERROR\n" if $ERROR;
}

 

5. And a procedure to build the gaphs:


sub updatelngraph {
my $period = $_[0];
my @rrd = ();
push @rrd, @{&rrd_header("ln", $period, "$Lang::tr{'ln'} ($Lang::tr{$period})", 0, 15000)};
push @rrd, "-v speed/noise";
push @rrd, "DEF:vspeed=$rrdlog/ln.rrd:speed:AVERAGE";
push @rrd, "DEF:vnoise=$rrdlog/ln.rrd:noise:AVERAGE";
push @rrd, "CDEF:xnoise=vnoise,2000,*";
push @rrd, "CDEF:s0=vspeed,1000,MIN";
push @rrd, "CDEF:s1=vspeed,2000,MIN";
push @rrd, "CDEF:s2=vspeed,3000,MIN";
push @rrd, "CDEF:s3=vspeed,4000,MIN";
push @rrd, "CDEF:s4=vspeed,5000,MIN";
push @rrd, "CDEF:s5=vspeed,6000,MIN";
push @rrd, "CDEF:s6=vspeed,7000,MIN";
push @rrd, "CDEF:s7=vspeed,8000,MIN";
push @rrd, "CDEF:s8=vspeed,9000,MIN";
push @rrd, "CDEF:s9=vspeed,10000,MIN";
push @rrd, "AREA:s9#8CFF8C:10k+ kbps";
push @rrd, "AREA:s8#85FF85:9k kbps";
push @rrd, "AREA:s7#7DFF7D:8k kbps";
push @rrd, "AREA:s6#77FF77:7k kbps";
push @rrd, "AREA:s5#6FEC6F:6k kbps";
push @rrd, "AREA:s4#68D068:5k kbps";
push @rrd, "AREA:s3#62B562:4k kbps";
push @rrd, "AREA:s2#5A995A:3k kbps";
push @rrd, "AREA:s1#537C53:2k kbps";
push @rrd, "AREA:s0#464646:1k kbps";
#push @rrd, "AREA:vspeed#00ff00:speed";
push @rrd, "LINE1:vspeed#000000:";
push @rrd, "LINE1:xnoise#c00000:noise\\j";
push @rrd, "GPRINT:vspeed:MAX:$Lang::tr{'maximal'} $Lang::tr{'linespd'}\\:%3.0lf kbps";
push @rrd, "GPRINT:vspeed:AVERAGE:$Lang::tr{'average'} $Lang::tr{'linespd'}\\:%3.0lf kbps";
push @rrd, "GPRINT:vspeed:LAST:$Lang::tr{'current'} $Lang::tr{'linespd'}\\:%3.0lf kbps\\j";
push @rrd, "GPRINT:vnoise:MAX:$Lang::tr{'maximal'} $Lang::tr{'linense'}\\:%3.2lf db";
push @rrd, "GPRINT:vnoise:AVERAGE:$Lang::tr{'average'} $Lang::tr{'linense'}\\:%3.2lf db";
push @rrd, "GPRINT:vnoise:LAST:$Lang::tr{'current'} $Lang::tr{'linense'}\\:%3.2lf db\\j";

push @rrd, @{&rrd_lastupdate()};
RRDs::graph(@rrd);
$ERROR = RRDs::error;
print "Error in RRD::graph for Line Quality: $ERROR\n" if $ERROR;
}

Noise is scaled to enable it to be clearly visible on the graph.  The y-axis has no bearing on the noise figure, but the max/average/current figures are accurate.

6. And at the end of the file, call the above procedures:


###
### System graphs
###

updateln();
updatelngraph("hour");
updatelngraph("day");
updatelngraph("week");
updatelngraph("month");
updatelngraph("year");

updatecpudata();
updatecpugraph("hour");
updatecpugraph("day");
updatecpugraph("week");
updatecpugraph("month");
updatecpugraph("year");

 

7. Because we have added some language dependant texts, add these to a file in /var/ipcop/addons/lang/ and run rebuildlangtexts.

8. We also need to ammend the file /home/httpd/cgi-bin/graphs.cgi to display the graphs. Here's the changes:


...
$ENV{'QUERY_STRING'} =~ s/&//g;
@cgigraphs = split(/graph=/,$ENV{'QUERY_STRING'});
$cgigraphs[1] = '' unless defined $cgigraphs[1];

if ($cgigraphs[1] =~ /(network|GREEN|BLUE|ORANGE|RED|ln)/) {
&Header::openpage($Lang::tr{'network traffic graphs'}, 1, '');
}
else {
&Header::openpage($Lang::tr{'system graphs'}, 1, '');
}
&Header::openbigbox('100%', 'left');

if ($cgigraphs[1] =~ /(GREEN|BLUE|ORANGE|RED|cpu|memory|diskuse|disk|ln)/) {
# Display 1 specific graph

my $graph = $cgigraphs[1];
my ($graphname, $count) = split('_', lc($graph));
my $back = '';
my $title = '';
if ($graph =~ /(GREEN|BLUE|ORANGE|RED|ln)/) {
$title = ($count >= 2) ? $Lang::tr{$graphname}." ".$count : $Lang::tr{$graphname};
$back = "<a href='/cgi-bin/graphs.cgi?graph=network'>";
$title = $Lang::tr{'ln'} if ($graph eq 'ln');}
else {
$title = $Lang::tr{'cpu usage'} if ($graph eq 'cpu');
$title = $Lang::tr{'memory usage'} if ($graph eq 'memory');
$title = $Lang::tr{'disk usage'} if ($graph eq 'diskuse');
$title = $Lang::tr{'disk access'} if ($graph eq 'disk');
$back = "<a href='/cgi-bin/graphs.cgi'>";
}

&Header::openbox('100%', 'center', "$title $Lang::tr{'graph'}");

if (-e "$graphdir/${graph}-day.png") {
print <<END
<table width='100%'><tr>
<td width='10%'>$back<img src='/images/back.png' alt='$Lang::tr{'back'}' title='$Lang::tr{'back'}' /></a></td>
<td>&nbsp;</td>
</tr></table>
<hr />
<img src='/graphs/${graph}-hour.png' border='0' alt='${graph}-$Lang::tr{'hour'}' /><hr />
<img src='/graphs/${graph}-day.png' border='0' alt='${graph}-$Lang::tr{'day'}' /><hr />
<img src='/graphs/${graph}-week.png' border='0' alt='${graph}-$Lang::tr{'week'}' /><hr />
<img src='/graphs/${graph}-month.png' border='0' alt='${graph}-$Lang::tr{'month'}' /><hr />
<img src='/graphs/${graph}-year.png' border='0' alt='${graph}-$Lang::tr{'year'}' />
END
;
}
else {
print $Lang::tr{'no information available'};
}

print <<END
<hr />
<table width='100%'><tr>
<td width='10%'>$back<img src='/images/back.png' alt='$Lang::tr{'back'}' title='$Lang::tr{'back'}' /></a></td>
<td>&nbsp;</td>
</tr></table>
END
;
&Header::closebox();
}
elsif ($cgigraphs[1] =~ /network/) {
# Display network graphs

push (@graphs, ("ln"));

for my $color ('GREEN', 'ORANGE', 'BLUE') {
my $icount = $netsettings{"${color}_COUNT"};
while($icount > 0) {
push (@graphs, ("${color}_${icount}"));
...


^Top
Previous page: Link Quality v1
Next page: Bandwidth