diff --git a/reports/2026-10-28-cudy-tr3000-wwan-watchdog.md b/reports/2026-10-28-cudy-tr3000-wwan-watchdog.md new file mode 100644 index 0000000..9db609c --- /dev/null +++ b/reports/2026-10-28-cudy-tr3000-wwan-watchdog.md @@ -0,0 +1,216 @@ +# Cudy TR3000:部署 Wi-Fi 上联看门狗与日志优化 + +- 日期:2026-10-28 +- 设备:Cudy TR3000 256MB v1(`cudy-tr3000.tail694d4.ts.net`,远程) +- 系统:OpenWrt 25.12.6 r33311-981c978eff,mediatek/filogic +- 无线:MT7981,mt76 驱动 +- 相关报告:[`2026-10-28-linksys-mx8500-wwan-recovery.md`](2026-10-28-linksys-mx8500-wwan-recovery.md) + +## 背景 + +Linksys MX8500 上发现 Wi-Fi 上联(STA)会卡在“已关联但发不出包”的状态,且不会自动恢复(见相关报告)。本次把同一套看门狗和日志设置部署到 Cudy TR3000,并检查它是否存在同样的问题。 + +这台路由器是远程设备,唯一在用的上联就是 Wi-Fi。改 Wi-Fi 设置会导致一段时间断线,所以只做了不影响 Wi-Fi 的改动。 + +## 现状 + +| 接口 | 设备 | 射频 | 上游 | 状态 | +|---|---|---|---|---| +| wwan5 | `phy1-sta0` | radio1(5G) | eduroam(WPA2-Enterprise,PEAP/MSCHAPv2) | 在用,mwan3 online | +| wwan2 | `phy0-sta0` | radio0(2.4G) | eduroam | `wireless.wifinet2.disabled='1'`,未启用 | +| wan | `eth0` | — | 有线 | 无载波,未使用 | + +注意射频编号和 MX8500 相反:这台的 5G 是 radio1 / phy1,2.4G 是 radio0 / phy0。 + +5G 射频上同样存在热点与 STA 频宽不一致: + +| | 频宽 | 中心频率 | +|---|---|---| +| 热点 `phy1-ap0` | HE80 | 5290 MHz | +| STA `phy1-sta0` | 20 MHz(eduroam 只给 20 MHz) | 5260 MHz | + +信道 52 是 DFS 信道。 + +## 检查结果:没有发现 MX8500 的故障 + +| 项目 | MX8500 故障时 | Cudy wwan5 | +|---|---|---| +| 连接时长 | 约 5 分钟后失效 | 30728 s(约 8.5 小时,开机至今未断) | +| tx failed / tx packets | 5775 / 6263(约 92%) | 67345 / 2242239(约 3%) | +| tx 速率 | HE-MCS0 NSS1,8.6 Mbit/s | HE-MCS11 NSS2,286.7 Mbit/s | +| 信号 | -53 dBm | -51 dBm | +| mwan3 离线记录 | 有 | 日志覆盖 17:43 起,无任何 offline 事件 | + +结论:mt76 驱动目前没有表现出 ath11k 的“半死”问题。频宽不一致本身不一定会触发故障。 + +## 修改内容 + +### 1. 部署看门狗 `/usr/sbin/wwan-watchdog` + +逻辑与 MX8500 的第二版相同(判定方式、确认次数、恢复步骤、退避),只有两处按本机调整: + +| 项目 | MX8500 | Cudy TR3000 | 原因 | +|---|---|---|---| +| 探测地址 `PROBE_IPS` | `223.5.5.5 1.1.1.1` | `1.1.1.1 8.8.8.8` | 设备在美国 | +| 接口映射 | wwan2→phy1/radio1,wwan5→phy0/radio0 | wwan2→phy0/radio0,wwan5→phy1/radio1 | 射频编号相反 | + +**eduroam 网关 172.27.64.1 不回 ping**(实测 100% 丢包,但外网正常)。MX8500 的第一版看门狗只 ping 网关、且第一次失败就重连,放在这里会每分钟强制重连一次。现在的版本是“网关或任一探测地址能通就算正常”,并且要连续两次失败才动手,所以不受影响。代价是“网关通但 mwan3 离线”这条提示在这台上不会出现。 + +恢复步骤: + +| 检测结果 | 处理 | +|---|---| +| 正常 | 清零计数 | +| 不通,第 1 次 | 只记日志,等下一次确认 | +| 不通,第 2、3 次 | `REASSOCIATE`(eduroam 会重新走一次 EAP 认证) | +| 不通,第 4 次 | `wifi up radio1` | +| 之后仍不通 | 每 10 次检测重启一次射频 | + +wwan2 当前未启用,`ifstatus wwan2` 不是 up,看门狗会直接跳过它。以后启用 wwan2 不需要改脚本。 + +相关改动: + +- `/etc/crontabs/root`:新增 `* * * * * /usr/sbin/wwan-watchdog`(原来没有任何定时任务),并 `cron enable` +- `/etc/mwan3.user`:追加 `disconnected` 事件时调用看门狗(备份:`/root/mwan3.user.bak`) +- `/etc/sysupgrade.conf`:加入 `/usr/sbin/wwan-watchdog` 和 `/etc/mwan3.user` + +部署过程中发现:BusyBox 的 `crontab -` 从管道读入时会写出空文件。所以这里直接写 `/etc/crontabs/root`,然后重启 cron。 + +### 2. 日志缓冲调大 + +`system.@system[0].log_size` 从 128 改为 1024(KB),出故障时能回溯更久的记录。 + +### 未改动 + +- **5G 频宽**:保持 HE80,没有和 STA 对齐。对齐只能降到 HE20,5G 热点带宽会降到约 1/4,而 TR3000 没有 6 GHz 可以补充;且目前没有任何故障证据。如果以后看门狗日志里出现 wwan5 卡死(判定故障时记录的 tx failed 暴涨、速率掉到 MCS0),再考虑改。 +- **`99-fix-same-subnet-routing`**:MX8500 用它给两条同时在线的 Wi-Fi 上联加源地址策略路由。这台目前只有 wwan5 一条上联,不需要。以后同时启用 wwan2 时再评估。 +- **HE overrides**:这台已经是完整版 `wpad-mbedtls`,但和 MX8500 一样不支持 `disable_he`(OpenWrt 25.12 没有打开 `CONFIG_HE_OVERRIDES`)。目前不需要。 + +## 验证 + +``` +$ crontab -l +* * * * * /usr/sbin/wwan-watchdog + +$ logread | grep wwan-watchdog +... cron.err crond[...]: USER root pid ... cmd /usr/sbin/wwan-watchdog # 每分钟运行 +(无 wwan-watchdog: 开头的动作日志,即没有误触发) + +$ mwan3 interfaces | grep wwan5 + interface wwan5 is online and tracking is active (online 08h:45m:53s, ...) +``` + +部署后观察期间 wwan5 未断线,看门狗未触发。 + +查看看门狗动作: + +```sh +logread -e wwan-watchdog | grep -v crond +``` + +## 回滚 + +```sh +sed -i '\#/usr/sbin/wwan-watchdog#d' /etc/crontabs/root && /etc/init.d/cron restart +cp /root/mwan3.user.bak /etc/mwan3.user +rm /usr/sbin/wwan-watchdog +sed -i '\#^/usr/sbin/wwan-watchdog$#d; \#^/etc/mwan3.user$#d' /etc/sysupgrade.conf +uci set system.@system[0].log_size='128' && uci commit system && /etc/init.d/log restart +``` + +不要用 `crontab -l | grep -v ... | crontab -`:在 BusyBox 上会清空整个 crontab。 + +## 附录:脚本全文 + +### `/usr/sbin/wwan-watchdog` + +```sh +#!/bin/sh +# Recover Wi-Fi STA uplinks that stay associated but stop passing traffic. +# Called every minute by cron and on mwan3 "disconnected" events. + +PATH=/usr/sbin:/usr/bin:/sbin:/bin +STATE_DIR=/tmp/wwan-watchdog +TAG=wwan-watchdog +PROBE_IPS="1.1.1.1 8.8.8.8" + +exec 9>/var/lock/wwan-watchdog.lock +flock -n 9 || exit 0 +mkdir -p "$STATE_DIR" + +log() { logger -t "$TAG" "$*"; } + +tx_stats() { + iw dev "$1" station dump 2>/dev/null | awk ' + /tx packets/ { p = $3 } + /tx failed/ { f = $3 } + /tx bitrate/ { r = $3 " " $4 " " $5 } + END { print "tx=" p " failed=" f " rate=" r }' +} + +# Healthy if the gateway or any probe address answers through this device +link_ok() { + local dev="$1" gw="$2" ip + for ip in "$gw" $PROBE_IPS; do + ping -c 2 -W 2 -I "$dev" "$ip" >/dev/null 2>&1 && return 0 + done + return 1 +} + +check() { + local iface="$1" dev="$2" radio="$3" + local count_file="$STATE_DIR/$iface" + local up gw count + + up=$(ifstatus "$iface" 2>/dev/null | jsonfilter -e '@.up') + [ "$up" = "true" ] || { rm -f "$count_file"; return; } + gw=$(ifstatus "$iface" | jsonfilter -e '@.route[@.target="0.0.0.0"].nexthop' | head -n 1) + [ -n "$gw" ] || return + + if link_ok "$dev" "$gw"; then + [ -f "$count_file" ] && log "$iface: link passing traffic again" + rm -f "$count_file" + if ping -c 2 -W 2 -I "$dev" "$gw" >/dev/null 2>&1 && \ + mwan3 interfaces 2>/dev/null | grep -q "interface $iface is offline"; then + log "$iface: gateway reachable but mwan3 offline (login expired or upstream down?)" + fi + return + fi + + count=$(( $(cat "$count_file" 2>/dev/null || echo 0) + 1 )) + echo "$count" > "$count_file" + + case "$count" in + 1) + log "$iface: gateway $gw and probes unreachable via $dev ($(tx_stats "$dev")), confirming next check" + ;; + 2|3) + log "$iface: still unreachable (check $count, $(tx_stats "$dev")), reassociating" + ubus call "wpa_supplicant.$dev" control '{"command":"REASSOCIATE"}' >/dev/null 2>&1 + ;; + 4) + log "$iface: still unreachable after reassociate ($(tx_stats "$dev")), restarting $radio" + wifi up "$radio" + ;; + *) + # Back off: retry the radio restart every 10 failed checks + if [ $(( count % 10 )) -eq 4 ]; then + log "$iface: unreachable for $count checks, restarting $radio again" + wifi up "$radio" + fi + ;; + esac +} + +check wwan2 phy0-sta0 radio0 +check wwan5 phy1-sta0 radio1 +``` + +### `/etc/mwan3.user`(追加部分) + +```sh + +[ "$ACTION" = "disconnected" ] && case "$INTERFACE" in + wwan2|wwan5) /usr/sbin/wwan-watchdog & ;; +esac +``` diff --git a/reports/2026-10-28-linksys-mx8500-wwan-recovery.md b/reports/2026-10-28-linksys-mx8500-wwan-recovery.md index 4479ee5..91c6287 100644 --- a/reports/2026-10-28-linksys-mx8500-wwan-recovery.md +++ b/reports/2026-10-28-linksys-mx8500-wwan-recovery.md @@ -279,7 +279,7 @@ uci set wireless.radio1.htmode='HE40' && uci set wireless.radio0.htmode='HE160' wifi up radio1 && wifi up radio0 cp /root/99-fix-same-subnet-routing.bak /etc/hotplug.d/iface/99-fix-same-subnet-routing cp /root/mwan3.user.bak /etc/mwan3.user -crontab -l | grep -v wwan-watchdog | crontab - +sed -i '\#/usr/sbin/wwan-watchdog#d' /etc/crontabs/root && /etc/init.d/cron restart rm /usr/sbin/wwan-watchdog sed -i '\#^/usr/sbin/wwan-watchdog$#d; \#^/etc/mwan3.user$#d' /etc/sysupgrade.conf ```