#!/usr/bin/perl use strict; use warnings; use Net::Pcap; use Getopt::Std; my $pktcount=0; my $curtime=0; my $reftime=0; my $endtime=0; my $timelen=0; my @pps=(); my @bps=(); sub process_pkt { my($user_data, $hdr, $pkt) = @_; $reftime = $hdr->{tv_sec} if ($reftime == 0); $endtime = $hdr->{tv_sec}; $curtime = sprintf("%d\n", $hdr->{tv_sec} - $reftime); $pktcount++; my $arrsize=@pps; if ($arrsize < $curtime) { # grow array if necessary for (my $i = $arrsize; $i <= $curtime; $i++) { $pps[$i]=0; $bps[$i]=0; } } $pps[$curtime]++; $bps[$curtime]+=($hdr->{len} * 8); } sub help { print "pcaputil [-h] -f pcapfile [-e filter expression] [-p] [-b]\n"; print "\n"; print "\t-h\t\thelp\n"; print "\t-f pcapfile\tinput file name (required)\n"; print "\t-e expression\tfilter expression (tcpdump compatible)\n"; print "\t-b\t\tgenerate bps graph\n"; print "\t-p\t\tgenerate pps graph\n"; print "\n"; exit(); } sub dump_data { my @data=@_; open(my $fh, ">", "temp.data"); for (my $i = 0; $i <= $timelen; $i++) { print $fh "$i $data[$i]\n"; } close($fh); } sub create_graph { my ($dataset)=@_; my $ylabel=""; my $filename=""; my $linecolor=""; if ($dataset eq 'pps') { $ylabel="Packets"; $filename="pps"; $linecolor="#4d0000"; } if ($dataset eq 'bps') { $ylabel="Bits"; $filename="bps"; $linecolor="#00004d"; } my $gpi = <<"END_MESSAGE"; set terminal postscript eps enhanced color "Helvetica" 30 set title "Throughput Graph" set style line 99 linetype 1 linecolor rgb "#999999" lw 2 set key right bottom set key box linestyle 99 set key spacing 1.2 set nokey set grid xtics ytics mytics set decimal locale "en_US.UTF-8" set format y "%'.0f" set size 2 set size ratio 0.4 set ylabel "$ylabel" set xlabel "Time (Seconds)" set style line 1 lc rgb '$linecolor' lt 1 lw 3 plot "temp.data" using 1:2 notitle with lines ls 1 END_MESSAGE open(GNUPLOT, "| gnuplot | epstopdf -f | convert -density 300 - $filename.png"); print GNUPLOT $gpi; close(GNUPLOT); } #### main my $err =''; my %opts=(); getopts('hbpe:f:', \%opts); if (defined $opts{h}) { help(); } if (not defined $opts{f}) { help(); } my $inputfile=$opts{f}; # process the pcap again, now do the bps and pps calculation my $pcap = Net::Pcap::open_offline($inputfile,\$err) or die "Can't open file...$err\n"; if (defined $opts{e}) { my $filter = $opts{e}; my $filter_t; if (Net::Pcap::compile($pcap, \$filter_t, $filter, 1, 0) == -1) { die "Unable to compile filter expression '$filter'\n"; } Net::Pcap::setfilter($pcap, $filter_t); } Net::Pcap::loop($pcap, -1, \&process_pkt, ''); Net::Pcap::close($pcap); $timelen = $endtime - $reftime; print STDERR "Packet Count:\t\t $pktcount\n"; print STDERR "Capture Duration:\t $timelen seconds\n"; if ($pktcount < 2) { print "\nNeed at least two packets to draw a graph.\n"; exit(); } if (defined $opts{p}) { print("Creating PPS graph..."); dump_data(@pps); create_graph('pps'); print("Done.\n"); } if (defined $opts{b}) { print("Creating BPS graph..."); dump_data(@bps); create_graph('bps'); print("Done.\n"); }