Skip to content

Commit ba14858

Browse files
committed
feat(stack-coexist): gate kernel-stack coexistence behind FF_KERNEL_COEXIST (default off)
Wrap all lib/ kernel-stack coexistence code (SOCK_KERNEL markers, managed kernel-fd encoding + host bridge, native ff_epoll merge, [stack] kernel_coexist config) behind the FF_KERNEL_COEXIST compile macro, disabled by default in lib/Makefile (added to both HOST_CFLAGS and CFLAGS). Macro off builds with zero coexist symbols (nm-verified) and keeps the original F-Stack paths byte-identical; macro on compiles the feature in. Unit tests gated likewise: off P1 50/50, on P1 54/54 incl. fd-encode roundtrip. Fix stale ff_api.h default_stack comment. Revise kernel_event_support_spec to the compile-macro paradigm and correct D1-D8 code/doc mismatches.
1 parent acfc0bd commit ba14858

34 files changed

Lines changed: 585 additions & 196 deletions

docs/kernel_event_support_spec/00-overview.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
1-
# 00 Overview: F-Stack User-Space Stack + Local Kernel Stack COEXISTENCE (per-fd marker selection + unified events)
1+
# 00 Overview: F-Stack User-Space Stack + Local Kernel Stack COEXISTENCE (compile-macro gated + per-fd marker selection + unified events)
22

33
> **Document ID**: SPEC-KE-00
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating: `FF_KERNEL_COEXIST` off by default + runtime `kernel_coexist` dual-layer switch)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
77
> **Scope**: Navigation, terminology, and scope statement for the spec in this directory
88
99
---
1010

11-
## 0. v4 Rework Background (must read)
11+
## 0. v5 Compile-Macro Gating Background (must read)
1212

13-
The v3 implementation routed `ff_socket(SOCK_KERNEL)` to `ff_host_socket()` → a raw host `socket()`, **completely bypassing the F-Stack user-space FreeBSD stack**, and the example was purely kernel-based — effectively running a kernel stack alone inside an F-Stack process and abandoning F-Stack. **This was a fundamental mistake.**
13+
v4 already landed coexistence (app ON F-Stack + per-fd `SOCK_KERNEL` to the kernel stack + unified events). But all v4 coexistence code in `lib/` is **compiled unconditionally**, so even deployments not using coexistence link it in and cannot guarantee byte-for-byte zero regression vs. upstream F-Stack.
1414

15-
**The correct v4 paradigm**: within **one F-Stack application process**, business connections use the **F-Stack user-space stack (DPDK + FreeBSD)**, while fds carrying the `SOCK_KERNEL` marker use the **host Linux kernel stack**, and the two **coexist in a single event loop**. This is exactly what F-Stack's two existing implementations do:
15+
**v5 new requirement**: gate ALL `lib/` coexistence code under a single compile macro `FF_KERNEL_COEXIST`, **commented off by default in `lib/Makefile`**, forming a **compile-time + runtime dual-layer switch**:
16+
17+
- **Compile-time (`FF_KERNEL_COEXIST`)**: undefined → all coexistence code (managed kernel-fd bridge, fd discrimination, `ff_epoll` merge, `ff_socket` kernel branch, per-`ff_*` routing, config `kernel_coexist`, `SOCK_FSTACK/SOCK_KERNEL` macros) is **not compiled**; `libfstack.a` is **byte-for-byte zero regression** vs. upstream. Defined (`make FF_KERNEL_COEXIST=1` or uncomment) → compiled in.
18+
- **Runtime (config `kernel_coexist`)**: **only when the macro is enabled**, `config.ini [stack] kernel_coexist=1` actually enables per-fd `SOCK_KERNEL` to use the kernel stack; default `=0` stays per-fd F-Stack.
19+
- **Opt-in impact**: `ff_api.h` `SOCK_FSTACK`/`SOCK_KERNEL` macros are also wrapped by `FF_KERNEL_COEXIST`, so a consumer (APP) must likewise define the macro to see these markers — the reasonable semantics of "off by default, explicitly enabled".
20+
21+
**The correct paradigm**: within **one F-Stack application process**, business connections use the **F-Stack user-space stack (DPDK + FreeBSD)**, while fds carrying the `SOCK_KERNEL` marker use the **host Linux kernel stack**, and the two **coexist in a single event loop**, gated by the compile macro `FF_KERNEL_COEXIST` (off by default). This is exactly what F-Stack's two existing implementations do:
1622
- the `FF_KERNEL_EVENT` compile mode of `adapter/syscall` (hook/LD_PRELOAD);
1723
- nginx's `kernel_network_stack` config switch.
1824

19-
This feature = **solidify that coexistence capability as the primary baseline (hook mode)** + **add unified-event coexistence to the native `ff_api` mode**, rather than building a side path that bypasses F-Stack.
25+
This feature = **solidify that coexistence capability as the primary baseline (hook mode)** + **add unified-event coexistence to the native `ff_api` mode**, gated by the `FF_KERNEL_COEXIST` compile macro, rather than building a side path that bypasses F-Stack.
26+
27+
> **v3 history**: v3 routed `ff_socket(SOCK_KERNEL)` to `ff_host_socket()` → a raw host `socket()`, completely bypassing the F-Stack user-space stack (a fundamental mistake), reverted in v4 and rewritten to the paradigm above.
2028
2129
## 1. One-Sentence Goal
2230

docs/kernel_event_support_spec/01-requirements-spec.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
# 01 Requirements Spec: F-Stack User-Space Stack + Local Kernel Stack COEXISTENCE
22

33
> **Document ID**: SPEC-KE-01
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating: `FF_KERNEL_COEXIST` off by default + runtime `kernel_coexist` dual-layer switch)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
77
> **Scope**: Define the problem domain, goals/non-goals, functional and non-functional requirements, and success criteria of this feature.
88
9+
> **v5 sync (key points; see `zh_cn/01-requirements-spec.md` for full detail)**:
10+
> - **FR-10 (compile-macro gating, opt-in)**: all `lib/` coexistence code is wrapped by `FF_KERNEL_COEXIST`, commented off by default in `lib/Makefile:57-60` (`#FF_KERNEL_COEXIST=1`); macro block at `lib/Makefile:174-177` adds `-DFF_KERNEL_COEXIST` to both `HOST_CFLAGS` and `CFLAGS`. Macro off → `libfstack.a` byte-for-byte zero regression (`nm`/`objdump` shows no `ff_host_*`/`ff_epoll_pairs` symbols).
11+
> - **FR-11 (marker opt-in visibility)**: `SOCK_FSTACK`/`SOCK_KERNEL` (`ff_api.h:81-99`) are wrapped by the macro; an APP must also define `FF_KERNEL_COEXIST` to see them.
12+
> - **NFR-1 strengthened to a compile-time guarantee**: when the macro is undefined, coexistence code is not compiled at all.
13+
> - **G4** clarified: config `kernel_coexist` is a **runtime** switch effective only when the compile macro is on.
14+
915
---
1016

1117
## 1. Problem Domain

docs/kernel_event_support_spec/02-current-state-analysis.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
# 02 Current-State Analysis: F-Stack's Existing "Dual-Stack Coexistence" Mechanism (code is authoritative)
22

33
> **Document ID**: SPEC-KE-02
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
7-
> **Scope**: Empirically measure the existing mechanism in F-Stack for "F-Stack user-space stack + host kernel stack coexisting within one process", to serve as the v4 **direct reuse baseline (hook mode) + reference (nginx) + new-design landing point (native mode)**. Covers: stack-selection markers, hook FF_KERNEL_EVENT coexistence, nginx kernel_network_stack coexistence, the native event-layer gap, and the v3-mistake revert check.
7+
> **Scope**: Empirically measure F-Stack's existing coexistence mechanism **and the now-landed native coexistence code**, as the v5 reuse baseline (hook) + reference (nginx) + existing native implementation to be gated by the compile macro. Covers: markers, hook FF_KERNEL_EVENT, nginx kernel_network_stack, **native mode current state (implemented, currently unconditionally compiled)**, the compile-macro gating state and 7-file wrapping points, and the v3-mistake revert check.
88
> **Iron rule**: every assertion carries `relative-path:line` (relative to `/data/workspace/f-stack/`); on conflict with docs/comments, **code is authoritative** and explicitly noted.
99
10+
> **v5 sync (key points; see `zh_cn/02-current-state-analysis.md` for full detail with measured line numbers)**:
11+
> - **D7 fix**: v4 called the native event layer a "gap (pure kqueue, no kernel-fd awareness)". **Code shows the gap is already filled**`lib/` already implements native coexistence: managed kernel fd = host fd + `FF_KERNEL_FD_BASE` 0x40000000 (`ff_host_interface.h:112-127`), 18 `ff_host_*` bridges (`.h:136-158` / `.c:246-367`), `ff_socket` kernel branch (`ff_syscall_wrapper.c:919-931`), 13 `ff_*` entry routes, `ff_epoll_pairs[64]` merge (`ff_epoll.c:36-37`, ctl `:97-111`, wait `:210-241`), config `kernel_coexist` (`ff_config.h:321-323` / `ff_config.c:1027-1031`,`:1363`).
12+
> - **Compile-macro state**: `lib/Makefile:57-60` (commented off) + `:174-177` (`ifdef`, dual CFLAGS) already exist, but the source `.c/.h` have **no `#ifdef FF_KERNEL_COEXIST` wrapping yet** — coexistence code is still unconditionally compiled. v5 R6 adds the source wrapping (7 files).
13+
> - **D1-D8** code-doc inconsistencies fixed in §6 (D2 config parse line `:1027-1031` not `:956`; D3 no `default_stack`, `ff_api.h:91` comment stale; D4 header `unsigned int` vs impl `socklen_t`; D5 `ff_stack_get_stats` NOT implemented; D6 encode-offset + `ff_epoll_pairs`, not enum/ownership-table; D8 routing covers 13 entries, NOT `ff_readv/writev/send/recv/getpeername/getsockname/shutdown/ioctl/sendmsg/recvmsg`).
14+
1015
---
1116

12-
## 0. v4 Current-State Positioning
17+
## 0. v5 Current-State Positioning
1318

1419
| Existing capability | Location | Form | Role in v4 |
1520
|---|---|---|---|

docs/kernel_event_support_spec/03-external-research.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# 03 External Solution Research: User-Space Stacks' "Single API + Marker Selection / Client-Side Selection / Kernel-Stack Coexistence"
22

33
> **Document ID**: SPEC-KE-03
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
7+
8+
> **v5 sync (key points; see `zh_cn/03-external-research.md` for full detail)**: added four low-trust external references (cross-check against code; code is authoritative): upstream F-Stack `adapter/syscall/README.md` (https://github.com/F-Stack/f-stack/blob/dev/adapter/syscall/README.md`FF_KERNEL_EVENT` supports both stacks at once; "kernel epoll fd leak fix" → native `ff_close` must clean up the `ff_epoll_pairs` host-epoll pairing, needs review), F-Stack site (https://www.f-stack.org/), and Chinese technical analyses (CSDN/Zhihu) corroborating the kernel-bypass + attached-kernel-side-path positioning.
79
> **Scope**: Research how other DPDK/user-space protocol-stack programs let an application **coexist between the user-space stack and the kernel stack** (business uses the user-space stack, some fds use the kernel stack on demand, in the same process and event loop), and how they handle "an application as a client connecting to local/external kernel services"; extract reusable points and limitations. Every entry carries an **accessible URL**.
810
> **Paradigm note (v4)**: this feature aims at **dual-stack coexistence** — the F-Stack user-space stack always carries the business, and per-fd `SOCK_KERNEL` makes some fds **additionally** use the kernel stack, in a unified event loop. Do **not** create a side socket that bypasses F-Stack (v3 `ff_host_socket` deprecated), do **not** add a whole-process default-to-kernel switch, do **not** create a dual API, do **not** do thread-level selection. Primary baseline = hook `FF_KERNEL_EVENT`, reference = nginx `kernel_network_stack`. KNI/packet reinjection is boundary clarification only.
911

docs/kernel_event_support_spec/04-architecture-design.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# 04 Architecture Design: F-Stack + Kernel Stack COEXISTENCE + per-fd marker selection + unified events
22

33
> **Document ID**: SPEC-KE-04
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
7+
8+
> **v5 sync (key points; see `zh_cn/04-architecture-design.md` for full detail)**: dual-layer switch — compile macro `FF_KERNEL_COEXIST` gates compile-time (off by default → coexistence code not compiled → byte-for-byte zero regression), config `[stack] kernel_coexist` gates runtime (effective only when the macro is on). `SOCK_*` markers are opt-in (APP must define the macro). Native coexistence is **already implemented** (not "new design"): fd discrimination via `FF_KERNEL_FD_BASE` encode offset + `ff_epoll_pairs[64]` pairing table (NOT enum/ownership-table, D6). Routing covers 13 entries only; `ff_readv/writev/send/recv/getpeername/getsockname/shutdown/ioctl/sendmsg/recvmsg` not covered (D8 known limitation).
79
> **Scope**: The coexistence architecture, the selection model, dual-stack unified events, the client/server bidirectional data flow, and both hook and native modes.
810
> **Basis**: `02` (code current state), `03` (external solutions); on conflict, code is authoritative.
911

docs/kernel_event_support_spec/05-interface-design.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
# 05 Interface Design: Marker Selection + config coexistence switch + hook/native dual-mode contracts
22

33
> **Document ID**: SPEC-KE-05
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
7+
8+
> **v5 sync (key points; see `zh_cn/05-interface-design.md` for full detail)**:
9+
> - **Compile-macro / opt-in contract**: `FF_KERNEL_COEXIST` off by default in `lib/Makefile:57-60`; macro block `:174-177`. `SOCK_FSTACK/SOCK_KERNEL` (`ff_api.h:81-99`) wrapped → APP must define the macro to see them.
10+
> - **D2 fix**: config parse is at `ff_config.c:1027-1031`, default `:1363` (NOT `:956`/`MATCH("kni","enable"):1011`); struct at `ff_config.h:321-323`.
11+
> - **D3 fix**: code has no `default_stack`; priority chain = `per-socket marker > config kernel_coexist enabled > F-Stack`; the `ff_api.h:91` "default_stack" comment is stale.
12+
> - **D4**: bridge declarations use `unsigned int` (`ff_host_interface.h:136-158`), implementations use `socklen_t` (`.c:246-367`) — equivalent/compilable on Linux.
13+
> - **D5**: `struct ff_stack_stats` / `ff_stack_get_stats` are **NOT implemented** (design intent only, do not treat as fact).
14+
> - **D6**: data structures are `FF_KERNEL_FD_BASE` encode offset (`ff_host_interface.h:112-127`) + `ff_epoll_pairs[64]` (`ff_epoll.c:36-37`), NOT `enum ff_stack_owner`/ownership table.
715
> **Scope**: Stack-selection marker convention, the config coexistence-capability switch, server/client usage, hook and native dual-mode adaptation, data structures, and error handling.
816
> **Core principle**: **do not create a side API, do not create a socket that bypasses F-Stack**; reuse the single API (the hook POSIX suite + the native `ff_*` suite), selecting the stack by per-fd markers + a config coexistence switch, with F-Stack always present.
917
> **Basis**: `02` (code current state), `04` (architecture). Line numbers are subject to the code; the gatekeeper's re-verification is authoritative in the implementation phase.

docs/kernel_event_support_spec/06-milestones.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# 06 Milestones and Coding Work List
22

33
> **Document ID**: SPEC-KE-06
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
7-
> **Scope**: The rework implementation roadmap of this feature.
7+
> **Scope**: The rework + compile-macro-gating implementation roadmap of this feature.
8+
9+
> **v5 sync (key points; see `zh_cn/06-milestones.md` for full detail)**: new milestone **R6 compile-macro gating** — wrap the already-landed coexistence code with `#ifdef FF_KERNEL_COEXIST` (the 7 wrapping points in `02 §4bis.2`) + Makefile macro block (commented off by default, dual CFLAGS, already in place at `lib/Makefile:174-177`) + macro-on/off dual-build `nm` zero-regression verification (macro off → no `ff_host_*`/`ff_epoll_pairs` symbols; macro on → functional).
810
911
---
1012

docs/kernel_event_support_spec/07-test-spec.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# 07 Test and Performance-Baseline Spec
22

33
> **Document ID**: SPEC-KE-07
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
66
> **Status**: Drafting
7-
> **Scope**: The unit/integration/performance-baseline test plan and gate standard for this feature (dual-stack coexistence: hook FF_KERNEL_EVENT + native unified events + config coexistence switch + client coexistence).
7+
> **Scope**: The unit/integration/performance-baseline/compile-macro-zero-regression test plan and gate standard for this feature (compile-macro `FF_KERNEL_COEXIST` gating + dual-stack coexistence: hook FF_KERNEL_EVENT + native unified events + config runtime switch + client coexistence).
8+
9+
> **v5 sync (key points; see `zh_cn/07-test-spec.md` for full detail)**: new **compile-macro zero-regression layer (MT-1~MT-5)** — macro off `make` + `nm`/`objdump` shows no coexistence symbols and matches upstream `libfstack.a` (FR-10/NFR-1); macro-off TU referencing `SOCK_KERNEL` fails to compile (opt-in, FR-11); macro on `make FF_KERNEL_COEXIST=1` → symbols appear, functional (MT-3); dual CFLAGS check (MT-4); `ff_api.symlist` unchanged (MT-5). cmocka coexistence cases (UT-3~UT-10) are conditional on the macro being on. D8 routing limitation must be documented (managed kernel fd must not call the 10 un-routed entries).
810
> **Alignment**: `tests/unit` (**cmocka**, *.c + *.ini), `tests/integration`, coverage `tests/run_full_coverage.sh` (lcov).
911
1012
---

docs/kernel_event_support_spec/08-review-gate.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# 08 Review Gate Report
22

33
> **Document ID**: SPEC-KE-08
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
6-
> **Status**: R1 spec gate PASS + R2-R4 implementation gate PASS (incl. real-hardware perf baseline PERF-1/2/3); R5 commit wrap-up
7-
> **Scope**: Gate verification of the v4 spec and implementation for "consistency with the actual code / coexistence-paradigm correctness / zero regression".
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
6+
> **Status**: v4 R1 spec + R2-R4 implementation gate PASS (incl. real-hardware perf baseline PERF-1/2/3); v5 adds R6 compile-macro gating gate (pending measurement)
7+
> **Scope**: Gate verification of the v5 spec and implementation for "consistency with the actual code (incl. D1-D8 fixes) / coexistence-paradigm correctness / compile-macro gating completeness / zero regression".
8+
9+
> **v5 sync (key points; see `zh_cn/08-review-gate.md` for full detail)**: new gate items — M1 wrapping completeness (7 files), M2 dual-side CFLAGS, M3 `symlist` unchanged, M4 macro-off symbol zero-regression (MT-1), M5 macro-on functional, M6 opt-in visibility, M7 `ff_api.h:91` comment fix; plus D1-D8 code-doc consistency checklist (all fixed in spec, R6 code wrapping + comment fix pending).
810
911
---
1012

docs/kernel_event_support_spec/09-impl-plan.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# 09 Implementation Plan: F-Stack + Kernel Stack Coexistence (R0-R5)
22

33
> **Document ID**: SPEC-KE-09 (implementation-phase plan)
4-
> **Version**: v4 (coexistence-paradigm rework)
5-
> **Date**: 2026-06-16
6-
> **Status**: In progress
7-
> **Basis**: the v4 spec in this directory (00-08); line numbers are subject to the actual code, gatekeeper re-verified.
4+
> **Version**: v5 (compile-macro gating)
5+
> **Date**: 2026-06-17
6+
> **Status**: In progress (R0-R5 done; R6 compile-macro gating pending)
7+
> **Basis**: the v5 spec in this directory (00-08); line numbers are subject to the actual code, gatekeeper re-verified.
8+
9+
> **v5 sync (key points; see `zh_cn/09-impl-plan.md` for full detail)**: **R6 landing steps** — (1) Makefile macro block (commented off `lib/Makefile:57-60`, dual CFLAGS `:174-177`, already in place); (2) wrap the 7 files per `02 §4bis.2` with `#ifdef FF_KERNEL_COEXIST` (`ff_api.h:81-99`, `ff_host_interface.h:94-158`, `ff_host_interface.c:29-31/42-45/246-367`, `ff_config.h:321-323`, `ff_config.c:1027-1031/1363`, `ff_epoll.c:25-68/97-111/210-241`, `ff_syscall_wrapper.c:64/919-931/13 entry routes`), keeping each `ff_*` default path outside the `#ifdef`; (3) fix the stale `default_stack` comment at `ff_api.h:91`; (4) dual-build `nm` zero-regression verification. `ff_api.symlist` unchanged; clean full rebuild after header changes (ABI skew).
810
911
---
1012

0 commit comments

Comments
 (0)