D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
usr
/
sbin
/
Filename :
tcpretrans.bt
back
Copy
#!/usr/bin/env bpftrace // tcpretrans.bt Trace or count TCP retransmits // For Linux, uses bpftrace and eBPF. // // This uses dynamic tracing of kernel functions, and will need to be updated // to match kernel changes. // // Example of usage: // // # ./tcpretrans.bt // TIME PID LADDR:LPORT RADDR:RPORT STATE // 01:55:05 0 10.153.223.157:22 69.53.245.40:34619 ESTABLISHED // 01:55:05 0 10.153.223.157:22 69.53.245.40:34619 ESTABLISHED // 01:55:17 0 10.153.223.157:22 69.53.245.40:22957 ESTABLISHED // [...] // // This output shows three TCP retransmits, the first two were for an IPv4 // connection from 10.153.223.157 port 22 to 69.53.245.40 port 34619. The TCP // state was "ESTABLISHED" at the time of the retransmit. The on-CPU PID at the // time of the retransmit is printed, in this case 0 (the kernel, which will // be the case most of the time). // // Retransmits are usually a sign of poor network health, and this tool is // useful for their investigation. Unlike using tcpdump, this tool has very // low overhead, as it only traces the retransmit function. It also prints // additional kernel details: the state of the TCP session at the time of the // retransmit. // // This is a bpftrace version of the bcc tool of the same name. // It doesn't support tracking TLPs. // // Copyright (c) 2018 Dale Hamel. // // 23-Nov-2018 Dale Hamel created this. #ifndef BPFTRACE_HAVE_BTF #include <linux/socket.h> #include <net/sock.h> #else // With BTF providing types, socket headers are not needed. // We only need to supply the preprocessor defines in this script. // AF_INET/AF_INET6 are part of the stable arch-independent Linux ABI #define AF_INET 2 #define AF_INET6 10 #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[(uint64)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); }