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


    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基础协议

    在这里插入图片描述
    基础协议包的定义如上:
    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) 
    
    • 1
    • 2

    Length: 报文从RequestID开始到报文最后一个字节的长度
    RequestID: 请求ID用来区分消息的来源,RequestID由ClientID与SessionID组成,Session ID的有效范围是0x1-0xFFFF, 当到达0xFFFF后,值重置为0x1
    Protocol Version: 协议版本号
    Interface Version :服务接口版本号
    Message Type : 消息类型,类型如下图
    在这里插入图片描述
    Return Code : 返回值类型,用来表示请求消息是否成功处理。该值只有在消息类型为Response/Error中才有代表意义,其他报文类型中,该值为0. 具体的错误码对照如下表。
    在这里插入图片描述
    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-SD协议格式

    SOME/IP-SD协议报文格式如下图所示
    在这里插入图片描述

    报文头

    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所包括的服务信息,在报文中的格式如下所示
    在这里插入图片描述
    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-SD报文
    在这里插入图片描述

    事件组实体

    事件组实体的SD报文格式与服务的实体报文格式有一定的区别,事件组的报文格式如下:
    在这里插入图片描述
    事件组实体的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。
    在这里插入图片描述
    Load Balancing Option: 负载均衡配置,这个配置项配置服务的优先级,权重等信息,客户端可以根据这个配置来选择与对应的服务交互。
    在这里插入图片描述
    IPv4 Endpoint Option: IPv4通讯配置,这个配置项包含了通信所需的IP地址,通讯方式(UDP/TCP),以及发送方的端口号。
    在这里插入图片描述
    IPv6 Endpoint Option: IPv6通讯配置,这个配置项包含了通信所需的IP地址,传输层协议(UDP/TCP),以及发送方的端口号。
    在这里插入图片描述
    IPv4 Multicast Option: IPv4组播配置项
    在这里插入图片描述
    IPv6 Multicast Option: IPv6组播配置项
    在这里插入图片描述
    IPv4 SD Endpoint Option: IPv4 SD网络端点配置

    在这里插入图片描述
    IPv6 SD Endpoint Option: IPv6 SD网络端点配置
    在这里插入图片描述

    通信行为流程

    启动阶段行为

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

    Not Ready (未就绪)
    Ready 
    	Initial Wait Phase (已就绪初始化阶段)
    	Repetition Phase (已就绪重复阶段)
    	Main Phase (已就绪主阶段)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    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报文。
    行为时序
    • 客户端网络链路状态变更时发布/订阅流程
      在这里插入图片描述
    • 双Client端订阅/发布时序
      在这里插入图片描述
    • 服务端网络链路状态发生变更时的发布/订阅流程
      在这里插入图片描述

    本文基于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中的招式来在车载以太网中打出自己的一招一拳。

  • 相关阅读:
    文件防泄密软件哪个好?
    C语言-入门-const关键字(十九)
    EMQX服务器的API接口使用介绍_完成上位机开发
    gcc: -fno-threadsafe-statics: __cxa_guard_acquire;__cxa_guard_release
    系统架构设计师 需求分析篇一
    Java-多线程基础及线程安全
    什么是P问题、NP问题和NPC问题
    Jmeter性能实战之分布式压测
    idea设置项目启动的JVM运行内存大小
    python request post from 提交表单
  • 原文地址:https://blog.csdn.net/zjfengdou30/article/details/125332151