Link Quality

Tested on:  1.4.21

I wanted to be reassured that the link to my ISP was clean and efficient. This addition is based on one I came across in the Coyote Linux project. I have amended it to work with IPCop. This is what the graph looks like:

Link Quality

The change involves changes to two files. You should take a copy of these first as the last thing you want to do is break your IPCop whilst editing!

  1. Edit /usr/local/bin/makegraphs and add a procedure updatelq as per the box below and save the change (I recommend adding it just after the updateifgraph procedure. This procedure, updatelq, that will create the rrd data and keep it upto date. It uses the ping command to ping the upstream ip from your red interface (this will be the first public ip at your isp). You'll need to add this ip as LQ_GATEWAY in the procedure.

  2. # Added for linkq
    # Creates and updates a link quality database
    # -------------------------------------------
    sub updatelq {
    if ( ! -e "$rrdlog/lq.rrd") {
    RRDs::create ("$rrdlog/lq.rrd", "--step=300",
    "DS:loss:GAUGE:600:0:100",
    "DS:roundtrip:GAUGE:600:0:10000",
    "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 link: $ERROR\n" if $ERROR;
    }

    my $packetloss=0;
    my $roundtrip=0;
    my $test=0;
    # ------------------------------------------------------------------ #
    # LQ_GATEWAY is the ip of your isp's public ip facing you
    my $LQ_GATEWAY="195.166.128.xxx";
    # ------------------------------------------------------------------ #
    # Mod by Rob Moore to use dynamic addresses
    # my $LQ_GATEWAY=`netstat -r | grep ^default | awk '{print \$2}'`;
    # or I found better...
    # my $LQ_GATEWAY=`netstat -rn | grep ^0.0.0.0 | awk '{print \$2}'`;
    # ------------------------------------------------------------------ #
    my $NUMPINGS=10;

    # -- Sample output on ipcp 1.4.6 --
    # root@ipcop:/usr/local/bin # ping -c 10 -q 195.xxx.128.yyy
    # PING 195.xxx.128.yyy (195.xxx.128.yyy): 56 data bytes
    # --- 195.xxx.128.yyy ping statistics ---
    # 10 packets transmitted, 10 packets received, 0% packet loss
    # round-trip min/avg/max/stddev = 23.550/33.319/54.759/11.499 ms

    my $pingoutput = `ping -c $NUMPINGS -q $LQ_GATEWAY`;
    chomp;
    my @temp = split (/\/|\%|\s/, $pingoutput);
    $packetloss = $temp[17];
    $roundtrip = $temp[28];

    # $test = $temp[18];
    # print "DEBUG: @temp \n\n";
    # print "DEBUG: $pingoutput \n";
    # print "DEBUG: $packetloss $roundtrip $test \n" ;

    RRDs::update ("$rrdlog/lq.rrd", "N:$packetloss:$roundtrip");
    $ERROR = RRDs::error;
    print "Error in RRD::update for line quality: $ERROR\n" if $ERROR;
    }

  3. Add another procedure, updatelqgraph, that builds the graphs for display. Add this procedure after that one above.
    sub updatelqgraph {
    my $period = $_[0];
    RRDs::graph ("$graphs/lq-$period.png",
    "--start", "-1$period", "-aPNG", "-i", "-z",
    "--alt-y-grid", "-w 600", "-h 100", "-u 70",
    "-t $tr{'lq'} ($tr{'graph per'} $tr{$period})",
    "--lazy",
    "--color", "SHADEA#EAE9EE",
    "--color", "SHADEB#EAE9EE",
    "--color", "BACK#EAE9EE",
    "-v pkt loss -% / ms",
    "DEF:roundtrip=$rrdlog/lq.rrd:roundtrip:AVERAGE",
    "DEF:loss=$rrdlog/lq.rrd:loss:AVERAGE",
    "CDEF:roundavg=roundtrip,PREV(roundtrip),+,1.05,/",
    "CDEF:lossavg=loss,PREV(loss),+,2,/",
    "CDEF:lossd=lossavg",
    "CDEF:loss10=loss,10,*",
    "CDEF:r0=roundtrip,20,MIN",
    "CDEF:r1=roundtrip,50,MIN",
    "CDEF:r2=roundtrip,80,MIN",
    "CDEF:r3=roundtrip,100,MIN",
    "AREA:roundtrip#EE7000:>100 ms",
    "AREA:r3#D88E1B:80-100 ms",
    "AREA:r2#B9B63F:50-80 ms",
    "AREA:r1#99E064:20-50 ms",
    "AREA:r0#80FF80:<20 ms",
    "AREA:lossd#FFAA33:Ave Packet loss %",
    "AREA:loss10#FF0000:Packet loss %\\j",
    "LINE1:roundtrip#707070:",
    "GPRINT:roundtrip:MAX:$tr{'maximal'} $tr{'linkqrt'}\\:%3.2lf ms",
    "GPRINT:roundtrip:AVERAGE:$tr{'average'} $tr{'linkqrt'}\\:%3.2lf ms",
    "GPRINT:roundtrip:LAST:$tr{'current'} $tr{'linkqrt'}\\:%3.2lf ms\\j",
    "GPRINT:loss:MAX:$tr{'maximal'} $tr{'linkqls'}\\:%3.2lf%%",
    "GPRINT:loss:AVERAGE:$tr{'average'} $tr{'linkqls'}\\:%3.2lf%%",
    "GPRINT:loss:LAST:$tr{'current'} $tr{'linkqls'}\\:%3.2lf%%\\j"
    );
    $ERROR = RRDs::error;
    print "Error in RRD::graph for Link Quality: $ERROR\n" if $ERROR;
    }
  4. Add the following lines at the start of the "### System graphs" section. I'll build the standard, year, month, week and day. I'll also build an hourly graph (in line with my other ipcop modification "hourly graphs" - if you havent installed this, you just wont get the hourly graph).

    ###
    ### System graphs
    ###
    # EAK
    updatelq();
    sleep 2;
    updatelqgraph("hour");
    updatelqgraph("day");
    updatelqgraph("week");
    updatelqgraph("month");
    updatelqgraph("year");

    updatecpudata();
    updatecpugraph ("day");

  5. Add a new file /var/ipcop/addon-lang/linkq.en.pl. In that file add the text below:
    # Added
    %tr = ( %tr,
    'LinkQ' => 'Link Quality',
    'lq' => 'Link Quality',
    'linkqrt' => 'Time',
    'linkqls' => 'Pkt Loss',
    'hour' => 'Hour',
    );
  6. You'll then need to run perl -e "require '//var/ipcop/lang.pl'; &Lang::BuildCacheLang" as per the instructions in /var/ipcop/lang.pl

    lang
  7. Next, we need to actually display the information on the GUI. I decided to add mine as the first graph under the traffic graphs. We do this in the /home/httpd/cgi-bin/graphs.cgi file. Add lq twice to the lines beginning if ($cgigraphs[1] = ~( xxx | yyy | zzz | ..... so ...

    $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|lq)/) {
    &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|swap|disk|lq)/) {
    my $graph = $cgigraphs[1];
    my $graphname = ucfirst(lc($cgigraphs[1]));
    &Header::openbox('100%', 'center', "$graphname $Lang::tr{'graph'}");

  8. Just above (if you want link quality first) the push (@graphs, ('GREEN')); line add a line to push the link quality graphs -> push (@graphs, ('lq')); so ...
    } elsif ($cgigraphs[1] =~ /network/) {
    push (@graphs, ('lq'));
    push (@graphs, ('GREEN'));
    if ($netsettings{'BLUE_DEV'}) {
    push (@graphs, ('BLUE')); }
    if ($netsettings{'ORANGE_DEV'}) {

Job done!