Skip to content

Commit 83161d0

Browse files
committed
docs: rework kernel_event_support spec (zh_cn) to single-API marker-based stack selection
- Drop ff_local_* dual API; standardize existing SOCK_KERNEL/SOCK_FSTACK markers - Add config.ini global default-stack switch (app marker overrides) - Add client-side stack selection: connect to local/loopback and external kernel-stack services - Cover both hook (LD_PRELOAD) and native ff_api modes; note native ff_socket marker gap - Remove gazelle thread-level selection; KNI stays out of scope
1 parent c618c26 commit 83161d0

9 files changed

Lines changed: 519 additions & 411 deletions
Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# 00 总览:F-Stack 连接级选栈增强(本机直访 F-Stack 服务
1+
# 00 总览:F-Stack 连接级选栈增强(单 API + 标记 + config 默认开关
22

33
> **文档编号**:SPEC-KE-00
4-
> **版本**v2(全量重做
4+
> **版本**v3(范式修正重做
55
> **日期**:2026-06-15
66
> **状态**:编写中
77
> **作用域**:本目录中文 spec 的导航、术语与范围声明
@@ -10,25 +10,30 @@
1010

1111
## 1. 一句话目标
1212

13-
F-Stack 提供一个 lib,使应用进程能在 **F-Stack 用户态栈****宿主机 Linux 内核栈****同时**创建/监听 socket,并以**统一的 fd / event 抽象**在单事件循环中服务两栈;从而即使 DPDK 接管了网卡,本机的 `ping` / `curl` 等工具也能**直接访问该应用在内核栈侧暴露的服务**
13+
**标准化 F-Stack 现有的"单 API + `SOCK_KERNEL`/`SOCK_FSTACK` 标记选栈 + 胶水自动适配"能力**,并在 config.ini 增加**一个全局默认栈开关**;使任意 F-Stack 应用**无需改用多套 API**,即可让某些 fd 走宿主机内核栈(本机 `ping`/`curl` 直访其服务,且该应用作客户端也能经内核栈 `connect` 本机/外部内核服务),其余 fd 走 F-Stack 高速路径
1414

1515
## 2. 范围声明(重要)
1616

17-
- **本特性 = 连接级选栈增强(Connection-level Stack Selection)**
18-
- **首要参考**:nginx 的 `kernel_network_stack` 开关(`belong_to_host` 1-bit 选栈 + 双事件后端)。
19-
- **次要参考**`adapter/syscall``FF_KERNEL_EVENT` 编译宏(`fstack_kernel_fd_map` + 双栈 epoll 合并)。
20-
- **明确排除(非目标)**:KNI / `rte_kni` / virtio-user / TAP / AF_XDP 等"报文回灌内核"方案——它们解决的是"未被应用接管的报文回到内核",与本特性"应用主动在内核栈侧暴露服务"是不同问题,仅在方案对比中用于澄清边界。
17+
- **本特性 = 连接级选栈增强**,选栈方式 = **app 标记(per-fd)+ config.ini 全局默认开关(per-process)**,胶水层自动适配。
18+
- **直接复用基线**`adapter/syscall` hook 模式的 `SOCK_KERNEL`/`SOCK_FSTACK` 标记选栈(`ff_hook_socket`/`ff_hook_connect`)+ `FF_KERNEL_EVENT` 双栈事件。
19+
- **双向覆盖**:服务端(内核栈监听被本机直访)+ **客户端(经内核栈 `connect` 本机/外部内核服务,新增)**
20+
- **双模式覆盖**:hook 模式(已支持,直接复用)+ 原生 `ff_api` 模式(补 `ff_socket` 标记识别)。
21+
- **明确排除**
22+
- ****新造 `ff_local_*` 双 API / 类 mTCP 双命名空间(v2 做法作废)。
23+
- ****做 gazelle 式线程级选栈(多进程模型靠不同 config 文件)。
24+
- ****做 config 端口/地址名单(仅一个全局默认开关)。
25+
- ****采用 KNI/`rte_kni`/virtio-user/TAP/AF_XDP 报文回灌(仅边界澄清)。
2126

2227
## 3. 阅读路径
2328

2429
| 顺序 | 文档 | 用途 |
2530
|---|---|---|
26-
| 1 | `plan.md` | 计划、团队、门禁、范围修正 |
31+
| 1 | `plan.md` | 计划、团队、门禁、范式修正 |
2732
| 2 | `01-requirements-spec.md` | 需求与目标/非目标 |
28-
| 3 | `02-current-state-analysis.md` | 机制 A/B 代码级现状(以代码为准) |
33+
| 3 | `02-current-state-analysis.md` | 单 API+标记/客户端/config/原生模式 代码现状(以代码为准) |
2934
| 4 | `03-external-research.md` | 外部方案调研(附 URL) |
30-
| 5 | `04-architecture-design.md` | 双栈选栈架构与事件模型 |
31-
| 6 | `05-interface-design.md` | lib 对外接口契约 |
35+
| 5 | `04-architecture-design.md` | 标记+config 选栈架构与双向数据流 |
36+
| 6 | `05-interface-design.md` | 标记/config 契约与双模式适配 |
3237
| 7 | `06-milestones.md` | 里程碑与编码工作清单 |
3338
| 8 | `07-test-spec.md` | 测试与性能基线方案 |
3439
| 9 | `08-review-gate.md` | 审核门禁结论 |
@@ -38,15 +43,15 @@
3843
| 术语 | 含义 |
3944
|---|---|
4045
| F-Stack 栈 | DPDK PMD + 用户态 FreeBSD 协议栈(业务高速路径) |
41-
| 内核栈 | 宿主机 Linux 内核网络协议栈(本机/管理/异常路径|
42-
| 连接级选栈 | socket/listen/connect 粒度上决定该连接走 F-Stack 还是内核栈 |
43-
| `belong_to_host` | nginx 中标记某连接/监听走内核栈的 1-bit 标志 |
44-
| `SOCK_FSTACK` | F-Stack 适配层在 `socket()` type 上附加的标志,表示走 F-Stack |
45-
| `FF_KERNEL_EVENT` | LD_PRELOAD 适配层的编译宏,使事件循环同时处理内核 fd |
46-
| `fstack_kernel_fd_map` | "F-Stack fd → 内核 fd"映射表,用于双栈事件合并 |
46+
| 内核栈 | 宿主机 Linux 内核网络协议栈(本机/管理/客户端连本机或外部内核服务|
47+
| 选栈标记 | socket `type` 上的 `SOCK_KERNEL`(0x02000000)/`SOCK_FSTACK`(0x01000000),per-fd 选栈 |
48+
| 全局默认栈开关 | config.ini 中决定本进程默认栈的开关(`[stack] default_stack` |
49+
| 胶水自动适配 | 创建时标记/配置定 fd 归属,后续 syscall 经 `is_fstack_fd`/`CHECK_FD_OWNERSHIP` 自动路由 |
50+
| hook 模式 | LD_PRELOAD 接管 POSIX API(`ff_hook_*`),标记选栈已支持 |
51+
| 原生模式 | 应用直接调 `ff_*``ff_api.h`),现状 `ff_socket` 不识别标记(需补强) |
4752

4853
## 5. 依据来源
4954

50-
- F-Stack 实际代码(`app/nginx-1.28.0/``adapter/syscall/``lib/`)——**最高优先级,冲突以代码为准**
55+
- F-Stack 实际代码(`adapter/syscall/``lib/``app/nginx-1.28.0/`)——**最高优先级,冲突以代码为准**
5156
- F-Stack 三层架构文档与知识图谱(`docs/`)。
52-
- 外网公开资料(GitHub issue/wiki、技术博客等),均在 `03` 附可访问 URL。
57+
- 外网公开资料(GitHub/技术博客等),均在 `03` 附可访问 URL。
Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,98 @@
1-
# 01 需求规格:F-Stack 连接级选栈增强 lib
1+
# 01 需求规格:F-Stack 连接级选栈增强(单 API + 标记 + config 默认开关)
22

33
> **文档编号**:SPEC-KE-01
4-
> **版本**v2(全量重做
4+
> **版本**v3(范式修正重做
55
> **日期**:2026-06-15
66
> **状态**:编写中
7-
> **作用域**定义"连接级选栈增强 lib"的问题域、目标/非目标、功能与非功能需求、成功标准。
7+
> **作用域**定义本特性的问题域、目标/非目标、功能与非功能需求、成功标准。
88
99
---
1010

1111
## 1. 问题域
1212

13-
F-Stack 通过 DPDK 接管网卡后,该网卡流量绕过 Linux 内核协议栈,导致**本机工具(`ping`/`curl`/`ssh` 等)无法访问运行在 F-Stack 用户态栈上的服务**
13+
F-Stack 通过 DPDK 接管网卡后,该网卡流量绕过 Linux 内核协议栈,导致
1414

15-
现有解法分两类:
15+
1. **服务端方向**:本机工具(`ping`/`curl`/`ssh`)无法访问运行在 F-Stack 用户态栈上的服务。
16+
2. **客户端方向**:F-Stack 应用作客户端时,无法用内核栈去 `connect` 本机服务(`127.0.0.1`/本机内核栈 IP)或外部内核栈服务。
1617

17-
- **报文回灌(KNI/virtio-user/TAP)**:把裸报文送回内核——**本特性不采用**(见非目标)。
18-
- **连接级选栈**:应用**主动**在内核栈侧也创建/监听 socket,按连接/监听粒度选栈,并在统一事件循环中服务两栈——**本特性采用**
18+
F-Stack 的 `adapter/syscall`(hook/LD_PRELOAD 模式)**已实现"单 POSIX API + `SOCK_KERNEL`/`SOCK_FSTACK` 标记 + 胶水自动适配"**的选栈能力(见 `02`),但:
19+
- 该标记语义**内嵌**在 syscall 适配层,未被标准化为"任意 F-Stack 应用可依赖的选栈约定";
20+
- **缺少 config.ini 级别的"全局默认栈开关"**(只能靠应用逐 socket 设标记);
21+
- **客户端连本机/外部内核栈服务**未被系统化文档化;
22+
- **原生 `ff_api` 模式**`ff_socket` 现状**不识别**选栈标记(`02 §5`,恒建 F-Stack socket)。
1923

20-
F-Stack 自身已有两处"连接级选栈"实现(`02` 机制 A/B),但分别**内嵌**在 nginx 适配与 LD_PRELOAD syscall 适配中,**无法被任意 F-Stack 应用直接复用**。本特性即将其抽象为**应用无关的通用 lib**
24+
本特性即:**标准化现有"单 API + 标记选栈"约定 + 补齐 config.ini 全局默认开关 + 覆盖客户端方向 + 在原生模式补齐标记识别**,使任意 F-Stack 应用无需改用多套 API 即可按需选栈
2125

2226
---
2327

2428
## 2. 目标与非目标
2529

2630
### 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。
31+
- **G1(标记标准化)**:以现有 `SOCK_KERNEL`/`SOCK_FSTACK``ff_adapter.h:7-8`)为**唯一选栈标记**,标准化为可被任意 F-Stack 应用使用的约定;**不新造 `ff_local_*` 双 API、不新造 `belong_to_host` 参数**
32+
- **G2(config.ini 全局默认开关)**:在 config.ini 新增**一个全局默认栈开关**(仿 `[kni]` 范式),决定本进程默认走 F-Stack 还是内核栈;**优先级:app 标记 > config 默认**
33+
- **G3(服务端选栈)**:应用可让某监听 socket 走内核栈,本机 `ping`/`curl`/`ssh` 直访其服务。
34+
- **G4(客户端选栈,新增)**:应用作客户端可经内核栈 `connect` 访问本机回环/本机内核栈 IP 服务**及外部内核栈服务**(承载点 `ff_hook_connect:858`)。
35+
- **G5(双模式覆盖)**:选栈标记与客户端能力同时覆盖 **hook 模式**(完整复用)与**原生 `ff_api` 模式**(补齐 `ff_socket` 标记识别,`02 §5`)。
36+
- **G6(统一事件)**:单事件循环同时服务内核栈 fd 与 F-Stack fd(复用 `fstack_kernel_fd_map` 双栈合并)。
37+
- **G7(低侵入/默认零开销)**:编译开关默认关闭;不设标记/默认 F-Stack 时行为与原 F-Stack 一致。
3138

3239
### 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+
- **N1******新造 `ff_local_*` 双 API / 类 mTCP 双命名空间(v2 做法作废)。
41+
- **N2******做 gazelle 式**线程级选栈**(F-Stack 多进程模型靠不同 config 文件区分,见 `02 §4`)。
42+
- **N3******做 config.ini 端口/地址规则名单(仅"一个全局默认开关")。
43+
- **N4******采用 KNI/`rte_kni`/virtio-user/TAP/AF_XDP 报文回灌。
44+
- **N5**:本阶段**不写实现代码、不改 f-stack 源码**,仅产出中文 spec;**不生成英文文档**
45+
- **N6**:不实现内核栈与 F-Stack 间 socket 自动迁移/透明代理(归属在创建时确定)。
3746

3847
---
3948

4049
## 3. 功能需求(FR)
4150

4251
| 编号 | 需求 | 验收要点 | 代码依据 |
4352
|---|---|---|---|
44-
| FR-1 | 应用可在内核栈侧创建监听 socket,本机 `curl`/`ssh` 可访问 | 本机访问内核栈监听成功 | 机制 A `ngx_event_connect.c:46-50` |
53+
| FR-1 | **标记选栈(服务端)**:带 `SOCK_KERNEL` 的监听 socket 走内核栈,本机 `curl`/`ssh` 可访问 | 本机访问内核栈监听成功 | `ff_hook_socket:387-390` |
4554
| 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` |
55+
| FR-3 | **标记选栈(客户端,新增)**:F-Stack 应用经内核栈 `connect` 本机回环/本机 IP 服务 | 本机 server + F-Stack client connect 通 | `ff_hook_connect:858` + `is_fstack_fd:309` |
56+
| FR-4 | **客户端连外部内核栈服务(新增)**:F-Stack 应用作客户端选栈访问外部内核栈服务 | 连外部内核服务成功 | `ff_hook_connect:858``ff_linux_connect:144` |
57+
| FR-5 | **config.ini 全局默认开关**:可配置本进程默认栈(F-Stack/内核),app 标记可覆盖 | 默认栈生效、标记覆盖生效 | `ff_config.c:1011`/`ff_config.h:310-319` 范式 |
58+
| FR-6 | **双模式覆盖**:hook 模式直接复用标记;原生 `ff_api` 模式补齐 `ff_socket` 标记识别 | 两模式均可标记选栈 | `02 §2`(hook)/`02 §5`(原生差异) |
59+
| FR-7 | 统一事件循环:单循环同时收 F-Stack 与内核栈事件 | 两栈事件均正确投递 | `ff_hook_syscall.c:2324+` |
60+
| FR-8 | fd 归属判定 + 资源联动:按归属分流,关闭/异常时两栈 fd 一致释放 | 行为正确、无 fd 泄漏 | `is_fstack_fd:309`、close 联动 `:1874-1883` |
61+
| FR-9 | 编译开关:本能力可编译期开/关,默认关闭零开销 | 关闭时与原 F-Stack 行为一致 | `Makefile -DFF_KERNEL_EVENT` 范式 |
5162

5263
---
5364

5465
## 4. 非功能需求(NFR)
5566

5667
| 编号 | 需求 |
5768
|---|---|
58-
| NFR-1 | **默认零开销**未开启本能力时不引入任何额外分支/内存开销 |
59-
| NFR-2 | **业务快路径无回归**:F-Stack 高速路径性能不受影响(性能基线见 `07`|
69+
| NFR-1 | **默认零开销**未开启/默认 F-Stack 时不引入额外分支/内存开销 |
70+
| NFR-2 | **业务快路径无回归**:F-Stack 高速路径性能不受影响(基线见 `07`|
6071
| NFR-3 | **可移植**:兼容本工作区 DPDK 23.11.5 / 24.11.6 与移植后的 FreeBSD 栈 |
6172
| NFR-4 | **可观测**:提供两栈 fd 数、事件数等基本统计 |
62-
| NFR-5 | **接口稳定**:lib API 语义贴合 POSIX/`ff_api.h`,降低学习成本 |
73+
| NFR-5 | **接口稳定/低侵入**:复用现有单 API + 标记,不引入多套 API;语义贴合 POSIX/`ff_api.h` |
74+
| NFR-6 | **多进程一致**:每进程经各自 config.ini 独立设默认栈,互不影响(`ff_config.filename:254`|
6375

6476
---
6577

6678
## 5. 边界与异常场景
6779

68-
- 内核栈侧地址/端口与 F-Stack 侧冲突时的行为约定(应报错而非静默)。
69-
- `maxevents` 过小(机制 B 要求 `>=2`)时的处理。
70-
- 内核栈 fd 与 F-Stack fd 在同一 epoll/kqueue 中混用时的事件合并正确性。
71-
- 本能力关闭(编译期/运行期)时,所有 API 退化为纯 F-Stack 行为。
72-
- 系统前提缺失(参考 gazelle `rp_filter=1`)时的检测与提示。
80+
- `SOCK_KERNEL``SOCK_FSTACK` 同时置位时的优先级(实测 `ff_hook_socket:387` 要求 `SOCK_KERNEL && !SOCK_FSTACK` 才走内核,需在接口契约明确)。
81+
- app 标记与 config 默认冲突时:**app 标记优先**
82+
- 内核栈侧地址/端口与 F-Stack 侧冲突时报错而非静默。
83+
- `maxevents` 过小(机制要求 `>=2``:2212-2218`)时的处理。
84+
- 客户端 `connect` 时 fd 归属与目的地址栈不匹配(如内核 fd 连 F-Stack 才可达的地址)时的行为约定。
85+
- 原生模式 `ff_socket` 标记识别补齐前后的兼容性(`02 §5`)。
86+
- 本能力关闭(编译期)时所有路径退化为纯 F-Stack 行为。
87+
- 系统前提缺失(参考 gazelle `rp_filter` 等)时的检测与提示。
7388

7489
---
7590

7691
## 6. 成功标准
7792

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` 门禁。
93+
1. DPDK 接管网卡后,带 `SOCK_KERNEL` 的内核栈监听:本机 `ping <内核栈IP>` 通、`curl <内核栈服务>` 成功(FR-1/FR-2)。
94+
2. F-Stack 应用作客户端:经内核栈 `connect` 本机服务(127.0.0.1/本机 IP)与外部内核栈服务均成功(FR-3/FR-4)。
95+
3. config.ini 全局默认栈开关生效,且 app 标记可覆盖(FR-5);多进程用不同 config 文件得到不同默认栈(NFR-6)。
96+
4. hook 与原生两模式均可标记选栈(FR-6);单事件循环正确服务两栈(FR-7/FR-8)。
97+
5. 本能力关闭/默认 F-Stack 时,业务性能与功能**零回归**(NFR-1/NFR-2)。
98+
6. spec 全集过 `08-review-gate.md` 门禁。

0 commit comments

Comments
 (0)