RK3572 双网口休眠唤醒后网络异常排查方案

一、问题现象

设备采用 RK3572 + Buildroot,存在两个有线网口:

text 复制代码
eth0 = 192.168.6.92/24
eth1 = 192.168.6.204/24
gateway = 192.168.6.1

正常开机时:

text 复制代码
default via 192.168.6.1 dev eth1
default via 192.168.6.1 dev eth0

两个网口均可以独立访问外网:

bash 复制代码
ping -c 4 www.baidu.com -I eth0
ping -c 4 www.baidu.com -I eth1

但经过:

bash 复制代码
echo mem > /sys/power/state

休眠唤醒后出现:

text 复制代码
eth0:公网正常
eth1:局域网正常,但无法访问公网

后续还发现域名解析存在约 7 秒额外等待,甚至出现:

text 复制代码
ping: www.baidu.com: Temporary failure in name resolution

最终确认存在两个相互独立的问题:

text 复制代码
问题1:
ConnMan 与 udhcpc 同时管理 eth0/eth1
→ ConnMan 在 resume 后删除 eth1 默认路由

问题2:
ConnMan 与 udhcpc 同时维护 /etc/resolv.conf
→ ConnMan 覆盖有线 DHCP 获取的 DNS
→ 域名解析变慢或失败

二、第一步:先确认是不是物理链路问题

休眠唤醒后先检查:

bash 复制代码
ifconfig

cat /sys/class/net/eth0/carrier
cat /sys/class/net/eth1/carrier

如果:

text 复制代码
eth0 carrier = 1
eth1 carrier = 1

同时内核日志有:

text 复制代码
eth0: Link is Up - 1Gbps/Full
eth1: Link is Up - 1Gbps/Full

说明:

text 复制代码
PHY恢复正常
GMAC恢复正常
RGMII链路正常
125MHz时钟基本正常

此时不要继续优先排查 YT8531、GMAC、RGMII。

再测试局域网:

bash 复制代码
ping -c 4 192.168.6.1 -I eth1

如果网关可以正常 ping 通,则进一步说明:

text 复制代码
eth1 TX/RX正常
ARP正常
局域网路由正常

问题应该继续往三层路由查。


三、第二步:对比休眠前后的路由

正常启动时:

bash 复制代码
ip route

例如:

text 复制代码
default via 192.168.6.1 dev eth1
default via 192.168.6.1 dev eth0

192.168.6.0/24 dev eth0 ...
192.168.6.0/24 dev eth1 ...

休眠唤醒后再次执行:

bash 复制代码
ip route

故障状态发现:

text 复制代码
default via 192.168.6.1 dev eth0

192.168.6.0/24 dev eth0 ...
192.168.6.0/24 dev eth1 ...
192.168.6.1 dev eth0
192.168.6.1 dev eth1

关键区别:

text 复制代码
default via 192.168.6.1 dev eth1

消失。

但仍存在:

text 复制代码
192.168.6.0/24 dev eth1
192.168.6.1 dev eth1

因此可以解释:

text 复制代码
局域网:
192.168.6.0/24
→ 有直连路由
→ 正常

公网:
0.0.0.0/0
→ 没有 eth1 default
→ 无法访问

到这里就可以把故障定位为:

eth1 默认路由丢失,而不是 eth1 本身无法发送数据。


四、第三步:使用 ip monitor 找出路由什么时候消失

执行:

bash 复制代码
ip monitor link address route rule

保持该终端运行,然后另一个终端:

bash 复制代码
echo mem > /sys/power/state

唤醒后查看输出。

本次问题抓到了非常关键的过程:

text 复制代码
eth1: Link is Up - 1Gbps/Full

192.168.6.204/24 dev eth1
192.168.6.0/24 dev eth1
192.168.6.1 dev eth1

default via 192.168.6.1 dev eth1 metric 4294962175

Deleted default via 192.168.6.1 dev eth1 metric 4294962175

也就是说:

text 复制代码
eth1 default不是没有恢复
而是:
恢复成功
→ 随后被某个用户空间程序删除

这一点非常重要。

eth1 的 Link、地址、本地路由和 default 都曾经正常恢复,然后 default 被明确删除。

因此排查方向由:

text 复制代码
驱动为什么没有恢复路由?

转为:

text 复制代码
哪个用户空间程序把路由删掉了?

五、第四步:确认是不是 udhcpc 删除

首先检查 udhcpc:

bash 复制代码
ps -ef | grep '[u]dhcpc'

正常看到:

text 复制代码
udhcpc ... -i eth0
udhcpc ... -i eth1

说明每个接口只有一个 DHCP Client,没有重复启动。

然后确认 udhcpc 使用的脚本:

bash 复制代码
udhcpc --help

可以看到:

text 复制代码
-s PROG
Run PROG at DHCP events
(default /usr/share/udhcpc/default.script)

再查看:

bash 复制代码
/usr/share/udhcpc/default.script

重点关注:

sh 复制代码
while route del default gw 0.0.0.0 dev $interface
do
        :
done

for i in $router
do
        route add default gw $i dev $interface
done

为了确认休眠时脚本是否执行,可以在脚本开头加入:

sh 复制代码
echo "$(date) event=$1 interface=$interface router=$router" \
        >> /tmp/udhcpc-debug.log

然后:

bash 复制代码
rm -f /tmp/udhcpc-debug.log

echo mem > /sys/power/state

cat /tmp/udhcpc-debug.log

实际结果:

text 复制代码
/tmp/udhcpc-debug.log 不存在

说明:

suspend/resume 过程中 udhcpc 并没有产生 renew/bound 事件。

所以不是 default.script 在 resume 后主动删除 eth1 路由。


六、第五步:手动触发 DHCP renew 验证

BusyBox udhcpc 支持:

SIGUSR1 → Renew lease

因此执行:

bash 复制代码
kill -USR1 "$(cat /var/run/udhcpc.eth1.pid)"

调试日志显示:

bash 复制代码
event=[renew]
interface=[eth1]
ip=[192.168.6.204]
router=[192.168.6.1]
staticroutes=[]

最终:

bash 复制代码
ip route

恢复:

bash 复制代码
default via 192.168.6.1 dev eth1
default via 192.168.6.1 dev eth0

这证明:

  • DHCP服务器正常
  • udhcpc正常
  • default.script正常
  • gateway正常

并进一步确定:

原问题是另一个网络管理组件在操作 eth1 路由。

七、第六步:检查是否存在多个网络管理器

查看启动服务:

bash 复制代码
ls /etc/init.d/

发现同时存在:

text 复制代码
S40network
S45connman

系统架构实际上是:

text 复制代码
S40network
    ↓
udhcpc
    ↓
eth0 / eth1

同时:

S45connman
    ↓
ConnMan
    ↓
也在管理 eth0 / eth1

也就是说:

text 复制代码
          eth0 / eth1
            ↑     ↑
            │     │
         udhcpc  ConnMan
            │     │
            └─冲突─┘

这是一个明显的网络管理所有权冲突。


八、第七步:通过异常 metric 锁定 ConnMan

ip monitor 中还有一条非常关键的信息:

text 复制代码
default via 192.168.6.1 dev eth1 metric 4294962175

eth1 的 ifindex:

text 复制代码
5: eth1

计算:

text 复制代码
UINT32_MAX - ifindex × 1024

即:

text 复制代码
4294967295 - 5 × 1024
= 4294962175

正好与日志完全一致。

因此这条低优先级默认路由具有明显的 ConnMan 特征。

可以进一步验证:

bash 复制代码
/etc/init.d/S45connman stop

执行后观察到:

text 复制代码
eth1: Link is Down
eth0: Link is Down

说明:

ConnMan 确实已经接管 eth0 和 eth1。

最终可以确认路由问题根因:

text 复制代码
S40network/udhcpc
        +
ConnMan

同时管理 eth0/eth1
        ↓
ConnMan选择一个default service
        ↓
另一个网口变成低优先级default
        ↓
resume重新选择service
        ↓
删除eth1 default
        ↓
eth1无法访问公网

九、路由问题最终解决方案

让 ConnMan 永久忽略 eth0、eth1。

创建:

text 复制代码
/etc/connman/main.conf

内容:

ini 复制代码
[General]
NetworkInterfaceBlacklist=eth0,eth1,vmnet,vboxnet,virbr,ifb,ve-,vb-,ham,veth

最终职责:

text 复制代码
eth0/eth1
    ↓
S40network + udhcpc

wlan0
    ↓
ConnMan

重启后重新测试:

bash 复制代码
ip route

ping -c 4 www.baidu.com -I eth0
ping -c 4 www.baidu.com -I eth1

再:

bash 复制代码
echo mem > /sys/power/state

唤醒后确认:

text 复制代码
default via 192.168.6.1 dev eth0
default via 192.168.6.1 dev eth1

均仍存在。


十、第八步:发现域名访问明显变慢

解决路由冲突以后,又发现:

bash 复制代码
time ping -c 4 www.baidu.com -I eth0

实际 RTT:

text 复制代码
3~4 ms

但总耗时:

text 复制代码
约18秒

首先绕过 DNS:

bash 复制代码
time ping -n -c 4 -I eth0 183.2.172.177
time ping -n -c 4 -I eth1 183.2.172.177

结果:

text 复制代码
real ≈ 3.0s

这说明:

text 复制代码
PHY正常
路由正常
公网正常
ICMP正常

额外约7秒:
发生在DNS解析阶段

十一、第九步:检查 resolv.conf

执行:

bash 复制代码
cat /etc/resolv.conf

发现:

text 复制代码
# Generated by Connection Manager
nameserver ::1
nameserver 127.0.0.1
nameserver 192.168.6.1 # eth0
nameserver 192.168.6.1 # eth1

其中:

text 复制代码
::1
127.0.0.1

是 ConnMan DNS Proxy。

临时测试:

bash 复制代码
echo "nameserver 192.168.6.1" > /etc/resolv.conf

重新:

bash 复制代码
time ping -c 4 www.baidu.com -I eth0
time ping -c 4 www.baidu.com -I eth1

结果从:

text 复制代码
≈18秒

恢复到:

text 复制代码
≈3秒

因此确认:

localhost DNS proxy 是第一次 DNS 延迟的直接原因。


十二、第十步:关闭 ConnMan DNS Proxy

S45connman 中有:

sh 复制代码
CONNMAND_ARGS="-n"

[ -r "/etc/default/$DAEMON" ] && \
        . "/etc/default/$DAEMON"

因此无需修改 init 脚本。

创建:

text 复制代码
/etc/default/connmand

内容:

sh 复制代码
CONNMAND_ARGS="-n --nodnsproxy"

重启以后:

bash 复制代码
ps -ef | grep '[c]onnmand'

确认:

text 复制代码
connmand -n --nodnsproxy

然后:

bash 复制代码
cat /etc/resolv.conf

localhost:

text 复制代码
::1
127.0.0.1

已经消失。

域名 ping 恢复约 3 秒。


十三、第十一步:继续稳定性测试发现 resolv.conf 仍被覆盖

进行多次网络测试后,两个有线口连续 20 次访问均正常,RTT 基本在 3.5~4.5 ms,未出现丢包。

但后续又出现:

bash 复制代码
cat /etc/resolv.conf

变成:

text 复制代码
# Generated by Connection Manager
nameserver fe80::6a1:51ff:fe94:5969

原来的:

text 复制代码
nameserver 192.168.6.1 # eth0
nameserver 192.168.6.1 # eth1

全部消失。

然后:

bash 复制代码
ping www.baidu.com -I eth0
ping www.baidu.com -I eth1

均报:

text 复制代码
Temporary failure in name resolution

但 eth0、eth1 IP 地址仍然正常。

这说明:

text 复制代码
路由问题已经解决
但是:

ConnMan
   +
udhcpc

仍然同时写:
/etc/resolv.conf

所以:

text 复制代码
--nodnsproxy

只是关闭 DNS Proxy,

并不等于:

text 复制代码
ConnMan 不修改 resolv.conf

十四、DNS问题最终解决方案

最终必须让 /etc/resolv.conf 也只有一个管理者。

由于 eth0/eth1 已经交给:

text 复制代码
S40network + udhcpc

因此 DNS 也统一由 udhcpc 维护。

最终 /etc/connman/main.conf

ini 复制代码
[General]
NetworkInterfaceBlacklist=eth0,eth1,vmnet,vboxnet,virbr,ifb,ve-,vb-,ham,veth
ResolvConf=/dev/null

其中:

text 复制代码
NetworkInterfaceBlacklist

解决:

text 复制代码
ConnMan 与 udhcpc 路由冲突

而:

text 复制代码
ResolvConf=/dev/null

解决:

text 复制代码
ConnMan 与 udhcpc 同时修改 /etc/resolv.conf

/etc/default/connmand

sh 复制代码
CONNMAND_ARGS="-n --nodnsproxy"

最终结构:

text 复制代码
                    RK3572
                       │
          ┌────────────┴────────────┐
          │                         │
      eth0 / eth1                 wlan0
          │                         │
          ▼                         ▼
 S40network + udhcpc              ConnMan
          │                         │
     IP / Route / DNS           Wi-Fi管理
          │
          ▼
 /etc/resolv.conf

ConnMan:
× 不管理 eth0
× 不管理 eth1
× 不启用 DNS Proxy
× 不修改 /etc/resolv.conf

十五、最终排查思路总结

遇到"休眠唤醒后某个网口无法联网"时,不要直接修改驱动,可以按以下顺序判断:

  1. 检查 Link
bash 复制代码
ifconfig
cat /sys/class/net/eth1/carrier

Link 正常则继续。

  1. 测试网关
bash 复制代码
ping 192.168.6.1 -I eth1

网关正常而公网失败,优先检查路由。

  1. 检查路由
bash 复制代码
ip route

检查是否缺:

text 复制代码
default via ... dev eth1
  1. 使用 ip monitor
bash 复制代码
ip monitor link address route rule

观察到底是:

text 复制代码
default根本没有添加

还是:

text 复制代码
default添加后又被删除

这两类问题完全不同。

  1. 确认是谁管理网络
bash 复制代码
ps -ef | grep '[u]dhcpc'
ls /etc/init.d/
ps -ef | grep '[c]onnman'

如果发现:

text 复制代码
udhcpc + ConnMan

同时管理同一个接口,就要优先解决所有权冲突。

  1. IP访问正常、域名访问慢

先:

bash 复制代码
time ping -n -c 4 183.2.172.177

再:

bash 复制代码
time ping -c 4 www.baidu.com

如果 IP 快、域名慢:

text 复制代码
直接查 DNS
  1. 检查 DNS 所有权
bash 复制代码
cat /etc/resolv.conf

再确认:

text 复制代码
谁写这个文件?

最终应该遵守一个原则:

同一个网络资源尽量只有一个管理者。

本次问题最终就是因为:

text 复制代码
路由:
udhcpc + ConnMan 双管理

DNS:
udhcpc + ConnMan 双管理

导致两个不同阶段的网络异常。

最终通过明确管理边界解决:

text 复制代码
Ethernet → S40network/udhcpc
Wi-Fi    → ConnMan
DNS      → udhcpc
相关推荐
Industio_触觉智能4 个月前
瑞芯微RK3572正式发布,中阶AIoT八核处理器,性能功耗双突破
rk3568·aiot·瑞芯微·rk3576·国产芯片·rk3572·rk3572j
坏孩子的诺亚方舟4 个月前
open_prj20_MPSOC概述
fpga开发·正点原子·mpsoc
Quinn274 个月前
正点原子 RK3562 Android14 Ubuntu 编译 SDK 环境准备:依赖、repo 与 Swap 配置一次搞定
linux·运维·ubuntu·mpu·正点原子·rk3562·arm linux
Quinn274 个月前
正点原子 RK3562 Android14 集成 GStreamer 1.24.13(CLI + V4L2 插件)完整移植方案
mpu·正点原子·rk3562·arm linux
Quinn274 个月前
正点原子 RK3562 Android14 双 IMX335 摄像头调试:从驱动链路到 Camera HAL 枚举排查
正点原子·rk3562·arm linux
Quinn274 个月前
正点原子 STM32MP257 修复异核 FreeRTOS+OpenAMP 例程里 SysTick 延时异常的问题
stm32·嵌入式硬件·正点原子·arm linux
Quinn271 年前
【正点原子】STM32MP257 同构多核架构下的 ADC 电压采集与处理应用开发实战
stm32·架构·正点原子·arm linux·stm32mp257
橘长_2 年前
repo仓库转移到自己本地的git服务器
服务器·git·repo·正点原子
神电测控2 年前
第6章>>实验8:PS(ARM)端Linux RT与PL端FPGA之间(通过FIFO队列进行通信和交互)-《LabVIEW ZYNQ FPGA宝典》
linux·arm开发·fpga开发·labview·zynq·正点原子·神电测控