How to Trace TCP Socket TCP_INFO tcpi_bytes_acked in Linux Using eBPF

In high-throughput Linux network infrastructure, measuring raw packet counts or socket buffer sizes only provides an approximation of real data delivery. Packets can be duplicated, dropped, or retransmitted multiple times without progressing the receiver’s byte stream. To measure true, confirmed data throughput, the Linux kernel maintains the tcpi_bytes_acked counter inside struct tcp_info, recording the exact cumulative number of data bytes confirmed as delivered to the peer application via acknowledgements.

Tracing tcpi_bytes_acked using extended Berkeley Packet Filter (eBPF) and bpftrace allows systems engineers to calculate exact byte-level transfer speeds and audit true goodput across production nodes non-invasively.

Understanding tcpi_bytes_acked in Kernel Space

Defined in include/uapi/linux/tcp.h, the Linux kernel tracks cumulative byte counters:

struct tcp_info {
    /* ... state fields ... */
    __u64   tcpi_bytes_acked;    /* RFC4898 tcpEStatsAppBytesAcked */
    __u64   tcpi_bytes_received; /* RFC4898 tcpEStatsAppBytesRcvd */
    __u32   tcpi_segs_out;
    __u32   tcpi_segs_in;
};

Unlike raw sequence numbers (which wrap around 32-bit limits), tcpi_bytes_acked is a 64-bit monotonically increasing counter. By sampling tcpi_bytes_acked across time intervals, engineers calculate true application goodput:

Goodput (Mbps) = ((bytes_acked_t2 - bytes_acked_t1) * 8) / (delta_t_seconds * 1,000,000)

Authoring the bpftrace Goodput Meter Probe

The following bpftrace script monitors tcp_close() to generate delivery audits upon connection termination:

#!/usr/bin/env bpftrace

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

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

    $daddr = ntop($inet->inet_daddr);
    $saddr = ntop($inet->inet_saddr);
    $dport = bswap($inet->inet_dport);
    $bytes = $tp->bytes_acked;
    $busy_s = $tp->busy_time / 1000000;

    if ($bytes > 100000 && $busy_s > 0) {
        $mbps = ($bytes * 8) / ($busy_s * 1000000);
        time("%H:%M:%S ");
        printf("DELIVERY AUDIT | %s -> %s:%d | Delivered: %d KB | Goodput: %d Mbps\n",
            $saddr, $daddr, $dport, $bytes / 1024, $mbps);
    }
}

Running the Trace and Diagnosing Transfer Speeds

Execute the bpftrace script on your Linux storage worker or CDN node:

sudo bpftrace trace_bytes_acked.bt

When connections terminate, bpftrace outputs confirmed delivery metrics:

08:22:15 DELIVERY AUDIT | 10.0.1.25 -> 198.51.100.88:443 | Delivered: 45200 KB | Goodput: 180 Mbps
08:22:30 DELIVERY AUDIT | 10.0.1.25 -> 203.0.113.12:443 | Delivered: 12400 KB | Goodput: 4 Mbps

The second log line flags a connection where confirmed goodput dropped to 4 Mbps, indicating persistent packet loss or severe receiver throttling along that path.

Production Applications and Monitoring

Tracking tcpi_bytes_acked via eBPF helps systems teams:

  1. Audit true customer data transfer volume for accurate billing and SLA reporting.
  2. Identify clients experiencing degraded goodput despite high raw packet transmission counts.
  3. Validate that TCP BBR pacing achieves target transmission velocity without generating retransmission storms.

Get the best tech tips delivered straight to your inbox.

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