1 Punkte von GN⁺ 2025-04-03 | 1 Kommentare | Auf WhatsApp teilen
  • Die Unterstützung für Plan 9 begann als Aprilscherz-Ankündigung, führte aber zu echten PRs sowie Kernel- und Go-Änderungen; Stand 2. April 2025 ist Tailscale unter Plan 9 lauffähig
  • Es ging nicht nur um einen einfachen Build mit GOOS=plan9 GOARCH=386: Im Plan-9-Port von Go traten zunächst Runtime-Crashes und Probleme mit Sonderbehandlungen im Compiler zutage
  • Durch Änderungen von Russ Cox am Plan-9-Kernel sowie an Go-Runtime und -Compiler wurden SSE, Floating-Point-Kontext, monotone Zeit, DNS und die Entwicklungsumgebung aufgeräumt
  • Tailscale nutzt Plan 9s /net-Dateischnittstelle und ergänzt damit eine TUN-ähnliche Implementierung, Routing, Tailscale SSH, MagicDNS und Service-Erfassung; einige Teile sind jedoch provisorisch oder noch unvollständig
  • Der aktuelle Validierungsumfang betrifft vor allem 9legacy und GOARCH=386; 9front, amd64, Exit Nodes und Go-net/netns-Unterstützung benötigen weitere Prüfung oder ein Redesign

Aus einem Aprilscherz wurde eine echte Portierung

  • Tailscale kündigte am 1. April 2025 Plan-9-Unterstützung an und erklärte am nächsten Tag, dass diese Ankündigung auf einer tatsächlich funktionierenden Portierung basierte
  • Die Arbeit mündete in einen Tailscale-PR und mehrere Änderungen an Plan 9 und Go
  • Der ursprüngliche Ansatz begann mit der Erwartung, dass es reichen würde, die beiden Go-Binaries von Tailscale mit GOOS=plan9 GOARCH=386 go install ./cmd/tailscale{,d} zu bauen
  • Beim ersten Versuch im August 2023 ließ sich ein Teil bauen, doch zur Laufzeit kam es zu abnormalen Crashes
    • Der Plan-9-Port von Go war kein First-Class-Port, sodass Regressionen liegen geblieben waren
    • Möglicherweise reizte Tailscale Go unter Plan 9 stärker aus als bisherige Software
  • Die Portierung lag 2024 weitgehend brach und wurde im März 2025 zusammen mit der Aprilscherz-Idee wieder aufgenommen

SSE und Aufräumen der Plan-9-Unterstützung in Go

  • Die 1999 mit dem Intel Pentium III eingeführten SSE-Instruktionen waren einer der wichtigsten Ausgangspunkte dieser Arbeit
  • Der Go-Compiler versuchte, auf dem Plan-9-Target die Nutzung von SSE zu vermeiden
    • Der Plan-9-Kernel speicherte und restaurierte in Note-Handlern keine SSE-Register
    • Der Go-Compiler konnte nicht wissen, welcher Code innerhalb eines Note-Handlers ausgeführt wird, und versuchte daher, SSE global zu deaktivieren
    • Diese Sonderbehandlung ging häufig kaputt, und im Compiler häuften sich plan9-Ausnahmen
  • Russ Cox änderte den Plan-9-Kernel so, dass Note-Handler Floating-Point- und SIMD-Kontext behandeln
  • Auf Go-Seite wurde die Sonderbehandlung bei der Codegenerierung für Plan 9 entfernt, wodurch tailscaled länger laufen konnte

IPC und Entwicklungsumgebung

  • Danach begann tailscaled, nicht mehr wegen Stack-Korruption, sondern wegen Speichermangel abzustürzen
  • Aus einem früheren Plan-9-Portierungsversuch gab es im Tailscale-IPC-Paket safesocket einen Bug, der unbegrenzt Goroutines erzeugte
  • Das Problem wurde zunächst gelöst, indem auf localhost-TCP umgestellt wurde
    • Das passt weniger gut zu Plan 9s Ansatz „alles ist eine Datei“, aber es wurde bestätigt, dass auch andere Plan-9-Dienste localhost-TCP verwenden
    • Künftig könnte es besser sein, die LocalAPI mit dem von Russ nach Go portierten srv9p package umzusetzen
    • Die aktuelle Implementierung kann anders als auf anderen Plattformen keine localhost-Authentifizierung hinzufügen; daher wird ausdrücklich davon abgeraten, sie auf gemeinsam genutzten Plan-9-Maschinen zu verwenden
  • Die frühe Entwicklung erfolgte in einer VM auf Basis eines 9legacy-CD-Images; der wiederholte Ablauf, Binaries per HTTP herunterzuladen und auszuführen, war langsam
  • rsc/plan9 von Russ Cox enthält den Plan-9-Quellcode, vorkompilierte Binaries und ein ./boot/qemu-Skript
    • Die qemu-VM bootet ohne Disk und verwendet ein von einem localhost-9P-Server bereitgestelltes Git-Repository als Root-Dateisystem
    • Durch das Teilen des Dateisystems zwischen Entwicklungsmaschine und Plan 9 sank die Iterationszeit von Minuten auf Sekunden
    • qemu nutzt außerdem virtio und wurde dadurch schneller

Netzwerkintegration: TUN, Routing, MagicDNS

  • Das erste funktionierende Tailscale lief im Userspace-Networking-Modus, der den Kernel-Netzwerkstack nicht verwendet
    • TCP, UDP, ICMP usw. werden über gVisors netstack verarbeitet
    • Um von einer Plan-9-Maschine aus auf ein Tailnet zuzugreifen, musste man den HTTP/SOCKS5-Proxy von tailscaled verwenden
    • Das war nicht ideal, da kaum Plan-9-Programme die Umgebungsvariablen HTTP_PROXY oder ALL_PROXY verstehen
  • Die TUN-ähnliche Implementierung von Plan 9 war sehr einfach
    • /net/ipifc/clone öffnen und die neue Interface-Nummer lesen
    • Wenn man "bind pkt\n" in das Control-fd schreibt, entsteht ein neues Interface wie /net/ipifc/2/*
    • /net/ipifc/2/data öffnen und IP-Pakete unverändert lesen und schreiben
    • Es sind weder ein separates ioctl noch Längen-Framing nötig
  • Auch die Manipulation der Routing-Tabelle erfolgt über die Datei /net/iproute
    • Mit "tag tail\n" erhalten anschließend hinzugefügte Routen das Tag tail
    • Routen werden über Nachrichten wie "add 100.64.0.0 /106 100.102.103.104" hinzugefügt
    • Da Plan 9 intern IPv6-zentriert ist und IPv4 als IPv4-mapped IPv6-Adressen behandelt, wird CGNAT 100.64.0.0/10 als /106 dargestellt
  • MagicDNS bestand unter Plan 9 darin, Peers unter Namen wie foo oder foo.tailnet-name.ts.net erreichbar zu machen
    • Es wurde auch diskutiert, Abfragen an /net/dns oder /net/cs abzufangen
    • Am Ende änderte Russ Plan 9 so, dass sich für bestimmte DNS-Suffixe alternative DNS-Server angeben lassen
    • Außerdem wurde ein Problem behoben, bei dem DNS-Abfragen fälschlich negativ gecacht wurden

Tailscale SSH und Service-Erfassung

  • Tailscale SSH ist ein in tailscaled integrierter SSH-Server, der über den mit dem Paket verbundenen WireGuard-Schlüssel gegen eine bekannte Tailscale-Identity authentifiziert
  • Zunächst wurde die Plan-9-Shell /bin/rc mit os/exec.Command gestartet und stdin/stdout verbunden
    • Die Shell lief, aber Echo, Navigation, Prozess-Interrupts und Ähnliches funktionierten nicht korrekt
  • Russ fügte das netshell example zu 9fans/go hinzu
    • Dieses Beispiel ähnelte einem sehr unsicheren Telnet-Server, war aber ausreichend, um es hinter Tailscale SSH zu hängen
    • Danach wurde es einfacher, per SSH den Inhalt von Plan 9s /dev/snarf abzurufen oder Go-Tests auf dem Laptop zu cross-kompilieren und anschließend per SSH auszuführen
  • Auch die optionale Tailscale-Funktion Service-Erfassung wurde für Plan 9 geprüft
    • Es wird /proc/NNN/fd durchlaufen, um Prozesse zu finden, die /net/tcp/clone geöffnet haben
    • Die QID des fd wird mit /net/tcp/NNN/{status,local} abgeglichen, um Listening-Status und Port zu ermitteln
    • Die Methode, die TCP-Nummer aus der QID zu berechnen, ist anfällig gegenüber Änderungen an der Kernel-Implementierung und bleibt daher ein unbefriedigender Punkt

Zeit, Web-Demo, v86

  • In einigen Fällen stürzte tailscaled ab, weil gVisors netstack meldete, dass die monotone Zeit rückwärts gelaufen sei
    • Die Plan-9-Zeitimplementierung von Go verwendete Wall Time als monotone Zeit
    • Wenn ntpd die Uhr zurückstellte, brach die Annahme von netstack über monotone Zeit
  • Russ fügte Plan 9s /dev/bintime monotone Zeit hinzu und änderte Go so, dass diese verwendet wird
  • Zum Ausführen von Plan 9 im Web wird v86 genutzt
    • v86 führt 32-Bit-Betriebssysteme in WASM aus und bietet mehrere Netzwerkmodi
    • Das war einer der Gründe, sich auf GOARCH=386 zu konzentrieren
  • Anfangs wurde Tailscales Netzwerksimulationsumgebung um wsproxy protocol support ergänzt, um Ethernet-Frames über ein WebSocket-Relay zu senden
    • Das läuft in einer Integrationstestumgebung, die ARP, DHCP, DNS, NAT, Control Plane, DERP usw. mit gVisor netstack nachbildet
    • Wegen der DHCP-Roundtrips wurde der Start der Plan-9-GUI rio jedoch langsam, wenn das Relay weit entfernt war
  • Später wurde auch ein WISP-Server implementiert, doch vor der Produktionsreife fehlte die Zeit; veröffentlicht wurde daher mit der Standard-Netzwerk-Relay-Konfiguration von copy.sh/v86
  • Das Disk-Image mit Tailscale und Plan 9 war 16 MB groß, das Tailscale-Binary nach dem Entpacken 23 MB
    • Deshalb sieht man beim Booten die Phase „gunzip…“
    • Das Beispiel-Image ist im 9legacy-Profil von copy.sh/v86 enthalten

Offene Arbeiten und tatsächliche Ergebnisse

1 Kommentare

 
GN⁺ 2025-04-03
Hacker-News-Kommentare
  • Wenn es Fragen gibt, kann ich sie beantworten.
    Ein paar Leute sprechen gerade unter https://meet.google.com/qre-gydb-mkv darüber.
    Edit: Nach einer Stunde sind alle gegangen.
    Der frühere Blogpost vom 1. April war https://tailscale.com/blog/tailscale-enterprise-plan-9-suppo...

    • Ich habe noch nie ein Plan-9-System eingerichtet; kann ich damit erreichen, dass Distributed-System-Kommunikation über mein Tailnet läuft?
  • Dass Russ Cox diesen Witz wirklich bis zum Ende durchgezogen hat, ist absolut legendär.

    • Jemand sollte Russ überzeugen, dass es unglaublich lustig wäre, einen vollwertigen Webbrowser in Plan 9 einzubauen.
  • Auf der 9fans-Liste gab es zum Aprilscherz Folgendes:
    Wegen der zu hohen Wartungskosten für unausgereifte Computerarchitekturen wie mips, 386, arm, arm64 und amd64 habe man beschlossen, sich auf reifere und stabilere Architekturen zu konzentrieren.
    Gemeint seien power64 und itanium; daher würden alle Architekturen außer power64 und itanium eingefroren, archiviert und zum End of Life befördert.

  • Kein Witz: Ich wünschte, es gäbe wirklich eine Enterprise-Version von Plan 9.
    Die meisten meiner Skripte schreibe ich inzwischen in rc; weil wir nix nutzen und sie mit direnv automatisch heranziehen können, tolerieren meine Kollegen das, und es war ziemlich gut.

    • Ich würde mir weniger Sorgen darüber machen, ob andere rc-Skripte ausführen können, als darüber, ob sie sie lesen und ändern können.
    • Ein Vorteil von rc ist dieser[1]:
      „Das wichtigste Prinzip beim Design von rc ist, dass es kein Makroprozessor ist. Eingaben werden vom lexikalischen und syntaktischen Analysecode niemals mehr als einmal gescannt.“
      Bei einer Unix-Firma, bei der ich früher gearbeitet habe, wurde einmal ein laufendes Shell-Skript geändert, wodurch ein Großteil der Arbeitsplatten gelöscht wurde. Zum Glück hatten wir tägliche Backups auf Band; das war vor etwa 17 Jahren.
      [1] https://www.scs.stanford.edu/nyu/04fa/sched/readings/rc.pdf
    • Kannst du genauer erklären, was du dir unter „Enterprise Plan 9“ konkret erhoffst?
  • Falls du den ersten Beitrag verpasst hast und es einfach selbst ausprobieren willst: Es läuft in diesem v86-Image:
    https://copy.sh/v86/?profile=custom&m=768&vram=16&hda.url=ht...
    In der VM kannst du tailscaled und tailscale starten. Wegen eingeschränkter Proxy-Verfügbarkeit kann es eine Weile dauern, bis sie online ist.
    Edit: Alt fungiert als dritte Maustaste. Um ein Terminal zu starten: Alt gedrückt halten und rechtsklicken, „new“ auswählen, Alt loslassen und per Rechtsklick-Ziehen die Größe des Terminalfensters festlegen.

  • Das Webinar läuft gerade (Google Meet): https://ftp.plan9.ts.net/webinar

    • Für alle, die interessiert gewesen wären: Es ist gerade zu Ende gegangen.
  • Die Prämisse des Witzes gefiel mir, aber je länger die Erklärung wurde, desto deprimierter wurde ich plötzlich.
    Es ist so viel kaputt und die Komplexität ist so groß. Und wofür am Ende – um einen Netzwerktunnel zu bauen? Wenn dieser Zusatzaufwand selbst der Witz gewesen wäre, wäre es lustig gewesen.

    • Für neue Arbeit war auf der Plan-9-Seite etwas Aufwand nötig, aber die eigentliche Tailscale-Implementierung war deutlich weniger Arbeit als bei anderen Unix-Systemen.
    • Klingt, als sei durch diese Arbeit auch der Go-Compiler besser geworden, weil weniger Plan-9-Sonderbehandlung im Code nötig ist.
  • Ich glaube, ich könnte rsc, Rob Pike und bradfitz stundenlang festhalten und mit ihnen besonders über Plan 9 reden. Natürlich wäre das eine völlige Verschwendung ihrer Zeit.
    Dieses Betriebssystem ist wirklich faszinierend.
    Ich erinnere mich an einen Experten, mit dem ich früh in meiner Karriere zusammenarbeitete: Er saß neben mir, zeigte mir geduldig Vorgehensweisen und beantwortete Fragen, bis ich genug verstanden hatte. Es war, als würde er mich ins tiefe Wasser werfen und zugleich dafür sorgen, dass ich schwimmen konnte; in drei Stunden fühlte es sich an, als hätte ich in einem Spezialgebiet einen Bachelorabschluss gemacht – einer der schnellsten Wachstumsschübe meiner Karriere.
    Ich kann weder C noch weiß ich genug, um Plan 9 produktiv zu nutzen, aber es gibt dort großartige und nützliche Funktionen, über die ich mehr wissen und lernen möchte – schon allein, um bedauern zu können, dass sie in den heutigen drei großen Betriebssystemen fehlen.
    Wenn ich das Geld hätte, würde ich mir Zeit mit allen dreien kaufen, um mein Go-Wissen zu erweitern, und zusätzlich Zeit mit rsc und Rob Pike, um endlich das Plan-9-Verständnis zu bekommen, das ich mir immer gewünscht, aber nie selbst erarbeitet habe.

  • Ich mag Plan 9 wirklich sehr. Viele seiner Prinzipien zu übernehmen und daraus mein eigenes Betriebssystem zu bauen, ist mein Ruhestandsprojekt und Lebensziel.
    Edit: Den Namen „chaos10“ habe ich für dieses Projekt reserviert. Denn wie bei SerenityOS wird es wohl keinen Plan geben.

  • Ich hätte überhaupt nicht erwartet, dass sie sogar den Plan-9-Kernel patchen würden, um das zum Laufen zu bringen.

    • Warum nicht? Offenbar hat so etwas noch niemand ernsthaft versucht, also scheint der fehlende Arbeitsaufwand vergleichsweise gering gewesen zu sein :)