#!/usr/bin/perl -w # # $Id: density.pl,v 1.2 2002/10/23 10:36:08 kjc Exp $ # # usage: # density.pl [-t '[type]'] file [file2...] # # a script to create a traffic density graph in the png format. # this version works only with IPv4 addresses # it assumes that the input data size is 720 points: # 5 sec x 720 = 1 hour # 2 min x 720 = 24 hours # 1 hour x 720 = 30 days # use Socket; use GD; $pngfile = "density.png"; $type = "[dst address]"; $xsize = 720; $ysize = 512; $xoff = 50; $yoff = 20; $x = $xoff - 1; # specified number of colors are assigned between $minval and $maxval $numcolors = 64; $maxval = 1.0; $minval = 0.0001; $minlog = log($minval) / log(10); $maxlog = log($maxval) / log(10); sub initcolors { my ($i, $v, $r, $g, $b); for ($i = 0; $i < $numcolors; $i++) { $v = $i / $numcolors; if ($v < 0.2) { $r = 0.0; $g = 0.0; $b = 255.0 * $v/0.2; } elsif ($v < 0.4) { $r = 0.0; $g = 255.0 * ($v - 0.2)/0.2; $b = 255.0; } elsif ($v < 0.6) { $r = 0.0; $g = 255.0; $b = 255.0 - 255.0 * ($v - 0.4)/0.2; } elsif ($v < 0.8) { $r = 255.0 * ($v - 0.6)/0.2; $g = 255.0; $b = 0.0; } else { $r = 255.0; $g = 255.0 - 255.0 * ($v - 0.8)/0.2; $b = 0.0; } $colors[$i] = $im->colorResolve($r, $g, $b); if ($colors[$i] < 0) { warn "can't alloc color\n"; } } } # create a new image $im = new GD::Image($xsize + 3 * $xoff, $ysize + 4 * $yoff); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); initcolors(); # put background image $im->filledRectangle(0, 0, $xsize + 3 * $xoff - 1, $ysize + 4 * $yoff ,$white); $im->filledRectangle($xoff, $yoff, $xoff + $xsize, $yoff + $ysize, $black); # # this version works only with IPv4 addresses # sub addr2key { my $addr = shift; my $ip = inet_aton($addr); my ($a, $b, $c, $d) = unpack('C4', $ip); $key = ($a << 24) + ($b << 16) + ($c << 8) + $d; return $key; } $addrdst = 0; $start = ""; $start2 = ""; $end = ""; $end2 = ""; while ($file = shift @ARGV) { if ($file eq "-t") { $type = shift @ARGV; next; } open(FOO, "< $file"); while() { if (/^\%!AGURI/) { $x++; if ($x > $xoff + $xsize) { warn "too many data input"; last; } next; } if ($start eq "") { if (/^\%\%StartTime:.*\((\d\d\d\d\/\d\d\/\d\d) (\d\d:\d\d:\d\d)\)/) { $start = $1; $start2 = $2; } } if (/^\%\%EndTime:.*\((\d\d\d\d\/\d\d\/\d\d) (\d\d:\d\d:\d\d)\)/) { $end = $1; $end2 = $2; } if (/^[\%\n]/) { next; } if (/^(\[.*\])/) { if ($1 eq $type) { $addrdst = 1; } else { $addrdst = 0; } next; } next if ($addrdst == 0); if (/\s*(\S+)\s+\d+\s+\(.*?(\d+\.\d+)\%\)/) { $addr = $1; $cnt = $2 / 100.0; if ($addr =~ /(.*)\/(\d+)/) { $addr = $1; $pfxlen = $2; } else { $pfxlen = 32; } $key = addr2key($addr); $y2 = $yoff + $ysize - $ysize * $key / 2 ** 32; $y1 = $y2 - $ysize / 2 ** $pfxlen; # # compute density index: # density = cnt / size # dindex = cnt / sqrt(size) # $n = (32.0 - $pfxlen) / 2.0; $didx = $cnt / 2**$n; $didx = log($didx) / log(10); if ($didx >= $maxlog) { $i = $numcolors - 1; } elsif ($didx <= $minlog) { $i = 0; } else { $i = ($didx - $minlog) / ($maxlog - $minlog) * $numcolors; } $color = $colors[$i]; if ($color != -1 && $color != 0) { $im->line($x, $y1, $x, $y2, $color); } } } close(FOO); } # # put labels (XXX: positions are hard coded) # $im->string(gdMediumBoldFont, $xoff + $xsize/2, $yoff*3/2 + $ysize, "time", $black); $im->stringUp(gdMediumBoldFont, $xoff/2, $yoff + $ysize/2, "address space", $black); $im->string(gdSmallFont, $xoff, $yoff + $ysize + 8, $start2, $black); $im->string(gdSmallFont, $xoff, $yoff + $ysize + 24, $start, $black); $im->string(gdSmallFont, $x - 36, $yoff + $ysize + 8, $end2, $black); $im->string(gdSmallFont, $x - 36, $yoff + $ysize + 24, $end, $black); $im->string(gdSmallFont, 16, $yoff, "2**32", $black); $im->string(gdSmallFont, 16, $yoff + $ysize - 10, "2**0", $black); $x = $xoff + $xsize + 10; $y1 = $yoff + 20; $didx = 1.0; $label = 1.0; while ($didx >= $minval) { $idx = log($didx) / log(10); if ($idx >= $maxlog) { $i = $numcolors - 1; } elsif ($idx <= $minlog) { $i = 0; } else { $i = ($idx - $minlog) / ($maxlog - $minlog) * $numcolors; } $y2 = $y1 + 4; $im->filledRectangle($x, $y1, $x + 10, $y2, $colors[$i]); if ($didx <= $label) { $im->line($x + 10 - 2, $y1, $x + 10 + 2, $y1, $black); $im->string(gdSmallFont, $x + 16, $y1 - 6, $label, $black); $label = $label * 0.1; } $y1 = $y2; $didx = $didx * 0.9; } $im->rectangle($x, $yoff + 20, $x + 10, $y2, $black); open(FOO, "> $pngfile"); # Convert the image to PNG and print it on standard output print FOO $im->png; close(FOO); exit 0;