本页目录
网络协议栈概述
覆盖: sk_buff → NAPI → softirq (NET_RX/NET_TX) → 协议栈分层 → socket API → net_device → multi-queue 内核版本: 2.6 ~ 6.x
概述
Linux 网络栈是世界上使用最广泛的 TCP/IP 实现。从网卡 DMA 收包到用户态 read() 返回,数据包经过 10+ 层处理。本文追踪这个完整路径,聚焦核心数据结构和设计决策。
sk_buff: 数据包描述符
// include/linux/skbuff.h
;
sk_buff 的核心设计是 head/data/tail/end 四指针布局:数据在 head~end 分配的缓冲区中,data~tail 是有效数据,head~data 和 tail~end 是 headroom/tailroom。协议栈每加一层协议头,data 指针往前移,复用已有的 headroom——无需拷贝。
NAPI: 中断 + 轮询混合
// net/core/dev.c
// 问题: 高速网卡 (10Gbps+) 每秒百万包 → 每个包一次中断 → 中断风暴
// NAPI: 第一个包用中断通知 → 关中断 → softirq 中轮询收包
// 网卡驱动:
// 1. 收到包 → 关 RX 中断 → napi_schedule(&napi)
// 2. NET_RX_SOFTIRQ 触发 → napi_poll()
// → 批量收包 (一个 budget, 通常 300 包)
// → 处理完一批 → 如果还有包 → 继续轮询
// → 如果包耗尽 → 开 RX 中断 → 回到步骤 1
收包完整路径
flowchart TD
DMA["网卡 DMA<br/>→ 环形缓冲区 (RX ring)"]
DMA -->|"硬件中断"| IRQ["驱动中断 handler<br/>napi_schedule()"]
IRQ -->|"NET_RX_SOFTIRQ"| POLL["napi_poll()<br/>批量收包, 最多 300 包"]
POLL -->|"每包"| NETIF["__netif_receive_skb()"]
NETIF --> XDP["XDP hook (bpf)<br/>最早处理点"]
NETIF --> RXH{"RX handler<br/>列表检查"}
RXH -->|"tcpdump"| AF_PACKET["AF_PACKET<br/>拷贝到 packet socket"]
RXH -->|"bridge/bonding/VLAN"| REDIR["可能重定向"]
NETIF --> DELIVER["deliver_skb()"]
DELIVER --> IP_RCV["ip_rcv()<br/>L3 (IPv4)"]
IP_RCV --> IP_LOCAL["ip_local_deliver()"]
IP_LOCAL --> NF{"netfilter<br/>PREROUTING"}
NF -->|"FORWARD"| FWD["转发到其他接口"]
NF -->|"INPUT"| IP_FINISH["ip_local_deliver_finish()"]
IP_FINISH --> TCP_RCV["tcp_v4_rcv()<br/>L4 (TCP)"]
TCP_RCV --> TCP_DO["tcp_v4_do_rcv()"]
TCP_DO --> STATE{"连接状态?"}
STATE -->|"ESTABLISHED"| FAST["tcp_rcv_established()<br/>fast path ⚡"]
STATE -->|"LISTEN"| SLOW["tcp_rcv_state_process()"]
SLOW --> QUEUE["数据入 receive queue"]
FAST --> QUEUE
QUEUE --> WAKE["sk_data_ready()<br/>唤醒阻塞的 read() ✅"]
classDef hw fill:#fff3e0,stroke:#ef6c00
classDef irq fill:#ffebee,stroke:#c62828
classDef l2 fill:#e3f2fd,stroke:#1565c0
classDef l3 fill:#f3e5f5,stroke:#7b1fa2
classDef l4 fill:#e8f5e9,stroke:#2e7d32
classDef decision fill:#fff8e1,stroke:#f9a825
class DMA,IRQ hw
class POLL,NETIF,XDP,RXH,AF_PACKET,REDIR l2
class IP_RCV,IP_LOCAL,IP_FINISH,DELIVER,NF,FWD l3
class TCP_RCV,TCP_DO,FAST,SLOW,QUEUE,WAKE l4
class STATE decision
Multi-Queue 与 RSS
RSS (Receive Side Scaling):
网卡用 hash(src_ip, dst_ip, src_port, dst_port) % N
→ N 个接收队列 → N 个 CPU
NAPI 的 napi_struct 是 per-queue 的:
→ 每个队列独立 NAPI → 收包并行
→ 相同 flow 的包始终去同一队列 → TCP 保序
XPS (Transmit Packet Steering):
发送端的多队列: 类似但用于 TX
net_device: 网络设备抽象
// include/linux/netdevice.h
;
调试
# 收发包统计
# 软中断统计 (NET_RX/NET_TX)
|
# NAPI 统计 (per-queue 轮询)
|
# 丢包原因 (drop counter)
参考
- 源码:
net/core/dev.c,include/linux/skbuff.h,include/linux/netdevice.h - 内核文档:
Documentation/networking/ - LWN: "The Linux networking stack", "NAPI design"
关键词: sk_buff, NAPI, NET_RX_SOFTIRQ, multi-queue, RSS, net_device, XDP