How to Trace TCP Socket TCP_INFO tcpi_retrans_synack Retries in Linux Using eBPF

Measuring inbound SYN-ACK retry frequency across public-facing ingress servers provides critical operational visibility into return-path packet loss and asymmetric network routing. The Linux kernel struct tcp_info records initial handshake retransmissions under tcpi_retrans_synack. Tracing this value with eBPF gives real-time visibility into server handshake retries before listen backlog exhaustion drops pending connections.

Understanding SYN-ACK Retry Backoff Dynamics

When a server accepts a connection request, it sends a SYN-ACK and waits for the final ACK. If no acknowledgment arrives within the initial RTO interval, the kernel initiates exponential backoff retries governed by net.ipv4.tcp_synack_retries. Tracking these retries exposes transient client reachability issues before handshake timeouts drop sockets.

eBPF BCC Program for SYN-ACK Retry Tracing

The following BCC Python script attaches to inet_rtx_syn_ack to capture SYN-ACK retry counts:

from bcc import BPF

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

struct synack_retry_event_t {
    u32 pid;
    u16 sport;
    u16 dport;
    u32 saddr;
    u32 daddr;
};

BPF_PERF_OUTPUT(synack_retry_events);

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

    struct synack_retry_event_t evt = {};
    evt.pid = bpf_get_current_pid_tgid() >> 32;
    evt.sport = sk->sk_num;
    evt.dport = bpf_ntohs(sk->sk_dport);
    evt.saddr = sk->sk_rcv_saddr;
    evt.daddr = sk->sk_daddr;

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

b = BPF(text=bpf_source)
b.attach_kprobe(event="inet_rtx_syn_ack", fn_name="trace_synack_retry")

def print_synack_retry(cpu, data, size):
    e = b["synack_retry_events"].event(data)
    print(f"SYN-ACK RETRY: Server port {e.sport} -> Client {e.dport} retrying handshake!")

b["synack_retry_events"].open_perf_buffer(print_synack_retry)
print("Listening for TCP SYN-ACK retries... Press Ctrl+C to terminate.")
while True:
    b.perf_buffer_poll()

Operational Diagnosis and Network Tuning

Run the script under root privileges:

sudo python3 trace_synack_retry.py

High SYN-ACK retry counts indicate return-path firewall throttling or client-side connection abandonment.

Get the best tech tips delivered straight to your inbox.

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