85 lines
2.1 KiB
Plaintext
Executable File
85 lines
2.1 KiB
Plaintext
Executable File
#!/usr/bin/env bpftrace
|
|
/*
|
|
* tcpretrans.bt Trace or count TCP retransmits
|
|
* For Linux, uses bpftrace and eBPF.
|
|
*
|
|
* USAGE: tcpretrans.bt
|
|
*
|
|
* This is a bpftrace version of the bcc tool of the same name.
|
|
* It doesn't support tracking TLPs.
|
|
*
|
|
* This uses dynamic tracing of kernel functions, and will need to be updated
|
|
* to match kernel changes.
|
|
*
|
|
* Copyright (c) 2018 Dale Hamel.
|
|
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
*
|
|
* 23-Nov-2018 Dale Hamel created this.
|
|
*/
|
|
|
|
#ifndef BPFTRACE_HAVE_BTF
|
|
#include <linux/socket.h>
|
|
#include <net/sock.h>
|
|
#else
|
|
#include <sys/socket.h>
|
|
#endif
|
|
|
|
BEGIN
|
|
{
|
|
printf("Tracing tcp retransmits. Hit Ctrl-C to end.\n");
|
|
printf("%-8s %-8s %20s %21s %6s\n", "TIME", "PID", "LADDR:LPORT",
|
|
"RADDR:RPORT", "STATE");
|
|
|
|
// See include/net/tcp_states.h:
|
|
@tcp_states[1] = "ESTABLISHED";
|
|
@tcp_states[2] = "SYN_SENT";
|
|
@tcp_states[3] = "SYN_RECV";
|
|
@tcp_states[4] = "FIN_WAIT1";
|
|
@tcp_states[5] = "FIN_WAIT2";
|
|
@tcp_states[6] = "TIME_WAIT";
|
|
@tcp_states[7] = "CLOSE";
|
|
@tcp_states[8] = "CLOSE_WAIT";
|
|
@tcp_states[9] = "LAST_ACK";
|
|
@tcp_states[10] = "LISTEN";
|
|
@tcp_states[11] = "CLOSING";
|
|
@tcp_states[12] = "NEW_SYN_RECV";
|
|
}
|
|
|
|
kprobe:tcp_retransmit_skb
|
|
{
|
|
$sk = (struct sock *)arg0;
|
|
$inet_family = $sk->__sk_common.skc_family;
|
|
|
|
if ($inet_family == AF_INET || $inet_family == AF_INET6) {
|
|
// initialize variable type:
|
|
$daddr = ntop(0);
|
|
$saddr = ntop(0);
|
|
if ($inet_family == AF_INET) {
|
|
$daddr = ntop($sk->__sk_common.skc_daddr);
|
|
$saddr = ntop($sk->__sk_common.skc_rcv_saddr);
|
|
} else {
|
|
$daddr = ntop(
|
|
$sk->__sk_common.skc_v6_daddr.in6_u.u6_addr8);
|
|
$saddr = ntop(
|
|
$sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr8);
|
|
}
|
|
$lport = $sk->__sk_common.skc_num;
|
|
$dport = $sk->__sk_common.skc_dport;
|
|
|
|
// Destination port is big endian, it must be flipped
|
|
$dport = bswap($dport);
|
|
|
|
$state = $sk->__sk_common.skc_state;
|
|
$statestr = @tcp_states[$state];
|
|
|
|
time("%H:%M:%S ");
|
|
printf("%-8d %14s:%-6d %14s:%-6d %6s\n", pid, $saddr, $lport,
|
|
$daddr, $dport, $statestr);
|
|
}
|
|
}
|
|
|
|
END
|
|
{
|
|
clear(@tcp_states);
|
|
}
|