此文标准来源于AUTOSAR_PRS_SOMEIPProtocol.pdf(R21-11)和AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol.pdf(R21-11);
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,面向服务的框架;
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的关系演变:
协议框架(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确认数据是否设置成功。
Service ID: 服务ID,标识应用程序(比如汽车中的某个模块)。
Method ID: 方法ID,标识方法或事件(比如要对汽车中的某个模块要做的事情/动作)。
该长度值为自request ID之后的数据长度。
Client ID: 客户端ID,区分客户端/订阅者,在整车中具有唯一性。
Session ID: 会话ID,区分同一客户端/订阅者的多次请求或消息。
注:
协议版本号,固定为1。
服务接口版本号。
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;
事件返回码。
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. |
有效负载/数据段。
数据长度说明,SOME/IP有效载荷字段的大小取决于所使用的传输协议。使用UDP时,SOME/IP有效负载应在0到1400字节之间。需要对1400字节进行限制,以允许将来对协议栈进行更改(例如更改为PV6或添加安全手段)。由于TCP支持有效负载的分段,因此会自动支持更大的大小。
端序问题,应该使用大端序(高字节低地址)
什么是序列化与反序列化?
序列化是指将数据结构或对象按定义的规则转换成二进制串的过程。
反序列化是指将二进制串依据相同规则重新构建成数据结构或对象的过程。
而本质就是一种编码规范。
在SOME/IP中使用序列化的目的和作用?
使数据按照固定格式进行编排成为字节序,实现数据在网络上的传输。
通信协议序列化是什么?
通过在数据后插入填充元素来对齐数据的开头,以确保对齐的数据从特定的内存地址开始。对于有些处理器架构可以更高效地访问数据。
当可变元素不是序列化数据流中最后一个元素,应依据规则对可变元素进行位填充来实现数据对齐。
填充示例:
示例1.
示例2.
注:数据对齐填充应尽量以8、16、32、64、128或256长度长度进行。
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 |
结构体序列化是依次按序进行的,如下图示例。
结构体序列化可按照TLV标准添加length和tag字段,如下图示例。
示例1.
示例2.
示例3.
结构体序列化也可以不配length参数,只配tag参数,如下图示例。
示例4.
传输ASCII、UTF-8、UTF-16字符的固定长度或动态长度字符串。对于动态长度字符串,字符串数据前有一个大端序的字符串长度参数。
包含相同参数类型。有固定长度和动态长度。对于具有动态长度的数组,使用长度字段。
枚举,具有命名不同值选项的uint。
8、16、32位参数,每一位代表一个布尔值。每个布尔值可以有一个名称,也可以有一个真值和假值的名称。
可以携带预定义参数类型的参数,该参数在运行时确定。序列化使用长度字段、类型字段和参数数据。
variant是什么数据类型?
示例1.(uint8)
示例2.(uint32)
将会介绍远程过程调用(RPC)、事件通知、错误处理。
1、SOME/IP支持TCP和UDP;
2、服务器运行同一服务的不同实例,则属于不同服务实例的消息应通过服务器的传输层端口映射到服务实例(通过不同的端口区分不同的实例);
3、传输层payload里允许有多个SOME/IP消息,不同的SOME/IP消息依据长度字段切分;
4、每个SOME/IP payload都有自己的SOME/IP头部结构;
5、一个服务实例可以有3种方法进行方法、事件、通知消息的传输: 最多一个TCP连接、最多一个UDP单播、最多一个UDP广播;
UDP绑定即基于UDP协议实现的SOME/IP消息传输。
SOME/IP信息是UDP的Payload部分,若是UDP Payload数据过大,将会被网络层分片。
一个单播UDP可以处理配置为UDP单播通信的方法、事件、通知。
一个多播UDP可以处理配置为UDP多播通信的方法、事件、通知。
TCP绑定即基于TCP协议实现的SOME/IP消息传输。
一个单播TCP可以处理配置为UDP单播通信的方法、事件、通知。
注:客户端通信前应负责建立TCP连接;客户端负责TCP的失败重连;客户端负责TCP连接关闭;客户端应在TCP所有连接服务不可用时断开连接(因为客户端需要事件处理数据,决定是否可以断开连接);客户端应在被服务端关闭TCP后被断重建连接;
同一服务的服务实例通过不同的实例ID进行标识。应支持多个服务实例驻留在不同的ECU上,以及一个或多个服务的多个服务实例驻留在一个ECU上。
虽然不同服务的多个服务实例应能够共享所用传输层协议的相同端口号,但单个ECU上相同服务的多个服务实例应使用不同的服务实例端口。
虽然实例ID用于服务发现,但它们不包含在SOME/IP头中。服务实例可以通过服务ID与套接字(即IP地址、传输协议(UDP/TCP)和端口号)的组合来识别。建议实例对UDP和TCP使用相同的端口号。如果服务实例使用UDP端口x,则只有该服务的该实例,而不是同一服务的另一实例,应该为其服务使用TCP端口x。
当基于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”。
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 ;
注:服务器/客户端在接收到完整的请求/响应消息前,忽略新的请求/响应报文。
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通信模式服务端不会回复,即使是发生了错误。错误处理和返回码应该由应用程序进行定义与实现。
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时,才会传输更新。
一个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时,事件通知着应该发送一个事件消息,将字段值发送给客户端;
服务端应具备错误处理能力;
错误处理可以在应用程序或通信层中实现,即在response中携带Return Code或Message Type = 0x81类型消息;
见3.1.7节。
SOME/IP消息接收者不应对events/notifications回复错误消息;
SOME/IP消息的接收者不应对fire&forget methods回复错误消息;
如果events/notifications和fire&forget methods的Message Type字段被错误地设置为Request或Response,SOME/IP消息的接收者不应回复错误消息;
当SOME/IP消息基于UDP传输时,应做如下验证:1.UDP数据报大小应至少为16字节(SOME/IP最小长度);2.UDP首部中Length字段值应小于或等于UDP Payload字节数;
错误检测流程,如下图所示:
RPC消息传输时,对消息传递的可靠性做了定义,1.可能 :不能保证一定到达(基于超时的UDP实现);2.至少一次:至少被到达一次(基于UDP实现);3.仅一次 :仅到达一次(基于TCP实现);
超时<示例>:
Interface Version标识了Payload的格式版本。
Payload格式和如下因素有关:
服务接口规范;
序列化配置(如可变大小数组、长度字段、填充、TLV、SOME/IP-TP);
Interface Version和如下因素有关:
Payload格式的不兼容;
服务行为的不兼容;
应用程序的设计要求;
Interface Version不受Payload格式变换的影响;
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消息封装的层次结构:
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
SOME/IP SD支持在Entries array中放置多个Entry;
Entries 用于同步服务实例状态(提供服务、发现服务)和发布/订阅管理;
Entries 有服务类型Entries和事件类型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表示任意版本;
发现服务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;
用于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;
用于Sever向Client提供服务;
规则与Offer Service Entry一致,但TTL应设置为0x000000;
Entries中Option的使用,如下图所示;
不是很明白这个表的关系?
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;
用于订阅事件组;
客户端通过什么方式(单播端口/多播端口)订阅事件,就通过什么方式接收订阅的事件信息;
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;
用于取消订阅事件组;
Stop Subscribe Eventgroup Entry规则与Subscribe Eventgroup Entry基本一致,除TTL: 0x000000外;
用于表示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匹配,用于标识服务实例的事件组;
用于表示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连接;
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)不可以提供相同的服务;
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中传输的信息来区分;
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;
Options用于将附加信息传输给Entries(例如,如何访问服务实例的信息(IP地址、传输协议、端口号));
Options字段类型,如下:
Length: 表示这个Option的字节数(除Length和Type外的字节数);
Type: 表示这个Option的类型;
Discardable Flag: 表示该Option是否可丢弃,为1表示可以被接收方抛弃;
bit1- Bit7: 保留,设置为0;
配置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],以此类推;
用于区分不同服务实例的优先级。
负载平衡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: 承载此实例的重量。值大意味着被选中的概率更高;
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: 传输层端口;
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: 传输层端口;
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: 传输层端口;
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: 传输层端口;
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;
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;
所有的SD消息都应该发送到SD_PORT;
SD_PORT用于SD单播/多播消息的源端口;
所有单播SD消息应将SD_PORT作为目标端口,除非还定义了其他端口;
所有多播SD消息应使用SD_MULTICAST_IP;
SOME/IP SD将Entries打包在一起而减少服务发现的消息数量,如1.不同服务实例多个Entries;2.不同类型的Entries;
开始发送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 service entry消息;
SD应该使用REQUEST_RESPONSE_DELAY配置项来延迟回答多播SOME/IP SD中接收到的Entries,如1.收到(多播)find后(多播/单播)Offer ;2收到(多播)offer后(单播)subscribe;
REQUEST_RESPONSE_DELAY不适用于单播-单播方式;
REQUEST_RESPONSE_DELAY应该设置临界值,并在临界区间内做随机选择;
所有的Find Service Entries都应通过使用单播传输的Offer Service Entries来做应答;
为达到优化目的,应支持一下行文选项:
若在主要阶段收到Unicast Flag = 1 的find消息,若最后一个Offer在不到1/2 CYCLIC_OFFER_DELAY之前发送的,使用单播响应;
若在主要阶段收到Unicast Flag = 1 的find消息,若最后一个Offer在1/2 CYCLIC_OFFER_DELAY或更早前发送,使用多播响应;
若服务端服务实例在重复阶段和主阶段停止,应发送Stop Offer Service Entry信息;
若服务端服务实例在初始等待阶段、重复阶段、主要阶段断开连接,当连接重启并可用时,SD应进入初始等待阶段;
若客户端服务实例在初始等待阶段、重复阶段、主要阶段断开连接,当连接重启并请求服务时,SD应进入初始等待阶段;
当服务端发送Stop Offer Service Entry信息时,服务端应删除该服务实例的所有订阅;
当客户端收到Stop Offer Service Entry信息时,客户端应删除该服务实例的所有订阅;
当客户端收到Stop Offer Service Entry信息时,客户端不可以发送Find Service Entry消息,而应等待Offer Service Entry或状态更改(应用程序、网络管理、以太网链路等);
当客户端服务实例在主要阶段停止(服务实例被释放),SD应为所有订阅该服务的事件组发送Stop Subscribe Eventgroup Entries消息;
当整个ECU(其上可以有客户端、服务端)被关闭,所有 Service Entry应发送Stop Offer Service Entry消息,所有Eventgroup Entry应发送Stop Subscribe Eventgroup Entries;
State Machines有服务端状态机和客户端状态机;
SOME/IP服务端服务状态机,如下图所示:
SOME/IP客户端服务状态机,如下图所示:
用于介绍SOME/IP SD出错情况、使用机制及相关配置。
软状态协议:SOME/IP SD即设计为软状态协议,意味着Entries具有生命周期, 需要刷新才可以保持有效值(若TTL设置为最大值将关闭此功能);
初始化等待阶段:启动ECU去偏移校正事件以避免流量突发;允许ECU手机SD消息中的Entry;
重复阶段:允许服务端和客户端快速同步,以指数方式增加两条消息之间的时间,以避免过载情况使系统无法同步;
主要阶段:SD趋于稳定状态,通过不再发送find service,并且仅在循环间隔(例如每1s)内发送offer service来降低数据包的速率;
请求/响应-延迟:SOME/IP SD应在对多播entry应答设置延迟,否则当发送一个SD entry消息,大量响应将给ECU带来很大的压力;
entry处理条件,如下:
1.检查空SOME/IP-SD消息的字节长度,即消息至少有12个字节长。如果不满足该条件,则该消息将被丢弃,无需进一步操作;
2.若接收entry的Service ID未知,忽略该entry;
3.若接收entry的Instance ID未知,忽略该entry;
4.若接收entry的Major Version未知,忽略该entry;
5.若接收entry的Eventgroup ID未知,忽略该entry;
6.如entries数组长度无效,则该消息将被丢弃,无需进一步操作;
检查Entry的Option,如下:
1.引用的Options存在;
2.该Entry引用了所有必需的Options(例如:使用单播的事件组应接收到的Subscribe Eventgroup Entry中的单播端口选项);
3.该Entry仅引用支持的Options(例如:不支持多播数据接收的事件组不支持Subscribe Eventgroup ACK Entry中的多播端口选项);
4.Entry引用的Options之间不存在冲突(即两个相同类型的选项内容是相互矛盾的);
5.被引用选项的类型已知或可丢弃标志设置为1;
6.被引用选项的类型被Entry允许或可丢弃标志设置为1;
7.被引用选项的长度与选项的类型一致;
8.端口选项具有有效的L4协议字段;
9.该选项有效(例如,多播端点选项应使用多播IP地址);
Entry引用了SD已知但服务不需要的Option,则应对Entry进行处理,如下:什么叫做SD已知但不需要的Option?
1.当基于TCP配置传输时,检查TCP连接是否已经存在;
2.检查是否剩余足够的资源;
3.若Find Entry登记失败,则忽略该Entry;
4.若Offer Entry登记失败,则忽略该Entry;
5.若Subscribe Eventgroup Entry登记失败,则发送Subscribe Eventgroup NACK Entry响应;
6.若 Subscribe Eventgroup ACK Entry登记失败,应对其进行处理,但不可以视为订阅成功;
Entry引用选项应被忽略,如下:
1.Option类型未知(未被指定或接收方不支持),且丢弃标记置为1;
2.Option是多余的(该Entry引用了另一个相同类型和内容的Option);
3.Option是不必要的(例如,提供的仅使用多播的事件组在收到的Subscribe Eventgroup Entry中不需要单播端口选项,尽管它仍然是允许的);
处理SOME/IP协议外,车上还使用了其他通信协议。如网络管理、诊断、刷写等,需要与服务实例进行交互;
非SOME/IP协议设置规则,如下:
Service ID = 0XFFFE;
Instance ID : 应该按照SOME/IP Service Eventgroup的描述使用;
应添加Config Option选项,并应包含一个带有键“otherserv”的Entry和一个由系统部门确定的可配置非空值;
注:应用程序不适用SOME/IP协议,但是可以通过SOME/IP SD发布信息。
非SOME/IP SD协议的PDU<示例>,如下图所示:
与SOME/IP的请求-响应机制对比,客户端不想每次都做消息请求。
客户端需要的所有事件/通知事件,应该使用SOME/IP-SD向服务端注册;
通知事件的交互流程,如下图所示:
服务器通过SOME/IP-SD Offer Service Entry向客户端推送通知;因此,它用作订阅的触发器;
若客户端仍然有兴趣接收此事件组的通知/事件,每个客户端都应使用SOME/IP-SD Subscribe Eventgroup Entry响应来自服务器的SOME/IP-SD Offer Service Entry消息;
若客户端能够使用SOME/IP-SD消息reboot flag可靠地检测到服务器的重新启动,则客户端可以选择仅在服务器重新启动后回复Offer Service消息(如果配置为这样做)(TTL设置为最大值)。即使服务器的SOME/IP-SD消息丢失,客户端也会确保其工作是可靠的;
若客户端没有对事件组的有效订阅,则客户端应通过设置初始数据请求标志来明确请求初始事件;
若客户端发送了额外的Subscribe Eventgroup Entries并且前一个订阅的TTL没有过期,那么客户端不应请求初始事件;
客户明确请求初始事件的原因,如下(包括但不限于):
1.客户端当前未订阅事件组;
2.客户端在最后一个Subscribe Eventgroup Entry之后看到了连接断开/连接启动;
3.客户端在最后一个常规订阅事件组之后没有收到订阅事件组确认;
4.客户端检测到此服务的服务器重新启动;
如果客户端订阅了两个或多个事件组,包括一个或多个相同的事件或字段,则服务器不应为该字段发送重复的事件或通知事件。这意味着是常规事件而不是初始事件;
将Offer Service Entry作为隐式发布发送的服务器必须保持此事件组实例的订阅事件组消息的状态,以便知道是否必须发送通知/事件;
客户端发布/订阅连接丢失,如下:
1.没有注册+客户订阅
2.客户端连接丢失
3.客户端再次订阅+检测到客户端重启
注:客户端应通过发送TTL=0的SOME/IP-SD订阅事件组消息(停止订阅事件组)从服务器注销;
=》发布/订阅,注册/注销行为,描述如下:
1.客户1订阅
2.客户2订阅
3.客户1停止订阅
4.客户2保持注册状态
整个过程,如下图所示:
注:若在发送事件或通知事件后发生相关的SOME/IP错误,服务端SOME/IP SD将删除订阅。
=》服务端连接丢失的发布/订阅处理:
1.没有先进行注册+客户订阅
2.服务端连接丢失
3.服务端再次提供订阅服务,客户端检测到服务端重启
整个过程,如下图所示:
客户端需要接收到Subscribe Eventgroup Entry的Subscribe Eventgroup Ack Entry。否则:在发送Subscribe Eventgroup Entry的同一SOME/IP-SD消息中发送Stop Subscribe Eventgroup Entry和Subscribe Eventgroup Entry;
客户端想订阅建立安全机制的服务,并等到安全机制建立起来。客户端应该向这个服务发送Subscribe Eventgroup entry后建立安全机制;
P76
=》发布/订阅(服务端多播事件组行为),如下图所示:
如果客户端使用不同的SOME/IP-SD消息订阅同一服务实例的不同事件组,并且所有事件组包含相同的字段,则服务器应为每个订阅分别发送该字段的初始事件;
如果客户端使用一条SOME/IP-SD消息订阅同一服务实例的不同事件组,并且所有事件组都包含相同的字段,则服务器可以选择不多次发送该字段的初始事件(服务端仅发送一次初始化来实现优化,若是架构是支持的);
发布/订阅状态(服务端自适应单播/多播行为),如下图所示:
当用户数量达到配置阈值,SOME/IP SD应该支持单播到多播的切换;
SOME/IP SD应该支持通信端口的隐式配置和订阅者注册,应基于静态配置,并不适用网络的上的任何SD消息;
下列Entry仅通过单播传输:
1.订阅事件组;
2.停止订阅事件组;
3.订阅事件组确认;
4.订阅事件组否定确认;
SUBSCRIBE_RETRY_MAX > 0,客户端应该重新订阅服务端服务的事件组;
若SUBSCRIBE_RETRY_DELAY超时时间内未收到事件组的Subscribe Eventgroup Ack/NAck entry,则应发送对Eventgroup的订阅;
若请求事件组为超过配置的重试计数SUBSCRIBE_RETRY_MAX,应该重试;
当服务端服务接收到TTL=0XFFFFFF的Offer Service,需要将SUBSCRIBE_RETRY_MAX设置为INF;这时,若做了Eventgroup请求但没收到SubscribeEventgroupAck/NAck entry,就应该重试;
将介绍保留标识符和特殊标识符相关信息。
保留的Service ID,如下图所示:
保留的指定Instance ID,如下图所示:
保留的指定Method/Event ID,如下图所示:
保留的Eventgroup ID,如下图所示:
Event ID = 0XFFFF时的Method ID:
Configuration Option除“otherserv”的其他配置:
该节主要介绍服务发现的强制功能集和相关的配置约束。
以下信息被定义为合规检查表。如果未实现某项功能,则认为该实现不符合SOME/IP SD基本功能集。
应实现如下Entry类型:
Find Service Entry;
Offer Service Entry;
Stop Offer Service Entry;
Subscribe Eventgroup Entry;
Stop Subscribe Eventgroup Entry;
Subscribe Eventgroup Ack Entry;
Subscribe Eventgroup Nack Entry;
当使用IPv4时,应实现如下Option:
IPv4 Endpoint Option
IPv4 Multicast Option
Configuration Option
IPv4 SD Endpoint Option (receiving at least)
当使用IPv6时,应实现如下Option:
IPv6 Endpoint Option
IPv6 Multicast Option
Configuration Option
IPv6 SD Endpoint Option (receiving at least)
服务端行为要求:
服务端应依据配置实现初始化等待阶段、重复阶段、主要阶段;
服务端应SD_MULTICAST_IP定义的多播地址上使用多播Offer Service(重复阶段、主要阶段);
服务端不需要在重复阶段回答Find Service Entry;
服务端应使用单播(没有基于单播标志的优化)以Offer Serive Entry来回答主要阶段的Find Service Entry;
服务端在关闭时应发送停止Offer Serice Entry;
服务端应接收Subscribe Eventgroup Entry和Stop Subscribe Eventgroup Entry,并根据本规范做出反应;
服务器应使用单播发送Subscribe Eventgroup Ack Entry和Subscribe Eventgroup Nack Entry;
服务器应支持基于SOME/IP-SD的订阅控制SOME/IP事件消息的发送。这可能包括发送基于多播的事件;
服务器应支持触发初始SOME/IP事件消息;
客户端行为要求:
客户端应仅在重复阶段使用Find Service Entry和多播(在SD_MULTICAST_IP 定义的多播地址上)来Find Service;
如果常规Offer Service Entry到达,客户端应停止Find Service Entry;
客户端应使用单播SD消息对服务器Offer Service Entry做出反应,该消息包括客户端当前想要订阅的服务器消息中提供的服务的所有订阅事件组;
客户应按照本文档中的规定解释并响应Subscribe Eventgroup Ack Entry和Subscribe Eventgroup Nack Entry;
客户端支持如下行文和配置约束:
如果仅指定SD计时的TTL,则客户端应能够处理事件组。这意味着在初始等待阶段、重复阶段和主要阶段的所有时序中,仅配置了TTL。这意味着客户端只能对服务器的Offer Service Entry作出反应;
即使没有配置Request-Response-Delay,客户也应使用订阅事件组响应Offer Service Entry,这意味着它不应等待而是立即响应;
客户端和服务器应实施本文档中指定的重启检测并做出相应动作。 这包括但不限于:
根据本规范设置Session ID和Reboot标志;
保留一个Session ID计数器仅用于发送多播SD消息;
保留多个Session ID计数器为每个单播用于发送SD单播消息;
根据本规范了解Session ID和Reboot标志;
每个ECU保留一个多播Session ID计数器,用于与ECU进行SD多播消息交互;
每个ECU保留一个单播Session ID计数器,用于与ECU进行SD单播消息交互;
根据此规范检测重启并做出相应动作;
正确解释有关重启检测的IPv4和IPv6 SD Endpoint Options;
客户端和服务器应实现“服务和事件的端口处理”。这包括但不限于:
如果需要UDP,则将1个UDP Endpoint Option添加到Offer Service;
如果需要TCP,则将1个TCP Endpoint Option添加到Offer Service;
如果需要UDP事件,则将1个UDP Endpoint Options添加到订阅事件组;
如果需要TCP事件,则将1个TCP Endpoint Option添加到订阅事件组;
如果需要U多播事件,则添加1个UDP Multicast Option到订阅事件组确认;
根据上述传输的端口和多播选项了解和采取行动;
使用这些Endpoint Option和Multicast Option的信息覆盖预配置的值(例如IP地址和端口);
将传入的IPv4和IPv6 Endpoint Option解释为SD端口,而不是外层的地址和端口号;
注:客户端和服务端应实现对初始事件的显式请求。
同一个服务支持多个版本。
为了支持迁移场景,ECU应支持服务以及使用同一服务的不同不兼容版本;
为了支持具有多个版本的服务,需要以下内容:
服务端应为每个主要版本提供一次该服务的服务实例;
客户端应在每个支持的主要版本中查找一次服务实例,或者应将主要版本用作0xFF(所有版本);
客户端应订阅它需要的服务版本的事件;
所有SOME/IP-SD Entries应使用相同的Service ID和 Instance ID,但主要版本不同;
服务器必须根据它们到达的套接字、Message ID、Major Version 对消息进行多路分解,并根据这些条件在内部将其中继/转发到正确的接收器;
在一个VLAN中,最多有一个Service ID、Major Version 和Instance ID相同的服务实例。这适用于服务端和客户端网络节点;
不允许在一个网络节点上配置多个仅在次要版本中不同的服务实例,因为无法在事件组条目中区分它们;
SOME/IP发展历史
以太网SOME/IP协议解读(汽车测试网)
关于SOME/IP理解
车载以太网-SMOE/IP简介
SOME/IP协议详解(收费)
SOME/IP介绍
E2E
SecOC
DTLS
TLV - 三元编码
详解SOME/IP协议文档-3
详解SOME/IP协议文档-2
详解SOME/IP协议文档-1
详解SOME/IP SD协议翻译
浅谈SOME/IP
Vsomeip开源代码实现
http://www.some-ip.com
AUTOSAR官网
抓包分析,Wireshark 3.2 SOME / IP支持是公开的