feat(N34): 阶段3 net层收敛——单一reconciler+忙等统一+镜像降级+E-02收口
实施方案 docs/网络/N34-自愈审计/实施方案.md §5 项1/2/3/5(项4 U15受E6暂缓): - 3a 合并reconciler:net_listener_pump删除,与net_reconcile_tick合并为 单一100ms tick;判据读驱动状态缓存(唯一刷新点=net_poll每轮全量刷新, E2背书18.1us);去抖分级②=1/③④⑤=2/①=4轮(M3让位窗400ms保留)+冷却1s; 链路态订阅留痕(F-DRV-13);探针去抖删除(F-MS-9) - 3b 忙等统一(P2b):listen/connect open重试与close排空循环改 net_sock_reset_sync(驱动sock_reset:读空RX→CLOSE→排空事件→等 byte0=00H,内置LISTEN态二段CLOSE补发);close不再读清全局中断寄存器 (F-NET-7);net_poll每轮步进活跃复位状态机(驱动契约,防搁浅) - 3c 镜像降级:net_sock_state_t声明为本层会话投影,芯片事实源=驱动缓存 - E-02收口:新API net_drop_conn(拆会话保监听,QUARANTINE语义,幂等; 模拟器双端实现;timeSync 30s预算耗尽接入;主机单测TC-TS-027d) 定案:CH395F close无RST,对内核存活不close的对端停FIN_WAIT_2, 监听恢复受限于对端close(Trap 07补充),兜底=E13 keepalive/TIMEOUT 台架全绿(Code=211348 RW=1104 ZI=154232):@test PASS;[STACK] net 1116/3840;Trap22 :7003 50/50+:21三档各50/50;Trap23 RST10/10+FIN5/5; Trap25 n30 11/11;E-02双PASS;iec104 18/18;对时跨会话连续; ftp_regression 11/11;integrity 15/15 SHA;ci_local L0+L0.5全过。
This commit is contained in:
+34
-14
@@ -7,10 +7,18 @@
|
||||
全体消费者的队列消息停摆最长 30s;
|
||||
2. 2s 后从 PC 发起 FTP(:21) 连接,测 banner 到达时延 = 队列响应性:
|
||||
修复前 ≈ 25~30s(队头冻结),修复后 ≈ 数百 ms 内;
|
||||
3. 34s 时 30s 总预算应已耗尽:设备拆除该连接(修复版落
|
||||
"time_sync: no TIME packet in 30s, drop conn" 日志,旧版静默)、
|
||||
监听重建,:8888 应能再接受新连接;
|
||||
4. 新连接发完整 8 字节 TIME 包 → 设备应落 "wall clock updated"。
|
||||
3. 34s 时 30s 总预算应已耗尽:设备拆掉该会话(N34 阶段 3 net_drop_conn:
|
||||
FIN 关闭 + 本层收口 + 重监听),随后**本探针模拟守规矩对端**:
|
||||
close 自己的 socket;
|
||||
4. 芯片回 CLOSED(TC-NET-204 模式 A:TIME_WAIT 过渡 ~150ms)→ relisten,
|
||||
:8888 应能再接受新连接(3s 重试窗内);新连接发完整 8 字节 TIME 包 →
|
||||
设备应落 "wall clock updated"。
|
||||
|
||||
⚠ 定案口径(Trap 07 定案更正 2026-10-11 + 实验方案 E13 §5):CH395F close
|
||||
**无 RST 语义**。若对端内核存活(app 挂起但 socket 不关,内核自动 ACK FIN),
|
||||
芯片停在 FIN_WAIT_2、监听恢复受限于对端 close——探针第 3 步的 close 正是
|
||||
模拟"对端配合"这一可恢复边界;不配合场景的兜底是芯片 TIMEOUT/keepalive
|
||||
拆僵尸会话(E13 定案,30~90s)。
|
||||
|
||||
用法: python e02_probe.py <run-tag>
|
||||
退出码: 0 = 队列响应性 PASS;1 = FAIL;2 = 探针自身异常
|
||||
@@ -53,16 +61,32 @@ def main():
|
||||
% ("PASS" if queue_ok else "FAIL",
|
||||
("%.0f" % (dt * 1000)) if dt is not None else "n/a"))
|
||||
|
||||
# 3. 等 30s 总预算耗尽(设备应拆除挂起连接、重建监听)
|
||||
# 3. 等 30s 总预算耗尽(设备应拆会话:FIN + 本层收口 + 重监听)
|
||||
remain = 34.0 - (time.time() - t0)
|
||||
if remain > 0:
|
||||
time.sleep(remain)
|
||||
|
||||
# 4. 监听应已重建:新连接可接入,且正常对时路径工作
|
||||
# 3b. 模拟守规矩对端:设备已发 FIN(drop_conn),本端 close 配合拆链。
|
||||
# CH395F close 无 RST 语义(Trap 07 定案更正):不配合的内核存活对端
|
||||
# 会把芯片停在 FIN_WAIT_2,监听恢复受限于对端 close——不在本探针判据内。
|
||||
try:
|
||||
ts.close()
|
||||
log("hung client socket closed (cooperate with device FIN)")
|
||||
except OSError:
|
||||
pass # 设备已先拆连,本地 close 报 ECONNRESET 属预期
|
||||
|
||||
# 4. 监听应已重建(芯片 TIME_WAIT 过渡 ~150ms + relisten):3s 重试窗
|
||||
t2 = time.time()
|
||||
listener_ok = False
|
||||
try:
|
||||
ts2 = socket.create_connection((DEV, 8888), timeout=5)
|
||||
ts2 = None
|
||||
while time.time() - t2 < 3.0:
|
||||
try:
|
||||
ts2 = socket.create_connection((DEV, 8888), timeout=2)
|
||||
break
|
||||
except Exception as e:
|
||||
log("second time-sync conn retry: %r" % (e,))
|
||||
time.sleep(0.3)
|
||||
if ts2 is not None:
|
||||
dt2 = time.time() - t2
|
||||
epoch = int(time.time())
|
||||
log("new time-sync conn in %6.0f ms, sent full TIME packet (epoch=%d)"
|
||||
@@ -71,12 +95,8 @@ def main():
|
||||
time.sleep(1.5) # 留时间给设备处理并打日志
|
||||
ts2.close()
|
||||
listener_ok = True
|
||||
except Exception as e:
|
||||
log("second time-sync conn FAIL: %r" % (e,))
|
||||
try:
|
||||
ts.close()
|
||||
except OSError:
|
||||
pass # 设备已先拆连,本地 close 报 ECONNRESET 属预期
|
||||
else:
|
||||
log("second time-sync conn FAIL (3s window)")
|
||||
log("OVERALL: queue=%s listener=%s"
|
||||
% ("PASS" if queue_ok else "FAIL", "PASS" if listener_ok else "FAIL"))
|
||||
return 0 if (queue_ok and listener_ok) else 1
|
||||
|
||||
@@ -60,6 +60,7 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
int net_listen(int sockfd);
|
||||
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||||
int net_close(int sockfd);
|
||||
int net_drop_conn(int sockfd);
|
||||
int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms);
|
||||
uint32_t net_get_generation(void);
|
||||
uint16_t net_htons(uint16_t hostshort);
|
||||
|
||||
@@ -235,6 +235,18 @@ int net_close(int sockfd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- net_drop_conn(N34 阶段 3 E-02 收口):计数 + 记录 fd ---- */
|
||||
static int s_drop_calls;
|
||||
static int s_drop_socks[32];
|
||||
|
||||
int net_drop_conn(int sockfd) {
|
||||
if (s_drop_calls < 32) {
|
||||
s_drop_socks[s_drop_calls] = sockfd;
|
||||
}
|
||||
s_drop_calls++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t net_get_generation(void) {
|
||||
int i = s_gen_calls++;
|
||||
|
||||
@@ -351,6 +363,7 @@ static void fakes_reset(void) {
|
||||
s_accept_calls = 0;
|
||||
s_accept_seq_n = 0;
|
||||
s_close_calls = 0;
|
||||
s_drop_calls = 0;
|
||||
s_gen_seq_n = 0;
|
||||
s_gen_default = 1u;
|
||||
s_gen_calls = 0;
|
||||
@@ -518,6 +531,7 @@ static void tc_handle_conn(void) {
|
||||
CHECK((s_recv_calls == 1) && (s_recv_len_log[0] == 16), "TC-TS-020c 首次请求 16 字节");
|
||||
CHECK(s_recv_to_log[0] == 50U, "TC-TS-020d 单次等待片长 = 50ms");
|
||||
CHECK(s_close_calls == 0, "TC-TS-020e 处理完**不**关闭连接(N34 阶段1:close 交外层 conn!=ls 分支)");
|
||||
CHECK(s_drop_calls == 0, "TC-TS-020g 成功会话不拆(drop 只用于放弃路径)");
|
||||
CHECK(g_tstest_info_count == 1, "TC-TS-020f 留痕 wall clock updated");
|
||||
|
||||
/* 2) 分段送达:4 + 4 */
|
||||
@@ -591,6 +605,7 @@ static void tc_handle_conn(void) {
|
||||
CHECK(s_recv_calls == 1, "TC-TS-027 预算耗尽后不再读(只读 1 次)");
|
||||
CHECK(g_tstest_info_count == 1, "TC-TS-027b 留痕 no TIME packet in 30s, drop conn");
|
||||
CHECK(s_close_calls == 0, "TC-TS-027c 预算耗尽也不关闭连接");
|
||||
CHECK(s_drop_calls == 1, "TC-TS-027d 预算耗尽主动拆会话(N34 阶段 3 E-02 收口:net_drop_conn 拆连接保监听)");
|
||||
|
||||
/* 9) 剩余预算不足一片 */
|
||||
fakes_reset();
|
||||
|
||||
Reference in New Issue
Block a user