Teil 4 hat das ACF-CAN-Tunneling mit den Open1722-User-Space-Beispielanwendungen gezeigt. Dieser Teil geht eine Ebene tiefer: das Open1722-Linux-Kernel-Modul (examples/acf-can/linux-kernel-mod/), das ACF-CAN-Tunneling direkt im Kernel abbildet — und zwar nicht mit den beiden veth-Interfaces auf einer einzigen Maschine aus dem Upstream-Beispiel, sondern zwischen zwei physischen BeagleBone Black, die per Ethernet-Kabel verbunden sind.

Dieser Post ist als eigenständiges Praxisprojekt gedacht, gegründet auf dem realen Readme.md aus examples/acf-can/linux-kernel-mod/ im Open1722-Repository — nicht auf dem AUTOSAR-Modul IEEE1722Tp selbst. Open1722 implementiert den allgemeinen IEEE-1722-Standard direkt; das Kernel-Modul ist ein experimentelles Community-Projekt ("fun experiment" laut eigenem README), kein AUTOSAR-BSW-Modul. Der Lerneffekt (ACF-CAN konkret anfassen) überträgt sich trotzdem 1:1 auf das Konzept aus Teil 2.

Architektur: ACF-CAN als ganz normales SocketCAN-Interface

Der Clou des Kernel-Moduls: aus Sicht des User-Space gibt es keinen Unterschied zwischen einem echten CAN-Treiber (Hardware-CAN-Controller) und dem acfcan-Netzwerkdevice — beide bedienen das normale Linux-SocketCAN-Interface. cansend/candump funktionieren identisch, unabhängig davon, ob dahinter ein echter CAN-Bus oder ACF-CAN über Ethernet steckt.

ACF-CAN-Kernel-Modul zwischen zwei echten BeagleBone Black
FeatureStatus laut Open1722-README

CAN und CAN FD

Unterstützt

Konfigurierbare Stream- und Bus-ID

Unterstützt

NTSCF

Unterstützt

Senden und Empfangen

Unterstützt

TSCF

Noch nicht unterstützt

CAN-BRIEF

Noch nicht unterstützt

Batching (mehrere ACF-CAN-Nachrichten pro Frame)

Noch nicht unterstützt — aktuell genau eine ACF-CAN-Nachricht pro IEEE-1722-Frame

Das Kernel-Modul ist laut eigenem README explizit "in active development" — es unterstützt bewusst nur NTSCF, nicht TSCF, und noch keine Bündelung mehrerer ACF-Nachrichten pro Frame (anders als das in Teil 2 beschriebene IEEE1722TpStreamAcfMixedBusTypeCollection). Für ein erstes Kennenlernen von ACF-CAN reicht das völlig aus.

Cross-Compile gegen den Yocto-Kernel der BeagleBone Black

Statt des im Open1722-README beschriebenen Ubuntu-Hosts wird hier gegen den bereits in der Kernel-Modul-Serie gezeigten Yocto-Kernel cross-kompiliert:

source /opt/poky/*/environment-setup-cortexa8hf-neon-poky-linux-gnueabi

cd Open1722/examples/acf-can/linux-kernel-mod
export CONFIG_ACF_CAN=m
make KDIR=$KERNEL_SRC

$KERNEL_SRC zeigt auf den konfigurierten Kernel-Quellbaum des Yocto-Builds (tmp/work-shared/beaglebone-yocto/kernel-source) — exakt dieselbe Kernel-Version und -Konfiguration, die auch auf dem Zielsystem läuft, sonst schlägt das Laden mit einem Versions-Mismatch fehl (siehe Kernel-Modul-Post).

Dieser Build-Schritt ist auf beiden Boards identisch — das Modul muss auf jedem BeagleBone Black einzeln gebaut (oder zumindest kopiert) und geladen werden.

Laden des Moduls

Auf beiden Boards zunächst die CAN-Subsystem-Abhängigkeit laden, dann das Modul selbst:

sudo modprobe can
sudo insmod acfcan.ko

modprobe can ist nötig, damit alle vom CAN-Subsystem benötigten Symbole bereits im Kernel geladen sind — ohne diesen Schritt schlägt insmod acfcan.ko beim ersten Laden von einem lokalen Verzeichnis mit fehlenden Symbolen fehl.

Setup: zwei physische Interfaces statt zweier veth-Paare

Das Upstream-Beispiel im Open1722-README zeigt zwei acfcan-Interfaces, verbunden über ein veth-Paar auf einer Maschine (ip link add dev mon1 type veth peer name mon2). Hier passiert dasselbe Prinzip stattdessen über ein echtes Ethernet-Kabel zwischen zwei Boards.

Auf Board A

sudo ip link add dev ecu0 type acfcan
sudo ip link set ecu0 mtu 72

# ethif zeigt auf das reale eth0 des Boards, nicht auf ein veth-Interface
echo -n "eth0" | sudo tee /sys/class/net/ecu0/acfcan/ethif

# dstmac ist die reale MAC-Adresse von Board B
echo -n "<MAC-Adresse Board B>" | sudo tee /sys/class/net/ecu0/acfcan/dstmac

echo -n "cafe11" | sudo tee /sys/class/net/ecu0/acfcan/tx_streamid
echo -n "dead22" | sudo tee /sys/class/net/ecu0/acfcan/rx_streamid

sudo ip link set up ecu0

Auf Board B

sudo ip link add dev ecu1 type acfcan
sudo ip link set ecu1 mtu 72

echo -n "eth0" | sudo tee /sys/class/net/ecu1/acfcan/ethif
echo -n "<MAC-Adresse Board A>" | sudo tee /sys/class/net/ecu1/acfcan/dstmac

echo -n "dead22" | sudo tee /sys/class/net/ecu1/acfcan/tx_streamid
echo -n "cafe11" | sudo tee /sys/class/net/ecu1/acfcan/rx_streamid

sudo ip link set up ecu1

tx_streamid von Board A muss exakt dem rx_streamid von Board B entsprechen, und umgekehrt — die Stream-IDs müssen gegenläufig gespiegelt werden. Verwechselt man das, verwirft die Gegenseite die ACF-CAN-Pakete kommentarlos, ohne einen offensichtlichen Fehler zu zeigen. Alle sysfs-Optionen unter /sys/class/net/<devname>/acfcan/ lassen sich nur setzen, während das Interface down ist.

Test: echter CAN-Traffic zwischen zwei Boards

# Auf Board B mitlauschen
candump ecu1

# Auf Board A senden
cansend ecu0 123#DEADBEEF

Die Nachricht erscheint auf Board B, obwohl kein echter CAN-Bus zwischen den Boards existiert — sie wurde vollständig über das Ethernet-Kabel als ACF-CAN-Nachricht getunnelt. Anders als beim Upstream-veth-Beispiel ist das hier kein Loopback auf einer Maschine, sondern echter Netzwerkverkehr zwischen zwei physischen Geräten.

Mit tcpdump -i eth0 -w capture.pcap parallel auf einem der beiden Boards (oder auf einem dazwischengeschalteten TSN-Switch aus der EthSwt-Serie) lässt sich der IEEE-1722-Frame in Wireshark inspizieren — NTSCF-Header und ACF-CAN-Payload sind dort direkt sichtbar, inklusive der zuvor konfigurierten Stream-IDs.

Diagnose

dmesg --follow

# Dynamic Debug aktivieren, sofern der Kernel das unterstützt
echo 'module acfcan +p' | sudo tee /sys/kernel/debug/dynamic_debug/control
ProblemTypische Ursache

insmod schlägt mit fehlenden Symbolen fehl

modprobe can vergessen

Kein Traffic bei candump sichtbar

tx_streamid/rx_streamid nicht gegenläufig gespiegelt, oder dstmac falsch

insmod schlägt mit Versions-Mismatch fehl

Modul nicht exakt gegen den auf dem Board laufenden Kernel gebaut — siehe Kernel-Modul-Post

Secure Boot verhindert das Laden

Bei selbstgebautem Yocto-Kernel auf der BeagleBone Black in der Praxis selten relevant — betrifft eher Ubuntu-Hosts mit aktiviertem Secure Boot

Fazit: der erste Baustein für ein zonales Gateway-Experiment

Dieses Setup — ein BeagleBone Black, das sein eigenes (simuliertes) CAN-Teilnetz transparent über ein TSN-fähiges Ethernet-Backbone an eine "Zentrale" tunnelt — ist im Kleinen genau das Szenario aus Teil 2: eine teilmigrierte zonale Architektur, in der ein Zonal Controller Legacy-CAN-Verkehr transparent tunnelt, ohne dass die eigentlichen CAN-Steuergeräte etwas davon merken. Zwei BeagleBone Black und ein Ethernet-Kabel reichen aus, um dieses Prinzip greifbar zu machen, bevor es an ein reales, mehrschichtiges Fahrzeugnetz geht.

Zusammenfassung

AspektKernaussage

Architektur

acfcan ist aus User-Space-Sicht ein normales SocketCAN-Interface — cansend/candump funktionieren unverändert

Build

Cross-Compile gegen den Yocto-Kernel-Quellbaum, exakt wie im Kernel-Modul-Grundlagen-Post — CONFIG_ACF_CAN=m, modprobe can vor insmod

Setup

Zwei physische acfcan-Interfaces, ethif auf das reale eth0, dstmac auf die reale Gegenstelle, tx_streamid/rx_streamid gegenläufig gespiegelt

Test

cansend/candump über zwei physische Boards hinweg, tcpdump zur Sichtbarmachung des IEEE-1722-Frames

Einordnung

Kleinformatiges, konkret nachvollziehbares Beispiel für das Zonal-Gateway-Szenario aus Teil 2 — kein AUTOSAR-BSW-Modul, aber dasselbe Grundprinzip