|
| 1 | +# F-Stack v1.25 第一层:总体架构与模块边界 |
| 2 | + |
| 3 | +> **目标受众**: 系统架构师、技术负责人 |
| 4 | +> **关键概念**: 模块划分、技术选型、数据流、进程模型 |
| 5 | +> **生成日期**: 2026-03-20 |
| 6 | +
|
| 7 | +## 1. 顶层架构概览 |
| 8 | + |
| 9 | +### 1.1 F-Stack 核心创新 |
| 10 | + |
| 11 | +F-Stack 采用了"用户态网络栈"架构,解决 Linux 内核网络处理的性能瓶颈: |
| 12 | + |
| 13 | +``` |
| 14 | +应用层 (Applications) |
| 15 | + ↓ (ff_socket/ff_read/ff_write 等 Linux-like API) |
| 16 | +F-Stack 库 (libfstack.a) |
| 17 | + ├─ FreeBSD TCP/IP 栈移植 |
| 18 | + ├─ 粘合层 (ff_glue.c) - 内核模拟 |
| 19 | + └─ 系统调用适配 (ff_syscall_wrapper.c) |
| 20 | + ↓ |
| 21 | +DPDK 库 (libdpdk) |
| 22 | + ├─ EAL (Environment Abstraction Layer) |
| 23 | + ├─ Mempool (mbuf 内存池) |
| 24 | + └─ Ethdev (网卡驱动无关接口) |
| 25 | + ↓ |
| 26 | +NIC 驱动 (igb_uio / vfio-pci) |
| 27 | + ↓ |
| 28 | +网卡硬件 |
| 29 | +``` |
| 30 | + |
| 31 | +### 1.2 三个核心支柱 |
| 32 | + |
| 33 | +| 支柱 | 组件 | 作用 | |
| 34 | +|-----|------|------| |
| 35 | +| **Kernel Bypass** | DPDK + PMD | 规避 Linux 内核网络瓶颈 | |
| 36 | +| **成熟协议栈** | FreeBSD 13.0 移植 | 复用久经考验的 TCP/IP 实现 | |
| 37 | +| **多核并行** | 多进程架构 + RSS | 充分利用多核处理能力 | |
| 38 | + |
| 39 | +### 1.3 关键性能指标 |
| 40 | + |
| 41 | +- **并发连接**: 1000 万+ |
| 42 | +- **请求吞吐**: 500 万+ RPS (Request Per Second) |
| 43 | +- **连接建立**: 100 万+ CPS (Connection Per Second) |
| 44 | +- **延迟**: 微秒级 (vs 毫秒级内核栈) |
| 45 | + |
| 46 | +## 2. 目录结构与模块边界 |
| 47 | + |
| 48 | +### 2.1 核心目录布局 |
| 49 | + |
| 50 | +``` |
| 51 | +/data/workspace/f-stack/ |
| 52 | +├── lib/ # F-Stack 核心库 (~21K 行 C 代码) |
| 53 | +│ ├── ff_dpdk_if.c (2855行) # DPDK 网卡接口层 - 最核心 |
| 54 | +│ ├── ff_glue.c (1466行) # FreeBSD 粘合层 |
| 55 | +│ ├── ff_config.c (1379行) # 配置解析 |
| 56 | +│ ├── ff_syscall_wrapper.c # Linux→FreeBSD 系统调用适配 |
| 57 | +│ ├── ff_host_interface.c # 主机接口 (pthread/mmap/时间) |
| 58 | +│ ├── ff_init.c (69行) # 初始化协调 |
| 59 | +│ ├── ff_epoll.c (159行) # epoll 接口转换 |
| 60 | +│ ├── ff_dpdk_kni.c # 虚拟网卡支持 |
| 61 | +│ ├── Makefile # 编译系统 |
| 62 | +│ └── include/ # 头文件 |
| 63 | +│ |
| 64 | +├── freebsd/ # FreeBSD 13.0 内核代码移植 |
| 65 | +│ ├── sys/ |
| 66 | +│ │ ├── netinet/ # IPv4 协议栈 |
| 67 | +│ │ ├── netinet6/ # IPv6 协议栈 |
| 68 | +│ │ ├── net/ # 通用网络接口 |
| 69 | +│ │ ├── kern/ # 内核服务 (malloc/锁/定时器) |
| 70 | +│ │ └── vm/ # 虚拟内存 |
| 71 | +│ ├── amd64/ # x86 架构特定代码 |
| 72 | +│ └── contrib/ck/ # ConcurrencyKit 依赖 |
| 73 | +│ |
| 74 | +├── dpdk/ # DPDK 23.11.5 (submodule) |
| 75 | +│ └── build/ # 编译产物 |
| 76 | +│ |
| 77 | +├── app/ # 应用集成 |
| 78 | +│ ├── nginx-1.25.2/ |
| 79 | +│ └── redis-6.2.6/ |
| 80 | +│ |
| 81 | +├── example/ # 示例代码 |
| 82 | +│ ├── main.c (222行) # kqueue HTTP 服务器 |
| 83 | +│ └── main_epoll.c (143行) # epoll HTTP 服务器 |
| 84 | +│ |
| 85 | +├── mk/ # 编译系统 |
| 86 | +│ ├── kern.pre.mk # FreeBSD 编译规则 |
| 87 | +│ ├── kern.mk # 内核编译规则 |
| 88 | +│ └── compiler.mk # 编译器配置 |
| 89 | +│ |
| 90 | +├── tools/ # 工具脚本 |
| 91 | +├── doc/ # 文档 |
| 92 | +└── config.ini # 默认配置文件 |
| 93 | +``` |
| 94 | + |
| 95 | +### 2.2 核心模块职责边界 |
| 96 | + |
| 97 | +| 模块 | 行数 | 职责 | 依赖 | |
| 98 | +|-----|------|------|------| |
| 99 | +| **ff_dpdk_if.c** | 2855 | NIC 驱动/DPDK 操作/收发包核心逻辑 | DPDK, ff_glue | |
| 100 | +| **ff_glue.c** | 1466 | FreeBSD 内核模拟/内存/锁/中断 | FreeBSD headers, DPDK | |
| 101 | +| **ff_config.c** | 1379 | INI 配置文件解析 | ff_ini_parser | |
| 102 | +| **ff_syscall_wrapper.c** | 1825 | Linux 系统调用→FreeBSD 适配 | FreeBSD sys | |
| 103 | +| **ff_init.c** | 69 | 初始化流程协调 | 上述所有模块 | |
| 104 | +| **ff_epoll.c** | 159 | Linux epoll→FreeBSD kqueue 转换 | FreeBSD kqueue | |
| 105 | +| **ff_host_interface.c** | -- | 主机 OS 接口 (mmap/pthread/rand) | 系统库 | |
| 106 | +| **ff_dpdk_kni.c** | -- | 虚拟网卡支持 (可选) | DPDK KNI | |
| 107 | + |
| 108 | +## 3. FreeBSD TCP/IP 栈移植方式 |
| 109 | + |
| 110 | +### 3.1 移植策略 |
| 111 | + |
| 112 | +F-Stack 采用了**完整移植**策略: |
| 113 | +- 从 FreeBSD 13.0 提取完整的 TCP/IP 协议栈代码 |
| 114 | +- 在 `freebsd/sys/netinet/` 中保留所有网络协议代码 |
| 115 | +- 通过 `ff_glue.c` 实现内核 API 的用户态模拟 |
| 116 | +- 通过条件编译支持可选功能 (IPv6, KNI, TCPHPTS 等) |
| 117 | + |
| 118 | +### 3.2 FreeBSD 移植的子系统 |
| 119 | + |
| 120 | +``` |
| 121 | +freebsd/sys/ |
| 122 | +├── netinet/ # IPv4: tcp_*.c, udp_*.c, ip_*.c, if_arp.c |
| 123 | +├── netinet6/ # IPv6: ip6_*.c, tcp6_*.c |
| 124 | +├── net/ # 通用网络: if.c, route.c, netisr.c |
| 125 | +├── kern/ # 内核服务: malloc, mutex, synch, callout |
| 126 | +├── vm/ # 虚拟内存: vm_page.c (mbuf 映射) |
| 127 | +└── sys/ # 系统定义: socket.h, mbuf.h 等 |
| 128 | +``` |
| 129 | + |
| 130 | +### 3.3 ff_glue.c 中的内核模拟 |
| 131 | + |
| 132 | +| 内核功能 | FreeBSD 原生 | F-Stack 模拟 | |
| 133 | +|---------|-------------|-----------| |
| 134 | +| 内存分配 | `malloc()` | DPDK `rte_malloc()` | |
| 135 | +| 互斥锁 | `struct mtx` | `pthread_mutex_t` | |
| 136 | +| 条件变量 | `struct condvar` | `pthread_cond_t` | |
| 137 | +| 软中断 | `swi_*` | 内部 taskqueue | |
| 138 | +| 定时器 | `callout{}` | DPDK `rte_timer` | |
| 139 | +| 分页内存 | `vm_page_alloc()` | DPDK mempool | |
| 140 | + |
| 141 | +## 4. DPDK 集成与 NIC 驱动层 |
| 142 | + |
| 143 | +### 4.1 ff_dpdk_if.c 核心职责 |
| 144 | + |
| 145 | +这是最核心的模块 (2855 行),负责整个数据链路: |
| 146 | + |
| 147 | +**初始化流程**: |
| 148 | +``` |
| 149 | +ff_dpdk_init() |
| 150 | + ├─ rte_eal_init() // DPDK 环境初始化 |
| 151 | + ├─ init_lcore_conf() // CPU 核心/端口映射 |
| 152 | + ├─ init_mem_pool() // mbuf 内存池创建 |
| 153 | + ├─ init_dispatch_ring() // 进程间消息队列 |
| 154 | + ├─ init_port_start() // NIC 启动 + RSS 配置 |
| 155 | + ├─ ff_rss_tbl_init() // RSS 分类表建立 |
| 156 | + └─ init_clock() // FreeBSD 时钟初始化 |
| 157 | +``` |
| 158 | + |
| 159 | +### 4.2 收包流程 (Ingress) |
| 160 | + |
| 161 | +``` |
| 162 | +NIC 硬件 (RSS 处理器分发) |
| 163 | + ↓ |
| 164 | +多个 RX 队列 (per-CPU-core) |
| 165 | + ↓ |
| 166 | +DPDK PMD (rte_eth_rx_burst()) |
| 167 | + ↓ |
| 168 | +process_packets() 函数 |
| 169 | + ├─ 协议过滤 (ARP/IPv4/IPv6/Multicast) |
| 170 | + ├─ 虚拟网卡处理 (veth_input) |
| 171 | + └─ FreeBSD 栈 (if_input → eth_input → ip_input → tcp_input → sorecv) |
| 172 | +``` |
| 173 | + |
| 174 | +### 4.3 发包流程 (Egress) |
| 175 | + |
| 176 | +``` |
| 177 | +应用 (ff_write/ff_sendto) |
| 178 | + ↓ |
| 179 | +FreeBSD TCP/UDP 栈 |
| 180 | + ├─ tcp_output() / udp_output() |
| 181 | + ├─ ip_output() |
| 182 | + └─ if_output() |
| 183 | + ↓ |
| 184 | +ff_glue.c if_start() |
| 185 | + ├─ 获取 mbuf |
| 186 | + ├─ 填充 L2/L3/L4 头 |
| 187 | + ├─ 配置硬件卸载 (TSO/Checksum) |
| 188 | + └─ send_single_packet() |
| 189 | + ↓ |
| 190 | +DPDK rte_eth_tx_burst() |
| 191 | + ↓ |
| 192 | +NIC 硬件 |
| 193 | +``` |
| 194 | + |
| 195 | +## 5. 主处理循环 |
| 196 | + |
| 197 | +### 5.1 main_loop() 伪代码 |
| 198 | + |
| 199 | +```c |
| 200 | +int main_loop(void *arg) { |
| 201 | + while (!stop_loop) { |
| 202 | + // [1] 驱动 FreeBSD 定时器 |
| 203 | + if (freebsd_clock.expire < cur_tsc) { |
| 204 | + rte_timer_manage(); |
| 205 | + } |
| 206 | + |
| 207 | + // [2] 轮询所有 RX 队列 |
| 208 | + for (each_rx_queue) { |
| 209 | + nb_rx = rte_eth_rx_burst(...); |
| 210 | + process_packets(pkts_burst, nb_rx); |
| 211 | + } |
| 212 | + |
| 213 | + // [3] 定时刷新 TX 队列 |
| 214 | + if (drain_tsc && (cur_tsc - prev_tsc) > drain_tsc) { |
| 215 | + for (each_port) { |
| 216 | + rte_eth_tx_burst(...); |
| 217 | + } |
| 218 | + } |
| 219 | + |
| 220 | + // [4] 执行用户回调 |
| 221 | + if (usr_loop) { |
| 222 | + usr_loop(arg); |
| 223 | + } |
| 224 | + } |
| 225 | +} |
| 226 | +``` |
| 227 | +
|
| 228 | +### 5.2 轮询特性 |
| 229 | +
|
| 230 | +- **无中断**: → 低延迟、高吞吐 |
| 231 | +- **占用 CPU**: 100% 利用 (通过 CPU 隔离优化) |
| 232 | +- **可配置睡眠**: `idle_sleep` 参数支持微秒级让步 |
| 233 | +
|
| 234 | +## 6. 进程模型 |
| 235 | +
|
| 236 | +### 6.1 单进程模式 (推荐) |
| 237 | +
|
| 238 | +``` |
| 239 | +F-Stack 进程 (1 个) |
| 240 | + └─ 单个 lcore (1 个 CPU 核心) |
| 241 | + ├─ NIC RX/TX 队列映射 |
| 242 | + ├─ FreeBSD 协议栈运行 |
| 243 | + └─ 应用逻辑执行 |
| 244 | +``` |
| 245 | +
|
| 246 | +**适用场景**: 小型应用、专用设备 |
| 247 | +
|
| 248 | +### 6.2 多进程模式 |
| 249 | +
|
| 250 | +``` |
| 251 | +主进程 (Primary) |
| 252 | + ├─ DPDK EAL 初始化 |
| 253 | + └─ 启动 N 个 Worker 进程 |
| 254 | + |
| 255 | +Worker-0 (CPU-0) ┐ |
| 256 | +Worker-1 (CPU-1) ├─ 各进程独立运行 |
| 257 | +... │ 通过 RSS 维持连接亲和性 |
| 258 | +Worker-N (CPU-N) ┘ |
| 259 | + |
| 260 | +共享资源: |
| 261 | + ├─ DPDK Mempool |
| 262 | + ├─ RSS 分类表 |
| 263 | + └─ 虚拟网卡 (KNI) |
| 264 | +``` |
| 265 | +
|
| 266 | +**优势**: 故障隔离、灵活扩展 |
| 267 | +**劣势**: 进程间同步复杂 |
| 268 | +
|
| 269 | +## 7. 技术选型分析 |
| 270 | +
|
| 271 | +### 7.1 为什么选 DPDK 而非 NETMAP/PF_RING |
| 272 | +
|
| 273 | +| 对比项 | DPDK | NETMAP | PF_RING | |
| 274 | +|-------|------|--------|---------| |
| 275 | +| 社区活跃度 | ★★★★★ | ★★★ | ★★★ | |
| 276 | +| 跨平台 | ✓ | ✓ | ✗ (Linux only) | |
| 277 | +| 生态完整性 | ★★★★★ | ★★★ | ★★ | |
| 278 | +| 企业采用 | ★★★★★ | ★★★ | ★★ | |
| 279 | +| 硬件卸载支持 | ★★★★★ | ★★★ | ★★ | |
| 280 | +
|
| 281 | +**选择原因**: |
| 282 | +- Tencent 已有 DPDK 积累 (DNSPod DNS) |
| 283 | +- 多进程架构支持最完善 |
| 284 | +- 硬件卸载支持最广泛 (TSO/GSO/Checksum) |
| 285 | +
|
| 286 | +### 7.2 为什么选 FreeBSD 栈而非自研 |
| 287 | +
|
| 288 | +| 方面 | FreeBSD 栈 | 自研栈 | |
| 289 | +|-----|-----------|--------| |
| 290 | +| 开发周期 | 即用 | 2-3 年 | |
| 291 | +| 功能完整 | ★★★★★ | ★★★ | |
| 292 | +| 性能优化 | ★★★★★ | ★★ | |
| 293 | +| RFC 兼容性 | ★★★★★ | ★★★ | |
| 294 | +| 社区反馈 | ★★★★★ | 无 | |
| 295 | +| 维护成本 | ★★★ | ★★★★★ | |
| 296 | +
|
| 297 | +**历史背景**: |
| 298 | +- 初期自研简单栈 → 性能不足 |
| 299 | +- 2017 年参考 libplebnet/libuinet → 完整移植 FreeBSD 栈 |
| 300 | +- 这决定了今天的架构 |
| 301 | +
|
| 302 | +## 8. 硬件卸载特性 |
| 303 | +
|
| 304 | +F-Stack 充分发挥现代 NIC 硬件能力: |
| 305 | +
|
| 306 | +### 8.1 RX 卸载 |
| 307 | +
|
| 308 | +| 特性 | 效果 | 支持度 | |
| 309 | +|-----|------|--------| |
| 310 | +| **校验和卸载** | 验证 L3/L4 由硬件完成 | 广泛 | |
| 311 | +| **LRO** (Large Receive Offload) | 合并小报文为大报文 | 部分 | |
| 312 | +
|
| 313 | +### 8.2 TX 卸载 |
| 314 | +
|
| 315 | +| 特性 | 效果 | 支持度 | |
| 316 | +|-----|------|--------| |
| 317 | +| **TSO** (TCP Segmentation Offload) | 大报文由硬件分段 | 广泛 | |
| 318 | +| **校验和卸载** | 计算 L3/L4 校验和 | 广泛 | |
| 319 | +| **VLAN 插入** | 硬件添加 VLAN 标签 | 部分 | |
| 320 | +
|
| 321 | +### 8.3 流分类 (RSS) |
| 322 | +
|
| 323 | +- **硬件 RSS**: 基于 5 元组 (src-ip, dst-ip, src-port, dst-port, proto) |
| 324 | +- **好处**: 同一连接总是路由到同一 RX 队列 → 避免 TCP 乱序 |
| 325 | +
|
| 326 | +## 总结 |
| 327 | +
|
| 328 | +F-Stack 的架构设计围绕三个核心支柱: |
| 329 | +1. **Kernel Bypass**: 规避 Linux 内核瓶颈 |
| 330 | +2. **成熟协议栈**: 复用 FreeBSD 久经考验的实现 |
| 331 | +3. **多核并行**: 充分利用现代多核 CPU 和 NIC 硬件能力 |
| 332 | +
|
| 333 | +这使得 F-Stack 能够达到 500 万+ RPS、10 亿+ 并发连接的性能水平,是云计算核心网络设施的理想选择。 |
0 commit comments