Baiul has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I am a total newbie and have so far with help managed
to make a script which logs onto our routers and does
a "sh ip accounting" command. This then logs the
output as follows:



Source Destination Packets Bytes
10.162.140.33 10.3.1.8 38 2455
10.163.64.52 157.172.251.16 391 497020
10.162.132.53 10.53.1.32 84 13000

I have even managed to cut this all down and make it
print out on screen. What I want to do with it now
is sort the data. I can't seem to get this to work
at all. I have added all double to from entries and
I have a list which I want to sort by Bytes size.

Here is what I have so far,

#!/usr/local/bin/perl -w $rep = "/tmp"; $base = "/appli/ipacc"; #@pool = ('lcvt017','lzdg003','lzdg003','lmhg016','lpar1037','lnrk005' +,'lpar640'); @pool = ('lcvt017'); foreach $router (@pool) { $datafile = "$router.txt"; open(INPUT,"$rep/$datafile"); while (<INPUT>) { if (not (/^###.*/)) { ($src, $dst, $packets, $bytes) = split ; $$summary{$src}{$dst} += $bytes; # $ip_src_list{$src}++; $ip_src_list{$src} += $bytes; $ip_dst_list{$dst}++; } } close(INPUT); #printf "%18s %18s %18s\n", "IP Source", "IP Destination", "Total Byte +s"; foreach $ipsrc (keys %ip_src_list) { foreach $ipdst (keys %ip_dst_list) { if ($$summary{$ipsrc}{$ipdst}) { $tt{"$ipsrc -> $ipdst"} = $$summary{$ipsrc}{$i +pdst}; #printf "%18s %18s %18s\n", $ipsrc, $ipdst, $$ +summary{$ipsrc}{$ipdst}; } } } @list_of_keys = keys %tt; foreach $key (sort keys %tt) { printf "%35s %15d\n",$key, $tt{$key}; }
Can anyone help me out Please ?

Baiul.

Replies are listed 'Best First'.
I'm starting to sound like a broken record . . .
by Fletch (Bishop) on Feb 25, 2002 at 16:15 UTC
    $ perldoc -q 'how do I sort' Found in /usr/lib/perl5/5.6.1/pod/perlfaq4.pod How do I sort an array by (anything)? [...] How do I sort a hash (optionally by value instead of key)?
      But it's such a charming tune... :)
Re: Sorting Cisco IP accounting data!
by zengargoyle (Deacon) on Feb 26, 2002 at 00:46 UTC

    Some searching will help with the sorting question... However there's a better way. Check if your router is capable of Netflow export. You can have the routers export to a collector machine, much much better than polling the router for stats.

    I'm using the cflowd package (C code) to collect the flows, but for processing there's Cflow.pm (same guy who wrote cflowd). A typical export looks something like:

    $ flowdumper -e '($exporterip eq "192.168.251.43") && ($input_if == 6) +' -c ../flows.current FLOW index: 0xc7ffff router: 192.168.251.43 src IP: 64.12.27.230 dst IP: 192.168.252.188 input ifIndex: 6 output ifIndex: 9 src port: 5190 dst port: 2877 pkts: 11 bytes: 2291 IP nexthop: 192.168.254.1 start time: Mon Feb 25 16:29:47 2002 end time: Mon Feb 25 16:32:42 2002 protocol: 6 tos: 0x0 src AS: 0 dst AS: 0 src masklen: 0 dst masklen: 24 TCP flags: 0x1a (SYN|ACK|PUSH) engine type: 1 engine id: 1 ...snip... matched 19333 of 27695 flows $

    The tools available are quite flexible. FlowScan is a perl application to gather stats/make graphs with a backend RRD database. If nothing else it's a good place to start rolling your own.

      Thanks for the info Zen. My main problem is that I
      do not have full access to the routers since the
      company I work for have them outsourced through a
      rather inefficient third party. This means that I do
      not have enable mode access and am very limited in
      what I can do.

      If I could get this sorting problem 'Sorted' I would
      be happy. :)

      Thanks for the input though,
      Baiul.

        foreach $key (sort keys %tt) { printf "%35s %15d\n",$key, $tt{$key}; }

        Assuming that works for you...

        while (($key, $value) = each %tt) { push @unsorted, [ $k, $v ]; } @sort_asc = sort { $a->[1] <=> $b->[1] } @unsorted; @sort_dsc = sort { $b->[1] <=> $a->[1] } @unsorted; print "low to high\n"; foreach (@sort_asc) { prinf "%35s %15d\n", $_->[0], $_->[1]; } print "\n"; print "high to low\n"; foreach (@sort_dsc) { prinf "%35s %15d\n", $_->[0], $_->[1]; }

        Talk to them. If the router can do it, they should be happy to do it for you. It's easier on the router to export them than for you to continuously connect to the console and dump them. That's easier loadwise. IMNSHO using the console for this type of thing is bad.

        Setup on the router is 3 lines...

        ip flow-export source Loopback0 ip flow-export version 5 origin-as ip flow-export destination <your host> 2055 (plus turning on flow cache on the interfaces, but most do that by default, big win.)

        I would go so far as to say that if they wouldn't do this for you, Replace Them.