From f2af255a814019f0fb70e74f8041cff796b95cda Mon Sep 17 00:00:00 2001 From: wangxujun 02605 Date: Wed, 9 Sep 2026 10:00:18 +0800 Subject: [PATCH] docs: publish day01 note (rerun) + kb 2026-09 (3 cards) --- kb/2026-09.md | 15 +++ kb/index.md | 1 + notes/index.md | 2 +- notes/phase0/day01-pcie-topology.md | 148 +++++++--------------------- 4 files changed, 51 insertions(+), 115 deletions(-) create mode 100644 kb/2026-09.md diff --git a/kb/2026-09.md b/kb/2026-09.md new file mode 100644 index 0000000..f449ae9 --- /dev/null +++ b/kb/2026-09.md @@ -0,0 +1,15 @@ +# 2026-09 + +## 09-09 P0-PCIe 拓扑与 Config Space +- 读: Day01 讲义(融合版,X540 / uNOS M0 锚点)+ lspci 命令用法 +- 写: Day01-lecture.md 重写 + Day01 笔记(重跑版) +- 数据: BDF 地址空间 256×32×8 = 65536;Config Space 256B,前 16B 全行业统一;MSI-X 32 向量 + +## 09-09 算法-哈希表原理 +- 读: 自写理论 `algo-theory/01-hash-table.md` +- 写: LC1 参考实现(未独立完成 🔴,09-11 重做) +- 数据: 平均 O(1) 最坏 O(n);负载因子 α>0.75 扩容 rehash + +## 09-09 做了-LC1 先查后存坑 +- 坑: 先存后查 → [3,3] 把自己匹配掉(同一元素用两次) +- → 修复: 先查后存,"只向过去提问";表里只有历史没有自己 diff --git a/kb/index.md b/kb/index.md index 7d23416..e924570 100755 --- a/kb/index.md +++ b/kb/index.md @@ -6,6 +6,7 @@ DPDK 学习与应用开发的知识积累。 ## 每月记录 +[2026-09 更新](./2026-09.md) [2026-08 更新](./2026-08.md) ## 知识分类 diff --git a/notes/index.md b/notes/index.md index a561916..b457cc8 100644 --- a/notes/index.md +++ b/notes/index.md @@ -6,7 +6,7 @@ | Day | 主题 | 日期 | |-----|------|------| -| [Day 01](/notes/phase0/day01-pcie-topology) | PCIe 拓扑结构 | Jun 2026 | +| [Day 01](/notes/phase0/day01-pcie-topology) | PCIe 拓扑结构 | Sep 2026(重跑版) | | [Day 02](/notes/phase0/day02-kernel-rx-path) | 内核收包路径分析 | Jun 2026 | | [Day 03](/notes/phase0/day03-kernel-memory) | 内核内存管理 | Jun 2026 | | [Day 04](/notes/phase0/day04-rcu-lockfree) | RCU & Lock-free 编程 | Jun 2026 | diff --git a/notes/phase0/day01-pcie-topology.md b/notes/phase0/day01-pcie-topology.md index ef3cc6c..c6fe181 100755 --- a/notes/phase0/day01-pcie-topology.md +++ b/notes/phase0/day01-pcie-topology.md @@ -1,127 +1,47 @@ -# Phase 0 · Day 1: PCIe 总线拓扑与 Config Space +# Phase 0 · Day 01: PCIe 总线拓扑与 Config Space(2026-09-09 重跑版) + +> 融合锚点: uNOS M0 骨架(找到 X540 网卡)+ X540-T2 硬件 +> 配套讲义: `notes/Phase0/Day01-lecture.md`(融合版,X540 + uNOS M0 视角) --- -## 一、BDF 地址:每个设备的唯一身份 +## 一、主线:PCIe 四件套 -``` -0000 : 02 : 01 . 0 - │ │ │ └── Function (0~7) — 一个物理芯片可以有多个功能 - │ │ └────── Device (0~31) — 同一总线上最多 32 个设备 - │ └─────────── Bus (0~255) — 256 条总线 - └───────────────── Domain (0~65535) — 多 CPU socket 系统有多个 domain - -单 CPU 系统 domain=0000。多路服务器每个 socket 一个 domain。 -``` - -DPDK 通过 BDF 地址接管网卡:`dpdk-devbind.py -b vfio-pci 02:01.0` - -### 为什么需要三级? - -PCI 是树形拓扑。每个 Bridge 引入一条新 bus。256 条 bus × 32 设备 × 8 功能 = 65536 个可寻址功能。如果没有 bus 层级,只靠 5-bit device 最多 32 个设备——一张显卡+一张网卡就满了。 - -## 二、拓扑中的四种角色 - -| 角色 | 你的实例 | 职责 | -|------|---------|------| -| **Root Complex** | `00:00.0` | CPU 和 PCIe 世界的桥梁,把 load/store 翻译成 TLP | -| **PCI Bridge** | `00:11.0` → Bus 02 | 传统 PCI 桥,用 subtractive decode 转发未认领的访问 | -| **PCIe Root Port** | `00:15.0` → Bus 03 | PCIe 原生桥,点对点链路,支持更高带宽 | -| **Endpoint** | `02:01.0` `03:00.0` | 叶子节点,实际的网卡设备 | - -关键差异:`02:01.0` (e1000) 是挂在传统 PCI Bridge 后面的老式设备,多条设备共享 Bus 02。`03:00.0` (VMXNET3) 是 PCIe Endpoint,独享 Bus 03 的整条链路(5GT/s × x32)。 - -## 二、PCIe 拓扑 - -``` -[0000:00] ← Root Complex (Host Bridge) - │ CPU 访问 PCIe 设备的唯一入口 - │ - ├── 11.0 → [02] ← PCI Bridge (老式总线) - │ ├── 01.0 e1000 (Endpoint) - │ └── 04.0 e1000 (Endpoint) - │ - └── 15.0 → [03] ← PCIe Root Port (真正的 PCI Express) - └── 00.0 VMXNET3 (Endpoint) -``` - -数据流:CPU → Root Complex → TLP 封装 → PCIe 链路 → Endpoint。 - -## 三、Config Space 完整解码 - -e1000 (02:01.0) 的 256 字节 Config Space,逐字段解码: - -| Offset | 字段 | Hex 值 | 含义 | -|--------|------|--------|------| -| 0x00-01 | Vendor ID | 0x8086 | Intel | -| 0x02-03 | Device ID | 0x100f | 82545EM | -| 0x04-05 | Command | 0x0113 | IO+Mem enable, BusMaster OFF | -| 0x0a-0b | Class Code | 0x020000 | Network Controller | -| 0x0e | Header Type | 0x00 | Endpoint | -| 0x10-13 | BAR0 | 0xfd5c0004 | Memory@0xfd5c0000, 64bit, 128KB, Non-Prefetchable | -| 0x18-1b | BAR2 | 0xfdff0004 | Memory@0xfdff0000, 64KB | -| 0x20-23 | BAR4 | 0x00002001 | IO Port@0x2000 | -| 0x34 | Capability Ptr | 0xdc | 链表起点 | -| 0x3c | Interrupt Line | 0x07 | IRQ 7 | -| 0x3d | Interrupt Pin | 0x01 | INTA# | - -BAR flag bit 解码: bit0=Memory/IO, bit[2:1]=32b/64b, bit3=Prefetchable。`0xfd5c0004` 中的 `4` = 0100₂ → 64-bit Memory, Non-Prefetchable。真实基址 = 0xfd5c0004 & ~0xF = 0xfd5c0000。 - -Capability 链表: 0xdc→PM(ID=1)→0xe4→PCI-X(ID=7)→0x00(End)。 - -## 四、VMXNET3 对比 (真正的 PCIe 设备) - -| | e1000 | VMXNET3 | +| 概念 | 一句话 | 你的类比 | |---|---|---| -| 总线 | PCI-X (老) | PCIe v2.0 | -| Capability | PM + PCI-X | PM + PCIe Express + MSI + MSI-X + Serial# | -| MSI-X | 无 | 25 向量, BAR2 offset 0, PBA offset 0x1000 | +| 拓扑 | CPU(Root Complex)→ Root Port → Endpoint 的树 | 机框 → 板卡 → 端口 | +| BDF | Bus:Device.Function,256×32×8 = 65536 个功能 | 端口门牌号 | +| Config Space | 256B 出厂说明书,前 16B 全行业统一(Vendor/Device ID 驱动匹配依据) | show version 板卡信息 | +| BAR + MMIO | 寄存器映射进 CPU 地址空间,读写地址 = 操作网卡 | asic_write_register 的物理本质 | +| MSI-X | 32 向量 = 多队列并行收包的硬件基础 | uNOS 未来扩核直接复用 | -## 五、实战踩坑 +**落点**: `rte_eal_init()` = 扫树 → 匹配 X540 ID → 读 BAR/MSI-X → vfio 绑定。M0 验收 `eth_dev_count()=1` 就是这条链路的结果。 -### 坑 1: Bus Master 没开 -- **现象**: DPDK 启动后一个包都收不到 -- **根因**: Command bit2=0 → 网卡不能 DMA -- **定位**: `lspci -vvv | grep "BusMaster"` -- **修复**: `pci_set_master(pdev)` 或 `setpci -s XX:XX.X COMMAND=0x117` +## 二、算法:哈希表 + LC1(🔴 待重做) -### 坑 2: 64-bit BAR 误读 -- **现象**: 物理地址 >4GB 时 MMIO 地址错误 -- **根因**: 只用 uint32_t 读 BAR0 低 32 位 -- **修复**: 用 `resource_size_t pci_resource_start(pdev, 0)` +- 哈希三组件:哈希函数 h(key)、桶数组、冲突处理(链地址法 / 开放寻址;DPDK rte_hash = cuckoo) +- 负载因子 α > 0.75 → 扩容 rehash;平均 O(1),最坏 O(n) +- **核心不变量:先查后存,只向过去提问**——表里只有历史,没有自己,天然排除自我匹配 +- LC1 参考实现已给(`job-search/algo-code/lc1-two-sum-ref.cpp`),**重做日 09-11**(重做前别看 ref) +- 产品锚点:conntrack 表 = 五元组哈希;flow cache 的 hash_key 在你自己的 uNOS 设计文档里就写着 -### 坑 3: MSI-X 向量不够 -- **现象**: 多队列网卡性能不增长 -- **根因**: pci_alloc_irq_vectors 返回数 < RX 队列数 -- **定位**: `cat /proc/interrupts | grep PCI-MSI | wc -l` -- **修复**: 增大内核 MSI-X 限制或 BIOS 调整 +## 三、踩坑节(今天真实的两个坑) -### 坑 4: PCIe 链路降速 -- **现象**: 100Gbps 网卡只能跑 25Gbps -- **定位**: `lspci -vvv | grep -E "LnkCap:|LnkSta:"` → Speed 2.5GT/s -- **修复**: 检查物理槽位宽度、PCIe 延长线、BIOS 设置 +### 坑 1:C++ 语法不熟导致无法起手 +- **现象**: 哈希原理讲完仍写不出代码,自己起手时把 map 声明成了 class 成员 +- **定位**: 词汇量不足(知道"要说什么",不会"怎么说"),不是算法不懂 +- **修复**: TODO 脚手架模式 + 参考实现逐段讲解 + 09-11 重做;语法文档 §3/§5 当字典随用随查 -### 坑 5: AER 静默数据损坏 -- **现象**: 偶尔出现 mbuf 数据乱码但不 crash -- **定位**: `dmesg | grep AER` → Uncorrectable Error -- **修复**: 必须换硬件,链路已不可靠 +### 坑 2:"先存后查"自我匹配 +- **现象**: 先存自己再查,`[3,3]` 会查到刚存的自己 +- **根因**: 查表时自己已在表里,违反"同一元素不能用两次" +- **修复**: 先查后存——查表那一刻表里只有"我之前的元素" -## 六、核心认知 +## 四、检验标准 -CPU 操作网卡的全路径: - -``` -读 Config Space → 匹配 Vendor/Device ID → 确定驱动 - → pci_enable_device → ioremap(BAR0) → 拿到虚拟地址 - → ioread32/iowrite32 操作寄存器 → 网卡开始工作 -``` - -BAR 是 MMIO 的入口,Config Space 是身份证,Capability 链表是扩展机制。 - -## 七、检验标准 -- [ ] 能解释 BDF 地址含义 -- [ ] 能手写 Config Space 前 16 字节字段 -- [ ] 能从 hex 值解码 BAR 的基址和大小 -- [ ] 能画 Capability 链表结构 -- [ ] 能对比 e1000(PCI-X) vs VMXNET3(PCIe v2) -- [ ] 能解释为什么 Bus Master bit 不置位就没 DMA +- [ ] 能画出 CPU → RC → Root Port → X540 拓扑并解释三角色 +- [ ] 能说出 Config Space 驱动匹配靠 Vendor/Device ID +- [ ] 能讲清 rte_eal_init 找到网卡的步骤链 +- [ ] 能口述哈希表三组件 + 负载因子的作用 +- [ ] 能讲清"先查后存,只向过去提问"的不变量 +- [ ] 09-11 重做 LC1:独立写出来(不看 ref)