Merge pull request #7 from csfrancis/tcpretrans_tlp

Add support for TCP tail loss probes
This commit is contained in:
Brendan Gregg
2014-09-08 14:51:09 -07:00
2 changed files with 46 additions and 19 deletions

View File

@@ -3,7 +3,7 @@
tcpretrans \- show TCP retransmits, with address and other details. Uses Linux ftrace.
.SH SYNOPSIS
.B tcpretrans
[\-hs]
[\-hsp]
.SH DESCRIPTION
This traces TCP retransmits that are sent by the system tcpretrans is executed
from, showing address, port, and TCP state information,
@@ -25,6 +25,7 @@ Since this uses ftrace, only the root user can use this tool.
.SH REQUIREMENTS
FTRACE and KPROBE CONFIG, tcp_retransmit_skb() kernel function.
You may have these already have these on recent kernels. And Perl.
TCP tail loss probes were added in Linux 3.10.
.SH OPTIONS
.TP
\-h
@@ -32,6 +33,9 @@ Print usage message.
.TP
\-s
Include kernel stack traces.
.TP
\-p
Include TCP tail loss probes.
.SH EXAMPLES
.TP
Trace TCP retransmits
@@ -62,6 +66,9 @@ Remote port.
.TP
STATE
TCP session state.
.TP
TLP
Tail loss probe: "Y/N".
.SH OVERHEAD
The CPU overhead is relative to the rate of TCP retransmits, and is
designed to be low as this does not examine every packet. Once per second the

View File

@@ -8,7 +8,7 @@
# sent by the kernel on timeouts). To keep overhead low, only
# tcp_retransmit_skb() calls are traced (this does not trace every packet).
#
# USAGE: ./tcpretrans [-hs]
# USAGE: ./tcpretrans [-hsp]
#
# REQUIREMENTS: FTRACE and KPROBE CONFIG, tcp_retransmit_skb() kernel function.
# You may have these already have these on recent kernels. And Perl.
@@ -67,16 +67,18 @@ local $SIG{HUP} = \&cleanup;
$| = 1;
### options
my ($help, $stacks);
my ($help, $stacks, $tlp);
GetOptions("help|h" => \$help,
"stacks|s" => \$stacks)
"stacks|s" => \$stacks,
"tlp|p" => \$tlp)
or usage();
usage() if $help;
sub usage {
print STDERR "USAGE: tcpretrans [-hs]\n";
print STDERR "USAGE: tcpretrans [-hsp]\n";
print STDERR " -h # help message\n";
print STDERR " -s # print stack traces\n";
print STDERR " -p # trace TCP tail loss probes\n";
print STDERR " eg,\n";
print STDERR " tcpretrans # trace TCP retransmits\n";
exit;
@@ -140,6 +142,27 @@ sub inet_h2a {
return join(".", @addr);
}
sub create_kprobe {
my ($kname, $kval) = @_;
appendto "p:$kname $kval", "kprobe_events"
or ldie "ERROR: creating kprobe for $kname.";
}
sub enable_kprobe {
my ($kname) = @_;
unless (writeto "1", "events/kprobes/$kname/enable") {
appendto "-:$kname", "kprobe_events";
ldie "ERROR: enabling kprobe.";
}
}
sub remove_kprobe {
my ($kname) = @_;
writeto "0", "events/kprobes/$kname/enable"
or ldie "ERROR: disabling kprobe $kname";
appendto "-:$kname", "kprobe_events";
}
### check permissions
chdir "$tracing" or die "ERROR: accessing tracing. Root? Kernel has FTRACE?" .
"\ndebugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)";
@@ -153,20 +176,18 @@ writeto "$$", $flock or die "ERROR: unable to write $flock.";
### setup and begin tracing
writeto "nop", "current_tracer" or ldie "ERROR: disabling current_tracer.";
my $kname = "tcpretrans_tcp_retransmit_skb";
appendto "p:$kname tcp_retransmit_skb sk=%di", "kprobe_events"
or ldie "ERROR: creating kprobe for inet_csk_accept().";
my ($kname, $kname_tlp) = ("tcpretrans_tcp_retransmit_skb", "tcpretrans_tcp_send_loss_probe");
create_kprobe $kname, "tcp_retransmit_skb sk=%di";
create_kprobe $kname_tlp, "tcp_send_loss_probe sk=%di" if $tlp;
if ($stacks) {
writeto "1", "options/stacktrace" or print STDERR "WARNING: " .
"unable to enable stacktraces.";
}
unless (writeto "1", "events/kprobes/$kname/enable") {
appendto "-:$kname", "kprobe_events";
ldie "ERROR: enabling kprobe.";
}
enable_kprobe $kname;
enable_kprobe $kname_tlp if $tlp;
map_tcp_states();
printf "%-8s %-6s %-20s -- %-20s %s\n", "TIME", "PID",
"LADDR:LPORT", "RADDR:RPORT", "STATE";
printf "%-8s %-6s %-20s -- %-20s %-12s %s\n", "TIME", "PID",
"LADDR:LPORT", "RADDR:RPORT", "STATE", "TLP";
#
# Read and print event data. This loop waits one second then reads the buffered
@@ -225,8 +246,8 @@ while (1) {
}
my $now = strftime "%H:%M:%S", localtime;
printf "%-8s %-6s %-20s R> %-20s %s\n", $now, $pid,
"$laddr:$lport", "$raddr:$rport", $state;
printf "%-8s %-6s %-20s R> %-20s %-12s %s\n", $now, $pid,
"$laddr:$lport", "$raddr:$rport", $state, $rest =~ /$kname_tlp/ ? "Y" : "N";
}
}
@@ -240,9 +261,8 @@ sub cleanup {
writeto "0", "options/stacktrace" or print STDERR "WARNING: " .
"unable to disable stacktraces.";
}
writeto "0", "events/kprobes/$kname/enable"
or ldie "ERROR: disabling kprobe";
appendto "-:$kname", "kprobe_events";
remove_kprobe $kname;
remove_kprobe $kname_tlp if $tlp;
writeto "", "trace";
unlink $flock;
exit;