#!/usr/bin/perl -w

use strict;

print "Content-Type: text/html";
print "\r\n\r\n";

if (exists $ENV{REQUEST_URI}) {
  print "<meta http-equiv=\"refresh\" content=\"10;$ENV{REQUEST_URI}\">";
}

my $oldTime = 0;
my $time = time;
my %classes;

if (open(F, "/tmp/tc2html.last")) {
  $oldTime = <F>;
  while (<F>) {
    chomp;
    my @a = split;
    $classes{$a[0]}->{oldBytes} = $a[1];
    $classes{$a[0]}->{oldPackets} = $a[2];
    $classes{$a[0]}->{oldDropped} = $a[3];
    $classes{$a[0]}->{oldOverlimits} = $a[4];
  }
  close(F);
}

open(F, "/sbin/tc -s class ls dev eth0 |");

my $class = undef;

while(<F>) {
  if (/^class [^ ]* ([^ ]*) (?:parent ([^ ]*) )?.*rate ([^ ]*)/) {
    $classes{$1}->{name} = "$1: $3";
    $classes{$1}->{children} = [];
    if (defined $2) {
      $classes{$1}->{parent} = $classes{$2};
      push @{$classes{$2}->{children}}, $classes{$1};
    }
    #print "$1 $3 " . (defined $2 ? $2 : "no parent") . "\n";
    $class = $classes{$1};
  } elsif (/^ Sent ([^ ]*) bytes ([^ ]*) pkts \(dropped ([^ ]*), overlimits ([^ ]*)\)/) {
    $class->{bytes} = $1;
    $class->{packets} = $2;
    $class->{dropped} = $3;
    $class->{overlimit} = $4;
  }
}

close(F);

print "<html>\n";
makeTable($classes{"1:"});
print "</html>\n";

open(F, "> /tmp/tc2html.last");
print F "$time\n";
foreach my $class (keys %classes) {
  print F join(" ", $class,
	       $classes{$class}->{bytes},
	       $classes{$class}->{packets},
	       $classes{$class}->{dropped},
	       $classes{$class}->{overlimit}), "\n"
}
close(F);

sub makeTable {
  my ($node) = @_;
  print "<table border=\"1\">\n";
  print "<tr><td>" . $node->{name} . "\n";
  if ($oldTime) {
    my $delta = $time - $oldTime + 0.1;
    printf " %.0f Kbit/sec\n", ($node->{bytes} - $node->{oldBytes}) / $delta * 8 / 1000;
  }
  print "<br>bytes: " . $node->{bytes} . ", " , $node->{packets} . " packets, ";
  print "dropped " . $node->{dropped} . ", overlimit " . $node->{overlimit} . "\n";
  foreach my $child (@{$node->{children}}) {
    makeTable($child);
  }
  print "</table>\n";
}
