3. DoIP协议栈核心机制
DoIP(Diagnostic over IP)并不是把UDS报文简单塞进TCP里,而是由ISO 13400-2定义了一整套“先发现、再声明、后激活、最后传输”的会话机制。在S32G诊断网关工程中,理解这套机制的关键,是把它看成两条并行的通道:一条是UDP承载的“轻量控制面”,负责车辆识别与声明;另一条是TCP承载的“可靠数据面”,负责路由激活与诊断报文传输。两者共用同一个DoIP通用头部,但端口、用途和状态机完全不同。
一、DoIP通用报文格式:所有消息的共同外壳
无论走UDP还是TCP,DoIP报文都以一个固定8字节的通用头部开始,这是解析一切DoIP流量的基础。头部字段依次为:协议版本(1字节)、协议版本反码(1字节)、载荷类型(2字节,大端)、载荷长度(4字节,大端)。协议版本反码是版本号按位取反,接收方用它做一致性校验,例如版本0x02对应反码0xFD,若两者不满足取反关系,报文应被丢弃。载荷类型决定后续载荷如何解释,常见取值包括:0x0000车辆识别请求、0x0004车辆声明/识别响应、0x0005路由激活请求、0x0006路由激活响应、0x8001诊断报文、0x8002诊断报文肯定应答、0x8003诊断报文否定应答。载荷长度只统计载荷本身,不含8字节头部,因此解析时必须先读头部再按长度取载荷,不能假设一个TCP段就是一个完整DoIP报文。
二、车辆识别与声明:让诊断仪先“看见”车
诊断仪接入网络后,第一步不是直接发UDS,而是通过UDP 13400端口广播车辆识别请求(0x0000),请求中可携带逻辑地址。网关或车辆节点收到后,以车辆声明/识别响应(0x0004)回复,响应载荷中包含VIN、逻辑地址、EID(实体标识)、GID(组标识)以及“进一步动作”字段。进一步动作字段很关键:0x00表示无需进一步动作,诊断仪可直接发起TCP连接;0x10表示需要中央安全认证;0x20表示需要车辆声明/识别请求的补充交互。在S32G网关中,通常由网关代理后端ECU完成声明,把VIN和网关逻辑地址返回给诊断仪,诊断仪据此判断目标车辆是否匹配。
实际工程中,车辆声明响应里的逻辑地址决定了后续诊断报文寻址。例如网关逻辑地址可设为0x0E00,诊断仪逻辑地址为0x0E80,后端某个ECU逻辑地址为0x0E10。诊断仪在路由激活时指定目标逻辑地址,网关据此建立“诊断仪—网关—目标ECU”的转发路径。若逻辑地址不匹配或目标不可达,网关会在路由激活响应中返回否定码,而不是等到UDS超时才发现。
三、路由激活:TCP连接上的“握手开关”
TCP连接建立后,诊断仪必须发送路由激活请求(0x0005),载荷包含激活类型、诊断仪逻辑地址、可选OEM特定数据。激活类型常见0x00(默认)和0x01(带OEM特定数据)。网关校验逻辑地址、激活类型和当前电源模式后,返回路由激活响应(0x0006),响应码0x10表示成功,其他如0x00、0x01、0x02、0x03、0x04、0x05、0x06、0x07分别对应未知源地址、所有socket已占用、源地址不匹配、源地址已激活、缺少认证、确认被拒绝、需要确认、需要路由激活等不同拒绝原因。只有收到0x10后,诊断仪才能在该TCP连接上发送0x8001诊断报文。
在S32G上实现时,路由激活状态通常与TCP连接一一绑定:每个连接维护一个激活标志、诊断仪逻辑地址和目标逻辑地址。若同一逻辑地址重复激活,应返回“源地址已激活”;若连接未激活就收到0x8001,应返回否定应答0x8003并保持连接,而不是直接断开,便于诊断仪纠正流程。
四、诊断电源模式:决定“能不能诊断”的前置条件
DoIP把车辆电源状态抽象为诊断电源模式,常见包括:默认(未上电或未知)、点火关闭、点火开启、运行等。网关在路由激活和诊断报文处理时都要检查当前电源模式。例如点火关闭时,网关可能只允许车辆识别与声明,拒绝路由激活;点火开启后才允许激活并转发诊断。S32G网关通常通过CAN或硬线采集KL15/KL30状态,映射为内部电源模式,再作为路由激活的准入条件。这样可避免在车辆休眠时被诊断仪意外唤醒或耗尽电量。
五、TCP/UDP端口与连接管理
ISO 13400-2规定DoIP默认使用UDP和TCP的13400端口。UDP用于车辆识别、车辆声明和部分广播场景,无连接、开销小;TCP用于路由激活和诊断报文,面向连接、保证顺序与重传。一个诊断仪可以建立多条TCP连接,但同一逻辑地址通常只允许一条激活连接。网关需要处理连接建立、激活、诊断传输、连接关闭的完整生命周期,并在连接异常断开时释放逻辑地址和路由资源。对于S32G这类多核网关,建议把UDP控制面和TCP数据面分配到不同核或不同任务,避免诊断大数据量传输阻塞车辆声明响应。
六、一个可参考的交互参数示例
假设诊断仪逻辑地址0x0E80,网关逻辑地址0x0E00,目标ECU逻辑地址0x0E10,车辆VIN为示例值。诊断仪广播0x0000后收到0x0004,进一步动作为0x00;随后建立TCP连接,发送0x0005,激活类型0x00,源地址0x0E80;网关在点火开启状态下返回0x0006,响应码0x10;诊断仪发送0x8001,目标地址0x0E10,网关转发至后端ECU并回传0x8002。若此时点火关闭,网关对0x0005返回0x0006且响应码为0x07(需要路由激活条件不满足),诊断仪应等待电源模式满足后重试,而不是反复重连。
| 报文类型 | 值 | 承载 | 作用 |
|---|---|---|---|
| 车辆识别请求 | 0x0000 | UDP | 发现车辆 |
| 车辆声明/识别响应 | 0x0004 | UDP | 返回VIN、逻辑地址、EID/GID |
| 路由激活请求 | 0x0005 | TCP | 申请诊断通道 |
| 路由激活响应 | 0x0006 | TCP | 0x10成功,其他为拒绝原因 |
| 诊断报文 | 0x8001 | TCP | 承载UDS请求/响应 |
把上述机制串起来看,DoIP的核心就是“UDP发现、TCP激活、按逻辑地址路由、受电源模式约束”。在S32G网关工程中,只要抓住通用头部解析、声明响应字段、路由激活状态机和端口/电源准入这四条主线,就能稳定实现符合ISO 13400-2的诊断入口。