车联网通信中间件 -- SOME/IP协议

SOME/IP 协议

    • 缩略词
    • SOME/IP基础协议
    • SOME/IP-SD协议
      • SOME/IP-SD协议格式
        • 报文头
        • 服务实体
        • 事件组实体
        • 配置项
        • 通信行为流程
          • 启动阶段行为
          • 关机行为
          • 行为时序

SOME/IP是一个应用于汽车或者嵌入式系统的通信中间件解决方案,该协议是一个基于IP的,且面向服务的应用层网络通信协议,具备可伸缩和可扩展,以及可应用在不同的操作系统中用于各类设备之间的通信等特性。通俗一点来说,SOME/IP它是一个协议,这个跟我们平时开发外设自己定义的那种TLV包的格式差不多,有包头,有报文长度,有报文内容, 多个设备间基于IP网络来进行包的收发,SOME/IP协议还定义了一些通信的动作以及具体场景下端与端之间的行为。

缩略词

在介绍具体协议内容之前可以先了解一下一些后面具体的名词定义,后续不管是协议还是协议栈中,都大量出现了相关的名词应用

  1. Method : SOME/IP实现端存在的方法,类似于一个函数,或者子程序。
  2. RR请求 : Request/Response,请求端调用目标端的method,并且有返回内容,可以理解为我们日常写程序过程中的调用一个带返回值的函数
  3. FF请求 : Fire And Forget,请求端调用目标端的method, 没有返回参数。可以理解为我们日常写程序过程中调用了一个返回值为void的函数。
  4. Event : 顾名思义就是一个事件,event事件在SOME/IP中是单向的,你可以理解成触发一个回调函数,通知函数监听方。
  5. Field : 顾名思义是一个属性,属性自带setter与getter方法,并且支持RPC调用,且还包含了一个notification,这个notification实际也是一个event,当属性值变化时通知监听对象。
  6. Service: 上面说过SOME/IP是面向服务开发的,Service是由一个个的Field,Event, Method组成的逻辑体。
  7. Eventgroup:事件组,event或者field notification组成的结合体,主要用来允许事件订阅

SOME/IP基础协议

车联网通信中间件 -- SOME/IP协议_第1张图片
基础协议包的定义如上:
MessageID: 占了4个byte共32位,前16位代表Service ID, 中间一位类型符用来表示后面的ID是Method ID(flag = 0)还是Event ID(flag = 1), 后15位代表Method ID或者Event ID.
格式如下:

 Service ID(16bit)  ------  0(1bit)   ------  MethodID(15bit)
 Service ID(16bit)  ------  1 (1bit)  ------  ClientID (15bit) 

Length: 报文从RequestID开始到报文最后一个字节的长度
RequestID: 请求ID用来区分消息的来源,RequestID由ClientID与SessionID组成,Session ID的有效范围是0x1-0xFFFF, 当到达0xFFFF后,值重置为0x1
Protocol Version: 协议版本号
Interface Version :服务接口版本号
Message Type : 消息类型,类型如下图
车联网通信中间件 -- SOME/IP协议_第2张图片
Return Code : 返回值类型,用来表示请求消息是否成功处理。该值只有在消息类型为Response/Error中才有代表意义,其他报文类型中,该值为0. 具体的错误码对照如下表。
车联网通信中间件 -- SOME/IP协议_第3张图片
Payload : 有效的数据负载,UDP传输时最大传输字节数为1400,TCP传输无限制

SOME/IP-SD协议

SOME/IP-SD协议是基于SOME/IP基础协议上制定的一系列通信业务协议,全称(Scalable service-Oriented MiddlewarE over IP - Service Discover),主要用于SOME/IP服务实例的定位,状态检测,以及SOME/IP服务发布/订阅机制的实现。我们可以这么理解,假设有这么一个场景,王者荣耀有个聊天室,很多人在里面发各种消息(有吹水的,有发红包的,有拉人的等等),我们就可以把这些消息当作一个个的SOME/IP消息包,这时候我们准备搞个5排,但是少了一个人,于是我们也往这个聊天室发了一个组队消息,告诉别人,我们现在有一个车队,全是王者以上的,你们可以来玩,有人想玩高端局的话,他就点击进去了,然后你们就跟这个人一起玩了一把(建立交流),这个发布组队的包的消息就可以理解为SD协议的其中一个功能。SOME/IP基础协议的通讯支持TCP/UDP两种方式,而SOME/IP-SD协议仅支持UDP通讯。通信层级模型如下所示
车联网通信中间件 -- SOME/IP协议_第4张图片

知识总图:
车联网通信中间件 -- SOME/IP协议_第5张图片

SOME/IP-SD协议格式

SOME/IP-SD协议报文格式如下图所示
车联网通信中间件 -- SOME/IP协议_第6张图片

报文头

SOME/IP-SD协议的报文头格式与基础协议一致,区别就是MessageID为固定的0xFFFF8100, 其中ServiceID为0xFFFF, MethodID为0x8100。其余值分别定义如下:
Protocol Version = 0x1
Interface Version = 0x1
Message Type = 0x2
Return Code = 0x0

基础协议这部分的内容介绍完成后,接下来是SOME/IP-SD的报文内容,SD的报文属于payload这部分.首个字节是Flags, Flags标记位占一个字节的长度,bit0代表客户端重启的flag, bit1代表当前SD是否使用单播方式通信(这个值已经废弃,只是为了兼容之前的版本所以保留),bit2代表当前ECU是否支持显式的初始化数据控制.

Flags后的三个字节用来预留。

Length of Entries Array:占4个字节的长度,用来表示实体数组的字节数。

SOME/IP-SD Entry: SD报文实体,主要用来同步服务实例的状态以及发布/订阅的实现,实体类型分为两种,服务实体(Service Entry)事件组实体(Eventgroup Entry),

服务实体

主要用来传输ECU所包括的服务信息,在报文中的格式如下所示
车联网通信中间件 -- SOME/IP协议_第7张图片
Type分三种,分别为FindService(0x00), OfferService(0x01), StopOfferService(0x01)
Index 1st options: 首配置项的下标(对应Options Array数组中的下标)
Index 2nd options: 第二配置项的下标(对应Options Array数组中的下标)
Number of Options 1: 首位配置项数
Number of Options 2: 第二配置项数
Service ID: 关联的服务ID
Instance ID : 关联的实例ID
Major Version: 服务的主版本号
TTL:实体的生命周期,单位是秒
Minor Version: 服务的小版本号

对照Wireshark中的报文结构看更加清晰,如下是ECU发送一条OfferService的SD报文

SOME/IP 报文头
车联网通信中间件 -- SOME/IP协议_第8张图片

SOME/IP-SD报文
车联网通信中间件 -- SOME/IP协议_第9张图片

事件组实体

事件组实体的SD报文格式与服务的实体报文格式有一定的区别,事件组的报文格式如下:
车联网通信中间件 -- SOME/IP协议_第10张图片
事件组实体的Type分为订阅Subscribe(0x6), 停止订阅StopSubscribeEventgroup(0x6), 订阅成功ack SubscribeACK(0x7), 以及订阅异常的NACK(0x7)
Index 1st options,
Index 2nd options
# of opt 1,
# of opt 2
Service ID, ,
InstanceID,
Major Version,
TTL
如上的值代表的意义同服务实体中的意义是一样的。

Initial Data Requested Flag : 该值如果为1,则表示服务端在客户端订阅成功的时候需要触发一次事件发布。
Counter : 用于区分同一订阅服务器的相同订阅事件组。如果未使用,则设置为0x0
Eventgroup ID : 事件组ID

配置项

配置项的主要作用是用来传输一些实体的额外信息,如IP地址,通信端口号,通信协议等。主要有如下几类配置项:
Configuration Option: 可以理解为配置类的配置项,数据的格式类似DNS TXT或者DNS-SD。
车联网通信中间件 -- SOME/IP协议_第11张图片
Load Balancing Option: 负载均衡配置,这个配置项配置服务的优先级,权重等信息,客户端可以根据这个配置来选择与对应的服务交互。
车联网通信中间件 -- SOME/IP协议_第12张图片
IPv4 Endpoint Option: IPv4通讯配置,这个配置项包含了通信所需的IP地址,通讯方式(UDP/TCP),以及发送方的端口号。
车联网通信中间件 -- SOME/IP协议_第13张图片
IPv6 Endpoint Option: IPv6通讯配置,这个配置项包含了通信所需的IP地址,传输层协议(UDP/TCP),以及发送方的端口号。
车联网通信中间件 -- SOME/IP协议_第14张图片
IPv4 Multicast Option: IPv4组播配置项
车联网通信中间件 -- SOME/IP协议_第15张图片
IPv6 Multicast Option: IPv6组播配置项
车联网通信中间件 -- SOME/IP协议_第16张图片
IPv4 SD Endpoint Option: IPv4 SD网络端点配置

车联网通信中间件 -- SOME/IP协议_第17张图片
IPv6 SD Endpoint Option: IPv6 SD网络端点配置
车联网通信中间件 -- SOME/IP协议_第18张图片

通信行为流程

启动阶段行为

每个SOME/IP应用都具备如下四个阶段:

Not Ready (未就绪)
Ready 
	Initial Wait Phase (已就绪初始化阶段)
	Repetition Phase (已就绪重复阶段)
	Main Phase (已就绪主阶段)

车联网通信中间件 -- SOME/IP协议_第19张图片

Not Ready:

  • 客户端状态为此阶段服务未被应用,或者IP地址对应的网卡未就绪。
  • 服务端状态为Service不可用,或者无法提供Service实例,或者IP地址对应的网卡未就绪。

Ready in Initial Wait Phase:
初始化等待阶段是为了优化启动时多个ECU同时启动发送SD报文引起的流量高峰问题,以及允许各个ECU收集SD报文中的多个实体,此时的行为动作对应如下:

  • 客户端等待INITIAL_DELAY的时间片段之后,发送首个Find Service SD报文
  • 服务端等待INITIAL_DELAY的时间片段之后,发送首个Offer Service SD报文

INITIAL_DELAY是一个随机值,协议栈需要定义一个范围,INITIAL_DELAY_MIN到INITIAL_DELAY_MAX,每次进入初始阶段的等待时间都是从这个范围内取的随机值

报文发送完成之后进入重复阶段。

Ready in Repetition Phase:
重复阶段设计的目的主要是为了快速同步客户端与服务端的状态。因为车上的ECU不可能事同时启动,肯定有先后,重复阶段的目的就是加快两者之间互相发现的效率。并且重复阶段以指数级增加的方式去增加消息发送的间隔时间,以避免过载情况使系统无法同步。重复阶段对应的动作如下:

  • 客户端重复发送FindService报文,间隔时间为2^(REPETITIONS_MAX - 1) * REPETITIONS_BASE_DEDAY,发送最大次数为REPETITIONS_MAX,如果在重复阶段有收到Offer Service报文,立即进入Main Phase

  • 服务端重复发送OfferService报文,间隔时间为2^(REPETITIONS_MAX - 1) * REPETITIONS_BASE_DEDAY,发送最大次数为REPETITIONS_MAX,如果收到客户端的FindService报文,则延迟一定时间(REQUEST_RESPONSE_DELAY)后,发送单播OfferService给客户端

Ready in Main Phase:
主阶段SOME/IP-SD尝试进入稳定状态,各类包的发送频率都有大幅减少

  • 客户端停止周期性发送FindService报文,在收到OfferService事,发送subscribeEventgroup报文
  • 服务端将以CYCLIC_OFFER_DELAY定义的值来周期性发送OfferService报文
关机行为
  • 服务端服务实例在重复阶段或者主阶段停止时,需要发送StopOfferService实体报文
  • 任意阶段检测到网络链路不可用时,进入Not Ready阶段
  • 任意阶段检测到网络链路状态变化时,如果链路可用并且服务依旧是有效状态,则服务端对应进入初始化等待阶段。
  • 任意阶段检测到网络链路状态变化时,如果链路可用并且服务依旧已被请求,则客户端对应进入初始化等待阶段。
  • 服务端发送StopOfferService实体报文后,所有服务实例中的相关事件订阅需要全部删除。
  • 客户端收到StopOfferService报文后,所有该服务实例相关的订阅需要全部删除。
  • 客户端收到StopOfferService报文后,不再发送Find Service实体。
  • 当处于主阶段的客户端服务实例停止后,SD模块需要发送StopSubscribeEventgroup实体报文。
  • 当ECU关机时,需要发送StopOfferService与StopSubscribeEventgroup报文。
行为时序
  • 客户端网络链路状态变更时发布/订阅流程
    车联网通信中间件 -- SOME/IP协议_第20张图片
  • 双Client端订阅/发布时序
    车联网通信中间件 -- SOME/IP协议_第21张图片
  • 服务端网络链路状态发生变更时的发布/订阅流程
    车联网通信中间件 -- SOME/IP协议_第22张图片

本文基于http://some-ip.com/standards.shtml 中的
《SOME/IP Protocol Specification》
《SOME/IP Service Discovery Protocol Specification》

两篇文档整理,了解了SOME/IP的协议基础就相当于掌握了基本的内功,但是光有内功还是不行,还得有招式,就像张无忌学了九阳神功之后,打架还是菜鸟,九阳只是内功,真正打架的还是招式,SOME/IP应用的招式就是vsomeip, 这是一个GENIVI开源的协议栈,对应的开源库地址https://github.com/GENIVI/vsomeip.git

下一篇,我将修炼vsomeip中的招式来在车载以太网中打出自己的一招一拳。

你可能感兴趣的:(Android车联网,中间件,tcp/ip,网络)