7efa58d9a1
分两段(用户裁定 2026-11-02):先做地址迁移,再把同类字面量收敛成
单一真源,以后再改地址只动一处。
一、IP 迁移 192.168.1.100 → 192.168.31.100(gw 同步 → .31.1)
- 工厂默认:Drivers/BSP/NETCFG/net_cfg.c 的 NET_CFG_DEF_IP/_GW
- 注释/文档示例、主机与板级测试、台架 py 脚本、两份 sim_config.ini
- 字节序教学点同步换算 hex:0x6401A8C0 → 0x641FA8C0(内存
C0 A8 1F 64),旧版示例引文与历史 Trap 记录按冻结纪律不动
- UI 黄金基准:网口设置 4 态 + shot_info 共 5 张 .bin 由
check_content_pages.py --update 重刷(渲染值 IP 变了,属预期变更)
- 保留判定:客户点表引用(IEC104/继电保护规划)、芯片手册摘录、
日期冻结的变更记录行、已退役台架档案 MDK-ARM/retracted_bench_*
二、单一真源收口(A+B+C+D,用户批准全做)
- 新建 test/host/bench_defaults.py:台架 py 默认值唯一定义点
(DEVICE_IP/DEVICE_GW/PC_IP/NET_BCAST),22 个脚本改为引用;
MDK-ARM 两探针与 scripts/board_ui_nav.py 经 sys.path shim 引入
- test/board/net_test_task.h 新增 TEST_PC_PEER_IP,板测三处
PHASE*_REMOTE_IP 改引该宏(保留 -D 覆盖);Phase1 断言改
memcmp 数组比较,数组各只出现一次
- simulator/tests/check_content_pages.py 从 net_cfg.c 正则解析
NET_CFG_DEF_* 推导期望值(解析失败即报错、不静默兜底),
脚本内台架 IP 字面量清零
- 装饰性注释去具体值(net_cfg.h/net_socket.h/net_socket.c/
net_socket_sim.c);字节序教学 hex 对刻意保留为唯一写值点
- 刻意不动:主机单测夹具 IP(逐文件钉住的任意值是正确测试
实践)、文档正文 IP(那是文档内容本身)
顺带:scripts/gen_task_table.py 规范串清掉「,B5」——编号清退提交
72b4b094 改了受管区没重跑生成器,task-table 门禁因此一直红
验证:产品 @build 0/0;CH395F 套件开关构建 0/0 后还原产品态;
6 套主机单测 rc=0;content_pages(含宏推导路径)/菜单 8 态/
推流位比对全 PASS;bom-drift 99 无漂移;doc-links/coding-standard/
cppcheck 绿;py_compile 23 文件 + --help 冒烟(含 shim 绝对路径)
161 lines
5.6 KiB
Python
161 lines
5.6 KiB
Python
# relisten 沉降段原语化受阻:芯片级复用时序台架主机端(与 test/board/ch395f_reuse_bench.c 共用变体表)
|
||
# 用法: python ch395f_reuse_host.py [--host IP] [--cycles N] [--mode legacy|e4]
|
||
# legacy: 按 idx 轮转连接 5000+idx 端口,记录收发结果与时刻。
|
||
# e4: E4 sock_reset A/B/C 矩阵配套(2026-10-13):每轮两次连接——
|
||
# ①污染:连上发 3000B 后 RST(SO_LINGER 0,TRAP-NET-18 中止形态);
|
||
# ②载荷:立即重连发 4096B 图案(pat[i]=(seed+i)&0xFF, seed=(rg*97+13)&0xFF)后 FIN。
|
||
# 端口 5100+rg,rg=0..(3*rounds-1),变体顺序 A/B/C(与固件 bench 表一致)。
|
||
import argparse
|
||
import socket
|
||
import struct
|
||
import sys
|
||
import time
|
||
|
||
import bench_defaults # 台架连接默认值单一真源
|
||
|
||
# {idx: (tx_len, close_mode)} 与固件表一致
|
||
VARS = {
|
||
0: (100, 0), # 0ms control
|
||
1: (100, 0), # 300ms control
|
||
2: (2000, 0), # 2KB control
|
||
3: (100, 0), # 0ms + ghost-wait fix
|
||
4: (100, 0), # 300ms + ghost-wait fix
|
||
5: (2000, 0), # 2KB + ghost-wait fix
|
||
}
|
||
|
||
|
||
def ts():
|
||
return time.strftime("%H:%M:%S") + ".%03d" % (int(time.time() * 1000) % 1000)
|
||
|
||
|
||
def run_round(host, idx, tx_len, close_mode):
|
||
port = 5000 + idx
|
||
# 等端口监听(芯片还没 open 时连接被拒,重试)
|
||
s = None
|
||
t0 = time.time()
|
||
while time.time() - t0 < 12.0:
|
||
try:
|
||
s = socket.create_connection((host, port), timeout=5)
|
||
break
|
||
except OSError:
|
||
time.sleep(0.2)
|
||
if s is None:
|
||
print("%s r%u CONNECT timeout" % (ts(), idx))
|
||
return False
|
||
|
||
ok = True
|
||
try:
|
||
s.settimeout(5)
|
||
got = 0
|
||
while got < tx_len:
|
||
chunk = s.recv(min(1024, tx_len - got))
|
||
if not chunk:
|
||
break
|
||
got += len(chunk)
|
||
note = ""
|
||
if got != tx_len:
|
||
note = " <<<< SWALLOWED (want %d)" % tx_len
|
||
ok = False
|
||
if close_mode == 1:
|
||
# 等芯片 FIN(mode1 芯片先关)
|
||
try:
|
||
fin = s.recv(1)
|
||
if fin:
|
||
note += " unexpected data after tx: %r" % fin
|
||
except socket.timeout:
|
||
note += " <<<< no FIN from chip (mode1)"
|
||
ok = False
|
||
print("%s r%u connected got=%d/%d%s" % (ts(), idx, got, tx_len, note))
|
||
except socket.timeout:
|
||
print("%s r%u recv timeout <<<< STALL" % (ts(), idx))
|
||
ok = False
|
||
except OSError as e:
|
||
print("%s r%u sock error %r" % (ts(), idx, e))
|
||
ok = False
|
||
finally:
|
||
s.close() # 主机关闭(mode0/2 主机先关)
|
||
return ok
|
||
|
||
|
||
def connect_retry(host, port, budget_s):
|
||
"""connect with retry until budget_s elapses; None on give-up"""
|
||
t0 = time.time()
|
||
while time.time() - t0 < budget_s:
|
||
try:
|
||
return socket.create_connection((host, port), timeout=5)
|
||
except OSError:
|
||
time.sleep(0.2)
|
||
return None
|
||
|
||
|
||
def e4_round(host, rg, rounds_per_variant, first_budget):
|
||
"""one E4 round: contaminate (send 3000B then RST) + payload (4096B pattern then FIN)"""
|
||
port = 5100 + rg
|
||
seed = (rg * 97 + 13) & 0xFF
|
||
budget = first_budget if rg == 0 else 30
|
||
s = connect_retry(host, port, budget)
|
||
if s is None:
|
||
print("%s E4 r%2d port%5d <<<< contam CONNECT timeout" % (ts(), rg, port))
|
||
return False
|
||
try:
|
||
s.sendall(b"\x33" * 3000)
|
||
except OSError as e:
|
||
print("%s E4 r%2d contam send err %r" % (ts(), rg, e))
|
||
try:
|
||
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack("ii", 1, 0))
|
||
except OSError:
|
||
pass
|
||
s.close() # RST: abort mid-session like ftp_abort_probe (TRAP-NET-18 form)
|
||
time.sleep(0.05)
|
||
|
||
s = connect_retry(host, port, 20)
|
||
if s is None:
|
||
print("%s E4 r%2d port%5d <<<< payload CONNECT timeout" % (ts(), rg, port))
|
||
return False
|
||
payload = bytes(((seed + i) & 0xFF) for i in range(4096))
|
||
try:
|
||
s.sendall(payload)
|
||
except OSError as e:
|
||
print("%s E4 r%2d payload send err %r" % (ts(), rg, e))
|
||
s.close()
|
||
return False
|
||
s.close() # FIN: full payload delivered, chip drains
|
||
print("%s E4 r%2d var=%s port%5d contam+payload sent (seed=%02X)"
|
||
% (ts(), rg, "ABC"[rg // rounds_per_variant], port, seed))
|
||
return True
|
||
|
||
|
||
def main():
|
||
ap = argparse.ArgumentParser()
|
||
ap.add_argument("--host", default=bench_defaults.DEVICE_IP)
|
||
ap.add_argument("--cycles", type=int, default=3)
|
||
ap.add_argument("--mode", choices=["legacy", "e4"], default="legacy")
|
||
ap.add_argument("--rounds", type=int, default=10, help="e4: rounds per variant")
|
||
ap.add_argument("--first-budget", type=int, default=300,
|
||
help="e4: connect budget for the first round (bench runs E2/E3 first)")
|
||
args = ap.parse_args()
|
||
|
||
if args.mode == "e4":
|
||
fails = []
|
||
total = 3 * args.rounds
|
||
for rg in range(total):
|
||
if not e4_round(args.host, rg, args.rounds, args.first_budget):
|
||
fails.append(rg)
|
||
print("E4 RESULT: %d/%d host-side ok, failures %s" % (total - len(fails), total, fails))
|
||
return 1 if fails else 0
|
||
|
||
fails = []
|
||
for c in range(args.cycles):
|
||
for idx in sorted(VARS):
|
||
tx_len, mode = VARS[idx]
|
||
print("%s === cycle%u r%u (tx=%d mode=%d) ===" % (ts(), c, idx, tx_len, mode))
|
||
if not run_round(args.host, idx, tx_len, mode):
|
||
fails.append((c, idx))
|
||
time.sleep(0.3)
|
||
print("RESULT: %d failures %s" % (len(fails), fails))
|
||
return 1 if fails else 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|