Skip to content

Commit a695757

Browse files
committed
docs: multi-agent review and fix for architecture docs and specs
Architecture docs (simplified + full versions): - Fix API signatures: ff_kevent_do_each (3→7 params), ff_route_ctl (2→5 params), ff_rtioctl, ff_zc_mbuf_get, ff_sysctl, ff_log/ff_vlog (add level+logtype) - Fix Socket API: struct sockaddr → struct linux_sockaddr throughout - Fix ff_openlog_stream → ff_log_reset_stream / ff_log_open_set - Fix global vars: enable_kni (static→non-static), nb_dev_ports (uint32_t→int), idle_sleep (uint32_t→unsigned, remove default), pktmbuf_pool (MAX_LCORE→NB_SOCKETS) - Fix struct ff_tx_offload and ff_dispatcher_context fields per source - Fix main_loop pseudocode: TX drain before RX, add idle sleep step - Fix code block language markers (8 blocks) - Fix markdown syntax (unclosed bold, list spacing) - Fix typo: unctions_default → functions_default Specs documents: - P0: Unify eventfd design (single evfd → dual eventfd_req/eventfd_rsp) across SPEC-002/003 - P0: Unify function naming (ff_create_ring_zone → ff_create_sc_ring_zone) across SPEC-002/003 - P0: Reconcile throughput targets (1.5x→1.2x micro, ≥10% Nginx) across SPEC-001/004 - P1: Fix ring entries count (32→64) in SPEC-001 NFR-004 - P1: Fix ff_thread_handle offset (68→72, 8-byte alignment) in SPEC-003 - P1: Add clarifying comment for ACQUIRE_ZONE_LOCK macro in Ring mode - P1: Fix operator precedence bug (++spin_count & 0xFF == 0) in SPEC-003 - P1: Annotate 72h stability test vs 24h acceptance criteria Stats: Update SUMMARY.txt line counts to match modified files
1 parent e5628d1 commit a695757

12 files changed

Lines changed: 119 additions & 125 deletions

docs/01-LAYER1-ARCHITECTURE.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
F-Stack 采用了"用户态网络栈"架构,解决 Linux 内核网络处理的性能瓶颈:
1212

13-
```
13+
```text
1414
应用层 (Applications)
1515
↓ (ff_socket/ff_read/ff_write 等 Linux-like API)
1616
F-Stack 库 (libfstack.a)
@@ -49,7 +49,7 @@ NIC 驱动 (igb_uio / vfio-pci)
4949

5050
### 2.1 核心目录布局
5151

52-
```
52+
```text
5353
/data/workspace/f-stack/
5454
├── lib/ # F-Stack 核心库 (~21K 行 C 代码)
5555
│ ├── ff_dpdk_if.c (2855行) # DPDK 网卡接口层 - 最核心
@@ -123,7 +123,7 @@ F-Stack 采用了**完整移植**策略:
123123

124124
### 3.2 FreeBSD 移植的子系统
125125

126-
```
126+
```text
127127
freebsd/sys/
128128
├── netinet/ # IPv4: tcp_*.c, udp_*.c, ip_*.c, if_arp.c
129129
├── netinet6/ # IPv6: ip6_*.c, tcp6_*.c
@@ -151,7 +151,7 @@ freebsd/sys/
151151
这是最核心的模块 (2855 行),负责整个数据链路:
152152

153153
**初始化流程**:
154-
```
154+
```text
155155
ff_dpdk_init()
156156
├─ rte_eal_init() // DPDK 环境初始化
157157
├─ init_lcore_conf() // CPU 核心/端口映射
@@ -164,7 +164,7 @@ ff_dpdk_init()
164164

165165
### 4.2 收包流程 (Ingress)
166166

167-
```
167+
```text
168168
NIC 硬件 (RSS 处理器分发)
169169
170170
多个 RX 队列 (per-CPU-core)
@@ -179,7 +179,7 @@ process_packets() 函数
179179

180180
### 4.3 发包流程 (Egress)
181181

182-
```
182+
```text
183183
应用 (ff_write/ff_send/ff_sendto/ff_sendmsg)
184184
185185
FreeBSD TCP/UDP 栈
@@ -241,7 +241,7 @@ int main_loop(void *arg) {
241241
242242
### 6.1 单进程模式 (推荐)
243243
244-
```
244+
```text
245245
F-Stack 进程 (1 个)
246246
└─ 单个 lcore (1 个 CPU 核心)
247247
├─ NIC RX/TX 队列映射
@@ -253,7 +253,7 @@ F-Stack 进程 (1 个)
253253

254254
### 6.2 多进程模式
255255

256-
```
256+
```text
257257
主进程 (Primary)
258258
├─ DPDK EAL 初始化
259259
└─ 启动 N 个 Worker 进程
@@ -335,4 +335,5 @@ F-Stack 的架构设计围绕三个核心支柱:
335335
1. **Kernel Bypass**: 规避 Linux 内核瓶颈
336336
2. **成熟协议栈**: 复用 FreeBSD 久经考验的实现
337337
3. **多核并行**: 充分利用现代多核 CPU 和 NIC 硬件能力
338-
这使得 F-Stack 能够达到 500 万+ RPS、1000 万+ 并发连接的性能水平,是云计算核心网络设施的理想选择。
338+
339+
这使得 F-Stack 能够达到 500 万+ RPS、1000 万+ 并发连接的性能水平,是云计算核心网络设施的理想选择。

docs/02-LAYER2-INTERFACES.md

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,25 @@ void ff_stop_run(void); // 优雅停止循环
2727
```c
2828
// Socket 创建和管理
2929
int ff_socket(int domain, int type, int protocol);
30-
int ff_bind(int s, const struct sockaddr *addr, socklen_t addrlen);
30+
int ff_bind(int s, const struct linux_sockaddr *addr, socklen_t addrlen);
3131
int ff_listen(int s, int backlog);
32-
int ff_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
33-
int ff_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags);
34-
int ff_connect(int s, const struct sockaddr *addr, socklen_t addrlen);
35-
int ff_close(int s);
32+
int ff_accept(int s, struct linux_sockaddr *addr, socklen_t *addrlen);
33+
int ff_accept4(int s, struct linux_sockaddr *addr, socklen_t *addrlen, int flags);
34+
int ff_connect(int s, const struct linux_sockaddr *name, socklen_t namelen);
35+
int ff_close(int fd);
3636
3737
// 数据 I/O
38-
ssize_t ff_read(int s, void *buf, size_t len);
39-
ssize_t ff_readv(int s, const struct iovec *iov, int iovcnt);
40-
ssize_t ff_write(int s, const void *buf, size_t len);
41-
ssize_t ff_writev(int s, const struct iovec *iov, int iovcnt);
38+
ssize_t ff_read(int d, void *buf, size_t nbytes);
39+
ssize_t ff_readv(int fd, const struct iovec *iov, int iovcnt);
40+
ssize_t ff_write(int fd, const void *buf, size_t nbytes);
41+
ssize_t ff_writev(int fd, const struct iovec *iov, int iovcnt);
4242
ssize_t ff_send(int s, const void *buf, size_t len, int flags);
4343
ssize_t ff_sendto(int s, const void *buf, size_t len, int flags,
44-
const struct sockaddr *to, socklen_t tolen);
44+
const struct linux_sockaddr *to, socklen_t tolen);
4545
ssize_t ff_sendmsg(int s, const struct msghdr *msg, int flags);
4646
ssize_t ff_recv(int s, void *buf, size_t len, int flags);
4747
ssize_t ff_recvfrom(int s, void *buf, size_t len, int flags,
48-
struct sockaddr *from, socklen_t *fromlen);
48+
struct linux_sockaddr *from, socklen_t *fromlen);
4949
ssize_t ff_recvmsg(int s, struct msghdr *msg, int flags);
5050
5151
// Socket 选项
@@ -63,8 +63,9 @@ int ff_kqueue(void);
6363
int ff_kevent(int kq, const struct kevent *changelist, int nchanges,
6464
struct kevent *eventlist, int nevents,
6565
const struct timespec *timeout);
66-
void ff_kevent_do_each(int kq, void *arg,
67-
void (*cb)(int fd, short, void *));
66+
int ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges,
67+
void *eventlist, int nevents, const struct timespec *timeout,
68+
void (*do_each)(void **, struct kevent *));
6869

6970
// Linux epoll (兼容)
7071
int ff_epoll_create(int size);
@@ -86,31 +87,33 @@ int ff_fcntl(int s, int cmd, ...);
8687
int ff_ioctl(int s, unsigned long request, ...);
8788
8889
// 系统配置
89-
int ff_sysctl(int *name, u_int namelen, void *oldp,
90-
size_t *oldlenp, void *newp, size_t newlen);
90+
int ff_sysctl(const int *name, u_int namelen, void *oldp,
91+
size_t *oldlenp, const void *newp, size_t newlen);
9192
```
9293

9394
### 1.5 特殊功能 API
9495

9596
```c
96-
// 原始包发送
97-
int ff_route_ctl(int cmd, struct rtentry *rt);
98-
int ff_rtioctl(int req, struct rt_addrinfo *info);
97+
// 路由控制
98+
int ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
99+
struct linux_sockaddr *dst, struct linux_sockaddr *gw,
100+
struct linux_sockaddr *netmask);
101+
int ff_rtioctl(int fib, void *data, unsigned *plen, unsigned maxlen);
99102

100103
// 零拷贝 mbuf 操作
101-
struct rte_mbuf *ff_zc_mbuf_get(int s);
102-
int ff_zc_mbuf_write(int s, struct rte_mbuf *m);
103-
int ff_zc_mbuf_read(int s, struct rte_mbuf **m); // 【注】暂未实现,后续考虑支持
104+
int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len);
105+
int ff_zc_mbuf_write(struct ff_zc_mbuf *m, const char *data, int len);
106+
int ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len); // 【注】暂未实现
104107

105108
// 时间相关
106109
int ff_gettimeofday(struct timeval *tv, struct timezone *tz);
107110

108111
// 日志
109-
void ff_log(const char *format, ...);
110-
void ff_vlog(const char *format, va_list ap);
111-
void ff_openlog_stream(FILE *fp);
112-
void ff_log_set_global_level(unsigned int level);
113-
void ff_log_set_level(unsigned int level);
112+
int ff_log(uint32_t level, uint32_t logtype, const char *format, ...);
113+
int ff_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap);
114+
int ff_log_reset_stream(void *f);
115+
void ff_log_set_global_level(uint32_t level);
116+
int ff_log_set_level(uint32_t logtype, uint32_t level);
114117
void ff_log_close(void);
115118

116119
// 多线程支持
@@ -379,15 +382,7 @@ void worker_main(int worker_id) {
379382

380383
### 4.3 进程间通信
381384

382-
```c
383-
// 发送消息到其他 lcore
384-
int ff_msg_send(unsigned lcore_id, void (*cb)(void *), void *arg);
385-
386-
// 在另一个 lcore 接收消息
387-
void msg_handler(void *arg) {
388-
// 在消息接收的 lcore 中执行
389-
}
390-
```
385+
> **注意**: `ff_msg_send()` 不是公开 API,在 `ff_api.h``ff_api.symlist` 中均不存在。进程间通信通过 `ff_msg` 消息队列(`lib/ff_msg.h`)实现,由 F-Stack 内部工具(knictl/sysctl 等)使用,应用层无需直接调用。
391386
392387
## 5. 线程安全性
393388

docs/03-LAYER3-FUNCTIONS.md

Lines changed: 45 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
|-----|------|------|
7575
| `ff_sysctl` | 6 | 读写内核变量 |
7676
| `ff_route_ctl` | 5 | 路由表控制 |
77-
| `ff_rtioctl` | 2 | 路由 ioctl |
77+
| `ff_rtioctl` | 4 | 路由 ioctl |
7878
| `ff_gettimeofday` | 2 | 获取系统时间 |
7979

8080
### 1.7 特殊功能函数
@@ -98,14 +98,14 @@
9898

9999
### 1.9 日志函数
100100

101-
| 函数 | 功能 |
102-
|-----|------|
103-
| `ff_log` | 格式化日志 |
104-
| `ff_vlog` | va_list 日志 |
105-
| `ff_openlog_stream` | 打开日志流 |
106-
| `ff_log_set_global_level` | 设置全局日志级别 |
107-
| `ff_log_set_level` | 设置模块日志级别 |
108-
| `ff_log_close` | 关闭日志 |
101+
| 函数 | 签名 | 功能 |
102+
|-----|------|------|
103+
| `ff_log` | `int ff_log(uint32_t level, uint32_t logtype, const char *format, ...)` | 格式化日志 |
104+
| `ff_vlog` | `int ff_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)` | va_list 日志 |
105+
| `ff_log_reset_stream` | `int ff_log_reset_stream(void *f)` | 重设日志输出流 |
106+
| `ff_log_set_global_level` | `void ff_log_set_global_level(uint32_t level)` | 设置全局日志级别 |
107+
| `ff_log_set_level` | `int ff_log_set_level(uint32_t logtype, uint32_t level)` | 设置模块日志级别 |
108+
| `ff_log_close` | `void ff_log_close(void)` | 关闭日志 |
109109

110110
## 2. 核心数据结构
111111

@@ -261,11 +261,11 @@ struct ff_msg {
261261

262262
```c
263263
struct ff_tx_offload {
264+
uint8_t ip_csum; // IP 校验和卸载
265+
uint8_t tcp_csum; // TCP 校验和卸载
266+
uint8_t udp_csum; // UDP 校验和卸载
267+
uint8_t sctp_csum; // SCTP 校验和卸载
264268
uint16_t tso_seg_size; // TSO 分段大小 (0 = 禁用)
265-
uint8_t tx_csum_ip; // IP 校验和卸载
266-
uint8_t tx_csum_l4; // L4 校验和卸载
267-
uint8_t vlan_insert; // VLAN 插入标志
268-
uint16_t vlan_id; // VLAN ID
269269
};
270270
```
271271

@@ -295,21 +295,14 @@ int ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len); // 暂未
295295
296296
### 2.8 ff_dispatcher_context 结构 (包分发)
297297
298+
> **注意**: 以下为 `ff_api.h` 中的实际定义。此结构作为 `dispatch_func_context_t` 回调的额外上下文参数传入,仅包含 VLAN 相关信息。报文数据、长度、队列等信息通过回调函数的其他参数传递。
299+
298300
```c
299301
struct ff_dispatcher_context {
300-
uint16_t port_id; // 入口网卡
301-
uint16_t queue_id; // 入口队列
302-
303-
uint8_t *data; // 报文数据
304-
uint16_t len; // 报文长度
305-
306-
// 解析结果
307-
uint16_t vlan_id; // VLAN ID
308-
uint8_t *l3_data; // L3 头指针
309-
uint8_t *l4_data; // L4 头指针
310-
311-
// 控制信息
312-
uint32_t flags; // 标志位
302+
struct {
303+
uint8_t stripped; // VLAN 是否已剥离
304+
uint16_t vlan_tci; // Priority (3) + CFI (1) + Identifier Code (12)
305+
} vlan;
313306
};
314307
```
315308

@@ -405,10 +398,10 @@ ff_dpdk_if.c
405398
**关键全局变量**:
406399

407400
```c
408-
static uint32_t enable_kni = 0; // KNI 启用标志
409-
static uint16_t nb_dev_ports = 0; // NIC 数量
410-
static uint32_t idle_sleep = 100; // 空闲睡眠微秒数
411-
static struct rte_mempool *pktmbuf_pool[RTE_MAX_LCORE]; // 每核 mbuf 池
401+
int enable_kni = 0; // KNI 启用标志(非 static)
402+
int nb_dev_ports = 0; // NIC 数量(非 static,非 uint16_t)
403+
static unsigned idle_sleep; // 空闲睡眠微秒数(由配置赋值,无硬编码默认值)
404+
struct rte_mempool *pktmbuf_pool[NB_SOCKETS]; // 按 NUMA socket 索引的 mbuf 池
412405
```
413406

414407
**初始化函数调用链**:
@@ -446,42 +439,42 @@ int main_loop(void *arg) {
446439
uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
447440
uint64_t cur_tsc, prev_tsc = 0;
448441

449-
while (!stop_loop) {
442+
while (1) {
443+
if (unlikely(stop_loop)) break;
444+
450445
cur_tsc = rte_rdtsc();
451446

452447
// === 1. 驱动 FreeBSD 定时器 ===
453448
if (unlikely(freebsd_clock.expire < cur_tsc)) {
454449
rte_timer_manage(); // 触发 TCP timers 等
455-
freebsd_clock.expire = cur_tsc + FREEBSD_CLOCK_TICK;
456450
}
457451

458-
// === 2. 接收报文 ===
459-
for (each_port in lr->ports) {
460-
for (each_queue) {
461-
uint16_t nb_rx = rte_eth_rx_burst(
462-
port_id, queue_id,
463-
pkts_burst, MAX_PKT_BURST
464-
);
465-
process_packets(pkts_burst, nb_rx);
452+
// === 2. TX burst queue drain (先于 RX) ===
453+
diff_tsc = cur_tsc - prev_tsc;
454+
if (unlikely(diff_tsc >= drain_tsc)) {
455+
for (each_port in qconf->tx_ports) {
456+
send_burst(qconf, ...);
466457
}
458+
prev_tsc = cur_tsc;
467459
}
468460

469-
// === 3. 发送报文 (定时刷新) ===
470-
if (drain_tsc && (cur_tsc - prev_tsc) > drain_tsc) {
471-
for (each_port in lr->ports) {
472-
uint16_t nb_tx = rte_eth_tx_buffer_flush(
473-
port_id, queue_id, tx_buffer
474-
);
475-
}
476-
prev_tsc = cur_tsc;
461+
// === 3. 接收报文 (RX) ===
462+
for (each_rx_queue in qconf->rx_queues) {
463+
uint16_t nb_rx = rte_eth_rx_burst(
464+
port_id, queue_id,
465+
pkts_burst, MAX_PKT_BURST
466+
);
467+
process_packets(pkts_burst, nb_rx);
477468
}
478469

479470
// === 4. 执行用户回调 ===
480471
if (lr->loop) {
481-
int ret = lr->loop(lr->arg); // 应用业务逻辑
482-
if (ret < 0) {
483-
ff_stop_run();
484-
}
472+
lr->loop(lr->arg); // 应用业务逻辑
473+
}
474+
475+
// === 5. 空闲睡眠 ===
476+
if (likely(idle && idle_sleep)) {
477+
rte_delay_us_sleep(idle_sleep);
485478
}
486479
}
487480

docs/F-Stack_Architecture_Layer1_System_Overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ F-Stack (用户态)
673673
- 默认速率限制:1K QPS 数据、9K QPS 控制、10K QPS 总体
674674
- 可选的报文分发回调:应用自定义哪些流进入 KNI
675675
676-
**kni和virtio选择
676+
**KNI 和 virtio 选择**
677677
678678
- 当前版本 KNI 功能保留,但底层实现已从 `rte_kni.ko` 内核模块切换为 `virtio_user`(见 lib/Makefile:34),不再依赖内核 KNI 模块
679679

0 commit comments

Comments
 (0)