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

Reply via email to