SocketCAN#

Linux SocketCAN is a set of open-source CAN drivers and a networking stack for Linux. It provides a standard socket interface for userspace applications to interact with the CAN bus, and it is based on the Berkeley socket API. SocketCAN supports multiple CAN controllers and is designed to be compatible with the CAN protocol standard ISO 11898.

The SocketCAN architecture is divided into two parts:

  • The CAN protocol stack, which runs in kernel space and provides low-level CAN communication, and the socket interface, which runs in user space and provides high-level communication to the applications. The CAN protocol stack is responsible for receiving and transmitting CAN frames, handling errors, and filtering incoming traffic.

  • The socket interface provides the userspace application with a simple way to interact with the CAN bus, by using standard socket calls such as bind(), send(), and recv().

The SocketCAN also provides a set of utilities for managing and configuring the CAN interfaces, such as can-utils. These utilities allow performing common tasks such as creating and deleting interfaces, setting the bitrate, sending and receiving CAN messages, and viewing the statistics of the interfaces.

Summary

  • Linux way of using CAN interfaces

  • Reuses network queues for CAN

  • SocketCAN provides multi-user access to a shared CAN interface

  • Part of Linux mainline. Implemented by Oliver Hartkopp [Har11].

  • Offers Linux sockets to user applications

../../_images/Dissertation2.png

Fig. 28 Protocol families of the Linux kernel. Author: Dr. Oliver Hartkopp#

  • Provides different socket types: CAN_RAW, CAN_BCM, CAN_ISOTP

  • CAN_RAW: Socket for CAN communication.

  • CAN_BCM: Broadcast-Manager for CAN. Allows to send periodic messages.

  • CAN_ISOTP: Transport-Layersocket for ISOTP communication. Entire protocol handling is done in kernel space.

../../_images/Dissertation.png

Fig. 29 The CAN subsystem kernel module of the Linux kernel. Author: Dr. Oliver Hartkopp#

Interfaces#

  • canX: Real CAN-Interfaces connected to the system.

  • vcanX: Virtual CAN-Interfaces. Great for testing. Require the vcan kernel module.

  • slcanX: Serial Line CAN-Interfaces. Socket wrapper for serial-to-CAN interfaces, supporting the slcan protocol. A /dev/tty device is turned into a CAN socket.

  • vxcan Virtual CAN tunnel across network namespaces, used for forwarding traffic to a container.

SocketCAN setup#

All examples use can0 as interface name!

  • Get interface status

ip a

    8: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN \ 
    group default qlen 10
        link/can 
  • Increase TX queue (useful on ISOTP communication)

sudo ip link set can0 txqueuelen 4000
  • Bring up CAN interface and specify baudrate

sudo ip link set dev can0 up type can bitrate 500000
  • Et voilà

ip a

    8: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc \ 
    pfifo_fast state UP group default qlen 4000
        link/can

SocketCAN usage from C#

/* Create the socket */
int skt = socket( PF_CAN, SOCK_RAW, CAN_RAW );

/* Locate the interface you wish to use */
struct ifreq ifr;
strcpy(ifr.ifr_name, "can0");
ioctl(skt, SIOCGIFINDEX, &ifr); 
/* ifr.ifr_ifindex gets filled
 * with that device's index */

/* Select that CAN interface, and bind the socket to it. */
struct sockaddr_can addr;
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
bind( skt, (struct sockaddr*)&addr, sizeof(addr) );

/* Send a message to the CAN bus */
struct can_frame frame;
frame.can_id = 0x123;
strcpy( (char *)frame.data, "foo" );
frame.can_dlc = strlen( (const char *)frame.data );
int bytes_sent = write( skt, &frame, sizeof(frame) );

/* Read a message back from the CAN bus */
int bytes_read = read( skt, &frame, sizeof(frame) );

Filters#

CAN filters consist of an identifier (FILTER-ID) and a mask.

  • Filtering

(CAN-ID & MASK) == (FILTER-ID & MASK)
  • Inverted Filtering (Blocking)

(CAN-ID & MASK) != (FILTER-ID & MASK)

can-utils#

  • Userspace utilities for Linux CAN subsystem (aka SocketCAN)

  • Installation on Debian-based systems

sudo apt-get install can-utils

candump#

All examples use can0 as the interface name!

  • Dump all messages to stdout

candump can0
  • Dump all messages to a log file

candump can0 -l
  • Dump with a CAN filter

candump can0,0x123:0x7FF
  • Dump with a CAN an inverted filter

candump can0,0x123~0x7FF

cansend#

All examples use can0 as the interface name!

  • Send a CAN message

cansend can0 123#aabb112233445566
  • Send a CAN message with an extended CAN identifier

cansend can0 1ff46623#aabb112233445566

Further utilities#

  • cangen: Generates random CAN traffic (Can be used for fuzzing)

  • cangw: Creates gateway between CAN networks

  • canplayer: Replays a candump log file

  • cansniffer: Similar to candump but with more options and highlighting of changes

  • canbusload: Show utilization of CAN buses

  • … and some more …

Also interesting

  • socketcand: Socketcand is a daemon that provides access to CAN interfaces on a machine via a network interface.

  • canneloni: A SocketCAN over Ethernet tunnel GitHub - cannelloni