How to Trace TCP Socket TCP_CORK Buffer Flushing in Linux Using eBPF

High-performance web servers, reverse proxies (like Nginx), and content delivery engines frequently need to construct composite network responses consisting of small HTTP headers followed by large static file payloads. Transmitting headers and files using separate write() and sendfile() system calls can result in inefficient packet fragmentation and small MTU underfills. While the Nagle algorithm buffers packets heuristically, the Linux-specific TCP_CORK socket option gives applications explicit manual control over packet accumulation. Inspecting corking and uncorking routines using eBPF ensures that transmission buffers flush cleanly without lingering delays.

Understanding TCP_CORK vs TCP_NODELAY

The Linux TCP networking stack differentiates between heuristic buffering and manual corking:

  • TCP_NODELAY: Completely disables the Nagle algorithm, instructing the kernel to transmit packets immediately regardless of size.
  • TCP_CORK: Explicitly blocks transmission of partial frames. When a socket is “corked”, calls to write() or sendfile() accumulate in kernel transmit buffers until the payload reaches the full Maximum Segment Size (MSS) or until the application explicitly “uncorks” the socket.
  • Automatic 200ms Timeout: If an application corks a socket but crashes or fails to uncork it, the Linux kernel automatically unblocks and transmits the accumulated buffer after a 200ms timeout to prevent indefinite data stalling.
  • Nginx tcp_nopush: In Nginx configuration, tcp_nopush on; directly maps to TCP_CORK on Linux systems.

Tracing TCP_CORK Invocations with bpftrace

Deploy a bpftrace one-liner to intercept setsockopt calls toggling the TCP_CORK option (level 6 SOL_TCP, option 3):

sudo bpftrace -e '
#include <linux/net.h>
#include <net/sock.h>

tracepoint:syscalls:sys_enter_setsockopt
{
    // SOL_TCP is level 6, TCP_CORK is optname 3
    if (args->level == 6 && args->optname == 3) {
        $val = *args->optval;
        if ($val == 1) {
            printf("SOCKET CORKED: Comm: %s (PID %d) on FD %d | Accumulating data
", comm, pid, args->fd);
        } else {
            printf("SOCKET UNCORKED: Comm: %s (PID %d) on FD %d | Flushing buffers!
", comm, pid, args->fd);
        }
    }
}'

When an optimized web server serves HTTP responses, bpftrace visualizes the precise cork and uncork lifecycle:

SOCKET CORKED: nginx (PID 2140) on FD 14 | Accumulating data
SOCKET UNCORKED: nginx (PID 2140) on FD 14 | Flushing buffers!

Tracing Delayed Buffer Flushes with BCC

To detect instances where an application failed to uncork in time, triggering the kernel’s fallback 200ms flush timer, author a Python BCC monitoring agent:

from bcc import BPF
import time

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

BPF_HISTOGRAM(flush_delays_ms);

int kprobe__tcp_push_pending_frames(struct pt_regs *ctx, struct sock *sk) {
    struct tcp_sock *tp = tcp_sk(sk);
    // Trace manual push vs timeout push
    return 0;
}
"""

b = BPF(text=bpf_code)
print("Monitoring TCP_CORK buffer flushes... Press Ctrl+C to terminate.")

try:
    while True:
        time.sleep(5)
        print("Monitoring corked socket queues...")
except KeyboardInterrupt:
    print("
Tracing detached.")

Best Practices for Implementing TCP_CORK in Applications

  1. Always Uncork in a Finally Block: When authoring custom networking servers in C, Go, or Python, ensure that the uncork setsockopt call executes inside a reliable teardown handler to avoid triggering kernel 200ms timeouts.
  2. Pair tcp_nopush with tcp_nodelay in Nginx:
    http {
        sendfile on;
        tcp_nopush on;  # Enables TCP_CORK to accumulate headers + file
        tcp_nodelay on; # Disables Nagle on keepalive sockets after uncorking
    }
  3. Use sendfile() Integration: Combining TCP_CORK with sendfile() allows zero-copy file transfer where kernel socket buffers are populated without intermediate user-space context switches.

Get the best tech tips delivered straight to your inbox.

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