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报文。

DoIP 通用头部与两类承载通道 通用头部(8 字节,UDP/TCP 共用) 版本 0x02 反码 0xFD 载荷类型(2B 大端) 载荷长度(4B 大端) → 载荷 UDP 通道(控制面) 端口 13400(广播/单播) 0x0000 车辆识别请求(VIN/逻辑地址) 0x0004 车辆声明/识别响应 0x0001 车辆识别请求(带EID) 无连接、可广播、用于发现与声明 TCP 通道(数据面) 端口 13400(面向连接) 0x0005 路由激活请求 0x0006 路由激活响应 0x8001 诊断报文(UDS) 连接建立后先激活,再传诊断

二、车辆识别与声明:让诊断仪先“看见”车

诊断仪接入网络后,第一步不是直接发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数据面分配到不同核或不同任务,避免诊断大数据量传输阻塞车辆声明响应。

判断DoIP交互是否正常,可按顺序检查:UDP 13400能否收到0x0004声明响应 → TCP 13400能否建立 → 0x0005是否返回0x10 → 0x8001是否收到0x8002肯定应答。任一步失败,先看对应响应码,再查逻辑地址与电源模式。

六、一个可参考的交互参数示例

假设诊断仪逻辑地址0x0E80,网关逻辑地址0x0E00,目标ECU逻辑地址0x0E10,车辆VIN为示例值。诊断仪广播0x0000后收到0x0004,进一步动作为0x00;随后建立TCP连接,发送0x0005,激活类型0x00,源地址0x0E80;网关在点火开启状态下返回0x0006,响应码0x10;诊断仪发送0x8001,目标地址0x0E10,网关转发至后端ECU并回传0x8002。若此时点火关闭,网关对0x0005返回0x0006且响应码为0x07(需要路由激活条件不满足),诊断仪应等待电源模式满足后重试,而不是反复重连。

报文类型值承载作用
车辆识别请求0x0000UDP发现车辆
车辆声明/识别响应0x0004UDP返回VIN、逻辑地址、EID/GID
路由激活请求0x0005TCP申请诊断通道
路由激活响应0x0006TCP0x10成功,其他为拒绝原因
诊断报文0x8001TCP承载UDS请求/响应

把上述机制串起来看,DoIP的核心就是“UDP发现、TCP激活、按逻辑地址路由、受电源模式约束”。在S32G网关工程中,只要抓住通用头部解析、声明响应字段、路由激活状态机和端口/电源准入这四条主线,就能稳定实现符合ISO 13400-2的诊断入口。