How to Trace TCP Socket TCP_INFO tcpi_snd_wnd Collapse Events in Linux Using eBPF

In high-throughput microservice communication, downstream client starvation can cause advertised receive windows to crash to absolute zero, triggering TCP zero-window probe loops. The kernel struct tcp_info records tcpi_snd_wnd, representing the maximum byte window the sender can transmit. Tracing zero-window collapse events with eBPF gives real-time visibility into client-side application stalls.

Understanding Zero-Window Probing Mechanics

When a remote host advertises a zero window (snd_wnd = 0), the Linux kernel halts transmission and arms the persist timer. The sender dispatches periodic 1-byte window probe packets to check if buffer space has reopened. Unchecked persist probe states indicate deep client application deadlocks or unhandled garbage collection freezes.

eBPF BCC Program for Zero-Window Detection

The following BCC Python script attaches to tcp_probe_timer to detect when sockets enter persist mode due to zero-window collapse:

from bcc import BPF

bpf_source = """
#include <net/sock.h>
#include <linux/tcp.h>

struct zero_wnd_event_t {
    u32 pid;
    u16 sport;
    u16 dport;
    u32 snd_wnd;
};

BPF_PERF_OUTPUT(zero_events);

int trace_persist(struct pt_regs *ctx, struct sock *sk) {
    if (sk->sk_family != AF_INET)
        return 0;

    struct tcp_sock *tp = tcp_sk(sk);
    if (tp->snd_wnd == 0) {
        struct zero_wnd_event_t evt = {};
        evt.pid = bpf_get_current_pid_tgid() >> 32;
        evt.sport = sk->sk_num;
        evt.dport = bpf_ntohs(sk->sk_dport);
        evt.snd_wnd = tp->snd_wnd;
        zero_events.perf_submit(ctx, &evt, sizeof(evt));
    }
    return 0;
}
"""

b = BPF(text=bpf_source)
b.attach_kprobe(event="tcp_send_probe0", fn_name="trace_persist")

def print_zero(cpu, data, size):
    e = b["zero_events"].event(data)
    print(f"CRITICAL: Port {e.sport} -> {e.dport} (PID {e.pid}) zero-window freeze detected!")

b["zero_events"].open_perf_buffer(print_zero)
print("Listening for TCP zero-window persist probes... Press Ctrl+C to terminate.")
while True:
    b.perf_buffer_poll()

Operational Diagnosis and Network Tuning

Run the script under root privileges:

sudo python3 trace_zero_wnd.py

Zero-window events point conclusively to client-side buffer ingestion failures rather than intermediate packet drops.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.