首页
关于
Search
1
PacketForge 博客部署文档
16 阅读
2
深入 SONiC 与 SAI:从命令行到芯片的完整数据之旅
14 阅读
3
DPU 与 CPO:AI 时代的网络基础设施革命
11 阅读
4
Broadcom芯片
10 阅读
5
DPDK高性能网络
10 阅读
默认分类
交换芯片
高性能网络
AI算力网络
WebSocket高性能项目
DPDK 成长路线
①性能工程基础
②DPDK 源码深读
③用户态协议栈
④软件交换与 SONiC
⑤PCIe、虚拟化与 DPU
⑥面试与复盘
登录
Search
标签搜索
DPDK→DPU 学习路线
P0
P1
P2
P3
P5
PCIe
P4
P6
libmtcp
NUMA
mTCP
OVS
SONiC
SAI
DPU
perf
gdb
EAL
mempool
PacketForge
累计撰写
53
篇文章
累计收到
3
条评论
首页
栏目
页面
关于
最新文章
热门文章
评论最多
点赞最多
2026-08-18
P0-07 · 内核网络栈初探:一个包的内核之旅
对应路线图:Phase 0 (Day 1-21) | 内核 v6.6 | 上一篇:P0-06 gdb | 下一篇:P1-01 EAL一句话定位一个包进入内核后要过 6 站:XDP → tap(tcpdump)→ ingress qdisc + netfilter → rx_handler → 协议分发 → 投递/丢弃。每一站都是查表和判断——这就是内核"通用性"的代价,也是 DPDK 绕开它的理由。本讲把 netif_receive_skb_core 逐站读完。真实源码精读:收包核心函数逐站过入口三层(net/core/dev.c):netif_receive_skb()(dev.c:5899)打 trace 后进 netif_receive_skb_internal()(dev.c:5824)——这里先做 RPS 判断,把包交给别的 CPU 的 backlog 队列(dev.c:5834-5845 的 enqueue_to_backlog);然后进入主角:static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc, struct packet_type **ppt_prev) // dev.c:5434 { // ... __this_cpu_inc(softnet_data.processed); // dev.c:5461注意 netif_receive_skb_core() 这个公开包装(dev.c:5666-5672)只做一件事:rcu_read_lock() 后调核心函数——后续所有查表都在 RCU 读临界区里进行,和 P0-04 的 list_for_each_entry_rcu 正好接上。第 ① 站 · 通用 XDP(dev.c:5463-5474):do_xdp_generic 执行 eBPF 程序,返回非 XDP_PASS 直接丢弃。这是内核里"最早处理包"的位置,也是 AF_XDP 生态的挂载点。第 ② 站 · tap(dev.c:5488-5498):遍历 ptype_all 列表——tcpdump / AF_PACKET 在这里拿到包的副本。注意这里的模式:pt_prev 先记录、延迟到下一站再真正 deliver,这是收包路径"减少函数调用深度"的经典技巧。第 ③ 站 · ingress qdisc + netfilter(dev.c:5500-5516):#ifdef CONFIG_NET_INGRESS if (static_branch_unlikely(&ingress_needed_key)) { bool another = false; skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev, &another); if (another) goto another_round; // tc redirect 了包 → 从头再走一遍 if (!skb) goto out; // 被 tc 吃掉(限速/丢弃) // ... if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < 0) // iptables PREROUTING goto out; } #endifsch_handle_ingress 是 tc 限速/重定向的落点;nf_ingress 是 netfilter PREROUTING 钩子(README 07-kernel-net:61-89 那张五钩子图里最上面那个)。another_round 意味着包可能被 redirect 后重头再走一遍全部流程。第 ④ 站 · rx_handler(dev.c:5534-5554):网桥、bonding、OVS 这类"设备接管者"。四种返回值:RX_HANDLER_CONSUMED(包归它了,结束)、ANOTHER(再来一轮)、EXACT(只投精确匹配的协议)、PASS(继续往下)。第 ⑤ 站 · 协议分发(dev.c:5593-5603):按 skb->protocol 查 ptype_base 哈希表——ip_rcv 就是在这里被找到并延迟记录的。第 ⑥ 站 · 收尾(dev.c:5610-5625):有 pt_prev 就交给 __netif_receive_skb_one_core 投递;没人认领则 kfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO)。包住的地方:struct sk_buff(include/linux/skbuff.h:843)——next/prev 挂队列、len, data_len 总长与分片长(skbuff.h:892-893)、cb[48] 供各层传私有数据(skbuff.h:876)。对应 DPDK 的 rte_mbuf(rte_mbuf_core.h:467),差异见对照表。实验怎么跑(README 07-kernel-net:46-53, 147-161)# 终端 1:挂探针 bpftrace -e 'kprobe:__netif_receive_skb_core { printf("%s\n", kstack); }' # 终端 2:发一个包 ping -c 1 8.8.8.8 # 预期栈:__netif_receive_skb_core → ip_rcv → ip_local_deliver → icmp_rcv # 丢包与状态 dropwatch -l kas # 内核丢包点实时统计 conntrack -L 2>/dev/null || cat /proc/net/nf_conntrack # 连接跟踪表 ss -s # socket 汇总tc 限速的例子(README 07-kernel-net:94-106)也跑一遍:htb qdisc + u32 filter 把某个源 IP 限到 100mbit——你会直观看到第 ③ 站的 sch_handle_ingress 在起作用。🐧 内核对照DPDK内核关键差异rte_eth_rx_burst 拿 mbuf中断 → NAPI → softirq → skb轮询 vs 中断,见 P0-03收包 1 阶段直达应用8 阶段(README 07-kernel-net:15-29)每站都是查表/判断的通用开销rte_flow 卸载到网卡tc/netfilter 软件过滤硬件卸载 vs 软件逐包KNI 回灌内核(README 07-kernel-net:127-143)原生协议栈DPDK 世界里的"内核通道":rte_kni_tx_burst(:141)送控制包,rte_kni_handle_request(:142)接回复面试 3 问__netif_receive_skb_core 按顺序过了哪几站? → XDP(dev.c:5463-5474)→ tap(dev.c:5488-5498)→ ingress qdisc + netfilter(dev.c:5500-5516)→ rx_handler(dev.c:5534-5554)→ 协议分发(dev.c:5593-5603)→ deliver/drop(dev.c:5610-5625)。RPS 是什么、在哪判断? → 把软中断处理分摊到其他 CPU:get_rps_cpu 选核后 enqueue_to_backlog 入对方队列(dev.c:5834-5845)。是内核版的"RSS 分流"——P1-07 会讲 RSS 与它的对照。为什么内核路径比 DPDK 慢一个数量级? → 8 个阶段每站查表/判断(README 07-kernel-net:15-29),加 3 次拷贝和上下文切换;DPDK 1 次 DMA 直达应用(README 03-pcie:13-25)。不是内核写得烂,是通用性的代价。数据落点perf-data/P0/07-kernel-net/:bpftrace-kstack.txt(真实调用栈)、dropwatch.txt、conntrack.txt、tc-htb.txt(限速前后的 iperf3 对比)。
2026年08月18日
0 阅读
0 评论
0 点赞
第 1/1 页 · 本页 1 条 · 共 1 条