Created
August 19, 2017 22:43
-
-
Save jsnell/fa4f0714b1d986f7991c8c5ebfe6c265 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -lw | |
use strict; | |
use List::Util qw(min max); | |
use JSON; | |
my %data = %{decode_json join '', <>}; | |
print join ',', qw(connection time rtt-min rtt-max win-min win-max inflight-max payload type); | |
for my $key (keys %data) { | |
my $record = $data{$key}; | |
my $type; | |
if ($record->{first_url} =~ m{^/networktest/}) { | |
$type = 'speedtest'; | |
} elsif ($record->{first_url} =~ m{UNCHARTED4}) { | |
$type = 'update' | |
} elsif ($record->{first_url} =~ m{^/gs2}) { | |
$type = 'download' | |
} else { | |
next; | |
} | |
for my $ts (keys %{$record->{ts}}) { | |
my $row = $record->{ts}{$ts}; | |
next if $row->{rtt_min} > 1; | |
next if $row->{rtt_max} > 1; | |
print join ',', $key, "2017-08-18 $ts", $row->{rtt_min}, | |
$row->{rtt_max}, $row->{win_min}, $row->{win_max}, | |
$row->{in_flight_max}, $row->{payload}, | |
$type; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -lw | |
use strict; | |
use List::Util qw(min max); | |
use JSON; | |
my %connections = (); | |
my %ts_first = (); | |
my %rtt = (); | |
my %full_rtt = (); | |
my %wscale = (); | |
my %counters = (); | |
my %out = (); | |
my %acked = (); | |
my %in_flight = (); | |
open my $in, "tcpdump -nnlr @ARGV 'tcp' | "; | |
sub time_to_seconds { | |
my @a = split /:/, shift; | |
return $a[0] * 3600 + $a[1] * 60 + $a[2]; | |
} | |
# print join ',', qw(from to ack last_in_flight in_flight_4tuple in_flight_host time); | |
while (<$in>) { | |
if (/(\S+) IP ((\S+)\.\d+) > ((\S+)\.\S+):.*,wscale (\d+)/) { | |
my ($time, $from, $fromip, $to, $toip, $wscale) = ($1, $2, $3, $4, $5, $6); | |
my $key = "$from $to"; | |
$wscale{"$key"} = 1 << $wscale; | |
} | |
if (/(\S+) IP ((\S+)\.\d+) > ((\S+)\.\S+):.*HTTP: GET (.*)/) { | |
my ($time, $from, $fromip, $to, $toip, $url) = ($1, $2, $3, $4, $5, $6); | |
my $key = "$to $from"; | |
$out{$key}{first_url} //= $url; | |
} | |
if (/^(\S+) IP ((\S+)\.\d+) > ((\S+)\.\S+): Flags \[\S+\], (?:seq (\d+):(\d+), )?ack (\d+), win (\d+)/) { | |
my ($time, $from, $fromip, $to, $toip, $seq, $end_seq, $ack, $win) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); | |
my $sec = time_to_seconds $time; | |
my $tkey = $time; | |
$tkey =~ s/\d\..*/0/; | |
my ($tsval, $tsecr) = /TS val (\d+) ecr (\d+)/g; | |
my $key = "$from $to"; | |
my $rkey = "$to $from"; | |
$win *= $wscale{$key} // 1; | |
if (defined $tsval) { | |
if (defined $ts_first{"$rkey $tsecr"}) { | |
$rtt{$key} = $sec - $ts_first{"$rkey $tsecr"}; | |
if (defined $rtt{$key} and defined $rtt{$rkey}) { | |
$full_rtt{$key} = $rtt{$key} + $rtt{$rkey}; | |
# print qq{$rtt{"$key"} + $rtt{"$rkey"}}; | |
if ($fromip eq '192.168.1.227') { | |
$out{$rkey}{ts}{$tkey}{rtt_min} = | |
min($full_rtt{$key}, | |
$out{$rkey}{ts}{$tkey}{rtt_min} // $full_rtt{$key}); | |
$out{$rkey}{ts}{$tkey}{rtt_max} = | |
max($full_rtt{$key}, | |
$out{$rkey}{ts}{$tkey}{rtt_max} // $full_rtt{$key}); | |
$out{$rkey}{ts}{$tkey}{win_min} = | |
min($win, | |
$out{$rkey}{ts}{$tkey}{win_min} // $win); | |
$out{$rkey}{ts}{$tkey}{win_max} = | |
max($win, | |
$out{$rkey}{ts}{$tkey}{max_min} // $win); | |
} | |
} | |
$acked{"$key $tsval"} = $ack; | |
if ($end_seq and | |
defined $acked{"$rkey $tsecr"}) { | |
my $in_flight = $end_seq - $acked{"$rkey $tsecr"}; | |
$out{$key}{ts}{$tkey}{in_flight_max} = | |
max($out{$key}{ts}{$tkey}{in_flight_max} // 0, | |
$in_flight); | |
} | |
} | |
$ts_first{"$key $tsval"} ||= $sec; | |
} | |
if ($end_seq) { | |
$out{$key}{ts}{$tkey}{payload} += $end_seq - $seq; | |
$out{$key}{payload} += $end_seq - $seq; | |
} | |
} | |
} | |
for my $key (keys %out) { | |
my $record = $out{$key}; | |
if ($record->{payload} < 10000) { | |
delete $out{$key}; | |
} | |
} | |
print to_json \%out, { pretty => 1 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d <- read.csv("stats.csv") | |
events=data.frame(time=as.POSIXct(c( | |
"2017-08-18 10:24:00", | |
"2017-08-18 10:26:10", | |
"2017-08-18 10:48:40", | |
"2017-08-18 10:59:40", | |
"2017-08-18 11:00:20" | |
)), event=c( | |
"Power on", | |
"Start game download", | |
"Enter rest mode", | |
"Power on again", | |
"Close background Netflix" | |
)) | |
png("dl1-rtt-full.png", width=1600, height=800); | |
print(ggplot(d) + geom_point(aes(x=as.POSIXct(time), y=rtt.min * 1000, color=type)) + scale_x_datetime() + xlab("Time") + ylab("RTT [ms]") + scale_y_continuous(limits = c(0, NA))) | |
dev.off(); | |
png("dl1-win-full.png", width=1600, height=800); | |
print(ggplot(d) + geom_point(aes(x=as.POSIXct(time), y=inflight.max / 1000, color="Max data in flight [kB]")) + geom_point(size=1, aes(x=as.POSIXct(time), y=win.max / 1000, color="Max receive window [kB]")) + scale_x_datetime() + xlab("Time") + ylab("kB") + scale_y_continuous(limits = c(0, NA)) + geom_vline(data=events, mapping=aes(xintercept=as.numeric(time)), color="blue") + geom_text(data=events, mapping=aes(x=time, y=0, label=event), size=3, angle=90, vjust=-0.4, hjust=-3)) | |
dev.off(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment