📊 一、Linux 内核网络知识图谱

Linux 网络子系统架构节点核心索引:
├── 用户态层
│ ├── App:用户应用程序(Web服务器、Ping、Traceroute)
│ └── Tools:配置工具(ip、tc、ethtool)
├── Socket/接口层
│ ├── Sock:Socket 系统调用(socket、bind、sendmsg)
│ └── Netlink:内核配置总线(route、neigh、addr)
├── 传输层 (L4)
│ └── TCP/UDP/ICMP:L4 协议处理(tcp_v4_rcv、udp_rcv)
├── 网络层 (L3) —— 核心转发
│ ├── IP:IPv4 协议栈(ip_rcv、ip_forward、ip_local_deliver、分片重组)
│ ├── Route:路由表 FIB(fib_lookup、fib_nh、fib_trie)
│ ├── Cache:路由缓存 DST(dst_entry、RCU 读锁、垃圾回收)
│ └── Neigh:邻居子系统 ARP/ND(NUD 状态机、arp_queue、代理ARP)
├── 链路层 (L2)
│ ├── Bridge:网桥(MAC 学习 FDB、生成树 STP、泛洪)
│ └── Qdisc:流量控制队列(HTB、SFQ、qdisc_run、dev_queue_xmit)
└── 驱动与硬件层
├── NAPI:收包软中断(net_rx_action、budget预算、NAPI轮询)
├── TXSoft:发包软中断(net_tx_action、释放skb、唤醒暂停队列)
├── IRQ:硬中断(关中断、最小操作、触发napi_schedule)
├── Dev:网卡驱动(注册net_device、hard_start_xmit)
└── Hw:物理网卡(DMA传输、发送/接收环形缓冲区)
🧩 二、十大核心知识模块
1. 数据结构基石
sk_buff(套接字缓冲区):Linux网络包的唯一载体。
- 零拷贝设计:通过
skb_push(加头)、skb_pull(去头)、skb_put(加数据)操作 head/data/tail/end 四个指针,实现各层协议头添加与剥离无数据拷贝。 - 引用计数:
users(结构体引用)和 dataref(数据区引用)协同,支持 skb_clone(浅拷贝)和 skb_copy(深拷贝)。
net_device(网络设备):物理网卡与虚拟网卡的统一抽象。包含 hard_start_xmit(发送函数)、flags(运行状态)、features(硬件卸载能力,如 NETIF_F_HW_CSUM、NETIF_F_TSO)。
2. 收包路径 RX(中断/软中断/NAPI)
- 硬中断(Top Half):执行时间极短,仅做“关中断”、“记录数据”、“调用
napi_schedule”后立即返回。 - 软中断(Bottom Half):
net_rx_action 处理。引入了 NAPI(New API)。 - NAPI 核心机制:
- 高负载时关闭硬中断,转而在软中断中主动轮询网卡。
budget 预算机制:防止单次软中断处理过多包导致 CPU 饿死(默认 64/300)。process_backlog:为非 NAPI 老驱动提供兼容的后备处理函数。
- RX 路径完整调用链:
HardIRQ -> napi_schedule -> net_rx_action -> poll -> netif_receive_skb -> ip_rcv / br_handle_frame。
3. 发包路径 TX / QoS
dev_queue_xmit:所有 L3 协议(IP、ARP)发送的统一入口。- 流量控制(Qdisc / 队列规则):Linux 强大的 QoS 层。通过
qdisc->enqueue 入队,qdisc->dequeue 出队,支持 HTB、SFQ 等复杂调度。 - 流控状态机:驱动检测到硬件 FIFO 满时,调用
netif_stop_queue(停止发送);硬件空间恢复后,调用 netif_wake_queue(唤醒重试)。 - 发送软中断(
net_tx_action):负责释放已发送完毕的 sk_buff,并唤醒因锁竞争而等待发送的设备。
4. 路由子系统 FIB / 缓存 / 查找
- 数据分层:
fib_info(转发动作:下一跳、出接口)。fib_node(目的地网络,按掩码分组)。fib_alias(策略:TOS、优先级)。- 复用设计:多个
fib_alias 可共享同一个 fib_info,大幅节省内存。
- 查找逻辑:
- LPM 最长前缀匹配:按
fn_zone 从 32 到 0 遍历,取掩码最长的路由。 - 双表设计:优先查
ip_fib_local_table(本机地址,极小),再查 ip_fib_main_table。 - 策略路由:
fib_rules 链表,优先级决定匹配顺序。支持按 iif、fwmark、src_ip 选表。
- 路由缓存(DST Cache):
- 核心是
dst_entry 结构中的 input 和 output 函数指针。 - RCU 读锁:查找几乎无锁,性能极高。
- 垃圾回收:异步
rt_check_expire 配合同步 rt_garbage_collect 双重机制。
5. 邻居子系统 ARP / NUD
- 通用基础设施:ARP(IPv4)和 ND(IPv6)共享同一套
neigh_table、struct neighbour 代码。 - NUD 状态机(网络不可达检测):
REACHABLE(可达) → 超时 → STALE(可能过期)。STALE 发数据 → DELAY(等待上层 TCP ACK 确认,优化窗口)。- 窗口过期未确认 →
PROBE(主动发送单播探测)。 - 探测超时 →
FAILED(解析失败)。
- ARP 核心逻辑:
- 代理 ARP:
arp_fwd_proxy 检查,arp_ignore 与 arp_filter 防震荡。 - 免费 ARP:用于 IP 冲突检测与 VIP 迁移后快速收敛。
- 队列(
arp_queue):每个邻居表项拥有独立队列,解析期间数据包入队等待。
6. 网桥 Bridging / STP
- 二层交换核心:基于 MAC 地址学习(FDB 表)转发。未知单播和广播采用泛洪。
- STP 生成树协议:
- 状态机(阻塞 -> 监听 -> 学习 -> 转发)。
- 收敛延迟:默认通过 30 秒的
Forward Delay(15秒 * 2),重大瓶颈,生产环境通常改用 RSTP 或 MSTP。
- Linux 实现差异:
br0 本身是个虚拟设备,绑定物理端口(br_add_if),并通过 br_pass_frame_up 将本地 IP 包交回网络栈处理。
7. IPv4 核心机制
- 分片与重组:
ip_fragment(发送端分片):支持快速路径(frag_list 零拷贝)和慢速路径(数据拷贝)。ip_defrag(接收端重组):通过 ipq 哈希表缓存碎片,使用定时器(默认30秒)清理死碎片。支持 重叠碎片处理(裁剪旧碎片,保留新碎片)。
- IP ID 生成:Linux 按目的 IP 在
inet_peer 中独立维护 ID 计数器,而不是全局计数器。 - 校验和设计:IP 校验和仅覆盖 IP 报头,不覆盖负载。L4 层(TCP/UDP)负责端到端校验。
- ICMP 与速率限制:
icmp_send / icmp_rcv 使用令牌桶(icmp_ratelimit)限制错误消息的发送频率,防止 ICMP 风暴。
8. 用户态配置接口
- Netlink(现代,推荐):全双工、异步、支持内核主动推送(如路由变化)。
iproute2 工具集基于此。 - ioctl(传统,弃用):单工、同步、扩展性差。
net-tools 工具集(ifconfig、route)基于此。 - /proc 与 /sys(实时调优):
/proc/sys/net/ipv4/:全局 IP 配置,如 ip_forward、ip_local_port_range。/proc/sys/net/ipv4/conf/:网卡级配置。/proc/sys/net/ipv4/neigh/:邻居子系统(ARP)调优,如 base_reachable_time、gc_thresh3。
9. 并发与锁机制(贯穿全书)
- RCU 锁(读-拷贝-更新):高频率读操作(如路由缓存查找、邻居表查找)专用的高性能锁。读端无需加锁,仅需
rcu_read_lock,大幅降低多核竞争。 - 自旋锁(Spinlock):保护短操作的临界区。软中断中常用
spin_lock_bh(关底半部)或 spin_lock_irqsave(关硬中断)。 - 信号量 / 互斥锁(Semaphore):允许睡眠,保护长耗时的配置操作。核心是
rtnl_lock,所有路由表、地址、链路配置修改都必须先获取它。
10. 常用内核调优参数(避免踩坑)
- 路由缓存/转发:
ip_forward(全局转发)、rp_filter(反向路径过滤)、net.ipv4.route.max_size(缓存上限)。 - 邻居子系统(ARP):
base_reachable_time(30秒,调大减广播)、gc_thresh3(1024,内存大可调大)、arp_ignore(多网卡防震荡)。 - 分片/重组:
ipfrag_high_thresh(256K,大流量调大)、ipfrag_time(30秒,低延迟调小)。 - ICMP 限制:
icmp_ratelimit(限制错误消息发送频率)、icmp_echo_ignore_broadcasts(防 Ping 风暴)。
🛠️ 三、常用知识点总结与高频排错“避坑”指南
| 知识点 | 核心本质 | 面试/实战极易踩坑点 |
|---|
| NAPI 机制 | 中断+轮询混合,解决中断风暴 | budget 用完退出,未清空队列时不要调用 napi_complete,否则网卡会永久卡死。 |
| sk_buff 零拷贝 | 四指针(head/data/tail/end)滑动 | 克隆的 skb 共享数据区,若修改数据必须在克隆体上深拷贝(skb_copy),否则污染原包。 |
| 路由查找 | 优先查缓存,未命中走 FIB | 策略路由(fib_rules)是按优先级顺序匹配的,配置不当可能导致流量突然“失踪”。 |
| ARP 状态机 | REACHABLE -> STALE -> DELAY | DELAY 是优化窗口(默认5秒),TCP ACK 在此窗口内可确认邻居可达无需广播探测。 |
| STP 收敛时间 | 默认 30~50 秒 | 生产环境(尤其是容器网络)必须改用 RSTP(802.1w)或 MSTP,或者直接禁用。 |
| IP 分片 | 仅第一个分片含 L4 头(端口) | 防火墙/NAT 处理分片包时必须重组才能看见端口,易被碎片攻击耗尽内存。 |
| ICMP 错误 | 错误消息触发速率限制 | 若大包不通小包通,通常是因为防火墙拦截了 ICMP_FRAG_NEEDED 导致 PMTUD 失败。 |
| rtnl_lock | 串行化路由配置修改 | 锁是信号量(可睡眠)。绝对不能在软中断上下文(如 net_rx_action)中获取它,否则触发 might_sleep 崩溃。 |