On 2024-02-12 18:54, Guy Harris wrote:
On Feb 12, 2024, at 4:04 AM, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
I assume only ARM(64), X64 and Risc-V architectures will get in contact with CAN XL. And all these archs are little-endian.
And the version of your Lua dissector at
https://github.com/hartkopp/canxl-utils/blob/main/wireshark/can_xl.lua
dissects multi-byte fields as little-endian.
Yes, that was a PoC based on the CAN XL Lua code I got from a colleague.
And I simply wanted to have some valid output on my X86_64 Laptop.
I'm not a Lua expert with introducing BE/LE data structures in the first
4 byte and therefore I did the 16 bit shifting and masking to get the
VCID from the then 32 bit prio.
Thus, I specified that all multi-byte fields in the CAN XL header, in LINKTYPE_CAN_SOCKETCAN packets, are little-endian (unlike the header for CAN classic and CAN FD, in which the CAN ID/flags field is big-endian):
https://www.tcpdump.org/linktypes/LINKTYPE_CAN_SOCKETCAN.html
So the question is whether the first 4 bytes of the CAN XL header are:
a single little-endian field in the form
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 6 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---------------+---------------+---------+---------------------+
| Reserved | VCID |Reserved | Priority |
+---------------+---------------+---------+---------------------+
Yes! This is the correct plan.
But in fact this is a 32 bit value. Analogue to the can_id field in CAN
CC and CAN FD:
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 6 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---------------------------------------------------------------+
|x|y|z| CAN Identifier |
+---------------------------------------------------------------+
Currently the first 4 bytes in the Wireshark data window (in the bottom
right) for CAN CC & CAN look like this for CAN ID 0123:
00 00 01 23 (which looks like big endian)
And CAN XL with VCID 0xCD and Prio 0x242 looks like this
00 CD 02 42 (which also looks like big endian, right?)
When the AF field is set to 0x11223344 then this 32 bit value is
represented in little endian:
0000 00 cd 02 42 81 00 0a 00 44 33 22 11 00 00 00 00
0010 00 00 00 00 00 00
(all values from latest Wireshark v4.3.0rc0-1521-g0e5416efbe94)
I still use the libpcap 1.10.4 from Debian Trixie.
So if you generally convert the first 4 bytes to big endian why should
there be an exception for CAN XL?
or, equivalently, two little-endian fields in the form
1 1 1 1 1 1
5 4 3 2 1 0 9 8 6 6 5 4 3 2 1 0
+---------+---------------------+
|Reserved | Priority |
+---------+---------------------+
1 1 1 1 1 1
5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---------------+---------------+
| Reserved | VCID |
+---------------+---------------+
with the first of those two being in bytes 0 and 1 and the second of those in bytes 2 and 3, in which case a VCID value of 0x12 and a priority value of 0x345 would be, as a sequence of octets, 0x45 0x03 0x12 0x00
These octets would have been the correct little endian representation.
or
a single little-median field in the form
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---------+---------------------+---------------+---------------+
|Reserved | Priority | Reserved | VCID |
+---------+---------------------+---------------+---------------+
or, equivalently, two little-endian fields in the form
1 1 1 1 1 1
5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---------------+---------------+
| Reserved | VCID |
+---------------+---------------+
1 1 1 1 1 1
5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---------+---------------------+
|Reserved | Priority |
+---------+---------------------+
with the first of those two being in bytes 0 and 1 and the second of those in bytes 2 and 3, in which case a VCID value of 0x12 and a priority value of 0x345 would be, as a sequence of octets, 0x12 0x00 0x45 0x03
Ugh. No.
(these being little-endian, the low-order, thus lower-numbered, bits are in the low-order, thus lower-address, bytes).
The currently discussed struct canxl_frame is here:
https://lore.kernel.org/linux-can/20240128183758.68401-1-socketcan@xxxxxxxxxxxx/
struct canxl_frame {
#if defined(__LITTLE_ENDIAN)
__u16 prio; /* 11 bit priority for arbitration */
__u8 vcid; /* virtual CAN network identifier */
__u8 __res0; /* reserved / padding must be set to zero */
#elif defined(__BIG_ENDIAN)
__u8 __res0; /* reserved / padding must be set to zero */
__u8 vcid; /* virtual CAN network identifier */
__u16 prio; /* 11 bit priority for arbitration */
#else
#error "Unknown endianness"
#endif
That appears to be the first of those two examples.
Yes, because it is the way to specify separate data elements with
correct endianess when you want to place the VCID "above" the 11 bit
Prio value.
Do you have an opinion whether this __ENDIAN hell above is the "better"
option or to shift the 8 bit VCID "above" the Prio ?
Best regards,
Oliver