How to Trace TCP Socket TCP_INQ Bytes in Queue Telemetry in Linux Using eBPF

In high-throughput event-driven network servers (such as proxy routers, stream processors, and message brokers), worker threads receive readable event notifications from epoll. However, traditional read loops either execute speculative read() calls until EWOULDBLOCK is returned—wasting CPU cycles on unnecessary system calls—or read fixed buffer sizes, leaving unread bytes lingering in kernel socket buffers. The Linux kernel socket option TCP_INQ (available alongside TCP_CM_INQ cmsg metadata) enables applications to receive the exact number of bytes currently queued in the TCP receive buffer alongside read payloads. This tutorial covers tracing TCP_INQ dynamics using eBPF.

The Mechanics of TCP_INQ and Kernel Receive Buffers

When an application configures setsockopt(fd, IPPROTO_TCP, TCP_INQ, &val, 4), the kernel appends an ancillary control message (cmsg) with level IPPROTO_TCP and type TCP_CM_INQ to every recvmsg() invocation. The cmsg data payload returns an integer indicating how many unread bytes remain in the socket’s receive queue (sk->sk_receive_queue) after the current read is satisfied. If the remaining count is zero, the application can safely yield to the event loop without making a redundant, blocking-prone syscall. Tracing this queue reveals application drain efficiency.

Prerequisites and Toolchain Setup

Install the required tracing tools on your Linux server:

sudo apt-get update
sudo apt-get install -y bpftrace linux-headers-$(uname -r)

Verify eBPF socket tracing support:

sudo bpftrace -e 'kprobe:tcp_recvmsg { printf("recvmsg called\n"); exit(); }'

Authoring the bpftrace TCP_INQ Telemetry Script

Save the following script as trace_tcpinq.bt to capture unread queue depths and detect slow-consumer bottlenecks:

#!/usr/bin/env bpftrace

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

kprobe:tcp_recvmsg
{
    $sk = (struct sock *)arg0;
    @active_reads[tid] = $sk;
}

kretprobe:tcp_recvmsg
/@active_reads[tid]/
{
    $sk = @active_reads[tid];
    $copied = retval;

    if ($copied > 0) {
        // Calculate unread bytes queued in sk_receive_queue
        $queued = $sk->sk_rmem_alloc.counter;
        @unread_bytes_hist = hist($queued);

        if ($queued > 65536) {
            $inet = (struct inet_sock *)$sk;
            $saddr = ntop($inet->sk.__sk_common.skc_rcv_saddr);
            $sport = bswap($inet->inet_sport);
            printf("[SLOW CONSUMER] Socket %s:%d has %d bytes buffered in kernel!\n",
                $saddr, $sport, $queued);
            @slow_consumer_warnings = count();
        }
    }

    delete(@active_reads[tid]);
}

interval:s:5
{
    printf("\n--- Unread TCP Receive Queue Distribution (Bytes) ---\n");
    print(@unread_bytes_hist);
    print(@slow_consumer_warnings);
}

END
{
    clear(@active_reads);
}

Executing the Trace and Analysing Consumption Rates

Run the monitor with administrative privileges:

sudo bpftrace trace_tcpinq.bt

Simulate high-bandwidth network input using netcat, curl, or benchmark tools. The output records socket buffer occupancy:

--- Unread TCP Receive Queue Distribution (Bytes) ---
[0, 1024)            24510 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1024, 4096)          1204 |@@                                                |
[4096, 16384)          340 |                                                  |
[65536, 131072)         12 |                                                  |
[SLOW CONSUMER] Socket 10.0.1.25:443 has 84210 bytes buffered in kernel!

Clusters in the sub-1KB range confirm that application worker threads are draining buffers immediately without backlog delays.

Application Performance Recommendations

  • Integrate TCP_INQ into custom C/Rust network engines to eliminate 50% of redundant read() system calls during bursty network intake.
  • Tune socket receive memory automatically: ensure net.ipv4.tcp_rmem allows dynamic scaling up to 16MB for high-bandwidth links while maintaining aggressive application drain loops.

Get the best tech tips delivered straight to your inbox.

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