Aus Linux-Magazin 11/2018

Kernel-Bonding vs. Libteam – welche Lösung ist besser?

© Ion Chiosea, 123 RF

Wenn Performance oder Verfügbarkeit einer Netzwerkkarte nicht ausreichen, nimmt man einfach zwei – unter Linux gibt es dafür verschiedene Implementierungen. Dieser Artikel stellt den Kernel-Oldie Ifenslave und das jüngere Libteam einander gegenüber.

Eine Überraschung für Menschen, die zum ersten Mal ein Rechenzentrum von innen sehen, ist die große Anzahl von LAN-Ports eines durchschnittlichen Servers: Praktisch kein Server kommt mit nur einer Netzwerkschnittstelle aus. Das hat verschiedene Gründe.

Denkbar ist etwa, dass der Anwender mehrere Netzwerkschnittstellen einsetzt, um die Redundanz zu erhöhen. In einem solchen Setup ist der Server über verschiedene Netzwerkports mit getrennten Switches verbunden, sodass der Ausfall eines Netzwerkgeräts nicht dazu führt, dass der Server offline ist.

In einem anderen Fall bündelt der Admin Ports, um die Bandbreite zu verdoppeln. Auch lassen sich die Ziele Redundanz und Performance kombinieren. Dafür braucht es allerdings schon mindestens vier Netzwerkports, und wegen Murphys Law sollten zwei der Ports obendrein auf einer anderen Netzwerkkarte beheimatet sein als die anderen beiden. Schließlich ist es nicht auszuschließen, dass die Netzwerkkarte selbst den Geist aufgibt oder der PCI-Bus, in dem sie steckt (Abbildung 1).

Abbildung 1: Netzwerkkarten mit mehreren Ports zu Redundanz- oder Performance-Zwecken sind im Rechenzentrum eher die Regel als die Ausnahme.

Abbildung 1: Netzwerkkarten mit mehreren Ports zu Redundanz- oder Performance-Zwecken sind im Rechenzentrum eher die Regel als die Ausnahme.

Ganz gleich wie viele Netzwerkschnittstellen ein Server hat und wie der Admin sie kombiniert – mit der Hardware alleine ist es nicht getan. Denn damit aus mehreren Netzwerkkarten eine echte Failover-Lösung oder eine fette Datenkanone wird, muss auch das Betriebssystem des Hosts wissen, dass die jeweiligen Geräte im Tandem unterwegs sind.

Wer sich mit diesem Problem unter Linux konfrontiert sieht, greift zumeist zum Bondingtreiber im Kernel und administriert diesen mit »ifenslave« auf der Kommandozeile. Das geschieht häufig ohne viel Nachdenken, weil die allermeisten Linux-Distributionen eine vollständige Ifenslave-Integration haben, die direkt aus der Netzwerkkonfiguration des jeweiligen Systems heraus gesteuert wird. Wegen dieser Integration ist vielen Admins gar nicht bewusst, dass es zum klassischen Bonding unter Linux durchaus Alternativen gibt.

Alternativen existieren

Eine davon ist die Libteam [1], die sich ebenfalls um das Zusammenschalten von Netzwerkkarten in Linux-Systemen kümmert. Im Gegensatz zum Bonding-Ansatz mit »ifenslave« ist Libteam ausschließlich im Userspace beheimatet und kommt fast ohne Kernel-Unterstützung aus. Vermarktet wird sie von ihrem Hauptentwickler Jirí Pírko als leichtfüßige Alternative zum schweren und alten Code im Linux-Kernel – wobei alt und erprobt ja bekanntlich nicht zwangsläufig auch schlecht und behäbig heißen muss.

Höchste Zeit also, die beiden Kontrahenten in einem Duell direkt gegeneinander antreten zu lassen. Dabei geht es weniger um die konkrete Performance – die war im Test durchaus vergleichbar und am Limit dessen, was die Hardware zu liefern imstande war. Vielmehr steht die Frage im Vordergrund, welche Funktionen beide Ansätze unterstützen und wo sie sich voneinander unterscheiden.

Bonding? Teaming?

Bevor es allerdings zur Sache geht, steht noch eine kurze Klärung der im Artikel verwendeten Begrifflichkeiten auf dem Plan. Im Linux-Kontext reden die Admins üblicherweise von Bonding, wenn sie das Zusammenschalten vieler Netzwerkschnittstellen für bessere Performance oder mehr Redundanz meinen. Der Begriff Teaming findet sich allerdings ebenfalls in diversen Dokumenten. Mal kommt er synonym zu Bonding vor, mal ist ausführlich erläutert, was Bonding und Teaming voneinander unterscheidet, etwa bei Red Hat [2]. Wieder andere halten die Begriffe lediglich für Beschreibungen derselben Technik im Kontext verschiedener Betriebssysteme.

Die deutschsprachige Wikipedia unterstützt dann auch dieses Argument und verortet Bonding im Linux-Umfeld, während Teaming eher im Novell- und Windows-Umfeld vorkommt. Dieser Artikel verwendet jedenfalls Bonding und Teaming synonym. Wo hier also einer der Begriffe auftaucht, wäre der jeweils andere ebenso gut gewesen.

Die Verfügbarkeit

Schon ganz zu Anfang stellt sich dem Admin die Frage, welche Form des Bonding er auf seinen Systemen mit möglichst wenigen Verrenkungen zum Laufen bekommt. Hier liegt der Bondingtreiber des Kernels ganz klar vorn, denn der ist eben Bestandteil von Linux und mithin in jeder aktuellen Linux-Distribution automatisch enthalten. Obendrein ist er in die Netzwerkverwaltung der jeweiligen Systeme unmittelbar integriert und lässt sich etwa über entsprechende Konfigurationswerkzeuge wie Yast oder Kickstart ohne Weiteres konfigurieren.

Auf Desktops kommt dies noch nicht so sehr zum Tragen, denn bei den gängigen Distributionen wie Fedora und Open Suse gehören Pakete für Libteam zum Lieferumfang. Auch stört es nicht, wenn die Netzwerkkonfiguration zwischenzeitlich händisch anzupassen ist.

Doch das natürliche Habitat von Bonding sind die Server. Auf denen laufen in aller Regel aber nicht Fedora oder Open Suse, sondern RHEL, Centos, SLES oder eine andere Enterprise-Distribution. Denen liegen zwar in der Regel auch mehr oder minder aktuelle Pakete von Libteam bei, doch so reibungslos wie die Konfiguration der Bonding-Interfaces mittels Systemwerkzeug geht das Setup hier nicht vonstatten.

Der Punkt in Sachen Bequemlichkeit geht also ganz klar aufs Konto des klassischen, im Kernel beheimateten Bondingtreibers (Abbildung 2). Immerhin: Auf RHEL-Systemen ist es kein Problem, die Libteam mit den Werkzeugen des Systems zu konfigurieren, denn letztlich ist Team eine Erfindung aus dem Hause Red Hat (Abbildung 3).

Abbildung 2: Der Bondingtreiber mit »ifenslave« lässt sich auf beinahe jedem Linux unmittelbar mit Bordmitteln konfigurieren.

Abbildung 2: Der Bondingtreiber mit »ifenslave« lässt sich auf beinahe jedem Linux unmittelbar mit Bordmitteln konfigurieren.


Abbildung 3: Zumindest auf Fedora- und Red-Hat-Systemen gibt es auch für Libteam eine grafische Konfigurationsoption.

Abbildung 3: Zumindest auf Fedora- und Red-Hat-Systemen gibt es auch für Libteam eine grafische Konfigurationsoption.

Userspace bei Libteam

In der zweiten Runde des Bonding-Schaulaufens steht die Architektur der zwei Probanden auf dem Prüfstand. Wie sind der Bondingtreiber und Libteam unter der Haube konzipiert? Ergeben sich daraus offensichtlich Vorteile für die eine oder andere Lösung? Den Anfang macht zur Abwechslung Libteam.

Bei der Libteam fällt sofort auf, dass sie deutlich jüngeren Datums ist als der im Linux-Kernel vorhandene Bondingtreiber. Die Entwicklung der Bibliothek durch Hauptentwickler Pírko begann im Jahr 2011. Die Libteam ist auf Github veröffentlicht und steht unter der GNU LGPL, entspricht also den Kriterien freier Software.

Libteam unterteilt sich in drei Komponenten: In die eigentliche Libteam, also eine Bibliothek, die verschiedene Funktionen bereitstellt, in Teamd sowie den Team-Netzwerktreiber. Der ist seit Linux 3.3 Bestandteil des Linux-Kernels und deshalb wie der Bondingtreiber auf jedem aktuellen Linux-System zu finden. Komplementär dazu ist Teamd ein Daemon, der auf den Systemen mit Bonding nach Team-Methode laufen muss, damit das Teaming funktioniert.

Teamd und Libteam verzichten so weit wie möglich auf Funktionen im Kernel und bewegen sich fast ausschließlich im Userspace. Die einzige Aufgabe des Kernelmoduls besteht darin, Pakete so schnell wie möglich zu empfangen und zu versenden – der Teil lässt sich im Kernel offenbar am effizientesten umsetzen. Der strikte Fokus auf das Userland ist einfach eine architektonische Entscheidung des Autors.

Übrigens sicher nicht, weil Jirí Pírko zur Kernelentwicklung nicht in der Lage wäre. Tatsächlich hat er die Entwicklung des Linux-Kernels in den vergangenen Jahren immer wieder mit diversen Patches unterstützt. Für seine Team-Implementation hat er bewusst auf den Userspace gesetzt und sich aus dem Kernelspace so weit wie möglich herausgehalten.

Praktisch: Teamd mit der Libteam im Rücken ist modular aufgebaut. So trägt Teamd für die Netlink-Kommunikation mit dem Team-Modul im Kernel die Verantwortung. Die eigentliche Umsetzung der Teaming-Funktionalität, also die verschiedenen Standard-Bonding-Modi, implementiert Teamd allerdings in Form von ladbaren Modulen.

Das Broadcast-Modul implementiert etwa einen Modus, bei dem Linux alle Pakete über alle verfügbaren Ports sendet. Wer stattdessen das Round-Robin-Modul lädt, bekommt Load Balancing auf Basis des Round-Robin-Prinzips. Activebackup implementiert stattdessen klassisches Failover-Bonding, falls mal eine Netzwerkkomponente den Geist aufgibt (Abbildung 4).

Abbildung 4: Prinzipiell funktioniert Libteam ähnlich wie Bonding.

Abbildung 4: Prinzipiell funktioniert Libteam ähnlich wie Bonding.

Die große Flexibilität im Userland gerät Teamd zum Vorteil. Möchte ein Unternehmen einen Bonding-Modus nutzen, den Teamd noch nicht unterstützt, kann es mit relativ geringem Aufwand auf Basis des Teaming-API von Teamd das entsprechende Modul selbst verfassen. Der Autor ermuntert die Anwender dazu ganz ausdrücklich und hält fest, dass Teamd ein Community-Produkt ist und gemeinschaftlich aktiv entwickelt wird.

Kontrastprogramm bei Bonding

Die Art der Implementierung des Bondingtreibers in Linux ist das exakte Gegenteil des Libteam-Ansatzes. Seit über 20 Jahren gehört »bonding.ko« zum Linux-Kernel und die gesamte Funktionalität des Treibers ist im Kernelspace implementiert. Nur die Konfiguration von Bonding-Geräten ist per Userspace und mit »ifenslave« zu erledigen – doch das Programm kommuniziert per Netlink mit dem Linux-Kernel, um diesem die vom Admin für das System vorgesehene Bonding-Konfiguration mitzuteilen.

Mit Fug und Recht lässt sich »bonding.ko« deshalb als Kerneltreiber von altem Schlage sowie als klassische Implementierung eines Linux-Treibers bezeichnen. Frei nach dem Motto: Was der Kernel tun kann, soll er bitte auch tun.

Aus Admin-Sicht kann das ein echter Nachteil sein: Wer ein Feature nutzen möchte, das der Bondingtreiber im Kernel schlicht nicht hat, beginnt er im schlimmsten Falle selbst am Kernel herumzuschrauben. Denn ein Modul-API wie bei Teamd sucht man beim Bonding-Kerneltreiber vergebens. Und so geht der Punkt für Eleganz der Architektur sowie für die Erweiterbarkeit des Designs eindeutig an Teamd.

Das leidige Thema Konfiguration

Eine zentrale Frage aus Sicht der Admins ist, wie sich die Bonding- oder auch Teaming-Lösung konfigurieren lässt und wie die praktische Administration im Alltag funktioniert. Weiter oben hat der Artikel bereits festgestellt, dass insbesondere »bonding.ko« tief in den Kernel integriert ist und Support für Bonding deshalb auf den gängigen Distributionen zum Standardlieferumfang gehört.

Das bedeutet aber nicht, dass die Konfiguration automatisch auch intuitiv, einfach oder leicht verständlich wäre. Wer sich in einem frisch installierten Centos-System schon mal ausgesperrt hat, indem er eine falsche Bonding-Konfiguration in Betrieb nahm, die anschließend nur per BMC-Interface wieder zu korrigieren war, kennt das Problem.

Und wie bereits bei der Architektur gilt auch in Sachen Konfiguration und Handhabung, dass sich Libteam und Bonding fundamental unterscheiden. Da ist auf der einen Seite der Bondingtreiber des Kernels, der aus dem Userland zwingend per »ifenslave« zu bearbeiten ist. Viel intuitiver als dieses Werkzeug ist die Konfiguration bei Centos & Co. generell nicht, und nicht sonderlich viele Admins werden ohne Dokumentation in der Lage sein, die nötigen Konfigurationsdateien in Centos so anzupassen, dass am Ende eine funktionierende Bonding-Konfiguration herauskommt.

Auch Ubuntu und Debian sowie SLES stellen sich hier allerdings nicht viel schlauer an. Ganz in Teufels Küche kommt der Admin, wenn er die Bondingmodule nicht mit den Standard-Parametern betreiben will, sondern modifizierte Werte etwa für die MII-Link-Monitoring-Frequenz angeben möchte. Im schlimmsten Fall hilft nur ein »modinfo« auf das Bondingmodul, um den nötigen Parameter zu finden – kombiniert mit der Systemdokumentation, um zu erfahren, wo man den Parameter denn reinschreiben muss, damit der Bondingtreiber ihn tatsächlich auch nutzt.

In Summe ist die User-Experience bei der Konfiguration von Bonding in Linux also in etwa auf dem Standard von vor 20 Jahren, was im Wesentlichen daran liegt, dass sie vor etwa 20 Jahren entstanden ist.

Konfiguration per Json bei Teamd

Ganz anders geht da Teamd ans Werk. Hier hinterlegt der Administrator die Konfiguration des Dienstes in Form einer Json-Datei im Ordner »/etc«, der tatsächliche Pfad kann sich je nach Distribution allerdings ändern. In seine »teamd.conf« schreibt der Admin alles, was Teamd wissen muss, um die Team-Geräte nach dem eigenen Start anzulegen.

Die Parameter wie etwa der vom User gewünschte Teaming-Modus oder der gewünschte ARP-Monitoring-Modus lassen sich samt und sonders pro Gerät in »teamd.conf« bestimmen. Für eben jene Datei gibt es sogar eine sehr schmucke Manpage (»man 5 teamd.conf«), in der alle relevanten Parameter im Detail samt den jeweiligen Standardwerten erläutert sind (Abbildung 5).

Abbildung 5: Teamd konfiguriert der Admin per Konfigurationsdatei &ndash; es entf&auml;llt das manuelle Basteln, wie man es von &raquo;<em class="replaceable">bonding.ko</em>&laquo; her kennt.

Abbildung 5: Teamd konfiguriert der Admin per Konfigurationsdatei – es entfällt das manuelle Basteln, wie man es von »bonding.ko« her kennt.

Konfiguriert der Admin seine Team-Geräte auf diese Weise, ist das beinahe schon langweilig: Vorbei die Zeiten, in denen ein Neustart der Netzwerkkonfiguration stets mit dem inhärenten Risiko verbunden war, sich selbst aus dem System auszusperren. Die Teamd-Konfiguration im Json-Format ist gut strukturiert, mit verständlichen Keywords ausgestattet und obendrein vorzüglich dokumentiert. Auch dieser Punkt geht deshalb ganz klar an Libteam und Teamd, sodass es nun 2:1 steht.

Die Grundfunktionen – solides Handwerk

Freilich ist die schönste Architektur und die tollste Konfiguration völlig nutzlos, wenn der Admin die jeweilige Lösung aus Mangel an Funktionalität gar nicht verwenden kann. So stellt sich die Frage, ob und inwiefern die grundlegenden Bondingmodi implementiert sind und mit welchen Funktionen die Entwickler ihre Schützlinge jeweils ausstatten. Den Anfang macht hier Teamd.

Teamd kennt ab Werk fünf Bondingmodi: Neben Broadcast, Round Robin sowie dem Aktiv-Backup-Modus stehen noch ein LACP-Treiber sowie ein Load-Balance-Treiber zur Verfügung. Ersterer bietet den Support für das Link Aggregation Control Protocol (LACP nach IEEE 802.3ad). Letzterer setzt auf den Berkeley Packet Filter auf und kommt mit verschiedenen Optionen daher, die der Admin per Konfigurationsdatei festlegt. So besteht unter anderem auch die Möglichkeit, den Hash-Algorithmus, der beim Load-Balancer-Treiber für Teamd zum Einsatz kommt, mit spezifischen Parametern gezielt zu beeinflussen.

Konfigurationsoptionen sind übrigens nicht auf den Load-Balancer-Treiber beschränkt. Jeder der Treiber, der sich per »teamd.conf« auswählen lässt, kommt mit spezifischen Optionen daher – die samt und sonders zuverlässig in der Manpage zu »teamd.conf« auch aufgeführt sind. Zum Teil geben die Treiberoptionen Aufschluss über bestimmte Features, die in Teamd zur Verfügung stehen. LACP lässt sich etwa auch per Round-Robin-Treiber verwenden, insbesondere im Hinblick auf das Monitoring der Ethernet-Links ist Teamd dem Pendant im Linux-Kernel einige Schritte voraus.

Hausmannskost beim Bondingtreiber

Der Bondingtreiber lässt es in Sachen Basisfunktionalität hingegen etwas ruhiger angehen. Damit kein falscher Eindruck entsteht: Die grundlegenden Features für den Betrieb von Bonding-Setups unterstützt »bonding.ko« wie Teamd und vergleichbar gut. Wer also LACP oder Bonding per Broadcast, per Round-Robin-Modus oder im Aktiv-Passiv-Modus braucht, der wird mit Bonding in Linux so glücklich wie mit Teamd.

Besonders beim Versenden von Daten setzen Bonding wie Teamd auf eine Hashfunktion, um das richtige Device zu ermitteln. Einfluss auf diese Hashfunktion kann der Admin beim Einsatz von »bonding.ko« jedoch nicht nehmen, denn sie ist nicht per BPF implementiert, sondern tief im Bondingtreiber vergraben. LACP für Bonding im Round-Robin-Modus gehört ebenfalls auf die Liste der Dinge, auf die der Admin beim Einsatz des Kerneltreibers verzichten muss.

Während man beim Kernel-Bonding für einzelne Netzwerkports eines Bond nur eine Priorität definieren kann, bietet Teamd hier unterschiedliche Priority-Konfigurationen und eine Stickiness-Einstellung, die quasi-dynamisch arbeitet. Ebenfalls nicht zum Lieferumfang gehört es beim Bondingtreiber, die Monitoringkonfiguration pro Port zu konfigurieren – vorgenommene Einstellungen gelten hier stets für jeden Port des gesamten Verbundes.

Einig sind Teamd und Bonding sich hingegen wieder, wenn es um VLANs geht: Die gehören bei beiden Lösungen zum Lieferumfang und werden unproblematisch unterstützt. Dasselbe gilt für die Anbindung an den Network Manager, der auf vielen Systemen die Netzwerkkonfiguration abwickelt: Sowohl der Bondingtreiber im Kernel als auch Teamd können direkt mit ihm sprechen.

Vergleicht man die Basisfunktionen der Lösungen miteinander, ergibt sich ein eindeutiges Bild: Bei den Basics leisten sich beide Lösungen praktisch keine Schwächen. Doch wie bereits zuvor ist es Libteam, das an verschiedenen Stellen pfiffige Zusatzfunktionen nutzt, die bei »bonding.ko« fehlen.

Das perfekte Beispiel ist die auf BPF basierte Load-Balancing-Funktionalität, die dem Bondingtreiber komplett abgeht. Wohl nicht zuletzt, weil es den BPF noch gar nicht gab, als der Bondingtreiber Einzug in den Linux-Kernel hielt. Auch bei diesem Kriterium geht der Punkt also an Libteam – es steht damit 3:1.

Performance

Ein spannender Aspekt beim Vergleich verschiedener Lösungen für dasselbe Problem ist das Thema Performance. Hier bestätigte sich im Test allerdings exakt das, was Red Hat als treibende Kraft hinter dem Teamingtreiber auf der eigenen Seite auch schon verkündet hat: Teamd und Bonding nehmen sich in Sachen Performance kaum etwas.

Die von Red Hat vorgelegten Zahlen [3] legen etwa nahe, dass der Teamd-Trunk zwar mehr Durchsatz liefert und diese Stärke insbesondere bei 1-KByte-Paketen ausspielt. Doch wirklich signifikante Performance-Unterschiede zum Kerneltreiber ergeben sich an dieser Stelle nicht. Am Ende bekommen beide Kontrahenten jeweils einen Punkt: 4:2.

Die durchschnittliche Latenz der beiden Geräte im direkten Vergleich ist in den Zahlen von Red Hat sogar identisch – was nicht ganz unwichtig ist, wenn eine Applikation auf dem Server laufen soll, die besonders Latenz-anfällig ist.

Nur bei Libteam

Mit Blick auf die letzte Disziplin ist es fast schon unanständig, Teamd und Bonding überhaupt miteinander zu vergleichen. Denn natürlich ist Teamd die jüngere Lösung und diverse Werkzeuge, die Libteam nativ unterstützt, kennt der alte Haudegen Bonding im Kernel erst gar nicht. Doch ist es die deutlich erkennbare Liebe zum Detail, die bei der Nutzung von Libteam ein ums andere Mal staunen lässt.

So hat Teamd etwa eine Anbindung an den Systembus D-Bus, über die es sich umfassend überwachen und von anderen D-Bus-Anwendungen auch modifizieren lässt. Weitere Konnektivität zu anderen Diensten erhält Teamd über die eigene Zero-MQ-Schnittstelle. Zero MQ ist ein Messagebus im Stile von Rabbit MQ oder Qpid, kommt aber ohne eigene Serverkomponente daher und verhält sich eher wie eine Art Bibliothek.

In dieser Kategorie geht Teamd zugegebenermaßen außer Konkurrenz an den Start, sodass es keinen weiteren Punkt für das Produkt gibt.

Fazit

Der unmittelbare Vergleich von Bondingtreiber und Teamd wirkt wie der Kampf zweier Generationen. Auf der einen Seite steht der etablierte Treiber im Kernel, der fest mit diesem verwoben ist und der dem Admin suggeriert, dass er hier wisse, was er bekommt. Bis heute hält sich in den Köpfen vieler Admins krampfhaft das Vorurteil, dass nur im Kernel implementierte Funktionalität der wahre Deal sei und Dinge im Kernelspace automatisch besser seien als jene, die “nur” im Userspace laufen.

Dieses Ammenmärchen haben mittlerweile jedoch diverse Werkzeuge und Tools klar widerlegt, und auch für Teamd gilt: Dass diese Lösung lediglich ein kleines Kernelmodul braucht, das darauf spezialisiert ist, im Kernel nur Pakete hin und her zu bewegen, wirkt sich in keiner Weise negativ aus.

Sehr positiv hingegen kommen die vielen Funktionen und Features zum Tragen, die in Teamd implementiert sind. Grundsätzlich gilt, dass der Bondingtreiber keine Funktion beherrscht, die Libteam und Teamd nicht auch können – der Umkehrschluss ist allerdings nicht zulässig. Eine intuitive und sehr leicht verständliche Konfigurationsdatei im Json-Format vermisst der Admin bei Bonding per Kerneltreiber ebenso schmerzlich wie die Möglichkeit, Bondinggeräte per D-Bus-Schnittstelle zu überwachen.

Punkten kann Bonding hingegen unmittelbar in Sachen Verfügbarkeit, denn sowohl »ifenslave« als auch »bonding.ko« finden sich in jedem Linux. Die Werkzeuge, die für Teamd nötig sind, muss der Admin hingegen nachinstallieren – was sich dank einer umfassenden Versorgung mit entsprechenden Paketen bei vielen Distributionen aber als kein Problem herausstellt.

Pfiffige Dreingaben wie die Möglichkeit, Teamd direkt mit Zero MQ sprechen zu lassen, runden das Gesamtbild ab. Wer bisher also auf Bonding setzt, sollte testen und sich Teamd und Libteam zumindest mal genau ansehen.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben