feat(net): 服务器侧 KeepAlive 转正(§5.56,E11)+ Phase 11 重开回归

E11(d96113b)证据链:"链路在、对端静默"注入下生产参数 60/5/3 实测
判死 ≈30s → TIM_OUT → QUARANTINE → pump 重建;静默但存活对端不误杀。
handle_connect_event LISTENING 分支按手册规定位置开启;反汇编确认
编译器把两分支尾部合并(LISTENING 跳入含 keepalive+fire_event 的公共
尾部,hex 全片仅该分支偏移 1 行差异,Code 尺寸不变属填充巧合)。
Phase 11 重开时发现其拉入 32KB s_rx_buf 超产品 RAM 余量(L6406E 链接
失败)→ 改专用 64B 探针缓冲(本 Phase 仅 64B 探针读,门控注释已留
"勿加回"警示),套件恢复 0 错 0 警;TC-NET-1101 步骤同步死对端注入法
(禁用网卡;Windows 防火墙规则对已建立连接无效,E11 实证)。
验证:产品/套件双构建 0 错 0 警 + 反汇编确认调用落地;台架确认
(:7003 静默对端判死 + Phase 11 实跑)待设备冷启动断电重上电后补做。
This commit is contained in:
2026-10-13 09:25:06 +08:00
parent d96113bcc4
commit 13a4a40a14
6 changed files with 43 additions and 33 deletions
+18 -12
View File
@@ -43,8 +43,10 @@
* 即首次使用 s_rx_buf)。P1-9 修复:原声明位于文件后段(Phase 8 注释块
* 之后),phase6_run 使用先于声明 → ARMCC #20 identifier undefined,
* 全部 NET 层测试配置不可编译。声明条件按各 Phase 实际用缓冲精确门控:
* s_rx_buf —— Phase 6(Echo)/9(Select)/11(KeepAlive) 恒用,
* Phase 8(大文件) 非 SEND 方向用;
* s_rx_buf —— Phase 6(Echo)/9(Select) 恒用,
* Phase 8(大文件) 非 SEND 方向用,Phase 10(边界) 用;
* (Phase 11 只用 64B 探针读,2026-10-13 改专用小缓冲——
* 产品 RAM 余量放不下 32KB,勿再把 11 加回本门控)
* s_tx_buf —— Phase 8(大文件) 非 RECV 方向(填充发送窗口)及
* Phase 10(边界) 用。
* PHASE8_DIRECTION 由下方方向配置块定义(仅 ENABLE_PHASE8_TESTS 时);
@@ -66,8 +68,7 @@
#if defined(ENABLE_PHASE6_TESTS) || \
(defined(ENABLE_PHASE8_TESTS) && (PHASE8_DIRECTION != PHASE8_DIR_SEND)) || \
defined(ENABLE_PHASE9_TESTS) || defined(ENABLE_PHASE10_TESTS) || \
defined(ENABLE_PHASE11_TESTS)
defined(ENABLE_PHASE9_TESTS) || defined(ENABLE_PHASE10_TESTS)
static uint8_t s_rx_buf[TEST_BUF_SIZE];
#endif
/* s_tx_buf 仅 SEND/ECHO(及 Phase 10)需要;RECV 不发送,避免未使用变量警告 */
@@ -791,19 +792,24 @@ static void phase10_run(int32_t sockfd) {
/* ===================================================================
* Phase 11 — TCP KeepAlive 超时断开
*
* 测试目的:验证 CH395F 的 TCP KeepAlive 机制:
* 1. 连接空闲超过 idle 阈值(60s)后开始发送探测包
* 2. 探测无响应(默认 3 次 × 5s = 15s)后触发 TIMEOUT
* 3. Socket 自动关闭并回到 LISTEN
* 测试目的:验证 CH395F 的 TCP KeepAlive 机制(服务器侧开关已由 net 层
* 在 CONNECT 事件后按 §5.56 转正开启,E11 2026-10-13):
* 1. 连接空闲超过 IDLE(60s)后芯片开始发送探测包
* 2. CNT × INTVL(3 × 5s)无 ACK → SINT_STAT_TIM_OUT
* 3. 本层 QUARANTINE → pump 重建 → 回 LISTEN
*
* 入口条件:Socket 0 处于 ESTABLISHED,PC 连接后静置(不发数据)。
* 通过:KeepAlive 断开时间 ≥ 60s(从连接建立到 recv 返回 0 的间隔)。
* 失败:不到 60s 就断开(可能是其他原因导致)或 75s 后仍未断开。
* 入口条件:Socket 处于 ESTABLISHED 且对端为**死对端**——PC 连 8080 后
* 禁用网卡(存活对端会 ACK 探测、TIMEOUT 永不触发,本测试将
* 一直等待;防火墙规则对已建立连接无效,E11 实证)。
* 通过:从连接建立到 recv 返回 0 的间隔 ≥ 60s(IDLE 阈值)。
* 注:芯片定时语义与手册公式(75s)不完全一致,实测判死窗口见
* 实验方案 E11(对端失联后 ≈30s)。
* =================================================================== */
#ifdef ENABLE_PHASE11_TESTS
static int32_t s_phase11_armed = 0;
static uint32_t s_phase11_start = 0;
static uint8_t s_phase11_buf[64]; /* 专用小缓冲:不占 32KB s_rx_buf(RAM 余量) */
static void phase11_run(int32_t sockfd) {
/*
@@ -818,7 +824,7 @@ static void phase11_run(int32_t sockfd) {
return;
}
int32_t n = net_recv(sockfd, s_rx_buf, 64, NET_MSG_DONTWAIT);
int32_t n = net_recv(sockfd, s_phase11_buf, 64, NET_MSG_DONTWAIT);
if (n == 0) {
uint32_t elapsed = HAL_GetTick() - s_phase11_start;
TEST_CHECK(elapsed >= 60000,