Skip to content

Commit 0f0472e

Browse files
author
unit-test-impl-leader
committed
test(unit): add P3 tests for ff_dpdk_kni + ff_in_pcbladdr (Stage-5)
Stage-5 P3 follow-ups (FU-S4-KNI / FU-S4-DPDK-IF-FULL): 7 new TCs. - test_ff_dpdk_kni (+4 TC): ff_kni_enqueue ratelimit branches via real EAL --no-huge + mempool/ring. - test_ff_dpdk_if (+3 TC): ff_in_pcbladdr 4-branch coverage. FU-S4-PKTMBUF deferred to integration tests (needs hugepage mempool). Total now 90 TC / 11 binaries / runtime ~5.2s, all PASS. See docs/unit_test_spec/zh_cn/99-stage5-p3-review.md for details.
1 parent 46227a0 commit 0f0472e

5 files changed

Lines changed: 539 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,4 @@ tests/unit/test_ff_thread
7979
tests/unit/test_ff_init
8080
tests/unit/test_ff_dpdk_pcap
8181
tests/unit/test_ff_dpdk_if
82+
tests/unit/test_ff_dpdk_kni
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# 99 — Stage-5 P3 Follow-ups Review
2+
3+
> 文档版本:v0.1(2026-06-10 11:15 UTC+8)
4+
> Stage:Stage-5(P3 follow-up:FU-S4-KNI / FU-S4-DPDK-IF-FULL / FU-S4-PKTMBUF)
5+
> 上一阶段:Stage-4 P2(HEAD `46227a0e0`,PASS)
6+
7+
---
8+
9+
## 0. 总评:**PASS**(BOUNCE 0/4)
10+
11+
| Gate | 检查 | 结果 |
12+
|---|---|---|
13+
| **G6d** | test_ff_dpdk_kni build & run(含 EAL `--no-huge` init) | ✅ 4/4 PASS |
14+
| **G6e** | test_ff_dpdk_if 增 3 TC(ff_in_pcbladdr) | ✅ 10/10 PASS(含 1 处 spec-vs-code 修正:EADDRNOTAVAIL=99 非 49)|
15+
| **G_FINAL** | 全套 `make test` 不退化 |**11 binaries / 90 TC / 5.19s 全 PASS** |
16+
17+
---
18+
19+
## 1. 三个 P3 Follow-up 处理结果
20+
21+
| Follow-up | 决策 | 实施 |
22+
|---|---|---|
23+
| **FU-S4-PKTMBUF** | DEFER to integration tests | ff_dpdk_pktmbuf_free 调 inline rte_pktmbuf_free_seg → 必须真 mempool;mempool 必须 EAL init + hugepages → 不适合 unit test。改建议在 helloworld/nginx 集成测试覆盖 |
24+
| **FU-S4-KNI** | 实施(部分) | ff_kni_enqueue 限速逻辑 4 TC(ff_kni_init/alloc/process 仍 deferred 因需 KNI subsystem + virtio_user hotplug) |
25+
| **FU-S4-DPDK-IF-FULL** | 实施(小子集) | ff_in_pcbladdr 3 TC(4 分支:no callback / AF_INET / AF_INET6_FREEBSD remap / unknown family) |
26+
27+
---
28+
29+
## 2. Phase 落地
30+
31+
### Phase 1 plan
32+
- `plan-stage5-p3-followups.md`(local-only via .gitignore plan-*.md)
33+
34+
### Phase 2 — FU-S4-KNI(test_ff_dpdk_kni.c, 4 TC)
35+
- TC-01 `test_ff_kni_enqueue_no_ratelimit`:限速=0 → enqueue 通过,ring 含 1 entry
36+
- TC-02 `test_ff_kni_enqueue_console_ratelimit_over`:console_ratelimit=2 → 第 3 次 over → -1 + rx_dropped++
37+
- TC-03 `test_ff_kni_enqueue_general_ratelimit_over`:general 路径同
38+
- TC-04 `test_ff_kni_enqueue_filter_classification`:FILTER_ARP→console / FILTER_KNI→general 计数器分流
39+
40+
**关键技术**`rte_eal_init(--no-huge --no-pci --no-shconf -m 32 --file-prefix=ff_kni_test)` 一次性 init EAL;创建真实 mempool 64 buf + ring 16 slot;wire kni_rp[0] / kni_stat[0]。EAL init 失败兜底(`SKIP_IF_NO_EAL` 宏全 4 TC skip)。
41+
42+
### Phase 3 — FU-S4-DPDK-IF-FULL(test_ff_dpdk_if.c +3 TC)
43+
- TC-08 `test_ff_in_pcbladdr_no_callback`:pcblddr_fun=NULL → 0
44+
- TC-09 `test_ff_in_pcbladdr_af_inet_dispatches`:family=AF_INET → callback 收到 (AF_INET, faddr, fport, laddr) 完全透传 + 返回值透传
45+
- TC-10 `test_ff_in_pcbladdr_af_inet6_freebsd_to_linux_remap`:AF_INET6_FREEBSD(28) remap 到 AF_INET6_LINUX(10) + unknown family → 返回 EADDRNOTAVAIL
46+
47+
### Phase 4 — Review + commit(本阶段)
48+
49+
---
50+
51+
## 3. spec-vs-code 修正(DP-U-12)
52+
53+
| # | 位置 | 期望(plan)| 实际(代码)| 修正 |
54+
|---|---|---|---|---|
55+
| 1 | TC-10 unknown family 返回值 | `ff_EADDRNOTAVAIL` (49) | POSIX `EADDRNOTAVAIL` (99 on Linux glibc) | TC 改用 `EADDRNOTAVAIL`|
56+
57+
---
58+
59+
## 4. 工作区合规
60+
61+
- ✅ 0 直接 rm/kill/chmod
62+
- ✅ make clean / coverage_clean 走 `rm_tmp_file.sh`
63+
- ✅ 新 binary `test_ff_dpdk_kni` 已加 `.gitignore`
64+
65+
---
66+
67+
## 5. 累计 TC 数
68+
69+
| Stage | TC 数 |
70+
|---|---|
71+
| Stage-2(spec 基线 + P0/P1) | 59 |
72+
| Stage-3(覆盖率 + 扩 5 TC) | 64 |
73+
| Stage-4(P2 +19) | 83 |
74+
| **Stage-5(P3 +7)** | **90** |
75+
76+
11 个 binaries / 总耗时 5.19s(< NFR-U-5 30s 阈值)。
77+
78+
---
79+
80+
## 6. 剩余 follow-up
81+
82+
| ID | 内容 | 优先级 | 建议 |
83+
|---|---|---|---|
84+
| **FU-S4-PKTMBUF** | ff_dpdk_pktmbuf_free(已 defer) | P4 | 集成测试覆盖 |
85+
| **FU-S4-KNI-INIT-ALLOC-PROCESS** | ff_kni_init / ff_kni_alloc / ff_kni_process 测试(需 virtio_user hotplug) | P4 | 集成测试覆盖 |
86+
| **FU-S4-DPDK-IF-OTHER** | ff_dpdk_if.c 其余 ~136 个 ff_* 函数(lcore_conf / rss_reta_size 全局依赖)| P4 | 集成测试覆盖 |
87+
| **FU-U-5** | CI 集成 | P2 | 下一 stage 候选 |
88+
| **FU-S2-1** | valgrind into make check | P3 | 下一 stage 候选 |
89+
| **FU-U-7** | 4 篇 spec 英文翻译 | P3 | 人工审计后 |
90+
91+
---
92+
93+
## 7. 交付物
94+
95+
| 文件 || tracked |
96+
|---|---|---|
97+
| `tests/unit/test_ff_dpdk_kni.c` | 270 | ✅ new |
98+
| `tests/unit/test_ff_dpdk_if.c` (modified) | +95 ||
99+
| `tests/unit/Makefile` (modified) | +12 ||
100+
| `.gitignore` (modified) | +1 ||
101+
| `99-stage5-p3-review.md` (本文件) | ~120 | ✅ new |
102+
103+
---
104+
105+
**Stage-5 P3 follow-up PASS** — 进入 commit。

tests/unit/Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@ $(error CMocka >= 1.1.7 required, found '$(CMOCKA_VER)')
2424
endif
2525

2626
# Host-only build flags (R-U-2 / NFR-U-4)
27+
# DPDK_CFLAGS includes -march=native -mssse3 etc. needed because rte_memcpy
28+
# and other inline DPDK helpers expand into ISA-specific intrinsics.
2729
CFLAGS := -O0 -g3 -Wall -Wextra -Wno-unused-parameter \
2830
-I$(LIB_DIR) -I$(COMMON_DIR) \
2931
$(CMOCKA_CFLAGS) \
32+
$(DPDK_CFLAGS) \
3033
-DFF_UNIT_TEST=1
3134

3235
# Fatal-function wraps applied globally (spec 04 §8.1):
@@ -46,7 +49,8 @@ SANITY_TESTS := test_hello
4649
P0_TESTS := test_ff_ini_parser test_ff_log
4750
P1_TESTS := test_ff_host_interface test_ff_epoll test_ff_config
4851
P2_TESTS := test_ff_thread test_ff_init test_ff_dpdk_pcap test_ff_dpdk_if
49-
ALL_TESTS := $(SANITY_TESTS) $(P0_TESTS) $(P1_TESTS) $(P2_TESTS)
52+
P3_TESTS := test_ff_dpdk_kni
53+
ALL_TESTS := $(SANITY_TESTS) $(P0_TESTS) $(P1_TESTS) $(P2_TESTS) $(P3_TESTS)
5054

5155
# Common stub objects
5256
COMMON_OBJS := $(COMMON_DIR)/ff_log_stub.o $(COMMON_DIR)/rte_stub.o
@@ -90,6 +94,11 @@ test_p2: $(P2_TESTS)
9094
echo "==> running $$t"; $(RUN_ENV) ./$$t || exit 1; \
9195
done
9296

97+
test_p3: $(P3_TESTS)
98+
@for t in $(P3_TESTS); do \
99+
echo "==> running $$t"; $(RUN_ENV) ./$$t || exit 1; \
100+
done
101+
93102
test: all
94103
@for t in $(ALL_TESTS); do \
95104
echo "==> running $$t"; $(RUN_ENV) ./$$t || exit 1; \
@@ -166,6 +175,12 @@ WRAP_FF_DPDKIF := -Wl,--wrap=rte_get_tsc_hz
166175
test_ff_dpdk_if: test_ff_dpdk_if.o $(LIB_OBJS_DIR)/ff_dpdk_if.o $(COMMON_DIR)/rte_stub.o
167176
$(CC) -o $@ $^ $(LDFLAGS_BASE) $(BASE_WRAPS) $(WRAP_FF_DPDKIF) $(DPDK_LIBS) -lrte_net_bond -Wl,-rpath=/usr/local/lib64 -lpthread -lcrypto -ldl -lm
168177

178+
# P3 #1 ff_dpdk_kni (FU-S4-KNI subset: ff_kni_enqueue ratelimit branches;
179+
# requires real DPDK EAL --no-huge for mempool + ring; if EAL init fails
180+
# at runtime, all 4 TC are marked skip().)
181+
test_ff_dpdk_kni: test_ff_dpdk_kni.o $(LIB_OBJS_DIR)/ff_dpdk_kni.o $(COMMON_DIR)/rte_stub.o
182+
$(CC) -o $@ $^ $(LDFLAGS_BASE) $(BASE_WRAPS) $(DPDK_LIBS) -lrte_net_bond -Wl,-rpath=/usr/local/lib64 -lpthread -lcrypto -ldl -lm
183+
169184
# ----- clean (NFR-U-7: must use workspace wrapper, no direct rm) -----
170185
clean:
171186
@find . -name '*.o' -type f -print 2>/dev/null | while read f; do \

tests/unit/test_ff_dpdk_if.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,105 @@ test_ff_get_tsc_ns_basic(void **state)
246246
assert_true(b >= a);
247247
}
248248

249+
/* ------------------------------------------------------------------------ */
250+
/* TC-U-P3-DPDKIF-08: ff_in_pcbladdr returns 0 when no callback registered */
251+
/* ------------------------------------------------------------------------ */
252+
#include <netinet/in.h> /* AF_INET */
253+
254+
static void
255+
test_ff_in_pcbladdr_no_callback(void **state)
256+
{
257+
(void)state;
258+
/* Reset to NULL via the public setter */
259+
ff_regist_pcblddr_fun(NULL);
260+
261+
int rv = ff_in_pcbladdr(AF_INET, NULL, 0, NULL);
262+
assert_int_equal(rv, 0);
263+
}
264+
265+
/* ------------------------------------------------------------------------ */
266+
/* TC-U-P3-DPDKIF-09: AF_INET dispatches to callback with family=AF_INET */
267+
/* ------------------------------------------------------------------------ */
268+
static struct {
269+
int invoked;
270+
uint16_t family_seen;
271+
void *faddr_seen;
272+
uint16_t fport_seen;
273+
void *laddr_seen;
274+
int ret_value;
275+
} g_pcblddr_capture;
276+
277+
static int
278+
capturing_pcblddr(uint16_t family, void *faddr, uint16_t fport, void *laddr)
279+
{
280+
g_pcblddr_capture.invoked++;
281+
g_pcblddr_capture.family_seen = family;
282+
g_pcblddr_capture.faddr_seen = faddr;
283+
g_pcblddr_capture.fport_seen = fport;
284+
g_pcblddr_capture.laddr_seen = laddr;
285+
return g_pcblddr_capture.ret_value;
286+
}
287+
288+
static void
289+
test_ff_in_pcbladdr_af_inet_dispatches(void **state)
290+
{
291+
(void)state;
292+
memset(&g_pcblddr_capture, 0, sizeof(g_pcblddr_capture));
293+
g_pcblddr_capture.ret_value = 7; /* arbitrary marker */
294+
ff_regist_pcblddr_fun(capturing_pcblddr);
295+
296+
int faddr = 0x12345678;
297+
int laddr = 0x9ABCDEF0;
298+
int rv = ff_in_pcbladdr(AF_INET, &faddr, 53, &laddr);
299+
300+
assert_int_equal(rv, 7); /* return value transparently */
301+
assert_int_equal(g_pcblddr_capture.invoked, 1);
302+
assert_int_equal((int)g_pcblddr_capture.family_seen, AF_INET);
303+
assert_ptr_equal(g_pcblddr_capture.faddr_seen, &faddr);
304+
assert_int_equal((int)g_pcblddr_capture.fport_seen, 53);
305+
assert_ptr_equal(g_pcblddr_capture.laddr_seen, &laddr);
306+
307+
ff_regist_pcblddr_fun(NULL); /* clean up */
308+
}
309+
310+
/* ------------------------------------------------------------------------ */
311+
/* TC-U-P3-DPDKIF-10: AF_INET6_FREEBSD (28) is remapped to AF_INET6_LINUX */
312+
/* (10) before dispatching; unknown family returns the host EADDRNOTAVAIL. */
313+
/* */
314+
/* IMPORTANT (DP-U-12 "代码为准"): ff_in_pcbladdr's else-branch returns the */
315+
/* POSIX errno macro `EADDRNOTAVAIL` (defined in <errno.h>, value=99 on */
316+
/* Linux), NOT F-Stack's `ff_EADDRNOTAVAIL` (49). The spec/plan referenced */
317+
/* the latter incorrectly; tests below use the actual Linux errno value. */
318+
/* ------------------------------------------------------------------------ */
319+
#define AF_INET6_FREEBSD_VAL 28 /* per ff_api.h L50 */
320+
#define AF_INET6_LINUX_VAL 10 /* per ff_api.h L48 */
321+
322+
#include <errno.h> /* host EADDRNOTAVAIL */
323+
324+
static void
325+
test_ff_in_pcbladdr_af_inet6_freebsd_to_linux_remap(void **state)
326+
{
327+
(void)state;
328+
memset(&g_pcblddr_capture, 0, sizeof(g_pcblddr_capture));
329+
g_pcblddr_capture.ret_value = 0;
330+
ff_regist_pcblddr_fun(capturing_pcblddr);
331+
332+
int rv = ff_in_pcbladdr(AF_INET6_FREEBSD_VAL, NULL, 0, NULL);
333+
assert_int_equal(rv, 0);
334+
assert_int_equal(g_pcblddr_capture.invoked, 1);
335+
/* Family must be remapped to AF_INET6_LINUX before reaching callback */
336+
assert_int_equal((int)g_pcblddr_capture.family_seen, AF_INET6_LINUX_VAL);
337+
338+
/* Reset capture and try unknown family -> EADDRNOTAVAIL (host=99 on Linux),
339+
* callback NOT called */
340+
memset(&g_pcblddr_capture, 0, sizeof(g_pcblddr_capture));
341+
rv = ff_in_pcbladdr(99 /* unknown */, NULL, 0, NULL);
342+
assert_int_equal(rv, EADDRNOTAVAIL); /* POSIX, =99 on Linux */
343+
assert_int_equal(g_pcblddr_capture.invoked, 0);
344+
345+
ff_regist_pcblddr_fun(NULL);
346+
}
347+
249348
/* ------------------------------------------------------------------------ */
250349
/* Main runner */
251350
/* ------------------------------------------------------------------------ */
@@ -260,6 +359,10 @@ main(void)
260359
cmocka_unit_test(test_ff_regist_packet_dispatcher_smoke),
261360
cmocka_unit_test(test_ff_regist_packet_dispatcher_context_smoke),
262361
cmocka_unit_test(test_ff_get_tsc_ns_basic),
362+
/* Stage-5 FU-S4-DPDK-IF-FULL: ff_in_pcbladdr branches */
363+
cmocka_unit_test(test_ff_in_pcbladdr_no_callback),
364+
cmocka_unit_test(test_ff_in_pcbladdr_af_inet_dispatches),
365+
cmocka_unit_test(test_ff_in_pcbladdr_af_inet6_freebsd_to_linux_remap),
263366
};
264367
return cmocka_run_group_tests(tests, NULL, NULL);
265368
}

0 commit comments

Comments
 (0)