With both adapters attached at power-on, pcan registered first and took can0, and the udev rule renamed it to can_pcan, confirming the race and the fix. qmi_wwan auto-loaded, povo auto-connected below WiFi, and gpsd came up on the stable symlink. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.2 KiB
type, date
| type | date |
|---|---|
| report | 2026-10-08 |
Stable Device Naming: CAN Interfaces and SIM7600 Ports
Problem
Kernel names come from registration order. That order isn't stable, so anything configured as can1 or ttyUSB3
can point at a different device after a reboot or replug.
- CAN:
mttcan(onboard) andpcan(USB, via/etc/modules) both load at boot. ThecanNnames go to whichever registers first, so the PCAN adapter can end up ascan0and the onboard controller ascan1. - SIM7600: five
ttyUSB*ports. Their numbers shift if another USB-serial device enumerates first.
Result
| Device | Identified by | Stable name |
|---|---|---|
| Onboard MTTCAN | platform device c310000.mttcan |
can_onboard |
| PEAK PCAN-USB | USB 0c72:000c |
can_pcan |
| SIM7600 NMEA port | USB 1e0e:9001, interface 01 |
/dev/sim7600-gps (symlink) |
| SIM7600 modem | ModemManager simtech plugin (USB IDs and per-interface port probing) |
n/a, nothing configured by port name |
| SIM7600 data | NetworkManager povo connection with ifname '*' |
n/a, follows whatever modem ModemManager exposes |
can_onboard was verified with a live rename (mttcan c310000.mttcan can_onboard: renamed from can0).
Verified across a cold boot (2026-10-08) with the PCAN-USB and SIM7600 both attached before power-on: pcan registered first
and took can0, which is the race this rule exists for. udev renamed it (pcan 1-2.4:1.0 can_pcan: renamed from can0), and
mttcan then got can0 and was renamed to can_onboard. ModemManager came up on cdc-wdm0 (qmi_wwan auto-loaded), povo
auto-connected with wwan0 at metric 1000 below WiFi, and gpsd started on /dev/sim7600-gps.
CAN: /etc/udev/rules.d/70-can-names.rules
SUBSYSTEM=="net", ACTION=="add", KERNELS=="c310000.mttcan", NAME="can_onboard"
SUBSYSTEM=="net", ACTION=="add", ATTRS{idVendor}=="0c72", ATTRS{idProduct}=="000c", NAME="can_pcan"
- Both interfaces get names outside the kernel's
canNpool. Renaming only the PCAN and pinning the onboard controller tocan0would race: ifpcanregisters first, it briefly holdscan0and the onboard rename collides. - Underscores rather than hyphens: systemd escapes
-in device unit names (sys-subsystem-net-devices-can\x2dpcan.device). - The file must sort before
80-net-setup-link.rules, which only assigns a name whenNAMEis still empty. - PCAN matching relies on the netdev's sysfs parent being the USB interface. In PEAK 9.2.0,
pcan_netdev.ccallsSET_NETDEV_DEV(ndev, pcandev_to_dev(pdev)), and for USB devices that returns&usb_intf->dev, soATTRS{idVendor}matches. - PEAK's own
assign=module parameter (peak,devid,pcanX:canY) can only producecanNnames, so it doesn't avoid the race. - More than one PCAN-USB: both would match
can_pcan, and the second rename would fail. Give each adapter a device ID (PEAK tools:pcan-settings), then add a per-ID match and distinct names.
Apply without a reboot (interface must be DOWN):
sudo udevadm control --reload
sudo udevadm trigger --action=add /sys/class/net/can0
Usage: sudo ip link set can_pcan up type can bitrate 500000 && candump can_pcan.
Generic detection still works: ip -d link show type can lists both regardless of name.
SIM7600: why no further rules are needed
- ModemManager identifies the modem by USB ID and probes each port, which gives it the
(at),(gps),(qmi)and(net)roles. It never relies on attyUSBnumber. - NetworkManager binds the
povoGSM connection to the ModemManager modem object (ifname '*'), not to a device node. - gpsd is the only consumer of a raw port, and it uses the
/dev/sim7600-gpsudev symlink (/etc/udev/rules.d/99-sim7600-gps.rules, matchingENV{ID_USB_INTERFACE_NUM}=="01"). ttyUSB2is mentioned in the SIM7600 report only for manual AT sessions.ls -l /dev/serial/by-id/shows the stable path (...-if02-port0) if numbering ever shifts.
Affected references
- PCAN setup report: its
can0/can1examples are from before this change. halogen-workstation-roadmapphase 17 lists "presence ofcan0" as a CAN heuristic. That heuristic is now false on this host;ip -d link show type canstill works.