SOME/IP与SOME/IP SD规范介绍
时间:2022-09-20 21:30:00
这篇文章的标准来自AUTOSAR_PRS_SOMEIPProtocol.pdf(R21-11)和AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol.pdf(R21-11);
1. 前言
AOTOSAR – AUTomotive Open System ARchitecture,汽车开发系统结构;
SOME/IP – Scalable service-Oriented MiddlewarE over IP,基于IP可扩展面向服务中间件;
CM – Communication Management,通信管理/控制;
E2E – End-to-end communication protection,端到端通信保护(发现这些错误干预导致的数据失效并发出警告);
SoC – Service-Oriented Communication,服务通信标准化(即服务通信);
SecOC – Secure Onboard Communication,安全车载通信(车载通信加密验证的安全方案);
DTLS – Datagram Transport Layer Security,数据安全传输;
DDS – Data Distribution Service,数据传输服务;
RTPS – Real Time Publish Subscribe Proto,订阅协议实时发布;
TTL – Time To Live,生存时间(或有效时间);
TLV – Tag-Length-Value,每个子域由tag标签(T),子域值的长度(L)和子域取值(V)构成;
RPC – Remote Procedure Call,远程调用;
QoS – Quality of Service,服务质量;
BOM – Byte Order Mark,字节序;
SOA – Service-Oriented Architecture,服务框架;
2.简介
SOME/IP,基于IP可扩展面向服务中间件。
SOME/IP的作用: 通过服务接口数据SOME/IP规则处理后TCP/IP中传输。
SOME/IP的目标: 低负载、 良好的兼容性(可以在多个系统上运行)、 更好的与AUTOSAR适应系统结构、 满足个性化要求、 扩展性更好。
SOME/IP适用场景: 不同软件操作系统或者无操作系统的嵌入式设备、ECU间C-S实现通信模式,AUTOSAR下RPC PDUs数据的分析和传输。
SOME/IP主要内容: 数据规范、事件管理与远程调用规范。
SOME/IP与AUTOSAR关系演变:
- AUTOSAR 4.0 – 对已存在的SOME/IP基本支持新闻。
- AUTOSAR 4.1 – 添加了对SOME/IP-SD支持发布/订阅。
- AUTOSAR 4.2 – 添加转换器进行序列化等优化。
- AUTOSAR 4.3 – 修复了一些转换器错误,增加了对带 SOME/IP-TP 的大型UDP支持新闻和 SOME/IP-SD优化。
协议框架(IOS五层模型)
通讯方式
注:
分为远程调用 - RPC(Request/Response)、事件通知 - Notification(Subscribe/Publish)、访问过程数据 - Getter/Setter。
RPC: 由Client进行Request远程调用,Server请求内容Response;
Notification: 单向数据传输,Server订阅相关服务client发送消息;
Getter/Setter: Getter是Client主动获取数据,Setter由Client主动设置数据;Server需要将Client通过设置数据Response反馈给Client, Client确认数据设置是否成功。
3. SOME/IP协议规范
3.1 SOME/IP数据格式
3.1.1 Message ID
Service ID: 服务ID,识别应用程序(如汽车中的某个模块)。
Method ID: 方法ID,识别方法或事件(如车内某个模块要做的事/动作)。
3.1.2 Length
长度值为自request ID之后的数据长度。
3.1.3 Request ID
Client ID: 客户端ID,区分客户端/订阅者,在整车中是独一无二的。
Session ID: 会话ID,区分同一客户端/订阅者的多个请求或信息。
注:
- Request ID在响应位到达之前,客户端/订阅者不能重用Request ID;
- 如果会话处于未激活状态,Session ID = 0x而且订阅者会忽略这种反应;
- 若会话处于激活状态,Session ID = 0x0001 ~ 0xFFFF,并按用例增加;
- 若Session ID = 0xFFFF后,将从0x重新开始计数001;
3.1.4 Protocol Version
协议版本号,固定为1。
3.1.5 Interface Version
服务接口版本号。
3.1.6 Message Type
Number | Message Type | Des |
---|---|---|
0x00 | REQUEST | A request expecting a response (evenvoid). |
0x01 | REQUEST_NO_RETURN | A fire&forget request. |
0x02 | NOTIFICATION | A request of a notification/event callback expecting no response. |
0x80 | RESPONSE | The response message. |
0x81 | ERROR | The response containing an error. |
0x20 | TP_REQUEST | A TP request expecting a response (evenvoid). |
0x21 | TP_REQUEST_NO_RETURN | A TP fire&forget request. |
0x22 | TP_NOTIFICATIO | A TP request of a notification/event callback expecting no response. |
0xa0 | TP_RESPONSE | The TP response message. |
0xa1 | TP_ERROR | The TP response containing an error. |
注:
对于TP消息,Message Type的第三个高位要设置为1,以表示这个SOME/IP是一个segment(这个是SOME/TP中的概念,类似于分包/分片/分段),那么0x00将对应0x20;
在AUTOSAR中,使用了5种类型:REQUEST、REQUEST_NO_RETURN、NOTIFICATION、RESPONSE、ERROR;
3.1.7 Return Code
事件返回码。
Message Type | Return Code |
---|---|
REQUEST | 0x00 |
REQUEST_NO_RETURN | 0x00 |
NOTIFICATION | 0x00 |
RESPONSE | Return Codes |
ERROR | Return Codes(No 0x00) |
Return Codes
ID | Value | Des |
---|---|---|
0x00 | E_OK | Success. |
0x01 | E_NOT_OK | An unspecified error occurred. |
0x02 | E_UNKNOWN_SERVICE | The requested Service ID is unknow. |
0x03 | E_UNKNOWN_METHOD | The requested Method ID is unknown. Service ID is known. |
0x04 | E_NOT_READY | Service ID and Method ID are known. But Applicationnot running。 |
0x05 | E_NOT_REACHABLE | System running the service is not reach. |
0x06 | E_TIMEOUT | A timeout occurred. |
0x07 | E_WRONG_PROTOCOL_VERSION | Version of SOME/IP protocol not supported. |
0x08 | E_WRONG_INTERFACE_VERSION | Interface version mismatch. |
0x09 | E_MALFORMED_MESSAGE | Deserialization err. |
0x0a | E_WRONG_MESSAGE_TYPE | An unexpected message type was received. |
0x0b | E_E2E_REPEATED | Repeated E2E calculation err. |
0x0c | E_E2E_WRONG_SEQUENCE | Wrong E2E sequence. |
0x0d | E_E2E | Not further specified E2E. |
0x0e | E_E2E_NOT_AVAILBLE | E2E not available. |
0x0f | E_E2E_NO_NEW_DATA | No new data for E2E calculation present. |
0x10 - 0x1f | RESERVED | Generic SOME/IP err. |
0x20 - 0x5e | RESERVED | Specific err. |
3.1.8 Payload
有效负载/数据段。
数据长度说明,SOME/IP有效载荷字段的大小取决于所使用的传输协议。使用UDP时,SOME/IP有效负载应在0到1400字节之间。需要对1400字节进行限制,以允许将来对协议栈进行更改(例如更改为PV6或添加安全手段)。由于TCP支持有效负载的分段,因此会自动支持更大的大小。
端序问题,应该使用大端序(高字节低地址)
3.3 SOME/IP数据序列化
什么是序列化与反序列化?
序列化是指将数据结构或对象按定义的规则转换成二进制串的过程。
反序列化是指将二进制串依据相同规则重新构建成数据结构或对象的过程。
而本质就是一种编码规范。
在SOME/IP中使用序列化的目的和作用?
使数据按照固定格式进行编排成为字节序,实现数据在网络上的传输。
通信协议序列化是什么?
3.3.1 内存对齐与填充
通过在数据后插入填充元素来对齐数据的开头,以确保对齐的数据从特定的内存地址开始。对于有些处理器架构可以更高效地访问数据。
当可变元素不是序列化数据流中最后一个元素,应依据规则对可变元素进行位填充来实现数据对齐。
填充示例:
示例1.
示例2.
注:数据对齐填充应尽量以8、16、32、64、128或256长度长度进行。
3.3.2 带有标识符合可选成员的结构体数据类型和参数
3.3.3 基础数据类型序列化(Basic Datatypes)
Type | DES | Size[bit] |
---|---|---|
Boolean | TRUE/FALSE | 8bit |
uint8 | unsigned | 8bit |
uint16 | unsigned | 16bit |
uint32 | unsigned | 32bit |
uint64 | unsigned | 64bit |
sint8 | signed | 8bit |
sint16 | signed | 16bit |
sint32 | signed | 32bit |
sint64 | signed | 64bit |
float32 | floating | 32bit |
float64 | floating | 64bit |
3.3.4 结构体序列化(Struct)
结构体序列化是依次按序进行的,如下图示例。
结构体序列化可按照TLV标准添加length和tag字段,如下图示例。
示例1.
示例2.
示例3.
结构体序列化也可以不配length参数,只配tag参数,如下图示例。
示例4.
3.3.5 字符串序列化(Strings)
传输ASCII、UTF-8、UTF-16字符的固定长度或动态长度字符串。对于动态长度字符串,字符串数据前有一个大端序的字符串长度参数。
3.3.6 数字序列化(Arrays)
包含相同参数类型。有固定长度和动态长度。对于具有动态长度的数组,使用长度字段。
3.3.7 枚举序列化(Enumeration)
枚举,具有命名不同值选项的uint。
3.3.8 位域序列化(Bitfield)
8、16、32位参数,每一位代表一个布尔值。每个布尔值可以有一个名称,也可以有一个真值和假值的名称。
3.3.9 联合体/变态类型序列化
可以携带预定义参数类型的参数,该参数在运行时确定。序列化使用长度字段、类型字段和参数数据。
variant是什么数据类型?
示例1.(uint8)
示例2.(uint32)
3.3.10 TLV序列化(Tag Length Value)
3.3 SOME/IP传输标准
将会介绍远程过程调用(RPC)、事件通知、错误处理。
1、SOME/IP支持TCP和UDP;
2、服务器运行同一服务的不同实例,则属于不同服务实例的消息应通过服务器的传输层端口映射到服务实例(通过不同的端口区分不同的实例);
3、传输层payload里允许有多个SOME/IP消息,不同的SOME/IP消息依据长度字段切分;
4、每个SOME/IP payload都有自己的SOME/IP头部结构;
5、一个服务实例可以有3种方法进行方法、事件、通知消息的传输: 最多一个TCP连接、最多一个UDP单播、最多一个UDP广播;
3.3.1 UDP绑定
UDP绑定即基于UDP协议实现的SOME/IP消息传输。
SOME/IP信息是UDP的Payload部分,若是UDP Payload数据过大,将会被网络层分片。
一个单播UDP可以处理配置为UDP单播通信的方法、事件、通知。
一个多播UDP可以处理配置为UDP多播通信的方法、事件、通知。
3.3.2 TCP绑定
TCP绑定即基于TCP协议实现的SOME/IP消息传输。
一个单播TCP可以处理配置为UDP单播通信的方法、事件、通知。
注:客户端通信前应负责建立TCP连接;客户端负责TCP的失败重连;客户端负责TCP连接关闭;客户端应在TCP所有连接服务不可用时断开连接(因为客户端需要事件处理数据,决定是否可以断开连接);客户端应在被服务端关闭TCP后被断重建连接;
3.3.3 多个服务实例
同一服务的服务实例通过不同的实例ID进行标识。应支持多个服务实例驻留在不同的ECU上,以及一个或多个服务的多个服务实例驻留在一个ECU上。
虽然不同服务的多个服务实例应能够共享所用传输层协议的相同端口号,但单个ECU上相同服务的多个服务实例应使用不同的服务实例端口。
虽然实例ID用于服务发现,但它们不包含在SOME/IP头中。服务实例可以通过服务ID与套接字(即IP地址、传输协议(UDP/TCP)和端口号)的组合来识别。建议实例对UDP和TCP使用相同的端口号。如果服务实例使用UDP端口x,则只有该服务的该实例,而不是同一服务的另一实例,应该为其服务使用TCP端口x。
3.3.4 SOME/IP TP
当基于UDP传输的SOME/IP消息太大,而需要分片时,应使用SOME/IP-TP。
使用SOME/IP-TP的SOME/IP消息应激活Session ID处理;
原始信息必须具有唯一的Session ID;
所有SOME/IP-TP分段应携带原始消息的Session ID,因此,它们都具有相同的Session ID;
SOME/IP-TP分段应将Message类型的TP标志设置为1;
发送时应对More Segment Flag = 1的信息进行等长分段(为1392byte,除最后一片),且按顺序/升序发送,不可以重复发送分片报文;
接收时根据SOME/IP-TP包中的Message ID、Protocol Version、Interface Version、Message Type等标志进行数据重组;
可接收来自不同客户端(IP、port、ID)相同Message ID重新组合多条消息(良好的缓冲机制);
当接收数据大于设置重组缓冲区时,剩余的数据将会被舍弃;
当新分片数据来临,旧分片的重组任务未结束,则应抛弃旧分片开始新的分片任务;
当检测到分片数据丢失后,应取消该片所属的重组任务;
当检测到分片数据重复后,应可以将重复分片覆盖,使重组可以正常进行;
接收完每个分片之后都应该返回Return Code,但只用最后一个分片的Return Code;
数据重组后应该进行完整性校验,正确重组的数据才能传递给应用程序;
数据重组后,应将分段标志设置为0;
接收数据时,应该可以升序或者降序的对分片数据进行重组;
接收数据时,应一个缓冲区对应一个原始数据的分片的重组,避免相同事件(IP、port、Message ID、TP);
SOME/IP-TP分段应在SOME/IP头之后有一个TP头,SOME/IP TP头格式如下图所示:
有效负载为5880的SOME/IP数据包<示例>,如下所示:
图中前4个段分别包含1392个有效负载字节,每个段的“More SegmentsFlag”设置为“1”。第5段是5880有效负载的剩余部分312字节,“More SegmentsFlag”设置为“0”。
3.4 SOME/IP通信模式
3.4.1 Request/Response
Request/Response模式为最常见的通信模式,一端(客户端)发送Request,另一端(服务端)回复Response。
客户端发送Request消息有如下要求:
构建Payload;
依据方法类型设置对应的Message ID;
Length = 8 + Payload长度;
Request ID应该是唯一的(如何确定是唯一的?);
设置Protocol Version;
设置Interface Version;
设置Message Type = 0x00;
设置Return Code = 0x00;
服务端发送Response消息有如下要求:
构建Payload;
复制Request中的Message ID;
Length = 8 + Payload长度;
复制Request中的Request ID;
设置Message Type = 0x80/0x81;
设置Return Code ;
注:服务器/客户端在接收到完整的请求/响应消息前,忽略新的请求/响应报文。
3.4.2 Fire&Forget
Fire&Forget类型通信仅发出Request但不会收到Response。
客户端发送Request消息有如下要求:
构建Payload;
依据方法类型设置对应的Message ID;
Length = 8 + Payload长度;
Request ID应该是唯一的(如何和确定是唯一的?);
设置Protocol Version;
设置Interface Version;
设置Message Type = 0x01;
设置Return Code = 0x00;
注:Fire&Forget通信模式服务端不会回复,即使是发生了错误。错误处理和返回码应该由应用程序进行定义与实现。
3.4.3 Notification Events
Notification描述了发布/订阅机制的概念。
通常是服务端发布服务客户端订阅的服务;
服务端会向客户端发送事件信息,如更新的参数、发生的事件等;
服务端通过SOME/IP的Notification向客户端发布消息,客户端通过SOME/IP-SD订阅服务。
服务端发送SOME/IP Notification消息要求:
构建Payload;
依据方法类型设置对应的Message ID;
Length = 8 + Payload长度;
设置Client ID = 0x00;
设置Session ID;
设置Protocol Version;
设置Interface Version;
设置Message Type = 0x02;
设置Return Code = 0x00;
发送Notification消息的策略<示例>:
循环更新:在固定的时间间隔内发送更新值,(例如,每100毫秒发送一次安全相关的活动消息)。
更改时更新:一旦“值”发生更改(例如门打开),立即发送更新。
Epsilon改变:仅当与最后一个值的差值大于某个Epsilon时发送更新。这个概念可能是自适应的,即预测基于历史。因此,只有当预测值和当前值之间的差值大于Epsilon时,才会传输更新。
3.4.4 Fields
一个Fields表示一个状态的有效值,订阅该字段的订阅者将字段值作为初始事件;
一个Fields包含getter、setter、notification event;
一个Fields没有getter、setter、notification event是错误的,一个Fields至少要包含一个getter或setter或notification event;
一个Fields的getter运用于当request的payload为空时,对应的response的payload中将会有getter字段;
一个Fields的setter运用于当request的payload中有请求值字段时,对应的response的payload中有该字段的当前值;
当客户端订阅该Fields时,事件通知着应该发送一个事件消息,将字段值发送给客户端;
3.4.5 Error Handling
服务端应具备错误处理能力;
错误处理可以在应用程序或通信层中实现,即在response中携带Return Code或Message Type = 0x81类型消息;
3.4.6 Return Code
见3.1.7节。
3.4.7 Error Message
SOME/IP消息接收者不应对events/notifications回复错误消息;
SOME/IP消息的接收者不应对fire&forget methods回复错误消息;
如果events/notifications和fire&forget methods的Message Type字段被错误地设置为Request或Response,SOME/IP消息的接收者不应回复错误消息;
3.4.8 Error Processing Overview
当SOME/IP消息基于UDP传输时,应做如下验证:1.UDP数据报大小应至少为16字节(SOME/IP最小长度);2.UDP首部中Length字段值应小于或等于UDP Payload字节数;
错误检测流程,如下图所示:
3.4.9 通信错误和通信错误处理
RPC消息传输时,对消息传递的可靠性做了定义,1.可能 :不能保证一定到达(基于超时的UDP实现);2.至少一次:至少被到达一次(基于UDP实现);3.仅一次 :仅到达一次(基于TCP实现);
超时<示例>:
3.4.10 Interface Version兼容处理
Interface Version标识了Payload的格式版本。
Payload格式和如下因素有关:
服务接口规范;
序列化配置(如可变大小数组、长度字段、填充、TLV、SOME/IP-TP);
Interface Version和如下因素有关:
Payload格式的不兼容;
服务行为的不兼容;
应用程序的设计要求;
Interface Version不受Payload格式变换的影响;
4. SOME/IP SD
SOME/IP SD全称,SOME/IP Service Discovery,即服务发现。在client与server间进行数据传输前,需要检测网络连接、询问server服务能力、数据传输要求、server与client之间的发布/订阅处理等,这样的一系列过程叫做服务发现;
SOME/IP SD报文特征,报文结构有普通SOME/IP报文一致,但Message ID = 0xFFFF8100;
SOME/IP SD功能,定位服务实例、检测服务实例状态、订阅/发布管理;
SOME/IP SD当前只支持基于IP的通信;
SOME/IP SD依赖于SOME/IP,SOME/IP支持TCP和UDP,但SOME/IP SD限制只能通过UDP(因为UDP单播、多播、延时小可满足SOME/IP SD要求);
SOME/IP SD消息封装的层次结构:
4.1 SOME/IP SD头部数据格式
SOME/IP SD 的传是基于SOME/IP的,只是部分字段给的是固定值,SOME/IP SD头部在SOME/IP的Payload部分;
SOME/IP-SD 消息的Client ID = 0x0000,因为只存在一个SOME/IP-SD实例;
SOME/IP-SD 消息可以配置Client ID前缀;
SOME/IP-SD Session ID遵循SOME/IP的原则(不能设置为0,从1开始并依次递增);
SOME/IP-SD 头部从falgs字段开始;
flags字段含义,如下图所示:
bit 0: reboot flag,在重新启动后所有消息的该标记应该设置为1,直到Session ID递增循环重新从1开始,Reboot标志将被设置为0;
发送方:有一个多播计数器;每个单播有一个计数器;
接收方:每个多播有一个计数器;每个单播有一个计数器;
reboot检测:old.reboot == 0 且 new.reboot == 1,则为检测到reboot;old.reboot ==1 并且new.reboot ==1 并且old.session_id>=new.session_id,则检测到reboot;
bit1: Unicast,单播标志;
当该位为1时,代表支持单播方式接收消息(该位始终设置为1);
bit3: Explicit Initial Data Control,ECU支持初始化数据控制标志(该标志始终设置为1);
其余位: 未定义位设置为0,接收方做忽略处理。
Reserved字段: 无;
Entries Array length 与 Entries Array: 携带了服务和服务实例信息;
Entries array length 与 Entries array: 是Entries的附加信息;
SOME/IP SD
4.2 Entries
SOME/IP SD支持在Entries array中放置多个Entry;
Entries 用于同步服务实例状态(提供服务、发现服务)和发布/订阅管理;
Entries 有服务类型Entries和事件类型Entries;
4.2.1 Service Entries
格式如下图所示:
Type字段: 包含FindService(0x00)、OfferService(0x01)、StopOfferService(0x01);
Index 1st Options: 在option array中要运行的第一个Option的索引,0表示第一个SOME/IP SD数据包;
Index 2nd Options: option array中要运行的第二个Option的索引,0表示第一个SOME/IP SD数据包;
of Opt 1: 描述第一个Option运行使用的option数量,0表示没有运行的option;
of Opt 2: 描述第二个Option运行使用的option数量,0表示没有运行的option;
Service ID: 描述entry相关的服务或服务实例的Service ID;
Instance ID: 描述entry相关的服务实例的实例ID,如果被设置为0xFFFF,表示一个服务的所有服务实例;
Major Version: 服务(实例)的主版本号,0xFF表示任意版本;
TTL: 描述Entry的生命周期,以秒为单位;
Minor Version: 服务的次要版本,0xFFFFFFFF表示任意版本;
4.2.1.1 Find Service Entry
发现服务Entry用于查找当前服务状态未知的服务实例(没有接收到当前service offer但仍有效),即client查找服务;
发送方不可以在发现服务Entry中引用端口、多播选项;
接收方应该忽略Endpoint Options和Multicast Options,其他选项则应该仍被使用;
接收发现服务Entry时,通过Service ID、Instance ID、Major Version、Minor Version去匹配服务实例;
发现服务Entry格式规则,如下所示:
Type: 0x00;
Service ID: 0xFFFF代表查找所有服务实例,否则设置为查找单个实例的实例ID;
Major Version: 0xFF任何版本的服务,否则返回指定主版本的服务;
Minor Version: 0xFFFF FFFF任何版本的服务,否则返回指定次版本的服务;
TTL: 生命周期,超时后将视为不存在,0xFFFFFF表示直到下次重启前一直有效,但不可以设置为0x000000;
4.2.1.2 Offer Service Entry
用于Sever向Client提供服务;
Offer Service Entry至少引用一个IPv4/IPv6端口Option,以表明服务如何可达;
对于服务所需的传输层协议(UDP/TCP),如果支持IPv4,则应添加IPv4端口Option,否则若支持IPv6,则应添加IPv6端口Option;
接收接收Offer Service Entry、或者后续Offer Service Entry、Stop Offer Service Entry时,都通过Service ID、Instance ID、Major Version、Minor Version参数去匹配服务实例,并且后续Entry与初始Entry参数应该保持一致;
提供服务Entry格式规则,如下所示:
Type: 0x01(表示Offer Service);
Service ID: 应设置为提供的服务实例的服务ID;
Instance ID: 应设置为提供的服务实例的Instance ID;
Major Version: 应设置为提供的服务实例的主要版本;
Minor Version: 应设置为提供的服务实例的次要版本;
TTL: 服务实例的生命周期。在此生命周期之后,服务实例将被视为未提供,为0xFFFFFF,则Offer Service Entry直到下一次重新启动都应被视为有效,TTL不应设置为0x000000,因为这被认为是停止Offer Service Entry;
4.2.1.3 Stop Offer Service Entry
用于Sever向Client提供服务;
规则与Offer Service Entry一致,但TTL应设置为0x000000;
4.2.1.4 Usage of Options in Entries
Entries中Option的使用,如下图所示;
不是很明白这个表的关系?
4.2.2 Eventgroup Entries
Eventgroup Entries格式规则,如下图所示:
Type字段: encodes Subscribe (0x06), StopSubscribeEventgroup (0x06),SubscribeAck (0x07) and SubscribeEventgroupNack (0x07);
Index 1st Options: 在option array中要运行的第一个Option的索引,0表示第一个SOME/IP SD数据包;
Index 2nd Options: option array中要运行的第二个Option的索引,0表示第一个SOME/IP SD数据包;
of Opt 1: 描述第一个Option运行使用的option数量,0表示没有运行的option;
of Opt 2: 描述第二个Option运行使用的option数量,0表示没有运行的option;
Service ID: 描述entry相关的服务或服务实例的Service ID;
Instance ID: 描述entry相关的服务实例的实例ID,任何实例的该值都不应该被设置为0xFFFF;
Major Version: 服务(实例)的主版本号;
TTL: 描述Entry的生命周期,以秒为单位;
Reserved: 应该被设置为0x000;
Counter: 用于区分同一订阅服务器的相同订阅事件组。如果未使用,则设置为0x0;
Eventgroup ID: 事件组ID;
一个entry的Major Version应该与相应的服务接口版本匹配;
对于经典平台上的服务发现,服务端服务和客户端服务的主版本必须分别与相应服务接口的接口版本相匹配;
两个不同的option都在运行(1st Option 和 2nd Options): 有两种不同类型的Option,多个SOME/IP SD条目之间通用的Option和每个SOME/IP SD条目的各自的Option。支持两种不同的选项运行是支持这两种类型选项的最有效方法,同时保持wire格式的高效性;
每个Option运行应参考第一个Option和当前运行的Option数量;
若Option数量为0,Option的运行将被视为空运行;空运行Option的索引应该设置为0;
4.2.2.1 Subscribe Eventgroup Entry
用于订阅事件组;
客户端通过什么方式(单播端口/多播端口)订阅事件,就通过什么方式接收订阅的事件信息;
Subscribe Eventgroup Entry最多支持两个IPv4或者两个IPv6端口,分别是一个UDP和一个TCP端口;
Subscribe Eventgroup Entry支持一个IPv4多播或者一个IPv6多播配置,多播只可以基于UDP实现;
网络传输设置时,应该考虑如下问题:
1.若服务器仅使用IP多播进行事件信息传输,则Subscribe Eventgroup Entry不需要设置UDP Endpoint Option;
2.若服务器在传输某个事件组的初始事件时,则Subscribe Eventgroup Entry将会引用对应的Endpoint Option;
3.若客户端服务使用多播订阅事件,由服务器发送初始化;这里不是很好理解其含义?
如果服务器接收到不带UDP端点选项的Subscribe Eventgroup Entry,且Eventgroup的多播_阈值未配置为值1,则应将Subscribe EventGroupNack发送回客户端;
Subscribe Eventgroup Entry按照如下规则设置:
Type: 0x06;
Service ID: 应设置为包含订阅的事件组的服务实例的服务ID;
Instance ID: 应设置为包含订阅的事件组的服务实例的实例ID;
Major Version: 应设置为订阅的事件组的服务实例的主版本;
Eventgroup ID: 应设置为订阅的事件组的事件组ID;
TTL: 应设置为订阅的生命周期;为0xFFFFFF,则Subscribe Eventgroup Entry应被视为有效,直到下一次重新启动;TTL不应设置为0x000000,否则将被认为是Stop Offer Service Entry;
Reserved: 应设置为0x00,直至另行通知;
**Counter:**用于区分并行订阅同一服务的同一事件组(仅端口不同)。若不使用,设置为0x0;
4.2.2.2 Stop Subscribe Eventgroup Entry
用于取消订阅事件组;
Stop Subscribe Eventgroup Entry规则与Subscribe Eventgroup Entry基本一致,除TTL: 0x000000外;
4.2.2.3 Subscribe Eventgroup Acknowledgement (Subscribe Eventgroup Ack) Entry
用于表示Subscribe Eventgroup Entry已经被接受;
Type: 0x07;
Service ID、Instance ID、Major Version、Eventgroup ID、TTL、Reserved、Counter应该与正在回答的订阅事件组一致;
使用多播配置的Subscribe Eventgroup Ack应该使用IPv4 MulticastOption 、IPv6 Multicast Option;
当收到Subscribe Eventgroup Ack或Subscribe Eventgroup Nack时,Service ID、Instance ID、Eventgroup ID、Major Version应与对应的Subscribe Eventgroup Entry匹配,用于标识服务实例的事件组;
4.2.2.4 Subscribe Eventgroup Negative Acknowledgment(Subscribe Eventgroup Nack) Entry
用于表示Subscribe Eventgroup Entry没有被接受;
Type: 0x07;
TTL: 0x000000;
Service ID、Instance ID、Major Version、Eventgroup ID、TTL, Reserved、Counter应该与正在回答的订阅事件组一致;
触发Subscribe Eventgroup Nack事件的原因,有如下几种:
Service ID、Instance ID、Eventgroup ID、Major Version组合未知;
客户端未打开所需的TCP连接;
配置的Option出现问题;
服务器资源问题;
客户端在做Subscribe Eventgroup Nack响应时,若是使用TCP协议,在响应前应该先检测TCP的连接情况(客户端应该保证TCP连接状态),如下检测:
检查是否收到数据;
发送Magic Cookie消息并等待TCP ACK;
重新建立TCP连接;
4.2.3 服务和事件的Endpoints处理
Endpoints将会在4.3.3-4.3.8节介绍,即端口。
如果静态配置的值与这些选项中的值不同,则服务发现应使用端点和多播选项中传输的IP地址和端口号覆盖这些IP地址和端口号;
Endpoints Option的IP地址和端口号也用于传输事件和通知事件;
基于UDP传输时,Endpoints Option作为事件和通知事件的源IP和源Port,也是客户端发送方法和请求的地址;
基于TCP传输时,Endpoints Option用做客户端需要打开的IP和Port,用于客户端接收事件信息;
SOME/IP允许同时使用UDP和TCP;
消息使用的传输协议由配置决定,Service可以同时支持UDP和TCP端口,前提是都做了配置;
不同的传输协议(TCP/UDP)不可以提供相同的服务;
4.2.3.1 Service Endpoints
Endpoints将会在4.3.3-4.3.8节介绍,即端口。
Offer Service Entries引用的Endpoints Option:1.服务实例在服务端可以访问的IP和Port;2.服务实例发送事件的源IP和源Port;
除了Offer Service Entries的Endpoints Option中给出的端口外,服务实例的事件不得从任何其他端口发送;
如果一个ECU提供多个服务实例,这些服务实例的SOME/IP消息应通过Offer Service Entries引用的Endpoints Option中传输的信息来区分;
4.2.3.2 Eventgroup Endpoints
Endpoints将会在4.3.3-4.3.8节介绍,即端口。
Subscribe Eventgroup Entries中引用的Endpoints Option也可以用于此服务实例发送单播UDP/TCP的SOME/IP事件;
Subscribe Eventgroup Entries中引用的端口选项是客户端的IP和Port;
Subscribe Eventgroup Ack Entries最多引用1个使用Internet协议(IPv4或IPv6)的多播选项;
初始事件应使用单播从服务器传输到客户端;
Multicast Option设置UDP作为传输协议;
客户端应尽快打开Subscribe Eventgroup Ack Entry引用的Multicast Option中指定的端口,以免错过多播事件;
不同Port和Multicast Option的 <示例>,如下图所示:
服务器在服务器UDP-Endpoint SU和TCP-Endpoint ST提供服务实例;
客户端应该主动打开TCP连接;
客户端发送带有客户端UDP-Endpoint CU(单播)和TCP-Endpoint CT的Subscribe Eventgroup Entry;
服务器以Multicast MU的Subscribe Eventgroup Ack Entry进行应答,然后发生以下操作:
客户端调用服务器上的方法;
对于UDP,CU->SU:请求,SU->CU:响应;
对于TCP,这将是:CT->ST:请求dyn,ST->CT:响应;
服务器发送单播UDP事件:SU->CU;
服务器发送单播TCP事件:ST->CT;
服务器发送多播UDP事件:SU->MU;
4.3 Options
Options用于将附加信息传输给Entries(例如,如何访问服务实例的信息(IP地址、传输协议、端口号));
Options字段类型,如下:
Length: 表示这个Option的字节数(除Length和Type外的字节数);
Type: 表示这个Option的类型;
Discardable Flag: 表示该Option是否可丢弃,为1表示可以被接收方抛弃;
bit1- Bit7: 保留,设置为0;
4.3.1 Configuration Option
配置Option应指定一组基于DNS TXT和DNS SD格式的"Key=Value"对;
Configuration String应该由长度字段开始,即Configuration string的有效字节长度(Configuration string = Configuration String length + Configuration String data);多少字节长度字段呢?
多个字符序列之间紧密相连,除非后面的长度字段设置为0x00,表示没有数据,不可再有任何字符;
一个字符编码后 = “一个键值” + “=” +“一个可选值”;
字符需要应包含一个“=”字符,隔开键和值;
“=”不属于键,“=”不能作为开头,没有“=”则表示键存在,“=”结尾表示键为空值;
键不可以是空白字符,为可打印的US ASCII值(0x20-0x7E);
应该支持单个配置Option中有多个相同Key的entry;
配置Option格式,如下图所示:
Length: 标识配置选项的字节数,不包括Length和Type字段;
Type: 应该设置为0x01;
Discardable flag: 若该配置Option可以被接收方丢弃,应该被设置为1;
bit1 - bit7: 保留,应该设置为0;
Configuration String: 标识配置信息;
配置Option <示例>:
length = 5,string = abc[Key]=x[Value],以此类推;
4.3.2 Load Balancing Option
用于区分不同服务实例的优先级。
负载平衡Option信息附加在Offer Service Entries后面;什么是Offer Service Entries在哪里?
负载平衡Option应携带与DNS-SRV记录类似的优先级和权重,用于对不同服务实例进行负载平衡;
在查找服务的所有服务实例时(服务实例设置为0xFFFF),客户端应选择具有最高优先级且也符合客户端特定标准的服务实例;
当有多个具有相同最高优先级(Priority字段中的最低值)的服务实例时,应根据权重随机选择服务实例。选择服务实例的概率=服务实例的权重/所有考虑的服务实例的权重之和;
如果一个Offer Service Entry没有引用负载平衡Option并且提供了多个服务实例,则客户端应按照最低优先级处理没有负载平衡选项的服务实例;
在查找某个服务的特定服务实例时(Service Instance设置为0xFFFF以外的任何值),负载平衡Option优先级不适用;
负载平衡Option格式,如下图所示:
Length: 应该设置为0x0005;
Type: 应该设置为0x02;
Discardable Flag: 1bit,是否可以被接收方丢弃,可以被接收方丢弃则应设置为1;
bit1 - bit7: 保留,设置为0;
Priority: 携带此实例的优先级。较低的值意味着较高的优先级;
Weight: 承载此实例的重量。值大意味着被选中的概率更高;
4.3.3 IPv4 Endpoint 口Option
IPv4端口Option用于SOME/IP SD实例向相关端口(本地IP地址、传输层协议、发送方端口)发送信号,也可用于事件和通知事件;
IPv4端口Option的Type字段 = 0x04;
IPv4端口Option应该指定使用的IPv4地址、传输层协议、端口;
服务器应使用带有Offer Service Entries的IPv4端口Option来向其提供服务的端口发出信号,即最多一个UDP端口和一个TCP端口;
服务器使用Offer Service Entry引用的端口也被用来作为事件源,即IPv4端口Option中传输协议的源IP和源Port;
客户端应使用带有Subscribe Eventgroup Entries的IPv4端口Option来通知IP地址和UDP/TCP端口号,在这些端口号上它已做好接收事件的准备;
IPv4端口Option应该按如下格式规则,如下图所示:
Length: 设置为0x0009;
Type: 设置为0x04;
Discardable Flag: 1个bit,应设置为0;
bit1 - bit7: 保留,设置为0;
IPv4-Address: 服务实例所在的主机的IPv4地址;
Reserved: 设置为0x00;
Transport Protocol: 传输层协议,0x06是TCP,0x11是UDP;
Transport Protocol Port Number: 传输层端口;
4.3.4 IPv6 Endpoint Option
IPv6端口Option被用于SOME/IP-SD实例向相关端口(本地IP地址、传输层协议(UDP/TCP)、送方的端口号)发出信号,这些端口也用于事件和通知事件;
IPv6端口Option的Type字段 = 0x06;
服务器应使用带有Offer Service Entries的IPv6端口Option来向端口发出服务可用的信号,即最多一个UDP端口和一个TCP端口;
服务器使用一个Offer Service Entry引用的端口也被用来作为事件源,即IPv6端口Option中传输协议的源IP地址和源Port;
客户端应使用带有Subscribe Eventgroup Entries的IPv6端口Option来通知IP地址和UDP/TCP端口号,它已做好接收事件的准备;
IPv6端口Option格式规则,如下图所示:
Length: 设置为0x0015;
Type: 设置为0x06;
Discardable Flag: 1个bit,应设置为0;
bit1 - bit7: 保留,设置为0;
IPv4-Address: 服务实例所在的主机的IPv6地址;
Reserved: 设置为0x00;
Transport Protocol: 传输层协议,0x06是TCP,0x11是UDP;
Transport Protocol Port Number: 传输层端口;
4.3.5 IPv4 Multicast Option
IPv4多播Option用于服务器发布IPv4多播地址、传输层协议、端口号,多播事件和多播通知事件将传输到这些地址;
IPv4多播Option用于客户端发布IPv4多播地址、传输层协议(ISO/OSI第4层)和端口号,客户端将在这些地址接收多播事件和多播通知事件;
IPv4多播Option在SubscribeEventgroup、StopSubscribeEventgroup 、SubscribeEventgroupAck中应按如下规则使用:
在SubscribeEventgroup中:用于描述客户端服务多播端点(即目标IP地址和目标端口),客户端将在该端点接收多播事件;
在StopSubscribeEventgroup中:用于终止之前通过客户端服务多播端点(即目标IP地址和目标端口)的客户端订阅;
在SubscribeEventgroupAck中:用于描述服务器服务多播端点(即目标IP地址和目标端口),服务器应将多播事件传输到该端点;
IPv4多播Option格式规则,如下图所示:
Length: 设置为0x0009;
Type: 设置为0x14;
Discardable Flag: 1个bit,应设置为0;
bit1 - bit7: 保留,设置为0;
IPv4-Address: 多播地址;
Reserved: 设置为0x00;
Transport Protocol: 传输层协议,0x11是UDP(当前仅适用于UDP);
Transport Protocol Port Number: 传输层端口;
4.3.6 IPv6 Multicast Option
IPv6多播Option用于服务器发布IPv6多播地址、传输层协议、端口号,多播事件和多播通知事件将传输到这些地址;
IPv6多播Option用于客户端发布IPv6多播地址、传输层协议、端口号,客户端希望在其中接收多播事件和多播通知事件;
IPv6多播OptionType = 0x16;
IPv6多播Option应指定IPv6地址、传输层协议、端口号;
IPv6-Address字段:如果服务器服务传输SubscribeentGroupack,则该字段应设置为相应提供事件组(服务器服务多播端点)的配置多播IP地址;如果客户端服务传输SubscribeEventgroup或StopSubscribeEventgroup,则该字段应设置为相应消费事件组(客户端服务多播端点)的配置IP多播地址;
Port Number字段:如果服务器服务传输SubscribeentGroupack,则该字段应设置为相应提供事件组(服务器服务多播端点)的配置端口;如果客户端服务传输SubscribeentGroup或StopSubscribeeEvent组,则该字段应设置为相应的已消费事件组(客户端服务多播端点)的配置端口;
IPv6多播Option在SubscribeEventgroup、StopSubscribeEventgroup 、SubscribeEventgroupAck中应按如下规则使用:
在SubscribeEventgroup中:用于描述客户端服务多播端点(即目标IP地址和目标端口),客户端将在该端点接收多播事件;
在StopSubscribeEventgroup中:用于终止之前通过客户端服务多播端点(即目标IP地址和目标端口)的客户端订阅;
在SubscribeEventgroupAck中:用于描述服务器服务多播端点(即目标IP地址和目标端口),服务器应将多播事件传输到该端点;
IPv6多播Option格式规则,如下图所示:
Length: 设置为0x0015;
Type: 设置为0x16;
Discardable Flag: 1个bit,应设置为0;
bit1 - bit7: 保留,设置为0;
IPv6-Address: 多播地址;
Reserved: 设置为0x00;
Transport Protocol: 传输层协议,0x11是UDP(当前仅适用于UDP);
Transport Protocol Port Number: 传输层端口;
4.3.7 IPv4 SD Endpoint Option
IPv4 SD端口Option用于传输发送方SD实现的端口(即IP地址和端口);
IPv4 SD端口Option即使在无法使用IP地址/端口号的情况下,这也可用于识别SOME/IP-SD实例;
IPv4 SD端口Option在任何SD消息中最多出现一次;
IPv4 SD端口Option如何存在,应该是Option Array的第一个选项;
IPv4 SD端口Option不应该被任何SD Entry使用;
IPv4 SD端口Option如果存在于SD消息中,接收方应使用Option的内容而不是源IP和源Port对SD消息应答;
IPv4 SD端口Option的Type = 0x24;
IPv4 SD端口Option应该指定发送方的IPv4地址、传输层协议、端口号;
IPv4 SD端口Option格式规则,如下图所示:
Length: 设置为0x0015;
Type: 设置为0x24;
Discardable Flag: 1个bit,应设置为0;
bit1 - bit7: 保留,设置为0;
IPv6-Address: 单播地址;
Reserved: 设置为0x00;
Transport Protocol: 传输层协议,0x11是UDP(当前仅适用于UDP);
Transport Protocol Port Number: 传输层端口,当前使用的是30490;
4.3.8 IPv6 SD Endpoint Option
IPv6 SD端口Option用于传输发送方SD实现的端口(即IP地址和端口);
IPv6 SD端口Option即使在无法使用IP地址/端口号的情况下,这也可用于识别SOME/IP-SD实例;
IPv6 SD端口Option在任何SD消息中最多出现1次;
IPv6 SD端口Option如何存在,应该在Option Array的第一个选项中;
IPv6 SD端口Option不应该被任何SD Entry使用;
IPv6 SD端口Option如果存在于SD消息中,接收方应使用Option的内容而不是源IP和源Port对SD消息应答;
IPv6 SD端口Option的Type = 0x26;
IPv6 SD端口Option应该指定发送方的IPv6地址、传输层协议、端口号;
IPv6 SD端口Option格式规则,如下图所示:
Length: 设置为0x0015;
Type: 设置为0x26;
Discardable Flag: 1个bit,应设置为0;
bit1 - bit7: 保留,设置为0;
IPv6-Address: 单播地址;
Reserved: 设置为0x00;
Transport Protocol: 传输层协议,0x11是UDP(当前仅适用于UDP);
Transport Protocol Port Number: 传输层端口,当前使用的是30490;
4.4 SD 报文/消息
所有的SD消息都应该发送到SD_PORT;
SD_PORT用于SD单播/多播消息的源端口;
所有单播SD消息应将SD_PORT作为目标端口,除非还定义了其他端口;
所有多播SD消息应使用SD_MULTICAST_IP;
4.5 Service Discovery Communication Behavior
SOME/IP SD将Entries打包在一起而减少服务发现的消息数量,如1.不同服务实例多个Entries;2.不同类型的Entries;
4.5.1 Startup Behavior
开始发送SD消息的基础步骤:
初始化等待阶段:当该服务实例所需的接口上的链接启动后,若应用程序请求客户端服务,SD便进入初始化阶段;若服务器服务可用时,SD进入等待阶段;
重复阶段:发送第一条消息后,进入实例的重复阶段;
主要阶段:收到offer service entry后,进入主要阶段;或者当REPETITIONS_MAX = 0时,直接有初始等待进入主要阶段;
链路可能已接通,但服务器端尚未提供服务;
系统已启动意味着此处需要的应用程序以及可能的外部传感器和执行器。基本上,此服务实例所需的功能必须准备好提供服务,并且在某些应用程序需要后,查找服务是适用的;
服务发现应在进入初始等待阶段后,在发送服务实例的第一条消息之前,基于INITIAL_DELAY进行等待;
INITIAL_DELAY应定义一个最小值和最大值,有效值随机在临界值之间进行选择;
若client服务和server服务分别引用相同的服务时间,并确保在同一时间点请求和释放引用的服务,则SD应该使用相同的随机值;
若client服务和server服务分别引用自己的服务时间,SD应该在不同的服务使用不同的随机值;
若client服务和server服务分别引用自己的服务时间,且client服务和server服务进入初始化等待阶段,他们将在等待阶段使用单独的随机值;
在重复阶段每发送一条消息后,延迟加倍;
在重复阶段SD最多只可以发送REPETITIONS_MAX个entries;REPETITIONS_MAX的值如何取?
收到offer service entry后,通过跳转到不发送find service entry的主要阶段,进而停止发送find service entry;
若REPETITIONS_MAX = 0,则应跳过重复阶段,并在初始等待阶段后直接进入服务实例的主要阶段;
进入主要阶段后,提供服务方需要等待1*CYCLIC_OFFER_DELAY胡才可以发送第一个offer service entry消息;
若设置了CYCLIC_OFFER_DELAY字段,在主阶段offer service entry消息应该循环发送;
在发送指定的服务实例的消息后,Service Discovery会等待1*CYCLIC_OFFER_DELAY,然后再发送此服务实例的下一条消息;
对于Find Entries(Find Service entry和Find Eventgroup entry),主阶段中不允许出现循环消息;
Subscribe EventGroup Entries应由循环发送的Offer service Entries触发;
SD消息开始发送 <示例>,如下所示:
初始等待阶段:1.在(INITIAL_DELAY_MIN,INITIAL_DELAY_MAX)区间随机值时间内,延迟等待;2.发送find service entry和offer service entry消息;
重复阶段(REPETITIONS_BASE_DELAY=100ms,REPETITIONS_MAX=2):1.等待2^0*100ms;2.发送find service entry和offer service entry消息;3.等待2^1*100ms;4.发送find service entry和offer service entry消息;
主阶段(消息处于活动状态且定义了CYCLIC_OFFER_DELAY):1.等待CYCLIC_OFFER_DELAY;2.发送offer s