ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DoIP车载以太网诊断抓包实战:从协议解剖到Wireshark全流程分析

DoIP车载以太网诊断抓包实战:从协议解剖到Wireshark全流程分析 1. 为什么诊断要上车载以太网DoIP解决的三个实际问题我最早接触车载诊断是从CANoe抓CAN报文开始的那时候觉得500 kbps的波特率看个故障码也就够了。直到有一次做某个域控制器的刷写整包固件接近2 GB老板站在我身后问这得刷多久保守估算要三四个小时。那一刻我意识到传统CAN诊断的带宽天花板已经不是够不够用的问题而是直接卡住整车研发和售后流程的瓶颈了。1.1 传统CAN诊断在带宽和成本上的天花板CAN这条总线本身设计得非常好——可靠、抗干扰、报文优先级机制在实时控制场景里几乎无可挑剔。但到了诊断领域尤其是刷写和标定场景CAN的天然限制就暴露得很明显。标准CAN最大500 kbpsCAN FD虽然提升到2 Mbps甚至5 Mbps但实际使用中受线束、收发器和网络拓扑影响很难稳定跑到理论极限。算一笔账一个2 GB的固件包去掉协议开销、诊断响应等待、擦除和校验时间在500 kbps链路上跑一个通宵都算快的。更尴尬的是现在的智能座舱、自动驾驶控制器之间早就用上了车载以太网摄像头数据流动辄几百Mbps。让一个千兆级域控制器通过CAN总线跟诊断仪对话就像开着高铁去走乡间土路链路能力完全不匹配。1.2 DoIP并不是CAN诊断的替代品而是诊断通道的升级DoIP的全称是Diagnostic over Internet Protocol对应ISO 13400标准直白说就是把UDS诊断报文封装进TCP/UDP包里跑在以太网链路上。它解决的问题不是CAN怎么不好而是当车上已经有以太网之后诊断这条逻辑通道怎么搭才是最优解。这里有个常见误区很多人以为DoIP是用来替代CAN诊断的其实不然。在量产车里UDS over CAN依然是低成本节点的首选门窗、座椅、灯光这些ECU不可能为了诊断单独拉一条以太网线。DoIP真正的主场是高性能域控制器、整车OTA刷写、产线EOL下线检测以及售后店里那台连着以太网口的诊断仪。另外DoIP还有一个隐藏优势它天然支持远程诊断的想象空间——只要车辆能联网诊断数据理论上可以走到云端。当然实际落地还有很多安全和合规考量但至少链路层已经铺好了。1.3 一个典型的学习路径从CAN诊断到DoIP思维要变什么从CAN诊断切到DoIP我总结下来有三个思维转变。第一从看ID变成看端口和逻辑地址。CAN诊断靠CAN ID区分报文流向DoIP靠TCP连接和DoIP头里的逻辑地址来区分UDS报文本身藏在TCP负载里。第二从单帧/多帧变成TCP数据流。CAN有单帧、首帧、连续帧的说法DoIP没有这个概念TCP天然处理分段和重组你要关注的是完整DoIP消息的边界。第三从看DBC变成看协议头。CAN报文解析依赖DBC文件DoIP报文解析靠的是ISO 13400定义好的固定头格式Wireshark里打开就能看。这篇文章我就按自己的实战路径来写先从DoIP协议头拆起再到Wireshark抓包环境的搭建接着走一遍从车辆发现到UDS诊断的完整报文流程最后把我在实际项目中踩过的坑逐个讲清楚。内容偏实操适合正在做车载以太网测试、诊断协议开发或者想从CAN诊断往以太网诊断转的工程师。2. DoIP报文解剖8字节通用头的每一个字段都在干什么Wireshark刚打开DoIP抓包时很多人会被那一长串十六进制整懵。其实DoIP的报文结构非常规整所有DoIP消息都共享一个通用的8字节头后面再跟不同的负载。把这几条字段规则吃透后面所有报文都能看懂。2.1 通用DoIP报头各字段与字节序规则还是老规矩先看一张字段表字节偏移长度字段名含义0-12字节协议版本号当前ISO 13400-2:2019为0x022-32字节版本号取反一般为0xFD0x02取反4-52字节负载类型Payload Type区分车辆识别、诊断消息、路由激活等6-94字节负载长度后续负载的字节数不含这8字节头10可变负载Payload具体内容取决于负载类型载荷类型这个字段默认抓包里最容易看花眼——后面我单独解剖。另外要注意的是头部这4个字段全部采用网络字节序大端。也就是说负载长度0x00000004在Wireshark里显示的是4但在二进制里是00 00 00 04不是04 00 00 00。我见过有人把负载长度倒过来读结果整条流直接解析错位所以字节序是首先要注意的坑。2.2 负载类型Payload Type一张表看懂0x0001到0x8002DoIP协议的精髓其实不在UDS那一层而在于它定义了一整套诊断会话生命周期的管理消息。我平时抓包统计下来出现频率最高的负载类型就这么几个负载类型报文方向含义与使用场景0x0001诊断仪 - ECU车辆识别请求UDP广播发出问总线上都有谁0x0004任一方向通用DoIP头否定确认你发的入口请求我没看懂/不接受0x0005诊断仪 - ECU诊断消息UDS请求0x0006ECU - 诊断仪诊断消息正确认UDS响应0x8001ECU - 诊断仪车辆识别响应携带VIN、逻辑地址、EID、GID等0x8002ECU - 诊断仪路由激活响应告诉测试仪你能不能上来0x0007任一方向诊断消息ACK确认收到了0x00050x8003ECU - 诊断仪诊断消息NACK因为某些原因没收到/没处理好注意区分0x0004和0x8003这两个否定码0x0004对应的是协议层错误比如版本号不匹配、负载长度错误、无效消息长度0x8003对应的是诊断消息交互层的否定确认比如收到的源地址无效、无法处理诊断消息。两个NACK码的排查方向完全不同。载荷类型这个字段默认抓包里最容易看花眼的是0x0005和0x0006它们是UDS诊断消息的外壳。每次做诊断请求和响应日志分析时我都是靠这俩字段来筛诊断报文的。2.3 为什么诊断报文必须走TCP车辆发现必须走UDP这是TCP/IP协议栈里一个很有意思的设计。DoIP把两种传输协议的优点都利用上了UDP 广播负责找人。诊断仪刚接上车辆网络时完全不知道总线上挂了哪些ECU必须发送UDP广播帧所有ECU都能听到并回应。这就像你站在新小区楼下吆喝一声谁是业主所有住户窗口都探出头来答一声我是。TCP 长连接负责办事。找到目标ECU之后诊断请求和响应必须可靠交付没有丢包、乱序问题而且一次诊断会话往往有几十个来回。TCP的三次握手、确认重传机制保证了诊断数据能完整到达。这也是为什么热词里总能看到TCP长连接与短连接的讨论——DoIP诊断从路由激活到会话结束就是一个典型的长连接场景所有UDS请求复用同一条TCP流避免频繁握手带来的延迟和TCP端口开销。这两类流量在抓包里也容易区分UDP的0x0001/0x8001都发往或来自13400端口TCP的0x0005/0x0006则出现在建立好的TCP连接上。所以Wireshark里想快速分拣过滤掉udp.port 13400就能只看车辆发现消息。3. 抓包之前环境、过滤规则和解码配置一个都不能省很多人第一步就栽在装备上。DoIP抓包跟普通TCP抓包最大的不同是——你手里那块USB千兆网卡可能根本抓不到车上的报文。车载以太网物理层是100BASE-T1也叫BroadR-Reach单对非屏蔽双绞线跟办公室里的100BASE-TX完全是两码事。3.1 硬件与链路车载以太网接口、镜像口和转接设备做DoIP抓包你需要保证接入的物理口能识别100BASE-T1信号。常见方案有几种整车厂测试台架一般已经引出RJ45调试接口直接接普通千兆网卡就能抓。专业数采设备像Vector的VN5650、峰值仪的CANoe Ethernet接口支持100BASE-T1物理层还能同时做报文仿真。分路TAP或者交换机镜像端口当车辆只有唯一一个以太网口、无法串接抓包设备时用端口镜像把诊断口流量复制一份到抓包电脑。设备链路的坑在于如果你用的物理口不支持100BASE-T1Wireshark里只会看到链路断开连一个错误包都不会有。所以我通常建议准备一根专用的车载以太网转接盒或者确认一下示波器的差分探头规格不然很容易怀疑自己抓包姿势不对实际是物理层压根没通。另外如果诊断仪本身走的是CAN总线车上还有一个DoIP转CAN的诊断网关热词里的doip转can诊断请求说的就是这类拓扑。这时候Wireshark抓到的是网关上来的以太网报文你要确认抓包点是在网关的以太网侧否则看不到完整的DoIP消息头。3.2 Wireshark的过滤规则与个性化配置环境通了以后接下来是过滤规则。这里分享一套我每次开工前会预先设置好的过滤器。Wireshark支持tshark语法可以直接在过滤器栏输入# 只看DoIP相关流量 ip.addr 13400 || tcp.port 13400 || udp.port 13400 # 只看车辆发现UDP广播 udp.port 13400 # 只看UDS诊断消息TCP 13400 tcp.port 13400 # 只看某个逻辑地址相关的流量 ip.addr 192.168.0.10但说实话直接按端口过滤有时会把需要追踪的TCP连接上下文丢掉。我个人的习惯是先抓全量再做显示过滤Display Filter。也就是Wireshark左侧的显示过滤栏里用表达式过滤就放在窗口顶部。这样保留原始包文件后面想重新分析随时可以放宽条件。比如观察UDS诊断的完整时序需要同时看到TCP三次握手和后续的路由激活、诊断请求这时就不能用只过滤UDP的简单条件。另外建议在视图 - 时间显示格式里改成相对时间Relative time或者干脆用视图 - 时间引用设置某个关键包为时间零点这样能一眼看出P2计时器过期的时间点。3.3 解码关联让Wireshark把DoIP负载正确识别成UDS这是Wireshark分析DoIP最关键的一步。Wireshark内置了ISO 13400的解码器但默认情况下不一定能自动把13400端口上的TCP数据解码成DoIPUDS。我遇到过很多次抓包文件里能看到TCP端口13400但包详情里全是TCP segment of a reassembled PDU根本看不到0x0005、0x22、0x62这些UDS字节。原因是Wireshark还没把该TCP流识别为DoIP协议。解决办法有两个。第一在解码为Decode As里手动指定右键 - 解码为Decode As- 选择 TCP 端口 13400 - 当前协议选 ISO 13400第二启用Wireshark的TCP流重组功能。在编辑 - 首选项 - Protocols - TCP里确保Allow subdissector to reassemble TCP streams是勾选的。这一步非常关键因为DoIP消息可能会被TCP拆分成多个段如果没有重组成完整的DoIP帧后面的UDS字段就全部对不上。配置好之后你再选中一个诊断请求包包详情依次展开应该是这样的层级Frame: 物理帧信息Ethernet II: 源/目的MACInternet Protocol Version 4: 源/目的IPTransmission Control Protocol: TCP端口信息ISO 13400-2: DoIP报头里的版本、负载类型、负载长度ISO 14229-1: UDS服务ID和参数能做到最后这层你才算真正看着UDS干活。4. 从三次握手到路由激活一次标准车辆接入的完整走读有了环境下面就走一遍标准流程。这是所有DoIP诊断会话必经的四步车辆发现 - TCP连接 - 路由激活 - UDS诊断。每一步在Wireshark里都有非常鲜明的特征。4.1 车辆发现UDP广播下的0x0001与0x8001打开Wireshark选择正确的网卡开始抓包然后诊断仪软件点击扫描车辆。这时你会看到一条UDP报文从诊断仪发出目标地址是255.255.255.255:13400负载类型是0x0001负载长度一般为0x00无额外参数。这就是车辆识别请求。紧接着总线上每个支持DoIP的ECU都会回一条0x8001车辆识别响应负载里带着VIN码17字节ASCII、逻辑地址2字节、EID6字节和GID6字节。Wireshark会把这些字段解析得非常漂亮VIN直接显示为字符串比对着十六进制数挨个翻译舒服太多了。这里有个容易忽略的细节车辆识别响应的源地址往往是ECU自身的IP但UDP源端口固定是13400。这是ISO 13400规定的所有DoIP实体统一监听UDP/TCP 13400端口。所以在Wireshark的过滤器里写udp.port 13400能同时筛到广播请求和所有响应。如果遇到扫描不到ECU的情况优先检查VLAN Tag是否被Wireshark误解析、诊断仪和ECU是否在同一网段、是否有防火墙挡住UDP广播。其中VLAN Tag问题我放到最后的坑点部分细说。4.2 TCP连接建立为什么DoIP诊断会看到先SYN再SYN-ACK车辆识别完成诊断仪选中目标ECU的逻辑地址然后发起TCP连接。Wireshark里你会看到教科书级的三次握手诊断仪 - ECUSYN标志置1初始序列号比如0x12345678目的端口13400。ECU - 诊断仪SYNACK序列号1确认号诊断仪初始序列号1同时ECU也分配一个自己的初始序列号。诊断仪 - ECUACK确认号ECU序列号1。整个过程Wireshark会标注为[SYN]、[SYN, ACK]、[ACK]三个包。三次握手完成就是一条TCP长连接建立。之后所有UDS诊断消息都会复用这条连接这也是热词里TCP长连接与短连接在DoIP场景下的具体体现——长连接最大的好处是省去重复握手的开销让诊断请求和响应的时序非常紧凑。在DoIP里TCP还有一个细节诊断仪通常会绑定一个固定的源端口不一定是13400但目的端口一定是13400。如果你看的抓包里源端口每次都不一样说明那是新起了一次连接不是复用旧连接。4.3 路由激活源地址、激活类型与0x0005报文的语义TCP连接建立后诊断仪还不能直接发UDS必须先发路由激活请求。这是DoIP的门卫机制。路由激活请求同样是负载类型0x0005但注意它跟UDS诊断消息共用同一个载荷类型。怎么区分通过负载的第一个字段——DoIP消息里有一个源地址字段UDS诊断消息也有源地址但路由激活的源地址后面紧跟的是激活类型。标准路由激活请求负载结构是源地址2字节诊断仪自己的逻辑地址测试仪通常填0x0E80激活类型1字节0x00默认0x01带安全证书0x02/0x03等有特殊约定ECU收到后回0x0005路由激活响应负载里的关键字段测试仪的逻辑地址就是刚才请求里的源地址ECU的逻辑地址激活响应码0x00成功0x01已激活0x02源地址未配置0x03并发访问被拒绝0x04包头格式错误0x05认证失败Wireshark解码后这些字段会直接以人类可读的方式展示出来。你不需要背响应码但至少要知道看到Response Code: 0x10十进制16之类的是路由激活成功看到0x04就要回头检查是不是把负载结构填错了。路由激活成功后DoIP就处于可诊断状态。此时ECU会开启S3超时计时器如果一段时间内没有UDS通信某些ECU会自动断开连接。这就是为什么长时间刷写时要不间断发0x3E保持激活信号。5. UDS服务在抓包里的真实样子从0x10到0x31逐个看路由激活之后报文的外层就不再变化了——TCP连接保持着DoIP头里的负载类型固定是0x0005/0x0006真正有业务语义的是UDS的Service ID和子功能。这一节我带大家逐个看常见UDS服务在Wireshark里长什么样。5.1 会话控制0x10和安全访问0x27一切诊断动作的前置条件0x10 诊断会话控制是每次诊断会话的第一个正式UDS请求。常见子功能0x01 默认会话上电后的默认状态响应较慢很多服务不可用0x02 编程会话刷写固件专用响应最快0x03 扩展会话标定、读写参数、执行例程时常用在Wireshark里一个完整的扩展会话请求/响应看起来是这样诊断请求 (DoIP 0x0005): ISO 14229-1 DiagnosticSessionControl Service ID: 0x10 SubFunction: 0x03 (扩展诊断会话) 诊断响应 (DoIP 0x0006): ISO 14229-1 DiagnosticSessionControl Service ID: 0x50 SubFunction: 0x03 P2: 0x00 0x50 (80ms) P2*: 0x01 0x00 0x00 (65536ms)这里有个Wireshark解析细节响应里的SID是请求SID加0x40所以0x10请求对应0x50响应。初学者看到0x50容易发懵其实就是一个标志位的事。0x27 安全访问是紧接着会话切换后的重头戏。过程是诊断仪发0x27 0x01请求种子ECU回0x67 0x01 种子值比如4字节seed诊断仪按密钥算法计算后发0x27 0x02 密钥值ECU回0x67 0x02表示解锁成功如果第4步收到的是0x7F 0x27 0x33那就是NRC 0x33——安全访问被拒绝通常是因为密钥算错了或者ECU设置了重试延迟通常是10秒内不允许再次尝试。在抓包里这个时间间隔可以直接从时间戳上看出来非常直观。很多刚转DoIP的工程师会犯一个错误想跨过会话切换直接发0x27。结果收到0x7F 0x27 0x7F也就是服务在当前会话不可用。这是因为某些安全等级只在扩展会话下开放。抓包一旦出现这种NRC先回头检查前面的会话切换是否成功。5.2 数据读写0x22/0x2E与故障码读取0x19/0x140x22按数据标识符读取数据。这个服务最能体现DID的概念。比如读VIN、读软件版本号、读当前电压每个都有对应的DID。Wireshark里0x22没有子功能直接是两个字节的DID跟着SID后面比如0x22 0xF1 0x90 // 读DID F190响应是0x62 DID 数据数据和DID一一对应。如果DID不存在返回NRC 0x31请求超出范围。0x2E写数据则相反请求里就要带上要写入的数据。一般用在标定参数写入、配置某些可调项。要注意的坑是写数据前必须先解锁安全访问否则就是0x7F 0x2E 0x33。0x19读DTC故障码是诊断里用得最多的服务之一子功能非常多0x01 按状态掩码读DTC0x02 按状态掩码读DTC快照记录0x04 按状态掩码读DTC扩展数据0x06 读最近发生的DTC0x0A 读所有支持DTC的状态Wireshark里最常用的是子功能0x02配合状态掩码通常0xFF表示读取全部状态。响应里会列出DTC的高字节、低字节和状态位比如0x59 0x02 DTCFormatIdentifier: 0x00 DTC: 0xC001 状态位: 0x28当前存在 历史出现 DTC: 0xC101 状态位: 0x20历史出现状态位的每一位对应一个故障状态0x28表示当前故障存在且历史出现过0x20表示历史出现但当前无故障。0x14清除诊断信息是0x19的反面。做维修验证时最经典的操作就是先读DTC清DTC复位再读DTC通过三次抓包对比确认故障是否彻底解决。5.3 例程控制0x31与刷写流程0x34/0x36/0x370x31例程控制是非常灵活的服务几乎每个ECU的自定义诊断功能都会通过它暴露。常见子功能0x01 启动例程0x02 停止例程0x03 查询例程结果比如擦除用户数据自检计算校验和都可以归为例程。Wireshark里0x31的报文特点是非常散负载里除了例程ID外全是自定义参数所以反而最需要结合DBC或诊断调查表来看。固件刷写是DoIP的重头戏核心链路是0x10 0x02 进入编程会话0x27 安全访问解锁0x31 0x01 0xFF00 清除内存擦Flash0x34 0x00 0x44 地址长度信息请求下载0x36 0x01 数据块传输数据循环N次0x37 0x01请求传输退出0x31 0x01 0xFF02 检查编程完整性0x11 0x01 ECU复位其中0x34响应里会返回一条最大块长度block length比如MaxNumberOfBlockLength: 0x000010004096字节后续0x36每次数据块大小都不能超过这个值。Wireshark里看0x36的报文特征非常明显——请求和响应都是成对出现且请求负载很大有时候一个0x36能占满好几个TCP段。这时候光看一个个包会非常累后面我会讲怎么用Wireshark的统计功能看流量全景。5.4 NRC否定响应码抓包中最值得盯住的那一帧UDS诊断里最让人头疼又最有价值的就是NRCNegative Response Code。每次抓包分析我都会第一时间在过滤栏里把否定响应拎出来uds.nrc.code 0Wireshark里NRC报文长这样0x7F 0x22 0x31从左到右肯定响应前缀0x7F请求的服务ID 0x22NRC码0x31。含义是你请求的0x22服务执行不了因为请求参数超出范围。常见NRC码与排查方向NRC码名称常见触发原因与排查方向0x11serviceNotSupported服务ID本身不被支持检查协议版本或服务范围0x12subFunctionNotSupported子功能不支持比如0x10会话切换里传了0x040x13incorrectMessageLengthOrInvalidFormat请求长度有误常见于DID参数长度不匹配0x22conditionsNotCorrect前置条件不满足比如没切会话就发安全访问、刷写步骤顺序不对0x31requestOutOfRangeDID或例程ID不存在或参数值超出范围0x33securityAccessDenied安全访问被拒绝密钥错误或处于延迟锁定0x78requestCorrectlyReceived-ResponsePending请求已收到但处理需要时间ECU稍后会再回响应刷写擦除时常见0x7FserviceNotSupportedInActiveSession当前会话不支持该服务先切会话再说我个人最怕看到0x78因为它不是错误而是我先忙着晚点再回你。Wireshark里0x78往往后面跟着一长串TCP keep-alive或0x3E如果不理解这个机制还以为是ECU死机了。应对0x78诊断仪侧必须配置P2扩展时间否则会误判超时把流程打断。6. 完整场景复盘读故障码与固件刷写的Wireshark全程记录单个报文会看了下一步就是看整体流程。这一节我复盘两个真实抓包场景把时间线上的先后顺序和关键节点串起来。6.1 场景A一次标准DTC读取的报文时间线假设一辆车报了个电机控制器通信丢失的故障售后诊断仪的操作流程和Wireshark对应报文如下诊断仪上电向UDP 13400广播0x0001车辆识别请求。ECU回0x8001车辆识别响应诊断仪界面显示车辆VIN和IP。诊断仪发起TCP三次握手SYN、SYN-ACK、ACK。诊断仪发0x0005路由激活请求ECU回0x0005路由激活响应响应码成功。诊断仪发0x10 0x03切扩展会话ECU回0x50 0x03含P2时间。诊断仪发0x22 F1 90读取VIN响应0x62 F1 90 VIN字符串确认节点身份。诊断仪发0x19 0x02 0xFF读所有DTCECU回0x59 0x02 DTC列表。诊断仪发0x14 FF FF FF清除DTCECU回0x54。诊断仪发0x11 0x01复位ECUECU回0x51TCP连接随后关闭。在Wireshark里这9步连起来就是一条完整的时间线。做测试用例评审时我最喜欢让新人把每一步的过滤条件写出来比如只看第5步的会话切换就是uds.sid 0x10 tcp.port 13400能一条命令过滤出目标报文说明已经对DoIP和UDS的结构有整体把握了。一个实用的排查技巧当某个UDS请求超时P2超时时先在时间轴上看看是不是少了某一步前置。我遇到过很多次读DTC超时最后定位竟是诊断仪没做路由激活ECU根本没进入可诊断状态。从Wireshark的时间戳和序号上这种问题一目了然。6.2 场景B固件刷写中的大量0x36重复帧如何快速统计刷写是最吃流量的诊断场景2 GB固件包发下来0x36传输数据请求能占到总包的99%。逐包翻页面不现实这时候Wireshark的统计功能才是主角。我的操作路径是用tcp.port 13400过滤只留DoIP流量。菜单统计 - IO图表设置Y轴单位选包数或字节数时间间隔调成1秒。如果能看到一条稳定的高流量曲线说明刷写传输阶段在正常推进如果曲线突然掉到0说明卡在擦除Flash或校验阶段。想统计0x36请求的数量可以直接用表达式做个显示过滤再在状态栏看显示包数uds.sid 0x36如果刷写失败最常见的定位方法是在Wireshark里找到第一个非0x36的响应或NRC报文。比如突然出现0x7F 0x36 0x31块超出范围说明诊断仪发的数据长度超过ECU在0x34响应里给的块长度上限出现0x7F 0x36 0x72generalProgrammingFailure则多半是Flash写入硬件错误。刷写流程中还有一种特殊情况ECU为了擦除Flash会在某个0x31周期发出0x78ResponsePending然后再给最终响应。Wireshark里看0x78前后的时间间隔能判断出当前Flash方案是快还是慢。有些方案动辄10秒以上如果诊断仪侧没有把P2扩展时间配置足够长就会导致刷写流程中断。6.3 抓包数据与DTC/刷写结果的相互印证抓包不只是看有没有通更重要的是用报文去解释业务现象。这里分享一个小例子有一次同事反馈ECU刷写后软件版本没变化抓包下去发现0x2E写版本号请求虽然返回了0x6E成功但紧接着诊断仪没有发0x11复位直接发了0x27安全访问因为界面跳转触发。ECU还是编程会话逻辑上写是写成功了但没生效——因为新版本号需要复位后才真正启动。这个结论在抓包里就是三个包的事0x6E、0x7F/0x27然后诊断仪没发0x11。所以说Wireshark里同一个现象往往能从报文时序里找到逻辑根因。不要只看单个响应是不是成功而是把整个流程串成链再判断。7. Wireshark分析DoIP时最容易翻车的四个细节文章最后按惯例分享几个我实际踩过的坑。这些细节不解决轻则抓包解析错乱重则直接误导整个测试结论。7.1 TCP粘包与拆包报文对不上号的原因DoIP跑在TCP上TCP是字节流协议不保障消息边界。所以一个DoIP消息可能被拆成多个TCP段发出去也可能好几个DoIP消息拼在一个TCP段里。Wireshark的TCP重组功能Allow subdissector to reassemble TCP streams能处理大部分情况但偶尔还是会遇到解析错位。我的经验是看到负载长度跟实际长度对不上时先不要怀疑Wireshark有问题而是检查这个DoIP消息是否跨了多个TCP段。最直接的办法是右键Follow TCP Stream看原始数据流的16进制视图按8字节DoIP头重新切分边界。只要认准负载长度字段手工也能切出正确的消息序列。7.2 时间戳与超时计时器P2、S3在抓包里的表现UDS协议里有几个计时器抓包时可以通过时间戳验证P2服务器处理请求的时间上限一般50ms。P2*出现0x78后服务器完成处理的扩展上限不同ECU差异大常见5000ms。S3非默认会话的保持时间超过这个时间没收到任何诊断请求ECU自动回默认会话通常5000ms。S3Server路由激活保持时间超时后连接自动断开。抓包里怎么看用相对时间显示视图 - 时间显示格式 - 相对时间选中关键包按下CtrlT设置时间参考后面包的时间差一目了然。我见过一个奇葩项目S3时间被设成1秒诊断仪软件稍一迟钝就掉回默认会话下一个诊断请求全是0x7F。这种问题不抓包根本想不到。7.3 VLAN Tag与Dedicated端口看不见的链路层信息车载以太网经常在链路层带VLAN Tag802.1Q用来区分控制数据和诊断数据。默认情况下Wireshark已经把802.1Q协议拨开包详情里会显示VLAN id: X。但如果你看到包协议列显示的是802.1Q Virtual LAN而不是Ethernet说明抓包网卡的VLAN硬件卸载没关Wireshark看到的不是原来那层封装。这时要把网卡属性里的VLAN hardware offload关掉重新抓包。另一个坑是有些ECU的DoIP实体绑定在特定VLAN ID上抓包网卡不加入这个VLAN直接看不到ECU的回应。这类问题定位起来特别费时间我会用Wireshark的分析 - 专家信息先看有没有malformed包如果没有再考虑是不是VLAN隔离。7.4 处理DoIP转CAN的抓包场景网关转换后的报文边界热词里doip转can诊断请求是指车上有一个诊断网关把以太网侧的DoIP请求转换成CAN侧的UDS over CAN请求。这种拓扑下如果诊断报文出了问题在以太网侧抓包往往看不出毛病因为网关已经把报文转换得看起来正常了。这时需要同时抓网关两侧的报文以太网侧一个pcapng文件CAN侧一个blf/asc文件然后按诊断请求的序号一一对应找差异。常见的转换问题是网关在转换时把CAN的DLC数据长度码截断或填充导致DoIP消息里的UDS数据和CAN侧的UDS数据在尾部多出或少了几个0x00。Wireshark只看以太网侧永远找不到根因非得两侧对照才行。说实话DoIP抓包这个事门槛不在协议本身多复杂而在很多细节不是靠翻文档能提前避开的。我写这篇也是想把自己见过的坑集中倒一倒能帮后面的同行少走点弯路就算值了。你如果在实际项目中遇到过更刁钻的抓包问题欢迎拿出来一起聊。
返回列表