tcpdump mailing list archives

Re: [PATCH] SocketCAN support for libpcap - draft implementation


From: Alexander Dupuy <adupuy () trustedcs com>
Date: Fri, 09 Oct 2009 08:27:55 -0400

Felix Obenhuber wrote:
2. The can frame struct is defined like this (from linux/can.h):
/**
 * struct can_frame - basic CAN frame structure
 * @can_id:  the CAN ID of the frame and CAN_*_FLAG flags, see above.
 * @can_dlc: the data length field of the CAN frame
 * @data:    the CAN frame payload.
 */
struct can_frame {
        canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
        __u8    can_dlc; /* data length code: 0 .. 8 */
        __u8    data[8] __attribute__((aligned(8)));
};

Gianluca Varenni noted a CAN2.0B spec exists at http://www.winpcap.org/gianluca/can.html
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PAD |    Identifier A     |            Identifier B           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  PAD  |  DLC  |        Data ( variable length )               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               |
+-+-+-+-+-+-+-+-+

*CAN 2.0B Packet Block Format.*
The meaning of the fields is:

    * PAD: 3 bits of padding for byte alignment.
    * Identifier A: The 11 bits of the CAN 2.0B Identfier from a CAN
      2.0B frame.
    * Identifier B: The 18 bits of the CAN 2.0B Extended Identfier
      from a CAN 2.0B frame.
    * PAD: 4 bits of padding for byte alignment.
    * DLC: The length of Data in bytes. This corresponds to the DLC in
      a CAN 2.0B frame.
    * Data: The payload of the block. Up to 8 bytes in length, the
      length should correspond to the value of the DLC.


Apart from the three bytes of padding that the __attribute__((aligned(8))) adds, this appears to be roughly the same in layout. However, although canid_t is a 32-bit field with the EFF/SFF/RTR flags packed into the three bits marked as PAD in the diagram above, the order of the identifiers seems to be different. In linux/can.h, you have

|||/
|//* special address description flags for the CAN_ID *//
||#*define* CAN_EFF_FLAG 0x80000000U //* EFF/SFF is set in the MSB *//
||#*define* CAN_RTR_FLAG 0x40000000U //* remote transmission request *//
||#*define* CAN_ERR_FLAG 0x20000000U //* error frame *//
||
||//* valid bits in CAN ID for frame formats *//
||#*define* CAN_SFF_MASK 0x000007FFU //* standard frame format (SFF) *//
||#*define* CAN_EFF_MASK 0x1FFFFFFFU //* extended frame format (EFF) *//
||#*define* CAN_ERR_MASK 0x1FFFFFFFU //* omit EFF, RTR, ERR flags *//
||
||//*
/||/ * Controller Area Network Identifier structure
/||/ *
/||/ * bit 0-28     : CAN identifier (11/29 bit)
/||/ * bit 29       : error frame flag (0 = data frame, 1 = error frame)
/||/ * bit 30       : remote transmission request flag (1 = rtr frame)
/||/ * bit 31       : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
/||/ *//
||*typedef* __u32 canid_t;
|

/|

Furthermore, the Linux canid_t keeps all of these bits in a (byte-ordered) 32-bit integer, which would give the following layouts:

Big-endian:

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|R|E|            Identifier B           |    Identifier A     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


Little-endian (Intel):

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    Lo Id A    | Lo Id B |HiIdA|    Mid Id B   |F|R|E| Hi Id B |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

(The little-endian one only looks so chopped up because the bits are shown in big-endian order, which is what these sorts of packet block diagrams always use - I don't know anything about CAN transmission order and in any case this is strictly an in-memory layout).

Given these differences between the two frame formats I would suggest that you use a new DLT for SocketCAN, especially as there would be no way to know for sure whether the flags were present or just padding (a packet with all zero flags would be indistinguishable). If you ever think that SocketCAN/libpcap will be used on big-endian systems, you might want to "canonicalize" the layout in the big-endian format above for a more comprehensible diagram, and because little-endian systems have htonl/ntohl macros that are not no-ops, making portable user-level coding simpler (if you standardize the little-endian format, portable code has to use #ifdefs to determine byte-order and then call a swap() function/macro on big-endian systems).

@alex

--
Alexander Dupuy
Senior Secure Systems Engineer
Trusted Computer Solutions
2350 Corporate Park Drive, Suite 500
Herndon, VA  20171-4848
mailto:adupuy () trustedcs com

-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


Current thread: