Skip to content

Instantly share code, notes, and snippets.

@jsnell
Created August 19, 2017 22:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jsnell/fa4f0714b1d986f7991c8c5ebfe6c265 to your computer and use it in GitHub Desktop.
Save jsnell/fa4f0714b1d986f7991c8c5ebfe6c265 to your computer and use it in GitHub Desktop.
#!/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;
}
}
#!/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 };
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