跳转至

W09 - MS5 验收收口:测试暴露的问题与修复

周期:2026-08-16 ~ 2026-08-22 分支:net-k3(2 个提交)

本周做了什么

QEMU 有界双向设备数据面(MS5)在这一周完成验收并归档。设备侧的两条数据通道——固定槽位、背压、完成账本、冲刷——主体在上周已经落地,这周做的是把验收真正收口:重做自动验证的记录方式,在模拟器里手工跑六种真实收发模式,并修掉了验证过程中暴露的几个问题。

其中两处是验证程序自身的问题(写出来的判定条件根本走不到、解析太宽松),一处是产品代码的真实缺陷(唤醒时机采样错位),都在测试证据面前被发现并修正。

自动验证记录重做

验证记录之前靠手工写命令和日志,评审连续两轮不过。这周改成两个配套工具:抓取工具用固定命令启动每项检查,逐条记录指令、退出码、日志路径和哈希;审计工具按清单逐项核对,缺记录、日志被改写、时间顺序错都判失败。自动检查 44/44 通过,审计通过。

测试中发现的问题与修复

1. "描述符满"的验证逻辑实际走不到

探针里判定描述符满的条件是"驱动返回的忙次数超过保持模式下的计数",测试跑起来发现这个差量条件永远不成立——声称验证的"描述符满→恢复"可能一直没真测到。

修复:改用守恒账本推导满状态——记录在途的包数,槽位容量和驱动容量都固定为 64,验证在保持模式下队列服务正好排空到 64 个在途包、释放后闭合,且从不触发那个假的"满"判定。为此新增一个带容量的模拟驱动。没有改动任何产品代码,问题出在验证程序。

2. 手工收发流程的时序边界不清

原实现一个函数同时负责监听客户端和收发数据,操作员很难掌控时机。拆成两个有限阶段:先监听(120 秒超时)等客户端注册,注册成功后开始短期交换;两端收发完成各自打印 DONE,收到对方的 ACK 才算确认。

3. DONE 消息解析过宽

原实现用固定 16 字符数组保存模式名,长名字被截断;用 strtoul 做前缀解析,会接受本应拒绝的错误格式。改为严格四字段解析:缺字段、多余尾巴、错误模式、溢出、负数、空计数全部拒绝,只有精确匹配才返回。

4. 自测自身的死循环

自测里有一个"第一次接收就超时"的用例,模拟 socket 不推进时钟,无条件超时后时钟又不动,导致死循环。修复:让模拟 socket 推进时钟,让绝对截止时间真正生效。

5. 生产缺陷:唤醒采样的时序错位

这是这周唯一动到产品代码的修复,在 crates/axnet/src/service.rs。队列服务每个轮次先采样"TX 槽是否已有待发帧",再做路由分发。当路由器在分发中消费了 ARP 回复、解析出邻居,会把之前悬着的第一帧冲刷进 TX 槽——但采样发生在分发之前,这次从空到非空的转换对队列任务不可见:沉睡的队列任务没有硬件完成事件可等,这条帧会一直躺在槽里。

修复:把采样移到轮次最开头(任何操作之前),保证路由过程中产生的帧也恰好发布一次队列唤醒;同时加两条测试——ARP 冲刷必须恰好唤醒一次,轮次开始时已 pending 的帧不得再次发布唤醒(防止唤醒风暴)。

模拟器里手工跑真实收发(六种模式)

为什么做:自动检查能证明代码行为,但"真机启动、真实收发"需要在能开网络端口的普通终端里跑。这一步只能手工,不由验证工具代替。

做法:宿主机起 HTTP 服务喂数据,模拟器里的客机走真实网络栈收发:

  1. 快照一致性
  2. 客机发包(只发不收)
  3. 双向收发
  4. 发包槽位满 → 恢复
  5. 描述符满 → 恢复
  6. 冲刷闭合

验证:六种模式全部以 PASS + 退出码 0 收尾,留下串口日志、抓包文件和产物清单作证据。首次跑某个模式的一次握手受操作时序影响未通过,重跑后通过。

收尾与归档

  • MS5 变更归档:12 轮评审迭代、27 项任务全部完成,最终评审通过(部分证据和兼容性项按你的明确授权豁免)。
  • 补了三份操作手册:双向数据面证据采集、模拟器内核网络分层诊断、网络测试总则更新。

提交记录

日期 提交 内容
8/17 2af394e6 自动验证记录与审计工具
8/19 518acb8f 测试问题修复、六模式模拟器验证、MS5 归档

下周

设备侧(队列、槽位、背压、冲刷、完成确认)已经收口,下一步让应用层"看得见"异步网络,分两步走(对应路线里的 MS6):

  1. 协议栈独立推进:现在协议栈的收发包推进依赖上层主动调用,没流量时上层一直在空转等待。这一步让协议栈自己跑一个后台任务,负责收包进入、发出去、定时维护(ARP 过期、重传等)三类工作,设备中断、软件事件、定时器都能唤醒它,空闲时睡觉。验收标准是:没流量时不轮询、持续流量下不饿死其他任务。

  2. 就绪状态桥接到 select/poll:现在应用想知道 socket 有没有数据只能问一次看一次。这一步把协议栈的唤醒信号接到系统的 poll/select 机制上,多个应用同时等各自的 socket 都能被正确唤醒。验收标准是:多个等待者、缓冲区溢出、连接关闭、出错这些情况下的 poll/select 结果和真实收发一致。

两步都在规划阶段,先做详细计划、写测试用例定义行为,再动手实现。

参考