How to Trace TCP Socket TCP_INFO tcpi_rcv_wnd in Linux Using eBPF

In high-performance networked applications—such as reverse proxies, ingestion workers, and streaming storage systems—the local server’s ability to absorb incoming TCP traffic without throttling remote senders is governed by its local receive window (rcv_wnd). When a local process encounters CPU starvation, database locking, or slow disk I/O, it fails to read data from the kernel socket buffer quickly enough. As unprocessed segments accumulate in the kernel receive queue (sk_rcvbuf), the Linux kernel automatically shrinks the advertised receive window sent in TCP acknowledgements, applying backpressure to the client.

The Linux kernel tracks the current local advertised window size in struct tcp_info as tcpi_rcv_wnd. Tracing this parameter with extended Berkeley Packet Filter (eBPF) and bpftrace allows systems engineers to detect local application bottlenecks before they cause socket timeouts or dropped packets.

Understanding tcpi_rcv_wnd in the Linux Networking Stack

The tcpi_rcv_wnd metric (defined in include/uapi/linux/tcp.h) reflects the unscaled byte space currently advertised in outgoing ACK packets:

struct tcp_info {
    /* ... state and counter fields ... */
    __u32   tcpi_snd_wnd;   /* Remote send window */
    __u32   tcpi_rcv_wnd;   /* Local advertised receive window */
    __u32   tcpi_rcv_space; /* Estimated window clamp space */
};

When the local application fails to call recv() or read(), the kernel socket receive buffer fills up. Once available space drops below the receiver’s window clamp, tcpi_rcv_wnd collapses toward zero, forcing remote clients to pause transmission.

Authoring the bpftrace Receive Window Diagnostic Probe

The following bpftrace script monitors outgoing ACK packets via tcp_send_ack() and detects instances where the local receive window collapses:

#!/usr/bin/env bpftrace

#include <net/sock.h>
#include <linux/tcp.h>

kprobe:tcp_send_ack
{
    $sk = (struct sock *)arg0;
    $inet = (struct inet_sock *)$sk;
    $tp = (struct tcp_sock *)$sk;

    $daddr = ntop($inet->inet_daddr);
    $saddr = ntop($inet->inet_saddr);
    $lport = bswap($inet->inet_sport);
    $rcv_wnd = $tp->rcv_wnd;

    // Detect receive window collapsing below 8KB on local listeners
    if ($rcv_wnd < 8192 && $rcv_wnd > 0) {
        time("%H:%M:%S ");
        printf("WARN: Local RcvWnd Saturated | Port: %d <- Peer: %s | RcvWnd: %d bytes | Buffer: %d\n",
            $lport, $daddr, $rcv_wnd, $sk->sk_rcvbuf);
    }

    if ($rcv_wnd == 0) {
        time("%H:%M:%S ");
        printf("CRITICAL: LOCAL ZERO WINDOW ADVERTISED | Port: %d <- Peer: %s | App Blocked\n",
            $lport, $daddr);
    }
}

Running the Trace and Diagnosing Host Bottlenecks

Launch the probe on your Linux server:

sudo bpftrace trace_rcv_wnd.bt

During heavy processing workloads, bpftrace flags local consumer lag instantly:

18:22:10 WARN: Local RcvWnd Saturated | Port: 8080 <- Peer: 192.168.1.104 | RcvWnd: 2896 bytes | Buffer: 131072
18:22:11 CRITICAL: LOCAL ZERO WINDOW ADVERTISED | Port: 8080 <- Peer: 192.168.1.104 | App Blocked
18:22:13 WARN: Local RcvWnd Saturated | Port: 8080 <- Peer: 192.168.1.104 | RcvWnd: 5792 bytes | Buffer: 131072

This event reveals that the application listening on port 8080 stopped draining its receive buffer, causing the Linux kernel to issue a Zero Window advertisement and temporarily halt inbound traffic.

Tuning and Architectural Remediation

When tcpi_rcv_wnd exhaustion occurs:

  1. Audit the receiving application’s event loop for synchronous disk I/O, heavy JSON parsing, or garbage collection stalls that delay socket reads.
  2. Increase default and maximum socket receive buffers in sysctl:
    sudo sysctl -w net.ipv4.tcp_rmem="4096 131072 6291456"
  3. Enable or verify net.ipv4.tcp_window_scaling = 1 across your infrastructure to allow receive windows to scale up to 1GB under high-bandwidth-delay product (BDP) conditions.

Get the best tech tips delivered straight to your inbox.

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