On Feb 6, 2024, at 10:42 AM, Oliver Hartkopp <socket...@hartkopp.net> wrote:
> I'm currently working on CAN XL support which is the latest CAN protocol > after Classical CAN and CAN FD. > > With Wireshark 3.6 I was able to add this dissector for CAN XL > https://github.com/hartkopp/canxl-utils/blob/main/wireshark/can_xl.lua > where Wireshark displayed Classical CAN, CAN FD and CAN XL correctly. > > As I could see from Guys commit 39604740898f ("socketcan: support the > CANFD_FDF flag for identifying CAN FD frames.") there has been a change from > LINKTYPE_LINUX_SLL (worked and had different ETH_P_* types) to > LINKTYPE_CAN_SOCKETCAN. Presumably meaning that, as per the commit comment for https://gitlab.com/wireshark/wireshark/-/commit/39604740898f "This will be needed when the current main-branch libpcap is released, as it uses LINKTYPE_CAN_SOCKETCAN rather than LINKTYPE_LINUX_SLL for ARPHRD_CAN devices". Yes, libpcap 1.10.2 includes the change in question: https://github.com/the-tcpdump-group/libpcap/commit/4357b2d0edbb6371906af2179cf3497e6e1db78a according to https://github.com/the-tcpdump-group/libpcap/blob/master/CHANGES#L247 (which is in the section that begins at https://github.com/the-tcpdump-group/libpcap/blob/master/CHANGES#L189 showing that it was introduced in 1.10.2). This means that *any* capture done with a program using 1.10.2 or later - tcpdump, Wireshark, etc. - on a Linux CANbus interface will use LINKTYPE_CAN_SOCKETCAN. It *also* means that a capture with those version of libpcap will have the CANFD_FDF flag set on all frames that have LINUX_SLL_P_CANFD as the protocol value provided by the PF_PACKET socket (that value is also what is copied into the LINKTYPE_LINUX_SLL header). This required that commit 39604740898f be made to Wireshark, to allow it to read those captures. was backported to the 1.10 branch - so capturing on > I assume with the LINKTYPE_CAN_SOCKETCAN the correct display of the different > CAN traffic types broke. As long as the frames in question are either CAN classic or CAN FD frames, and as long as the low-level capture code path (none of which is in Wireshark or tcpdump, it's in the Linux kernel and libpcap) sets the CANFD_FDF flag on CAN FD frames and doesn't set it on CAN classic frames, the display of those CAN traffic types works. Note, however, that there is no mention of CAN XL there. Wireshark includes absolutely *no* code to handle CAN XL. libpcap also includes no such code. This means that CAN XL frames will either look as if they're CAN classic or CAN FD frames; given the way libpcap works, they'll look as if they're CAN classic frames, as they don't have ETH_P_CANFD as the protocol type. The LINKTYPE_CAN_SOCKETCAN header looks like https://www.tcpdump.org/linktypes/LINKTYPE_CAN_SOCKETCAN.html The headers from Linux for various CAN frame types are, as taken from Linux's can.h header: /** * struct can_frame - Classical CAN frame structure (aka CAN 2.0B) * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition * @len: CAN frame payload length in byte (0 .. 8) * @can_dlc: deprecated name for CAN frame payload length in byte (0 .. 8) * @__pad: padding * @__res0: reserved / padding * @len8_dlc: optional DLC value (9 .. 15) at 8 byte payload length * len8_dlc contains values from 9 .. 15 when the payload length is * 8 bytes but the DLC value (see ISO 11898-1) is greater then 8. * CAN_CTRLMODE_CC_LEN8_DLC flag has to be enabled in CAN driver. * @data: CAN frame payload (up to 8 byte) */ struct can_frame { canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ union { /* CAN frame payload length in byte (0 .. CAN_MAX_DLEN) * was previously named can_dlc so we need to carry that * name for legacy support */ __u8 len; __u8 can_dlc; /* deprecated */ } __attribute__((packed)); /* disable padding added in some ABIs */ __u8 __pad; /* padding */ __u8 __res0; /* reserved / padding */ __u8 len8_dlc; /* optional DLC for 8 byte payload length (9 .. 15) */ __u8 data[CAN_MAX_DLEN] __attribute__((aligned(8))); }; /* * defined bits for canfd_frame.flags * * The use of struct canfd_frame implies the FD Frame (FDF) bit to * be set in the CAN frame bitstream on the wire. The FDF bit switch turns * the CAN controllers bitstream processor into the CAN FD mode which creates * two new options within the CAN FD frame specification: * * Bit Rate Switch - to indicate a second bitrate is/was used for the payload * Error State Indicator - represents the error state of the transmitting node * * As the CANFD_ESI bit is internally generated by the transmitting CAN * controller only the CANFD_BRS bit is relevant for real CAN controllers when * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make * sense for virtual CAN interfaces to test applications with echoed frames. * * The struct can_frame and struct canfd_frame intentionally share the same * layout to be able to write CAN frame content into a CAN FD frame structure. * When this is done the former differentiation via CAN_MTU / CANFD_MTU gets * lost. CANFD_FDF allows programmers to mark CAN FD frames in the case of * using struct canfd_frame for mixed CAN / CAN FD content (dual use). * Since the introduction of CAN XL the CANFD_FDF flag is set in all CAN FD * frame structures provided by the CAN subsystem of the Linux kernel. */ #define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ #define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */ /** * struct canfd_frame - CAN flexible data rate frame structure * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition * @len: frame payload length in byte (0 .. CANFD_MAX_DLEN) * @flags: additional flags for CAN FD * @__res0: reserved / padding * @__res1: reserved / padding * @data: CAN FD frame payload (up to CANFD_MAX_DLEN byte) */ struct canfd_frame { canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ __u8 len; /* frame payload length in byte */ __u8 flags; /* additional flags for CAN FD */ __u8 __res0; /* reserved / padding */ __u8 __res1; /* reserved / padding */ __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8))); }; /* * defined bits for canxl_frame.flags * * The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC * and shares the relative position of the struct can[fd]_frame.len element. * The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame. * As a side effect setting this bit intentionally breaks the length checks * for Classical CAN and CAN FD frames. * * Undefined bits in canxl_frame.flags are reserved and shall be set to zero. */ #define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */ #define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */ /** * struct canxl_frame - CAN with e'X'tended frame 'L'ength frame structure * @prio: 11 bit arbitration priority with zero'ed CAN_*_FLAG flags * @flags: additional flags for CAN XL * @sdt: SDU (service data unit) type * @len: frame payload length in byte (CANXL_MIN_DLEN .. CANXL_MAX_DLEN) * @af: acceptance field * @data: CAN XL frame payload (CANXL_MIN_DLEN .. CANXL_MAX_DLEN byte) * * @prio shares the same position as @can_id from struct can[fd]_frame. */ struct canxl_frame { canid_t prio; /* 11 bit priority for arbitration (canid_t) */ __u8 flags; /* additional flags for CAN XL */ __u8 sdt; /* SDU (service data unit) type */ __u16 len; /* frame payload length in byte */ __u32 af; /* acceptance field */ __u8 data[CANXL_MAX_DLEN]; }; The LINKTYPE_CAN_SOCKETCAN header works with both the Linux CAN classic and CAN FD headers, but *doesn't* work with the CAN XL headers. So this will have to be redone for CAN XL. The fifth octet of the header is: for CAN classic, a payload length, which is always, as far as I know, < 128; for CAN FD, a payload length, which is always, as far as I know, < 128; for CAN XL, a flags field, which *always* has the CANXL_XLF (0x80) bit set. As the Linux comment notes, this allows CAN XL frames to be distinguished from CAN classic and CAN FD frames. Just To Make Sure, libpcap could force the CANXL_XLF flag on for frames with ETH_P_CANXL as the protocol type, just as it forces the CANFD_FDF flag on for frames with ETH_P_CANFD. > But for Wireshark there is only Classical CAN traffic happening (see attached > picture) - not even the CAN FD frame is detected in the "Protocol" field and > correctly decoded with the CAN FD specific flags. So what tool was used to capture this traffic? What version of libpcap was it using? And there were CAN FD frames - *not* CAN XL frames, which Wireshark can't handle - in those captures? If so, please provide a sample capture. > So how can I help to fix the broken display of CAN types and also add proper > CAN XL support? 1) Provide a capture file that contains CAN FD frames but that isn't correctly dissected, so we can see *why* the FD frames aren't being detected (is the CANFD_FDF flag not set?). 2) Add support to CAN XL, using the "is the 0x80 bit set in the fifth octet of the header?" test, to epan/dissectors/packet-socketcan.c. 3) Perhaps have libpcap forcibly set that flag based on the protocol field. ___________________________________________________________________________ Sent via: Wireshark-dev mailing list <wireshark-dev@wireshark.org> Archives: https://www.wireshark.org/lists/wireshark-dev Unsubscribe: https://www.wireshark.org/mailman/options/wireshark-dev mailto:wireshark-dev-requ...@wireshark.org?subject=unsubscribe