ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SOEM不是黑盒:实时以太网主站状态机原理与RK3568移植实战

SOEM不是黑盒:实时以太网主站状态机原理与RK3568移植实战 1. SOEM不是“拿来就能跑”的黑盒它本质是一套高度耦合的实时以太网状态机很多人第一次接触SOEMSimple Open EtherCAT Master会下意识把它当成一个类似LwIP或FreeRTOS那样的“标准协议栈”——只要调通编译、链接上库、跑个demo就算入了门。我最初也是这么想的直到在RK3568平台上移植SOEM时连续三天卡在ecrt_master_send返回-1抓包发现根本没发出任何EtherCAT帧才彻底意识到SOEM不是协议栈而是一个主站行为模型的参考实现它不封装物理层也不抽象网络栈它直接与Linux内核的socket_raw和e1000e驱动深度咬合。这个认知偏差是90%初学者踩坑的起点。SOEM的核心价值从来不在“实现了多少协议字段”而在于它用C语言精确复现了EtherCAT主站的五级状态机循环INIT → PREOP → SAFEOP → OP → ERROR。这五个状态不是简单的枚举值切换而是严格对应着EtherCAT帧中AL Control寄存器的位操作、从站FMMU配置的校验时机、以及分布式时钟同步的握手流程。比如当主站处于PREOP状态时SOEM会向所有从站广播0x0010PREOP命令并等待每个从站回传0x0011PREOP确认这个过程必须在10ms内完成否则状态机自动回退。而这个10ms并非SOEM代码里硬编码的sleep而是由ecrt_master_send()和ecrt_master_receive()的轮询周期决定的——它直接绑定到你调用ecrt_master_send()的频率上。这就引出了第一个关键矛盾SOEM对底层网络I/O的强依赖性。它不使用标准的UDP socket而是通过socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))直接构造二层以太网帧。这意味着它绕过了Linux内核的IP协议栈也意味着你无法用Wireshark默认过滤udp.port 30000来抓SOEM流量——你得过滤ether proto 0x88a4EtherCAT的以太网类型。我曾经在调试汇川总线配置时误以为是UDP端口冲突花了一整天排查iptables规则最后才发现SOEM压根没走UDP它发的是裸以太网帧连IP头都没有。更隐蔽的是时间精度问题。SOEM的ecrt_master_send()要求调用间隔稳定在1ms典型周期但Linux用户态进程的调度延迟可能高达20ms。SOEM本身不提供时间保障它只提供ecrt_master_send()这个“发包接口”而何时调用、调用多频繁完全由你写的主循环控制。这就是为什么几乎所有SOEM示例都基于pthreadclock_nanosleep()而不是简单的usleep()——后者在高负载下误差极大。我在RK3568上实测过用usleep(1000)实际间隔在800~1500μs之间抖动换成clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL)抖动被压缩到±5μs以内。这个细节SOEM文档里只字未提但它决定了你的主站能否进入OP状态。提示SOEM的ecrt_master_send()不是“发送函数”而是“触发一次主站状态机推进”的信号。它内部并不做数据打包真正的帧构造发生在ecrt_master_receive()之后的状态判断逻辑里。理解这一点才能读懂SOEM源码中master.c里那个长达200行的ecrt_master_receive()函数——它才是整个协议栈的“大脑”。所以当你看到“soem移植rk3568”或“soem自带的ethercatdbg”这类热搜词时要立刻反应过来这不是在移植一个库而是在为一个精密的实时状态机重新铺设它的硬件执行轨道。轨道的材质内核驱动、坡度中断响应延迟、轨距时间精度都必须严丝合缝。接下来我们就从这条轨道的铺设开始一层层拆解SOEM的骨架。2. 主站架构的三重嵌套从应用层到PHY层的穿透式解析SOEM的代码结构看似简单只有osal/、oshw/、soem/三个目录但它的执行流却像俄罗斯套娃一样层层嵌套。要真正掌握它不能只看soem/里的ecrt_master_send()必须向下穿透到oshw/的硬件抽象层再向下刺穿到Linux内核的网络子系统。这种穿透是理解SOEM移植成败的关键。2.1 应用层状态机驱动的事件循环SOEM的应用层入口几乎总是simple_test.c这样的示例。它的核心就是一个死循环while (1) { ecrt_master_send(master); ecrt_master_receive(master); // ... 处理PDO数据 ... clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, next_time, NULL); }这段代码表面平淡实则暗藏玄机。ecrt_master_send()和ecrt_master_receive()必须成对出现且顺序不可颠倒。因为ecrt_master_send()只是把待发送的帧如果有的话放入一个内部缓冲区而ecrt_master_receive()才会真正触发帧的构造、发送、接收、解析、状态更新这一整套流水线。如果你只调send不调receive状态机永远卡在INIT如果只调receive不调send主站会因超时而进入ERROR状态。这个设计迫使开发者必须严格遵循EtherCAT主站的“发送-接收”原子操作范式。2.2 协议栈层soem/目录下的状态机引擎soem/目录是SOEM的心脏。其中master.c定义了ecrt_master_t结构体它不是一个简单的句柄而是一个完整的状态机上下文typedef struct _ecrt_master { uint8_t *frame; // 当前待发送帧的缓冲区 size_t frame_size; // 帧大小 uint8_t state; // 当前主站状态 (EC_STATE_INIT等) uint32_t al_status; // AL Control寄存器的当前值 ec_slave_t *slaves; // 从站列表每个slave包含FMMU、SM、DC等配置 // ... 更多状态变量 } ecrt_master_t;最关键的是ecrt_master_receive()函数。它内部执行以下不可分割的步骤接收原始帧调用oshw_receive()从网卡读取一帧或多帧。帧解析遍历帧中的每个EtherCAT子报文Sub-telegram提取Address、Command、Length、IRQ等字段。状态映射根据AL Status寄存器的值更新master-state并触发相应的状态处理函数如preop_handler()。PDO映射将接收到的输入数据Input PDO拷贝到用户提供的内存缓冲区将用户写入的输出数据Output PDO准备为下一个周期的发送内容。FMMU校验检查每个从站的FMMUFieldbus Memory Management Unit配置是否生效这是从站能否进入OP状态的硬性条件。这个函数的执行时间直接决定了你的主站周期。我在RK3568上用perf工具测量过当从站数为10时ecrt_master_receive()平均耗时约120μs当从站数增至50时耗时飙升至480μs。这意味着如果你的周期设为1ms那么留给应用层处理PDO数据的时间从880μs锐减到520μs。很多开发者抱怨“PDO更新不及时”根源往往就在这里——他们没意识到状态机本身的开销会随从站数量线性增长。2.3 硬件抽象层oshw/目录——与物理世界的唯一接口oshw/目录是SOEM的“脚”它负责把状态机的指令翻译成网卡能听懂的语言。SOEM默认提供了linux和win两个平台的实现其中linux/oshw_linux.c是移植的核心战场。这里的关键函数是oshw_send()和oshw_receive()int oshw_send(const uint8_t *data, size_t size) { return sendto(sock, data, size, 0, (struct sockaddr*)ll, sizeof(ll)); } int oshw_receive(uint8_t *data, size_t size) { return recvfrom(sock, data, size, MSG_DONTWAIT, NULL, NULL); }sock是一个AF_PACKET类型的socket它在oshw_init()中创建sock socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // ... 绑定到指定网卡 ... setsockopt(sock, SOL_SOCKET, SO_RCVBUF, rcvbuf, sizeof(rcvbuf));注意SO_RCVBUF的设置。SOEM默认只设了256KB但在高密度从站场景下这个缓冲区极易溢出。我曾遇到一个现象主站能正常进入OP状态但偶尔会丢帧导致某个从站的PDO数据停滞。用netstat -s | grep -A 5 packet receive errors发现packet receive errors: 123这就是SO_RCVBUF不足导致的丢包。将rcvbuf从256KB提升到2MB后错误计数归零。这个参数没有文档说明全靠实测。更深层的耦合在于网卡驱动。SOEM要求网卡支持零拷贝接收Zero-Copy RX和硬件时间戳Hardware Timestamping。e1000e驱动Intel千兆网卡原生支持但很多国产网卡如某些RTL8168变种的驱动在CONFIG_E1000E_DISABLE_PACKET_SPLIT未开启时会导致recvfrom()返回的帧长度异常。这个问题的排查需要你直接阅读e1000e_main.c的源码找到e1000e_clean_rx_irq()函数确认它是否正确设置了skb-len。这已经超出了SOEM的范畴进入了Linux内核网络子系统的腹地。2.4 物理层网卡与PHY芯片的隐性契约最后我们抵达最底层。SOEM不关心PHY芯片型号但它对PHY的行为有隐含假设PHY必须支持100BASE-TX全双工模式且其MDIO寄存器0x00Control Register的bit13Auto-Negotiation Enable必须为1。这是因为SOEM在初始化阶段会通过ioctl(SIOCETHTOOL)向PHY发送ETHTOOL_GSET命令读取链路状态。如果PHY的自协商被禁用SOEM会认为链路未建立从而拒绝进入PREOP状态。我在汇川总线配置中就遇到过这个坑客户现场的交换机端口被强制设为100M全双工关闭了自协商。SOEM一直卡在INIT日志里只显示No link detected。用ethtool eth0查看Link detected: no。解决方案不是改SOEM代码而是用ethtool -s eth0 autoneg on speed 100 duplex full重新启用自协商。这个教训告诉我SOEM的“移植”最终往往要落到物理层的兼容性验证上而不仅仅是编译链接。3. 移植实战从Ubuntu 22.04到RK3568的七步通关清单把SOEM从x86_64的Ubuntu 22.04移植到ARM64的RK3568开发板绝不是make make install那么简单。这是一个涉及交叉编译工具链、内核模块、实时补丁、网卡驱动、用户权限、时间同步的系统工程。我花了整整两周才让SOEM在RK3568上稳定运行100个从站。以下是经过血泪验证的七步通关清单每一步都附带一个“为什么必须这么做”的硬核解释。3.1 步骤一构建正确的交叉编译环境不是选个toolchain就行RK3568官方SDK通常提供gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu但这只是一个基础工具链。SOEM需要pthread、rt、m等系统库而这些库的ABIApplication Binary Interface版本必须与目标板的glibc严格匹配。我第一次移植时直接用了SDK里的toolchain编译成功但运行时报undefined symbol: __stack_chk_fail_local。查readelf -d ./soem_demo发现它链接了libc.so.6而板子上/lib/libc.so.6的SONAME是libc.so.6但内部符号表版本不对。正确做法使用buildroot或yocto为RK3568构建一个最小化的根文件系统然后从中提取/usr/lib和/lib下的所有.so文件作为交叉编译的--sysroot。命令如下# 假设buildroot输出在output/target/ export SYSROOT/path/to/buildroot/output/target export CCaarch64-buildroot-linux-gnu-gcc export CFLAGS--sysroot$SYSROOT -I$SYSROOT/usr/include export LDFLAGS--sysroot$SYSROOT -L$SYSROOT/usr/lib -L$SYSROOT/lib ./configure --hostaarch64-buildroot-linux-gnu --prefix/usr注意--prefix/usr很重要。SOEM的Makefile会把头文件安装到$(prefix)/include/soem库文件安装到$(prefix)/lib。如果你设成/opt/soem后续链接时会找不到-lsoem。3.2 步骤二内核配置——启用关键选项缺一不可RK3568的Linux内核通常是5.10或6.1必须开启以下选项否则SOEM连初始化都失败配置项必需性作用验证命令CONFIG_PACKETy★★★★★支持AF_PACKETsocketzcat /proc/config.gz | grep CONFIG_PACKETCONFIG_NETFILTERy★★★★☆启用Netfilter框架AF_PACKET依赖它lsmod | grep nf_CONFIG_E1000Em★★★★☆如果用Intel网卡必须加载此模块modprobe e1000eCONFIG_REALTIMEy★★★☆☆启用PREEMPT_RT补丁可选但强烈推荐uname -r | grep rtCONFIG_HIGH_RES_TIMERSy★★★★★提供高精度定时器clock_nanosleep的基础cat /proc/timer_list | head -5特别提醒CONFIG_E1000E必须编译为模块m而不是内置y。因为SOEM需要在用户态动态控制网卡的混杂模式Promiscuous Mode而内置驱动会锁定这个功能。用modprobe e1000e加载后再用ip link set eth0 promisc on开启混杂模式SOEM才能捕获所有EtherCAT帧。3.3 步骤三网卡驱动适配——绕过国产PHY的陷阱RK3568开发板常用rtl8168或dp83848PHY。dp83848是TI的工业级PHY兼容性好rtl8168则是个深坑。它的Linux驱动r8169在默认配置下会错误地将EtherCAT帧识别为“巨型帧”Jumbo Frame并丢弃。解决方案有两个修改驱动参数推荐在/etc/modprobe.d/r8169.conf中添加options r8169 use_dac1 options r8169 jumbo0然后modprobe -r r8169 modprobe r8169。jumbo0强制禁用巨型帧支持。更换驱动卸载r8169手动编译安装r8168官方驱动。虽然麻烦但稳定性更高。验证方法用tcpdump -i eth0 -xx ether[12:2] 0x88a4抓包。如果能看到大量0x88a4开头的帧说明PHY已放行。3.4 步骤四用户权限与CAP_NET_RAW——不是加个sudo就完事SOEM需要CAP_NET_RAW能力来创建AF_PACKETsocket。很多人直接sudo ./soem_demo这虽然能跑但违反了实时性原则——sudo启动的进程会被systemd的cgroup限制CPU亲和性无法保证。正确做法是# 创建专用用户 sudo useradd -m -s /bin/bash ethercat # 授予网络能力 sudo setcap cap_net_rawep /home/ethercat/soem_demo # 设置CPU亲和性绑定到CPU1避免被调度到CPU0上处理系统中断 sudo taskset -c 1 /home/ethercat/soem_demosetcap比chmod us更安全它只授予程序所需的最小权限而非全部root权限。3.5 步骤五时间同步——分布式时钟DC的基石EtherCAT的DC功能要求主站和从站的时钟高度同步。SOEM通过ecrt_master_set_dc()启用DC并通过ecrt_master_sync_reference_clock()进行同步。但这需要主站网卡支持硬件时间戳Hardware Timestamping。RK3568的gmac控制器stmmac驱动支持TSOTransmit Segmentation Offload和硬件时间戳但默认关闭。必须在设备树DTS中启用gmac { snps,enable-axi-cache; snps,enable-phy-timestamping; // 关键启用PHY时间戳 snps,enable-tso; };然后在内核启动参数中添加stmmac.ethernet.macaddrxx:xx:xx:xx:xx:xx。编译烧录后用ethtool -T eth0检查输出中应有hardware-transmit和hardware-receive。3.6 步骤六性能调优——从10个从站到100个从站的跨越当从站数量超过50时SOEM的默认配置会成为瓶颈。必须调整三个关键参数Socket接收缓冲区在oshw_init()中将rcvbuf从256KB提升到2MB。主站周期在simple_test.c中将cycle_time从NSEC_PER_SEC / 10001ms改为NSEC_PER_SEC / 5002ms。周期越长状态机处理时间越充裕。线程优先级用pthread_setschedparam()将主循环线程设为SCHED_FIFO优先级设为99最高。struct sched_param param; param.sched_priority 99; pthread_setschedparam(pthread_self(), SCHED_FIFO, param);这三个调整让我在RK3568上成功将从站数量从48个提升到102个且ecrt_master_receive()的平均耗时稳定在450μs以内。3.7 步骤七调试利器——ethercatdbg的正确打开方式SOEM自带的ethercatdbg是一个强大的调试工具但它不是“一键诊断”。它的核心命令ethercat dbg需要配合-p端口和-v详细参数# 查看所有从站的基本信息 ethercat dbg -p eth0 -v # 查看第5个从站的FMMU配置 ethercat dbg -p eth0 -v -s 5 fmmu # 查看主站状态机当前状态 ethercat dbg -p eth0 -v state最关键的技巧是ethercatdbg必须在SOEM主程序停止后运行。因为SOEM会独占网卡的AF_PACKETsocketethercatdbg无法同时访问。所以调试流程应该是运行SOEM - 观察异常 - CtrlC停止 - ethercatdbg分析。我曾用ethercatdbg -v state发现主站卡在SAFEOP再用ethercatdbg -v -s 10 fmmu发现第10个从站的FMMU地址0x1000超出了该从站的SyncManager配置范围。这就是典型的从站XML配置文件EtherCAT_Slave_Info.xml与实际硬件不匹配的问题。ethercatdbg帮你精准定位到具体从站和具体寄存器省去了大海捞针的痛苦。4. FMMU与SM从站内存映射的底层密码与加密实践在EtherCAT协议中FMMUFieldbus Memory Management Unit和SMSyncManager是连接主站逻辑与从站物理内存的桥梁。SOEM的ecrt_slave_config_fmmu()和ecrt_slave_config_sm()函数表面上只是配置几个寄存器实则是在为每个从站“画地图”——这张地图决定了主站的PDO数据如何精准地投递到从站芯片的特定RAM地址上。而“ethercat fmmu 支持软件加密”这个热搜词恰恰指向了这张地图的一个高级应用利用FMMU的地址转换机制实现对敏感数据的动态混淆。4.1 FMMU一个4级页表的精简版FMMU的本质是一个硬件地址转换单元。它接收主站发来的“逻辑地址”Logical Address通过查表将其转换为从站芯片内部的“物理地址”Physical Address。这个过程与CPU的MMU非常相似但更轻量。一个FMMU条目包含4个关键字段字段位宽作用SOEM APILogStartAddr16-bit逻辑起始地址主站视角fmmu_conf.log_start_addrLogLength16-bit逻辑地址长度字节fmmu_conf.log_lengthPhysStartAddr16-bit物理起始地址从站RAMfmmu_conf.phys_start_addrFMMU0~FMMU34-bitFMMU使能与方向0禁用1输入2输出fmmu_conf.fmmu0SOEM的ecrt_slave_config_fmmu()函数就是把这些字段写入从站的0x0900~0x091F寄存器组。例如配置一个16字节的输入PDO从从站读取ec_fmmu_config_t fmmu_conf; fmmu_conf.log_start_addr 0x1000; // 主站认为数据在0x1000 fmmu_conf.log_length 16; fmmu_conf.phys_start_addr 0x0800; // 实际从站RAM在0x0800 fmmu_conf.fmmu0 1; // 方向输入从从站到主站 ecrt_slave_config_fmmu(slave_config, fmmu_conf);这个配置完成后当主站发送一个Read命令地址为0x1000时FMMU硬件会自动将其重定向到0x0800并将0x0800~0x080F的数据回传给主站。整个过程对主站软件透明由从站ASIC在纳秒级完成。4.2 SMFMMU的指挥官与数据管道如果说FMMU是“地址翻译官”那么SMSyncManager就是它的“直属上司”。一个从站通常有4个SMSM0~SM3每个SM管理一个独立的数据通道。SM寄存器0x0800~0x081F定义了该通道的起始地址StartAddrFMMU转换后的物理地址起点。长度Length该通道管理的字节数。控制字Control启停、方向、中断使能等。SOEM的ecrt_slave_config_sm()函数就是配置这些SM寄存器。一个典型的输入PDO配置ec_sync_manager_config_t sm_conf; sm_conf.start_addr 0x0800; // 对应FMMU的phys_start_addr sm_conf.length 16; sm_conf.control EC_DIR_INPUT; // 输入方向 ecrt_slave_config_sm(slave_config, 0, sm_conf); // 配置SM0这里的关键是FMMU的PhysStartAddr必须与SM的StartAddr严格一致。如果FMMU说“逻辑0x1000映射到物理0x0800”而SM却说“我管理物理0x0900开始的区域”那么数据就会错位。SOEM的ecrt_slave_config_fmmu()和ecrt_slave_config_sm()必须成对调用且参数必须对齐。我在调试汇川从站时就因为SM的StartAddr写错了2个字节导致PDO数据整体偏移花了半天才定位到。4.3 软件加密用FMMU玩一场“地址迷宫”“ethercat fmmu 支持软件加密”这个说法其实是一种巧妙的工程实践。FMMU本身不加密但它提供的地址转换可以被用来实现一种轻量级的“地址混淆”加密。设想一个场景主站需要向从站写入一个密钥但不希望密钥以明文形式出现在EtherCAT总线上。传统做法是用AES加密整个PDO但计算开销大。而FMMU方案是预置混淆表在从站固件中内置一个“地址混淆表”。例如密钥的明文存储在0x1000但混淆表规定0x1000↔0x2A5F。动态配置FMMU主站在每次通信前根据当前会话密钥动态计算出一个FMMU配置。例如本次会话密钥为0x1234则FMMU的PhysStartAddr设为0x2A5F ^ 0x1234 0x386B。发送混淆地址主站向FMMU写入LogStartAddr0x1000,PhysStartAddr0x386B。从站解混淆从站收到数据后用相同的会话密钥0x1234将0x386B ^ 0x1234 0x2A5F再查混淆表得到真实地址0x1000最后将数据写入0x1000。整个过程中总线上传输的始终是混淆后的地址0x386B而非真实的密钥地址0x1000。攻击者即使截获EtherCAT帧也无法知道密钥的真实存储位置。这是一种基于地址空间的“白盒加密”无需额外的加解密运算非常适合资源受限的从站MCU。SOEM本身不提供这个加密API但它开放了ecrt_slave_config_fmmu()的底层接口让你可以自由构造FMMU配置。这正是SOEM作为“参考实现”的魅力所在它不替你做决定而是给你一把精准的手术刀让你在协议框架内实现自己的创新。5. 常见故障的根因排查链路从ecrt_master_send()返回-1说起在SOEM开发中ecrt_master_send()返回-1是最常见的报错但它只是一个表象。这个返回值可能源于从应用层到PHY层的任何一个环节。一个合格的SOEM工程师必须能像侦探一样沿着一条清晰的排查链路逐层下钻直至找到真正的“凶手”。下面是我总结的、经过数十个项目验证的标准排查流程。5.1 第一层应用层检查——确认调用姿势是否正确ecrt_master_send()返回-1首先要排除最简单的错误是否在ecrt_master_create()之后、ecrt_master_activate()之前调用在ecrt_master_create()后主站对象处于未激活状态此时调用send必然失败。必须先调用ecrt_master_activate()它会初始化内部缓冲区并尝试与网卡建立连接。是否在ecrt_master_receive()之后立即调用SOEM要求send和receive成对出现。如果receive刚执行完send就立刻调用中间没有clock_nanosleep()会导致状态机来不及响应返回-1。标准模式是send-receive-sleep-send...master指针是否为空或已被释放用gdb调试时加断点break ecrt_master_send然后print master确认指针有效。如果以上都OK进入第二层。5.2 第二层协议栈层检查——ecrt_master_receive()的返回值ecrt_master_send()的失败往往是因为前一次ecrt_master_receive()没有成功处理完帧。所以必须检查ecrt_master_receive()的返回值int ret ecrt_master_receive(master); if (ret 0) { printf(ecrt_master_receive failed: %d\n, ret); // ret -1: socket接收失败底层I/O错误 // ret -2: 帧解析失败CRC错误或格式错误 // ret -3: 状态机超时从站无响应 }ret -1这是oshw_receive()返回的错误。用strace -e tracerecvfrom ./soem_demo看recvfrom()是否返回-1 EAGAIN无数据或-1 ENOBUFS缓冲区满。前者说明网卡没收到帧后者说明SO_RCVBUF太小。ret -2用tcpdump抓包看是否能抓到0x88a4帧。如果能抓到但SOEM解析失败说明帧的CRC校验失败。这通常意味着网线质量差、电磁干扰强或者PHY芯片工作异常。ret -3这是最棘手的。它表示主站发出了命令如PREOP但没有在超时时间内收到从站的响应。此时必须用ethercatdbg检查从站状态ethercatdbg -p eth0 state。如果所有从站都显示INIT说明链路不通如果部分从站显示PREOP部分显示INIT说明拓扑中有坏节点。5.3 第三层硬件抽象层检查——oshw_receive()的底层真相如果ecrt_master_receive()返回-1就要深入oshw_receive()。在oshw_linux.c中找到该函数添加日志int oshw_receive(uint8_t *data, size_t size) { int ret recvfrom(sock, data, size, MSG_DONTWAIT, NULL, NULL); if (ret 0) { perror(oshw_receive); // 打印具体的errno } return ret; }常见errno及对策errno含义解决方案EAGAIN无数据可读检查网卡是否UPip link show eth0检查混杂模式ip link show eth0 | grep PROMISCENOBUFS接收缓冲区溢出增大SO_RCVBUF见3.6节ENETDOWN网络接口已关闭sudo ip link set eth0 upEINVALsocket参数错误检查sock是否为有效的AF_PACKETsocket5.4 第四层物理层检查——用ethtool和tcpdump做终极审判当软件层排查完毕问题依然存在就必须祭出物理层武器ethtool eth0关注Link detected: yes链路是否建立、Speed: 100Mb/s速率是否匹配、Duplex: Full双工模式。如果Link detected: no检查网线、交换机端口、PHY供电。tcpdump -i eth0 -xx ether[12:2] 0x88a4这是黄金命令。如果tcpdump能抓到0x88a4帧说明PHY
返回列表