D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
usr
/
sbin
/
Filename :
tcpdrop.bt
back
Copy
#!/usr/bin/env bpftrace // tcpdrop.bt Trace TCP kernel-dropped packets/segments. // For Linux, uses bpftrace and eBPF. // // This provides information such as packet details, socket state, and kernel // stack trace for packets/segments that were dropped via kfree_skb. // It cannot show tcp flags. // // Example of usage: // // # ./tcpdrop.bt // TIME PID COMM SADDR:SPORT DADDR:DPORT STATE // 00:39:21 0 swapper/2 10.231.244.31:3306 10.229.20.82:50552 ESTABLISHE // tcp_drop+0x1 // tcp_v4_do_rcv+0x135 // tcp_v4_rcv+0x9c7 // ip_local_deliver_finish+0x62 // [...] // // The last column shows the state of the TCP session. // // This tool is useful for debugging high rates of drops, which can cause the // remote end to do timer-based retransmits, hurting performance. // // This is a bpftrace version of the bcc tool of the same name. // // For Linux 5.17+ (see tools/old for script for lower versions). // // Copyright (c) 2018 Dale Hamel. // // 23-Nov-2018 Dale Hamel created this. // 01-Oct-2022 Rong Tao use tracepoint:skb:kfree_skb #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 drops. Hit Ctrl-C to end.\n"); printf("%-8s %-8s %-16s %-21s %-21s %-8s\n", "TIME", "PID", "COMM", "SADDR:SPORT", "DADDR:DPORT", "STATE"); // See https://github.com/torvalds/linux/blob/master/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"; } tracepoint:skb:kfree_skb { let $daddr; let $saddr; $reason = args.reason; $skb = (struct sk_buff *)args.skbaddr; $sk = (struct sock *)$skb.sk; $inet_family = $sk.__sk_common.skc_family; if ($reason > SKB_DROP_REASON_NOT_SPECIFIED && ($inet_family == AF_INET || $inet_family == AF_INET6)) { 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 %-16s ", pid, comm); printf("%39s:%-6d %39s:%-6d %-10s\n", $saddr, $lport, $daddr, $dport, $statestr); printf("%s\n", kstack); } } END { clear(@tcp_states); }