#!/usr/bin/perl
#
# Perform a statistical analysis of the fields present 
# in /proc/net/dccpprobe (preferably saved into separate file first)

unless (@ARGV) { @ARGV = qw# /tmp/dccp_probe.out # }

die "Usage: $0 <filename>\n" unless @ARGV;
my ($sec, $sap, $dep, $size, $s, $rtt, $p, $x_calc, $x_recv, $x, $t_ipi);
my (%s, %rtt, %p, %x_calc, %x_recv, %x, %t_ipi);

while(<>) {
# format:  sec.usec   src:sport   dst:dport   ccid  s  rtt   p   X_calc   X_recv   X    t_ipi
#          1          2           3           4     5  6     7   8        9        10   11
 ($sec, $sap, $dep, $size, $s, $rtt, $p, $x_calc, $x_recv, $x, $t_ipi) = split;
 
 $first = $sec unless defined $first;       # record the start time
 last if ($t_ipi eq "");

 update_fields($s,      \%s);
 update_fields($rtt,    \%rtt);
 update_fields($p,      \%p);
 update_fields($x_calc, \%x_calc);
 update_fields($x_recv, \%x_recv);
 update_fields($x,      \%x);
 update_fields($t_ipi,  \%t_ipi);
}
exit 1 unless %s;                           # file empty

# strip the microseconds
$first =~ s#\.\.*$##;
$sec   =~ s#\.\.*$##;

printf "\n\tSTATISTICS for n=%d entries, total running time %d sec\n\n", 
                                                $s{'count'}, $sec -$first;
print_stats(\%s,      "s");
print_stats(\%rtt,    "RTT");
print_stats(\%p,      "p");
print_stats(\%x_calc, "X_calc");
print_stats(\%x_recv, "X_recv");
print_stats(\%x,      "X");
print_stats(\%t_ipi,  "t_ipi");

#----------- SUBROUTINES ---------------------------------------------
# update_fields($field, $ref)
sub update_fields {
 my ($val, $ref) = @_;

 return unless $val =~ m#^\d+$#;  # Integer values only
 
 if (! defined(${$ref}{'min'})) { 
   ${$ref}{'min'} = ${$ref}{'max'} = $val;
 } else {
   ${$ref}{'min'} = $val if ($val < ${$ref}{'min'} || ${$ref}{'min'} == 0 );
   ${$ref}{'max'} = $val if ($val > ${$ref}{'max'});
 }
 ${$ref}{'sum'}   += $val;
 ${$ref}{'sumsq'} += $val * $val;
 ${$ref}{'count'}++;
}

# print_stats($ref, $name)
sub print_stats {
 my ($ref, $name) = @_;
 my ($avg, $stddev);

 $avg = ${$ref}{'sum'}/${$ref}{'count'};
 $stddev = 1/(${$ref}{'count'} - 1) * (${$ref}{'sumsq'} - $avg * ${$ref}{'sum'});

 printf "%-8s min %d,  avg %.1f,  max %d   (stddev %.2f)\n", $name . ":",
         ${$ref}{'min'}, $avg, ${$ref}{'max'}, sqrt($stddev),  ${$ref}{'count'}++;
}
