|
1 | | -# 需求与问题域规格(01-requirements-spec.md) |
| 1 | +# 01 需求规格:F-Stack 连接级选栈增强 lib |
2 | 2 |
|
3 | 3 | > **文档编号**:SPEC-KE-01 |
4 | | -> **版本**:v0.1 草稿 |
| 4 | +> **版本**:v2(全量重做) |
5 | 5 | > **日期**:2026-06-15 |
6 | 6 | > **状态**:编写中 |
7 | | -> **作用域**:F-Stack 本地 socket/fd/event 访问能力的需求边界 |
| 7 | +> **作用域**:定义"连接级选栈增强 lib"的问题域、目标/非目标、功能与非功能需求、成功标准。 |
8 | 8 |
|
9 | 9 | --- |
10 | 10 |
|
11 | 11 | ## 1. 问题域 |
12 | 12 |
|
13 | | -### 1.1 根因 |
14 | | -F-Stack 启动后,DPDK 通过 UIO/VFIO 将物理网卡从内核驱动解绑并独占(PMD 轮询),内核协议栈**不再能看到该网卡**。因此本机基于内核栈的工具——`ping`、`curl`、`ssh`、`ntpdate`、监控 agent 等——**无法经该网卡收发**,运维/管理面受阻。 |
| 13 | +F-Stack 通过 DPDK 接管网卡后,该网卡流量绕过 Linux 内核协议栈,导致**本机工具(`ping`/`curl`/`ssh` 等)无法访问运行在 F-Stack 用户态栈上的服务**。 |
15 | 14 |
|
16 | | -### 1.2 现状(详见 `02-current-state-analysis.md`,以代码为准) |
17 | | -F-Stack 已存在三类"流量回内核"机制: |
18 | | -- **机制 A** nginx `kernel_network_stack`:仅服务 nginx,per-server/upstream 选栈,强耦合 nginx 源码。 |
19 | | -- **机制 B** `FF_KERNEL_EVENT`:LD_PRELOAD 层,仅镜像 epoll 事件,不覆盖数据 socket。 |
20 | | -- **机制 C** KNI(已迁移为 **virtio-user + vhost-net** exception path):报文级分流、可运行时调控,**已能支撑本机 ping/curl**,但缺少面向通用应用的统一编程接口与易用封装。 |
| 15 | +现有解法分两类: |
21 | 16 |
|
22 | | -### 1.3 缺口 |
23 | | -机制 C 提供了数据面通路,但: |
24 | | -- 配置分散(`config.ini [kni]` + 运行时 `FF_KNICTL` IPC),无统一 lib API; |
25 | | -- 缺少面向"本地 socket/fd/event"的应用编程模型(应用难以显式声明"这条连接走内核栈"); |
26 | | -- 缺少独立可复用的 lib 形态(当前能力散落在 `lib/ff_dpdk_if.c`、`lib/ff_dpdk_kni.c`、`adapter/syscall/`、nginx 补丁中)。 |
| 17 | +- **报文回灌(KNI/virtio-user/TAP)**:把裸报文送回内核——**本特性不采用**(见非目标)。 |
| 18 | +- **连接级选栈**:应用**主动**在内核栈侧也创建/监听 socket,按连接/监听粒度选栈,并在统一事件循环中服务两栈——**本特性采用**。 |
27 | 19 |
|
28 | | -## 2. 目标 |
| 20 | +F-Stack 自身已有两处"连接级选栈"实现(`02` 机制 A/B),但分别**内嵌**在 nginx 适配与 LD_PRELOAD syscall 适配中,**无法被任意 F-Stack 应用直接复用**。本特性即将其抽象为**应用无关的通用 lib**。 |
29 | 21 |
|
30 | | -提供一个**lib 库**,使**任意本机应用**(不限 nginx)在 DPDK 接管网卡的前提下,仍可: |
31 | | -1. 通过内核协议栈完成本机/管理面网络操作(ping、本地 curl 等); |
32 | | -2. 以统一、显式的接口声明某个 socket/fd/事件走"内核栈"或"F-Stack 用户态栈"; |
33 | | -3. 复用 F-Stack 既有 virtio-user exception path 数据面(机制 C),不重造轮子。 |
| 22 | +--- |
| 23 | + |
| 24 | +## 2. 目标与非目标 |
34 | 25 |
|
35 | | -## 3. 范围 |
| 26 | +### 2.1 目标(In Scope) |
| 27 | +- G1:提供一个 lib,使 F-Stack 应用能在**内核栈侧创建/监听 socket**,本机 `ping`/`curl` 等可直接访问该服务。 |
| 28 | +- G2:提供**连接/监听级选栈**能力(某监听走内核栈、某监听走 F-Stack),范式借鉴机制 A 的 `belong_to_host`。 |
| 29 | +- G3:提供**统一 fd/event 抽象**,使一个事件循环可同时服务内核栈 fd 与 F-Stack fd(合并事件),范式借鉴机制 B 的 `fstack_kernel_fd_map` + 双栈 epoll。 |
| 30 | +- G4:对应用**低侵入**(编译开关 + 少量 API),不强制改造业务逻辑;不绑定 nginx 或 LD_PRELOAD。 |
36 | 31 |
|
37 | | -### 3.1 本阶段(spec 文档) |
38 | | -- **仅产出中文 spec 文档**,不写实现代码、不改源码。 |
39 | | -- 交付:需求/现状/外部调研/架构/接口/里程碑/测试/门禁 共 9 篇(见 `plan.md`)。 |
| 32 | +### 2.2 非目标(Out of Scope) |
| 33 | +- N1:**不**采用 KNI / `rte_kni` / virtio-user / TAP / AF_XDP 等报文回灌方案(`rte_kni` 已于 DPDK 23.11 移除;gazelle KNI 亦衰退)。 |
| 34 | +- N2:本阶段**不写实现代码、不改 f-stack 源码**,仅产出中文 spec。 |
| 35 | +- N3:本阶段**不生成英文文档**。 |
| 36 | +- N4:不实现内核栈与 F-Stack 之间的 socket 自动迁移/透明代理(连接归属在创建时确定)。 |
40 | 37 |
|
41 | | -### 3.2 后续实现阶段(本 spec 规划,非本阶段交付) |
42 | | -- 在 mechanism C 之上抽象统一 lib(暂名 `libff_local` / `ff_local_*`)。 |
43 | | -- 提供编译开关与运行时控制对齐。 |
44 | | -- 单测/集成/性能基线。 |
| 38 | +--- |
45 | 39 |
|
46 | | -### 3.3 不在范围 |
47 | | -- 不改变 F-Stack 业务快路径性能模型; |
48 | | -- 不引入新的自研内核模块(KNI 内核模块已被 DPDK 23.11 移除,禁止回退); |
49 | | -- 本阶段不产出英文文档。 |
| 40 | +## 3. 功能需求(FR) |
50 | 41 |
|
51 | | -## 4. 功能性需求(FR) |
| 42 | +| 编号 | 需求 | 验收要点 | 代码依据 | |
| 43 | +|---|---|---|---| |
| 44 | +| FR-1 | 应用可在内核栈侧创建监听 socket,本机 `curl`/`ssh` 可访问 | 本机访问内核栈监听成功 | 机制 A `ngx_event_connect.c:46-50` | |
| 45 | +| FR-2 | 本机 `ping`(ICMP)对内核栈侧地址可达 | ping 通 | 内核栈原生处理 ICMP | |
| 46 | +| FR-3 | 连接/监听级选栈:可声明某监听走内核栈或 F-Stack | 两类监听并存且各自可达 | 机制 A `belong_to_host` `ngx_http.c:1890` | |
| 47 | +| FR-4 | 统一事件循环:单循环同时收 F-Stack 与内核栈事件 | 两栈事件均被正确投递 | 机制 B `ff_hook_syscall.c:2329-2338` | |
| 48 | +| FR-5 | fd 归属判定:lib 能区分 fd 属内核栈还是 F-Stack | API 行为按归属正确分流 | 机制 B `is_fstack_fd` `:309` | |
| 49 | +| FR-6 | 资源联动:关闭/异常时两栈 fd 一致释放 | 无 fd 泄漏 | 机制 B close 联动 `:1874-1883` | |
| 50 | +| FR-7 | 编译开关:本能力可编译期开/关,默认关闭零开销 | 关闭时与原 F-Stack 行为一致 | 机制 B `Makefile -DFF_KERNEL_EVENT` | |
52 | 51 |
|
53 | | -| 编号 | 需求 | 验收线索 | |
54 | | -|---|---|---| |
55 | | -| FR-1 | 本机可经内核栈 `ping` F-Stack 主机网卡 IP | 启用方案后 `ping <nic_ip>` 通 | |
56 | | -| FR-2 | 本机可经内核栈 `curl` 本机/外部地址 | `curl` 成功,走 veth/virtio-user | |
57 | | -| FR-3 | 提供统一开关:全部走内核 / 全部走 F-Stack / 默认按规则 | 对齐 `FF_KNICTL_ACTION_*`(`lib/ff_msg.h:118-123`) | |
58 | | -| FR-4 | 支持按 tcp/udp 端口、协议(ICMP/ARP/OSPF)分流 | 对齐 `config.ini [kni] method/tcp_port/udp_port` | |
59 | | -| FR-5 | 提供运行时动态调整分流策略的接口 | 对齐 `handle_knictl_msg`(`lib/ff_dpdk_if.c:1960-1977`) | |
60 | | -| FR-6 | 提供本地 socket/fd/event 编程接口(供应用显式选栈) | 借鉴机制 A 的 1-bit 选栈与机制 B 的 fd 映射 | |
| 52 | +--- |
61 | 53 |
|
62 | | -## 5. 非功能性需求(NFR) |
| 54 | +## 4. 非功能需求(NFR) |
63 | 55 |
|
64 | 56 | | 编号 | 需求 | |
65 | 57 | |---|---| |
66 | | -| NFR-1 | 关闭本能力时对业务快路径**零额外开销**(默认 KNI 关闭,见官方提示) | |
67 | | -| NFR-2 | 开启时分流检查开销可控、可限速(对齐 `console_packets_ratelimit`/`general_packets_ratelimit`/`kernel_packets_ratelimit`) | |
68 | | -| NFR-3 | 不依赖已移除的 `rte_kni`;仅用 upstream 能力(virtio-user/vhost-net) | |
69 | | -| NFR-4 | 与现有 `config.ini`、`FF_KNICTL` 语义兼容,不破坏既有部署 | |
70 | | -| NFR-5 | 多进程(primary/secondary)模型下行为明确 | |
| 58 | +| NFR-1 | **默认零开销**:未开启本能力时不引入任何额外分支/内存开销 | |
| 59 | +| NFR-2 | **业务快路径无回归**:F-Stack 高速路径性能不受影响(性能基线见 `07`) | |
| 60 | +| NFR-3 | **可移植**:兼容本工作区 DPDK 23.11.5 / 24.11.6 与移植后的 FreeBSD 栈 | |
| 61 | +| NFR-4 | **可观测**:提供两栈 fd 数、事件数等基本统计 | |
| 62 | +| NFR-5 | **接口稳定**:lib API 语义贴合 POSIX/`ff_api.h`,降低学习成本 | |
71 | 63 |
|
72 | | -## 6. 边界与异常场景 |
| 64 | +--- |
| 65 | + |
| 66 | +## 5. 边界与异常场景 |
73 | 67 |
|
74 | | -- 内核 `vhost-net` 模块缺失 / 无权限 / hugepage 不足 → 明确报错路径。 |
75 | | -- `method=accept` vs `reject` 语义边界(见 `config.ini:250-253`)。 |
76 | | -- 单网卡场景:管理流量与业务流量共网卡时的端口规划。 |
77 | | -- secondary 进程不创建 virtio_user 口(`lib/ff_dpdk_if.c:609-611` 仅 primary 翻倍端口)。 |
| 68 | +- 内核栈侧地址/端口与 F-Stack 侧冲突时的行为约定(应报错而非静默)。 |
| 69 | +- `maxevents` 过小(机制 B 要求 `>=2`)时的处理。 |
| 70 | +- 内核栈 fd 与 F-Stack fd 在同一 epoll/kqueue 中混用时的事件合并正确性。 |
| 71 | +- 本能力关闭(编译期/运行期)时,所有 API 退化为纯 F-Stack 行为。 |
| 72 | +- 系统前提缺失(参考 gazelle `rp_filter=1`)时的检测与提示。 |
| 73 | + |
| 74 | +--- |
78 | 75 |
|
79 | | -## 7. 成功标准 |
| 76 | +## 6. 成功标准 |
80 | 77 |
|
81 | | -1. 文档层面:架构/接口/里程碑/测试方案完整、与代码交叉验证一致、外部方案附 URL,通过 `08-review-gate.md` 门禁。 |
82 | | -2. (后续实现阶段)功能层面:FR-1~FR-6 可演示;NFR 满足;性能基线达标(详见 `07-test-spec.md`)。 |
| 78 | +1. DPDK 接管网卡后,本机 `ping <内核栈侧IP>` 通、`curl <内核栈侧服务>` 成功(FR-1/FR-2)。 |
| 79 | +2. 同一应用进程内"内核栈监听"与"F-Stack 监听"并存,单事件循环均正确收发(FR-3/FR-4)。 |
| 80 | +3. 本能力关闭时,F-Stack 业务性能与功能**零回归**(NFR-1/NFR-2)。 |
| 81 | +4. spec 全集过 `08-review-gate.md` 门禁。 |
0 commit comments