简介:小兵以太网测试工具(XB Ethernet Tester)master 版完整源码包,面向需要检测和评估以太网性能的网络管理员、运维工程师及网络协议开发者。该工具遵循 IEEE 802.3 标准,涵盖吞吐量、丢包率、延迟、错误检测与压力测试等核心功能,可在 Linux 与 Windows 环境下编译运行,适合在服务器和网络设备环境中开展链路质量排查与性能调优。源码包共 69 个文件,包含 25 个 C 源文件、14 个头文件、3 个 Makefile 与 1 个 mk 规则文件,以及 ico 图标资源、txt 说明文档、Windows 下的安装包(WinPcap 驱动)等辅助内容,整体压缩后约 1021KB,目录结构清晰,便于按模块阅读和二次开发。已有 546 人学习下载。通过研读源码,读者可以理解从数据包捕获、网络层收发到统计界面展示的完整实现思路,也能依据测试结果定位网络瓶颈、优化参数配置,是学习以太网测试工具设计与 Linux 网络编程的实用参考。
1. 小兵以太网测试工具:以太网调试需求下的第一手工具
做嵌入式网络调试的兄弟都有这种经历:板子上的以太网接口灯狂闪,就是 ping 不通;W5500 模块按手册初始化了,数据就是发不出去;ZYNQ 上跑的 UDP 测试程序,一到高帧率就丢包。这种问题靠抓瞎解决不了,你需要一个能自己发包、自己抓包、自己统计吞吐的工具。小兵以太网测试工具(xb-ether-tester)就是干这个的,它把以太网接口测试里最常用的抓包、构造报文、吞吐统计三件事做成了命令行工具,适合在嵌入式板卡、车载以太网节点和工控设备上做快速验证。它能解决的问题很具体:物理链路通不通、以太网协议栈收发是否符合预期、接口吞吐边界在哪。适合三类人:被板卡网络问题折磨的嵌入式工程师、做网络设备功能测试的验证工程师、要在产线做以太网接口自检的制造岗位。
2. 部署与启动:先摸清工具包的组成与环境依赖
2.1 工具包的目录结构与工作原理
拿到压缩包解压之后,第一件事不是急着 make,而是先看目录结构。我见过很多以太网调试工具是单文件脚本,跑起来简单,但没法扩展。小兵工具把抓包、发包、统计三个动作分离成独立模块,这一点在实际调试里很有用。
xb-ether-tester-master/ ├── Makefile ├── README.md ├── src/ │ ├── main.c # 命令行入口与参数解析 │ ├── capture.c # 抓包线程,基于 libpcap │ ├── inject.c # 发包通道,基于原始套接字 │ ├── stats.c # 帧计数、吞吐与丢包统计 │ └── util.c # 以太网帧构造、CRC 计算等公共函数 ├── scripts/ │ ├── eth_loop_test.sh # 回环测试脚本 │ └── csv_report.py # 统计结果导出 CSV └── doc/ └── usage.md # 命令行参数说明从构建层面看,这个工具的核心设计是抓发分离。capture.c 挂在 libpcap 上,负责从网卡把流经的以太网帧抄一份到用户态;inject.c 走 AF_PACKET 原始套接字,自己拼 MAC 头、VLAN 头和数据载荷,再交给驱动。抓发通道独立最大的好处是:你可以一边发一个带错误 CRC 的帧,一边抓包确认对端到底收没收到、有没有回包。两个通道互不干扰,比 tcpdump 加 ping 的组合要顺手得多。
选型上,libpcap 是 Linux 抓包的事实标准,tcpdump、Wireshark 底层都走它,所以过滤语法可以沿用 BPF 表达式,不需要重新学。发包用原始套接字而不是 libpcap 的 pcap_inject,是因为原始套接字可以直接控制二层头,也能绕过协议栈的校验,方便构造坏帧。如果你之前用过 Scapy,上手会非常快;但 Scapy 装机重、起 Python 解释器慢,在板卡环境里不如这个工具轻量。它不是追求协议完备的大而全工具,而是把精力集中在调试现场最常用的几类动作上:指定网口、指定帧长、指定发包间隔、指定过滤条件,然后看统计输出。它更像一把扳手,不是一套工具箱。
2.2 编译安装:依赖检查与 Makefile 参数
编译之前先把依赖装好。这个工具在 Linux 下依赖 libpcap 和 libnl-3,前者做抓包,后者用来读取和配置网卡状态。Debian/Ubuntu 系统下执行:
sudo apt-get update sudo apt-get install -y build-essential libpcap-dev libnl-3-dev tar -xzf xb-ether-tester-master.tar.gz cd xb-ether-tester-master make sudo make install依赖装好不代表一定能编过。我遇到过 libnl-3 版本不匹配导致编译报错的情况。新版系统里 libnl-3-dev 通常默认安装,但在老版本 Ubuntu 或 CentOS 上跑,建议先执行 pkg-config --modversion libnl-3.0 确认版本在 3.2 以上。CentOS 下包名是 libnl3-devel,安装命令是 yum install -y libnl3-devel。如果你看到 fatal error: netlink/netlink.h: No such file or directory,就是这个依赖没装,别怀疑是源码有问题。
make 完成后,可执行文件生成在源码根目录下的 xb-ether-tester。安装脚本默认把二进制放到 /usr/local/bin,如果你不想全局安装,直接用 ./xb-ether-tester 跑就行,工具不依赖运行时安装位置。抓包和原始发包都需要 root 权限,所以运行时记得加 sudo,或者给二进制加 capabilities。我一般用 sudo setcap cap_net_raw,cap_net_admin=eip /usr/local/bin/xb-ether-tester,这样在开发机上不用每次输 sudo,测试脚本里被权限卡住的概率小很多。
如果你的目标平台是 ARM 板卡,小兵工具也支持交叉编译。先把 libpcap 和 libnl-3 的交叉编译版本装进工具链的 sysroot,然后在 Makefile 里指定编译器:
sudo apt-get install -y gcc-aarch64-linux-gnu make CROSS_COMPILE=aarch64-linux-gnu-交叉编译完的可执行文件要放到板子上跑,注意板子的网卡驱动必须支持 AF_PACKET 套接字和 ethtool 的链路状态读取。老一点的 FPGA 网卡驱动可能只做了收发路径,没有实现 ethtool 的链路状态查询,工具启动时读取网卡状态会失败,这不是编译问题,后面避坑章节再细说。
2.3 最小可用性验证:回环接口自测
编译完成后不要急着上板子,先用回环接口自测一把。回环接口(lo)不带以太网头,但可以验证工具的命令行解析、发包线程和统计模块是否正常。
sudo ./xb-ether-tester -i lo -m loopback -c 100 -s 64 -r 1000这条命令的意思是:在 lo 接口上发送 100 帧,帧长 64 字节,发送速率限制在 1000 帧/秒。工具在发送结束后会打印总发送帧数、接收帧数、丢包率和平均时延。回环接口下如果收帧数跟发帧数相等,说明整个链路跑通了。
参数说明:-i 指定网络接口,-m 指定模式,loopback 模式是发完就收、统计同一接口的帧;-c 控制总帧数,第一次跑建议设小一点,比如 100,确认流程没问题再拉大到几万帧;-s 是帧长,64 字节是以太网最小帧长;-r 是发包率,单位是帧/秒,用来模拟不同压力场景。如果你在板子上跑回环模式要谨慎,有些嵌入式网卡驱动不把发出的帧送到接收路径,收帧数会显示 0,这并不代表工具坏了,得先排除驱动行为。
回环验证通过后再接真网口测。以 ZYNQ 板子为例,把网线直连 PC,两边配同一网段的静态 IP,用小兵工具在 PC 上抓板子发出来的 UDP 报文,同时用板子上的测试程序发 1000 帧,PC 侧抓到的帧数和板子发送的帧数一致,基本就能确认物理链路和驱动收发路径正常。
3. 核心功能与参数拆解:抓包、构包与吞吐
3.1 抓包模式:BPF 过滤器与混杂模式
抓包是这个小工具最常用的功能。它的抓包模块支持标准 BPF(Berkeley Packet Filter)语法,可以像用 tcpdump 一样精确控制抓取范围。
sudo ./xb-ether-tester -i eth0 -m capture -f "vlan 100 and tcp port 502" -t 30这条命令在 eth0 上抓 30 秒,只抓打了 VLAN 标签 100、且 TCP 端口为 502 的帧。502 是 Modbus TCP 的默认端口,在工控以太网调试里特别常见。如果你在车载以太网场景下抓 SOME/IP 流量,把过滤器改成 -f "udp port 30490" 就行。过滤器语法和 tcpdump 一致,host、net、ether host 这些关键字都支持。
抓包模式默认不把网卡设为混杂模式,只抓发往本机或广播的帧。要抓局域网里其他设备的帧,必须加 -p 打开混杂模式,同时确认交换机端口没有做端口隔离。我见过这样的翻车现场:工程师在实验室用工具抓不到对端流量,先怀疑工具坏了,最后发现是交换机端口做了隔离,加 -p 也没用。所以抓包之前,先看网卡状态是不是 UP,再用 ethtool -p eth0 亮灯确认物理连线对得上。
提示:抓包模式下即使不加过滤器,也不建议长时间全量抓帧,尤其是千兆口。用户态抓包在高速率下会丢帧,统计结果偏小,这不是工具 bug,是 libpcap 的通用瓶颈。要测千兆线速,得依赖网卡硬件时间戳和内核绕开拷贝,这超出了小兵工具的设计范围。
3.2 构造报文:帧头、VLAN 与 CRC 的处理
构造报文是测试刚需。调试中要么需要发标准帧验证对端能正常收,要么需要故意发坏帧看对端协议栈怎么反应。inject 模块提供了几个很实际的参数。
sudo ./xb-ether-tester -i eth0 -m inject -d aa:bb:cc:dd:ee:ff \ -s 128 -c 1000 -r 2000 --vlan 200 --crc-error这条命令构造 1000 个 128 字节的以太网帧,目的 MAC 设为 aa:bb:cc:dd:ee:ff,以 2000 帧/秒连续发送,打上 VLAN 标签 200,并且故意不计算正确 CRC,让每个帧的校验字段是错的。
参数逻辑值得展开。目的 MAC 用 -d 指定,发广播就填 ff:ff:ff:ff:ff:ff;源 MAC 默认取网卡 MAC,一般不要改,除非要测交换机的 MAC 学习功能。帧长参数 -s 包含以太网头部在内的整帧长度,不含前导码和 SFD,这一点和 Wireshark 的帧长显示一致。64 字节以下的小帧要注意:以太网规范要求 64 字节是最小帧长,如果数据部分不够 46 字节,工具会自动做 padding,并在统计里标记填充字段。有些 FPGA 的 MAC 控制器不识别带 padding 的非标准帧,这种情况建议把帧长发成 68 字节以上,避开填充边界。
CRC 的处理是小工具做得比较细的地方。默认自动计算 CRC32 并填到帧尾,加 --crc-error 后故意写一个错误的 CRC。对端网卡会直接丢掉这种帧,但如果你在对端抓包,能看到这个帧被标记为 bad checksum。这个功能在排查对端为什么收不到时特别有用:先发坏 CRC 帧,确认抓包能看到坏帧,再发正确帧,如果对端还是没反应,问题就不在链路上而在对端协议栈。
3.3 吞吐测试:速率统计与判定边界
吞吐测试最怕看起来很高、实际不对。小兵工具的吞吐模式可以理解成一台简化版打流仪。它支持单向和双向两种测试,单向适合验证链路带宽上限,双向适合验证交换机转发能力。
sudo ./xb-ether-tester -i eth0 -m throughput --direction tx \ -s 1518 -t 60 --rate-limit 1000000这条命令在 eth0 上以 1000000 帧/秒的速率上限发 60 秒测试帧,每帧长度 1518 字节,统计发送和接收侧的帧数差。要测对端接收能力,把 --direction 改成 rx,工具会静默收包并统计每秒收到的帧数和字节数。
吞吐统计里最容易误读的是丢包率判定。工具给出的丢包率等于发送帧数减接收帧数再除以发送帧数,但前提是测试帧的目的 MAC 指向本机,且对端回环路径被正确配置。如果你把测试帧发到一个不存在的 MAC,对端网卡根本不会收,丢包率会显示 100%,这不代表链路有问题。所以单向吞吐测试时,我一般会在对端起一个小兵工具收包,两边统计对齐后才有参考价值。
关键换算:--rate-limit 的单位是帧/秒。带宽等于帧长(含 8 字节前导码和 12 字节帧间隙)乘以帧率。1518 字节的帧加上 20 字节额外开销,单帧占用 1538 字节,1000000 帧/秒理论值是 1.538 GB/s,超过千兆口能力。测千兆口时 --rate-limit 超过 812743 帧/秒没有意义,工具会显示线路速率封顶。理解了这层换算,就知道为什么同样工具在不同帧长下测出的带宽不同:64 字节小帧能达到的帧率远超 1518 字节大帧,但有效吞吐反而低,因为开销占比大。
4. 避坑指南:以太网测试中高频故障与排查记录
4.1 抓不到包:混杂模式没开对
现象:把测试仪接到交换机镜像口,拿小兵工具在 PC 上抓包,结果只有广播帧,没有目标设备的单播帧。
原因:镜像口通常把流量复制过来,但 PC 网卡必须工作在混杂模式,否则驱动会把目的 MAC 不是本机的帧直接丢掉,libpcap 根本拿不到。只加 -p 参数还不够,有些 USB 转以太网或平板网卡驱动对混杂模式支持不完整,驱动层面就把非本机帧过滤了。
解决:先用 ifconfig eth0 up 确认网卡状态,再执行 sudo ./xb-ether-tester -i eth0 -m capture -p。还不行就查网卡驱动是否支持 RXALL 标志,用 ethtool -k eth0 看 rx-all,显示 off 则执行 sudo ethtool -K eth0 rx-all on。这招对大多数 PCIe 网卡有效,但对 RTL8152 这类 USB 网卡有时候仍拿不到完整镜像流量,建议直接换一块 PCIe 千兆网卡。血泪经验:在实验室常备三块不同芯片的 PCIe 网卡,能节约半天定位时间。
4.2 发送报文对端不收:CRC 与最小帧长
现象:用小兵工具构造了 64 字节的 UDP 帧发给 ARM 板,板子没反应,但用 Wireshark 在板子另一个口抓包能看到这个帧。
原因:多半是之前的测试没有退出坏 CRC 模式,或者脚本里把 CRC 手工改过,工具继续发错误 CRC 的帧,对端网卡直接丢弃。另外 64 字节最小帧长是指整个二层帧,15 字节 UDP 载荷加上 14 字节以太网头、20 字节 IP 头、8 字节 UDP 头一共 57 字节,工具自动补了 pad,但有些 FPGA MAC 控制器不识别这种帧。
解决:先确认命令里没有 --crc-error,再抓包看帧尾 4 字节是不是正确 CRC 值。再查对端 MAC 控制器的接收帧长设置,部分 FPGA 工程默认只收 64 到 1518 字节的帧,把接收长度下限改小,或把测试帧长度设为 68 字节以上。这一步最容易踩的坑是把问题归结到工具,其实是构造的帧不符合对端预期。
4.3 吞吐量上不去:中断合并与驱动参数
现象:千兆网卡直连对端,工具测出来只有 300 Mbps,iperf 也只能跑到 400 Mbps。
原因:CPU 频率不够或中断处理不过来。小兵工具的吞吐模式是单线程读包加统计,如果网卡中断合并做得差,驱动每收一帧触发一次中断,中断开销吃掉大量 CPU。测试机 CPU 主频只有 1.2GHz 时,小包打到 400 Mbps 后丢包率直线上升。
解决:先把 CPU 频率调成 performance 模式,再用 ethtool -C eth0 rx-usecs 1 把中断合并时延改小,亲测能让小包吞吐提升 20% 到 30%。还不行就确认网卡多队列,执行 sudo ethtool -L eth0 combined 4 开启 4 个队列,同时用 taskset 把工具绑定到单独 CPU 核。这套组合在 x86 平台几乎每次都能见效,但在 ARM 板卡上受限于板级功耗策略,效果会打折,建议同步检查板子的散热和 CPU 调频策略。
4.4 时间戳漂移:软件时间戳与硬件时间戳的取舍
现象:双向吞吐测试时,两边统计的时延不一致,同一帧从 A 到 B 测出 20 微秒,从 B 到 A 测出 200 微秒,量级都对不上。
原因:工具默认用接收侧软件时间戳减去发送侧时间戳。软件时间戳是网卡驱动在中断上下文里记的,受系统调度和中断繁忙程度影响很大。嵌入式板子上开了 NFS 或高频率定时器后,中断延迟能拉高几十到几百微秒,误差已经接近被测时延本身。
解决:不要用软件时间戳评估微秒级时延。网卡支持硬件时间戳的话,用 ethtool -T eth0 能看到 hardware receive timestamps,启动参数加 --hw-timestamp 切换为硬件时间戳。硬件时间戳只对支持打戳的帧生效,PTP 报文最准,普通 UDP 帧部分网卡也支持。如果对端不支持,测试结论改成对比统计而不是绝对时延。另外,把所有时延测试放在同一个网段、关闭交换机绿色节能模式,能减少一层不确定性。
4.5 长时间测试内存不停涨:统计缓存没有收敛
现象:跑百万帧的大压力吞吐测试,工具 RSS 内存占用持续上升,跑 10 分钟不降。
原因:工具的统计模块对每个源 MAC 和目的 MAC 组合维护一个计数器链表,测试帧的源 MAC 或目的 MAC 变化太多时,链表不断增长又不回收,内存峰值跟帧数成正比。用随机 MAC 地址连续跑大流量测试,特别容易触发。
解决:统计前先加过滤条件,尽量让源 MAC 和目的 MAC 的基数收敛。比如 -f "ether dst aa:bb:cc:dd:ee:ff" 只统计发往固定目的 MAC 的帧。如果一定要用随机 MAC 测交换机的地址老化,建议把 -t 时长分成多段,每段结束后重启进程写一次结果。从那次以后,我每次做长时间压力测试前,都会先确认统计键值空间是有限的,避免测试跑到一半内存翻车。
5. 进阶:把测试过程脚本化,做可重复的回归验证
吞吐和时延测试不能每次手工敲命令,尤其是产线自检和版本回归,必须保证任何人、任何时候用同一套参数跑出同一套数据。我的习惯是把常用测试场景写成脚本,跑完自动出 CSV,再用 CSV 做判定。
#!/bin/bash # 简化版回归脚本:三种典型帧长各测 10 秒 IFACE=${1:-eth0} OUTFILE=${2:-result.csv} echo "interface,frame_len,frame_rate,tx_frames,rx_frames,loss_rate" > $OUTFILE for len in 64 128 512 1518; do sudo ./xb-ether-tester -i $IFACE -m throughput --direction tx \ -s $len -t 10 --rate-limit 100000 > /tmp/test.log tx=$(grep "tx_frames" /tmp/test.log | awk -F: '{print $2}') rx=$(grep "rx_frames" /tmp/test.log | awk -F: '{print $2}') loss=$(awk -v tx=$tx -v rx=$rx 'BEGIN {printf "%.2f", (tx-rx)/tx*100}') echo "$IFACE,$len,100000,$tx,$rx,$loss" >> $OUTFILE done python3 scripts/csv_report.py $OUTFILE这段脚本干了三件事:循环三种典型帧长各跑 10 秒、从日志里抽收发帧数、算丢包率并写成 CSV。我一般再把 csv_report.py 扩展成自动对比历史数据,同一帧长的丢包率超过上次结果 1% 时标红。变量 IFACE 和 OUTFILE 抽成参数后,不同测试工位只要改接口名就能复用这个脚本,不用每台机器手工维护命令。
真正让我养成这个习惯的是一次乌龙。我手工在某个版本上测吞吐,数据发给一台新的 ARM 板,发现丢包率明显偏高,反复调网卡参数都没改善,最后跑回归脚本对比才发现是上一个版本的驱动没有同步更新,根本不是工具或参数的问题。如果没有历史 CSV,我可能还在调工具参数,时间就白费了。从那以后,我每次拿到新板卡或者改完驱动,都强制走一遍脚本化测试流程。脚本的价值不在于省几分钟,而在于能确认之前是好的,当问题出现时,能正面回答:哪次改动引入了退化,哪一层行为发生了变化。希望帮到你。
本文还有配套的精品资源,点击获取