一、概述
SOME/IP(Scalable service-Oriented MiddlewarE over IP):IP上可扩展的面向服务的中间件。
可扩展(scalable),也叫做可伸缩,指能够适应不同操作系统,以及不同大小的设备。
• 不同大小的设备:小到摄像头,大到车机或通信设备
• 不同操作系统:AUTOSAR/OSEK/Linux
面向服务的(setvice-oriented)
• 起源于传统IT概念,关注对象为服务
• 是相对于传统面向信号通信的另一种实现手段
中间件(middleware)
• 一种独立的系统软件或服务程序,分布式应用软件可借助Middleware在不同的技术之间共享资源。(分布式应用软件,在这里指的就是“服务”;不同的技术之间,在这里指的就是“不同的平台或操作系统,比如Linux系统或AUTOSAR系统等。)
• 为软件应用程序提供服务的软件,屏蔽了底层的通讯,交互,连接等复杂又通用化的功能,使软件开发者集中精力于应用层开发
基于IP(over IP)
• 就是基于IP/TCP协议的传输,也就是用以太网传输
SOME/IP-SD:SOME/IP的服务发现,用于订阅服务实例,并检测服务实例是否正在运行以及实现发布/订阅处理。
SOME/IP:用于控制通信的一种面向服务的数据传输方法。
二、服务
1.服务基本概念
面向服务的通信,是相对于传统的面向信号的通信的另一种实现手段,借助于远程过程调用(Remote Procedure Calls, RPC)机制。
SOME/IP通过网络提供面向服务的通信。它基于列出服务提供的功能的服务定义。一个服务可以由零个或多个事件、方法和字段的组合组成。事件提供周期性发送的数据或从提供者发送到订阅者的数据。方法为订阅者提供了发出在提供者端执行的远程过程调用的可能性。字段是以下三个一个或多个的组合通知程序发送数据改变供应商的用户可以称为用户显式查询提供者的值设置者可以调用用户当它想要改变提供方的值
远程过程调用
远程过程调用协议(Remote Procedure Call Protocol)是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。远程过程调用RPC(Remote Procedure Call)通过网络从服务端程序上请求实现某一项或多项功能。
4种类型的服务接口
服务接口是服务与外界通信的通道,服务内容需要通过该通道传输给外界,是服务内容的传递者,SOME/IP作为中间件打包的数据内容,就放在服务接口中。
1.请求/响应通信(Request/Response Communication)—— 方法(Method)
Client发送请求报文,Server回复响应报文
2.单向请求通信(Fire & Forget Communication) —— 单向方法(F&F Method)
不需要响应报文的请求通信
3.通知事件(Notification Event):—— 事件(Event)
Client订阅一个服务,Service发布该服务
状态值:on change/cycle/事件值变化超过预期设置范围
4.域(Field):——属性(Properties)
• Setter(设置器)
• Getter(获取器)
• Notifier(通知器)
Service服务:由0个或多个event、method和field组成。
Event事件:提供周期性发送的数据或从提供者发送到订阅者的变更数据。
Method方法:订阅者发出远程过程调用,该调用是在提供方执行的。
Field属性:以下3个中的一个或多个组合:
- Notifier:将更改的数据从提供者发送到订阅者。
- Getter:订阅者显式地查询提供者的值。
- Setter:订阅者想要在提供方更改地值。
The notifier of field和event的区别:事件仅在更改时发送,属性的通知还会在订阅后直接发送数据。
Eventgroup事件组:一个服务内部事件和属性通知事件的逻辑分组,包括,以便允许订阅。事件和属性的通知被映射到至少一个事件组。
数据结构的序列化
序列化
将数据结构或对象依据实现定义的规则转换成可以存储或传输的二进制串,是一种数据在PDU中的表达形式,真实数据经过RTE装换成固定格式的字节序。
反序列化
将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。
内存对齐
当数据从一个特定数字的倍数(例如32位的倍数)的地址开始时,当有一些处理器架构可以更高效地访问数据。
数据类型
- 基本类型
类型 | 描述 | 大小[bit] |
boolean | True、False值 | 8 |
uint8 | 无符号整数 | 8 |
uin16 | 无符号整数 | 16 |
uint32 | 无符号整数 | 32 |
sint8 | 带符号整数 | 8 |
sint16 | 带符号整数 | 16 |
sint32 | 带符号整数 | 32 |
float32 | 浮点数 | 32 |
float64 | 浮点数 | 64 |
对于boolean值,只解释最低位的uint8。
- 结构体
标记字段:2字节,保留1bit,线类型3bit,数据ID12bit。
保留 | Wire Type | Data ID |
Length | ||
线类型 | 以下数据 |
0 | 8bit基本数据类型 |
1 | 16bit基本数据类型 |
2 | 32 bit基本数据类型 |
3 | 64 bit基本数据类型 |
4 | 复杂数据类型:数组、结构、字符串、具有静态长度字段的联合(在数据定义中配置) |
5 | 复杂数据类型:数组、结构、字符串、长度字段大小1字节(忽略静态定义) |
6 | 复杂数据类型:数组、结构、字符串、长度字段大小为2字节的联合(忽略静态定义) |
7 | 复杂数据类型:数组、结构、字符串、长度字段大小为4字节(忽略静态定义) |
- 字符串
固定长度字符串和动态长度字符串。
支持不同的Unicode编码:UTF-8、UTF-16BE and UTF-16LE
所有字符串应以字节顺序标记(BOM)开头,以“\0”字符结尾。BOM包含在长度中。
动态长度字符串,长度字段在BOM之前,默认的长度字段占32bit,长度字段本身不包含在字符串长度里。
- 数组
1.固定长度数组
可以被看作是重复的元素。
实际长度大于预期长度,只解释预期长度内的元素。
实际长度小于预期长度,应中止序列化,消息视为畸形。
一维固定数组
多维固定数组
2.动态长度数组
长度字段的长度应为0、8、16或32位。长度不包括长度字段的大小。
一维动态数组
多维动态数组
- 枚举
在SOME/IP中不考虑枚举。枚举应作为无符号整数数据类型传递。
- 位域
位域(bitfield)应作为无符合数据类型uint8/uint16/uint32进行传输。
- 联合/变体
长度不包括长度字段和类型字段的大小,如果长度字段的长度为0位,则联合节点中的所有类型都应为相同的长度。类型字段为0的值应为NULL类型保留
-
报文格式
SOME/IP报文格式
SOME/IP报文主要由首部(Header)和数据段(Payload)组成。首部是按照固定格式排列的有效信息,这些有效信息包括报文ID、报文长度信息、请求ID、协议版本、接口版本、报文类型、返回码。数据段包含的是“处理之后(序列化后的)”的服务数据信息。
Message ID,32bit,唯一性,用于识别对一个应用程序的一个方法的RPC调用或识别一个事件。包括3部分:
- Service ID服务,16bit,标识一个服务。
- 置0,1bit。
- Method ID方法,15bit,标识一个方法。
- Service ID服务,16bit,标识一个服务。
- 置1,1bit。
- Event ID方法,15bit,标识一个事件。
Length,32bit,从Request ID开始到Payload的字节长度,也就是8字节+payload的长度。
Request ID,32bit,对于提供者和订阅者的组合,请求ID应是唯一的。当生成响应消息时,提供者应将请求ID从请求复制到响应消息。在响应到达或预计不再到达(超时)后,可以重用请求ID。
- Client ID,16bit,区分不同客户端,Method的请求报文和响应报文Client ID值相同,Event报文Client ID值为0x0000,SD报文中的Client ID值为0x0000。
- Session ID,16bit,区分同一客户端的多次调用。
会话处理处于活动状态,会话ID应该在每次调用后进行递增,当会话ID达到0x FFFF时,会以0x0001重新开始。
会话处理处于非活动状态,会话ID应设置为0x00。
会话状态 | 会话ID |
非活动状态 | 0x0000 |
活动状态 | 0x0001~0x FFFF |
同一条请求和响应中的会话ID应一致,如果响应的会话ID与请求的会话ID不匹配,则订阅者必须忽略响应。
Protocol Version,8bit,协议版本标识已使用的SOME/IP首部格式,协议版本固定为0x01。
Interface Version,8bit,服务接口的主要版本,接口版本固定为0x01。
Message Type,8bit,区分不同类型的报文。
数值 | 类型 | 描述 |
0x00 | 请求 | 期望得到响应的请求(甚至无效) |
0x01 | 无返回请求 | 无返回的请求报文 |
0x02 | 通知 | 期望没有响应的通知/事件回调的请求报文 |
0x80 | 响应 | 响应报文 |
0x81 | 错误 | 包含一个错误的响应报文 |
0x20 | TP请求 | 期望得到响应的TP请求(甚至无效) |
0x21 | TP无返回请求 | 无返回的TP请求报文 |
0x22 | TP通知 | 期望没有响应的通知/事件回调的TP请求报文 |
0x23 | TP响应 | TP响应报文 |
0x24 | TP错误 | 包含一个错误的TP响应报文 |
备注:Message 字段的高位第3bit为 TP标志, TP类型,为1。
Return Code,8bit,返回代码用于指示一个请求是否已被成功处理。
数值 | 类型 | 描述 |
0x00 | E_OK | 没有发生错误 |
0x01 | E_NOT_OK | 发生了未指定的错误 |
0x02 | E_UNKOWN_SERVICE | 所请求的服务ID未知 |
0x03 | E_UNKOWN_METHOD | 所请求的方法ID未知 (服务ID已知) |
0x04 | E_NOT_READY | 应用程序未运行(已知的服务ID和方法ID) |
0x05 | E_NOT_REACHABLE | 无法访问运行该服务的系统 (仅限内部错误代码) |
0x06 | E_TIMEOUT | 发生了超时 (仅限内部错误代码) |
0x07 | E_WRONG_PROTOCOL_VERSION | 不支持SOME/IP协议的版本 |
0x08 | E_WRONG_INTERFACE_VERSION | 接口版本不匹配 |
0x09 | E_MALFORMED_MESSAGE | 反序列化错误,导致有效负载不能被反序列化。 |
0x0a | E_WRONG_MESSAGE_TYPE | 收到了一个意外的报文类型(例如,一个定义为请求的方法的REQUEST_NO_RETURN) |
0x0b-0x1f | 保留 | 保留给一般的SOME/IP错误。这些错误将在本文档的未来版本中指定。 |
0x20-0x5e | 保留 | 保留给服务和方法的特定错误。这些错误是由接口规范指定的。 |
Payload
使用UDP,SOME/IP有效负载应在0到1400字节之间。需要限制到1400字节,以便允许将来更改协议栈
SOME/IP-SD报文格式
SOME/IP-SD(Service Discovery)的作用:
- 找到服务实例。
- 检测服务实例是否正在运行
- 实现发布/订阅处理。
SOME/IP-SD报文通过UDP发送。
服务的信息清单及管理机制,也是一种服务。主要实现服务寻址及事件订阅两种功能。
• 服务提供者(Provider)通过SD通知其他ECU某服务可用,并间接地通知该服务的地址。
• 服务消费者(Consumer)了解某服务状态后,能够调用该服务。
•实现车内服务通信的动态管理。
1.SOME/IP首部
Message ID
Service ID,16bit,服务ID为0x FFFF(16位)。
Method ID,16bit,方法ID为0x8100(16位)。
Length
Request ID
Client ID,16bit,设置为0x0000,因为只存在一个SOME/IP-SD实例。
Session ID,16bit,会话ID应以1开始,每次发送的SOME/IP-SD报文都应增加会话ID。
Protocol Version,8bit,协议版本为0x01。
Interface Version,8bit,接口版本为0x01。
Message Type,8bit,消息类型为0x02(通知)。
Return Code,8bit,返回代码为0x00(E_OK)。
2.SOME/IP-SD首部
Flags:SOME/IP-SD首部以1字节的Flags开头。
Reboot Flag,重启标志,在重启后的所有消息设置为1,直到SOME/IP头中的会话ID结束,因此再次以1开始,重启标志被设置为0。
Unicast Flag,单播标志,对于所有SD消息,SOME/IP-SD报头的单播标志应设置为单播(即1),因为这意味着支持使用单播进行接收。
Explicit Initial Data Control Flag,显示初始化数据标志,显式初始数据控制标志应始终设置为1,这意味着ECU支持此功能。
保留,24bit。
未定义的标志位,5bit,置为0。
Entries Array
Length of Entries Array,32bit,一个Entry的长度为16字节(即32bit),Entry组的长度为16字节*Entry个数。
Entries Array,条目组,存在两种类型的条目:服务的服务输入类型和事件组的事件组输入类型。
1.服务类型
类型字段,8bit,说明该Entry属于哪种类型。
0x00为FindService。
0x01为OfferService或者StopOfferService(TTL=0)。
Index 1st options,8bit,索引到Options中的所使用的第一个Option。
Index 2nd options,8bit,索引到Options中的所使用的第二个Option。
# of opt 1,4bit,第一个option的数量。
# of opt 2,4bit,第二个option的数量。
Service ID,16bit,描述该Entry涉及的服务的Service ID
Instance ID,16bit,描述服务实例的Instance ID。
Find报文中Instance ID为0xffffffff时,需返回所有服务实例;
Find报文中Instance ID为特定值时,需返回特定服务实例。
Major Version,8bit,主要版本,对该服务的主要版本进行编码。
TTL,24bit,以秒为单位描述该条目的生命周期。
Minor Version,8bit,次要版本,对该服务的次要版本进行编码。
2.事件组类型
类型字段:8bit,说明该Entry属于哪种类型,
0x06为SubscribleEventgroup或者StopSubscribleEventgroup(TTL=0)。
0x07为SubscribleEventgroupAck或者SubscribleEventgroupNAck(TTL=0)。
Index 1st options,8bit,索引到Options中的所使用的第一个Option。
Index 2nd options,8bit,索引到Options中的所使用的第二个Option。
# of opt 1,4bit,第一个option的数量。
# of opt 2,4bit,第二个option的数量。
Service ID,16bit,描述该Entry涉及的服务的Service ID
Instance ID,16bit,描述服务实例的Instance ID。如果涉及服务的所有服务实例,则此条目将设置为0x FFFF。
Major Version,8bit,主要版本,对该服务的主要版本进行编码。
TTL,24bit,以秒为单位描述该条目的生命周期。
Reserved:8bit,应设置为0x00。
Initial Data Requested Flag :1bit,如果服务器需要发送初始数据,则应设置为1。
Reserved2:3bit,如果没有另行指定,则应设置为0x0。
计数器:4bit,用于区分同一订阅者的相同订阅事件组。如果不使用,则设置为0x0。
事件组ID:16bit,传输一个事件组的ID。
Options Array
Length of Options Array,32bit,一个Option的长度为12字节(即32bit),Option组的长度为12字节*Option个数。
Options Array,每个选项都有一个16bit的Length长度字段和一个8bit的Type类型字段,长度字段的值为除去选项的长度和类型字段剩下的选项的字节。
1.Configuration Option
2.Load Balancing Option
3.IPv4 Endpoint Option
IPv4端点选项由SOME/IP-SD实例用来向相关的端点发出信号。端点包括本地IP地址、传输层协议(例如,UDP或TCP)和发送方的端口号。这些端口也用于事件和通知事件。
L4-Proto:8bit,0x06为TCP,0x11为UDP。
服务器应使用带有Offer Service提供服务条目的IPv4端点选项,向其提供服务的端点发出信号。
客户端应使用具有Subscribe EventGroup订阅事件组条目的IPv4端点选项来通知IP地址和UDP和/或TCP端口号,并准备在这些号码上接收事件。
4.IPv4 Multicast Option
服务器使用IPv4多播选项来宣布IPv4组播地址、传输层协议(ISO/OSI层4)以及发送到的组播事件和组播通知事件的端口号。由于传输层协议,目前只支持UDP。Subscribe Eventgroup Ack引用 IPv4组播选项
测试
- ETS(Enhanced Testability Service)
方法列表
方法 | ID | 单向 |
检查字节顺序 | 31(0x1F) | |
客户端服务激活 | 47(0x2F) | √ |
客户端服务失效 | 48(0x30) | √ |
客户端服务订阅事件组 | 50(0x32) | √ |
常见数据类型 | 35(0x23) | |
枚举 | 23(0x17) | |
浮点型64 | 18(0x12) | |
整型64 | 52(0x34) | |
整型8 | 14(0x0E) | |
静态无符号8数组 | 54(0x36) | |
无符号8 | 8(0x08) | |
无符号8数组 | 9(0x09) | |
无符号8数组8比特长度 | 62(0x3E) | |
无符号8数组8比特长度 | 63(0x3F) | |
53(0x35) | ||
55(0x37) | ||
11(0x0B) | ||
10(0x0A) | ||
25(0x19) | ||
22(0x16) | ||
20(0x14) | ||
21(0x15) | ||
19(0x13) | ||
1(0x01) | √ | |
2(0x02) | √ | |
3(0x03) | √ | |
4(0x04) | √ | |
5(0x05) | √ | |
6(0x06) | √ | |
58(0x3A) | √ | |
客户端服务通过TCP获取事件的最后一个值 | 59(0x3B) | |
客户端通过单播UDP获取事件的最后一个值 | 60(0x3C) | |
客户端通过多播UDP获取事件的最后一个值 | 61(0x3D) |
事件和字段列表
- SOME/IP-SD(Service Discovery)
复位接口
方法 | ID |
resetInterface(复位接口) | 1(0x01) |
此方法会将接口重置为默认值。
- 挂起接口
方法 | ID |
suspendInterface(挂起接口) | 2(0x02) |
此方法允许暂停增强的可测试性服务;因此,强制DUT停止提供该服务,并在给定的时间后开始重新提供该服务。
输入参数包括:
Start:停止服务前几秒钟的等待时间
Duration:在停止服务和重新提供服务之间的等待时间,以秒为单位。
- 测试客户端交互
为了测试作为客户端的正确功能,增强的可测试性服务支持以下方法:
方法 | ID |
clientServiceActivate (客户端服务激活) | 47 (0x2F) |
clientServiceDeactivate (客户端服务取消激活) | 48 (0x30) |
clientServiceSubscribeEventgroup (客户端服务订阅事件组) | 50 (0x32) |
clientServiceGetLastValueOfEventTCP (客户端服务TCP获取事件的最后一个值) | 59 (0x3B) |
clientServiceGetLastValueOfEventUDPUnicast (客户端服务单播UDP获取事件的最后一个值) | 60 (0x3C) |
clientServiceGetLastValueOfEventUDPMulticast (客户端服务组播UDP获取事件的最后一个值) | 61 (0x3D) |
命令客户端服务激活和客户端服务停用应指示DUT是否启动其SOME/IP客户端,从而控制系统何时开始查找具有特殊可配置实例ID(例如0x00f4)的增强可测试性服务。
客户端服务订阅事件组应在服务发现中触发订阅行为。
clientServiceGetLastValueOfEventTCP方法返回TestEventUINT8Reliable的最后接收值。
clientServiceGetLastValueOfEventUDPUnicast方法返回TestEventUINT8的最后接收值。
clientServiceGetLastValueOfEventUDPMulticast方法返回TestEventUINT8Multicast的最后接收值。
序列化
- 检查字节顺序
方法 | ID |
checkByteOrder(检查字节顺序) | 31 (0x1F) |
此方法用于测试字节顺序的正确处理。输入参数包括一个uint8和一个大环境uint16,应在uint32大环境中作为输出参数相加返回。
- 常见数据类型回显
方法 | ID |
echoCommonDatatypes(常见数据类型回显) | 35 (0x23) |
该方法可用于测试公共数据类型。输入参数应按反向顺序响应。
- 同步数据类型
方法 | ID |
echoCommonDatatypes | 35 (0x23) |
echoENUM | 23 (0x17) |
echoFLOAT64 | 18 (0x12) |
echoINT8 | 14 (0x0E) |
echoStaticUINT8Array | 54 (0x36) |
echoUINT8 | 8 (0x08) |
echoUINT8Array | 9 (0x09) |
echoUINT8Array8BitLength | 62 (0x3E) |
echoUINT8Array16BitLength | 63 (0x3F) |
echoUINT8Array2Dim | 53 (0x35) |
echoUINT8ArrayMinSize | 55 (0x37) |
echoUINT8E2E | 11 (0x0B) |
echoUINT8RELIABLE | 10 (0x0A) |
echoUNION | 25 (0x19) |
echoUTF16DYNAMIC | 22 (0x16) |
echoUTF16FIXED | 20 (0x14) |
echoUTF8DYNAMIC | 21 (0x15) |
echoUTF8FIXED | 19 (0x13) |
echoBitfields | 65 (0x41) |
- 测试事件
方法 | ID |
triggerEventUINT8 | 3 (0x03) |
triggerEventUINT8Array | 4 (0x04) |
triggerEventUINT8E2E | 6 (0x06) |
triggerEventUINT8Reliable | 5 (0x05) |
triggerEventUINT8Multicast | 58 (0x3A) |
在调用方法triggerEventUINT8Reliable (start, duration, debounceTime)后,服务可测试性等待<Start>秒,并触发一个经过的持续时间和删除时间的周期性事件testEventUINT8Reliable(uINT8Value)。事件消息的传输协议为TCP。
- 测试域(getter, setter, notify)
不同的测试字段可用于测试相应的设置方法,通过不可靠UDP和可靠TCP
Getter
Setter
Notifier