前言
SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块:
1. SOME/IP协议讲解
2. SOME/IP-SD协议讲解
3. python/C++举例调试讲解
4.2.1.4 Transporting large SOME/IP messages of UDP (SOME/IP-TP)
The UDP binding of SOME/IP can only transport SOME/IP messages that fit directly
into an IP packet. If larger SOME/IP messages need to be transported over UDP
(e.g. of 32 KB) the SOME/IP Transport Protocol (SOME/IP-TP) shall be used. The
SOME/IP message too big to be transported directly with the UDP binding shall be
called "original" SOME/IP message. The "pieces" of the original SOME/IP message
payload transported in SOME/IP-TP messages shall be called "segments".
Use TCP only if very large chunks of data need to be transported (> 1400 Bytes) and
no hard latency requirements in the case of errors exists
如何使用 **SOME/IP 传输协议(SOME/IP-TP)** 通过 UDP 传输较大的 SOME/IP 消息。
1. **UDP 绑定的限制**:
- SOME/IP 的标准 UDP 绑定只能传输适合单个 IP 数据包的消息。这通常受限于网络的 **最大传输单元(MTU)**,默认情况下约为 1500 字节(包括 IP 和 UDP 头部)。
2. **SOME/IP-TP 的作用**:
- 如果需要通过 UDP 传输更大的 SOME/IP 消息(例如 32 KB),则需要使用 **SOME/IP-TP**。
- SOME/IP-TP 将原始 SOME/IP 消息(称为“原始消息”)分割成多个较小的片段(称为“段”),然后通过多个 UDP 数据包传输。
3. **原始消息与段**:
- **原始消息**:无法直接通过 UDP 绑定的 SOME/IP 消息。
- **段**:原始消息的有效载荷被分割后,通过 SOME/IP-TP 消息传输的片段。
4. **TCP 的使用场景**:
- 如果需要传输非常大的数据块(超过 1400 字节),并且对错误情况下的延迟没有严格要求,则建议使用 TCP 而不是 UDP。
5. **UDP 直接传输会怎么样**:
如果是大包的SOME/IP数据 通过UDP直接传输 而不在SOME/IP层分包的话,数据则会直接转到IP层,IP层有MTU的限制 会进行分包发送,到接收端后IP层会重新组包。如果其中一个分包有问题,则整包直接丢弃,没有重传。
所以UDP传输大的SOME/IP报文 需要在SOME/IP层进行 分包。
总结来说,SOME/IP-TP 是为了解决 UDP 传输大消息的限制而设计的,通过分段传输实现。而 TCP 更适合传输非常大的数据块,尤其是在对延迟要求不严格的情况下。
[PRS_SOMEIP_00720]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00012
SOME/IP messages using SOME/IP-TP shall activate Session Handling (Session ID
must be unique for the original message).
SOME/IP-TP应该激活会话处理功能,即SessionID对于所有被分包的SOME/IP报文而言要连续唯一且大于0。分包之后的子包中的SessionID要和原始包一致
[PRS_SOMEIP_00721]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00012
All SOME/IP-TP segments shall carry the Session ID of the original message; thus,
they have all the same Session-ID.
所有切片包中的sessionID必须和 原始包一样
[PRS_SOMEIP_00722]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00011
SOME/IP-TP segments shall have the TP-Flag of the Message Type set to 1.
SOME/IP-TP子包中MessageType的 TP-Flag要设置为1
在SOME/IP header之后 payload之前 有TP-header 格式如下:
[PRS_SOMEIP_00931]
Upstream requirements: RS_SOMEIP_00027
SOME/IP-TP Header shall be encoded in network byte order (big endian). 大端字节序 和SOME/IP保持同步。
[PRS_SOMEIP_00724]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00027
The Offset field shall transport the upper 28 bits of a uint32. The lower 4 bits shall be
always interpreted as 0.
Note:
This means that the offset field can only transport offset values that are multiples of 16
bytes.
10000 --> 偏移量不是第几包,而是第多少个16字节。16的整数倍。
[PRS_SOMEIP_00725]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00027
The Offset field of the TP header shall be set to the offset in bytes of the transported
segment in the original message
offset 应该被设置
[PRS_SOMEIP_00726]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00027
The Reserved Flags shall be set to 0 by the sender and shall be ignored (and not
checked) by the receiver
接收端不应该检查 3个保留位,虽然有可能没有设置为0.
[PRS_SOMEIP_00727]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00027
The More Segments Flag shall be set to 1 for all segments but the last segment. For
the last segment it shall be set to 0
more flag :
所有子包除了最后一包全都要设置为1,最后一包为0
[PRS_SOMEIP_00728]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00027
The SOME/IP length field shall be used as specified before. This means it covers the
first 8 bytes of the SOME/IP header and all bytes after that
legth字段 包含了TP头和payload的长度
Note:
This means that for a SOME/IP-TP message transporting a segment, the SOME/IP
length covers 8 bytes(是length和TP头之间的 8个字节) of the SOME/IP header, the 4 bytes of the TP header, and the
segment itself.这里的段 表示 payload
[PRS_SOMEIP_00729]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The length of a segment must reflect the alignment of the next segment based on the
offset field. Therefore, all but the last segment shall have a length that is a multiple of
16 bytes
除了最后一个段,前面的段的长度都应该是16字节的整数倍。
[PRS_SOMEIP_00730] Maximum segement length
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00029, RS_SOMEIP_00051
In accordance with the recommended payload size (see [PRS_SOMEIP_00382] -- SOME/IP UDP最大1400字节, 再多的话要用TCP传输), the
maximum length of a segment that is correctly aligned should be 1392(87 * 16) bytes.
这里的最大值指的是payload传输的最大值,SOME/IP包中length字段还要 +8 +4
[PRS_SOMEIP_00731]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
SOME/IP-TP messages shall use the same Message ID (i.e. Service ID and Method
ID), Request ID (i.e. Client ID and Session ID), Protocol Version, Interface Version,
and Return Code as the original message.
这些统一和原始包保持一致
Note:
As described above the Length, Message Type, and Payload are adapted by SOME/IP-TP.
这三个 由 TP包动态设置
Example -- 大包分包的例子
This example describes how an original SOME/IP message of 5880 bytes payload has to be transmitted. The Length field of this original SOME/IP message is set to 8 + 5880 bytes.
This original SOME/IP message will now be segmented into 5 consecutive SOME/IP
segments. Every payload of these segments carries at most 1392 bytes in this example.
For these segments, the SOME/IP TP module adds additional TP fields (marked red).
The Length field of the SOME/IP carries the overall length of the SOME/IP segment
including 8 bytes for the Request ID, Protocol Version, Interface Version, Message Type
and Return Code. Because of the added TP fields (4 bytes), this Length information is
extended by 4 additional SOME/IP TP bytes.
The following figure provides an overview of the relevant SOME/IP header settings for
every SOME/IP segment:
Sender specific behavior -- 发送的规范行为
[PRS_SOMEIP_00732]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The sender shall segment only messages that were configured to be segmented. 这里指的被配置为分段的消息意思是:按照需求大于1400字节payload的UDP包才需要分包,否则不能分包浪费资源。
[PRS_SOMEIP_00733]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The sender shall send segments in ascending order. 按升序发送
[PRS_SOMEIP_00734]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The sender shall segment in a way that all segments with the More Segment Flag set
to 1 are of the same size. 除了最后一包其他的分包发送的字节数应该一样。
[PRS_SOMEIP_00735]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The sender shall try to maximize the size of segments within limitations imposed by
this specification. 除了最后一个子包 前面的包 应该按最大的字节数发送,不能浪费资源。
[PRS_SOMEIP_00736]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The sender shall not send overlapping or duplicated segments.不能发送重复的段 浪费资源
Receiver specific behavior
[PRS_SOMEIP_00738]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver shall match segments for reassembly based on the configured values of
Message-ID, Protocol-Version, Interface-Version and Message-Type (w/o TP Flag).
组装的时候 依赖这几个字段匹配组装
[PRS_SOMEIP_00740]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
It shall be supported to reassemble multiple messages with the same Message ID but
sent from different clients (difference in Sender IP, Sender Port, or Client ID) in parallel.
This should be controlled by configuration and determines the amount of "reassembly
buffers".
server可以支持同一个消息id来自不同client的分段消息的组装--即并发处理多个分段消息。-- 这个受缓冲区的大小控制
[PRS_SOMEIP_00741]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The Session ID shall be used to detect the next original message to be reassembled.
组装时需要不通的 sessionID 说明来自不同的原始包 的子包
[PRS_SOMEIP_00742]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver shall start a new reassembly (and may throw away old segments that
were not successfully reassembled), if a new segment with a different Session-ID is
received.
对于同一个client同一个messageID的同一个的requestID ,收到了新的sessionID 则丢弃之前未组装好的包
[PRS_SOMEIP_00743]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver should only reassemble up to its configured buffer size and skip the rest
of the message.
对于同一个client同一个messageID的同一个的requestID ,收到了新的sessionID 则应该组装新的原始包。如果上一原始包还没组装完成 可以丢弃 或延时丢弃 -- 需要自己决定怎么实现。
[PRS_SOMEIP_00744]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
dOnly correctly reassembled message of up to the configured size shall be passed to
an application.
所有的包组装完成后 才能给应用程序
Note:
This means that the implementation must make sure that all bytes of the message must
be bytes that were received and reassembled correctly. Counting non-overlapping,
non-duplicated bytes and comparing this to the length could be a valid check.
核心要求
消息完整性:
在重组 SOME/IP 消息时,必须确保所有字节都是正确接收的,且没有丢失、重复或重叠的字节。
字节计数检查:
可以通过统计 非重叠、非重复的字节数,并将其与消息的预期长度进行比较,来验证消息是否完整和正确。
[PRS_SOMEIP_00379] .
Upstream requirements: RS_SOMEIP_00010
The receiver shall cancel the current assembly process, when no segement
has been received during a configured SOMEIPTP_REASSEMBLY_TIMEOUT (see
[PRS_SOMEIP_00378]) period.
超时 则取消拼包 SOMEIPTP_REASSEMBLY_TIMEOUT 需要客户指定配置
[PRS_SOMEIP_00745]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The Return Code of the last segment used for reassembly shall be used for the reassembled message.
returnCode以最后拼装的一包为准
[PRS_SOMEIP_00746]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
During reassembling the SOME/IP TP segments into a large unsegmented message,
the Message Type shall be adapted, the TP Flag shall be reset to 0.
组包完成后TP flag应该设置为0,---我认为没用,应为组装完成后的包只需要把payload传给 上层应用就行
[PRS_SOMEIP_00747]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver shall support reassembly of segments that are received in ascending
and descending order.
server段可支持按照升序或降序的方式从缓冲区取包进行组装
[PRS_SOMEIP_00749]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
When a missing segment is detected during assembly of a SOME/IP message, the
current assembly process shall be canceled.
发现有缺失的包应停止组装
Note:
This means that reordering is not supported.
类似于IP层:不支持乱序重排,丢帧补发。
[PRS_SOMEIP_00750]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
Interleaving of different segmented messages using the same buffer (e.g. only the
Session-ID and payload are different) is not supported.
编程指导:不建议把不同的sessionID放在同一块缓冲区
Note:
This prohibits that equal events (same Message-ID, IP-Addresses, ports numbers, and
transport protocol) arrive in the wrong order, when some of their segments get reordered.
[PRS_SOMEIP_00751]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
Reordering of segments of completely different original messages (e.g. Message ID
is different) is not of concern since those segments go to different buffers.
这两段内容([PRS_SOMEIP_00750] 和 [PRS_SOMEIP_00751])涉及 **SOME/IP 分段消息** 的处理规则,特别是关于 **消息交错(Interleaving)** 和 **分段重排序(Reordering)** 的限制。以下是详细解释:
---
### **[PRS_SOMEIP_00750]**
#### 内容:
不支持使用同一缓冲区对不同分段消息进行交错(例如,仅 Session-ID 和有效载荷不同)。
#### 关键点:
1. **消息交错**:
- 消息交错是指在同一缓冲区中混合处理来自不同原始消息的分段。
- 例如,如果两个不同的消息(具有相同的 Message-ID、IP 地址、端口号和传输协议)的分段被交错接收,可能(除非也判断instanceID)会导致重组错误。
2. **限制原因**:
- 这种限制是为了防止具有相同事件标识(Message-ID、IP 地址、端口号和传输协议)的分段消息因重排序而到达错误顺序。
- 如果分段消息被交错处理,可能会导致重组后的消息顺序错误,从而影响系统行为。
3. **实现要求**:
- 实现必须确保同一缓冲区不用于处理来自不同原始消息的分段,即使它们的 Session-ID 和有效载荷不同。
#### 注释:
- 该规则禁止了相同事件的分段消息因重排序而到达错误顺序的情况。
- 例如,如果两个分段消息的分段被重新排序,可能会导致重组后的消息顺序错误。
---
### **[PRS_SOMEIP_00751]**
#### 内容:
完全不同的原始消息(例如 Message ID 不同)的分段重排序不会引起问题,因为这些分段会进入不同的缓冲区。
#### 关键点:
1. **不同消息的分段**:
- 如果分段属于完全不同的原始消息(例如 Message ID 不同),则它们的重排序不会影响重组。
- 因为这些分段会被分配到不同的缓冲区,彼此之间不会产生冲突。
2. **缓冲区隔离**:
- 每个原始消息的分段会被独立处理,使用单独的缓冲区。
- 因此,即使分段在传输过程中被重新排序,也不会影响其他消息的重组。
3. **实现要求**:
- 实现需要为每个原始消息维护独立的缓冲区,确保不同消息的分段不会混合处理。
---
### 总结
1. **消息交错限制**:
- 不允许在同一缓冲区中交错处理来自不同原始消息的分段,特别是当它们具有相同的 Message-ID、IP 地址、端口号和传输协议时。
- 这是为了防止因分段重排序而导致的消息顺序错误。
2. **不同消息的分段处理**:
- 完全不同的原始消息(Message ID 不同)的分段可以独立处理,因为它们会被分配到不同的缓冲区。
- 这些分段的重排序不会影响重组结果。
3. **实现建议**:
- 实现应为每个原始消息维护独立的缓冲区,确保分段消息的正确重组。
- 需要特别注意具有相同标识(Message-ID、IP 地址、端口号和传输协议)的分段消息,避免交错处理。
---
### 示例场景
#### 场景 1:相同 Message-ID 的分段消息
- 消息 A 和消息 B 具有相同的 Message-ID、IP 地址、端口号和传输协议。
- 如果消息 A 的分段 1 和消息 B 的分段 1 被交错接收,可能会导致重组错误。
- 根据 [PRS_SOMEIP_00750],实现必须禁止这种情况。
#### 场景 2:不同 Message-ID 的分段消息
- 消息 X 和消息 Y 具有不同的 Message-ID。
- 即使消息 X 的分段 1 和消息 Y 的分段 1 被重新排序,也不会影响重组,因为它们会被分配到不同的缓冲区。
- 根据 [PRS_SOMEIP_00751],这种情况是允许的。
[PRS_SOMEIP_00752]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver shall correctly reassemble overlapping and duplicated segments by over-writing based on the last received segment.
接收到最后的端后,可以把重复的段覆盖的方式重新组装。
[PRS_SOMEIP_00753]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver may cancel reassembly, if overlapping or duplicated segments change
already written bytes in the buffer, if this feature can be turned off by configuration.
server段收到重复段 可以停止组包。也可以继续组包 --- 这个可以通过配置打开或关闭(客户给需求时可以指定这个)
[PRS_SOMEIP_00754]
Upstream requirements: RS_SOMEIP_00010, RS_SOMEIP_00051
The receiver shall be able to detect and handle obvious errors gracefully. E.g. cancel
reassembly if segment length of a segment with MS=1 is not a multiple of 16.
Note:
This means that buffer overflows or other malfunction shall be prevented by the receiving code.
接收端应该能够检查并处理明显的错误,比如MoreFlag=1 但payload字节数不是16的倍数等。