Kurzanleitung zum Treiber-Tuning unter Linux, mit dem Beispiel rt2800lib

2015-01-02

Zum Treiber-Tuning, bei dem nur ein Modul ausgetauscht wird, sind drei Schritte nötig:

1.
Kernel-Source installieren, traditionell nach /usr/src/linux. Dazu gibt es das Skript getkernelsources_ubuntu.sh für Ubuntu und auch Ubuntu-Varianten wie Kubuntu.
Hierbei wird unter Ubuntu zunächst in das aktuelle Verzeichnis installiert, beispielsweise zu Kernel 3.15.0-6 die Dateien linux_3.15.0-6.11.dsc (11 kB, PGP-signierte Paketliste) und linux_3.15.0-6.11.tar.gz (125 MB, Sourcen zu Ubuntu) sowie das Verzeichnis linux-3.15.0 (671 MB, Kernel-Sourcen aus linux_3.15.0-6.11.tar.gz).
Für andere Distributionen ist es mehr oder minder anders; da hilft beispielsweise Google weiter.

2.
Die betreffende Datei aus den Sourcen holen und modifizieren. Meistens ist es nur ein Übernehmen der Änderungen, die man mit einem Programm wie kompare mit ein paar Klicks erledigt hat. Dieser Schritt entfällt, wenn man schon die aktuell getunte Version hat. Dafür gibt es das Original und die getunte Version, damit man mit einem Vergleichsprogramm wie kompare sieht was früher geändert wurde und entsprechend bei der neuen Datei zu ändern ist.
Zum rt2800lib findet man dazu das Original hier, die betreffende Kernel-Version hier und die getunte Version hier. Da sich die Teiber-Dateien nicht selten über Monate oder gar Jahre nicht ändern, ist die betreffende Kernel-Version nur eine Stichprobe und meist enthalten ältere wie neuere Kernel-Sourcen die gleiche Datei-Version.

3.
Das Modul neu erstellen, wozu beim ersten Mal auch der Kernel compiliert werden muss, was circa eine Stunde auf einem etwas langsamen PC dauert. Dafür gibt es das Skript makemodule_rt2800lib.sh.

Das in linux_3.15.0-6.11.tar.gz und dem Verzeichnis linux-3.15.0 das gleiche enthalten ist, sieht man nach dem Auspacken (mit tar -xzf linux_3.15.0-6.11.tar.gz) durch Vergleichen der Verzeichnisinhalte, beispielsweise mit "diff -qr linux-3.15.0 ubuntu-utopic".

Zum rt2800lib gibt es auch eine readme.txt, in der das Tuning und Messergebnisse beschrieben sind.
Die genannten Skripte sind nicht einfach direkt ausführbar, weil sie nicht alles automatisch machen können, z. B. nicht feststellen ob der Kernel noch zu compilieren ist oder nicht, und die Kernel-Sourcen Patchen machen sie auch nicht. Daher sollten die Skripte per Copy and Paste ausgeführt werden; sie sind eher eine kurze Anleitung als richtige Skripte.


Zu Kernel-Updates:

Es gibt zwei Sorten Updates: a) Updates der initial Ramdisk und b) Updates der Kernel-Version.
Bei a) ändert sich für das Modul nichts, bei b) ändert sich die Versionsnummer und generell muss in dem Fall auch das Modul neu erstellt werden, zumindest wenn man nicht mehr über das Boot-Menü eine ältere Kernel-Version mit damit funktionierendem Modul auszuwählen wählen kann.
Die Versionsnummer des Kernels entspricht dem Software Release Practice Howto, hat also die Form Major-Nummmer.Minor-Nummer.Release-Nummer und optional noch eine Spezialbezeichnung angehängt. Bleiben Major- und Minor-Nummer bei einem Kernel-Update gleich, so kann man meist problemlos das alte Modul mit dem neuen Kernel verwenden. Hierzu muss man nur das alte Modul an die passende Stelle kopieren, nachdem man vorher ein Backup vom neuen angelegt hat:

cd /lib/modules/`uname -r`/kernel/drivers/net/wireless/rt2x00/
cp -a rt2800lib.ko rt2800lib.`date +%F%H%M`
cp -a -f /usr/src/linux/drivers/net/wireless/rt2x00/rt2800lib.ko .

kopieren. Ob das reicht zeigt sich danach mit dem Entladen des Moduls und das Laden des neuen Moduls:

modprobe -r rt2800usb
modprobe -r rt2800lib
modprobe -r rt2x00usb
modprobe -r rt2x00lib
sleep 1
modprobe rt2800usb
modprobe rt2800lib
modprobe rt2x00usb
modprobe rt2x00lib

Wenn es keine Fehlermeldung gab, ist man fertig. Ansonsten muss man wieder bei Schritt 1 beginnen.
Für das eine Modul müssen auch drei weiter entladen und geladen werden, weil sie voneinander abhängen, wie

lsmod | grep 2800

zeigt. Das Entladen muss man beginnen mit einem Modul, das keine Abhängigkeit hat usw..
Den Prozess der Modul-Erstellung und -Aktualisierung kann man auch automatisieren, mit DKMS (Dynamic Kernel Module Support). Siehe beispielsweise http://wiki.ubuntuusers.de/DKMS. Allerdings zeigte sich damit beim NVIDIA-Treiber das es meistens, aber nicht immer funktioniert. Zudem können die Modul-Modifikationen, zum rt2800lib, nicht immer automatisch übernommen werden, beispielsweise wenn Variablen umbenannt wurden.

Es stellt sich gelegentlich die Frage ob denn das getunte Modul noch das aktuelle ist, also dasjenige welche das der Kernel zum Adapter laden würde, denn durch Updates kann ein neuer Kernel mit neuen Modulen installiert werden und dann ist ein neueres Modul das aktuelle, also das Modul, welches was vom Kernel geladen wird. Beispielsweise wird statt dem getunten Modul

/lib/modules/3.15.0-5-generic/kernel/drivers/net/wireless/rt2x00/rt2800lib.ko

nach einem Update auf Kernel 3.15.0-6 automatisch das neuere

/lib/modules/3.15.0-6-generic/kernel/drivers/net/wireless/rt2x00/rt2800lib.ko

geladen. Um die Frage schnell und auch ohne Laden des Moduls einfach zu beantworten kann man auch modinfo nutzen, denn das zeigt zeigt die Selbstauskunft vom aktuellen Modul. Die zugehörigen Zeilen stehen im Sourcecode meist am Dateiende. Dort kann man beispielsweise dem Text der Beschreibung (MODULE_DESCRIPTION) hinten anfügen ", boosted version". Das kann man auch einfach Automatisieren mit Pipe, grep und mail in einem Boot-Skript, so dass man automatisch darauf hingewiesen dass die getunte Version neu zu erstellen ist. Das Tuning selbst kann man 2014 nicht ganz automatisieren, denn dafür bräuchte man einiges an künstlicher Intelligenz (KI), die vielleicht 2024 verfügbar ist. Bis dahin muss noch ein Mensch diese Arbeit leisten.

Daneben kann man auch das automatische Deinstallieren von Kerneln bei Updates verhindern. Hierzu muss man den Status der betreffenden Pakete auf hold setzen. Dazu muss man als erstes die betreffenden Pakete suchen, mit der Suche nach der Kernel-Versionsnummer, beispielsweise 3.15.0-5, mittels

aptitude search 3.15.0-5

Die hierdurch gefundenen Pakete setzt man dann auf den Status hold:

aptitude hold linux-headers-3.15.0-5 linux-headers-3.15.0-5-generic linux-headers-3.15.0-5-lowlatency linux-image-3.15.0-5-generic linux-image-extra-3.15.0-5-generic linux-signed-image-3.15.0-5-generic

Und eine Übersicht der gehaltenen Pakete erhält man mit:

aptitude search ~ahold

Ansonsten werden beispielsweise unter Ubuntu Utopic Unicorn (development branch) bei Updates automatisch nur die drittneuesten Kernel-Versionen behalten und alle älteren deinstalliert. Das spart zwar Platz, aber dadurch verliert man ältere Kernel. Alte Kernel und Quellen kann man später, nach einem Distributions-Upgrade, nicht einfach erneut installieren, weil die in Repositories zu vorherigen Distributionen liegen. Daher sollte man die erhaltenswwerten Pakete schnell auf Status hold setzen.

Wichtig: Der Status hold ist kein kompletter Schutz, denn ein "apt-get autoremove" schlägt auch einiger solcher Pakete zur Deinstallation vor und dabei es zeigt den Status nicht einmal an!
Dieses Problem zeigte sich beispielsweise mit den Paketen linux-headers-3.16.0-25-lowlatency und linux-image-3.16.0-25-lowlatency. Deshalb sollte man zum Wegräumen veralteter und nicht mehr benötigter Pakete stattdessen "apt-get autoclean" verwenden.



Wozu?

Die Prozedur ist nötig wenn man selber Module entwickelt oder Module ändern möchte.
Beispielsweise ist wegen diverser gesetztlicher Auflagen in verschiedenen Ländern im Modul rt2800lib die Sendeleistung begrenzt, 2014-05 beim Adapter WL0162 (Chipsatz Ralink RT3070L) auf 100 mW - auch dann wenn man als Land eines angibt, in dem 1000 mW erlaubt sind, beispielsweise Bolivien oder Neuseeland. Dies hat aber auch technische Hintergründe wie das die Sendeleistung nur prozentual, also relativ, eingestellt werden kann, aber die gesetzlichen Limits sind absolut, so das Programmierer generell die Leistungseinstellung vorsichtshalber ungeändert lassen oder nur niedrige Werte verwenden, denn nach unten hin gibt es keine gesetzlichen Limits. Nebeneffekte sind das irgendwelche Leistugsangaben von Treiber ausgegeben werden und eine kurze Sendereichweite, mit der Folge das man viele Access Points zwar empfangen kann, aber mangels Sendeleistung kann zu den meisten keine Verbindung aufbauen.
Mit einem Dutzend relativ kleiner Änderungen in rt2800lib.c kann man einfach 100 % Sendeleistung einstellen und das erhöhte bei einem mit einem kleinen Lüfter (Sunon GB0545AFV1-8) aktiv gekühlten WL0162 die gemessene Sendeleistung bei 4,90 V und 23°C von 121 mW = 20.8 dBm auf 555 mW = 27.4 dBm, also rund Faktor fünf und entsprechend 2,5 mal größere Reichweite. Dabei ist die Leistungsangabe vom Treiber, die man beispielsweie mit "iw list" angezeigt bekommt, immer auf 1000 mW = 30 dBm.
Durch das Tuning der Sendeleistung ist die Empfindlichkeit unverändert, aber die Empfangsreichweite ungefähr gleich der Sendereichweite, so das man mit einem WL0162 die allermeisten sichtbaren Access Points auch erreichen kann, d. h. eine Verbindung aufbauen kann. Man kann zwar auch mit WLAN-Boostern die Sendereichweite steigern, aber bei empfindlichen Adaptern wie dem WL0162 empfängt man damit weninger, weil der Booster das empfangene Signal nicht nur verstärkt sonder auch verrauscht. Weil empfindliche Adapter wie der WL0162 nur knapp oberhalb vom thermischen Rauschlimit arbeiten, mit bei 802.11b: 1M -101 dBm und 11M -95 dBm, können Booster deren Empfangsreichweite nicht erhöhen.

Die getunte rt2800lib wirkt nicht nur beim nicht mehr produzierten WL0162 sondern auch vielen anderen Adaptern mit Ralink-Chipsatz, insbesondere mit Chipsatz RT2400, RT2500, RT2570, RT61, RT73, RT2770, RT2870, RT3070 RT3071, RT3072 und RT3572. Beispielse sind ALFA AWUS036NH, AWUS050NH und AWUS051NH und eine längere Liste findet man unter https://wiki.debian.org/rt2800usb#Supported_Devices.

Ob der getunte Treiber aktiv ist, sieht man auch an den eingebauten Kernel-Meldungen (printk), beispielsweise per dmesg.


Regulations-Tuning

Mit dem Treiber-Tuning kann man Details wie die Leistung oder Short Preamble/Long Preamble tunen, aber das ist nur die Hälfte des Tunings. Es gibt nämlich noch diverse Einschränkungen, beispielsweise bezüglich verfügbarer Kanäle und umgesetzt werden die unter Linux meist mittels CRDA: http://wiki.ubuntuusers.de/iw/Reg-Database
http://deckardt.nl/blog/2011/01/20/regulatory-limitations-in-linux-wireless/.
Unter diesen Links ist beschrieben, wie man dort eigene Regionen mit eigenen Regeln hinzufügt.
Um die Änderungen aktiv werden zu lassen kann man wie dort beschrieben Rebooten, aber es geht auch einfacher, da letztlich nur das Modul cfg80211 entladen und neu geladen werden muss. Weil es meist von mehreren anderen Modulen abhängt, muss man zuerst diese entladen, aber die findet man heraus mittels "lsmod | grep cfg80211". Beispielsweise genügt auf meinem Ultrabook und mit einem Adapter mit Realtek-Chipsatz:

modprobe -r rt2800usb
modprobe -r rt2800lib
modprobe -r rt2x00usb
modprobe -r rt2x00lib
modprobe -r wl
modprobe -r cfg80211
modprobe -r lib80211
sleep 1
modprobe rt2800usb
modprobe rt2800lib
modprobe rt2x00usb
modprobe rt2x00lib

Wenn man das öfters braucht, sollte man das in ein Skript eintragen oder als Alias definieren.

Hilfreicht ist das Tuning an den Regulationen nicht nur für mehr Leistung oder Bandbreite sondern auch für weniger, beispielsweise zum Beschränken auf wenige interessante Kanäle, zum Strom Sparen oder zum Reduzieren der Sendereichweite auch gegen unerwünschte Lauscher, nach dem Motto "weniger ist mehr".
Bespielsweise verwende ich um Dual-Band-Adapter auf nur ein Band zu beschränken, was auch beim Scannen/Wardriving hilfreich sein kann, die drei Regionen DF, DG und DH:

# only 2 GHz band
country DF:
    (2000 - 3000 @ 40), (50)

# only 5 GHz band
country DG:
    (4000 - 8000 @ 80), (50)

# only 60 GHz band
country DH:
    # 60 gHz band channels 1-4, ref: Etsi En 302 567
    (57240 - 65880 @ 2160), (50)

Für eine starre Konfiguration kann man noch weiter gehen und sich auf nur einen Kanal beschränken.
Um quasi alles freizuschalten verwendet man mehrere breite Bänder:

# "everything"
country DI:
    (2000 - 2990 @ 40), (50)
    (3000 - 4990 @ 80), (50)
    (5000 - 9990 @ 160), (50)
    (10000 - 99990 @ 2160), (50)

Nutzen kann man davon natürlich nur das, was die Hardware kann und das ist meist nicht viel. Beispielsweise können die in mobilen Geräten (Notebook/Laptop/Tablet etc.) eingebauten Adapter meist nur mit maximal 15 dBm senden und haben häufig keinen Kanal 14. Einige USB-Adapter hingegen haben viele Kanäle, beispielsweise haben der Alfa AWUS050NH wie auch der AWUS051NH 60 Kanäle, wie iw list | grep MHz zeigt (nach Sortierung nach der Frequenz):

    * 2412 MHz [1] (50.0 dBm)
    * 2417 MHz [2] (50.0 dBm)
    * 2422 MHz [3] (50.0 dBm)
    * 2427 MHz [4] (50.0 dBm)
    * 2432 MHz [5] (50.0 dBm)
    * 2437 MHz [6] (50.0 dBm)
    * 2442 MHz [7] (50.0 dBm)
    * 2447 MHz [8] (50.0 dBm)
    * 2452 MHz [9] (50.0 dBm)
    * 2457 MHz [10] (50.0 dBm)
    * 2462 MHz [11] (50.0 dBm)
    * 2467 MHz [12] (50.0 dBm)
    * 2472 MHz [13] (50.0 dBm)
    * 2484 MHz [14] (50.0 dBm)
    * 4920 MHz [184] (50.0 dBm)
    * 4940 MHz [188] (50.0 dBm)
    * 4960 MHz [192] (50.0 dBm)
    * 4980 MHz [196] (50.0 dBm)
    * 5180 MHz [36] (50.0 dBm)
    * 5190 MHz [38] (50.0 dBm)
    * 5200 MHz [40] (50.0 dBm)
    * 5220 MHz [44] (50.0 dBm)
    * 5230 MHz [46] (50.0 dBm)
    * 5240 MHz [48] (50.0 dBm)
    * 5260 MHz [52] (50.0 dBm)
    * 5270 MHz [54] (50.0 dBm)
    * 5280 MHz [56] (50.0 dBm)
    * 5300 MHz [60] (50.0 dBm)
    * 5310 MHz [62] (50.0 dBm)
    * 5320 MHz [64] (50.0 dBm)
    * 5500 MHz [100] (50.0 dBm)
    * 5510 MHz [102] (50.0 dBm)
    * 5520 MHz [104] (50.0 dBm)
    * 5540 MHz [108] (50.0 dBm)
    * 5550 MHz [110] (50.0 dBm)
    * 5560 MHz [112] (50.0 dBm)
    * 5580 MHz [116] (50.0 dBm)
    * 5590 MHz [118] (50.0 dBm)
    * 5600 MHz [120] (50.0 dBm)
    * 5620 MHz [124] (50.0 dBm)
    * 5630 MHz [126] (50.0 dBm)
    * 5640 MHz [128] (50.0 dBm)
    * 5660 MHz [132] (50.0 dBm)
    * 5670 MHz [134] (50.0 dBm)
    * 5680 MHz [136] (50.0 dBm)
    * 5700 MHz [140] (50.0 dBm)
    * 5745 MHz [149] (50.0 dBm)
    * 5755 MHz [151] (50.0 dBm)
    * 5765 MHz [153] (50.0 dBm)
    * 5785 MHz [157] (50.0 dBm)
    * 5795 MHz [159] (50.0 dBm)
    * 5805 MHz [161] (50.0 dBm)
    * 5825 MHz [165] (50.0 dBm)
    * 5835 MHz [167] (50.0 dBm)
    * 5845 MHz [169] (50.0 dBm)
    * 5855 MHz [171] (50.0 dBm)
    * 5865 MHz [173] (50.0 dBm)
    * 6040 MHz [208] (50.0 dBm)
    * 6060 MHz [212] (50.0 dBm)
    * 6080 MHz [216] (50.0 dBm)

Allerdings sind hier die angezeigten 50 dBm (=100 Watt) eine Falschmeldung vom Treiber, denn Messung wie auch Datenblatt zeigen maximal 27 dBm (=500 mW).
Zum Centrino Advanced-N 6235 hingegen bekommt man die korrekten 15 dBm angezeigt sowie Einschränkungen wie beispielsweise "(no IR, radar detection)".
Beim Freischalten von mehr als normalerweise im jeweiligen Land erlaubt ist, sollte man darauf achten das dadurch niemand gestört wird, also Betrieb nur in einer Abschirmkammer, einem abgeschirmten Messaufbau, einem gut abschirmenden Keller oder nur für wenige Sekunden für kurze Tests in den eigenen vier Wänden.

Die Einschränkung bezüglich der Kanäle hat als Nebeneffekt dass ein Scan (iwlist wlan0 scanning) schneller erledigt ist, kürzer dauert. Beispielsweise dauert (Juni 2013 unter Ubuntu) beim Centrino Advanced-N 6235 ein Scan vom 2,4 GHz-Band (13 Kanäle beim 6235) nur 0,55 s, beim 5 GHz-Band (24 Kanäle beim 6235) 2,7 s und bei beiden zusammen (37 Kanäle beim 6235) 3,2 s. Hier zeigt sich das "weniger ist mehr" in der Form das weniger Kanäle zu scannen schneller erledigt ist.


Weiteres Tuning

Eine weitere Schnittstelle zum Modul cfg80211 sind die Dateien in /sys/module/cfg80211, aber 2015-01 zeigen sich dort unter dem aktuellen Ubuntu nur zwei im Unterverzeichnis parameters.

Weitere Tuning-Möglichkeiten kann das Treiber-Modul über seine Optionen liefern, beispielsweise ob Verschlüsselung in Hardware oder Software gemacht wird (Option nohwcrypt:Disable hardware encryption (bool)), denn Hardware Encryption sollte Strom sparen und auch schneller sein. Welche Modul-Optionen es gibt, verrät modinfo ⟨Modulname⟩.

Es kann noch weitere Configurationsmöglichkeiten geben. Beispielsweise kann man beim RTL8192C im Makefile konfigurieren für minimum power saving mode oder maximum power saving mode sowie USB autosuspend (enable/disable). Und in Realtek-Treibern wird über den Parameter CONFIG_82211D festgelegt ob vom Access Point das eingestellte Land übernommen wird (802.11d function), mit dem Nebeneffekt, das die Betreffenden Regularien (Ländereinschränkungen) beim WLAN aktiv werden.

Daneben kann man auch am Linux selbst Tunen, beispielsweise einen Vanilla- (Mailine-)Kernel wählen oder einen Lowlatency-Kernel oder einen Realtime-Kernel. Der Vanilla-Kernel ist der Default-Kernel, also automatisch vorhanden, so das man nur die anderen installieren muss. Unter Ubuntu genügt dafür:

aptitude install linux-image-lowlatency linux-headers-lowlatency linux-lowlatency linux-image-realtime linux-headers-realtime linux-realtime

Allerdings benötigt man für Realtime, also einen Kernel mit PREEMPT_RT, in der /etc/apt/sources.list vorher diese beiden zusätzlichen Zeilen:

deb http://ppa.launchpad.net/abogani/realtime/ubuntu precise main
deb-src http://ppa.launchpad.net/abogani/realtime/ubuntu precise main

Erst danach, und "aptitude update", stehen auch die Realtime-Pakete zur Verfügung.
Und das precise muss man natürlich durch die jeweils verwendete Ubuntu-Version ersetzen.


Links


Mini Howto of WiFi (power) tuning under Linux

WLAN Leistungsmessungen

Sitemap