]> git.sesse.net Git - nms/commitdiff
Merge with space:/root/nms
authorEirik Nygaard <eirikn@space>
Wed, 4 Apr 2007 10:25:19 +0000 (12:25 +0200)
committerEirik Nygaard <eirikn@space>
Wed, 4 Apr 2007 10:25:19 +0000 (12:25 +0200)
31 files changed:
clients/ciscong.pl
clients/ciscong2.pl [new file with mode: 0644]
clients/dhcptail.pl
clients/snmpfetch.pl
config/make-port-config.pl
mbd/mbd.pl
web/bg07.png
web/dhcpkart.pl
web/ext/comparegraph.cpp [new file with mode: 0644]
web/ext/flowpusher.cpp [new file with mode: 0644]
web/ext/flowpusher.h [new file with mode: 0644]
web/ext/flowutil.cpp [new file with mode: 0644]
web/ext/flowutil.h [new file with mode: 0644]
web/ext/graph.cpp [new file with mode: 0755]
web/ext/graph.h
web/ext/graphall.cpp [new file with mode: 0644]
web/ext/showswitch.pl
web/ext/totalcount.cpp [new file with mode: 0644]
web/ext/totalgraph.cpp [new file with mode: 0644]
web/make-switches.pl
web/nettkart-telnet.pl
web/nettkart-text.pl
web/nettkart-web.pl
web/nettkart.pl
web/overlay.pl
web/portkart.pl
web/sendsms.pl
web/smanagement.pl
web/sshow.pl
web/stempmap.pl
web/streaming.pl

index 89ad6d58609151686f9f7e819b656aa78d991b3a..76ec4759102a2d9556f1352ec28bc68ec8230d46 100644 (file)
@@ -12,12 +12,14 @@ use Net::Ping;
 
 use Data::Dumper;
 
-#my $patchlist = "/root/patchlist.txt";
-#my $switches = "/root/switches.txt";
+my $patchlist = "/root/patchlist.txt";
+my $switches = "/root/switches.txt";
 #my $patchlist = "/home/eirikn/patchlist.txt.eirik";
 #my $switches = "/home/eirikn/switches.txt.eirik";
-my $patchlist = "/root/patchlist.txt.d01-1-2";
-my $switches = "/root/switches.txt.d01-1-2";
+#my $patchlist = "/root/patchlist.txt.d05";
+#my $switches = "/root/switches.txt.d05";
+
+open LOG, ">>/tmp/zyxel.could.not.connect" or die "Could not open log";
 
 
 BEGIN {
@@ -69,7 +71,12 @@ sub do_distro {
 
        my $ios = Net::Telnet::Cisco->new(Host => $dip,
                        Errmode => 'return',
-                       Prompt => '/[^\s\(]+(\([^\(]\)){0,1}[#>]/');
+                       Prompt => '/\S+[#>]/');
+#                      Prompt => '/[^\s\(]+(\([^\(]\)){0,1}[#>]/');
+       if (!defined($ios)) {
+               print "Could not connect to $dip";
+               return;
+       }
        $ios->login($nms::config::ios_user, $nms::config::ios_pass);
        $ios->enable;
 
@@ -100,8 +107,9 @@ sub do_distro {
        printf "Waiting for zyxel to come up...\n";
        my $counter = 0;
        while (1) {
-               if ($counter > 180) {
-                       print "Waiting for zyxel on $dip:$vlan timed out, wanted to set ip: $newip";
+               if ($counter > 6) {
+                       print "Waiting for zyxel on $dip:$vlan timed out, wanted to set ip: $newip\n";
+                       print LOG "Could not connect to $switchname\n";
                        stop_vlan($ios, $vlan);
                        return;
                }
@@ -158,6 +166,9 @@ sub first_run {
        open(PATCHLIST, $patchlist) or die "Unable to open patchlist";
        while (<PATCHLIST>) {
                my ($switch, $distro, $port) = split;
+
+               #print "Testing: ".$ARGV[1]." $switch\n";
+               next if (defined($ARGV[1]) and $ARGV[1] ne $switch);
                
                print "First run...\n";
                my ($row, $place, $ipnet, $vlan, $ip, $dip) = switch_info($switch, $distro, $port);
@@ -191,9 +202,15 @@ sub verify_run {
                printf "Checking if zyxel is up $dip:$vlan $ip...\n";
                my $counter = 0;
                while (1) {
-                       if ($counter > 10) {
+                       if ($counter > 4) {
                                print "No answer from $dip:$vlan $ip, trying to route it up\n";
                                do_distro($dip, $ip, $vlan, $switch);
+                               my $pid = fork();
+                               if ($pid == 0) {
+                                       sleep 100;
+                                       system("perl ./ciscong2.pl $switch");
+                                       exit 0;
+                               }
                                last;
                        }
                        last if $p->ping($ip);
@@ -215,5 +232,6 @@ else {
        verify_run();
 }
 
+close(LOG);
 
 
diff --git a/clients/ciscong2.pl b/clients/ciscong2.pl
new file mode 100644 (file)
index 0000000..b8c33b2
--- /dev/null
@@ -0,0 +1,146 @@
+#!/usr/bin/perl
+#
+#
+
+use warnings;
+use strict;
+
+use lib '../include';
+
+use Net::Telnet::Cisco;
+use Net::Ping;
+
+use Data::Dumper;
+
+my $patchlist = "/root/patchlist.txt";
+my $switches = "/root/switches.txt";
+#my $patchlist = "/home/eirikn/patchlist.txt.eirik";
+#my $switches = "/home/eirikn/switches.txt.eirik";
+#my $patchlist = "/root/patchlist.txt.d05";
+#my $switches = "/root/switches.txt.d05";
+
+open LOG, ">>/tmp/zyxel.could.not.connect2" or die "Could not open log";
+
+
+BEGIN {
+       require "../include/config.pm";
+       eval {
+               require "../include/config.local.pm";
+       };
+}
+
+sub ios_getroute {
+       my ($t, $net) = @_;
+
+       $t->cmd("show ip route".($net ? " $net" : '')) or return 0;;
+       
+       return 1;
+}
+
+#my $ios_server = "noc-gw.net.tg07.gathering.org";
+#my $vlannumber = 16;
+
+#my $ios = nms::ios_connect($ios_server, $nms::config::ios_user, $nms::config::ios_pass)
+#      or die "Unable to connect to cisco";
+
+
+sub do_distro {
+       my ($dip, $newip, $net, $switchname) = @_;
+
+       my $ios = Net::Telnet::Cisco->new(Host => $dip,
+                       Errmode => 'return',
+                       Prompt => '/(\S+[#>])|(es-3024>)/');
+#                      Prompt => '/[^\s\(]+(\([^\(]\)){0,1}[#>]/');
+       if (!defined($ios)) {
+               print "Could not connect to $dip";
+               return;
+       }
+       $ios->login($nms::config::ios_user, $nms::config::ios_pass);
+       $ios->enable;
+
+#nms::ios_enable($ios);
+#$ios->cmd();
+#nms::ios_getroute($ios, "192.168.1.0");
+#$ios->cmd("");
+
+#nms::ios_close($ios);
+
+# Disable paging
+       $ios->cmd("terminal length 0");
+
+#my @routes = $ios->cmd("show ip route");
+
+
+       $ios->print("telnet $newip");
+       $ios->waitfor("/Password:/");
+       print "Hei\n";
+       $ios->cmd($nms::config::zyxel_password);
+
+       my ($first, $second, $third, $fourth) = split(/\./, $net);
+       my $gw = "$first.$second.$third.".(int($fourth)+1);
+       $ios->cmd("ip route drop 192.168.1.0/24");
+       $ios->cmd("ip route add default $gw");
+       $ios->cmd("exit");
+
+       #system("perl ./zyxelng.pl 192.168.1.1 $newip $switchname");
+
+####
+
+       $ios->close();
+
+}
+
+## Collect switch ips
+
+my %switchips;
+
+open(SWITCHES, $switches) or die "Unable to open switches";
+while(<SWITCHES>) {
+       my ($ip, $net, $name) = split;
+
+       if ($name =~ /e\d+-\d/) {
+               die "We only support /26 nets for now you wanted $net" if ($net ne "26");
+               $switchips{$name} = $ip;
+       }
+}
+close(SWITCHES);
+
+sub switch_info {
+       my ($switch, $distro, $port) = @_;
+
+       $switch =~ /e(\d+)-(\d)/;
+       my ($row, $place) = ($1, $2);
+       my $ipnet = $switchips{$switch};
+       my $vlan = $row . $place;
+       my ($first, $second, $third, $fourth) = split(/\./, $ipnet);
+       my $ip = "$first.$second.$third.".(int($fourth)+2);
+       my $dip = $distro.".net.tg07.gathering.org";
+
+       return ($row, $place, $ipnet, $vlan, $ip, $dip);
+}
+
+sub first_run {
+
+       open(PATCHLIST, $patchlist) or die "Unable to open patchlist";
+       while (<PATCHLIST>) {
+               my ($switch, $distro, $port) = split;
+
+               next if (defined($ARGV[0]) and $ARGV[0] ne $switch);
+               
+               print "First run...\n";
+               my ($row, $place, $ipnet, $vlan, $ip, $dip) = switch_info($switch, $distro, $port);
+               print "Switch: $switch, Distro: $distro, vlan: $vlan\n";
+               print "Ip net: $ipnet\n";
+               print "Ip: $ip\n";
+
+               do_distro($dip, $ip, $ipnet, $switch);
+#      my ($dip, $newip, $vlan) = @_;
+       }
+       close(PATCHLIST);
+}
+
+first_run();
+
+close(LOG);
+
+
index a1e1c624fa0511a11677980020bf9f2adfdf1a11..6a529de940caa23aa252afe5e4b5972f6c41c754 100755 (executable)
@@ -7,7 +7,7 @@ use strict;
 use warnings;
 
 # WARNING: CHANGE THIS! :-P
-my $year = 2006;
+my $year = 2007;
 
 my %months = (
        Jan => 1,
@@ -31,7 +31,7 @@ while (<>) {
 
        if (!defined($dbh) || !$dbh->ping) {
                $dbh = nms::db_connect();
-               $q = $dbh->prepare("UPDATE dhcp SET last_ack=? WHERE inet ? << network AND ( last_ack < ? OR last_ack IS NULL )")
+               $q = $dbh->prepare("UPDATE dhcp SET last_ack=? WHERE ?::inet << network AND ( last_ack < ? OR last_ack IS NULL )")
                        or die "Couldn't prepare query";
        }
 
index bc64b60fb97cd737d56f546e305dc347eb2a48ec..74f3aa5b7da5b3aac1d8cfd411651e0a52187c01 100755 (executable)
@@ -144,7 +144,7 @@ while (1) {
                        print $avgtemp." avgtemp\n";
                        $qtemppoll->execute($switch->{'switch'},
                                        $avgtemp) or die "Could not exec qtemppoll";
-                } elsif ($switch->{'switchtype'} eq 'cisco6509') {
+                } elsif ($switch->{'switchtype'} eq 'cisco6509' && 0) {
                        # fetch load data for the entities
                        for my $i (1..5) {
                                # find the ID
@@ -269,41 +269,41 @@ sub mylog {
        printf STDERR "[%s] %s\n", $time, $msg;
 }
 
-sub switch_exec {
-       my ($cmd, $conn) = @_;
-
-       # Send the command and get data from switch
-#      $conn->dump_log(*STDOUT);
-       my @data = $conn->cmd($cmd);
-       my @lines = ();
-       foreach my $line (@data) {
-               # Remove escape-7 sequence
-               $line =~ s/\x1b\x37//g;
-               push @lines, $line;
-       }
-
-       return @lines;
-}
-
-sub switch_connect {
-       my ($ip) = @_;
-
-       my $conn = new Net::Telnet(     Timeout => $timeout,
-                                       Dump_Log => '/tmp/dumplog-tempfetch',
-                                       Errmode => 'return',
-                                       Prompt => '/es-3024|e(\-)?\d+\-\dsw>/i');
-       my $ret = $conn->open(  Host => $ip);
-       if (!$ret || $ret != 1) {
-               return (0);
-       }
-       # XXX: Just send the password as text, I did not figure out how to
-       # handle authentication with only password through $conn->login().
-       #$conn->login(  Prompt => '/password[: ]*$/i',
-       #              Name => $password,
-       #              Password => $password);
-       my @data = $conn->cmd($password);
-       # Get rid of banner
-       $conn->get;
-       return $conn;
-}
+#sub switch_exec {
+#      my ($cmd, $conn) = @_;
+#
+#      # Send the command and get data from switch
+##     $conn->dump_log(*STDOUT);
+#      my @data = $conn->cmd($cmd);
+#      my @lines = ();
+#      foreach my $line (@data) {
+#              # Remove escape-7 sequence
+#              $line =~ s/\x1b\x37//g;
+#              push @lines, $line;
+#      }
+#
+#      return @lines;
+#}
+
+#sub switch_connect {
+#      my ($ip) = @_;
+#
+#      my $conn = new Net::Telnet(     Timeout => $timeout,
+#                                      Dump_Log => '/tmp/dumplog-tempfetch',
+#                                      Errmode => 'return',
+#                                      Prompt => '/es-3024|e(\-)?\d+\-\dsw>/i');
+#      my $ret = $conn->open(  Host => $ip);
+#      if (!$ret || $ret != 1) {
+#              return (0);
+#      }
+#      # XXX: Just send the password as text, I did not figure out how to
+#      # handle authentication with only password through $conn->login().
+#      #$conn->login(  Prompt => '/password[: ]*$/i',
+#      #              Name => $password,
+#      #              Password => $password);
+#      my @data = $conn->cmd($password);
+#      # Get rid of banner
+#      $conn->get;
+#      return $conn;
+#}
 
index ee75cab1b2e4e1b693d32bf07858f1027ce76b9c..893d4f406c1b6256a8cf71eaec007b70b4ac99d4 100755 (executable)
@@ -26,6 +26,7 @@ while (<PATCHLIST>) {
        }
 
        my $vlan = "$row$switch";
+       my $ipv6 = sprintf "F%02u%u", $row, $switch;
 
        $distros{$distro} .= <<"EOF";
 vlan $vlan
@@ -39,7 +40,9 @@ interface vlan $vlan
   ip helper-address 87.76.254.2
   no ip proxy-arp
   ip access-group great-wall-of-tg in
-  ipv6 address 2001:16D8:FFFF:$vlan::1/64
+  ipv6 address 2001:16D8:FFFF:${ipv6}::1/64
+  ip igmp version 3
+  ip pim sparse-mode
   no shutdown
 !
  
@@ -52,7 +55,6 @@ interface $port
  spanning-tree portfast
  spanning-tree bpduguard enable
 
- ip igmp snooping
  storm-control broadcast level 2
  no shutdown
 !
index cbb1237c9d6d49c379c701d6a84db7a6b929f0ba..7fcc8d8100a3a67e6e2f41bd763d797c684e4a06 100644 (file)
@@ -16,6 +16,8 @@ sub fhbits {
        return $bits;
 }
 
+open LOG, ">>", "mbd.log";
+
 my @ports = mbd::find_all_ports();
 
 # Open a socket for each port
@@ -62,6 +64,8 @@ while (1) {
                        last;
                }
 
+               print LOG "$dport $size $pass\n";
+
                if (!$pass) {
                        print "$dport, $size bytes => filtered\n";
                }
index c5c39604edb90fc382b6b2d89b3c5a8a9fe1aaa7..6c367a6923486e4483a5dd007eb07688d84aef03 100644 (file)
Binary files a/web/bg07.png and b/web/bg07.png differ
index 0cc0e6772398b7ab1c8cc868cde97fe392ecbf22..e14e0c5a8bbfa356cf7811fee777f7023400d093 100755 (executable)
@@ -12,11 +12,11 @@ my $maxtimeout = $greentimeout*9;
 my $dbh = nms::db_connect();
 
 GD::Image->trueColor(1);
-$img = GD::Image->new('bg2.png');
+$img = GD::Image->new('bg07.png');
 
 my $blk = $img->colorResolve(0, 0, 0);
 
-$img->string(gdMediumBoldFont,0,0,"TG05 - DHCP-lease status",$blk);
+$img->string(gdMediumBoldFont,0,0,"TG07 - DHCP-lease status",$blk);
 $img->string(gdSmallFont,0,20,"Last recieved DHCP-request",$blk);
 
 # first  1/5: green (<30 min)
@@ -70,7 +70,7 @@ $dbh->disconnect;
 
 if (!defined($ARGV[0])) {
        print $cgi->header(-type=>'image/png',
-                          -refresh=>'10; http://nms.tg05.gathering.org/dhcpkart.pl');
+                          -refresh=>'10; http://nms.tg07.gathering.org/dhcpkart.pl');
 }
 print $img->png;
 
diff --git a/web/ext/comparegraph.cpp b/web/ext/comparegraph.cpp
new file mode 100644 (file)
index 0000000..5beb37d
--- /dev/null
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include <pqxx/pqxx>
+#include "graph.h"
+#include "flowpusher.h"
+#include "flowutil.h"
+
+namespace pqxx {
+       template<>
+       void from_string<long long>(const char *from, long long &to)
+       {
+               to = atoll(from);
+       }
+}
+                                               
+
+int main(int argc, char **argv)
+{
+       int width = 1000, height = 500;
+       pqxx::connection conn05("dbname=nms05 host=localhost user=nms password=seesahS4");
+       pqxx::connection conn("dbname=nms host=localhost user=nms password=seesahS4");
+
+       std::vector<flow_element> flow, total_flow, total_flow05;
+       FlowPusher fp(flow);
+       int last_port = -1;
+       
+       mallopt(M_TRIM_THRESHOLD, -1);
+       
+       int num_total = 0;
+       pqxx::work t(conn, "fetch_all");
+       pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where ((switchtype='es3024' and port < 25) or (switchtype='summit400' and port > 1)) order by switch,port,time", "fetch_all", 500);
+       
+       for ( ;; ) {
+               pqxx::result res;
+               
+               cstream >> res;
+               if (res.empty()) 
+                       break;
+
+               for (unsigned i = 0; i < res.size(); ++i) {
+                       int port = res[i][0].as<int>();
+                       double x = res[i][1].as<double>();
+                       unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+                       if (port != last_port) {
+                               if (last_port != -1) {
+                                       total_flow = sum_flows(total_flow, flow);
+                                       fprintf(stderr, "%u (%u)\n", last_port, ++num_total);
+                               }
+
+                               // reset
+                               last_port = port;
+                               fp.reset(x, y1, y2);
+                               continue;
+                       }
+
+                       fp.push(x, y1, y2);
+               }
+       }
+       total_flow = sum_flows(total_flow, flow);
+
+       unsigned long long min_y = 0;
+       unsigned long long max_y = 10000000;
+
+       for (unsigned i = 0; i < total_flow.size(); ++i) {
+               flow_element fe = total_flow[i];
+               
+               min_y = std::min(min_y, fe.y1);
+               max_y = std::max(max_y, fe.y1);
+               
+               min_y = std::min(min_y, fe.y2);
+               max_y = std::max(max_y, fe.y2);
+       }
+
+       printf("06 done.\n");
+       
+       num_total = 0;
+       pqxx::work t05(conn05, "fetch_all");
+       pqxx::icursorstream::icursorstream cstream05(t05, "select port,extract(epoch from (time + interval '1 year 20 days')) as time,bytes_in,bytes_out from polls natural join switches where (switchtype='es3024' and port < 25) order by switch,port,time", "fetch_all", 500);
+
+       last_port = -1;
+       
+       for ( ;; ) {
+               pqxx::result res;
+       
+               cstream05 >> res;
+               if (res.empty()) 
+                       break;
+       
+               for (unsigned i = 0; i < res.size(); ++i) {
+                       int port = res[i][0].as<int>();
+                       double x = res[i][1].as<double>();
+                       unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+                       if (port != last_port) {
+                               if (last_port != -1) {
+                                       total_flow05 = sum_flows(total_flow05, filter_flow(flow));
+                                       fprintf(stderr, "TG05: %u (%u)\n", last_port, ++num_total);
+                               }
+
+                               // reset
+                               last_port = port;
+                               fp.reset(x, y1, y2);
+                               continue;
+                       }
+
+                       fp.push(x, y1, y2);
+               }
+       }
+       total_flow05 = sum_flows(total_flow05, filter_flow(flow));
+
+       for (unsigned i = 0; i < total_flow05.size(); ++i) {
+               flow_element fe = total_flow05[i];
+               
+               min_y = std::min(min_y, fe.y1);
+               max_y = std::max(max_y, fe.y1);
+               
+               min_y = std::min(min_y, fe.y2);
+               max_y = std::max(max_y, fe.y2);
+       }
+       
+       double min_x = std::min(total_flow[0].x, total_flow05[0].x);
+       double max_x = std::max(total_flow[total_flow.size() - 1].x, total_flow05[total_flow05.size() - 1].x);
+       
+       graph *g = mygraph_new(width, height);
+       g = mygraph_make_graph(g, min_x, max_x, min_y, max_y, 5);
+
+       // PLOT FIRST
+       int *x = new int[total_flow.size()];
+       unsigned long long *y1 = new unsigned long long[total_flow.size()];
+       unsigned long long *y2 = new unsigned long long[total_flow.size()];
+
+       // de-interleave
+       for (unsigned i = 0; i < total_flow.size(); ++i) {
+               x[i] = total_flow[i].x;
+               y1[i] = total_flow[i].y1;
+               y2[i] = total_flow[i].y2;
+       }
+
+       mygraph_plot_series(g, x, y1, total_flow.size(), 1.0f, 0.0f, 0.0f);
+       mygraph_plot_series(g, x, y2, total_flow.size(), 0.0f, 0.0f, 1.0f);
+
+       delete[] x;
+       delete[] y1;
+       delete[] y2;
+       
+       // PLOT SECOND
+       x = new int[total_flow05.size()];
+       y1 = new unsigned long long[total_flow05.size()];
+       y2 = new unsigned long long[total_flow05.size()];
+
+       // de-interleave
+       for (unsigned i = 0; i < total_flow05.size(); ++i) {
+               x[i] = total_flow05[i].x;
+               y1[i] = total_flow05[i].y1;
+               y2[i] = total_flow05[i].y2;
+       }
+
+       mygraph_plot_series(g, x, y1, total_flow05.size(), 0.0f, 1.0f, 0.0f);
+       mygraph_plot_series(g, x, y2, total_flow05.size(), 1.0f, 0.0f, 1.0f);
+
+       delete[] x;
+       delete[] y1;
+       delete[] y2;
+       
+       mygraph_to_file(g, "comparative.png");
+       mygraph_cleanup(g);
+}
diff --git a/web/ext/flowpusher.cpp b/web/ext/flowpusher.cpp
new file mode 100644 (file)
index 0000000..7bcbf6a
--- /dev/null
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include "flowpusher.h"
+
+FlowPusher::FlowPusher(std::vector<flow_element> &flow) : flow(flow)
+{
+}
+
+void FlowPusher::find_diff(double x, double &prev_x, unsigned long long y1, unsigned long long prev_y1, unsigned long long y2, unsigned long long prev_y2,
+       unsigned long long &yf1, unsigned long long &yf2)
+{
+       // Heuristics: if last reading was more than ten minutes away, and both
+       //             readings went down from last reading, we assume the counters
+       //             were zeroed. If not, we assume wraparound.
+       bool over_10mins = (x - prev_x >= 600);
+       bool y1_wrapped = ((prev_y1 == 0 && y1 == 0) || y1 < prev_y1);
+       bool y2_wrapped = ((prev_y2 == 0 && y2 == 0) || y2 < prev_y2);
+       bool both_zero = (y1 == 0 && y2 == 0);  
+       bool any_wide = (prev_y1 > 4294967296ULL || prev_y2 > 4294967296ULL);
+       
+       if ((over_10mins && (y1_wrapped || y2_wrapped)) || both_zero || (any_wide && (y1_wrapped || y2_wrapped))) {
+               prev_y1 = 0;
+               prev_y2 = 0;
+
+               // our best estimate for when it was zeroed :-)
+               prev_x = (prev_x + x) / 2;
+       }
+
+       if (y1 < prev_y1) {
+               yf1 = (unsigned long long)(((unsigned long long)y1 + 4294967296ULL) - prev_y1);
+       } else {
+               yf1 = (unsigned long long)(y1 - prev_y1);
+       }
+       
+       if (y2 < prev_y2) {
+               yf2 = (unsigned long long)(((unsigned long long)y2 + 4294967296ULL) - prev_y2) / (x - prev_x);
+       } else {
+               yf2 = (unsigned long long)(y2 - prev_y2);
+       }
+}
+
+void FlowPusher::push(double x, unsigned long long y1, unsigned long long y2)
+{
+       unsigned long long yf1, yf2;
+
+       find_diff(x, prev_x, y1, prev_y1, y2, prev_y2, yf1, yf2);
+       yf1 /= (x - prev_x);
+       yf2 /= (x - prev_x);
+               
+       flow_element fe;
+       fe.x = unsigned((prev_x + x)*0.5);
+       fe.y1 = yf1;
+       fe.y2 = yf2;
+
+       min_x = std::min(min_x, fe.x);
+       max_x = std::max(max_x, fe.x);
+       
+       min_y = std::min(min_y, fe.y1);
+       max_y = std::max(max_y, fe.y1);
+       
+       min_y = std::min(min_y, fe.y2);
+       max_y = std::max(max_y, fe.y2);
+
+       flow.push_back(fe);
+
+       prev_x = x;
+       prev_y1 = y1;
+       prev_y2 = y2;
+}
+
+void FlowPusher::reset(double x, unsigned long long y1, unsigned long long y2)
+{
+       flow.resize(0);
+       
+       min_y = 0;
+       max_y = 10000000;
+       
+       max_x = time(NULL);
+       min_x = max_x - 86400;
+       
+       prev_x = x;
+       prev_y1 = y1;
+       prev_y2 = y2;
+}
diff --git a/web/ext/flowpusher.h b/web/ext/flowpusher.h
new file mode 100644 (file)
index 0000000..a16f7b1
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _FLOWPUSHER_H
+#define _FLOWPUSHER_H 1
+
+struct flow_element {
+       unsigned x;
+       unsigned long long y1, y2;
+};
+
+class FlowPusher
+{
+private:
+       std::vector<flow_element> &flow;
+       unsigned min_x, max_x;
+       long long unsigned min_y, max_y;
+       double prev_x;
+       unsigned long long prev_y1, prev_y2;
+       
+public:
+       FlowPusher(std::vector<flow_element> &flow);
+       void reset(double x, unsigned long long y1, unsigned long long y2);
+       void push(double x, unsigned long long y1, unsigned long long y2);
+       static void find_diff(double x, double &prev_x, unsigned long long y1, unsigned long long prev_y1, unsigned long long y2, unsigned long long prev_y2,
+               unsigned long long &yf1, unsigned long long &yf2);
+       
+       unsigned get_min_x() { return min_x; }
+       unsigned get_max_x() { return max_x; }
+       unsigned get_min_y() { return min_y; }
+       unsigned get_max_y() { return max_y; }
+};
+
+#endif /* !defined(_FLOWPUSHER_H) */
diff --git a/web/ext/flowutil.cpp b/web/ext/flowutil.cpp
new file mode 100644 (file)
index 0000000..9df12dc
--- /dev/null
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include "graph.h"
+#include "flowutil.h"
+
+std::vector<flow_element> sum_flows(const std::vector<flow_element> &a, const std::vector<flow_element> &b)
+{
+       std::vector<flow_element> ret;
+       std::vector<flow_element>::const_iterator ia = a.begin(), ib = b.begin();
+
+       double last_xa = 0.0, last_y1a = 0.0, last_y2a = 0.0;
+       double last_xb = 0.0, last_y1b = 0.0, last_y2b = 0.0;
+       
+       while (ia != a.end() && ib != b.end()) {
+               if (ia->x == ib->x) {
+                       flow_element fea = *ia, feb = *ib, fe;
+                       
+                       last_xa = fea.x;
+                       last_y1a = fea.y1;
+                       last_y2a = fea.y2;
+                       
+                       last_xb = feb.x;
+                       last_y1b = feb.y1;
+                       last_y2b = feb.y2;
+               
+                       fe.x = fea.x;
+                       fe.y1 = fea.y1 + feb.y1;
+                       fe.y2 = fea.y2 + feb.y2;
+
+                       ret.push_back(fe);
+
+                       ++ia, ++ib;
+               } else if (ia->x < ib->x) {
+                       flow_element fe = *ia;
+                       
+                       last_xa = fe.x;
+                       last_y1a = fe.y1;
+                       last_y2a = fe.y2;
+                       
+                       double t = (fe.x - last_xb) / (ib->x - last_xb);
+                       fe.y1 += last_y1b + t * (ib->y1 - last_y1b);
+                       fe.y2 += last_y2b + t * (ib->y2 - last_y2b);
+
+                       ret.push_back(fe);
+
+                       ++ia;
+               } else {
+                       flow_element fe = *ib;
+                       
+                       last_xb = fe.x;
+                       last_y1b = fe.y1;
+                       last_y2b = fe.y2;
+                       
+                       double t = (fe.x - last_xa) / (ia->x - last_xa);
+                       fe.y1 += last_y1a + t * (ia->y1 - last_y1a);
+                       fe.y2 += last_y2a + t * (ia->y2 - last_y2a);
+
+                       ret.push_back(fe);
+                       ++ib;
+               }
+       }
+
+       while (ia != a.end()) {
+               ret.push_back(*ia);
+               ++ia;
+       }
+       while (ib != b.end()) {
+               ret.push_back(*ib);
+               ++ib;
+       }
+
+       return ret;
+}
+
+std::vector<flow_element> filter_flow(const std::vector<flow_element> &flow)
+{
+       unsigned long long last_y1 = 0, last_y2 = 0;
+       std::vector<flow_element> ret;
+       
+       for (std::vector<flow_element>::const_iterator i = flow.begin(); i != flow.end(); ++i) {
+/*             if ((i->y1 > 100000 && last_y1 < 10000 && i->y2 > 100000 && last_y2 < 1000) ||
+                   (last_y1 > 10000 && last_y2 > 10000 && i->y1 / last_y1 > 10 && i->y2 / last_y2 > 10)) {
+                       printf("yoyo: %llu %llu (%llu %llu)\n", i->y1, i->y2, last_y1, last_y2);
+               } else {
+                       ret.push_back(*i);
+                       last_y1 = i->y1;
+                       last_y2 = i->y2;
+               } */
+               if (!(i->x >= 1145056800 && i->x <= 1145070800)) {
+                       ret.push_back(*i);
+               }
+       }
+
+       return ret;
+}
+
+void make_graph(int port, unsigned width, unsigned height, unsigned min_x, unsigned max_x, unsigned long long min_y, unsigned long long max_y, std::vector<flow_element> &flow)
+{
+       char filename[256];
+       graph *g = mygraph_new(width, height);
+       g = mygraph_make_graph(g, min_x, max_x, min_y, max_y, 5);
+
+       int *x = new int[flow.size()];
+       unsigned long long *y1 = new unsigned long long[flow.size()];
+       unsigned long long *y2 = new unsigned long long[flow.size()];
+
+       // de-interleave
+       for (unsigned i = 0; i < flow.size(); ++i) {
+               x[i] = flow[i].x;
+               y1[i] = flow[i].y1;
+               y2[i] = flow[i].y2;
+       }
+
+       mygraph_plot_series(g, x, y1, flow.size(), 1.0f, 0.0f, 0.0f);
+       mygraph_plot_series(g, x, y2, flow.size(), 0.0f, 0.0f, 1.0f);
+       sprintf(filename, "port-%u-500-250.png", port);
+       mygraph_to_file(g, filename);
+       mygraph_cleanup(g);
+
+       delete[] x;
+       delete[] y1;
+       delete[] y2;
+}
+
diff --git a/web/ext/flowutil.h b/web/ext/flowutil.h
new file mode 100644 (file)
index 0000000..235ebc9
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _FLOWUTIL_H
+#define _FLOWUTIL_H 1
+
+#include <vector>
+#include "flowpusher.h"
+
+std::vector<flow_element> sum_flows(const std::vector<flow_element> &a, const std::vector<flow_element> &b);
+std::vector<flow_element> filter_flow(const std::vector<flow_element> &flow);
+void make_graph(int port, unsigned width, unsigned height, unsigned min_x, unsigned max_x, unsigned long long min_y, unsigned long long max_y, std::vector<flow_element> &flow);
+
+#endif /* !defined(_FLOWUTIL_H) */
diff --git a/web/ext/graph.cpp b/web/ext/graph.cpp
new file mode 100755 (executable)
index 0000000..a516b31
--- /dev/null
@@ -0,0 +1,240 @@
+#include "graph.h"
+
+int tz_local_offset() { return 7200; } // riktig?
+
+
+void
+mygraph_fill_background(graph *mygraph);
+
+void
+mygraph_draw_graph (cairo_t *cr,
+                   int x,
+                   int y );
+
+graph *
+mygraph_new (int width, int height)
+{
+  graph *mygraph;
+  mygraph = (graph *)malloc(sizeof(graph));
+  mygraph->width = width;
+  mygraph->height = height;
+
+
+  int stride = width * 4;
+  unsigned char *image;
+  image = (unsigned char *) malloc (sizeof(unsigned char) * stride * height);
+
+  mygraph->surface = cairo_image_surface_create_for_data (image, CAIRO_FORMAT_ARGB32,
+                                                      width, height, stride);
+  mygraph->cr = cairo_create (mygraph->surface);
+
+  cairo_set_source_rgb (mygraph->cr, 1.0, 1.0, 1.0);
+  mygraph_fill_background (mygraph);
+
+  cairo_select_font_face (mygraph->cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
+                         CAIRO_FONT_WEIGHT_NORMAL);
+  cairo_set_font_size (mygraph->cr, 10);
+
+  cairo_set_antialias(mygraph->cr, CAIRO_ANTIALIAS_NONE);
+  cairo_set_line_width (mygraph->cr, 1.0);
+
+  return mygraph;
+}
+
+graph *
+mygraph_make_graph (graph *mygraph, double min_x, double max_x,
+                   double min_y, double max_y, int tickgran)
+{
+  int xoffset = 70;
+  cairo_text_extents_t extents;
+
+  mygraph->xoffset = xoffset;
+  mygraph->min_x = min_x;
+  mygraph->max_x = max_x;
+  mygraph->min_y = min_y;
+  mygraph->max_y = max_y;
+
+/*   cairo_t *cr; */
+/*   cairo_surface_t *surface; */
+
+  double xs = ((double)mygraph->width - (double)(xoffset+2)) /
+             (double)(max_x - min_x);
+
+  double ys = ((double)mygraph->height - 33.) / (double)(min_y - max_y);
+
+  mygraph->xs = xs;
+  mygraph->ys = ys;
+
+  double starthour = fmod((min_x + (double)tz_local_offset()) / 3600., 24.);
+  double diff, center, begin, end;
+
+  char string[20];
+  int i;
+  for (i = 0; i<240; i++)
+    { // Hour marks and text
+      if ((i % 2) == 0)
+       cairo_set_source_rgb (mygraph->cr, 1.0, 1.0, 1.0);
+      else
+       cairo_set_source_rgb (mygraph->cr, 0.90, 0.90, 1.0);
+      
+      diff = (double)i - starthour;
+      begin = (diff * 3600.) * xs;
+      end = ((double)(i+1) - starthour) * 3600.0 * xs;
+      center = (begin + end) / 2.;
+
+      if (begin < 0.0)
+       continue;
+      if (begin > ((double)mygraph->width - ((double)xoffset)))
+       continue;
+
+      cairo_rectangle (mygraph->cr, xoffset+begin, 0,
+                      end - begin, mygraph->height);
+      
+      cairo_fill (mygraph->cr);
+
+      if (begin <= 0.0 || end >= mygraph->width - (xoffset))
+       continue;
+
+      cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 0.0);
+
+      sprintf(string, "%d", i % 24);
+//           printf("showing string %s @ %fx%f\n", string, xoffset + center - (extents.width/2), (mygraph->height - extents.height - 2));
+
+      cairo_text_extents (mygraph->cr, string, &extents);
+      cairo_move_to (mygraph->cr, xoffset + center -
+                    (extents.width/2),
+                    (mygraph->height - extents.height - 2));
+
+      cairo_show_text (mygraph->cr, string);
+
+    }
+
+  cairo_set_source_rgb (mygraph->cr, 0.4, 0.4, 0.4);
+   long long ytick;
+  do
+    {
+      ytick = ((long long)max_y - (long long)min_y) / 11;
+      ytick = (long long)(ceil (ytick / tickgran) * tickgran);
+      tickgran /= 10;
+    } while (((long long)max_y - (long long)min_y) / ytick < 4);
+
+  int y;
+  unsigned long long traf;
+  for (i = -11; i<12; i++)
+    {
+      y = (int)((i * ytick - (long long)max_y) * ys + 10);
+      if (y < 2 || y > mygraph->height - 18)
+       continue;
+
+/*       printf("draw line at %d\n", y); */
+
+      cairo_move_to (mygraph->cr, xoffset, y);
+      cairo_line_to (mygraph->cr, mygraph->width-1, y);
+
+      if (i == 0)
+       {
+
+         cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 1.0);
+         cairo_stroke (mygraph->cr);
+         cairo_set_source_rgb (mygraph->cr, 0.6, 0.6, 0.6);
+       }
+      else
+       cairo_stroke (mygraph->cr);
+
+      // draw text
+      traf = 8 * ((unsigned long long)i * ytick);
+/*       printf("traffic: %d\n", traf); */
+
+      if (traf >= 500000000)
+       sprintf (string, "%.1f Gbit", ((double)traf/1000000000));
+      else if (traf >= 500000)
+       sprintf (string, "%.1f Mbit", ((double)traf/1000000));
+      else
+       sprintf (string, "%.1f kbit", ((double)traf/1000));
+
+      cairo_text_extents (mygraph->cr, string, &extents);
+
+/*      if (y - (extents.height/2) < 2 ||
+         y + (extents.height/2) > mygraph->height - (extents.height + 2))
+       continue; */
+
+      cairo_move_to (mygraph->cr,
+                    xoffset - 4 - extents.width,
+                    y + (extents.height/2));
+
+      cairo_show_text (mygraph->cr, string);
+    }
+
+  cairo_rectangle (mygraph->cr, xoffset, 0, mygraph->width-xoffset-1, mygraph->height-1);
+
+  cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 0.0);
+  cairo_stroke (mygraph->cr);
+
+  return mygraph;
+}
+
+void
+mygraph_plot_series (graph *mygraph, int *xvals, unsigned long long *yvals, int n_vals,
+                    double r, double g, double b)
+{
+  int x, i;
+  unsigned long long y;
+  x = xvals[0];
+  y = yvals[0];
+
+  cairo_set_antialias(mygraph->cr, CAIRO_ANTIALIAS_DEFAULT);
+  cairo_set_source_rgb (mygraph->cr, r, g, b);
+
+  int xp = (int)((x - mygraph->min_x) * mygraph->xs + mygraph->xoffset + 1);
+  int yp = (int)((y - mygraph->max_y) * mygraph->ys + 10);
+  
+  cairo_move_to (mygraph->cr, xp, yp);
+
+/*   printf("Plotting from:\n");
+   printf("(%d, %d) %d (%d, %d)<br/>\n",
+        x, y, (int)((double)(x - (int)mygraph->min_x) * mygraph->xs + (double)(mygraph->xoffset + 1)) ,
+        (int)((double)(x - (int)mygraph->min_x) * mygraph->xs + (double)(mygraph->xoffset + 1)),
+        (int)((double)(y - (int)mygraph->max_y) * mygraph->ys + 10.)); */
+
+  int last_xp = xp, last_yp = yp;
+  
+  for (i = 1; i < n_vals; i++)
+    {
+      x = xvals[i];
+      y = yvals[i];
+      
+      int xp = (int)((x - mygraph->min_x) * mygraph->xs + mygraph->xoffset + 1);
+      int yp = (int)((y - mygraph->max_y) * mygraph->ys + 10);
+      
+      if (abs(xp - last_xp) < 2 && yp > last_yp)
+       continue;
+      
+      cairo_line_to (mygraph->cr, xp, yp);
+      last_xp = xp;
+      last_yp = yp;
+    }
+
+  cairo_stroke(mygraph->cr);
+}
+
+void
+mygraph_to_file (graph *mygraph, char *filename)
+{
+  cairo_surface_write_to_png (mygraph->surface, filename);
+}
+
+void
+mygraph_cleanup (graph *self)
+{
+  cairo_destroy (self->cr);
+  cairo_surface_destroy (self->surface);
+}
+
+void
+mygraph_fill_background (graph *mygraph)
+{
+  cairo_rectangle (mygraph->cr, 0, 0, mygraph->width, mygraph->height);
+  cairo_fill (mygraph->cr);
+}
+
index 2d392173e5fffec9250d72ab9ecc746965d12dd9..c6376af1952bd7c612081ffb1cffd1bf78f0d864 100644 (file)
@@ -11,29 +11,26 @@ typedef struct _graph {
   int width;
   int height;
   int xoffset;
-  int yoffset;
-  float min_x;
-  float max_x;
-  float min_y;
-  float max_y;
-  float xs;
-  float ys;
+  double min_x;
+  double max_x;
+  double min_y;
+  double max_y;
+  double xs;
+  double ys;
 } graph;
 
-int tz_local_offset() { return 7200; } // riktig?
-
 void mygraph_fill_background(graph *mygraph);
 
 void mygraph_draw_graph (cairo_t *cr, int x, int y );
 
 graph *mygraph_new (int width, int height);
 
-graph *mygraph_make_graph (graph *mygraph, float min_x,
-                          float max_x, float min_y, float max_y,
+graph *mygraph_make_graph (graph *mygraph, double min_x,
+                          double max_x, double min_y, double max_y,
                           int tickgran);
 
-void mygraph_plot_series (graph *mygraph, int *xvals, int *yvals,
-                         int n_vals, float r, float g, float b);
+void mygraph_plot_series (graph *mygraph, int *xvals, unsigned long long *yvals,
+                         int n_vals, double r, double g, double b);
 
 void mygraph_to_file (graph *mygraph, char *filename);
 
diff --git a/web/ext/graphall.cpp b/web/ext/graphall.cpp
new file mode 100644 (file)
index 0000000..a21fc45
--- /dev/null
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include "graph.h"
+#include "flowpusher.h"
+#include "flowutil.h"
+
+int main(int argc, char **argv)
+{
+       bool total_only = false;
+       int width = 500, height = 250;
+       
+       std::vector<flow_element> flow, total_flow;
+       FlowPusher fp(flow);
+       int last_port = -1;
+       
+       mallopt(M_TRIM_THRESHOLD, -1);
+       
+       if (argc == 2 && strcmp(argv[1], "--total-only") == 0) {
+               width = 1000;
+               height = 500;
+               total_only = true;
+       }
+
+       int num_total = 0;
+       
+       for ( ;; ) {
+               int port;
+               double x;
+               unsigned long long y1, y2;
+               
+               if (scanf("%d %lf %llu %llu", &port, &x, &y1, &y2) != 4)
+                       break;
+
+               if (port != last_port) {
+                       if (last_port != -1) {
+                               if (!total_only)
+                                       make_graph(last_port, width, height, fp.get_min_x(), fp.get_max_x(), fp.get_min_y(), fp.get_max_y(), flow);
+                               total_flow = sum_flows(total_flow, flow);
+                               fprintf(stderr, "%u (%u)\n", last_port, ++num_total);
+                       }
+
+                       // reset
+                       last_port = port;
+                       fp.reset(x, y1, y2);
+                       continue;
+               }
+
+               fp.push(x, y1, y2);
+       }
+
+       // last graph
+       if (!total_only)
+               make_graph(last_port, width, height, fp.get_min_x(), fp.get_max_x(), fp.get_min_y(), fp.get_max_y(), flow);
+       total_flow = sum_flows(total_flow, flow);
+       
+       // total graph
+       unsigned long long min_y = 0;
+       unsigned long long max_y = 10000000;
+
+       for (unsigned i = 0; i < total_flow.size(); ++i) {
+               flow_element fe = total_flow[i];
+               
+               min_y = std::min(min_y, fe.y1);
+               max_y = std::max(max_y, fe.y1);
+               
+               min_y = std::min(min_y, fe.y2);
+               max_y = std::max(max_y, fe.y2);
+       }
+       
+       make_graph(65535, width, height, total_flow[0].x, total_flow[total_flow.size() - 1].x, min_y, max_y, total_flow);
+}
index c0150054e271d89c605af1c110cc7e50868996fe..f2851c149f2998ab05a0ad2d3186e0b346f0f199 100755 (executable)
@@ -6,6 +6,9 @@ use POSIX ":sys_wait_h";
 use strict;
 use warnings;
 
+use lib '../../include';
+
+use nms;
 use mygraph;
 require 'glue.pl';
 
@@ -22,8 +25,7 @@ $height = 250 unless (defined($height));
 my $graph = mygraph::mygraph_new($width, $height);
 
 my $start = [Time::HiRes::gettimeofday];
-my $dbh = DBI->connect("dbi:Pg:dbname=tg", "tg", "tg06")
-    or die "Couldn't connect to database";
+my $dbh = nms::db_connect();                                                                           
 
 # Fetch the name
 my $ref = $dbh->selectrow_hashref('SELECT sysname FROM switches WHERE switch=?', undef, $switch);
@@ -38,7 +40,7 @@ print <<"EOF";
     <h1>Switch $switch ($ref->{'sysname'})</h1>
 EOF
 
-my $q = $dbh->prepare('select port,coalesce(description, \'Port \' || port) as description,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches natural left join portnames where time between \'2005-03-23 05:17:36+01\' and  \'2005-03-24 05:17:36+01\' and switch=? order by switch,port,time;');
+my $q = $dbh->prepare('select port,coalesce(description, \'Port \' || port) as description,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches natural left join portnames where time between now() - \'1 day\'::interval and now() and switch=? order by switch,port,time;');
 $q->execute($switch);
 
 my (@totx, @toty1, @toty2) = ();
@@ -60,7 +62,7 @@ while (my $ref = $q->fetchrow_hashref()) {
     my $in = $ref->{'bytes_in'};
     my $out = $ref->{'bytes_out'};
     next if ($time == $prev_time);
-
+    
     if ($ref->{'port'} != $last_port) {
        if ($last_port != -1) {
            my $filename = "$switch-$last_port-$width-$height.png";
diff --git a/web/ext/totalcount.cpp b/web/ext/totalcount.cpp
new file mode 100644 (file)
index 0000000..bb4b1c0
--- /dev/null
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include <pqxx/pqxx>
+#include "graph.h"
+#include "flowpusher.h"
+#include "flowutil.h"
+
+namespace pqxx {
+       template<>
+       void from_string<long long>(const char *from, long long &to)
+       {
+               to = atoll(from);
+       }
+}
+                                               
+int main(int argc, char **argv)
+{
+       int width = 1000, height = 500;
+       unsigned long long traffic = 0ULL;
+       pqxx::connection conn("dbname=nms host=localhost user=nms password=seesahS4");
+
+       std::vector<flow_element> flow;
+       int last_port = -1;
+       
+       mallopt(M_TRIM_THRESHOLD, -1);
+       
+       int num_total = 0;
+       pqxx::work t(conn, "fetch_all");
+//     pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where ((switchtype='es3024' and port < 25) or (switchtype='summit400' and port > 1)) order by switch,port,time", "fetch_all", 500);
+       pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where switch=1447 order by switch,port,time", "fetch_all", 500);
+       
+       double prev_x;
+       unsigned long long prev_y1, prev_y2;
+       
+       for ( ;; ) {
+               pqxx::result res;
+               
+               cstream >> res;
+               if (res.empty()) 
+                       break;
+
+               for (unsigned i = 0; i < res.size(); ++i) {
+                       int port = res[i][0].as<int>();
+                       double x = res[i][1].as<double>();
+                       unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+                       if (port != last_port) {
+                               if (last_port != -1) {
+                                       fprintf(stderr, "%.2f TB (%u)\n", traffic / double(1024.0 * 1024.0 * 1024.0 * 1024.0), ++num_total);
+                               }
+
+                               // reset
+                               last_port = port;
+                               prev_x = x;
+                               prev_y1 = y1;
+                               prev_y2 = y2;
+                               continue;
+                       }
+
+                       unsigned long long yf1, yf2;
+                       FlowPusher::find_diff(x, prev_x, y1, prev_y1, y2, prev_y2, yf1, yf2);
+                       traffic += 0.5 * (yf1 + yf2);
+                       
+                       prev_x = x;
+                       prev_y1 = y1;
+                       prev_y2 = y2;
+               }
+       }
+       fprintf(stderr, "%.2f TB\n", traffic / double(1024.0 * 1024.0 * 1024.0 * 1024.0));
+}
diff --git a/web/ext/totalgraph.cpp b/web/ext/totalgraph.cpp
new file mode 100644 (file)
index 0000000..f1301d2
--- /dev/null
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include <pqxx/pqxx>
+#include "flowpusher.h"
+#include "flowutil.h"
+
+namespace pqxx {
+       template<>
+       void from_string<long long>(const char *from, long long &to)
+       {
+               to = atoll(from);
+       }
+}
+                                               
+
+int main(int argc, char **argv)
+{
+       int width = 1000, height = 500;
+       pqxx::connection conn("dbname=nms host=localhost user=nms password=seesahS4");
+
+       std::vector<flow_element> flow, total_flow;
+       FlowPusher fp(flow);
+       int last_port = -1;
+       
+       mallopt(M_TRIM_THRESHOLD, -1);
+       
+       int num_total = 0;
+       pqxx::work t(conn, "fetch_all");
+       pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where (switchtype='es3024' and port < 25) or (switchtype='summit400' and port > 1) order by switch,port,time", "fetch_all", 500);
+       
+       for ( ;; ) {
+               pqxx::result res;
+               
+               cstream >> res;
+               if (res.empty()) 
+                       break;
+
+               for (unsigned i = 0; i < res.size(); ++i) {
+                       int port = res[i][0].as<int>();
+                       double x = res[i][1].as<double>();
+                       unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+                       if (port != last_port) {
+                               if (last_port != -1) {
+                                       total_flow = sum_flows(total_flow, flow);
+                                       fprintf(stderr, "%u (%u)\n", last_port, ++num_total);
+                               }
+
+                               // reset
+                               last_port = port;
+                               fp.reset(x, y1, y2);
+                               continue;
+                       }
+
+                       fp.push(x, y1, y2);
+               }
+       }
+
+       unsigned long long min_y = 0;
+       unsigned long long max_y = 10000000;
+
+       for (unsigned i = 0; i < total_flow.size(); ++i) {
+               flow_element fe = total_flow[i];
+               
+               min_y = std::min(min_y, fe.y1);
+               max_y = std::max(max_y, fe.y1);
+               
+               min_y = std::min(min_y, fe.y2);
+               max_y = std::max(max_y, fe.y2);
+       }
+       
+       make_graph(65535, width, height, total_flow[0].x, total_flow[total_flow.size() - 1].x, min_y, max_y, total_flow);
+}
index 2829ed7fb28daf60f57c821d7ebdb61e3f192f95..e1d3fe9b3c4f400bfabc3a7e585317889723a2f6 100644 (file)
@@ -22,7 +22,7 @@ while (<PATCHLIST>) {
        $name =~ /e(\d+)-(\d+)/;
        my ($e, $s) = ($1, $2);
 
-       my $x = int(202 + $e * 8.25);
+       my $x = int(244 + $e * 9.87);
        my $y;
 
        $x += 7 if ($e >= 19);
@@ -35,12 +35,12 @@ while (<PATCHLIST>) {
                $c = $e;
                $d = ($s - 1) * 64;
 
-               $y = 470 - $s * 48;
+               $y = 455 - $s * 48;
        } else {
                $c = $e + 1;
                $d = ($s - 4) * 64;
 
-               $y = 400 - $s * 48 - ($s - 3) * 2;
+               $y = 424 - $s * 48 - ($s - 3) * 2;
        }
 
        my $xx = $x + 12;
index 3a8353907051aeef652e0c7ed2b2c160b51545aa..783f53ebf8e71bd68db213523d2ca389bc3b51ef 100755 (executable)
@@ -6,7 +6,7 @@ use nms;
 my $cgi = CGI->new;
 
 my $dbh = nms::db_connect();
-print $cgi->header(-type=>'text/html', -refresh=>'45; http://nms.tg05.gathering.org/nettkart-telnet.pl');
+print $cgi->header(-type=>'text/html', -refresh=>'45; http://nms.tg07.gathering.org/nettkart-telnet.pl');
 
 print <<"EOF";
 <html>
index 7255e581de5874a7af31ea7530be33a9b3041969..cf198dd36ee20fca507bfd27403172215b0aa73c 100755 (executable)
@@ -6,7 +6,7 @@ use nms;
 my $cgi = CGI->new;
 
 my $dbh = nms::db_connect();
-print $cgi->header(-type=>'text/html', -refresh=>'10; http://nms.tg05.gathering.org/nettkart-text.pl');
+print $cgi->header(-type=>'text/html', -refresh=>'10; http://nms.tg07.gathering.org/nettkart-text.pl');
 
 print <<"EOF";
 <html>
index 154181f3814b977de41fc99df35187aaf3eda886..040d4767865e5ee2a5566a60ff079caf0be4933f 100755 (executable)
@@ -6,7 +6,7 @@ use nms;
 my $cgi = CGI->new;
 
 my $dbh = nms::db_connect();
-print $cgi->header(-type=>'text/html', -refresh=>'45; http://nms.tg05.gathering.org/nettkart-web.pl');
+print $cgi->header(-type=>'text/html', -refresh=>'45; http://nms.tg07.gathering.org/nettkart-web.pl');
 
 print <<"EOF";
 <html>
index e0b47e8bba26669fbcf7def7879d5067ab989c76..89c63eaca08af3b9de603ec83b37084acdbebec1 100755 (executable)
@@ -1,35 +1,71 @@
 #! /usr/bin/perl
 use CGI;
 use GD;
+use Image::Magick;
 use DBI;
 use lib '../include';
 use nms;
 my $cgi = CGI->new;
 
+# Sekrit night-mode
+my $night = defined($cgi->param('night'));
+
 my $dbh = nms::db_connect();
 
 GD::Image->trueColor(1);
-$img = GD::Image->new('bg2.png');
+my ($img, $text_img);
+
+$img = GD::Image->new('bg07.png');
+if ($night) {
+       my ($width, $height) = ($img->width, $img->height); 
+
+       $img = GD::Image->new($width, $height);
+       $img->alphaBlending(0);
+       $img->saveAlpha(1);
+       my $blank = $img->colorAllocateAlpha(0, 0, 0, 127);
+       $img->filledRectangle(0, 0, $img->width - 1, $img->height - 1, $blank);
+
+       $text_img = GD::Image->new($width, $height);
+       $text_img->alphaBlending(0);
+       $text_img->saveAlpha(1);
+       my $blank = $text_img->colorAllocateAlpha(0, 0, 0, 127);
+       $text_img->filledRectangle(0, 0, $text_img->width - 1, $text_img->height - 1, $blank);
+} else {
+       $img = GD::Image->new('bg07.png');
+       $text_img = $img;
+}
 
 my $blk = $img->colorResolve(0, 0, 0);
 
 for my $y (42..236) {
-       my $i = 2.0 * ($y - 236.0) / (42.0 - 237.0);
+       my $i = 4.0 * ($y - 236.0) / (42.0 - 237.0);
        my $clr = get_color($i);
        
-       $img->filledRectangle(32,$y,53,$y+1,$clr);
+       $img->filledRectangle(12, $y, 33, $y+1, $clr);
+       $text_img->filledRectangle(12, $y, 33, $y+1, $clr);
 }
 
+$text_img->rectangle(12,42,33,236,$blk);
+
+my $tclr = $night ? $text_img->colorResolve(255, 255, 255) : $blk;
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/4.0, "100 Gbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/4.0, "10 Gbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/4.0, "1 Gbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/4.0, "100 Mbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*4.0/4.0, "10 Mbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 620, "NMS (C) 2005-2007 Tech:Server");
+
 my $q = $dbh->prepare('select * from switches natural join placements natural left join
-( select switch,sum(bytes_in)/count(*) as
-bytes_in,sum(bytes_out)/count(*) as bytes_out from get_datarate() group
-by switch ) t1 where ip<>\'127.0.0.1\'');
+( select switch,sum(bytes_in) as bytes_in,sum(bytes_out) as bytes_out from get_datarate() group
+by switch ) t1 order by zorder');
 $q->execute();
 while (my $ref = $q->fetchrow_hashref()) {
 
        # for now:
-       # 100kbit/port = all green
-       # 1gbit/port = all red
+       # 10Mbit/switch = green
+       # 100Mbit/switch = yellow
+       # 1Gbit/switch = red
+       # 10Gbit/switch = white
        
        my $clr;
 
@@ -37,12 +73,12 @@ while (my $ref = $q->fetchrow_hashref()) {
                my $intensity = 0.0;
                my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'};  # average and convert to bits (should be about the same in practice)
 
-               my $max = 20_000_000.0;   # 10mbit
-               my $min =    100_000.0;   # 100kbit
+               my $max = 10_000_000_000.0;   # 10Gbit
+               my $min =     10_000_000.0;   # 10Mbit
                if ($traffic >= $min) {
-                       $intensity = 2.0 * (log($traffic / $min) / log(10)) / (log($max / $min) / log(10));
-                       $intensity = 2.0 if ($intensity > 2.0);
-               }       
+                       $intensity = log($traffic / $min) / log(10);
+                       $intensity = 3.0 if ($intensity > 3.0);
+               }
                $clr = get_color($intensity);
        } else {
                $clr = $img->colorResolve(0, 0, 255);
@@ -50,18 +86,44 @@ while (my $ref = $q->fetchrow_hashref()) {
        
        $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
        $img->filledRectangle($3,$4,$1,$2,$clr);
+       $text_img->filledRectangle($3,$4,$1,$2,$clr);
+
        $img->rectangle($3,$4,$1,$2,$blk);
-        $img->stringUp(gdSmallFont,$3,$2-3,$ref->{'sysname'},$blk);
+       $text_img->rectangle($3,$4,$1,$2,$blk);
+        $text_img->stringUp(gdSmallFont,$3,$2-3,$ref->{'sysname'},$blk);
 }
 $dbh->disconnect;
 
 print $cgi->header(-type=>'image/png');
-print $img->png;
+if ($night) {
+       my $magick = Image::Magick->new;
+       $magick->BlobToImage($img->png);
+       $magick->Blur(sigma=>10.0, channels=>'All');
+       $magick->Gamma(gamma=>1.90);
+
+       my $m2 = Image::Magick->new;
+       $m2->Read('snmp-bg.png');
+       $m2->Negate();
+       $m2->Composite(image=>$magick, compose=>'Atop');
+
+       my $m3 = Image::Magick->new;
+       $m3->BlobToImage($text_img->png);
+       $m2->Composite(image=>$m3, compose=>'Atop');
+       
+       $img = $m2->ImageToBlob();
+       print $img;
+} else {       
+       print $img->png;
+}
 
 sub get_color {
        my $intensity = shift;
        my $gamma = 1.0/1.90;
-       if ($intensity > 1.0) {
+       if ($intensity > 3.0) {
+               return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma));
+       } elsif ($intensity > 2.0) {
+               return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma));
+       } elsif ($intensity > 1.0) {
                return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0);
        } else {
                return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0);
index 95e91989ace2745bcc5e5bf0c37089388130705e..3265b070e7b6e71be10f36fe327c28631ecf28bb 100755 (executable)
@@ -146,7 +146,7 @@ for my $y (0..479) {
 }
 
 
-print CGI::header(-type=>'image/png', -refresh=>'10; http://nms.tg05.gathering.org/overlay.pl?cam=' . $cam);
+print CGI::header(-type=>'image/png', -refresh=>'10; http://nms.tg07.gathering.org/overlay.pl?cam=' . $cam);
 print $gd->png;
 
 sub get_color {
index 259376e39522f73a024449260de09e853620ff1e..28e043f3243f87987a6609c352d4b3eff49c530a 100755 (executable)
@@ -9,18 +9,25 @@ my $cgi = CGI->new;
 my $dbh = nms::db_connect();
 
 GD::Image->trueColor(1);
-$img = GD::Image->new('bg2.png');
+$img = GD::Image->new('bg07.png');
 
 my $blk = $img->colorResolve(0, 0, 0);
 
 for my $y (42..236) {
-       my $i = 2.0 * ($y - 236.0) / (42.0 - 237.0);
+       my $i = 3.0 * ($y - 236.0) / (42.0 - 237.0);
        my $clr = get_color($i);
        
-       $img->filledRectangle(32,$y,53,$y+1,$clr);
+       $img->filledRectangle(12,$y,33,$y+1,$clr);
 }
 
-my $q = $dbh->prepare('select switch,port,bytes_in,bytes_out,placement,switchtype from switches natural join placements natural join get_current_datarate() where switchtype in (\'es3024\')');
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/3.0, "1 Gbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/3.0, "100 Mbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/3.0, "10 Mbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/3.0, "1 Mbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 620, "NMS (C) 2005-2007 Tech:Server");
+
+my $q = $dbh->prepare('select switch,port,bytes_in,bytes_out,placement,switchtype from switches natural join placements natural join get_datar
+ate() where switchtype in (\'es3024\')');
 $q->execute();
 while (my $ref = $q->fetchrow_hashref()) {
 
@@ -34,11 +41,11 @@ while (my $ref = $q->fetchrow_hashref()) {
                my $intensity = 0.0;
                my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'};  # average and convert to bits (should be about the same in practice)
 
-               my $max = 20_000_000.0;   # 100mbit
-               my $min =    100_000.0;   # 100kbit
+               my $max = 1_000_000_000.0;   # 1Gbit
+               my $min =     1_000_000.0;   # 1Mbit
                if ($traffic >= $min) {
-                       $intensity = 2.0 * (log($traffic / $min) / log(10)) / (log($max / $min) / log(10));
-                       $intensity = 2.0 if ($intensity > 2.0);
+                       $intensity = log($traffic / $min) / log(10);
+                       $intensity = 3.0 if ($intensity > 3.0);
                }
                $clr = get_color($intensity);
        } else {
@@ -64,7 +71,9 @@ print $img->png;
 sub get_color {
        my $intensity = shift;
        my $gamma = 1.0/1.90;
-       if ($intensity > 1.0) {
+       if ($intensity > 2.0) {
+               return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma));
+       } elsif ($intensity > 1.0) {
                return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0);
        } else {
                return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0);
index 86b80effda0fc0856115b9e59eb552fc8a218fbb..2f1bea2cd7ccbc5bd9c84e95ddf685ec94f267ff 100755 (executable)
@@ -14,17 +14,17 @@ my $ua = new LWP::UserAgent;
 $ua->timeout(15);
 $ua->agent('Mozilla/5.0');
 
-#$ua->credentials( "http://zepo.tg05.gathering.org", "/", $uname, $pass );
+#$ua->credentials( "http://zepo.tg07.gathering.org", "/", $uname, $pass );
 
 my $content;
 my %form;
 $form{'userid'} = $uname;
 $form{'next'} = "Look me up";
 
-#my $content = $ua->get("http://zepo.tg05.gathering.org/");
+#my $content = $ua->get("http://zepo.tg07.gathering.org/");
 
 
-$content = $ua->post("http://zepo.tg05.gathering.org/login", \%form);
+$content = $ua->post("http://zepo.tg07.gathering.org/login", \%form);
 
 if (!defined($content->{'_headers'}{'location'})) {
        die "Could not find dudes";
@@ -41,7 +41,7 @@ print Dumper($content);
 $form{'password'} = $pass;
 $form{'userid'} = 39457;
 $form{'next'} = "Log in";
-$content = $ua->post("https://zepo.tg05.gathering.org/enter&got=it", "cookie" => "SID=".$sessioncookie, \%form);
+$content = $ua->post("https://zepo.tg07.gathering.org/enter&got=it", "cookie" => "SID=".$sessioncookie, \%form);
 
 print Dumper($content);
 
index ed783b2fa915b245f821f92c9d19675416df061c..de7e1b8d134d4df33b69b99bfae02d59e7c810fd 100755 (executable)
@@ -4,6 +4,7 @@ use strict;
 use CGI;
 use DBI;
 use Data::Dumper;
+use Switch;
 use lib '../include';
 use nms;
 
@@ -28,15 +29,15 @@ sub parse_range($) {
 
        my @rangecomma = split(/\s*,\s*/, $switches);
        foreach (@rangecomma) {
-               my ($first, $drop1, $last, $drop2) = $_ =~ /(e\d+\-[123456])(sw)?\s*\-\s*(e\d+\-[123456])?(sw)?/;
-               if (!defined($first) && $_ =~ /e\d+\-[123456]/) {
+               my ($first, $last) = $_ =~ /(e\d+\-(?:sw)?[123456])\s*\-\s*(e\d+\-(?:sw)?[123456])?/;
+               if (!defined($first) && $_ =~ /e\d+\-(sw)?[123456]/) {
                        $first = $_;
                }
                if (!defined($first)) {
                        print "<font color=\"red\">Parse error in: $_</font><br>\n";
                        next;
                }
-               my ($rowstart, $placestart) = $first =~ /e(\d+)\-([123456])/;
+               my ($rowstart, $placestart) = $first =~ /e(\d+)\-(?:sw)?([123456])/;
                if (!defined($rowstart) || !defined($placestart)) {
                        print "<font color=\"red\">Parse error in: $_</font><br>\n";
                        next;
@@ -47,7 +48,7 @@ sub parse_range($) {
                        $placeend = $placestart;
                }
                else {
-                       ($rowend, $placeend) = $last =~ /e(\d+)\-([123456])/;
+                       ($rowend, $placeend) = $last =~ /e(\d+)\-(?:sw)?([123456])/;
                }
                if (!defined($rowend) || !defined($placeend)) {
                        print "<font color=\"red\">Parse error in: $_</font><br>\n";
@@ -64,7 +65,7 @@ sub parse_range($) {
                        }
                        for (my $j = $dostart; $j <= 6; $j++) {
                                last if ($i == $rowend && $j > $placeend);
-                               push(@range, "e$i-$j");
+                               push(@range, "e$i-sw$j");
                        }
                }
        }
@@ -77,9 +78,9 @@ sub parse_range($) {
 sub get_addr_from_switchnum($) {
        my ($sysname) = @_;
 
-       $sgetip->execute($sysname."sw");
+       $sgetip->execute($sysname);
        if ($sgetip->rows() < 1) {
-               print "Could not get the ip for: ".$sysname."sw";
+               print "Could not get the ip for: ".$sysname;
                return undef;
        }
        my $row = $sgetip->fetchrow_hashref();
index bae9511e84dbc267f4fbac1672b7318d6fe0707d..b840ac8a70a1b940e0951d8f7b2dfe24b64de3fd 100755 (executable)
@@ -110,9 +110,6 @@ if (defined($cgi->param('agid'))) {
        my $gid = $cgi->param('gid');
        if (!defined($gid)) {
                print "<font color=\"red\">Du har ikke valgt en gid å slette.</font>\n";
-       }
-       if ($cgi->param('agid') eq 'Disable') {
-               $sdisablegid->execute($gid);
                print "<p>gid: ".$cgi->param('gid')." har blitt disablet.\n";
        }
        else {
index 2399b31677dcb977519315d3db09ac5ff9ac663c..33cad52a7eaac37efcff92c3ae9147053ff33a33 100755 (executable)
@@ -12,7 +12,7 @@ use warnings;
 
 GD::Image->trueColor(1);
 
-my $img = GD::Image->new('bg2.png');
+my $img = GD::Image->new('bg07.png');
 #my $img = GD::Image->new(100,100);
 my $cgi = CGI->new;
 
index 4b12add6d321960188540b954befacd8ebedd17b..8137de9791db675921d8dfc0d51e1fe0186c7226 100755 (executable)
@@ -20,6 +20,6 @@ $img->interlaced('true');
 $img->string(gdMediumBoldFont,0,0,"TG05 - Streaming",$blu);
 
 print $cgi->header(-type=>'image/png',
-                   -refresh=>'10; http://nms.tg05.gathering.org/streaming.pl');
+                   -refresh=>'10; http://nms.tg07.gathering.org/streaming.pl');
 print $img->png;