Repository navigation
[BUG] USB 枚举路径漂移导致生成重复接口 3_1_2,并持续刷屏 "sim card is ready" #280
Copy link
Copy link
Open
Labels
bugSomething isn't workingSomething isn't working
Description
描述问题
型号:MangoPi M28C
目标平台:rockchip/armv8
固件版本:LEDE R26.02.20 / LuCI openwrt-23.05 branch git-26.249.11976-dd742f5
安装方式:自行编译
内核版本:6.12.80
Qmodem版本:qmodem - 3.4.0_rc3-104
调制解调器名称:FM650-CN
制造商:Fibocom Wireless Inc.
AT 端口:/dev/ttyUSB0
正常接口:4_1_2,物理路径 /sys/bus/usb/devices/4-1.2/
异常接口:3_1_2
QModem 原本正常使用 4_1_2 接口拨号,运行约两天后,网络配置中额外出现了 3_1_2 接口。
4_1_2 可以正常拨号并获得 IP:10.74.127.106。
但 3_1_2 无法正常拨号,并且日志持续每 5 秒左右刷屏:
[2026-09-23 12:23:55] modem_dial:info sim card is ready
[2026-09-23 12:24:00] modem_dial:info sim card is ready
[2026-09-23 12:24:05] modem_dial:info sim card is ready
[2026-09-23 12:24:11] modem_dial:info sim card is ready
...
疑似 USB 枚举路径发生漂移后,QModem 将同一个物理模组识别成了新的设备,从而创建了重复接口 3_1_2,但没有正确清理或去重。
复现方法
Steps to Reproduce
- 正常配置并启用 QModem,接口为 4_1_2
- 使用一段时间,约两天。
- 期间发生过重启、断电重新启动
- 之后 QModem 网络配置中多出 3_1_2
- 3_1_2 持续打印 sim card is ready,无法正常拨号
期望行为
描述正常情况下应该是什么行为
同一个物理模组不应因为 USB 路径变化而生成重复接口
自动探测失败时不应无限刷屏日志。
3_1_2 这种异常接口不应反复尝试拨号
日志信息
异常接口 3_1_2 日志片段:
[2026-09-23 12:23:55] modem_dial:info sim card is ready
[2026-09-23 12:24:00] modem_dial:info sim card is ready
[2026-09-23 12:24:05] modem_dial:info sim card is ready
[2026-09-23 12:24:11] modem_dial:info sim card is ready
...
正常接口 4_1_2 日志片段:
[2026-04-04 06:32:16] modem_dial:modem_path=/sys/bus/usb/devices/4-1.2/,driver=ecm,interface=4_1_2,at_port=/dev/ttyUSB0,using_sim_slot:1,dns_list:,bridge_enabled:0,bridge_ports:,bridge_management_ip:
[2026-04-04 06:32:21] modem_dial:info sim card is miss
[2026-04-04 14:32:26] modem_dial:info sim card is miss
[2026-04-04 14:32:32] modem_dial:info sim card is miss
[2026-04-04 14:32:37] modem_dial:info sim card is miss
[2026-04-04 14:32:42] modem_dial:info sim card is ready
[2026-04-04 14:32:42] modem_dial:create interface 4_1_2 with proto dhcp and metric 11
[2026-04-04 14:32:42] modem_dial:create interface 4_1_2v6 with proto dhcpv6 and metric 11
[2026-04-04 14:32:42] modem_dial:set interface 4_1_2 to usb0
[2026-04-04 14:32:43] modem_dial:network reload
[2026-04-04 14:32:43] modem_dial:firewall reload
[2026-04-04 14:32:43] modem_dial:dialing /sys/bus/usb/devices/4-1.2/ driver ecm
[2026-04-04 14:32:43] modem_dial:dialing: vendor:fibocom; platform:unisoc; driver:ecm; apn:; command:AT+GTRNDIS=1,1 pdp_index:1
[2026-04-04 14:32:43] modem_dial:dial_cmd: AT+GTRNDIS=1,1; cgdcont_cmd: AT+CGDCONT=1,"IPV4V6"; ppp_auth_cmd:
[2026-09-23 12:51:04] modem_dial:ip changed from , to ,10.251.229.7
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
FUjr commentedon Sep 24, 2026
关于重复接口
3_1_2的修复(可测试分支)感谢反馈。根因已定位并实现了修复,欢迎帮忙实机验证。
根因:
modem_scand把 UCI 段名直接绑定到 sysfs 槽位名(4-1.2→4_1_2),既没有记录「这个段属于哪个物理模组」,也不会回收已经失效的旧段。模组换端口重新枚举后就会多出一个段;而一个网卡(usb0)只能属于一条 sysfs 路径,旧段永远等不到网卡,于是modem_dial.sh的 5 秒轮询就一直刷sim card is ready。修复内容(分支
fix/modem-scand-device-dedup-280,commit6fe6851):usb:<vid>:<pid>@<物理端口>加设备序列号(0123456789ABCDEF之类的厂商占位串会被拒绝),PCIe 用pcie:<slot>;alias/apn/pincode/metric/enable_dial全部保留,并把state重新置为enabled(否则重插后不会拨号);如何把 feeds 切到这个分支
把
feeds.conf.default里的改成
然后:
产物在
bin/packages/<arch>/qmodem/modem_scan-*.ipk(apk 系统是*.apk),传到设备后:opkg install --force-reinstall /tmp/modem_scan-*.ipk /etc/init.d/qmodem_network restart验证方法
预期:只保留一个 modem-device 段,
path指向当前端口,alias/apn不变,重复段被停掉,之后不再刷sim card is ready。已知限制(请知悉)
3_1_2是旧版本创建的,没有scan_id/scan_serial。新代码无法证明它是重复段,因此只会把它停用(state=disabled),不会自动删除。如果uci show qmodem.3_1_2里的network仍指向usb0,停用会自动生效;否则请在 LuCI 里手动删掉这一个段即可,删除后不会再产生新的。application/qmodem/tests/test_modem_scan_device_dedup.sh,46 条断言,CI 的 Vendor fixture tests 已通过),尚未在真机上验证,所以非常需要你的实机反馈。/,而仓库的 SDK 自动编译工作流用的是branches: ['*'](*不匹配/),因此不会为这个分支产出固件包,需要按上面的步骤本地编译。modem_dial.sh的 5 秒轮询没有退避),本次没有一并改动,以免和正在进行的 PR 冲突。如果验证有问题,请把
logread | grep qmodem和uci show qmodem贴出来,我继续跟进。sassalana commentedon Sep 24, 2026
感谢作者的修复和详细指导
我已经编译并安装了
modem_scan_3.4.0_rc3-1_aarch64_generic.ipk。当前进展
3_1_2已清理,sim card is ready刷屏已停止。我的模组是 PCIe 接口但走 USB 线路,主板只有一个 PCIe 插槽,无法物理拔插换 USB 口。因此我准备通过日常使用来继续尝试触发USB 路径漂移
再次感谢!有结果我会及时反馈。
sassalana commentedon Sep 24, 2026
再次感谢作者的修复!有一个非常好的测试结果:
我把模组从 ECM 拨号模式切换到 NCM 模式,这正好触发了一次 USB 路径漂移:
/sys/bus/usb/devices/4-1.2//sys/bus/usb/devices/2-1.2/usb:2cb7:0a04@4-1.2usb:2cb7:0a05@2-1.2MD6JQY007ZMD6JQY007Z结果:
scan_serial正确识别为同一物理模组。4_1_2,sim card is ready刷屏没有复现。10.41.3.161。一些补充说明:
这次是主动切换拨号模式触发的路径变化,不是自然漂移,我会继续观察几天确认自然环境下是否也会正常。
主板上似乎只有 4-1.2 是高速 USB,切换到 NCM 后路径变成了 2-1.2,可能是低速端口,这或许会影响网络性能
切换过程中出现了 6 次 sim card is miss 的轮询(间隔 5 秒),最终恢复,期待后续修复。
切换后的拨号日志:
从结果看,修复逻辑在真机上验证通过了。感谢!
FUjr commentedon Sep 25, 2026
太好了,感谢实机验证 🙏 这个结果很有价值——它同时验证了序列号匹配这条路径确实生效(
pid从0a04变成0a05、端口从4-1.2变成2-1.2,仍然被认成同一个模组,段名保持4_1_2,没有产生第二个段)。你的日志暴露了一个我还漏掉的场景,已修复
你这次是 ECM → NCM,也就是同一个槽位重新枚举,所以段名恰好还是
4_1_2,没有触发那个漏洞。但如果是同一个模组换到另一个端口(
4_1_2→3_1_2),会走另一条分支,而那条分支里我犯了个错:这个跳过本意是「不要删掉马上要重写的那一段」,但段名撞车时它会把真正的持有者跳过:老段
4_1_2里带着scan_id/scan_serial(它就是同一模组),代码却因为它叫4_1_2而不回收它,然后在3_1_2上又建一个新段——正好又变成重复段。现在改成:只有「就是本次正在写入的那一段」才跳过;名字被别的槽位占用时,带同一身份的旧段照常回收。 同时补了一条保护——如果某个段记录的设备此刻仍然存在于别的路径,那它就不是残留,绝不回收。
需要你再验证一次
因为这是你报告里最接近原始场景(
3_1_2那种漂移)的路径,麻烦把 feeds 分支重新拉一下(同一个分支名,新 commit8f48aa9):./scripts/feeds update qmodem git -C feeds/qmodem log --oneline -1 # 应显示 8f48aa9 make package/feeds/qmodem/modem_scan/compile V=s然后再用 ECM/NCM 切换一次(这次段名会保持
4_1_2,只是确认没有回归),并且如果条件允许,把模组换到主板上另一个 USB/PCIe 口——那才是原始 issue 的场景。切换后看:关于你提到的另外两点
1.
sim card is miss轮询 6 次(约 30 秒)这个属于探测阶段的正常重试,不是 bug:
dial()在拨号前要等 SIM 就绪和网卡出现,超时后每 5 秒重试一次。ECM→NCM 切换时模组要重新初始化 USB 配置,30 秒属于合理范围。真正的问题是 issue 里说的无限刷屏——那需要「准备阶段永远无法满足」才会发生(比如旧代码那种幽灵段,网卡被别的段占着)。现在段不会再重复,这条路径已经堵住了。
另外提醒一句:拨号日志(
/var/run/qmodem/<段名>_dir/dial_log)是超过 300 行才清空,logread里的记录不受这个限制。如果你看到logread里持续刷同一条,那才是需要处理的;dial_log本身不会无限增长。2. NCM 后路径变成
2-1.2、担心低速端口影响网速路径编号(
2-1.2vs4-1.2)是 USB 控制器/总线编号,不是速率等级——它取决于模组以哪个 USB 配置枚举、挂在哪个 root hub 下,不代表链路变慢了。真正决定速率的是协商出来的 USB 速度,可以直接看:如果 NCM 下
speed仍是480(甚至5000),那就没有性能损失;如果掉到12/1.5,才需要担心。方便的话把这两个值和lsusb -t的输出贴一下,我帮你看。当前分支状态
fix/modem-scand-device-dedup-280→8f48aa9(在6fe6851之上加了这个修复)感谢配合,等你换端口的结果。
sassalana commentedon Sep 26, 2026
太棒了,我成功通过拔掉天线完美复现了路径从 4-1.2 变成 3-1.2 的场景,并且验证了你的
8f48aa9补丁完美生效!拔掉天线后,模组的网络模式从
NR5G-SA Mode变为了FDD LTE并经历了重启短暂的断电重新枚举,USB 控制器编号发生变动,路径发生了漂移。以下是抓取的完整数据:1. 模组段状态(只保留了一个段,没有产生重复)
2.物理身份与路径(路径变了,但 scan_serial 保留,APN 保留)
3.迁移日志(明确打印了 migrate modem,没有触发回收残留段)
4. 拨号日志(没有刷屏,自动重建并成功拨号)
5. 速度验证(未降速,依然是 5000M)
6. 重启后的再次漂移验证(路径变回 4-1.2)
为了进一步确认稳定性,我重启了一次路由器,发现 USB 枚举具有随机性,路径又从
3-1.2漂移回了4-1.2。以下是重启后的拨号日志,依然没有产生重复段,且自动拨号成功:结论:新补丁成功处理了跨端口漂移(无论
4-1.2还是3-1.2),旧段被正确迁移到新槽位,配置完整保留,没有产生重复段,也没有出现刷屏。由于xhci-hcd在枚举时随机分配了总线号,路径会随机变化,但速度始终保持在 5000M 高速。非常感谢作者的修复!这个困扰我很久的接口问题终于彻底解决了!Medvedolog commentedon Oct 22, 2026
Hi @FUjr, thanks for the fix on fix/modem-scand-device-dedup-280.
We hit the same bug on an Orange Pi Zero 3 (OpenWrt 25.12, several USB modems: Fibocom FM350, Foxconn T99W175, Dell DW5821e). This board renumbers the USB buses on reboot, so the same FM350 appeared as 1-1.3, 3-1.3 and 6-1.3 on different boots. QModem kept a section for each slot name (1_1_3, 3_1_3, 6_1_3), and each one brought its own set of network interfaces. What followed:
An old section stayed enabled with the AT port of an earlier boot. After renumbering, that tty belonged to another modem: 3_1_3 kept at_port /dev/ttyUSB5 while the FM350 had come back as cdc_acm (ttyACM0-2), and ttyUSB5 was now the T99's (3-1.4:1.1). QModem then sent its AT commands to the wrong modem (tom_modem ... AT+QSIMDET? every minute), and tom_modem got stuck in D state.
The leftover interfaces were brought up by netifd on the live netdev, and 6_1_3v6 looped (125 times in one log).
To be fair: we run with block_auto_probe=1, so _try_device and the hotplug remove handler, which would disable a section whose path is gone, are skipped on our side. But renumbering on reboot makes duplicates anyway, which is the case your fix handles with the vid:pid + serial identity. For now we remove the leftover sections downstream ourselves, and a proper fix in QModem would be much better.
@sassalana confirmed 8f48aa9 on hardware on 2026-09-26: after drifting from 4-1.2 to 3-1.2, one section was left, migrate modem was in the log, and dialing worked again after a reboot. Could you merge it into main and backport it to stable?
We build QModem from stable (3c44579, 2026-10-19). The branch is based on main at c49654e and doesn't apply to stable: git apply --3way gives five conflicts in modem_scand.c. All five are where stable added config_lock() / g.queue_lock / event_current() around the same section writes that the fix now does under uci_lock: in add_modem, the remove path and disable_slot. Merging the two locking schemes is better done by you than downstream.
We can test a stable build with the fix on this Orange Pi Zero 3 and report back.
中文简述:我们在 Orange Pi Zero 3(OpenWrt 25.12,多个 USB 模块)上遇到了同样的问题:每次重启 USB 总线编号都会变化,同一个 FM350 生成了 1_1_3、3_1_3、6_1_3 三个配置段;旧配置段保留的 AT 口在重新编号后属于另一个模块(T99),tom_modem 卡在 D 状态,残留的 v6 接口循环启动。#280 的修复已在硬件上确认有效,希望合并到 main 并移植到 stable。该分支基于 main(c49654e),在 stable(3c44579)上有 5 处冲突,都在加锁部分。我们可以在这块板子上测试 stable 版本。
FUjr commentedon Oct 22, 2026
@Medvedolog @sassalana
中文
感谢补充多模组场景的反馈。我重新考虑了这个问题的处理边界:我倾向于认为 USB 总线编号在重启后变化是 board/platform 层面的问题;我不希望在 QModem 中引入额外的身份判定机制来合并不同 slot 的配置。 这还不是对具体板级根因的最终确认。不过,旧配置继续拨号、向已经属于另一模组的 AT 口发送命令,确实是 QModem 应该处理的生命周期问题。
因此,我实现了一个新的方案,供大家测试:PR #288,分支
fix-modem-presence-280,提交f644cfa。这次实现的目标是保证扫描与拨号的时序:state=enabled。block_auto_probe=1,已有配置的存在性检查和掉线处理仍然执行;自动发现和配置探测仍被禁止。固定配置也需要通过存在性检查。与之前 #285 的方案不同,这次不会合并、迁移或自动删除历史模组配置,也不会把 APN 自动迁移到新 slot。 路径发生变化后,旧段应保留但停用;自动模式可以独立发现新 slot,手动模式需要修正配置后重新检查。验收重点是“失效段不运行、不误用其他模组的端口”,不是“UCI 中永远只有一个段”。
宿主机编译和回归测试已通过,这一版尚未经过实机验证,之前对
8f48aa9的硬件结果不能代替对本实现的验证。目前 PR 基于main,尚未移植到stable。方便的话,请在 Orange Pi Zero 3 多模组环境测试这一版,尤其是保留
block_auto_probe=1后重启、USB 总线重新编号、旧 tty 被另一模组复用,以及拔插/重新枚举。请检查旧段是否变为 disabled、对应 procd 实例和残留 IPv4/IPv6 接口是否被清理,以及当前有效模组能否正常拨号。也欢迎复测 ECM/NCM 模式切换。English
Thanks for the additional multi-modem report. After reconsidering the scope, I tend to view USB bus renumbering across reboots as a board/platform issue, and I do not want to introduce extra identity heuristics in QModem to merge configurations across slots. This is not a final diagnosis of the board-specific cause. However, allowing a stale configuration to keep dialing or send AT commands to a port now owned by another modem is a lifecycle problem QModem should address.
I have implemented a new approach in PR #288, branch
fix-modem-presence-280, commitf644cfa:state=enabledis insufficient.block_auto_probe=1, while automatic discovery/configuration probing remains blocked. Fixed configurations also require presence validation.This approach does not merge, migrate or automatically delete historical modem sections, and does not transfer APN settings to a new slot. An old section may remain in UCI, but it should be disabled and inactive. Automatic mode can discover the new slot independently; manual mode requires correcting the configuration and checking it again. The acceptance criterion is that stale sections stop running and cannot use another modem's port, not that only one section remains.
Host compilation and regression tests pass, but this implementation has not been tested on hardware. The earlier hardware results for
8f48aa9do not validate this new approach. This PR targetsmain; astablebackport is not included yet.Could you test this on the Orange Pi Zero 3 multi-modem setup, particularly reboot/bus renumbering with
block_auto_probe=1, tty reuse by another modem, and unplug/re-enumeration? Please check whether stale sections become disabled, their procd instances and leftover IPv4/IPv6 interfaces disappear, and correctly configured present modems can dial. ECM/NCM switching feedback is also welcome.测试分支 / Test branch
请将现有 qmodem feed 切换到以下分支,然后同时编译、安装
qmodem和modem_scan,安装后重启路由器。仅更新扫描包不够。Change the existing qmodem feed entry to this branch, then build and install both
qmodemandmodem_scan, and reboot the router. Updating only the scanner package is insufficient.请反馈测试提交、场景和以下输出 / Please include the tested commit, scenario and these outputs: