嵌入式设备ping不通?tcpdump 5分钟找到凶手,比加printf快10倍

嵌入式设备ping不通?tcpdump 5分钟找到凶手,比加printf快10倍

嵌入式开发调试网络问题,最常见的画面:开发板ping不通网关,或者跟服务器连不上。然后呢?打着手电筒看网口灯、拿示波器点PHY芯片管脚、在代码里拼命加printk打网络数据------emmm,你确定要这样?

我见过一个兄弟,调试一个MQTT断连问题,在代码里加了30多行printk打数据包内容,编译烧录一次5分钟,折腾了一整天没找到原因。我过去敲了一行tcpdump,30秒定位是服务器端TLS证书过期了

今天这篇不讲花哨的,就跟你聊tcpdump在嵌入式场景下的5种实战用法。随便哪种,都能让你少加100行printk。


前提:你的板子上有tcpdump吗?

大部分嵌入式Linux系统(Buildroot/Yocto出来的)默认没有 tcpdump。别慌,两个办法:

方案一:交叉编译

bash 复制代码
# 下载tcpdump源码,交叉编译扔到板子上就行
./configure --host=arm-linux-gnueabihf --prefix=/opt/tcpdump
make && make install
# 把tcpdump和libpcap.so拷到板子上
arm-linux-gnueabihf-strip tcpdump  # 减到500K左右
scp tcpdump root@板子IP:/usr/sbin/

方案二:用Busybox自带的(阉割版)

bash 复制代码
# 如果Busybox编译时勾选了CONFIG_TCPSUPPORT
# 有个阉割版能用,功能少但够用
tcpdump -i eth0 -n

如果空间极度紧张(Flash只有4MB),还有一个骚招:把tcpdump编译成静态链接扔到/tmp里,反正tmpfs是内存。跑完就没了,不占Flash空间。


场景一:板子ping不通网关------看ARP就知道谁在搞鬼

嵌入式设备最常见场景:ping 192.168.1.1,卡住不动了。

bash 复制代码
# 在板子上抓ARP包
tcpdump -i eth0 -n arp

输出长这样:

perl 复制代码
12:34:56.789012 ARP, Request who-has 192.168.1.1 tell 192.168.1.100, length 46
12:34:57.789012 ARP, Request who-has 192.168.1.1 tell 192.168.1.100, length 46
12:34:58.789012 ARP, Request who-has 192.168.1.1 tell 192.168.1.100, length 46

只发不收------说明网关没理你。这时候原因只有三个:

  1. IP不在同一网段(最常见):板子配了192.168.1.100/24,但网关是192.168.2.1
  2. MAC地址过滤:交换机的端口安全功能把陌生MAC拦了
  3. 物理层没通:PHY芯片auto-negotiation失败,Link没起来

如果看到:

vbscript 复制代码
ARP, Request who-has 192.168.1.1 tell 192.168.1.100
ARP, Reply 192.168.1.1 is-at 00:11:22:33:44:55

ARP通了但ping还不行------那就不是链路层问题了,查路由表或防火墙。

flowchart TD A[ping 网关不通] --> B{tcpdump抓ARP包} B -->|只发不收| C[链路层问题] B -->|有回复但ping不通| D[网络层问题] C --> C1[检查IP网段] C --> C2[检查MAC过滤] C --> C3[检查PHY Link状态] D --> D1[查路由表 route -n] D --> D2[查iptables规则] D --> D3[检查网关防火墙] C1 --> E[修复后验证] D1 --> E

场景二:TCP连接被拒------别猜,看RST包

另一个经典场景:板子上的应用连服务器,connect返回-1,errno=ECONNREFUSED。

bash 复制代码
tcpdump -i eth0 -n 'tcp port 8080'

输出:

bash 复制代码
12:34:56.789 IP 192.168.1.100.12345 > 10.0.0.1.8080: Flags [S], seq 100
12:34:56.790 IP 10.0.0.1.8080 > 192.168.1.100.12345: Flags [R.], seq 0, ack 101

SYN包发出去,立刻收到RST------服务器端口没开或者防火墙拦了。不需要猜,不需要看代码。

如果看到:

ini 复制代码
12:34:56.789 IP 192.168.1.100.12345 > 10.0.0.1.8080: Flags [S], seq 100
12:34:56.790 IP 10.0.0.1.8080 > 192.168.1.100.12345: Flags [S.], seq 200, ack 101
12:34:56.790 IP 192.168.1.100.12345 > 10.0.0.1.8080: Flags [.], ack 201

三次握手完成------这时如果应用还报错,那是应用层的问题(协议解析、认证、TLS握手等),跟网络无关了。


场景三:嵌入式设备做服务端------看看谁在扫你

你的板子当服务器(比如HTTP API),有客户端连不上来,先抓包看看有没有人来找你:

bash 复制代码
tcpdump -i eth0 -n 'tcp port 80'

如果根本没包------是客户端找不到你,跟板子没关系。查DNS解析、查路由可达性。

如果有SYN但没回复:

bash 复制代码
12:34:56.789 IP 192.168.1.200.54321 > 192.168.1.100.80: Flags [S], seq 789
# ... 没下文了

说明你的服务端程序压根没在监听,或者防火墙把入站连接丢了。netstat -tlnp看一眼80端口有没有LISTEN就清楚了。


场景四:嵌入式设备上网慢------看TCP重传

设备联网了,但奇慢无比。一条AT指令要等好几秒?这就是TCP重传的典型症状。

bash 复制代码
tcpdump -i eth0 -n 'tcp[13] & 0x0c != 0'
# 只抓RST和SYN包,精确定位连接问题

或者更直接的:

bash 复制代码
# 抓重传包
tcpdump -i eth0 -n 'tcp[13] & 4 != 0'

看到大量重传(RST标志位),基本可以确定:

  • WiFi/4G信号弱(嵌入式无线设备最常见)
  • 服务器太远延迟太高
  • 缓冲区太小,TCP window满了

进一步看看延迟:

bash 复制代码
# 带时间戳抓包,看延迟
tcpdump -i eth0 -n -tttt 'host 服务器IP'

对比每个包的时间戳,如果RTT超过500ms,那不管你怎么优化代码都没用------瓶颈在网络本身。


场景五:嵌入式板子没DHCP地址?抓DHCP包

bash 复制代码
tcpdump -i eth0 -n -e port 67 or port 68

DHCP有四步握手:

yaml 复制代码
# DISCOVER:板子找DHCP服务器
IP 0.0.0.0.68 > 255.255.255.255.67: DHCP-DISCOVER
# OFFER:服务器回复
IP DHCP服务器.67 > 255.255.255.255.68: DHCP-OFFER
# REQUEST:板子确认
IP 0.0.0.0.68 > 255.255.255.255.67: DHCP-REQUEST
# ACK:服务器最终确认
IP DHCP服务器.67 > 255.255.255.255.68: DHCP-ACK

缺了哪一步就查哪一步。没有OFFER =网络里没有DHCP服务器(或者说DHCP中继没配)。有OFFER没ACK=IP冲突或服务器拒绝了。

flowchart LR subgraph 板子 A[DHCP Client] end subgraph 网络 B[DHCP Server] end A -->|1. DISCOVER 广播| B B -->|2. OFFER 单播/广播| A A -->|3. REQUEST 广播| B B -->|4. ACK 确认| A C{哪个阶段断了} --> C1[无DISCOVER: 网口没UP] C --> C2[无OFFER: 没有DHCP服务器] C --> C3[无ACK: IP冲突或服务器拒绝]

几个嵌入式场景下的tcpdump骚操作

场景:Flash空间只剩2MB

bash 复制代码
# 不要-i eth0全量抓,先指定过滤条件缩小
# 抓完用-W限制文件大小,-C做轮转

tcpdump -i eth0 -n -C 10 -W 5 -w /tmp/capture.pcap 'host 目标IP'
# 最多5个文件,每个10MB,循环覆盖
# 抓完了scp拿下来慢慢分析

场景:分析之前抓的包

bash 复制代码
# 不在板子上看,把pcap拉回PC用Wireshark
# 或者在板子上离线读取
tcpdump -r /tmp/capture.pcap -n

场景:板子没屏幕没键盘

bash 复制代码
# 开机自动抓包,出问题后分析
# 加到/etc/init.d/rcS里
tcpdump -i eth0 -C 5 -W 10 -w /tmp/netlog.pcap 'not port 22' &
# 排除SSH端口避免把自己抓进去

总结

嵌入式网络调试,顺序应该是:

看灯 → 抓包 → 看代码

先物理层,再链路层,再网络层,最后才是应用层代码。大多数时候,tcpdump在第二三步就把问题解决了,根本不需要改代码。

我见过太多人一上来就翻代码、加log、反复编译烧录------折腾半天发现是IP配错了或者网线松了。工具先上,脑子后用。

课后练习

  1. 你的板子ping不通外网,arp回复有,默认网关能ping通------怎么排查?
  2. 板子上跑HTTP服务器,客户端connect一直超时,tcpdump看不到任何SYN包到板子------问题可能在哪?
  3. 嵌入式4G模块上网,偶尔断连。怎么用tcpdump抓完整网络日志又不占太多Flash?

答案我就不写了,自己抓两把包就全明白了。

相关推荐
巴啦啦小魔仙变身2 小时前
SIGINT = Signal Interrupte
linux·服务器·python
RisunJan2 小时前
Linux命令-route(查看/修改 IP 路由表)
linux·运维
凉、介3 小时前
Linux 设备驱动匹配机制
linux·笔记·单片机·学习·操作系统·嵌入式
卵男(章鱼)3 小时前
第4章:软件架构与SOA
linux·车载系统·汽车
是摆烂第一名呀3 小时前
【RK3506】RGB屏幕与背光调试记录
linux·arm开发·驱动开发·嵌入式硬件
qetfw3 小时前
CentOS 7 搭建 DNS 主从服务
linux·运维·centos·dns·bind
JustNow_Man4 小时前
【Claude Code】 中给 Python + XML 项目建立可靠验证体系
xml·linux·python
CodeStats4 小时前
【Linux IO】从文件描述符到硬件中断:Linux IO 系统底层完全拆解
java·linux·开发语言·io·socket