1. 为什么UDS On DoIP的测试值得单独拿出来聊
做车载诊断的同行大概率都经历过这个阶段:一开始用CAN总线跑UDS,搞个CANoe或者类似工具,配好dbc和诊断描述文件,点几下就能发请求收响应,日子过得很舒服。但一旦项目切到以太网,诊断协议从UDS On CAN变成UDS On DoIP,很多人就懵了——IP地址怎么配、逻辑地址怎么填、路由激活怎么做、诊断报文怎么封装,每一步都跟CAN时代不一样。
UDS(Unified Diagnostic Services,统一诊断服务)本身是一套应用层协议,ISO 14229定义的就是它。它不关心底层跑的是CAN、CAN FD、LIN还是以太网。DoIP(Diagnostics over IP)则是ISO 13400定义的一套协议,专门解决“怎么在IP网络上传输诊断报文”这个问题。两者叠在一起,就是现在很多新车型、新域控制器都在用的UDS On DoIP方案。
DiVa在这个场景里扮演的角色,是一套诊断集成验证与自动化测试工具。它支持DoIP协议栈,能模拟诊断仪(Tester)向ECU发请求,也能模拟ECU响应外部诊断请求,还能做自动化测试序列。相比手搓Python脚本或者用通用网络工具拼报文,DiVa的优势在于它把DoIP的连接管理、路由激活、诊断消息封装这些底层细节都封装好了,你只需要关注诊断服务本身。
这篇文章适合谁看?如果你是刚接触UDS On DoIP的测试工程师,或者之前只用过CAN诊断、现在项目切到以太网需要快速上手,又或者你已经在用DiVa但对其中的配置细节和踩坑点还不太清楚,那这篇内容应该能帮你省下不少翻文档和试错的时间。我会从整体设计思路讲到具体配置步骤,再到实际测试中遇到的典型问题和排查方法,尽量把每个环节的“为什么”说清楚。
2. UDS On DoIP的整体设计与DiVa的定位
2.1 DoIP协议栈的分层逻辑
要理解DiVa怎么测UDS On DoIP,得先搞清楚DoIP协议栈的分层结构。从下往上说,最底层是物理层和链路层,通常是以太网PHY和MAC,跑的是100BASE-T1或者1000BASE-T1车载以太网。往上是网络层和传输层,用的是IP和TCP/UDP。DoIP协议本身位于传输层之上、UDS应用层之下,它定义了诊断消息在IP网络上的封装格式和通信流程。
DoIP报文有两种承载方式:UDP和TCP。UDP主要用于车辆发现、路由激活、状态查询这类轻量级交互;TCP则用于实际的诊断消息传输,因为诊断请求和响应通常需要可靠传输。DiVa在配置的时候,你需要分别指定UDP端口和TCP端口,默认情况下UDP用13400,TCP也用13400,但实际项目中可能会改。
再往上就是UDS层了。UDS定义了一系列诊断服务,比如0x10会话控制、0x22按标识符读数据、0x2E按标识符写数据、0x27安全访问、0x31例程控制等等。DiVa的作用就是让你能方便地构造这些UDS请求,通过DoIP通道发出去,然后解析ECU返回的响应。
2.2 为什么选DiVa而不是其他方案
市面上能做UDS On DoIP测试的工具不少,有商业的也有开源的。商业工具里,CANoe加以太网选件是很常见的选择,功能强大但价格不菲。开源方案里,有人用Python的udsonip库自己写脚本,灵活但需要自己处理很多底层细节。
DiVa的定位介于两者之间。它不像CANoe那么重,但比纯脚本方案提供了更多的封装和自动化能力。具体来说,DiVa在以下几个方面有优势:
- DoIP协议栈内置:不需要自己实现DoIP的报文封装和解析,配置好IP和端口就能用。
- 诊断描述文件支持:可以导入ODX或CDD文件,自动解析诊断服务和参数,减少手工构造报文的工作量。
- 自动化测试序列:支持用脚本或图形化方式编排测试步骤,适合做回归测试。
- 报文记录与回放:能抓取DoIP通信过程,方便事后分析。
当然,DiVa也不是万能的。如果你的项目用的是非标准DoIP实现,或者需要深度定制协议行为,可能还是得回到脚本方案。但对大多数遵循ISO 13400标准的项目来说,DiVa够用了。
2.3 测试拓扑的典型搭建方式
用DiVa测UDS On DoIP,典型的拓扑是这样的:DiVa运行在一台PC上,PC通过以太网接口连接到被测ECU所在的网络。如果ECU是直接带以太网接口的域控制器,可以直连;如果是通过网关路由的,DiVa就连到网关的以太网口,然后通过逻辑地址寻址到目标ECU。
这里有个关键点:DoIP通信需要先做路由激活。DiVa作为诊断仪,要先向网关或ECU发送路由激活请求,激活成功后才能发诊断消息。路由激活的过程中会协商一些参数,比如诊断仪的逻辑地址、通信协议版本等。DiVa的配置界面里通常有专门的DoIP配置页,填好这些参数才能建立连接。
另外,如果被测网络里有多个DoIP实体,DiVa需要能区分它们。DoIP协议里用逻辑地址来标识不同的ECU,逻辑地址通常是两个字节,比如0x0001到0x0FFF给诊断仪用,0x1000以上给ECU用。DiVa在发诊断请求时,需要在DoIP头部里填目标ECU的逻辑地址,ECU响应时也会带上自己的逻辑地址。
3. DiVa中UDS On DoIP的核心配置细节
3.1 DoIP通道配置的关键参数
在DiVa里新建一个DoIP通道,需要填的参数不少,但每一个都有明确的作用。我按重要性排个序来说。
本机IP和端口:这是DiVa作为诊断仪在网络上监听的地址。如果PC有多张网卡,一定要选对那张连到被测网络的网卡。端口默认13400,如果被测ECU用的是非标准端口,这里要改。
目标IP和端口:被测ECU或网关的IP地址。如果是直连ECU,就填ECU的IP;如果是通过网关,填网关的IP。端口同样默认13400。
诊断仪逻辑地址:DiVa作为Tester的逻辑地址,通常填0x0E00到0x0FFF之间的值。这个地址在路由激活请求里会发给ECU,ECU后续响应诊断请求时也会用这个地址作为目标。
目标ECU逻辑地址:你要诊断的那个ECU的逻辑地址。这个地址通常由ECU供应商定义,在诊断规范里有说明。填错了会导致ECU不响应或者返回否定响应。
通信协议版本:DoIP协议版本,通常是0x02(对应ISO 13400-2:2012)或0x03(对应ISO 13400-2:2019)。版本不匹配可能导致路由激活失败。
激活类型:默认是0x00,表示默认激活。有些ECU支持更复杂的激活类型,比如带OEM特定数据的激活,那就需要填0x01并附带额外数据。
这些参数里,最容易出错的是逻辑地址和协议版本。我见过不少新手把诊断仪逻辑地址填成0x0000,结果路由激活直接被拒。也见过协议版本填成0x01的,那是更老的版本,现在基本不用了。
3.2 UDS诊断服务的配置与参数化
DoIP通道建好之后,下一步是配置UDS诊断服务。DiVa支持两种方式:一种是手工定义诊断服务,另一种是导入诊断描述文件(ODX/CDD)。
手工定义的方式适合服务数量少、结构简单的场景。你需要在DiVa里新建一个诊断服务,填服务ID(比如0x22),然后定义请求参数和响应参数的格式。比如读数据服务0x22,请求参数是两个字节的DID(数据标识符),响应是DID加数据。DiVa里可以定义DID的解析规则,比如某个DID返回的是ASCII字符串,某个DID返回的是数值,这样解析出来的结果更可读。
导入诊断描述文件的方式适合服务数量多、结构复杂的项目。ODX文件里已经定义了所有诊断服务、DID、例程、安全访问算法等信息,DiVa导入后能自动生成对应的诊断请求模板。这种方式省时省力,但前提是你拿到的ODX文件是完整且正确的。我遇到过ODX文件里DID定义不全的情况,最后还是得手工补。
不管用哪种方式,有几个细节要注意:
- 会话与安全状态:很多诊断服务需要在特定的会话模式下才能执行,比如扩展会话(0x03)或编程会话(0x02)。有些服务还需要先通过安全访问(0x27)解锁。DiVa里可以配置这些前置条件,让测试序列自动处理。
- 响应挂起处理:ECU在处理某些耗时服务时会先返回0x78(响应挂起),等处理完再返回最终响应。DiVa需要能正确处理这种情况,否则会误判为超时。
- 否定响应解析:ECU返回否定响应时,会带一个NRC(否定响应码),比如0x31表示请求超出范围,0x33表示安全访问被拒。DiVa里可以配置NRC的解析和显示,方便快速定位问题。
3.3 自动化测试序列的编排思路
DiVa的自动化测试序列功能是它的一大卖点。你可以把多个诊断请求按顺序编排,加上判断条件和循环,形成一个完整的测试用例。
编排测试序列时,我通常按这样的结构来组织:
- 初始化阶段:建立DoIP连接,发送路由激活请求,切换到扩展会话,执行安全访问解锁。
- 测试主体:按测试用例设计,依次发送诊断请求,检查响应是否符合预期。
- 清理阶段:切换回默认会话,断开DoIP连接。
每个步骤都可以设置超时时间和重试次数。超时时间要根据ECU的实际响应速度来定,太短了容易误判,太长了测试效率低。我一般先用手动方式测一遍,记录每个服务的实际响应时间,然后在此基础上加50%到100%的余量作为超时时间。
判断条件方面,DiVa支持检查响应中的特定字节或字段。比如检查响应码是否为0x62(0x22服务的肯定响应),检查DID数据是否在预期范围内。对于更复杂的判断逻辑,可以用DiVa的脚本接口写自定义判断函数。
4. 实操过程与核心环节实现
4.1 环境准备与连接建立
先说环境准备。你需要一台装了DiVa的PC,PC上至少有一个以太网接口。如果PC自带的网口是普通办公网口,而车载以太网用的是100BASE-T1或1000BASE-T1,那还需要一个转换器,把普通以太网转成车载以太网。转换器选型上,常见的有Technica、Vector等品牌的媒体转换器,选的时候注意支持的速度和接口类型要匹配。
PC的IP地址要设置成和被测ECU同网段。比如ECU的IP是192.168.1.100,子网掩码255.255.255.0,那PC可以设成192.168.1.10。如果网络里有DHCP服务器,也可以让PC自动获取,但车载网络里通常没有DHCP,还是手工配静态IP更稳妥。
连接建立的过程是这样的:先在DiVa里新建DoIP通道,填好本机IP、目标IP、逻辑地址等参数。然后启动通道,DiVa会尝试与目标建立TCP连接。如果目标IP可达且端口开放,TCP连接会建立成功。接下来DiVa发送路由激活请求,这个请求是通过UDP发的,目标端口13400。路由激活请求里包含诊断仪逻辑地址和激活类型。ECU收到后,如果接受,会返回路由激活响应,里面包含ECU的逻辑地址和响应码。响应码为0x10表示成功,其他值表示失败。
路由激活成功后,DiVa就可以通过TCP连接发送诊断消息了。诊断消息的DoIP头部里会带上源地址(诊断仪逻辑地址)和目标地址(ECU逻辑地址),ECU根据目标地址判断这条消息是不是发给自己的。
4.2 诊断请求的构造与发送
构造诊断请求时,DiVa会根据你选择的诊断服务和填的参数,自动生成UDS请求报文。比如你要读DID 0xF190的数据,选择0x22服务,填入DID 0xF190,DiVa生成的UDS请求就是22 F1 90。然后DiVa会把这个UDS请求封装到DoIP消息里,加上DoIP头部,通过TCP发出去。
发送之前,DiVa会检查当前是否处于正确的会话和安全状态。如果配置了前置条件,DiVa会自动先发送会话切换和安全访问的请求。这一步很关键,很多新手直接发0x22请求,结果收到0x7F 0x22 0x33(安全访问被拒)或者0x7F 0x22 0x7F(当前会话不支持该服务),就是因为没有先做前置操作。
发送之后,DiVa会等待ECU的响应。响应可能是肯定响应,也可能是否定响应,还可能是响应挂起。DiVa会根据配置的超时时间来判断是否超时。如果收到响应挂起,DiVa会继续等待,直到收到最终响应或超时。
4.3 响应解析与结果判定
收到响应后,DiVa会按照诊断服务的定义解析响应数据。对于0x22服务,肯定响应的格式是62 DID DATA,DiVa会提取出DID和数据部分,然后根据DID的定义解析数据。比如DID 0xF190通常返回VIN码,是17个字节的ASCII字符串,DiVa可以配置成按ASCII解析,显示出来就是可读的VIN。
结果判定方面,DiVa支持多种判定方式:
- 响应码判定:检查响应码是否为预期的肯定响应码。
- 数据范围判定:检查响应数据是否在预期范围内。
- 数据一致性判定:检查响应数据是否与预期值一致。
- 自定义脚本判定:用脚本实现更复杂的判定逻辑。
判定结果会记录在测试报告中,通过或失败都有明确的标识。对于失败的用例,DiVa会记录实际的响应内容,方便事后分析。
4.4 批量测试与报告生成
单个用例调通之后,就可以做批量测试了。DiVa支持把多个测试用例组织成一个测试套件,一次性执行。执行过程中,DiVa会按顺序运行每个用例,记录每个用例的结果。执行完后,可以生成测试报告,报告里包含每个用例的详细信息,包括请求报文、响应报文、判定结果、执行时间等。
报告格式方面,DiVa通常支持HTML和XML两种。HTML格式适合人工阅读,XML格式适合导入到其他测试管理工具里做进一步分析。我一般会同时生成两种,HTML用来快速浏览,XML用来存档和做趋势分析。
批量测试的时候有个细节要注意:用例之间的状态隔离。如果一个用例把ECU切到了编程会话,下一个用例期望在默认会话下执行,那就会失败。所以每个用例开始时最好都做一次状态复位,切回默认会话,必要时做ECU复位。DiVa里可以在用例的前置步骤里配置这些操作。
5. 常见问题与排查技巧实录
5.1 路由激活失败的几种典型情况
路由激活失败是UDS On DoIP测试中最常见的问题之一。表现是DiVa发送路由激活请求后,收到否定响应或者根本收不到响应。根据我的经验,原因通常集中在以下几个方面:
逻辑地址不匹配:诊断仪逻辑地址或目标ECU逻辑地址填错了。诊断仪逻辑地址通常有规定范围,填了范围外的值会被拒。目标ECU逻辑地址如果填成了网关的地址而不是目标ECU的地址,路由激活可能成功但后续诊断请求会被网关拒绝或丢弃。
协议版本不匹配:DiVa配置的DoIP协议版本与ECU支持的版本不一致。有些ECU只支持特定版本,版本不对就直接拒绝。解决办法是查ECU的诊断规范,确认支持的协议版本。
激活类型不支持:有些ECU要求使用特定的激活类型,比如带OEM特定数据的激活。如果DiVa用了默认激活类型而ECU要求特定类型,就会失败。这种情况需要查规范,在DiVa里配置对应的激活类型和附加数据。
网络不通:PC和ECU之间的网络不通,TCP连接建立不起来。可以用ping命令先确认IP层是否可达,再用telnet或类似工具确认TCP端口是否开放。
ECU未上电或未初始化:ECU没上电或者还在初始化过程中,DoIP协议栈还没起来,自然无法响应路由激活。等ECU完全启动后再试。
排查的时候,我一般按这样的顺序来:先ping目标IP,确认网络层可达;再用网络抓包工具抓一下UDP 13400端口的报文,看路由激活请求有没有发出去、有没有响应;然后检查DiVa里的逻辑地址和协议版本配置;最后查ECU的诊断规范,确认激活类型和其他参数。
5.2 诊断请求超时或无响应的排查思路
路由激活成功但诊断请求超时或无响应,这个问题也很常见。排查思路如下:
确认目标逻辑地址是否正确:诊断请求的DoIP头部里带了目标地址,如果这个地址不是目标ECU的地址,ECU会忽略这条消息。检查DiVa里配置的目标ECU逻辑地址是否与ECU实际使用的地址一致。
确认会话和安全状态:很多诊断服务需要在特定会话下才能执行,有些还需要安全访问解锁。如果当前会话不对或未解锁,ECU会返回否定响应而不是不响应。但如果DiVa配置的超时时间太短,可能在收到否定响应之前就超时了。可以先手动发一个会话切换请求,确认能收到响应,再逐步排查。
确认TCP连接是否正常:DoIP的诊断消息是通过TCP传输的。如果TCP连接断了,诊断请求发不出去。DiVa里可以查看TCP连接状态,如果断了需要重新建立连接。
确认ECU是否支持该诊断服务:有些ECU可能不支持某些诊断服务,或者支持的DID范围有限。发了一个ECU不支持的服务或DID,ECU可能返回否定响应,也可能直接不响应。查ECU的诊断规范确认支持的服务和DID列表。
检查是否有其他诊断仪占用连接:DoIP协议通常只允许一个诊断仪同时与一个ECU建立诊断连接。如果已经有其他诊断仪连上了,DiVa再连可能被拒或者收不到响应。确认没有其他诊断仪在占用。
5.3 响应挂起处理不当导致的误判
响应挂起(NRC 0x78)是UDS协议里的一种机制,ECU用它来告诉诊断仪“请求收到了,正在处理,稍后给你最终响应”。如果DiVa没有正确处理响应挂起,可能会把0x78当成最终响应,判定为失败。
DiVa里通常有专门的响应挂起处理配置。你需要确认这个配置是开启的,并且设置的等待时间足够长。等待时间要根据ECU处理该服务的最长时间来定,一般设成几秒到十几秒。如果ECU处理时间超过等待时间,DiVa会超时,这时候需要调整等待时间。
另外,有些ECU在响应挂起期间会要求诊断仪发送“保持连接”的消息,否则会中断处理。DiVa里如果有这个配置项,也要确认是否开启。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 路由激活无响应 | 网络不通 | ping目标IP | 检查网线、IP配置、转换器 |
| 路由激活被拒 | 逻辑地址错误 | 查诊断规范 | 修正诊断仪或ECU逻辑地址 |
| 路由激活被拒 | 协议版本不匹配 | 查ECU支持版本 | 修改DiVa协议版本配置 |
| 诊断请求超时 | 目标逻辑地址错误 | 抓包看DoIP头部 | 修正目标ECU逻辑地址 |
| 诊断请求超时 | TCP连接断开 | 查看DiVa连接状态 | 重新建立连接 |
| 收到NRC 0x33 | 未做安全访问 | 检查前置步骤 | 配置安全访问前置条件 |
| 收到NRC 0x7F | 当前会话不支持 | 检查会话状态 | 切换到正确会话 |
| 响应挂起被误判 | 挂起处理未开启 | 检查DiVa配置 | 开启响应挂起处理并调整等待时间 |
| 批量测试用例失败 | 状态未隔离 | 检查用例前置步骤 | 每个用例前做状态复位 |
5.5 几个容易被忽略的实操心得
第一个心得是关于IP地址规划的。在实际项目里,被测网络里可能有多个DoIP实体,每个都有自己的IP和逻辑地址。建议在测试前先画一张网络拓扑图,标清楚每个ECU的IP、逻辑地址、支持的协议版本。这张图在排查问题时非常有用,能帮你快速定位是哪个环节出了问题。
第二个心得是关于抓包的。DiVa自带的报文记录功能能抓到DoIP层的报文,但有时候需要抓到更底层的以太网帧来分析。这时候可以在PC上装一个抓包工具,比如Wireshark,配合DiVa一起用。Wireshark能解析DoIP和UDS协议,看起来比原始十六进制直观得多。抓包的时候注意过滤条件,只看13400端口的流量,不然会被其他网络流量淹没。
第三个心得是关于测试用例设计的。UDS On DoIP的测试用例不要只测正常流程,异常流程同样重要。比如发一个超出范围的DID,看ECU是否返回正确的NRC;发一个长度不对的请求,看ECU是否健壮处理;在错误的会话下发服务,看ECU是否拒绝。这些异常用例往往能发现ECU诊断协议栈的bug。
第四个心得是关于DiVa工程文件的版本管理。DiVa的工程文件里包含了通道配置、诊断服务定义、测试序列等信息。项目迭代过程中,这些配置会不断修改。建议用版本管理工具管理DiVa工程文件,每次修改都记录变更内容。这样当测试结果出现异常时,可以回溯到之前的版本对比,快速定位是配置变更导致的还是ECU本身的问题。
6. 从单次测试到持续集成的扩展思路
单次手动测试跑通之后,下一步自然是考虑怎么把UDS On DoIP测试集成到持续集成流程里。DiVa通常提供命令行接口,可以用脚本调用DiVa执行测试序列并生成报告。这样就可以把诊断测试挂到CI流水线上,每次ECU软件更新后自动跑一遍诊断回归测试。
具体做法是:在CI服务器上装DiVa,配置好工程文件和测试序列。CI流水线里加一个步骤,调用DiVa的命令行接口执行测试,指定输出报告的路径。测试完成后,解析报告里的结果,如果有失败用例就标记流水线失败并通知相关人员。
这种做法的好处是诊断测试不再依赖人工执行,能更早发现ECU软件更新引入的诊断问题。缺点是需要维护CI环境和DiVa工程文件的同步,ECU诊断规范变更时,DiVa工程文件也要相应更新,否则测试可能失败但原因是配置过时而不是ECU有问题。
另外,DiVa的测试报告是XML格式的,可以导入到测试管理平台里做趋势分析。比如统计每个版本诊断测试的通过率,看是否有下降趋势。如果某个DID的读取测试连续几个版本都失败,那可能是ECU软件确实有问题,需要开发团队介入。
我个人在实际操作中的体会是,UDS On DoIP的测试复杂度确实比UDS On CAN高不少,主要高在网络配置和协议栈的环节。但一旦把DiVa的通道配置和诊断服务定义调通了,后续的测试用例编写和执行反而比CAN时代更灵活,因为以太网的带宽大,能同时跑多个诊断会话,测试效率更高。踩过的坑主要集中在逻辑地址和协议版本这两个参数上,新手一定要先把这两个参数确认清楚再往下做。