How to Trace TCP Socket TCP_QUICKACK Suppression in Linux Using eBPF

In low-latency networked applications—such as financial market data gateways, database replication clusters, and real-time streaming services—delayed ACKs can introduce 40ms to 200ms latency spikes when interacting with Nagle’s algorithm. The Linux kernel provides the TCP_QUICKACK socket option via setsockopt(), forcing the network stack to transmit immediate ACK packets instead of waiting for delayed ACK timers to expire. However, Linux resets quickack mode back to normal delayed ACK operation whenever data packets are acknowledged. Tracing quickack toggling and suppression dynamics with eBPF gives engineers critical visibility into latency-critical socket paths.

The Transience of TCP_QUICKACK in the Linux Kernel

Unlike persistent socket configurations (such as TCP_NODELAY), TCP_QUICKACK is ephemeral by design in the Linux kernel network subsystem:

/* Setting quickack in application code */
int quickack = 1;
setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &quickack, sizeof(quickack));

When quickack is enabled, the kernel sets the internal flag icsk->icsk_ack.quick = 1. However, as soon as an incoming packet is acknowledged or outbound communication occurs, the kernel clears this bit, reverting to the default delayed ACK heuristic (RFC 1122). Applications that fail to re-enable TCP_QUICKACK after every receive call experience erratic latency fluctuations.

Authoring a Custom bpftrace QuickACK Telemetry Script

To monitor when TCP_QUICKACK is applied and trace when delayed ACK suppression falls back to normal timers, write a bpftrace instrumentation script:

#!/usr/bin/env bpftrace

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

kprobe:tcp_enter_quickack_mode
{
  $sk = (struct sock *)arg0;
  @quickack_entered[$sk] = count();
}

kprobe:tcp_send_delayed_ack
{
  $sk = (struct sock *)arg0;
  @delayed_acks_fired[$sk] = count();
}

interval:s:10
{
  print(@quickack_entered);
  print(@delayed_acks_fired);
  clear(@quickack_entered);
  clear(@delayed_acks_fired);
}

Save this script as trace_quickack.bt. It instruments both tcp_enter_quickack_mode() and tcp_send_delayed_ack(), capturing active mode transitions per socket pointer.

Executing and Evaluating Kernel Telemetry

Run the bpftrace monitoring tool with administrative privileges:

sudo bpftrace trace_quickack.bt

Observe the telemetry counters while running latency-sensitive workloads:

  • QuickACK continuity: If @delayed_acks_fired continues to increment despite application calls to TCP_QUICKACK, the application is likely failing to re-assert the socket option on subsequent receive loops.
  • Interaction with Nagle: Cross-reference with TCP_NODELAY on client connections. Combining TCP_NODELAY on senders with persistent TCP_QUICKACK on receivers provides the lowest possible round-trip latency.
  • System-wide counters: Check nstat -z | grep -i delayedack to evaluate overall delayed ACK volume across network interfaces.

Configuring Sockets for Persistent Low Latency

To eliminate delayed ACK penalties systematically across production services:

  1. Re-arm TCP_QUICKACK immediately after each recv() or read() system call completes.
  2. Alternatively, evaluate modern kernel options such as TCP_NODELAY and SO_BUSY_POLL to reduce socket receive queue latency.
  3. Verify that network interface interrupt moderation (adaptive-rx) does not introduce packet batching delays that counteract quickack benefits.

Get the best tech tips delivered straight to your inbox.

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