#!/usr/bin/perl -w -T # Graph multicast beacon data # Andrew Daviel, TRIUMF, June 2004 # mod. Sept 2004 - add "-T" # Oct 2004 - minor text changes $debug = 0 ; # Get previous-history file from central beacon server # Get file every 5 minutes, if it's changed. Then rebuild HTML # link tables (loss.html etc.) # run from crontab e.g. # 0,5,10,15,20,25,30,35,40,45,50,55 * * * * cd $beaconhistory ; ./get-next # saves history as "history." which must be cleaned out regularly # e.g. # 2 * * * * find $beaconhistory -mmin +600 -name 'history.*' -exec rm {} \; # also appends to "allhistory.txt" which currently will grow # indefinitely $maxage = 60*30 ; $url = "http://beacon.ncsa.uiuc.edu/prevhistory.txt" ; $allh = "allhistory.txt" ; $ENV{PATH} = '/usr/bin' ; # where to find wget if ($debug) { print "file mod size\n" ; } opendir (DIR,".") or die ; foreach $file (sort bymod readdir(DIR)) { unless ($file =~ /^history/) { next ; } @stat = stat($file) ; $size = $stat[7] ; $mod = stat[9] ; if ($debug) { print "$file $mod $size\n" ; } if ($size) { $lf = $file ; } } if (-r "$lf") { open (IN,$lf) or die ; while () { chomp ; if (/^Last-Modified:[\s]+(.*)/) { $mod = $1 ; last ; } } } else { $mod = 0 ; } if ($debug) { print "Last $lf $mod\n" ; } $now = time() ; $date = gmtime() ; $s = system("wget -t 2 -q -nv --save-headers -O history.$now --header=\"If-Modified-Since: $mod\" $url") ; if ($s) { unlink("history.$now") ; exit ; } @stat = stat($allh) ; if ((time() - $stat[9]) > $maxage) { open (OUT,">>$allh") or die ; $wout = 1; } open (IN,"history.$now") or die ; while () { unless (/([\d]+),([\d]+),([\d]+),([\d:]+),([\w]+),([\w]+),([\d\.]+),([\d\.]+),([\d\-]+),([\d\-]+),([\d\-]+)/) { next ; } $y = $1 ; $m = $2 ; $d = $3 ; $hms = $4 ; # $ssrc = $5 ; $rssrc = $6 ; $rx = $7 ; $tx = $8 ; $loss = $9 ; $rtt = $10 ; $jitter = $11 ; $time = "$y-$m-$d-$hms" ; if ($time0 && $time ne $time0) { last ; } $nrx = &resolve($rx) ; $ntx = &resolve($tx) ; if ($wout) { print OUT $_ ; } $time0 = $time ; $name{$tx} = $ntx ; $sname{$tx} = &get_sortname($ntx) ; $name{$rx} = $nrx ; $sname{$rx} = &get_sortname($nrx) ; $loss{$tx}{$rx} = $loss ; $rtt{$tx}{$rx} = $rtt ; $jitter{$tx}{$rx} = $jitter ; } foreach $type ('loss','rtt','jitter') { open (OUT,">$type.html") or die ; $ns = $nr = 0 ; print OUT<Multicast Beacon Graph - $type

Beacon Graphs - $type

Data is from NCSA central server previous history file, retrieved at $date UTC.

(The code for this page is available here)

Click on value for a PNG graph of the last 10 hours. (graph may take some time to appear, depending on number of beacons)
Click on the "*" for a dialogue (SVG plot, multi-day etc.) (graph may take longer to appear, depending on size of archived history)
Time axis on graphs is Central Zone (CST/CDT). Values of -1 correspond to "NA" (no data).
Node names are derived from IP address and may not match hostnames sent to central server.

Graphs of: Central Loss - Central RTT - Central Jitter

EOT foreach $S ( sort { $sname{$a} cmp $sname{$b} } keys %name) { $ns++ ; print OUT "" ; } print OUT "\n" ; foreach $R ( sort { $sname{$a} cmp $sname{$b} } keys %name) { $nr++ ; print OUT "" ; foreach $S ( sort { $sname{$a} cmp $sname{$b} } keys %name) { if ($type eq 'loss') { $value = $loss{$S}{$R} ; } elsif ($type eq 'rtt') { $value = $rtt{$S}{$R} ; } else { $value = $jitter{$S}{$R} ; } if ($value == -1) { $value = 'NA' ; } if ($S eq $R) { print OUT " EOT } print OUT "\n" ; } print OUT<
Andrew Daviel
TRIUMF
EOT close(OUT) ; } exit ; sub get_sortname() { my $startname = shift(@_); #my $ssrc = shift(@_); #my $sortname = &reverse_name($startname) . "|" . $ssrc; my $sortname = &reverse_name($startname) ; return $sortname; } # get_sortname sub reverse_name() { my $startwith = shift(@_); my $kk; my $reverse_tld; # Split current name into component pieces my @tld = split /\./, $startwith; foreach $kk (reverse @tld) { # reverse the pieces for sorting $reverse_tld .= $kk . "."; # concat $reverse_tld with next chunk and a "." } chop $reverse_tld; # Whack trailing "." return ($reverse_tld); # Send back the reversed name } # reverse_name sub resolve { my @oct = split(/\./, $_[0]); my $name ; if ( $oct[0] == 255 or $oct[1] == 255 or $oct[2] == 255 or $oct[3] == 255 # broadcast or $oct[3] == 0 # broadcast or ($oct[0] == 169 && $oct[1] == 254) # microsoft autonet ) { return $_[0] ; } else { eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 2 ; $name = gethostbyaddr(pack('C4',@oct),2); alarm 0 ; } ; if ($@) { die unless $@ eq "alarm\n"; # propagate unexpected errors } unless ($name) { $name = $_[0] ; } } return $name; } sub bymod { my @stat ; my $moda ; my $modb ; @stat = stat($a) ; $moda = $stat[9] ; @stat = stat($b) ; $modb = $stat[9] ; return ( $moda <=> $modb) ; }
#NameIP AddressS$ns
R$nr$name{$R}$R" ; } elsif ( $value eq 'NA') { print OUT "" ; } else { print OUT "" ; } print OUT<$value *