From 562a6c42405d0a5a8d8be270a35d8bcf66465cf9 Mon Sep 17 00:00:00 2001 From: LinuxDev9002 Date: Sun, 26 Jul 2026 09:27:20 -0700 Subject: [PATCH] docs: restore tutorial fidelity checks --- .../skills/write-bpf-production-tutorial/SKILL.md | 12 +++++++----- README.md | 2 +- README.zh.md | 2 +- src/56-tc-flow-index/README.md | 2 +- src/56-tc-flow-index/README.zh.md | 2 +- src/57-oom-watch/README.md | 8 ++++---- src/57-oom-watch/README.zh.md | 8 ++++---- src/60-afxdp-dump/README.md | 14 +++++++------- src/60-afxdp-dump/README.zh.md | 14 +++++++------- src/SUMMARY.md | 2 +- src/SUMMARY.zh.md | 2 +- src/compatibility.md | 2 +- src/compatibility.zh.md | 2 +- 13 files changed, 37 insertions(+), 35 deletions(-) diff --git a/.agents/skills/write-bpf-production-tutorial/SKILL.md b/.agents/skills/write-bpf-production-tutorial/SKILL.md index cf575a9..cd00fb2 100644 --- a/.agents/skills/write-bpf-production-tutorial/SKILL.md +++ b/.agents/skills/write-bpf-production-tutorial/SKILL.md @@ -5,13 +5,13 @@ description: Write or rewrite bilingual bpf-developer-tutorial lessons by assign # Write a BPF Tutorial -Keep one writer for the complete reader-facing text. One Claude Opus process performs one free, paragraph-by-paragraph pass over one tutorial's English and Chinese README pair. Codex coordinates the invocation and performs mechanical checks without becoming a second writer or reviewer. +Keep one writer for the complete reader-facing text. One Claude Opus process performs one free, paragraph-by-paragraph pass over one tutorial's English and Chinese README pair. Codex coordinates the invocation and performs integrity and technical-fidelity checks without becoming a second prose writer or reviewer. ## 1. Give Opus the complete task once Use the exact model ID `claude-opus-4-5-20251101`. Stop when that model is unavailable instead of substituting another model. -Run one non-interactive invocation from the repository root for one tutorial directory. Name that tutorial's English and Chinese README pair, the applicable `scripts/guideline_advance.md` or `scripts/guideline_basic.md`, and existing tutorials as general references. Ask Claude to revise every paragraph freely from the reader's perspective, improve readability, adjust content or structure wherever useful, finish both files before returning, and ask no questions. +Run one non-interactive invocation from the repository root for one tutorial directory. Name that tutorial's English and Chinese README pair, its implementation, headers, Makefile, tests, the applicable `scripts/guideline_advance.md` or `scripts/guideline_basic.md`, and existing tutorials as general references. Ask Claude to read those sources, keep technical claims grounded in them, revise every paragraph freely from the reader's perspective, improve readability, adjust content or structure wherever useful, finish both files before returning, and ask no questions. Start a separate Claude process for every additional tutorial. Never batch README pairs from different tutorial directories into one process. @@ -25,10 +25,12 @@ Reader-facing prose must not use em dashes, doubled Chinese em dashes, or en das Use exactly one Claude writing pass per tutorial. Do not ask Claude to review its result, respond to a defect list, polish selected paragraphs, or rewrite the tutorial again. Do not invoke another model, subagent, or independent reviewer for the prose. When the result needs another writing pass, report that fact to the user and wait for an explicit request. -## 3. Perform mechanical checks only +## 3. Check integrity and technical fidelity -Check only that the intended files exist, remain nonempty, stay within the requested file scope, contain no merge markers, and expose no local paths, usernames, secrets, prompts, or private infrastructure. The mandatory dash scan in the previous section is part of Codex's punctuation pass. Do not count lines or code fences as a quality proxy. Never run `sync-source-blocks.py` or compare README code fences against a complete repository source inventory as writing acceptance. Do not require the README to contain a byte-exact copy of every source file, and do not treat an omitted complete user-space loader as a failure. These checks establish basic file integrity; they are not a prose, style, structure, factual, or technical review. +Check that the intended files exist, remain nonempty, stay within the requested file scope, contain no merge markers, and expose no local paths, usernames, secrets, prompts, or private infrastructure. The mandatory dash scan in the previous section is part of Codex's punctuation pass. Do not count lines or code fences as a quality proxy. Do not require the README to contain a byte-exact copy of every source file, and do not treat an omitted complete user-space loader as a failure. -Run repository formatting or documentation validation only when it does not rewrite the text. Report mechanical failures without repairing words or asking Claude to revise them. Preserve prompts, responses, drafts, and failed runs; never delete real conversation or agent history. +Verify every included source excerpt, command, output sample, version, requirement, and behavior claim against the implementation, tests, captured evidence, or a primary source. Use `sync-source-blocks.py` for blocks intended to reproduce complete repository files when the script supports the lesson, but do not compare focused excerpts against a required inventory of every source file. Run non-rewriting repository documentation validation. When technical commands, runtime behavior, requirements, or output claims changed, run the smallest relevant build or test, or identify exact current validation evidence for the unchanged implementation. + +These are content-fidelity checks, not a second prose-writing pass. Codex may make the smallest factual correction needed to match the implementation or evidence, but must not ask another model, subagent, or independent reviewer to rewrite or polish content-only changes. Preserve prompts, responses, drafts, and failed runs; never delete real conversation or agent history. Stop with the local result unless the user explicitly asks to commit, push, or update a PR. diff --git a/README.md b/README.md index 32b11f9..bd53ce2 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Networking: - [lesson 50-tcx](src/50-tcx/README.md) Composable Traffic Control with TCX Links - [lesson 53-egress-pacer](src/53-egress-pacer/README.md) Building an Egress Pacer with BPF Qdisc - [lesson 56-tc-flow-index](src/56-tc-flow-index/README.md) Building a Top-Flow Monitor with Dual Rbtree Indexing -- [lesson 60-afxdp-dump](src/60-afxdp-dump/README.md) High-Performance UDP Packet Capture with AF_XDP +- [lesson 60-afxdp-dump](src/60-afxdp-dump/README.md) High-Performance UDP Receiving with AF_XDP Tracing: diff --git a/README.zh.md b/README.zh.md index 01f5c83..31d34b6 100644 --- a/README.zh.md +++ b/README.zh.md @@ -78,7 +78,7 @@ GPU: - [lesson 50-tcx](src/50-tcx/README.zh.md) eBPF 入门实践教程第五十篇:使用 TCX Link 实现可组合的流量控制 - [lesson 53-egress-pacer](src/53-egress-pacer/README.zh.md) eBPF 教程:用 BPF Qdisc 实现出口限速 - [lesson 56-tc-flow-index](src/56-tc-flow-index/README.zh.md) eBPF 实战教程:用双红黑树索引构建 Top-Flow 监控器 -- [lesson 60-afxdp-dump](src/60-afxdp-dump/README.zh.md) eBPF 实战教程:用 AF_XDP 实现高性能 UDP 抓包 +- [lesson 60-afxdp-dump](src/60-afxdp-dump/README.zh.md) eBPF 实战教程:用 AF_XDP 高性能接收 UDP 报文 追踪: diff --git a/src/56-tc-flow-index/README.md b/src/56-tc-flow-index/README.md index 26f3f26..6f27720 100644 --- a/src/56-tc-flow-index/README.md +++ b/src/56-tc-flow-index/README.md @@ -32,7 +32,7 @@ When a subsequent packet for this flow arrives, we find the existing entry in th ## Architecture Overview -The implementation splits into three files: +The implementation splits into four files: | File | Purpose | |------|---------| diff --git a/src/56-tc-flow-index/README.zh.md b/src/56-tc-flow-index/README.zh.md index 2c03043..6c85579 100644 --- a/src/56-tc-flow-index/README.zh.md +++ b/src/56-tc-flow-index/README.zh.md @@ -32,7 +32,7 @@ Linux 6.4 引入了引用计数,6.16 又添加了树遍历功能。两者结 ## 架构概览 -实现分为三个文件: +实现分为四个文件: | 文件 | 作用 | |------|------| diff --git a/src/57-oom-watch/README.md b/src/57-oom-watch/README.md index b1d1ffa..daee169 100644 --- a/src/57-oom-watch/README.md +++ b/src/57-oom-watch/README.md @@ -2,7 +2,7 @@ Have you ever had a container or service suddenly killed by the Linux OOM killer, leaving you with nothing but a cryptic log message? The kernel tells you *which* process it chose as a victim, but says almost nothing about the memory pressure that led there. How many times did the system try to reclaim memory? How long did each attempt take? Which kernel code paths consumed all that time? -This tutorial builds `oom-watch`, an eBPF tool that captures what happens *before* the kill. It profiles every memcg reclaim attempt as a latency histogram and a set of sampled kernel stacks, then attaches this accumulated profile to the OOM victim and tracks the process until it exits. +This tutorial builds `oom-watch`, an eBPF tool that captures what happens *before* the kill. It profiles recorded memcg reclaim intervals as a latency histogram and a set of sampled kernel stacks, then attaches this accumulated profile to the OOM victim and tracks the process until it exits. > Complete source code: @@ -17,13 +17,13 @@ Looking only at the `oom/mark_victim` tracepoint loses all this context. You see - Did reclaim come from allocations inside the cgroup, or from external proactive reclaim via `memory.reclaim`? - Which kernel functions dominated the reclaim time? -`oom-watch` answers all of these. It hooks into the kernel's vmscan tracepoints to measure every reclaim interval, samples kernel stacks to show where time was spent, and when OOM selects a victim, it snapshots the accumulated profile right alongside the victim information. +`oom-watch` answers all of these. It hooks into the kernel's vmscan tracepoints to measure matched reclaim intervals, samples kernel stacks to show where time was spent, and when OOM selects a victim, it snapshots the accumulated profile right alongside the victim information. Its drop counters expose intervals that could not be retained in the bounded state maps. ## Why eBPF for Memory Profiling? Traditional monitoring approaches have serious limitations for this use case. Polling `/proc/meminfo` or cgroup stats misses short-lived reclaim events. `perf` can capture stack traces but requires careful setup and post-processing. Neither approach easily connects reclaim activity to a specific OOM event. -eBPF changes the game. Programs run directly in the kernel, triggered by events with nanosecond precision. Maps carry state between events, letting us build histograms and correlate begin/end pairs. The ring buffer delivers events to userspace with minimal overhead. And because eBPF programs are verified before loading, there's no risk of crashing the kernel. +eBPF changes the game. Programs run directly in the kernel, triggered by events with nanosecond precision. Maps carry state between events, letting us build histograms and correlate begin/end pairs. The ring buffer delivers events to userspace with minimal overhead. The verifier rejects unsafe programs before loading, substantially reducing the risk of kernel memory corruption compared with an unchecked kernel module. For `oom-watch`, we use several tracepoints: @@ -510,7 +510,7 @@ Profiles accumulate from program attach until exit, using bounded LRU maps: 4096 ## Summary -`oom-watch` turns the chaos before an OOM kill into evidence you can examine. It measures every memcg reclaim interval, samples and ranks the kernel paths that consumed time, correctly attributes work to the target cgroup (even for cross-cgroup reclaim), and connects this profile to the victim selection and exit. +`oom-watch` turns the chaos before an OOM kill into evidence you can examine. It measures recorded memcg reclaim intervals, samples and ranks the kernel paths that consumed time, correctly attributes work to the target cgroup (even for cross-cgroup reclaim), and connects this profile to the victim selection and exit. The next time a container dies and someone asks "what happened?", you'll have more than a one-line kernel log to show them. diff --git a/src/57-oom-watch/README.zh.md b/src/57-oom-watch/README.zh.md index 05b7c62..6dbc239 100644 --- a/src/57-oom-watch/README.zh.md +++ b/src/57-oom-watch/README.zh.md @@ -2,7 +2,7 @@ 你是否遇到过容器或服务突然被 Linux OOM killer 杀掉,只留下一行不明所以的内核日志?内核会告诉你它选择了*哪个*进程作为 victim,但对于导致这一结果的内存压力几乎只字未提。系统尝试了多少次内存回收?每次花了多久?哪些内核路径消耗了这些时间? -本教程构建 `oom-watch`,一个 eBPF 工具,用于捕获 OOM kill *之前*发生的事情。它将每次 memcg 回收尝试记录为延迟直方图和采样的内核调用栈,然后将积累的 profile 附加到 OOM victim 上,并跟踪进程直到它退出。 +本教程构建 `oom-watch`,一个 eBPF 工具,用于捕获 OOM kill *之前*发生的事情。它将记录到的 memcg 回收间隔汇总为延迟直方图和采样的内核调用栈,然后将积累的 profile 附加到 OOM victim 上,并跟踪进程直到它退出。 > 完整源代码: @@ -17,13 +17,13 @@ - 回收是由 cgroup 内部的分配触发的,还是通过 `memory.reclaim` 从外部主动触发的? - 哪些内核函数占用了回收时间? -`oom-watch` 可以回答所有这些问题。它通过 hook 内核的 vmscan tracepoint 来测量每个回收间隔,采样内核调用栈以展示时间花在了哪里,当 OOM 选择 victim 时,它会将累积的 profile 快照与 victim 信息一起输出。 +`oom-watch` 可以回答所有这些问题。它通过 hook 内核的 vmscan tracepoint 来测量成功匹配的回收间隔,采样内核调用栈以展示时间花在了哪里,当 OOM 选择 victim 时,它会将累积的 profile 快照与 victim 信息一起输出。对于有界状态 map 未能保留的间隔,工具会通过 drop 计数器明确报告。 ## 为什么用 eBPF 做内存分析? 传统监控方法在这个场景下有严重的局限性。轮询 `/proc/meminfo` 或 cgroup 统计会错过短暂的回收事件。`perf` 可以捕获调用栈,但需要仔细配置和后处理。两种方法都不容易将回收活动与特定的 OOM 事件关联起来。 -eBPF 改变了这一切。程序直接在内核中运行,以纳秒级精度响应事件。Map 在事件之间传递状态,让我们可以构建直方图并关联 begin/end 对。Ring buffer 以最小的开销将事件传递给用户空间。而且因为 eBPF 程序在加载前经过验证,不会有崩溃内核的风险。 +eBPF 改变了这一切。程序直接在内核中运行,以纳秒级精度响应事件。Map 在事件之间传递状态,让我们可以构建直方图并关联 begin/end 对。Ring buffer 以最小的开销将事件传递给用户空间。验证器会在加载前拒绝不安全的程序,与未经检查的内核模块相比,这显著降低了破坏内核内存的风险。 对于 `oom-watch`,我们使用几个 tracepoint: @@ -510,7 +510,7 @@ Profile 从程序附加开始累积直到退出,使用有界的 LRU map:4096 ## 总结 -`oom-watch` 将 OOM kill 之前的混乱变成可以检查的证据。它测量每个 memcg 回收间隔,采样并排名消耗时间的内核路径,正确归因工作到目标 cgroup(即使对于跨 cgroup 回收),并将此 profile 与 victim 选择和退出关联起来。 +`oom-watch` 将 OOM kill 之前的混乱变成可以检查的证据。它测量记录到的 memcg 回收间隔,采样并排名消耗时间的内核路径,正确归因工作到目标 cgroup(即使对于跨 cgroup 回收),并将此 profile 与 victim 选择和退出关联起来。 下次容器死掉有人问"发生了什么?"时,你将不仅仅有一行内核日志可以展示。 diff --git a/src/60-afxdp-dump/README.md b/src/60-afxdp-dump/README.md index bb907e7..268f471 100644 --- a/src/60-afxdp-dump/README.md +++ b/src/60-afxdp-dump/README.md @@ -1,8 +1,8 @@ -# eBPF Tutorial: High-Performance UDP Packet Capture with AF_XDP +# eBPF Tutorial: High-Performance UDP Receiving with AF_XDP -Have you ever wondered how packet capture tools like Suricata or high-frequency trading systems receive millions of packets per second without drowning in kernel overhead? The secret is bypassing most of the network stack entirely. AF_XDP lets you intercept packets at the driver boundary, copy them directly into your application's memory, and process them without system calls for every packet. +Have you ever wondered how high-performance network applications receive millions of packets per second without drowning in kernel overhead? The key is bypassing most of the network stack. AF_XDP lets you select packets at the driver boundary, copy them directly into your application's memory, and process them without a system call for every packet. -This tutorial builds a complete packet capture tool from scratch using the raw AF_XDP interface. No helper libraries, no magic abstractions. You'll see exactly how UMEM registration, ring buffers, and XDP redirection work together. The result is `afxdp-dump`, a tool that captures IPv4 UDP packets for a specific port, prints a payload preview, and properly recycles every frame to keep receiving indefinitely. +This tutorial builds an exclusive packet receiver from scratch using the raw AF_XDP interface. No helper libraries, no magic abstractions. You'll see exactly how UMEM registration, ring buffers, and XDP redirection work together. The result is `afxdp-dump`, a tool that redirects IPv4 UDP packets for a specific port away from the normal socket stack, prints a payload preview, and properly recycles every frame to keep receiving indefinitely. > Complete source code: @@ -12,7 +12,7 @@ Traditional packet capture with `libpcap` or raw sockets has a fundamental probl AF_XDP solves this by establishing shared memory between kernel and userspace. The kernel writes packets directly into memory your application can read. You communicate through lock-free ring buffers instead of system calls. A single `poll()` can wake you for hundreds of packets. This architecture enables packet rates of millions per second on commodity hardware. -The technology has real production use. Meta runs AF_XDP in their load balancers. Cilium uses it for Kubernetes networking. High-frequency trading firms use it to shave microseconds off their latency. Even if you never build a trading system, understanding AF_XDP teaches you patterns that appear throughout high-performance systems: shared memory, lock-free data structures, and explicit ownership transfer. +Understanding AF_XDP also teaches patterns that appear throughout high-performance systems: shared memory, lock-free data structures, and explicit ownership transfer. ## The AF_XDP Architecture @@ -121,7 +121,7 @@ The UDP validation ensures the length field is sane and that the destination por The XSKMAP lookup is also a safety check. If userspace hasn't registered a socket for this queue, the lookup returns NULL and we pass the packet to the normal stack. When everything checks out, `bpf_redirect_map()` sends the packet to AF_XDP. The second argument is the queue index, which becomes the map key. The third argument is the fallback action if something goes wrong. -One important detail: once a packet is redirected, it's consumed by AF_XDP. The regular socket stack will never see it. This is exactly what we want for a capture tool, but it means you need to be careful about what you redirect. +One important detail: once a packet is redirected, it's consumed by AF_XDP. The regular socket stack will never see it. This is expected for this exclusive receiver, but it means you need to be careful about what you redirect. ## The Userspace Application @@ -713,9 +713,9 @@ This example is deliberately minimal: receive-only, single-queue, single-buffer ## Summary -AF_XDP gives you kernel-bypass packet reception with eBPF's safety guarantees. The XDP program selects traffic at the driver boundary, the XSKMAP routes packets to your socket, and lock-free ring buffers transfer data without system calls. This example showed the complete receive contract: post frames to Fill, receive descriptors on RX, process packets, recycle frames back to Fill. +AF_XDP lets packet reception bypass the normal network stack while retaining eBPF's safety checks. The XDP program selects traffic at the driver boundary, the XSKMAP routes packets to your socket, and lock-free ring buffers transfer data without system calls. This example showed the complete receive contract: post frames to Fill, receive descriptors on RX, process packets, recycle frames back to Fill. -Understanding this flow is valuable beyond packet capture. The patterns here, shared memory between kernel and userspace, explicit ownership transfer, lock-free synchronization, appear throughout high-performance systems from databases to GPU drivers. +Understanding this flow is valuable beyond packet reception. The patterns here, shared memory between kernel and userspace, explicit ownership transfer, lock-free synchronization, appear throughout high-performance systems from databases to GPU drivers. > If you'd like to dive deeper into eBPF, check out our tutorial repository at or visit our website at . diff --git a/src/60-afxdp-dump/README.zh.md b/src/60-afxdp-dump/README.zh.md index 84085c9..c21a4a2 100644 --- a/src/60-afxdp-dump/README.zh.md +++ b/src/60-afxdp-dump/README.zh.md @@ -1,8 +1,8 @@ -# eBPF 实战教程:用 AF_XDP 实现高性能 UDP 抓包 +# eBPF 实战教程:用 AF_XDP 高性能接收 UDP 报文 -你有没有好奇过 Suricata 这样的抓包工具或者高频交易系统是如何每秒接收数百万个报文而不被内核开销拖垮的?秘密在于绕过大部分网络协议栈。AF_XDP 让你在网卡驱动入口拦截报文,直接复制到应用程序的内存空间,处理时几乎不需要为每个报文做系统调用。 +你有没有好奇过高性能网络应用是如何每秒接收数百万个报文而不被内核开销拖垮的?关键在于绕过大部分网络协议栈。AF_XDP 让你在网卡驱动入口选择报文,直接复制到应用程序的内存空间,处理时不需要为每个报文做一次系统调用。 -本教程从零开始,使用原始的 AF_XDP 接口构建一个完整的抓包工具。没有辅助库,没有魔法抽象。你会清楚看到 UMEM 注册、ring buffer 和 XDP 重定向是如何协同工作的。最终成果是 `afxdp-dump`,一个捕获指定端口 IPv4 UDP 报文、打印 payload 预览、并正确回收每个 frame 以持续接收的工具。 +本教程从零开始,使用原始的 AF_XDP 接口构建一个独占式报文接收器。没有辅助库,没有魔法抽象。你会清楚看到 UMEM 注册、ring buffer 和 XDP 重定向是如何协同工作的。最终成果是 `afxdp-dump`,它把指定端口的 IPv4 UDP 报文从普通 socket 协议栈重定向到用户态,打印 payload 预览,并正确回收每个 frame 以持续接收。 > 完整源代码: @@ -12,7 +12,7 @@ AF_XDP 通过在内核和用户态之间建立共享内存来解决这个问题。内核把报文直接写入你的应用程序可以读取的内存,双方通过无锁的 ring buffer 通信,而不是系统调用。一次 `poll()` 就能唤醒你处理数百个报文。这种架构在普通硬件上就能达到每秒数百万报文的接收速率。 -这项技术已经在生产环境中使用。Meta 的负载均衡器运行 AF_XDP,Cilium 用它做 Kubernetes 网络,高频交易公司用它来缩短微秒级延迟。即使你永远不会构建交易系统,理解 AF_XDP 也能教会你高性能系统中反复出现的模式:共享内存、无锁数据结构、显式的所有权转移。 +理解 AF_XDP 也能让你掌握高性能系统中反复出现的模式:共享内存、无锁数据结构和显式的所有权转移。 ## AF_XDP 架构 @@ -121,7 +121,7 @@ UDP 验证确保长度字段合理,目的端口与目标匹配。只有这时 XSKMAP lookup 也是一个安全检查。如果用户态没有为这个 queue 注册 socket,lookup 返回 NULL,我们就把报文传递给普通协议栈。当所有检查都通过时,`bpf_redirect_map()` 把报文发送到 AF_XDP。第二个参数是 queue index,会成为 map 的 key。第三个参数是出错时的回退 action。 -一个重要细节:一旦报文被重定向,它就被 AF_XDP 消费了。普通的 socket 协议栈永远不会看到它。这正是抓包工具需要的,但这意味着你需要小心选择重定向什么。 +一个重要细节:一旦报文被重定向,它就被 AF_XDP 消费了。普通的 socket 协议栈永远不会看到它。这符合这个独占式接收器的设计,但也意味着你需要小心选择重定向哪些报文。 ## 用户态应用程序 @@ -713,9 +713,9 @@ Packet 65 证明至少有一个 frame 完成了完整的所有权周期:发布 ## 总结 -AF_XDP 给你提供了具有 eBPF 安全保证的内核旁路报文接收。XDP 程序在驱动边界选择流量,XSKMAP 把报文路由到你的 socket,无锁的 ring buffer 不用系统调用就能传输数据。这个例子展示了完整的接收契约:向 Fill 发布 frame,在 RX 上接收 descriptor,处理报文,把 frame 回收到 Fill。 +AF_XDP 让报文接收绕过普通网络协议栈,同时保留 eBPF 的安全检查。XDP 程序在驱动边界选择流量,XSKMAP 把报文路由到你的 socket,无锁的 ring buffer 不用系统调用就能传输数据。这个例子展示了完整的接收契约:向 Fill 发布 frame,在 RX 上接收 descriptor,处理报文,把 frame 回收到 Fill。 -理解这个流程的价值超越了抓包本身。这里的模式包括内核与用户态之间的共享内存、显式的所有权转移和无锁同步,这些模式在从数据库到 GPU 驱动的各种高性能系统中反复出现。 +理解这个流程的价值超越了报文接收本身。这里的模式包括内核与用户态之间的共享内存、显式的所有权转移和无锁同步,这些模式在从数据库到 GPU 驱动的各种高性能系统中反复出现。 > 如果你想深入了解 eBPF,请查看我们的教程代码仓库 或访问我们的网站 。 diff --git a/src/SUMMARY.md b/src/SUMMARY.md index e19034b..e110c20 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -70,7 +70,7 @@ Networking: - [lesson 50-tcx](50-tcx/README.md) Composable Traffic Control with TCX Links - [lesson 53-egress-pacer](53-egress-pacer/README.md) Building an Egress Pacer with BPF Qdisc - [lesson 56-tc-flow-index](56-tc-flow-index/README.md) Building a Top-Flow Monitor with Dual Rbtree Indexing -- [lesson 60-afxdp-dump](60-afxdp-dump/README.md) High-Performance UDP Packet Capture with AF_XDP +- [lesson 60-afxdp-dump](60-afxdp-dump/README.md) High-Performance UDP Receiving with AF_XDP Tracing: diff --git a/src/SUMMARY.zh.md b/src/SUMMARY.zh.md index 0a6d8b2..5e483f5 100644 --- a/src/SUMMARY.zh.md +++ b/src/SUMMARY.zh.md @@ -70,7 +70,7 @@ GPU: - [lesson 50-tcx](50-tcx/README.zh.md) eBPF 入门实践教程第五十篇:使用 TCX Link 实现可组合的流量控制 - [lesson 53-egress-pacer](53-egress-pacer/README.zh.md) eBPF 教程:用 BPF Qdisc 实现出口限速 - [lesson 56-tc-flow-index](56-tc-flow-index/README.zh.md) eBPF 实战教程:用双红黑树索引构建 Top-Flow 监控器 -- [lesson 60-afxdp-dump](60-afxdp-dump/README.zh.md) eBPF 实战教程:用 AF_XDP 实现高性能 UDP 抓包 +- [lesson 60-afxdp-dump](60-afxdp-dump/README.zh.md) eBPF 实战教程:用 AF_XDP 高性能接收 UDP 报文 追踪: diff --git a/src/compatibility.md b/src/compatibility.md index a226f33..6570ec3 100644 --- a/src/compatibility.md +++ b/src/compatibility.md @@ -64,7 +64,7 @@ This table is generated from each tutorial's `.config` metadata. `Minimum kernel | [eBPF Tutorial: Building a DNS-Derived IP Allowlist with cgroup BPF](55-dns-egress/README.md) | 5.12 | Required feature | x86_64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_CGROUP_BPF=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_INET=y | None | Required | CI build | | [eBPF Tutorial: Building a Top-Flow Monitor with Dual Rbtree Indexing](56-tc-flow-index/README.md) | 6.16 | Required feature | x86_64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_NET_SCHED=y, CONFIG_NET_CLS_BPF=y | Network interface | Required | CI build | | [eBPF Tutorial: Profiling Memory Reclaim Before an OOM Kill](57-oom-watch/README.md) | 7.1 | Required feature | x86_64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_BPF_EVENTS=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_MEMCG=y | None | Required | CI build | -| [eBPF Tutorial: High-Performance UDP Packet Capture with AF_XDP](60-afxdp-dump/README.md) | 5.7 | Required feature | x86_64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_XDP_SOCKETS=y | Network interface | Required | CI build | +| [eBPF Tutorial: High-Performance UDP Receiving with AF_XDP](60-afxdp-dump/README.md) | 5.7 | Required feature | x86_64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_XDP_SOCKETS=y | Network interface | Required | CI build | | [eBPF Tutorial: cgroup-based Policy Control](cgroup/README.md) | 5.8 | Required feature | x86_64, arm64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_CGROUPS=y, CONFIG_CGROUP_BPF=y, CONFIG_CGROUP_DEVICE=y, CONFIG_DEBUG_INFO_BTF=y | None | Required | CI build | | [eBPF Tutorial by Example: BPF Arena for Zero-Copy Shared Memory](features/bpf_arena/README.md) | 6.9 | Tutorial docs | x86_64, arm64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y | None | Required | CI build | | [eBPF Tutorial: BPF Iterators for Kernel Data Export](features/bpf_iters/README.md) | 5.8 | Tutorial docs | x86_64, arm64 | Required | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_DEBUG_INFO_BTF=y | None | Required | CI build | diff --git a/src/compatibility.zh.md b/src/compatibility.zh.md index 34f6b1b..eaf59c8 100644 --- a/src/compatibility.zh.md +++ b/src/compatibility.zh.md @@ -64,7 +64,7 @@ | [eBPF 实战教程:用 cgroup BPF 构建基于 DNS 的 IP 允许列表](55-dns-egress/README.zh.md) | 5.12 | 必需特性 | x86_64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_CGROUP_BPF=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_INET=y | 无 | 需要 | CI 构建测试 | | [eBPF 实战教程:用双红黑树索引构建 Top-Flow 监控器](56-tc-flow-index/README.zh.md) | 6.16 | 必需特性 | x86_64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_NET_SCHED=y, CONFIG_NET_CLS_BPF=y | 网络接口 | 需要 | CI 构建测试 | | [eBPF 实战教程:在 OOM Kill 之前分析内存回收](57-oom-watch/README.zh.md) | 7.1 | 必需特性 | x86_64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_BPF_EVENTS=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_MEMCG=y | 无 | 需要 | CI 构建测试 | -| [eBPF 实战教程:用 AF_XDP 实现高性能 UDP 抓包](60-afxdp-dump/README.zh.md) | 5.7 | 必需特性 | x86_64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_XDP_SOCKETS=y | 网络接口 | 需要 | CI 构建测试 | +| [eBPF 实战教程:用 AF_XDP 高性能接收 UDP 报文](60-afxdp-dump/README.zh.md) | 5.7 | 必需特性 | x86_64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y, CONFIG_XDP_SOCKETS=y | 网络接口 | 需要 | CI 构建测试 | | [eBPF 实例教程:基于 cgroup 的策略控制](cgroup/README.zh.md) | 5.8 | 必需特性 | x86_64, arm64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_CGROUPS=y, CONFIG_CGROUP_BPF=y, CONFIG_CGROUP_DEVICE=y, CONFIG_DEBUG_INFO_BTF=y | 无 | 需要 | CI 构建测试 | | [eBPF 实例教程:BPF Arena 零拷贝共享内存](features/bpf_arena/README.zh.md) | 6.9 | 教程文档 | x86_64, arm64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_BPF_JIT=y, CONFIG_DEBUG_INFO_BTF=y | 无 | 需要 | CI 构建测试 | | [eBPF 教程:BPF 迭代器用于内核数据导出](features/bpf_iters/README.zh.md) | 5.8 | 教程文档 | x86_64, arm64 | 需要 | CONFIG_BPF=y, CONFIG_BPF_SYSCALL=y, CONFIG_DEBUG_INFO_BTF=y | 无 | 需要 | CI 构建测试 |