SOME/IP
Serialization: how data is laid out
Serialization writes the data of the SWC into the payload byte by byte, in the order of the data type, with no gaps added on its own. A length field in front of variable-length data (it says how many bytes follow) lets a receiver find its way.
Basic data types
| Type | Bytes | Note |
|---|---|---|
| boolean | 1 | FALSE 0, TRUE 1; a receiver looks only at the lowest bit |
| uint8 / sint8 | 1 | signed types in two's complement |
| uint16 / sint16 | 2 | |
| uint32 / sint32, float32 | 4 | floats as IEEE 754 binary32 |
| uint64 / sint64, float64 | 8 | floats as IEEE 754 binary64 |
| enumeration, bitfield | 1, 2 or 4 | sent as the unsigned integer underneath |
The byte order of the payload is set by configuration. In the Classic Platform one setting, byteOrder (the configured byte order of the payload) of the SOMEIPTransformationDescription, applies to all parameters: mostSignificantByteFirst (big-endian), mostSignificantByteLast (little-endian: the least significant byte goes first) or opaque. Length fields and the type fields of unions, like the SOME/IP header, are always big-endian.
Structures, strings, arrays
struct
Members in order
Written member after member, depth-first through nested structs. An optional length field of 1, 2 or 4 bytes may come first (sizeOfStructLengthFields); in the Classic Platform it is switched on per signal, and then every struct and nested struct gets one.
string
BOM and terminator
Strings start with a BOM (byte order mark: bytes that name the encoding; UTF-8 EF BB BF, UTF-16BE FE FF, UTF-16LE FF FE) and end with a zero (two zero bytes for UTF-16). Fixed-length strings are filled up with zeros; dynamic ones get a length field, 4 bytes unless configured to 1 or 2 (sizeOfStringLengthFields).
array
Length in bytes
A fixed array carries exactly n elements, optionally behind a length field. A dynamic array has a length field (1, 2 or 4 bytes, default 4, sizeOfArrayLengthFields) giving its size in bytes. In multidimensional arrays every inner array has its own length field.
union
Length, type, data
By default a 4-byte length field (sizeOfUnionLengthFields), a 4-byte type field (which member of the union follows), then the data, optionally followed by padding (filler bytes, for example so that every member takes the same 4 bytes and the following data stays aligned). The length field counts data and padding only; the receiver skips whatever follows the data of the selected member. Type 0 means "empty".
The Classic Platform option implementsLegacyStringSerialization (legacy string serialization: strings without BOM and terminator) sends strings as plain bytes; the specification itself warns that it will be removed and recommends byte arrays instead.
Alignment
Alignment (starting an element at a byte position that is a multiple of a set size) is not automatic for fixed-length data: SOME/IP never adds padding after it; if a member must be aligned, the data type itself needs a padding element. After variable-length data that is not the last element, padding is added up to the configured alignment (8 to 256 bits), and the position is counted from the start of the SOME/IP message, SOME/IP header included. The value of padding bytes is not defined.
TLV for extensible data
A struct can also be sent with TLV serialization (tag, length, value: a 2-byte tag in front of every member). The tag holds 1 reserved bit, a 3-bit wire type (how the size of the member is coded) and a 12-bit Data ID (the number of the member). Wire types 0–3 mean a basic data type of 8, 16, 32 or 64 bits (no length field); 4 means a complex value with the configured length field; 5, 6, 7 a complex value with a 1-, 2- or 4-byte length field. A receiver skips members whose Data ID it does not know, so members can be added anywhere and optional members become possible.
Try it
A struct Object = { uint16 distance; sint8 angle; string name; uint8[] points }, sent as a NOTIFICATION. Change values and settings and click bytes to see what they are. Byte numbers count from the start of the SOME/IP message.
Things to notice. Switch the byte order: distance changes from 00 2A to 2A 00, but the length fields stay big-endian. The name "car" takes 3 + 3 + 1 = 7 bytes plus its length field. Turn on 32-bit alignment: padding appears after the name (variable, not last) but never after the points (last element) or after distance (fixed size).
Check yourself optional
New terms in this lesson
| Term | Meaning |
|---|---|
| length field | A field in front of a struct, string, array or union that says how many bytes follow; it never counts itself and is always big-endian |
| little-endian | Least significant byte first; a possible byte order of the payload, never of the SOME/IP header |
byteOrder | Configured byte order of the payload: mostSignificantByteFirst, mostSignificantByteLast or opaque |
| BOM | Byte order mark at the start of every SOME/IP string; it names the encoding (UTF-8 EF BB BF) |
implementsLegacyStringSerialization | Legacy option: strings without BOM and terminator |
| alignment | Start position rule for the data after variable-length data, counted from the start of the message (8 to 256 bits) |
| padding | Filler bytes with undefined value, added for alignment; in a union, the bytes after the data that the length field still covers |
| TLV | Tag, length, value: serialization with a tag in front of every member, so members can be added or left out |
| wire type | 3 bits of the TLV tag: how the size of the member is coded |
| Data ID | 12 bits of the TLV tag: the number of the member |
Source: SOME/IP Protocol Specification, R20-11, section 4.1.4; SOME/IP Transformer, R20-11, sections 7.2.2 and 7.2.4.