2、DoIP物理层与传输层:以太网物理层要求、TCP/UDP端口分配、DoIP报文封装格式
2.1 以太网物理层要求——别小看这根线
做DoIP,首先得把物理层搞定。说白了,就是你的车和诊断仪之间,到底用什么样的网线、什么样的接口来连。
我个人习惯把物理层分成两块来看:车载端和诊断仪端。
车载端现在主流是100BASE-T1(也叫BroadR-Reach)。它只用一对双绞线,就能跑100Mbps。我记得第一次在项目里看到这个,心里还犯嘀咕:一对线?能稳定吗?后来实测发现,只要线束质量过关,完全没问题。它比传统的100BASE-TX少了两对线,对整车线束减重很有帮助。
诊断仪端呢?通常是100BASE-TX或1000BASE-T。就是咱们电脑上常见的RJ45接口,四对线。这个大家都很熟了,我就不多啰嗦。
这里有个坑,我曾经踩过——连接器选型。车载端不能用普通的RJ45,得用专用的车载以太网连接器(比如H-MTD、MATEnet)。普通RJ45的机械强度不够,车一颠簸就容易接触不良。嗯,这一点你设计时一定要跟线束供应商确认清楚。
物理层关键参数速查表
| 参数 | 100BASE-T1(车载) | 100BASE-TX(诊断) |
|---|---|---|
| 线对数 | 1对 | 2对 |
| 速率 | 100 Mbps | 100 Mbps |
| 最大距离 | 15米(车内够用) | 100米 |
| 连接器 | H-MTD / MATEnet | RJ45 |
2.2 TCP/UDP端口分配——别搞混了
DoIP在传输层用了两个协议:TCP和UDP。它们分工很明确。
UDP端口:13400
这个端口用来做车辆发现和路由激活。你想想看,诊断仪刚连上车,还不知道车上有哪些ECU呢。这时候就得靠UDP广播。诊断仪发一个"谁在?"的广播包,车上的DoIP实体收到后,回复自己的IP地址和VIN码。
为什么用UDP?因为它快,无连接,适合这种一问一答的场景。我建议你抓包时重点关注这个端口,很多连接问题都是UDP广播没发出去导致的。
TCP端口:13400
等车辆发现之后,真正的诊断数据交换就走TCP了。诊断仪和ECU之间建立TCP连接,然后通过这个连接发送UDS诊断请求和响应。
TCP保证了数据不丢包、不乱序。你想想看,如果刷写ECU固件时丢了一个包,那整个ECU可能就变砖了。所以诊断数据必须走TCP。
我的小技巧: 端口号13400是ISO 13400标准定义的。你可以在代码里硬编码这个端口,但记得留个配置接口,万一客户要求改端口呢?我在一个项目里就遇到过,客户非要改成13401,说是跟他们的防火墙策略冲突。嗯,灵活一点总没错。
2.3 DoIP报文封装格式——一层套一层
DoIP的报文封装,说白了就是一层套一层。咱们从外往里看。
第一层:以太网帧头
MAC地址、VLAN标签(可选)、以太网类型(0x0800表示IPv4)。
第二层:IP头
源IP、目标IP。车载网络通常用IPv4,地址段比如192.168.0.0/16。
第三层:TCP/UDP头
源端口(随机高位)、目标端口(13400)。
第四层:DoIP头部
这才是DoIP协议的核心。它的结构如下:
+--------+--------+--------+--------+
| 协议版本 | 逆版本 | 负载类型 | 保留字节 |
+--------+--------+--------+--------+
| 负载长度(4字节) |
+--------+--------+--------+--------+
| 负载数据(可变长度) |
+--------+--------+--------+--------+
我来解释一下每个字段:
- 协议版本:1字节。目前是0x02(ISO 13400-2:2019)。
- 逆版本:1字节。就是版本号取反,比如0xFD。用来做校验,防止版本识别错误。
- 负载类型:2字节。这个很重要,它告诉接收方"这个包是干嘛的"。比如0x0001是车辆识别请求,0x0004是路由激活请求。
- 保留字节:2字节。填0x0000。
- 负载长度:4字节。表示后面负载数据的字节数。
- 负载数据:可变长度。具体内容由负载类型决定。
注意: 我曾经在调试时发现,某个ECU总是回复"负载类型不支持"。查了半天,发现是逆版本字段算错了。版本号是0x02,逆版本应该是0xFD,结果代码里写成了0xFE。就这一位之差,整个DoIP通信都建立不起来。所以,逆版本一定要用按位取反,别自己手动算。
2.4 一个完整的DoIP报文示例
咱们来看一个实际的抓包例子。这是一个车辆识别请求报文:
以太网帧头:
MAC目标: 01:00:5E:00:00:01 (组播)
MAC源: 00:1A:2B:3C:4D:5E
类型: 0x0800 (IPv4)
IP头:
源IP: 192.168.0.10
目标IP: 239.192.255.255 (组播)
UDP头:
源端口: 49152
目标端口: 13400
DoIP头部:
协议版本: 0x02
逆版本: 0xFD
负载类型: 0x0001 (车辆识别请求)
保留: 0x0000
负载长度: 0x00000000 (无额外负载)
你看,这个报文很简单。诊断仪通过UDP组播发出去,车上的ECU收到后,就知道"有人在找我",然后回复自己的信息。
我个人建议你刚开始做DoIP开发时,先学会用Wireshark抓包分析。把上面这个报文结构记在心里,然后对照着抓包数据看。看多了,你自然就熟了。
总结一下:
- 物理层:车载用100BASE-T1,诊断用100BASE-TX
- UDP端口13400:车辆发现和路由激活
- TCP端口13400:诊断数据交换
- DoIP头部:版本+逆版本+负载类型+长度+负载
下一章咱们会深入聊DoIP的车辆发现机制,包括VIN码的广播和路由激活的完整流程。到时候我会分享一个我在实车测试中遇到的"幽灵ECU"问题,挺有意思的。