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