SOME/IP-SD 是"Scalable service-Oriented MiddlewarE over IP - Service Discovery"的缩写,是SOME/IP的一种特殊报文,可以让Client知道Server可以提供哪些服务,SOME/IP有两种动态发现服务的机制:一种是Offer Service,由Server向网络上的小伙伴告知它所提供的服务;另一种是Find Service,由Client向Server请求可用的服务。
该协议规范定义了SOME/IP-SD的格式、消息序列和语义。SOME/IP-SD主要任务是车载功能实体调用服务的通信可用性以及控制事件消息的发送行为。这种机制只允许事件消息发送给需要它们的接收者(Publish/Subscribe)。
SOME/IP-SD 主要用于
SOME/IP-SD用于车载网络的服务发现,使用该协议有以下约束:
从下图可以看出SOME/IP-SD是基于SOME/IP协议,而SOME/IP协议是基于TCP或UDP协议,但是SOME/IP-SD只能基于UDP协议。
ID | Name | Description |
---|---|---|
UC_001 | 提供服务 | 服务端向网络提供服务,而不需要在客户端静态配置服务器 |
UC_002 | 订阅服务 | 客户端在不知道发送者位置的情况下找到所需的服务并订阅它 |
UC_003 | 灵活的通信路径 | 开发人员希望在不知道谁将接收数据或谁将发送所需数据的情况下设计应用程序。服务发现允许在集成期间建立通信路径。 |
略
术语/缩略语 | 描述 |
---|---|
Byte Order Mark | 字节顺序标记(byte order mark, BOM)是一个Unicode字符,U+FEFF字节顺序标记(byte order mark, BOM),它作为一个魔数出现在文本流的开头,用于表明所使用的编码 |
Method | 可被调用的方法、过程、函数或子程序 |
Parameters | 方法或事件的输入、输出或输入/输出参数 |
Remote Procedure Call (RPC) | 从一个ECU到另一个ECU的方法调用,使用消息传输 |
Request | 客户端发给服务端用来调用方法(Method)的消息 |
Response | 服务端响应客户端方法调用的消息 |
Request/Response communication | 一次请求/回复过程,也就是RPC |
Event(事件) | 单向数据传输,只在变化时调用或循环调用,从数据的生产者发送到消费者 |
Field | Field(字段)代表一种状态,因此在getter、setter和notifier操作的任何时候都有一个有效值 |
Notification Event | 用字段通知的事件消息 |
Getter | 允许读取字段的请求/响应调用。 |
Setter | 允许对字段进行写访问的请求/响应调用。 |
Service | 零个或多个方法、零个或多个事件、零个或多个字段的逻辑组合。 |
Eventgroup | 一个服务中事件和字段通知事件的逻辑组合,以便允许订阅 |
Service Instance | 一个服务的实现,它可以在车辆上多次存在,也可以在ECU上多次存在 |
Server | 提供服务实例的ECU在这个服务实例的上下文中应该被称为服务器。 |
Client | 在这个服务实例的上下文中,使用服务器服务实例的ECU应该被称为客户端。 |
Fire and Forget | 无回复的请求叫做 解雇并遗忘 |
User Datagram Protocol | 一种传输层协议 |
Union | 一种动态假设不同数据类型的数据结构 |
non-extensible (standard) struct | 序列化时不带标签的结构体。最多可以在结构体末尾以兼容的方式添加新成员,而不能添加可选成员。 |
extensible struct | 用标签序列化的结构体。可以在任意位置以兼容的方式添加新成员,也可以添加可选成员。 |
SOME/IP-SD 主要用于
车辆内部的服务实例的位置通常是已知的;因此,服务实例的状态是主要关注的问题。服务的位置(即ip地址、传输协议和端口号)是次要的。
如果需要在多个网络接口上提供服务,则每个网络接口应提供一个单独的服务端服务实例
如果需要将服务配置为使用多个不同的网络接口访问,则每个网络接口应使用一个单独的客户端服务实例
SOME/IP-SD 消息的字段组成如下:
字段结构如下图所示:
SD头部以8位字段“flags”开始,字段的表示如下图5.3所示
注意:这意味着不管是发送方还是接收方都要单独计数
发送方:需要为多播设置一个计数器,也需要为单播设置一个计数器
接收方:对于组播,每个对等体都应该有一个计数器;对于单播,每个对等体都要有一个计数器
检测重启的方法如下(使用来自通信伙伴的当前数据包的新值和之前接收到的最后一个值):
if old.reboot == 0 and new.reboot==1 then Reboot detected;
if old.reboot 1 and new.reboot1 and old.session_id>=new.session_id then Reboot detected
第二个标志位叫单播标志位(Unicast Flag),所有SD消息该位都要设置成1。单播标志是从历史的SOME/IP版本遗留下来的,只是出于兼容性的原因而保留。除此之外,它的用途非常有限。
Flags 字段未定义的位都要设置成0
在Flags字段后,需要有24位作为保留字段
条目字段以序列化的顺序为准
SOME/IPSD消息的Entries数组和Options数组应该以length字段作为uint32开始,该字段统计了以下数据的字节数;即条目或选项。
5.1.2.3 条目格式(Entry format)
SD报文协议应支持一条SD报文里可以包含多个条目。这些条目用于同步服务实例的状态和发布/订阅处理。
协议中有两种条目:一种服务条目,另一种事件组条目。
服务条目有16个字节大小,包含的字段如下所示:
服务条目的字段结果如下图所示:
事件组条目一共16个字节,它包含以下字段:
对于经典平台上的服务发现,SdServerService主版本和SdClientService主版本分别需要与对应服务接口的接口版本匹配
Options用于将附加信息传输给条目"Entries",包括例如如何访问服务实例的信息(IP地址、传输协议、端口号)
为了识别Option类型,每个Option都应以下面字段开始:
Length字段表示该Option除了Length字段和Type字段外的所有字节数, 如果接收方ECU不支持该Option,且可以丢弃它,那么Discardable Flag应该设置为1
Option的种类如下:
Configuration Option
“配置选项”用于传输任意的配置字符串,这允许对附加信息进行编码,例如服务名称或是它的配置
“配置选项”的格式如下:
– 配置选项应指定一组基于DNS TXT和DNS-SD格式的"名称-值"对
– 配置字符串的格式应以单个字节长度字段开始,该字段描述该长度字段之后的字节数。在长度字段之后应遵循具有指定长度的字符序列
– 在每个字符序列之后,期望另一个长度字段和随后的字符序列,直到长度字段应设置为0x00
– 将长度字段设置为0x00后,不得跟随任何字符
– 一个字符序列应该编码一个键和一个可选的值
– 字符序列应包含一个相等的字符(“=”,0x3D)来划分键和值
– 键不应包含相等的字符,并且应至少是一个非空白字符。“Key”的字符应为可打印的US ASCII值(0x20-0x7E),不包括‘=’(0x3D)
– “=”不应是序列的第一个字符
– 对于没有“=”的字符序列,该键应被解释为存在
– 对于以“=”结尾的字符序列,该键应被解释为具有空值
– 应支持在单个配置选项中具有多个相同键的条目
配置选项的格式为:
负载平衡选项(Load Balancing Option)
负载平衡Option用于区分服务的不同实例的优先级,以便客户端根据这些设置选择服务实例。此Option附加在Offer Service Entries的后面
负载平衡选项应携带与DNS-SRV记录类似的优先级和权重,用于对不同服务实例进行负载平衡
在查找服务的所有服务实例时(服务实例设置为0xFFFF),客户端应选择具有最高优先级且也符合客户端特定标准的服务实例
当有多个具有最高优先级(Priority字段中的最低值)的服务实例时,应根据服务实例的权重随机选择服务实例。选择服务实例的概率应为服务实例的权重除以所有考虑的服务实例的权重之和
如果一个Offer Service Entry没有引用负载平衡选项并且提供了多个服务实例,则客户端应按照最低优先级处理没有负载平衡选项的服务实例
在查找某个服务的特定服务实例时(Service Instance设置为0xFFFF以外的任何值),Load Balancing Option的优先级不适用
负载平衡选项的格式如下:
IPv4 Endpoint Option
IPv4端口Option被SOME/IP-SD实例用于向相关端口发出信号。端口包括本地IP地址、传输层协议(例如UDP或TCP)以及发送方的端口号。这些端口也用于事件和通知事件
IPv4端口Option的格式如下:
“ 服务器应使用带有Offer Service Entries的IPv4端口Option来向其提供服务的端口发出信号。即最多一个UDP端口和一个TCP端口
”
“ 服务器使用Offer Service Entry引用的端口也被用来作为事件源。即端口选项中传输协议的源IP地址和源端口号
”
“ 客户端应使用带有Subscribe Eventgroup Entries的IPv4端口Option来通知IP地址和UDP和/或TCP端口号,在这些端口号上它已准备好接收事件
”
IPv6 Endpoint Option
IPv6端口Option被SOME/IP-SD实例用于向相关端口发出信号。端口包括本地IP地址、传输层协议(例如UDP或TCP)以及发送方的端口号。这些端口也用于事件和通知事件
IPv6端口Option的格式如下:
“ 服务器应使用带有Offer Service Entries的IPv6端口选项来向端口发出服务可用的信号。即最多一个UDP端口和一个TCP端口
”
“ 服务器使用一个Offer Service Entry引用的端口也被用来作为事件源。即端口选项中传输协议的源IP地址和源端口号
”
“ 客户端应使用带有Subscribe Eventgroup Entries的IPv6端口选项来通知IP地址和UDP和/或TCP端口号,它已准备好接收事件
”
IPv4 Multicast Option
服务器使用IPv4多播Option来宣布IPv4多播地址、传输层协议(ISO/OSI第4层)以及多播事件和多播通知事件发送到的端口号。作为传输层协议,目前仅支持UDP
“ IPv4多播选项应由Subscribe Eventgroup Ack Entries引用
”
“ IPv4多播选项应使用类型0x14
”
“ IPv4多播选项应指定IPv4地址、使用的传输层协议(ISO/OSI第4层)及其端口号
”
IPv4多播Option的格式如下:
服务器应引用对IPv4多播地址和端口号进行编码的IPv4多播选项。而这个IPv4多播地址和端口号,是服务器发送多播事件和通知事件的地址和端口号
IPv6 Multicast Option
服务器使用IPv6多播Option来宣布IPv6多播地址、第4层协议以及多播事件和多播通知事件发送到的端口号。对于传输层协议(ISO/OSI第4层),目前仅支持UDP
“ IPv6多播选项应使用类型0x16
”
“ IPv6多播选项应指定IPv6地址、使用的传输层协议(ISO/OSI第4层)及其端口号
”
IPv6多播Option的格式如下:
“ Subscribe Eventgroup Ack消息应引用IPv6多播选项而不是IPv6端口选项
”
“ 服务器应引用对IPv6多播地址和端口号进行编码的IPv6多播选项。而这个IPv6多播地址和端口号,是服务器发送多播事件和通知事件的地址和端口号
”
IPv4 SD Endpoint Option
IPv4 SD端口Option用于传输发送方SD实现的端口(即IP地址和端口)。即使在无法使用IP地址和/或端口号的情况下,这也可用于识别SOME/IP-SD实例
“ IPv4 SD端口选项在任何SD消息中最多出现1次
”
“ 仅当SOME/IP-SD消息通过IPv4传输时,才应包括IPv4 SD端口选项
”
“ IPv4 SD端口Option是Options Array中的第一个选项(如果存在)
”
“ 任何SD Entry都不应引用IPv4 SD端口选项
”
“ 如果IPv4 SD端口选项包含在SD消息中,则接收方应使用此选项的内容,而不是源IP地址和源端口
”
这对于回答接收到的SD消息(例如,在Find后Offer或在Offer后Subscribe或在Subscribe后Subscribe Ack)以及重新启动检测(基于SD端口Option而不是输出地址的通道)非常重要
“ IPv4 SD端口选项应使用类型0x24
”
“ IPv4 SD端口选项应指定用于服务发现的发送方的IPv4地址、传输层协议(ISO/OSI第4层)和端口号
”
IPv4 SD端口Option的格式如下:
IPv6 SD Endpoint Option
IPv6 SD端口Option用于传输发送方SD实现的端口(即IP地址和端口)。即使在无法使用IP地址和/或端口号的情况下,这也可用于识别SOME/IP-SD实例
“ IPv6 SD端口选项在任何SD消息中最多出现1次
”
“ IPv6 SD端口Option应是Option Array中的第一个选项(如果存在)
”
“ 任何SD Entry都不应引用IPv6 SD端口选项
”
“ 如果IPv6 SD端口选项包含在SD消息中,则接收方应使用此选项的内容而不是源IP地址和源端口来回答此SD消息
”
“ IPv6 SD端口选项应使用类型0x26
”
“ IPv6 SD端口选项应指定用于服务发现的发送方的IPv6地址、传输层协议(ISO/OSI第4层)和端口号
”
IPv6 SD端口Option的格式如下:
Find Service Entry
Find Service Entry类型用于查找服务实例,并且仅在服务的当前状态未知时才发送(没有接收到当前的Service Offer并且仍然有效)
Find Service Entry应按以下方式设置Entry字段:
“ 发送方不得在Find Service Entry中引用端口选项或多播选项
”
“ 接收方应忽略Find Service Entry中的Endpoint Options和Multicast Options
”
“ 其他选项(既不是端口也不是多播选项),仍应允许在Find Service Entry中使用
”
“ 当接收到Find Service Entry时,服务ID、实例ID、主要版本和次要版本应与配置的值完全匹配以识别服务实例,除非Entry中有“任何值”(例如服务ID为0xFFFF,实例ID为0xFFFF,主要版本为0xFF,次要版本为0xFFFFFFFF)
”
Offer Service Entry
Offer Service Entry类型用于向其他通信伙伴提供服务
Offer Service Entry应按以下方式设置Entry字段:
“ Offer Service Entry应始终至少引用一个IPv4或IPv6端口选项,以表明服务如何可达
”
“ 对于服务所需的每个传输层协议(即UDP和/或TCP),如果支持IPv4,则应添加IPv4端口选项
”
“ 对于服务所需的每个传输层协议(即UDP和/或TCP),如果支持IPv6,则应添加IPv6端口选项
”
“ 当接收到初始的Offer Service Entry时,服务ID、实例ID、主要版本和次要版本应与配置的值完全匹配以识别服务实例,除非在服务配置中有“任何值”(例如0xFFFF用于实例ID,0xFFFFFFFF次要版本)
”
“ 当接收到后续的Offer Service Entry或Stop Offer Service Entry时,服务ID、实例ID、主要版本应与初始Offer Service Entry中的值完全匹配,以识别服务实例
”
Stop Offer Service Entry
“ Stop Offer Service Entry类型用于停止提供服务实例
”
“ Stop Offer Service Entry应设置与它们正在停止的Offer Service Entry完全相同的Entry字段,除了:TTL应设置为0x000000
”
“ 如果静态配置的值与这些选项中的值不同,则SD应使用在端口和多播选项中传输的IP地址和端口号重写
”
“ 端口选项的IP地址和端口号也用于传输事件和通知事件
”
“ 在UDP的情况下,端口选项用于作为事件和通知事件的源地址和源端口,也是客户端能够向其发送方法请求的地址
”
“ 在TCP的情况下,端口选项用于作为客户端需要打开TCP连接的IP地址和端口,以使用TCP接收事件
”
“ SOME/IP应允许服务同时使用UDP和TCP
”
“ 哪个消息由哪个底层传输协议发送由配置决定:一个Service可以同时使用UDP和TCP端口。但是无论使用TCP还是UDP,每个服务元素都应该配置
”
需要在配置中限制通过TCP/UDP提供哪些方法和哪些事件。这也意味着不能通过TCP和UDP提供相同的事件
Service Endpoints
Offer Service Entries引用的端口选项表示:
“ 除了Offer Service Entries的端口选项中给出的端口之外,该服务实例的事件不得从任何其他端口发送
”
“ 如果一个ECU提供多个服务实例,这些服务实例的SOME/IP消息应通过Offer Service Entries引用的端口选项中传输的信息来区分
”
Eventgroup Endpoints
“ Subscribe Eventgroup Entries中引用的端口选项也用于此服务实例的发送单播UDP或TCP SOME/IP事件
”
因此,Subscribe Eventgroup Entries中引用的端口选项是客户端的IP地址和端口号
“ 在发送Subscribe Eventgroup Entry之前,TCP事件使用客户端打开到服务器的TCP连接进行传输
”
“ 初始事件应使用单播从服务器传输到客户端
”
“ Subscribe Eventgroup Ack Entries最多引用1个使用Internet协议(IPv4或IPv6)的多播选项
”
“ 多播选项设置UDP作为传输协议
”
“ 客户端应尽快打开Subscribe Eventgroup Ack Entry引用的多播选项中指定的端口,以免错过多播事件
”
下图显示了具有不同端口和多播选项的示例:
所有服务发现消息都应发送到SD_PORT,SD_PORT用于服务发现单播/多播消息的源端口,所有单播SD消息都应将SD_PORT作为目标端口,除非SD端口Option定义了不同的端口,所有SD多播消息都应使用SD_MULTICAST_IP发送。
Subscribe Eventgroup Entry
Subscribe Eventgroup Entires 按以下方式设置Entry字段:
“Subscribe Eventgroup Entries引用最多两个IPv4或最多两个IPv6端口选项(一个用于UDP,一个用于TCP)”
如果服务器仅使用IP多播通过UDP传输事件,则 Subscribe Eventgroup Entry不需要引用UDP端口选项。如果服务器传输事件组的初始事件,则 Subscribe Eventgroup Entry应引用相应的端口选项,因为
“ 当接收到SubscribeEventgroup或StopSubscribeEventgroup时,服务ID、实例ID、事件组ID和主要版本应与配置的值完全匹配,以标识服务实例的事件组
”
“ 如果服务器接收到没有UDP端口选项的Subscribe Eventgroup Entry,并且事件组的MulticastThreshold未配置为值1,则应将SubscribeEventGroupNack发送回客户端
”
Stop Subscribe Eventgroup Entry
Stop Subscribe Eventgroup Entry类型应用于停止订阅事件组
Stop Subscribe Eventgroup Entries应设置与它们正在停止的订阅事件组Entry完全相同的Entry字段,除了:TTL设置为0x000000
Stop Subscribe Eventgroup Entry应引用与Subscribe Eventgroup Entry引用的相同Options。这包括但不限于端口和配置选项
Subscribe Eventgroup Acknowledgement (Subscribe Eventgroup Ack) Entry
Subscribe Eventgroup Acknowledgment Entry类型用于指示Subscribe Eventgroup Entry已被接受,Subscribe Eventgroup Acknowledgment Entry应按以下方式设置Entry字段:
引用通过多播传输的事件和通知事件的Subscribe Eventgroup Ack Entries应引用IPv4多播选项和/或IPv6多播选项。
当接收到SubscribeEventgroupAck或SubscribeEventgroupNack时,Service ID、Instance ID、Eventgroup ID和Major Ver-sion应与对应的SubscribeEventgroup Entry完全匹配,以标识Service Instance的Eventgroup
Subscribe Eventgroup Negative Acknowledgement (Subscribe Eventgroup Nack) Entry
Subscribe Eventgroup Negative Acknowledgment Entry类型应用于指示Subscribe Eventgroup Entry未被接受。
Subscribe Eventgroup Negative Acknowledgment Entries应按以下方式设置条目字段:
不接受订阅事件组的原因包括(但不限于):
当客户端在需要TCP连接的SubscribeEventgroup上收到SubscribeEventgroupNack作为应答时,客户端应检查TCP连接并在需要时重新启动TCP连接
服务器可能丢失了TCP连接,而客户端没有
检查TCP连接可能包括以下内容:
SOME/IP Service Discovery通过将Entries打包在一起来减少服务发现消息的数量。例如:
对于每个服务实例,Service Discovery 在发送Entries方面至少应具有以下三个阶段:
实际的已实现的状态机将不仅仅需要这三个阶段的状态。例如, 本地服务可能仍处于关闭状态,而远程服务可能已经知道(不再需要查找)
“ 当此服务实例所需的接口上的链接已启动并且应用程序请求客户端服务时,Service Discovery应进入客户端服务实例的初始等待阶段
”
“ 当该服务实例所需的接口上的链接已启动且服务器服务可用时,Service Discovery应进入该服务器服务实例的初始等待阶段
”
链接可能已建立,但服务器端的服务尚不可用
系统已启动在这里表示所需的应用程序以及可能的外部传感器和执行器。基本上,此服务实例所需的功能必须准备好提供服务,并且在某些应用程序需要它之后找到服务是适用的
“ Service Discovery在进入初始等待阶段之后,在为服务实例发送第一条消息之前,将根据INITIAL_DELAY等待
”
“ INITIAL_DELAY应定义为最小和最大延迟
”
“ 等待时间应通过在INITIAL_DELAY的最小值和最大值之间选择一个随机值来确定
”
“ 如果ClientService和ServerService分别引用相同的ClientServiceTimer和ServerServiceTimer,并且它确保分别在同一时间点请求和释放引用的ClientServiceS和ServerServiceS,则服务发现应使用相同的随机值
”
“ 如果ClientServices和ServerService分别引用它们自己的ClientServiceTimer和ServerServiceTimer,则服务发现应为每个ClientService和ServerService使用不同的随机值。因此,如果ClientService或ServerSerivce进入初始等待阶段,它们将在初始等待阶段使用单独计算的随机值
”
“ 发送第一条消息后,进入此服务实例/这些服务实例的重复阶段
”
“ Service Discovery将根据REPETITIONS_BASE_DELAY在重复阶段等待
”
“ 在重复阶段发送每条消息后,延迟加倍
”
“ 服务发现在重复阶段只能发送最多REPETITIONS_MAX个entries
”
“ 在收到相应的Offer entries后,通过跳转到不发送Find entries的Main阶段停止发送Find entries
”
“ 如果REPETITIONS_MAX设置为0,则应跳过重复阶段,并在初始等待阶段后进入服务实例的主阶段
”
“ 在重复阶段之后,进入服务实例的主要阶段
”
“ 进入Main阶段后,提供者需要等待1CYCLIC_OFFER_DELAY才能发送第一个offer entry消息
”
“ 如果配置了CYCLIC_OFFER_DELAY,则在主阶段Offer消息应循环发送
”
“ 在发送指定的服务实例的消息后,Service Discovery会等待1CYCLIC_OFFER_DELAY,然后再发送此服务实例的下一条消息
”
“ 对于Find Entries(Find Service和Find Eventgroup),主阶段中不允许出现循环消息
”
“ Subscribe EventGroup Entries应由循环发送的Offer Entries触发"
例如:
初始等待阶段:
在(INITIAL_DELAY_MIN, _MAX)范围内中等待random_delay
发送消息(Find Service和Offer Service Entries)
重复阶段(REPETITIONS_BASE_DELAY=100ms,REPETITIONS_MAX=2):
等待 2 0 ∗ 100 m s 2^{0}*100ms 20∗100ms
发送消息(Find Service和Offer Service Entries)
等待 2 1 ∗ 100 m s 2^{1}*100ms 21∗100ms
发送消息(Find Service和Offer Service Entries)
主阶段(只要消息处于活动状态并且定义了CYCLIC_OFFER_DELAY):
等待CYCLIC_OFFER_DELAY
发送消息(Offer Service Entries)
Service Discovery应使用配置项REQUEST_RESPONSE_DELAY延迟回答在多播SOME/IP-SD消息中接收到的Entries。这适用于以下两种情况:
“ 如果用单播消息回答单播消息,则REQUEST_RESPONSE_DELAY将不适用
”
“ REQUEST_RESPONSE_DELAY应由最小值和最大值指定
”
“ 实际延迟应在REQUEST_RESPONSE_DELAY的最小值和最大值之间随机选择
”
“ 对于基本实现,所有Find Service Entries都应通过使用单播传输的Offer Service Entries来回答 "
出于优化目的,应支持以下行为作为选项:
“ 当ECU的服务器服务实例处于重复和主阶段并正在停止时,应发出Stop Offer Service Entry
”
“ 当一个服务器服务实例在初始等待阶段、重复阶段或主阶段链路断开时,当链路再次启动且服务仍然可用时,Service Discovery将进入初始等待阶段
”
“ 当客户端服务实例在初始等待阶段、重复阶段或主阶段链路断开时,Service Discovery应在链路再次启动且仍请求服务时进入初始等待阶段
”
“ 当服务器发出Stop Offer Service Entry时,该服务实例的所有订阅都应在服务器端删除
”
“ 当客户端收到Stop Offer Service Entry时,该服务实例的所有订阅都应在客户端删除
”
“ 当客户端收到Stop Offer Service Entry时,客户端不应发送Find Service Entry,而是等待Offer Service Entry或状态更改(应用程序、网络管理、以太网链路或类似)
”
“ 当ECU的客户端服务实例处于主阶段并且正在停止(即服务实例被释放)时,SD应为所有订阅的事件组发送Stop Subscribe Eventgroup Entries
”
“ 当整个ECU被关闭时,所有的服务Entries应发送Stop Offer Service Entries,所有的事件组应发送Stop Subscribe Eventgroup Entries
”
SOME/IP Service状态机(服务器)如下图所示:
SOME/IP Service状态机(客户端)如下图所示:
在本节中,讨论了错误情况下的SOME/IP-SD(例如丢失或损坏的数据包)。这也被理解为使用的机制和可能的配置的基本原理
软状态协议:SOME/IP-SD被设计为软状态协议,这意味着Entries具有生命周期,需要刷新才能保持有效(将TTL设置为最大值将关闭此功能)
初始等待阶段:
引入初始等待阶段有两个原因:启动ECU的去偏移事件以避免流量突发,并允许ECU收集SD消息中的多个entries
重复阶段:
引入了重复阶段以允许客户端和服务器的快速同步。如果客户端启动较晚,它会很快找到服务器。而且如果服务器稍后启动,可以很快找到客户端。重复阶段以指数方式增加两条消息之间的时间,以避免过载情况使系统无法同步
主阶段:
在主阶段,SD尝试稳定状态,从而通过不再发送查找服务来降低数据包速率,并且仅在循环间隔(例如每1秒)中提供
请求-响应-延迟:
SOME/IP-SD应配置为通过请求-响应-延迟来延迟对多播消息中entries的回答。这在具有许多ECU的大型系统中很有用。当发送一个包含许多entries的SD消息时,来自不同ECU的大量回复同时到达,并且对接收所有这些回复的ECU施加了很大的压力
上图显示了对传入的SOME/IP-SD消息进行错误处理的简化过程
“ 检查是否存在用于空SOME/IP-SD消息的至少足够字节,即消息至少有12个字节长。如果检查失败,则该消息将被丢弃,无需进一步操作
”
“ 如果接收到的entry的服务ID未知,则应忽略该entry
”
“ 如果接收到的entry的实例ID未知,则应忽略该entry
”
“ 如果接收到的entry的主版本未知,则应忽略该entry
”
“ 如果接收到的entry的事件组ID未知,则应忽略该条目。这仅适用于事件组entry
”
“ 如果Entries数组的长度无效(即entries数组将超过消息大小),则应丢弃该消息,无需进一步操作
”
检查每个收到的Entry引用的选项:
“ 检查TCP连接是否已经存在(仅适用于为事件组配置TCP并且收到 Subscribe Eventgroup Entry的情况)
”
“ 检查是否剩余足够的资源(例如套接字连接)
”
“ 如果对收到的Find entry的检查失败,则应忽略该entry
”
“ 如果对收到的Offer entry的检查失败,则该entry将被忽略
”
“ 如果对接收到的Subscribe Eventgroup Entry的检查失败,则应发送Subscribe Eventgroup NACK Entry
”
“ 如果对接收到的 Subscribe Eventgroup ACK Entry的检查失败,则应处理该entry,但不应将订阅视为成功
”
如果出现以下情况,Entry引用的选项将被忽略:
除了SOME/IP之外,车内还使用了其他通信协议;例如,用于网络管理、诊断或闪存更新。此类通信协议可能需要与服务实例通信或还具有事件组
对于非SOME/IP协议(应用程序协议本身不使用SOME/IP,但它通过SOME/IP SD发布)应使用特殊的服务ID,并应使用配置选项添加更多信息:
“ SOME/IP服务不应使用配置选项中的otherserv-string”
“ 对于Find Service/Offer Service/Request Service Entry,在宣布非SOME/IP服务实例时应使用otherserv-String”
注意:与SOME/IP请求/响应机制相比,在某些情况下,客户端可能需要从服务器获得一组参数,但不希望每次需要时都请求该信息。它们被称为通知、关注事件和字段(Fields)。
“ 通过SOME/IP-SD Entry Offer Service,服务器提供向客户端推送通知;因此,它用作订阅的触发器
”
“ 只要客户端仍然有兴趣接收此事件组的通知/事件,每个客户端都应使用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没有过期,那么客户端不应请求初始事件”
客户明确请求初始事件的原因包括但不限于:
“ 如果客户端订阅了两个或多个事件组,包括一个或多个相同的事件或字段,则服务器不应为该字段发送重复的事件或通知事件。这意味着是常规事件而不是初始事件”
客户端链接丢失的发布/订阅描述如下:
没有事先注册+客户端订阅
(a) Server: OfferService()
(b) Client: SubscribeEventgroup[Session ID=x, Reboot=0]
© Server: updateRegistration()
(d) Server: SubscribeEventgroupAck + Events()
客户端链路丢失
(a) Client: linkDown()
(b) Client: deleteEntries()
© Client: linkUp()
客户端应通过发送TTL=0的SOME/IP-SD订阅事件组消息(停止订阅事件组)从服务器注销
发布/订阅,注册/注销行为描述如下:
如果在发送事件或通知事件后发生相关的SOME/IP错误,服务器上的SOME/IP-SD将删除订阅,错误包括但不限于无法到达通讯伙伴和TCP连接错误
服务器上链接丢失的发布/订阅描述如下:
“ 如果通过TCP提供服务并且客户端根据配置通过TCP请求事件组,则客户端应在发送Subscribe Eventgroup Entry之前打开与服务器的TCP连接
”
“ 客户端发送Subscribe Eventgroup Entry后,服务器应发送Subscribe Eventgroup Ack Entry
”
客户端应等待确认Subscribe Eventgroup Entry的Subscribe Eventgroup Ack Entry。如果在发送下一个Subscribe Eventgroup Entry之前该Subscribe Eventgroup Ack Entry未到达,则客户端应执行以下操作:
如果服务器的“显式初始数据控制标志”设置为0,则在发送Subscribe Eventgroup Entry的同一SOME/IP-SD消息中发送Stop Subscribe Eventgroup Entry和Subscribe Eventgroup Entry
如果“服务器的显式初始数据控制标志设置为1”,则将下一个Subscribe Eventgroup Entry的初始数据请求标志设置为1
这种行为的存在是为了应对短时间的通信丢失,因此会触发新的初始事件以降低消息丢失的影响
如果客户端发送一个订阅事件组Entry作为对单播Offer的反应,并且在此之后但在订阅事件组确认entry可以由服务器发送和接收之前立即到达多播Offer,则客户端不应抱怨(例如停止订阅/订阅) 关于尚未收到的确认
存在这种行为是为了应对短时间的通信丢失。停止订阅事件组和订阅事件组组合的接收者将发送初始事件以降低消息丢失的影响
“ 如果初始值值得关注 - 例如对于字段 - 并且客户端将显式初始数据控制标志(在SOME/IP-SD首部中)设置为0,则服务器在发送订阅事件组确认后应立即发送第一个通知/事件(即初始事件)
”
“ 如果服务器接收到初始数据请求标志设置为0且显式初始数据控制标志(在SOME/IP-SD首部中)设置为1的Subscribe Eventgroup Entry,则服务器将不发送通知/事件(即初始事件)
”
“ 如果服务器接收到初始数据请求标志设置为1且显式初始数据控制标志(在SOME/IP-SD首部中)设置为1的订阅事件组Entry,则服务器在发送订阅事件组确认后应立即发送通知/事件(即初始事件)
”
“ 订阅时不允许发送事件的初始值(纯事件而非字段)
”
“ 字段通知器的事件消息应在订阅上发送(字段而不是纯事件)
”
“ 如果订阅已经有效并且由订阅事件组Entry更新,则不应发送初始事件
”
“ 接收Stop Subscribe/Subscribe组合触发字段通知的初始事件
”
“ 初始事件应在订阅事件组确认之后发送"
发布/订阅状态(单播事件组的服务器行为)定义如下:
“ 如果客户端使用不同的SOME/IP-SD消息订阅同一服务实例的不同事件组,并且所有事件组包含相同的字段,则服务器应为每个订阅分别发送该字段的初始事件
”
“ 如果客户端使用一条SOME/IP-SD消息订阅同一服务实例的不同事件组,并且所有事件组都包含相同的字段,则服务器可以选择不多次发送该字段的初始事件
”
这意味着服务器可以通过仅发送一次初始事件来优化,如果其架构支持的话
服务端自适应单播/组播事件组行为的发布/订阅状态时序图如下:
“如果达到了用户数量的配置阈值,SOME/IP-SD应支持从单播到多播的自动切换”
“SOME/IP SD协议应支持通信端口的隐式配置和订阅者的注册。这些应基于静态配置,并且不使用网络上的任何SD消息”
以下entries应仅通过单播传输:
“ 如果SUBSCRIBE_RETRY_MAX配置为大于0,客户端应重试订阅 ServerService的Eventgroup。如果在可配置的超时(SUBSCRIBE_RETRY_DELAY)内未收到请求的Eventgroup的SubscribeEventgroupAck/NAck entry,则应发送对Eventgroup 的订阅)。只要请求事件组并且未超过配置的重试计数(SUBSCRIBE_RETRY_MAX),就应进行重试
”
“ 接收到的OfferService的TTL设置为0xFFFFFF的ServerService,可以将SUBSCRIBE_RETRY_MAX设置为INF。在这种情况下,只要请求了Eventgroup并且没有收到请求的Eventgroup的SubscribeEventgroupAck/NAck entry,就应该进行重试
本章节主要介绍保留标识符和特殊标识符
Name | Description |
---|---|
INITIAL_DELAY_MIN | Minimum duration to delay randomly the transmission of a message. |
INITIAL_DELAY_MAX | Maximum duration to delay randomly the transmission of a message. |
REPETITIONS_BASE_DELAY | Duration of delay for repetitions. |
REPETITIONS_MAX | Configuration for the maximum number of repetitions. |
REQUEST_RESPONSE_DELAY | The Service Discovery shall delay answers using this configuration item. |
CYCLIC_OFFER_DELAY | Interval between cyclic offers in the main phase. |
SD_PORT | is a UDP Port for SD Messages (30490 as default). |
SD_MULTICAST_IP | address which shall be used by the SD multicast messages. |
SUBSCRIBE_RETRY_MAX | Max count of retries for subscribe, as long as the Event-group is requested (0=no retry, INF= retry forever (as long as the Eventgroup is requested and no no SubscribeEventgroupAck/Nack entry was received)). |
SUBSCRIBE_RETRY_DELAY | Duration of delay to send a consecutive subscribe entries, if a Eventgroup is requested and no SubscribeEventgroupAck/Nack entry was received. |
MULTICAST_THRESHOLD | Specifies the number of subscribed clients with different endpoint information per Eventgroup that triggers the server to change the transmission of events to the server service multicast endpoint. This multicast endpoint is configured by the server service and provided with the SubscribeEventgroupAck: - If configured to 0 only the client service unicast/-multicast endpoint will be used. - If configured to 1 the first client and all further subscribed clients will be served via the server service multicast endpoint. - If configured to n up to n-1 clients with different endpoint information will be served via a client service unicast/multicast endpoint provided by the client within the SubscribeEventgroup. As soon as the number of subscribed clients with different endpoint information reaches n, then all subscribed clients are served via the server service multicast endpoint. |
“ 接收到的SOME/IP-SD消息应检查端口选项和SD端口选项中接收的IP地址是拓扑正确的(参考使用SOME/IP-SD的IP子网中的 IP地址)并且应忽略不是拓扑正确的以及引用这些选项的entries
”
这意味着只能访问同一子集中的客户端和服务器
在本节中,将讨论服务发现的强制性功能集和相关的配置约束。 这允许在没有当前用例可能不需要的可选的或信息化的功能的情况下进行最低限度的实现
以下信息被定义为合规检查清单。如果未实现某个功能,则认为该实现不符合SOME/IP-SDs基本功能集
应实现以下entry类型:
Find Service
Offer Service
Stop Offer Service
Subscribe Eventgroup
Stop Subscribe Eventgroup
Subscribe Eventgroup Ack
Subscribe Eventgroup Nack
当需要 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
服务器应使用单播(没有基于单播标志的优化)以Offer Serive来回答主阶段的Find Service
服务器在关闭时应发送停止Offer Serice
服务器应接收订阅事件组和停止订阅事件组,并根据本规范做出反应
服务器应使用单播发送订阅事件组确认和订阅事件组确认。
服务器应支持基于SOME/IP-SD的订阅控制SOME/IP事件消息的发送。这可能包括发送基于多播的事件
服务器应支持触发初始SOME/IP事件消息
以下行为/反应应在客户端实施:
客户端应仅在重复阶段使用查找服务entry和多播(在SD_MULTICAST_IP 定义的多播地址上)来Find Service
如果常规Offer Service到达,客户应停止Find Service
客户端应使用单播SD消息对服务器OfferService做出反应,该消息包括客户端当前想要订阅的服务器消息中提供的服务的所有订阅事件组
客户应按照本文档中的规定解释并响应订阅事件组确认和订阅事件组否定确认
客户端应支持以下行为和配置约束:
如果仅指定SD计时的TTL,则客户端应能够处理事件组。这意味着在初始等待阶段、重复阶段和主阶段的所有时序中,仅配置了TTL。这意味着客户端只能对服务器的Offer Service作出反应
即使没有配置Request-Response-Delay,客户也应使用订阅事件组响应Offer Service,这意味着它不应等待而是立即响应
客户端和服务器应实施本文档中指定的重启检测并做出相应反应。 这包括但不限于:
根据本规范设置会话ID和重启标志
保留仅用于发送多播SD消息的会话ID计数器
为每个单播关系保留会话ID计数器以发送单播SD消息
根据本规范了解会话ID和重启标志
为与该ECU交换多播SD消息的每个ECU保留一个多播会话ID计数器
为与该ECU交换单播SD消息的每个ECU保留一个单播会话ID计数器
根据此规范检测重启并做出相应反应
正确解释有关重启检测的IPv4和IPv6 SD端口选项
客户端和服务器应实现“服务和事件的端口处理”。这包括但不限于:
如果需要UDP,则将1个端口选项UDP添加到提供服务
如果需要TCP,则将1个端口选项TCP添加到提供服务
如果需要UDP事件,则将1个端口选项UDP添加到订阅事件组
如果需要TCP事件,则将1个端口选项TCP添加到订阅事件组
如果需要多播事件,则添加1个多播选项UDP到订阅事件组确认
根据上述传输的端口和多播选项了解和采取行动
使用这些端口和多播选项的信息覆盖预配置的值(例如IP地址和端口)
将传入的IPv4和IPv6端口选项解释为SD端口,而不是外层的地址和端口号
“ 客户端和服务器应实现对初始事件的显式请求
”
为了支持迁移场景,ECU应支持服务以及使用同一服务的不同不兼容版本
为了支持具有多个版本的服务,需要以下内容:
服务器应为每个主要版本提供一次该服务的服务实例
客户端应在每个支持的主要版本中查找一次服务实例,或者应将主要版本用作0xFF(所有版本)
客户端应订阅它需要的服务版本的事件
所有SOME/IP-SD Entries应使用相同的服务ID和实例ID,但主要版本不同
服务器必须根据它们到达的套接字、消息ID、主要版本对消息进行多路分解,并根据这些条件在内部将其中继到正确的接收器
“ 在一个VLAN中,最多有一个Service ID、Major Version 和Instance ID相同的服务实例。这适用于服务器和客户端网络节点
”
不允许在一个网络节点上配置多个仅在次要版本上有所不同的服务实例,因为它们在事件组entries中无法区分
1.AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol
2. 详解SOME/IP-SD协议文档