结论:网络状态是一条「慢速快照 → 分类 → 费用策略」的链路:hardwared 约每 10 秒采集一次网络/调制解调器/USB 快照,分类函数从 /proc/net/route、wpa_supplicant 与 modem 状态文件 推导类型、强度与计费位,再由 uploader、Athena 与 updated 消费。关键边界有三处:网络接口切换本身不是立即刷新触发器;蜂窝缺 signal_quality 会落入 poor 而非 unknown;未知 Wi-Fi 计费可能被当成免费网络,不能作为上传费用授权的保守依据。本文未连接 Wi-Fi、蜂窝网络或运营商账单。
来源与关键函数
类型判断从 get_default_route_iface() 开始:它解析 /proc/net/route,只取目的地为 00000000 且带网关标志的条目,以 (metric, 接口名) 元组最小者为接口,不单独要求 UP 标志。默认路由名匹配 wlan* 即认作 Wi-Fi、eth* 即认作以太网,否则读取 modem 的 connected 与制式,未知返回 none。SSID 与 RSSI 来自 wpa_supplicant_cmd():它用抽象 UNIX datagram socket 发命令,跳过以尖括号开头的事件消息,收到 FAIL 前缀即返回空结果,超时异常向调用方传播。
| 入口 | 实现语义 |
|---|---|
wpa_supplicant_cmd() |
抽象 UNIX datagram socket;跳过事件消息,FAIL 返回空字典,超时异常传播 |
get_default_route_iface() |
取默认目的地且带网关标志的条目,按 (metric, 接口名) 最小者;不要求 UP 标志 |
get_network_type() |
wlan*/eth* 优先;否则读 modem connected 与制式,未知返回 none |
get_modem_state() |
文件缺失或 JSON 语法错误返回 {};权限异常透传;合法 JSON 非对象不检查形状 |
parse_strength() / get_network_strength() |
四档阈值分类;Wi-Fi 用 RSSI,蜂窝用 signal_quality,以太网直接 great |
get_network_metered() |
蜂窝取 GsmMetered;Wi-Fi 按 SSID 匹配 NetworkManager keyfile 的 metered,无明确值回退基类 |
hw_state_thread() |
约每 10 秒或 USB 拓扑变化构造快照;容量 1,队列满丢弃新状态 |
hardware_thread() |
复用最后成功快照发布 deviceState.network*,并把计费位写入持久 NetworkMetered |
路由、信号与计费的精确回退
网络类型先按 /proc/net/route 的最低 metric 默认路由接口名判断;同 metric 时按接口名字典序选取,路由行只要求默认目的地和网关标志,不检查 UP 位。格式错误的行会让解析函数抛异常,get_network_type() 则吞掉它并尝试 modem,不会跳过坏行继续比较其余路由。若 modem 虽连接但制式不在 nr/lte/utran/umts/gsm 表内,仍返回 none。
强度方面,get_network_strength() 对以太网固定给 great,并非链路质量实测。Wi-Fi 通过 wpa_supplicant 的 SIGNAL_POLL 读 RSSI,只有大于 -100 且小于等于 0 的 dBm 才映射为 120 + clamp(dBm, -100, -20),再按四档阈值分类;恰好 -100 dBm、缺 RSSI、非法值或 socket 异常保持 unknown。蜂窝缺 signal_quality 时默认数值 0,会进入 poor,不是 unknown;读取异常则因宽泛异常捕获返回 unknown。信号质量读取与 modem 网络分类仍不是一次原子快照。
| 场景 | 结果 | 边界说明 |
|---|---|---|
| 以太网强度 | great |
固定值,非链路质量实测 |
| Wi-Fi RSSI 有效 | 120 + clamp(dBm, -100, -20) 后四档 |
仅当 dBm 大于 -100 且小于等于 0 |
| 恰好 -100 dBm / 缺 RSSI / 非法值 | unknown |
socket 异常同样保持 unknown |
蜂窝缺 signal_quality |
poor |
默认数值 0,不是 unknown |
| 蜂窝读取异常 | unknown |
由强度函数的宽泛异常捕获返回 |
get_modem_state() 只把文件不存在及 JSON 语法错误转为 {},权限错误会向调用方传播;它不验证 JSON 顶层必须为对象——合法数组会原样返回,get_network_type() 在需要 modem 回退时访问 .get() 可抛 AttributeError,而 get_network_strength() 会捕获异常并返回 unknown。这是控制流差异,不能据此断言真实 modem 写入了这种文件。
计费方面,蜂窝读取布尔参数 GsmMetered(源码默认真)。Wi-Fi 先读 wpa 的 STATUS SSID,再尝试把其转义形式转换为 NetworkManager keyfile 的文本或 byte;byte; 编码,在运行态与持久目录搜索配置。首个匹配 SSID 的配置若有 metered=1/2 分别返回真/假;若为默认或未知值,会跳出搜索并回退基类,后续同名配置不再检查。SSID 缺失、读取或解析失败也回退基类,而基类对 Wi-Fi、以太网和 none 返回非计费。因此「未知 Wi-Fi 计费」在此路径可能被当成免费网络,不能作为上传费用授权的保守依据。
从慢速快照到上传决策
hw_state_thread() 把类型、网络信息、强度、计费位分次调用取值,采集异常只记录、不发布该次快照。约 10 秒的采样周期可被 USB 拓扑变化提前触发,但网络接口切换本身不是立即刷新触发器;队列满时新快照会被丢弃。主线程沿用最后一次快照并以较高频率重复发布 deviceState,其消息 logMonoTime 不能代替这些网络字段的实际采样年龄。
uploader.main() 消费 deviceState.networkType/networkMetered,Athena.upload_handler() 为禁止蜂窝的任务检查计费位,updated 则读 hardwared 写入的持久 NetworkMetered 决定自动拉取节奏。三者消费的是分类/配置状态,不是计费账单、当前传输 socket 的实际路由或全链路一致快照,状态切换窗口须靠传输层重新核验。
自研硬件与插件接口
网络插件至少输出 link_type、default_route、connectivity、metering 四个独立字段,并携带接口 ID、来源、采样单调时间、有效位和原因。metering=unknown 应由宿主费用策略保守处理,不应默认为免费;上传器还需在每次开始与传输过程中按实际出口接口和账单策略复核。蜂窝 eSIM/SIM 身份属于敏感信息,遥测与日志插件不应默认共享 ICCID/IMEI。
验证层面,探针只覆盖隔离控制流;台架或隔离网络测试仍应覆盖双默认路由 metric 切换、Wi-Fi RSSI 缺失、SSID 转义、真实配置读取、蜂窝 GsmMetered 切换、慢快线程交错和队列满,并同时观察 deviceState、NetworkMetered、uploader/Athena/updated 决策与真实出站接口。
常见问题
蜂窝信号缺 signal_quality 时为什么不是 unknown?
因为源文档说明默认数值为 0,会进入 poor,不是 unknown;只有读取异常才因强度函数的宽泛异常捕获返回 unknown。这一差异在费用与上传策略里很关键,因为 poor 与 unknown 的保守程度不同。
未知 Wi-Fi 的计费状态会被当成什么?
可能被当成免费网络。源文档指出:首个匹配 SSID 的配置若为默认或未知值,会跳出搜索并回退基类,而基类对 Wi-Fi、以太网和 none 返回非计费。因此 metering=unknown 应由宿主费用策略保守处理,不能作为上传费用授权的保守依据。
网络接口切换会不会立刻刷新状态?
不会。约 10 秒的采样周期可被 USB 拓扑变化提前触发,但源文档明确网络接口切换本身不是立即刷新触发器,且队列满时新快照会被丢弃;主线程会沿用最后一次快照重复发布,其消息时间不能代表网络字段的实际采样年龄。
deviceState 的 logMonoTime 能当网络状态的采样时间吗?
不能。主线程沿用最后一次快照并以较高频率重复发布 deviceState,其消息 logMonoTime 不能代替这些网络字段的实际采样年龄。网络插件应显式携带采样单调时间与有效位。
延伸阅读
- 网络设置与 eSIM —— 承接本文蜂窝状态、制式判定与敏感身份信息的边界。
- modem 的 PPP、路由与 DNS 归属契约 —— 与本文
/proc/net/route与 modem 回退直接衔接。 - Athena 上传队列的持久化与重试 —— 解释计费位如何进入上传决策。
- 车载信号为什么会说谎:TTL、源时间与 500 ms 新鲜度阈值 —— 与本文「快照年龄不等于消息时间」互为对照。
参考资料
- 项目 02 ——
openpilot-research/COMMA_NETWORK_ROUTE_SIGNAL_METERING_SNAPSHOT_DEEP_DIVE.md(取用了网络分类、强度与计费回退、慢速快照与上传决策边界及插件接口要求)。 - 项目 02 ——
openpilot-research/ATHENA_DEVICE_NETWORK_METADATA_RPC_DEEP_DIVE.md(仅用于确认设备网络元数据接口的上下文)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复