In high-throughput Linux network infrastructure, aggregate bandwidth metrics often hide micro-bursting: short millisecond spikes where a network socket emits hundreds of packets simultaneously. While average utilization over a 1-second window might appear modest (e.g., 200 Mbps), micro-bursts can momentarily saturate top-of-rack switch buffers, causing tail-drop packet loss and triggering latency spikes across co-located tenants. Inside the Linux kernel, the cumulative number of transmitted segments is tracked in struct tcp_info as tcpi_segs_out.
Using extended Berkeley Packet Filter (eBPF) and bpftrace, systems engineers can sample tcpi_segs_out across millisecond intervals to detect micro-bursting behavior and audit TCP pacing efficiency in real time.
Understanding tcpi_segs_out in Kernel Space
Defined in include/uapi/linux/tcp.h, struct tcp_info exposes segment transmission counters:
struct tcp_info {
/* ... state fields ... */
__u32 tcpi_segs_out; /* Total outbound segments sent */
__u32 tcpi_data_segs_out; /* Outbound segments containing payload */
__u32 tcpi_pacing_rate; /* Current TCP pacing rate (bytes/sec) */
__u32 tcpi_max_pacing_rate;
};
When TCP pacing is disabled or misconfigured, the kernel releases an entire congestion window’s worth of segments upon receiving an ACK. With a large CWND (e.g., 100 packets), this creates an instant 150KB burst onto the wire. TCP pacing spreads packet transmission evenly over the round-trip time.
Authoring the bpftrace Micro-Burst Detection Probe
The following bpftrace script samples tcp_write_xmit() to detect burst transmissions exceeding 40 packets in a single transmit burst:
#!/usr/bin/env bpftrace
#include <net/sock.h>
#include <linux/tcp.h>
kprobe:tcp_write_xmit
{
$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);
$segs = $tp->segs_out;
$cwnd = $tp->snd_cwnd;
if ($cwnd > 50) {
time("%H:%M:%S ");
printf("MICRO-BURST POTENTIAL | %s -> %s:%d | CWND: %d pkts | Pacing: %d KB/s\n",
$saddr, $daddr, $dport, $cwnd, $tp->pacing_rate / 1024);
}
}
Running the Trace and Diagnosing Burst Patterns
Execute the bpftrace script with root privileges:
sudo bpftrace trace_bursts.bt
When high-CWND sockets transmit without pacing, bpftrace outputs structured alerts:
10:14:02 MICRO-BURST POTENTIAL | 10.0.1.20 -> 198.51.100.44:443 | CWND: 120 pkts | Pacing: 0 KB/s
10:14:08 MICRO-BURST POTENTIAL | 10.0.1.20 -> 203.0.113.88:443 | CWND: 85 pkts | Pacing: 42000 KB/s
The first log line flags an unpaced socket: with a CWND of 120 packets and zero pacing rate, it bursts 120 segments simultaneously, risking switch buffer drops.
Production Remediation and TCP Pacing Configuration
To eliminate micro-burst packet loss across your fleet:
- Deploy the FQ (Fair Queue) packet scheduler on egress network interfaces:
FQ enforces kernel-level TCP pacing, converting bursty transfers into smooth, continuous packet streams.sudo tc qdisc replace dev eth0 root fq - Transition to rate-based congestion control algorithms like BBR:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr - Verify that socket send buffers are not configured with excessively large burst thresholds.