TCP Segmentation Offload (TSO): How the NIC Slices Your 64KB Send Into MTU-Sized Packets

2026-07-04

When your application calls send() with a 64KB buffer, the kernel doesn't want to build 44 separate 1500-byte packets, each with its own TCP header, IP header, and checksum. That's 44 trips through the network stack, 44 skb allocations, 44 route lookups. TSO pushes that work down to the NIC.

Here's the trick: the kernel builds one giant skb — a single "super-packet" up to 64KB — with one TCP header, one IP header, and pretends the MSS is 64000. It hands this monster to the driver with a flag: skb_shinfo(skb)->gso_size = 1448. The driver programs the NIC's descriptor to say "segment this into 1448-byte chunks."

The NIC hardware then:

Real-world example: a 10Gbps NIC saturating the link with 1500-byte MTU needs to push ~820,000 packets/sec. Without TSO, that's 820K trips through tcp_transmit_skb(), each ~1μs — burning a whole CPU core just on send-path overhead. With TSO at 64KB super-packets, the kernel only touches ~19,000 skbs/sec. Same bytes, 43x less CPU.

Check it yourself:

ethtool -k eth0 | grep tcp-segmentation-offload
# tcp-segmentation-offload: on

Rule of thumb: the CPU cost of a TCP send is roughly proportional to the number of skbs, not the number of bytes. TSO lets you send N×MSS bytes for the cost of one skb. If you see high si (softirq) CPU on a busy server, check that TSO is enabled — a broken driver or a tunnel that disabled it can 10x your send-path CPU overnight.

Gotcha: TSO breaks with encapsulation the NIC doesn't understand. Wrap traffic in a VXLAN or WireGuard tunnel and the kernel silently falls back to GSO (software segmentation just before the driver) — same skb interface, no hardware acceleration. Your throughput graph drops and nothing logs why. Modern NICs support "inner TSO" for VXLAN/GRE; check ethtool -k for tx-udp_tnl-segmentation.

TSO is also why tcpdump on the sender shows suspiciously huge packets — you're capturing before segmentation happens, at the kernel-driver boundary.

Key Takeaway: TSO lets the kernel hand the NIC one 64KB skb instead of 44 MTU-sized ones, cutting send-path CPU cost by ~40x — but any tunnel the NIC can't parse silently disables it.

All newsletters