Das SocketCAN-Gateway cangw

Mit dem kürzlich veröffentlichten Linux Kernel 3.2 hat das SocketCAN-Subsystem eine neue Funktionalität erhalten. Über das Tool cangw aus den can-utils ist es möglich, den Kernel anzuweisen, dass er zwischen verschiedenen CAN-Bussen ein Routing von bestimmten Frames durchführen soll. Die Bedienung ist an das bekannte iptables für IP-Pakete angelehnt. Dies hat den Vorteil, dass man einerseits keine Latenzprobleme beim Routen der Frames bekommt, wie es in einem Multiuser-Betriebssystem bei einem Gateway-Programm im User-Space der Fall wäre. Außerdem lässt sich so sehr schnell und einfach mit ein paar Aufrufen aus einem Startskript ein komplexes Routing-Setup aufbauen.

In einem Paper wird die Performance des Ansatzes ausführlich analysiert und man kommt zu dem folgenden Schluss:

The results indicate that the gateway itself introduces no significant overhead under real-life bus loads and working conditions and can reliably work as a part of a distributed embedded system. Our results were used to support merging the gateway into Linux mainline

Hier ein kleines Beispiel was man mit dem Tool so anstellen kann. Zunächst brauchen wir zwei virtuelle CAN-Busse:

$ ip link add dev vcan0 type vcan
$ ip link add dev vcan1 type vcan
$ ip link set up vcan0
$ ip link set up vcan1

Jetzt lassen wir auf vcan0 im Hintergrund zufällige CAN-Frames generieren:

$ cangen vcan0 &

Nun wird mit cangw eine neue Regel erstellt, die alle Frames von vcan0 auf vcan1 spiegelt:

$ cangw -A -s vcan0 -d vcan1 -e
$ cangw -L
cangw -A -s vcan0 -d vcan1 -e # 31 handled 0 dropped

Der zweite Aufruf listet alle aktiven Regeln auf und zeigt auch die Anzahl der Frames, die von der Regel betroffen waren. Ein Blick mit candump zeigt, dass das Routing tatsächlich funktioniert:

$ candump vcan1
vcan1  3CB  [5] 1E F1 55 16 EF
vcan1  6F7  [4] AC CB 4F 2F
vcan1  4BA  [2] DC E4
vcan1  770  [8] E7 FA BD 13 C7 FB 33 69
vcan1  19A  [8] 3A 48 0E 13 31 D2 F4 51
vcan1  4FC  [8] D8 01 DA 2C AF 6C 39 5A
vcan1  5DA  [0]

Jetzt löschen wir alle Regeln und erstellen eine neue etwas komplexere. Die Frames werden wieder von vcan0 nach vcan1 weitergeleitet. Dieses Mal wird zusätzlich eine Veränderung vorgenommen. Der DLC wird auf 4 Byte gesetzt und die ersten zwei Byte sind immer 0xFFFF.

$ cangw -F
$ cangw -A -s vcan0 -d vcan1 -e -m SET:L:000.4.0000000000000000 -m OR:D:000.0.FFFF000000000000
$ candump vcan1
vcan1  10E  [4] FF FF E3 6A
vcan1  6A2  [4] FF FF 25 5D
vcan1  1F7  [4] FF FF 1B 32
vcan1  33F  [4] FF FF EF 7D
vcan1  697  [4] FF FF 49 3E
vcan1   30  [4] FF FF 3D 5F
vcan1  3E7  [4] FF FF 7C 34
vcan1  66D  [4] FF FF A2 10
vcan1  21D  [4] FF FF AA 7E

In der Praxis lassen sich sicher sinnvollere Veränderungen finden aber man sieht schon, dass das Tool sehr mächtig ist. Die Hilfe-Seite des Tools zeigt alle möglichen Optionen auf. Darunter sind:

  • Filtern nach bestimmten IDs
  • Filtern nach ID-Bereichen
  • Modifikation der Daten und IDs (SET, XOR, OR, AND)
  • Berechnung von CRC8 Prüfsummen nach der Veränderung