How to Trace TCP Socket TCP_INFO tcpi_snd_cwnd Dynamic Fluctuations in Linux Using eBPF

Real-time visibility into TCP congestion window (snd_cwnd) sizing is indispensable for diagnosing sudden throughput collapse and transport microbursts in production Linux environments. The kernel struct tcp_info records tcpi_snd_cwnd, representing the current congestion window size in maximum segment sizes (MSS). Tracing this value with eBPF gives non-intrusive visibility into congestion control algorithmic states.

Dynamics of the Congestion Window

Modern Linux TCP congestion controllers (such as Cubic and BBR) modulate snd_cwnd in response to round-trip time variations, ECN markings, and acknowledgment feedback. When packet loss occurs, algorithms drastically reduce snd_cwnd, triggering sharp throughput drops. Continuous observation identifies whether drops stem from physical link congestion or application burstiness.

eBPF BCC Program for Congestion Window Observation

The following BCC Python script attaches a probe to tcp_cong_avoid to monitor real-time congestion window adjustments:

from bcc import BPF

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

struct cwnd_event_t {
    u32 pid;
    u16 sport;
    u16 dport;
    u32 snd_cwnd;
    u32 snd_ssthresh;
};

BPF_PERF_OUTPUT(cwnd_events);

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

    struct tcp_sock *tp = tcp_sk(sk);
    struct cwnd_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_cwnd = tp->snd_cwnd;
    evt.snd_ssthresh = tp->snd_ssthresh;

    cwnd_events.perf_submit(ctx, &evt, sizeof(evt));
    return 0;
}
"""

b = BPF(text=bpf_code)
b.attach_kprobe(event="tcp_cong_avoid", fn_name="trace_cwnd")

def print_cwnd(cpu, data, size):
    evt = b["cwnd_events"].event(data)
    print(f"PID {evt.pid:<6} | Port {evt.sport} -> {evt.dport} | cwnd: {evt.snd_cwnd} MSS | ssthresh: {evt.snd_ssthresh}")

b["cwnd_events"].open_perf_buffer(print_cwnd)
print("Tracing tcpi_snd_cwnd dynamics... Press Ctrl+C to terminate.")
while True:
    b.perf_buffer_poll()

Operational Diagnosis and Network Tuning

Execute the tracing agent under root privileges:

sudo python3 trace_cwnd.py

If snd_cwnd collapses repeatedly to 1 or 2 MSS on high-speed datacenter links, check intermediate switch buffer queue drops and verify whether Explicit Congestion Notification (ECN) is negotiated cleanly.

Get the best tech tips delivered straight to your inbox.

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