Linux Kernel TCP/IP Architecture: Packet Flow, Socket Buffers (sk_buff) & NAPI Polling
Created: 2026-11-08 · Last updated: 2026-11-08 · Nejat Hakan
Executive Summary: Every packet entering or leaving a Linux server is processed by the Linux kernel networking subsystem. Rather than treating networking as an abstract theoretical concept, production systems engineering requires understanding how physical Ethernet frames are transferred via Direct Memory Access (DMA) into kernel ring buffers, managed through
struct sk_buffdata structures, scheduled via NAPI SoftIRQs, and demultiplexed into POSIX user-space socket queues.
-
Kernel Data Structures
Understand the anatomy of
struct sk_buff: zero-copy buffer manipulation viaskb_push,skb_pull, headroom, and tailroom pointers in kernel RAM. -
Interrupts & NAPI Polling
Trace the transition from physical NIC Hard-IRQs to SoftIRQ
NET_RX_SOFTIRQpoll loops, preventing CPU interrupt storms under 10G/40G packet loads. -
Wire-to-Socket Ingress
Follow an incoming frame through L2 driver validation, L3 IP routing and Netfilter hooks, L4 TCP segment reconstruction, and socket receive buffers.
-
Kernel Diagnostics & Tuning
Inspect hardware ring buffers with
ethtool -g, monitor CPU softnet drops via/proc/net/softnet_stat, and measure socket backlog depths.
1. The Pragmatic 4-Layer Kernel Model vs. Theoretical OSI
While textbooks frequently teach the theoretical 7-Layer OSI model, the Linux kernel network stack implements the pragmatic 4-Layer TCP/IP Model.
%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
L7["Layer 7: Application Layer<br/>Nginx, SSHd, PostgreSQL<br/>User-Space Process / POSIX Socket File Descriptor"]
L4["Layer 4: Transport Layer<br/>TCP State Machine / UDP Datagrams<br/>Kernel Socket Buffers: sk_receive_queue & sk_write_queue"]
L3["Layer 3: Network Layer (IP)<br/>Routing Decisions & Netfilter/nftables Hooks<br/>IPv4/IPv6 Header Parsing, TTL Decrement, Fragmentation"]
L2["Layer 2/1: Link & Physical Layer<br/>NIC Driver, DMA Ring Buffers, Ethernet MAC<br/>Hard-IRQ / NAPI SoftIRQ Processing"]
L7 <-->|"sys_sendto() / sys_recvfrom()"| L4
L4 <-->|"TCP/UDP Headers Pushed / Stripped"| L3
L3 <-->|"IP Headers & Routing Lookup"| L2
Kernel Subsystem Mapping Reference
| TCP/IP Layer | PDU (Data Unit) | Kernel Subsystem & Core Functions | Key Diagnostic Tools |
|---|---|---|---|
| Application | Payload Data | POSIX VFS Sockets (sys_read, sys_write, epoll) |
ss -tulpne, lsof -i |
| Transport | TCP Segment / UDP Datagram | tcp_v4_rcv(), udp_rcv(), TCP congestion engine (CUBIC/BBR) |
ss -ti, cat /proc/net/tcp |
| Network (IP) | IP Packet | ip_rcv(), Netfilter (NF_INET_PRE_ROUTING), ip_forward() |
ip route get, nft list ruleset |
| Link & Driver | Ethernet Frame | NIC driver (e1000e, virtio_net), napi_gro_receive() |
ethtool -S eth0, ip -s link |
2. Kernel Memory Architecture: struct sk_buff
At the heart of the Linux network subsystem lies struct sk_buff (defined in <linux/skbuff.h>). To achieve multi-gigabit throughput, the kernel avoids copying payload memory as a packet traverses the network stack. Instead, it adjusts pointer offsets within a pre-allocated contiguous buffer.
+-----------------------------------------------------------------------+
| struct sk_buff Control Structure (metadata, pointers, interface ref) |
+-----------------------------------------------------------------------+
| | | |
v v v v
head data tail end
+----------------+------------------+----------------+
| Headroom | Packet Payload | Tailroom |
| (Reserved for | (Headers + User | (Reserved for |
| L2/L3/L4 | Application | protocol |
| Headers) | Data) | trailers) |
+----------------+------------------+----------------+
Zero-Copy Pointer Operations
skb_push(skb, len): Moves thedatapointer backward into the headroom. Used during packet transmission (egress) when the transport layer prepends a TCP header, and the IP layer prepends an IP header.skb_pull(skb, len): Moves thedatapointer forward. Used during packet reception (ingress) to strip off the Ethernet and IP headers as the payload moves up to user-space.skb_reserve(skb, len): Adjusts bothdataandtailpointers to ensure sufficient headroom exists before packet construction begins.
Performance Impact of Zero-Copy Design
Because headers are added or stripped simply by incrementing or decrementing memory addresses (data and tail), the Linux kernel does not perform memory allocations (kmalloc) or memory copies (memcpy) per protocol layer.
3. The Ingress Packet Flow: From Wire to Socket
Understanding the journey of an incoming packet is critical for diagnosing dropped packets, CPU saturation, and latency spikes:
%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
A["Physical Wire / Fiber Link"] --> B["NIC PHY / MAC Controller"]
B --> C["NIC DMA Transfer to Host RAM<br/>(Circular RX Ring Buffer)"]
C --> D["Hardware Interrupt (Hard-IRQ)<br/>NIC alerts CPU core"]
D --> E["NAPI Scheduling<br/>Disables Hard-IRQ, raises NET_RX_SOFTIRQ"]
E --> F["SoftIRQ ksoftirqd / NAPI Poll Loop<br/>Driver fetches frames from RX Ring"]
F --> G["L2: napi_gro_receive()<br/>Generic Receive Offload aggregates packets"]
G --> H["L3: ip_rcv() & Netfilter PREROUTING<br/>Firewall rules & Routing decision"]
H --> I["L4: tcp_v4_rcv() / udp_rcv()<br/>Checksum verification & TCP State Machine"]
I --> J["POSIX Socket Buffer<br/>Packet appended to sk_receive_queue"]
J --> K["User-Space Application<br/>epoll wakes up process -> recvfrom() read"]
The Role of NAPI (New API) & SoftIRQs
In high-throughput environments (e.g., 10Gbps+ links), raising a hardware interrupt for every arriving packet would cause Interrupt Storms, forcing the CPU to spend 100% of its cycles handling context switches (livelock).
Linux solves this via NAPI (New API):
1. When the first packet arrives, the NIC raises a Hard-IRQ.
2. The interrupt handler disables further interrupts on that NIC queue and schedules a SoftIRQ (NET_RX_SOFTIRQ).
3. The kernel's ksoftirqd daemon enters a polling loop, pulling packets directly from the DMA ring buffer in batches (default budget is usually 300 packets).
4. Once the ring buffer is empty, interrupts are re-enabled, returning the system to idle state.
4. Hands-On Kernel Inspection & Troubleshooting
1. Inspecting NIC Ring Buffer Capacity
Check if your network card is dropping packets due to undersized RX/TX hardware ring buffers:
# Display maximum versus current RX/TX ring buffer size
sudo ethtool -g eth0
# Example Output:
# Ring parameters for eth0:
# Pre-set maximums:
# RX: 4096
# TX: 4096
# Current hardware settings:
# RX: 512
# TX: 512
If dropped frames occur under load, expand the ring buffer up to the hardware maximum:
2. Monitoring CPU SoftIRQ Processing & Drops
The kernel records SoftIRQ statistics in /proc/net/softnet_stat. Each line corresponds to an online CPU core:
The columns represent:
* Column 1 (total_frames): Total number of frames processed by the CPU core.
* Column 2 (dropped_frames): Number of frames dropped because the process backlog queue exceeded net.core.netdev_max_backlog.
* Column 3 (time_squeeze): Number of times the NAPI poll loop ran out of budget (net.core.netdev_budget) while packets were still waiting in the ring buffer.
# Script to parse /proc/net/softnet_stat into human-readable columns
awk '{printf "CPU %2d: Processed=%10d Dropped=%6d Squeezed=%6d\n", NR-1, "0x"$1, "0x"$2, "0x"$3}' /proc/net/softnet_stat
3. Tuning the Kernel Process Backlog
If Column 2 (dropped_frames) or Column 3 (time_squeeze) increments, increase the backlog queue and budget via /etc/sysctl.d/99-network-performance.conf:
# File: /etc/sysctl.d/99-network-performance.conf
# Maximum number of packets queued on the input side when the interface receives packets faster than the kernel can process them
net.core.netdev_max_backlog = 16384
# Maximum number of packets processed in one NAPI polling iteration
net.core.netdev_budget = 600
# Maximum time (in microseconds) spent in a single NAPI polling cycle
net.core.netdev_budget_usecs = 4000
Apply immediately without reboot:
5. Next Steps
With a firm grasp of the kernel packet pipeline and sk_buff memory architecture, proceed to calculating IP address boundaries and subnetting rules:
-
IPv4 CIDR Subnetting & Addressing
Master VLSM subnet math, RFC 1918 private boundary rules, and host calculation tables.