Use SocketCAN as data link type of CAN frame

In our project, we use tcpdump to capture frames on CAN bus. In the core library used by tcpdump, libpcap used SocketCAN as the data link type previously.

In commit 93ca5ff, SocketCAN was removed. Instead, it handled all CAN captures in general cooked mode on Linux, which will have an additional 16-byte SLL header. This will increase (actually double) the size of captured frames saved in file, which is critical for embedded environment. As shown in following screenshot, CAN frame captured in Linux cooked mode is 32 bytes (on the left), while CAN frame in SocketCAN format is 16 bytes (both frames are legacy CAN frames, not CAN FD).

Left: SLL; Right: SocketCAN

Left: SLL; Right: SocketCAN

That extra 16-byte SLL header is quite useless, so we decided to restore to the original format, so that we could capture more frames in the same storage space.

However, simply modifying data link type from LINKTYPE_LINUX_SLL back to LINKTYPE_CAN_SOCKETCAN doesn’t work, because the byte orders of CAN ID in these two formats are different.

Refer to the screenshot above, the raw CAN ID in SLL format is 03 ff ee 98, and it’s interpreted as 0x18eeff03 (most significant bit as “Extended Flag”), meaning “the field containing the CAN ID and flags is in host byte order” (little-endian in this case). Similarly, the raw CAN ID in SocketCAN frame 9c ff 21 0d is interpreted as 0x1cff210d with Extended Flag being True, which means “the field containing the CAN ID and flags is in network byte order (big-endian).”

So we need to deal with the difference of byte order of CAN ID as well.

I pushed the required changes in my forked libpcap repository in commit 4e709dc. If you find any issues with that commit, please comment below. Thanks.

comments powered by Disqus