新闻详情

新闻详情

首页 / 资讯中心 / 详情

DoIP抓包实战:UDS诊断与64MB OTA升级深度拆解

发布时间:2026/9/28 5:52:26来源:尧图网络
DoIP抓包实战:UDS诊断与64MB OTA升级深度拆解
有次我去支持一个量产阶段的OTA问题固件包64MBTester连着域控制器每跑到几十MB就断。研发同事第一反应是“服务器带宽不够”第二反应是“TCP被防火墙切了”最后把DoIP抓包文件导出来才发现连接压根没断是路由激活成功后双方逻辑地址对不上UDS请求发到了错误的target。那个晚上之后我就养成了一个习惯不管线上线下任何诊断和刷写问题先抓DoIP包再谈优化。这篇文章就从报文层面把我对DoIP协议、UDS诊断与64MB OTA升级的理解完整拆一遍。适合刚接手车载以太网诊断的软件工程师、测试工程师也适合正在做OTA集成、刷写工具链的同行参考。文章里的抓包片段和参数来自我做过的实际项目和实验台架你可以直接在Wireshark里对照着看。1. CAN时代诊断链路的天花板为什么要上DoIP1.1 CAN诊断到底慢在哪传统CAN总线上的UDS诊断消息走的是ISO-TPISO 15765单帧最多只有8字节其中服务ID、子功能、数据长度等控制字段还要占掉一部分实际有效载荷只有7字节左右。读一个2KB的参数要拆成接近300个帧每帧之间还要等流控帧稍微大一点的刷写动辄几十分钟。以前做Bootloader刷写256KB的App要刷十几分钟车上所有人就干等着。后来换到CAN FD稍微好点一帧64字节但和以太网相比依然不是同一个量级。还有一个隐藏的问题CAN总线的仲裁机制。总线上ECU多的时候高优先级帧会不断抢占总线诊断报文本身优先级又不一定最高延迟抖动非常明显。恢复时间、超时参数的标定都容易踩雷。1.2 DoIP不是替代诊断而是扩展了诊断的“运输带宽”DoIPDiagnostic over IP本质上是ISO 13400定义的一套传输层映射把UDS诊断消息封装到IP网络中传输底层跑TCP或UDP端口固定用13400。TCP承载诊断消息和路由激活等关键交互UDP主要承担车辆发现、状态通告这类广播类功能。换成DoIP之后单条诊断消息的有效载荷可以达到1KB甚至更高整包64MB的固件在理论上用百兆以太网传输纯网络耗时只要几秒。虽然ECU内部Flash擦写速度仍然是瓶颈但传输链路上的效率提升是革命性的。更重要的是DoIP把诊断从“点对点总线”变成了“IP网络应用”。网关、域控制器、Ota Server之间可以走标准网络拓扑远端诊断、云端日志、产线自动化都变得顺理成章。OTA升级能规模化落地DoIP是底层支撑之一。1.3 从CAN ID到逻辑地址CAN诊断里我们习惯用CAN ID区分ECU比如物理寻址0x7E0、功能寻址0x7DF。到了DoIP没有CAN ID的概念改成了“逻辑地址”。逻辑地址是一个16位正整数由OEM统一规划。同一条DoIP物理链路上每个ECU的逻辑地址必须唯一。Tester也有自己的逻辑地址通常OEM会预留一段给诊断仪或上位机用。抓包时看到诊断消息里有源地址和目标地址不要以为是IP地址这两个2字节字段就是逻辑地址。后面拆包的时候会具体看到。2. 动手拆DoIP报文8字节头、13400端口与四条关键消息2.1 DoIP头逐字节拆解不管哪种DoIP消息TCP或UDP载荷的前8字节都是固定格式的DoIP Header我按Wireshark里的展开顺序给你过一遍Version1字节当前主流是0x03对应ISO 13400-2:2012及之后版本Inverse Version1字节0xFC用于校验版本有效性和字节序Payload Type2字节大端标识DoIP消息类型Payload Length4字节大端表示DoIP头之后载荷的字节数这里最容易踩的坑是Payload Length。它只算DoIP头后面的数据不含这8字节头。很多人写协议栈时把这个长度算错导致对端解析错位整个诊断链路直接瘫痪。用Wireshark抓包时如果看到某个DoIP帧的Info列显示“Malformed”多半就是Payload Length和实际载荷对不上。DoIP消息类型我按实战中出现的频率排个序做成一张表方便查阅Payload Type名称传输方式典型场景0x0005Routing Activation RequestTCPTester连接后发送0x0006Routing Activation ResponseTCPECU返回激活结果0x0007Alive Check RequestTCPECU检测Tester是否存活0x0008Alive Check ResponseTCPTester回复存活0x0001Vehicle Identification RequestUDP发现车辆0x0004Vehicle Identification ResponseUDP车辆回报VIN等信息0x8001Diagnostic MessageTCP承载UDS消息0x8002Diagnostic Message Positive AckTCPDoIP层确认收到诊断消息0x8003Diagnostic Message Negative AckTCPDoIP层拒收诊断消息0x0000Generic DoIP Header Negative AckTCP/UDPHeader本身错误2.2 车辆发现阶段UDP 13400的广播与响应DoIP会话从“发现车辆”开始。Tester向UDP 13400端口发送Vehicle Identification Request0x0001请求载荷可以为空也可以携带EID或VIN进一步缩小范围。支持DoIP的ECU或网关收到后会回应Vehicle Identification Response0x0004消息里包含VIN、逻辑地址、EID、GID。这些字段在Wireshark里都是字符串形式展示的比如VIN是17位ASCII码打开抓包文件一眼就能认出是哪台车。之前我遇到过一个问题Tester发车辆识别请求ECU就是不回。持续排查发现是UDP广播被台架网络隔离了。DoIP的发现机制依赖UDP广播在子网隔离、VLAN划分明显的产线网络里广播经常到不了ECU。2.3 路由激活与Alive CheckTCP连接上的“登录”TCP连接建立后Tester必须发送Routing Activation Request0x0005相当于向ECU报到并申请一条诊断路由。请求里最关键的是Source Address和Activation Type。Activation Type不同OEM策略不一样常见的有0x00默认模式、0x01 WWH-OBD模式。这块要特别小心ECU会根据路由表判断是否允许这个Tester使用指定逻辑地址。如果请求里的Source Address不可用或超出分配范围ECU会返回带非0响应码的Routing Activation Response。Alive Check是TCP连接上很有意思的一类消息。ECU会周期性发送0x0007 Alive Check RequestTester必须在规定时间内回0x0008否则ECU认为Tester已离线会回收路由资源。我在实际项目中遇到的“连接没断但诊断无响应”问题有几次就是这个机制引起的——Tester端没有实现Alive Check自动应答ECU默默把路由关了。2.4 诊断消息0x8001A_SA/A_TA与真正的UDS所有UDS报文都封装在0x8001 Diagnostic Message里。它的Payload结构是Source Address2字节Tester的逻辑地址Target Address2字节目标ECU的逻辑地址User Data真正的UDS报文比如0x10 0x03、0x27 0x01、0x34 0x20等抓包时Wireshark会把User Data解析成UDS层直接显示服务名比如“DiagnosticSessionControl”“TransferData”。如果显示的UDS服务是“Unknown”通常说明这条UDS请求是OEM私有扩展不代表报文错误。0x8002和0x8003要专门说一下。很多刚接触DoIP的同事会把0x8002当成UDS响应其实不是。0x8002只是DoIP层的确认表示ECU收到了这条诊断消息真正的UDS响应还在后面由ECU以另一条0x8001消息发回来。所以一次完整的单请求交互Wireshark里至少能看到三条消息Tester发0x8001、ECU回0x8002、ECU再发0x8001携带UDS响应。3. UDS诊断在DoIP上的时序抓包从建链到解锁3.1 一次典型UDS交互的抓包骨架任何DoIP诊断流程都从TCP三次握手开始然后是路由激活接下来才是UDS交互。我保存过一份标准抓包在Wireshark里看连接层面是这样的1 Tester - ECU TCP SYN 2 ECU - Tester TCP SYNACK 3 Tester - ECU TCP ACK 4 Tester - ECU Routing Activation Request (0x0005) 5 ECU - Tester Routing Activation Response (0x0006, code0x00) 6 Tester - ECU Diagnostic Message (0x8001, UDS: 10 03) 7 ECU - Tester Diagnostic Message ACK (0x8002) 8 ECU - Tester Diagnostic Message (0x8001, UDS: 50 03)如果你抓到的包少了第5步或响应码非0后续UDS请求大概率全部无响应。所以在工具链开发时路由激活的成功与否一定要作为首要检查项很多“ECU没反应”的问题根源就在这里。TCP连接层面还有个常见现象Wireshark里出现“TCP segment of a reassembled PDU”。这是因为DoIP诊断消息携带的数据较长超过了单个TCP分段的承载量被TCP拆成了多段传输。DoIP解析器会自动重组不需要你手动处理新手不要看到这种标记就以为报文丢了。3.2 诊断会话切换与安全解锁0x10/0x27在DoIP里的样子UDS进入DoIP后服务定义没有变仍然是ISO 14229-1那一套。0x10诊断会话控制、0x27安全访问、0x3E TesterPresent一个都没少。抓包时看0x10的时序非常有代表性。比如切到扩展会话Tester发0x10 0x03ECU回0x50 0x03。在DoIP环境下同样会出现NRC 0x7F 0x10 0x7F表示该会话不支持这和CAN那边完全一致。0x27安全访问在OTA里是必经之路。刷写前ECU通常要求先做种子密钥验证。抓包里一般是两段Tester发0x27 0x01 DemandSeedECU回0x67 0x01加种子数据Tester发0x27 0x02 SendKeyECU回0x67 0x02表示通过如果第1步返回0x7F 0x27 0x33表示当前会话不允许执行安全访问如果返回0x7F 0x27 0x36说明尝试次数超限。有一次在台架上反复测安全解锁失败抓包发现工具每次连上都换一个Tester逻辑地址ECU把每个地址的失败计数都算独立最后才解锁成功。这个细节不抓包根本发现不了。3.3 物理寻址与功能寻址的区别CAN诊断里的物理寻址和功能寻址到了DoIP依然保留。物理寻址的Target Address是具体ECU的逻辑地址消息只发给这一个节点功能寻址的Target Address是一个广播性质的逻辑地址ECU收到后自行判断是否处理。抓包时区分这两种寻址看Target Address字段就行。比如目标地址是某个具体的0x0001、0x0011就是物理寻址如果是一个OEM规定的功能寻址值比如0x000A或0x0100就可能是功能寻址。在OTA场景中功能寻址常用于全车唤醒、批量关闭DTC这类广播操作但0x36传输数据这类大块数据必须用物理寻址。我这里有个教训早期做网关路由测试时不小心把0x34请求下载发成了功能寻址结果链路上多个ECU同时响应测试仪直接乱套。后来规范里明确要求凡涉及地址空间的操作一律物理寻址。4. 64MB OTA的报文全景0x34/0x36/0x37与性能计算4.1 OTA刷写的完整生命周期64MB这种体量的OTA不会只靠0x36一条服务从头传到尾。完整流程在抓包里通常能看到明显分阶段。我稍微拆一下大家可以对号入座预检阶段进入扩展会话读取ECU软件版本、指纹信息关闭DTC记录0x85部分场景还要停掉非诊断通信0x28环境准备切到编程会话0x10 0x02再次安全解锁Flash解锁和擦除用0x31例程控制触发擦除App区的例程这一步通常耗时很长容易被误判为卡死数据下载0x34请求下载0x36传输数据0x37请求传输退出这是核心传输阶段校验与跳转用0x31例程控制执行完整性校验成功后0x11 ECU复位回归验证重连后读版本号确认升级生效抓包时最容易忽略的是阶段2和阶段5之间的会话状态切换。如果会话在擦除或校验过程中超时回落到默认会话后续0x36就会被ECU拒绝现象是返回0x7F 0x36 0x7F。解决方案是在长耗时操作前合理延长会话超时参数并且抓包确认是否在操作间隙有0x3E TesterPresent保活帧。4.2 请求下载0x34服务器与ECU的“合同”0x34请求下载是数据下载阶段的起点相当于双方签一份传输合同。请求参数包括dataFormatIdentifier压缩和加密方式标识addressAndLengthFormatIdentifier内存地址和长度的字节宽度memoryAddress目标Flash地址memorySize要写入的数据长度ECU返回0x74后后面跟的是maxNumberOfBlockLength这个值决定了单条0x36能承载的最大数据量。假设ECU回复0x74 0x20 0x08 0x00表示maxNumberOfBlockLength为0x0800也就是2048字节。这个数字直接由Bootloader的接收缓冲区大小决定溢出了会返回NRC。抓包时看0x74报文里附带的最大块长度可以预判整个传输需要多少条0x36。这是评估OTA耗时的第一步。4.3 传输数据0x36把64MB拆成块0x36传输数据的请求结构是SID 0x36 blockSequenceCounter transferRequestParameter。blockSequenceCounter从0x01开始递增到0xFF回绕到0x00再继续消息里的实际数据就是blockSequenceCounter后面那些字节。每条0x36的数据长度不能超过0x34响应里给定的maxNumberOfBlockLength。在DoIP下传输大块数据不需要像CAN那样刻意做多帧流控。一条0x36消息可以直接带几百甚至几千字节数据只要TCP连接正常DoIP层面就能保证送达。这也是DoIP刷写速度大幅提升的根本原因。举一个实际计算例子64MB 67108864字节。如果ECU的maxNumberOfBlockLength为2048字节那么需要的0x36消息数是2048/67108864 32768条准确说是67108864除以2048等于32768恰好整除。每条0x36的消息开销为DoIP头8字节加源地址和目的地址4字节加UDS SID 1字节加blockSequenceCounter 1字节总共约14字节头。总网络负载大约在64MB基础之上再多约0.5MB头开销。这个开销放在百兆以太网里基本可以忽略但如果你用4G网络远程刷写这个头开销和TCP ACK的往返时间就值得优化。4.4 传输耗时计算与优化空间以2ms的往返确认时间估算不同块大小下的纯传输耗时是这样的maxNumberOfBlockLength0x36消息数理想耗时2ms/条1024字节65536条131秒2048字节32768条65秒4096字节16384条33秒8192字节8192条16秒16384字节4096条8秒这张表不是绝对准确最终还受ECU Flash写时间、擦除时间、P2*超时、TCP重传等因素影响但它能说明一个规律块大小翻倍消息数量减半总耗时几乎线性下降。实际项目中我看到很多OEM把maxNumberOfBlockLength做得比较保守比如1024或2048字节。原因很现实ECU的RAM有限接收缓冲区不可能开太大。如果OTA时间敏感可以从两个方向优化一是让Bootloader扩大接收缓冲区提高块大小二是在应用层做并行写Flash比如收到一块先缓存上一块还在写的时候下一块已经在TCP缓冲区里排队。传输到后半段有一个容易被忽略的抓包特征blockSequenceCounter连续递增但实际每三次就会出现一次较大的TCP延迟。这是因为ECU在写Flash时无法同时处理网络中断TCP窗口被暂时填满Wireshark里的RTT会明显变大。这个现象属于正常如果RTT持续超过P2*且没有0x78响应那才是协议栈出问题了。5. 抓包排障中的高频坑与定位手段5.1 工具链准备抓包环境与过滤条件做DoIP抓包硬件上最简单的是在Tester侧镜像口抓包或者直接使用支持DoIP的VN设备。如果没有专用硬件PC上装Wireshark把以太网网卡设为混杂模式过滤13400端口也能抓到完整的对话。Wireshark开启后建议立刻检查首选项里DoIP解析器是否启用。很多版本默认支持但如果抓包时看到一堆原始TCP载荷而不是整洁的DoIP树形结构可以在“Decode As”里手动指定为DoIP协议。抓包时的显示过滤条件可以参考tcp.port 13400 || udp.port 13400只看DoIP消息可以简化为doip如果只想看诊断消息doip.payload_type 0x8001用tshark在命令行下快速筛查也很方便。我经常用类似下面的命令对抓包文件做粗扫tshark -r ota.pcapng -Y doip -c 50 -T fields -e frame.number -e _ws.col.Info保存下来的pcapng我会保留VIN和逻辑地址信息方便后续在OEM或UDS工具里回放。回放时注意如果Tester逻辑地址变了ECU很可能不接受路由激活回放结果会和现场不一致。5.2 高频异常场景与定位方法整理一下几个我在抓包里反复见过的异常现象以及排查切入角度。现象可能原因抓包验证方式路由激活响应码非0逻辑地址冲突、激活类型不被支持看0x0006响应的code字段UDS请求正常但ECU不回复0x8002有回复但UDS无响应常为ECU应用层卡死检查ECU端的P2/P2*参数0x36大量返回0x7F 0x22条件不满足可能是不在编程会话或未安全解锁回看0x10和0x27的时序刷写中途连接断开TCP RST或Alive Check超时查看RST前30秒是否有0x0007/0x00080x36经常回0x7F 0x36 0x78ECU写Flash需要时间进入pending状态确认后续0x76是否到达传输速度远低于预期块大小设置太小或TCP窗口受限统计0x36数量和时间戳其中0x78这个最值得多说两句。抓包里出现0x7F 0x36 0x78表示ECU已经收到请求但处理时间会超过默认P2它先用这个响应暂时稳住Tester。当Flash写入完成后ECU会补回0x76。如果Tester端没有实现0x78等待机制而是直接把0x78当异常就会反复重发反而越刷越慢。有一次客户报OTA失败率高抓包发现工具对0x78的处理改成“立即重发0x36”几十KB之后ECU的接收状态机就乱了。这个属于典型的工具侧问题抓包一对比责任就清楚了。5.3 判责和复现时的建议最后说点抓包工程师的经验。遇到OTA或诊断问题先不要改代码先抓一份完整pcapng然后按四个维度归档时间线、业务阶段、协议层错误、统计信息。时间线看整体卡在哪一步业务阶段看是会话切换、安全访问还是数据传输协议层错误看NRC和DoIP响应码统计信息看TCP重传率、RTT趋势。统计TCP重传可以这样看Wireshark统计菜单里的“TCP Stream Graphs”和“I/O Graph”或者直接看Time Column里有没有明显的时间跳跃。重传太多时优先怀疑网线质量、交换机配置和半双工模式这些硬件因素在台架上经常出现但容易被软件背锅。抓包文件保留时间要长一点最好跟着项目版本走。我在交付阶段把所有OTA相关pcapng和当时的ECU软件版本一起归档后面再做Bootloader升级直接拿旧包对照新包很多异常一眼就能判断是不是回归问题。这个习惯救过我不少次。根据我个人经验DoIP抓包分析最有价值的产出不是“找到了某个NRC”而是建立对整条链路的体感。当你看到0x34响应里的maxNumberOfBlockLength能本能地估算出64MB要多少条0x36、大概多少秒当你看到0x78不再慌而是耐心等后续响应当你看到Alive Check请求第一反应是检查Tester自动应答有没有开——这些体感只能从一帧一帧的报文里建立起来。最后再分享一个小技巧抓包设备最好不要用测试仪的板载网卡用独立USB千兆网卡再接一个检测交换机或TAP这样能同时看到Tester侧和ECU侧的完整交互。别小看这个物理层面的隔离很多“抓不到包”“包丢了一半”的问题在换独立网卡后整条链路就清晰了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Model-Optimizer:大模型推理端到端加速工程实践 2026/9/28 6:50:24

Model-Optimizer:大模型推理端到端加速工程实践

1. 项目概述:Model-Optimizer不是工具名,而是一类工程实践的统称“Model-Optimizer”这个标题乍看像某个开源库或商业软件的名字,但结合NVIDIA、TensorRT-LLM、vLLM、PT文件转换、Qwen3-Embedding量化部署、RTX 4060 Laptop GPU适配等高频热词…

阅读更多 →
openGauss Worker线程与CPU飙升排查:从线程池到执行计划 2026/9/28 6:50:18

openGauss Worker线程与CPU飙升排查:从线程池到执行计划

1. Worker线程在openGauss里的角色,很多人一开始就没完全搞明白先说一个我自己经历过的场景。某次凌晨一点左右,运营反馈核心业务库的CPU使用率直接飙到90%以上,业务侧报错“连接数不足”。我登录服务器一看,top里冒出几十个名字类…

阅读更多 →
ROS2 Humble下TurtleBot3仿真导航全流程避坑指南 2026/9/28 6:50:18

ROS2 Humble下TurtleBot3仿真导航全流程避坑指南

1. 为什么这个流程值得你花三小时认真读完——一个ROS2新手的真实踩坑账本我第一次在Ubuntu 22.04上跑通turtlebot3自主导航仿真,花了整整两天半。不是因为不会敲命令,而是因为每一步都卡在别人没写清楚的细节里:rviz2加载模型时黑屏、amcl定…

阅读更多 →
眼底影像多任务深度学习:中心凹检测、血管分割与DR分级实战解析 2026/9/28 6:50:18

眼底影像多任务深度学习:中心凹检测、血管分割与DR分级实战解析

简介:一套面向眼底疾病智能诊断的 Python 深度学习源码,覆盖中心凹检测定位、视网膜血管分割和糖尿病视网膜病变分级三个典型任务,形成从眼底图像预处理、模型训练到结果评估的完整流程;面向计算机相关专业学生、高校教师及算法工…

阅读更多 →
Claude Code for VS Code 使用教程:settings.json 配置 TaoToken 接入 API Token 2026/9/28 6:50:18

Claude Code for VS Code 使用教程:settings.json 配置 TaoToken 接入 API Token

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
基于Spark与线性回归的电商销售预测系统全栈实战 2026/9/28 6:50:17

基于Spark与线性回归的电商销售预测系统全栈实战

1. 项目概述:为什么做电商销售预测系统做毕业设计或者企业实战项目,选"电商销售分析"这个题目是有讲究的。电商行业数据量大、业务场景清晰、指标定义明确,天然适合拿来做大数据处理和分析。标题里那套组合——Spark做计算、Hadoop…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉