Multiple CAN Adapters Under systemd
Introduction
When using more than one CAN adapter or a CAN adapter and a board in USB to CAN Bridge mode, it makes sense to ensure:
- CAN adapters can easily be identified
- CAN adapters do not change enumeration or interface during reboot or reconnecting
- Different settings can be applied to different adapters or interfaces
Note
- Works with one or multiple adapters (less benefit for a single device).
- Tested on
systemdv255. Required minimum is v248.- Alternative:
udevrules (not covered here).
Identifying the CAN Adapters
Each connected CAN adapter that is identified as such is automatically assigned a can-networking interface by the Linux Operating System (OS). The first is can0, the second can1, etc.
To distinguish between the different interfaces, a unique property needs to be identified.
Listing all identified adapters
Run the command
ip -details -s link show
An identified CAN adapter will look like:
7: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
can state STOPPED restart-ms 0
gs_usb: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp_inc 1
clock 48000000
re-started bus-errors arbit-lost error-warn error-pass bus-off
0 0 0 0 0 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 parentbus usb parentdev 2-1.4:1.0
RX: bytes packets errors dropped missed mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
Identifying the system path of the Adapter
Run the following command in the Linux shell:
udevadm info -q path -p /sys/class/net/can0
The output will look similar to:
/devices/platform/soc/5310000.usb/usb2/2-1/2-1.4/2-1.4:1.0/net/can0
- For the following command, exactly this device path is needed.
- Repeat for each CAN adapter by replacing
can0in the command part/sys/class/net/can0withcan1, etc.
Identifying the Adapters Properties:
Run the command
udevadm info /sys/devices/platform/soc/5310000.usb/usb2/2-1/2-1.4/2-1.4:1.0/net/can0
- The relevant part is the device path identified above prepended with
/sys/ - Each CAN adapter will have its own unique path
The output will look like:
P: /devices/platform/soc/5310000.usb/usb2/2-1/2-1.4/2-1.4:1.0/net/can0
M: can0
R: 0
U: net
I: 7
E: DEVPATH=/devices/platform/soc/5310000.usb/usb2/2-1/2-1.4/2-1.4:1.0/net/can0
E: SUBSYSTEM=net
E: INTERFACE=can0
E: IFINDEX=7
E: USEC_INITIALIZED=9036766055
E: ID_NET_DRIVER=gs_usb
E: ID_BUS=usb
E: ID_MODEL=FLY-UTOC_USB_to_CAN_adapter
E: ID_MODEL_ENC=FLY-UTOC\x20USB\x20to\x20CAN\x20adapter
E: ID_MODEL_ID=606f
E: ID_SERIAL=Mellow._FLY-UTOC_USB_to_CAN_adapter_002100255842571320323035
E: ID_SERIAL_SHORT=002100255842571320323035
E: ID_VENDOR=Mellow.
E: ID_VENDOR_ENC=Mellow.
E: ID_VENDOR_ID=1d50
E: ID_REVISION=0000
E: ID_TYPE=generic
E: ID_USB_MODEL=FLY-UTOC_USB_to_CAN_adapter
E: ID_USB_MODEL_ENC=FLY-UTOC\x20USB\x20to\x20CAN\x20adapter
E: ID_USB_MODEL_ID=606f
E: ID_USB_SERIAL=Mellow._FLY-UTOC_USB_to_CAN_adapter_002100255842571320323035
E: ID_USB_SERIAL_SHORT=002100255842571320323035
E: ID_USB_VENDOR=Mellow.
E: ID_USB_VENDOR_ENC=Mellow.
E: ID_USB_VENDOR_ID=1d50
E: ID_USB_REVISION=0000
E: ID_USB_TYPE=generic
E: ID_USB_INTERFACES=:ffffff:fe0101:
E: ID_USB_INTERFACE_NUM=00
E: ID_USB_DRIVER=gs_usb
E: ID_VENDOR_FROM_DATABASE=OpenMoko, Inc.
E: ID_MODEL_FROM_DATABASE=Geschwister Schneider CAN adapter
E: ID_PATH_WITH_USB_REVISION=platform-5310000.usb-usbv2-0:1.4:1.0
E: ID_PATH=platform-5310000.usb-usb-0:1.4:1.0
E: ID_PATH_TAG=platform-5310000_usb-usb-0_1_4_1_0
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/73-usb-net-by-mac.link
E: ID_NET_NAME=can0
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/can0
E: TAGS=:systemd:
E: CURRENT_TAGS=:systemd:
- Each adapter will have its own properties and values, depending on the hardware, type of connection, etc.
- You need to identify a property and value that looks unique to this adapter. In the example above, this could be:
E: ID_SERIAL=Mellow._FLY-UTOC_USB_to_CAN_adapter_002100255842571320323035 - The best properties to use are hardware-specific serial numbers like
ID_SERIALorID_SERIAL_SHORT, as they are unique to the device. Avoid using path-based properties likeID_PATHif possible, as these can change if you use a different USB port.
Setting up .link and .network file
To configure the adapter, two files are needed: .link and .network files are simple text files with an INI-style format. For this configuration, they must adhere to the following rules:
- Location: The files must be created in the
/etc/systemd/network/directory to ensure they take precedence over any system defaults. - Filename: Each file must have a
.link/.networkextension. - To control the processing order and ensure they are evaluated before the defaults, their names should be prefixed with a number lower than 99 and the
.linkfiles before the.networkfiles. A logical naming scheme would be:10-can0.linkand11-can1.linkand so on20-can0.networkand20-can1.networkand so on
- Content:
- A
.linkfile is composed of sections. The[Match]section contains keys thatudevuses to identify a specific device. The[Link]section contains directives that configure the matched device, most importantly theNamekey for renaming it. - A
.networkfile contains a[Match]section to identify the interface it applies to (by its now-stable name from the corresponding.linkfile) and one or more configuration sections. For this task, the key section is[CAN].
- A
Complete Example for the above
Note
- Creating or modifying these files, requires
sudo
/etc/systemd/network/11-can_mellow.link
[Match]
Property=ID_SERIAL=Mellow._FLY-UTOC_USB_to_CAN_adapter_002100255842571320323035
[Link]
Name=can_mellow
TransmitQueueLength=128
- Note the
Property=notation in the[Match]section. This uniquely identifies the adapter as determined in the previous chapters. This is thesystemd-networkdsyntax for matching audevproperty. - Note the
Name=can_mellowsetting: Here an arbitrary name can be assigned (no blanks or special characters allowed) TransmitQueueLength=128is a relevant setting for proper Klipper operation.
/etc/systemd/network/21-can_mellow.network
[Match]
Name=can_mellow
[Link]
RequiredForOnline=no
[CAN]
BitRate=1M
RestartSec=500ms
- Note the
Name=notation in the[Match]section. This must match the name assigned in the.linkfile - Note the
RequiredForOnlinesetting. This is required untilsystemdversion 256. Potentially backported in some distributions. It preventssystemdfrom waiting for CAN links to report “up” before starting dependent services. - Other settings like
BitRatecan now be specified on a stable adapter basis
Note
- Reboot for the settings to take effect
Verifying the Settings
Issue the command:
ip -details -s link show
Output:
5: can_mellow: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 128
link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
can state ERROR-ACTIVE restart-ms 500
bitrate 1000000 sample-point 0.750
tq 62 prop-seg 5 phase-seg1 6 phase-seg2 4 sjw 2 brp 3
gs_usb: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp_inc 1
clock 48000000
re-started bus-errors arbit-lost error-warn error-pass bus-off
0 0 0 0 0 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 parentbus usb parentdev 2-1.5:1.0
RX: bytes packets errors dropped missed mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
- Note the newly assigned name at the beginning of line 1
- Note the proper queue length at the end of line 1
- Note the defined
bitratein line 4
Now, issue the command:
networkctl status can_mellow
Output:
● 3: can_mellow
Link File: /etc/systemd/network/11-can_mellow.link
Network File: /etc/systemd/network/21-can_mellow.network
State: carrier (configured)
Online state: offline
Type: can
Kind: can
Path: platform-5311400.usb-usb-0:1:1.0
Driver: gs_usb
Vendor: OpenMoko, Inc.
Model: Geschwister Schneider CAN adapter
MTU: 16
QDisc: pfifo_fast
Number of Queues (Tx/Rx): 1/1
Activation Policy: up
Required For Online: no
- Note the proper
.linkand.networkfiles in lines 2 and 3 - Note the
Required For Online: nostatement
Usage
Everywhere, e.g. in the printer.cfg or in command line utilities like flashtool.py, the interface now needs to be explicitly called under its new name.