1 ポイント 投稿者 GN⁺ 2025-04-03 | 1件のコメント | WhatsAppで共有
  • エイプリルフール発表として始まった Plan 9 対応は、実際の PR とカーネル・Go の修正へとつながり、2025 年 4 月 2 日時点で Tailscale が Plan 9 上で動作する状態にまで到達した
  • 単なる GOOS=plan9 GOARCH=386 のビルド問題ではなく、Go の Plan 9 ポートで ランタイムクラッシュとコンパイラの特殊処理の問題が先に明らかになった
  • Russ Cox による Plan 9 カーネルおよび Go ランタイム・コンパイラの修正により、SSE、浮動小数点コンテキスト、単調時刻、DNS、開発環境の問題があわせて整理された
  • Tailscale は Plan 9 の /net ファイルインターフェイスを活用して TUN 風の実装、ルーティング、Tailscale SSH、MagicDNS、サービス収集を組み込んだが、一部は暫定実装または未完成である
  • 現在の検証範囲は主に 9legacyGOARCH=386 であり、9front・amd64・exit node・Go の net/netns 対応には追加検証や再設計が必要である

エイプリルフールの冗談が実際の移植へつながる

  • Tailscale は 2025 年 4 月 1 日に Plan 9 対応を発表し、翌日、この発表が実際に動作する移植作業をもとにしていたという背景を公開した
  • 作業は Tailscale PR と、複数の Plan 9・Go 修正へとつながった
  • 初期のアプローチは、Tailscale の Go バイナリ 2 つを GOOS=plan9 GOARCH=386 go install ./cmd/tailscale{,d} でビルドすればよいだろうという期待から始まった
  • 2023 年 8 月の最初の試みでは一部のビルドは進んだが、実行中に異常クラッシュが発生した
    • Go の Plan 9 ポートが first-class port ではなかったため、リグレッションが放置された状態だった
    • Tailscale が Plan 9 上で、従来よりも Go を強く使い込んだ可能性もある
  • 移植作業は 2024 年を通じて止まっていたが、2025 年 3 月にエイプリルフールのアイデアとともに再開された

SSE と Go の Plan 9 対応の整理

  • 1999 年に Intel Pentium III に導入された SSE 命令が、今回の作業の主な出発点の一つだった
  • Go コンパイラは Plan 9 ターゲットで SSE の使用を避けようとしていた
    • Plan 9 カーネルが note handler で SSE レジスタを保存・復元していなかったためである
    • Go コンパイラは、どのコードが note handler 内で実行されるのか分からないため、SSE をグローバルに無効化しようとしていた
    • この特殊処理はたびたび壊れ、コンパイラの各所に plan9 例外が増えていった
  • Russ Cox は、Plan 9 カーネルが note handler で浮動小数点・SIMD コンテキストを扱うよう修正した
    • 386 側には sys/src/9: allow floating point in note handlers の修正が入った
    • amd64 9k カーネルでは、fork 後の FP 状態の aliasing、note handler の SIMD、noted(NCONT) のレジスタ喪失など、追加の問題が見つかった
  • Go 側では Plan 9 コード生成の特殊処理削除 が進み、tailscaled がより長く実行できるようになった

IPC と開発環境

  • その後 tailscaled は、スタック破損ではなく メモリ不足でクラッシュし始めた
  • 以前の Plan 9 移植の試みで、Tailscale の safesocket IPC パッケージに goroutine を無限に作るバグがあった
  • ひとまず localhost TCP を使うよう変更することで問題は解決した
    • Plan 9 の「すべてがファイル」という方式にはあまり合わないが、他の Plan 9 サービスも localhost TCP を使っていることを確認した
    • 将来的には Russ が Go に移植した srv9p package を使って LocalAPI を載せる方式の方がよいかもしれない
    • 現在の実装は他のプラットフォームのような localhost 認証を付けられないため、共有 Plan 9 マシンでは使わないよう明記されている
  • 初期開発は 9legacy CD イメージベースの VM で行われ、バイナリを HTTP でダウンロードして実行する反復作業は遅かった
  • Russ Cox が作成した rsc/plan9 は、Plan 9 ソース、事前コンパイル済みバイナリ、./boot/qemu スクリプトを含む
    • qemu VM はディスクなしで起動し、localhost の 9P サーバが提供する Git リポジトリをルートファイルシステムとして使う
    • 開発マシンと Plan 9 ファイルシステムを共有することで、反復時間が分単位から秒単位に短縮された
    • qemu は virtio も使うため、さらに高速になった

ネットワーク統合: TUN、ルーティング、MagicDNS

  • 最初に動作した Tailscale は、カーネルのネットワークスタックを使わない ユーザー空間ネットワーキングモードだった
    • TCP、UDP、ICMP などは gVisor の netstack を通じて処理された
    • Plan 9 マシンから tailnet へアクセスするには、tailscaled の HTTP/SOCKS5 プロキシを使う必要があった
    • Plan 9 プログラムのうち HTTP_PROXYALL_PROXY 環境変数を認識するものはほとんどなく、理想的ではなかった
  • Plan 9 の TUN 風実装は非常に単純だった
    • /net/ipifc/clone を開き、新しいインターフェイス番号を読む
    • control fd に "bind pkt\n" を書き込むと、/net/ipifc/2/* のような新しいインターフェイスが作られる
    • /net/ipifc/2/data を開き、IP パケットをそのまま読み書きする
    • 別途 ioctl や長さフレーミングは不要である
  • ルーティングテーブルの操作も /net/iproute ファイルを通じて行われる
    • "tag tail\n" を書き込んで、以後追加される route に tail タグを付ける
    • "add 100.64.0.0 /106 100.102.103.104" のようなメッセージで route を追加する
    • Plan 9 内部は IPv6 中心で、IPv4 を IPv4-mapped IPv6 アドレスとして扱うため、CGNAT 100.64.0.0/10/106 のように表現される
  • MagicDNS は Plan 9 で peer に foo または foo.tailnet-name.ts.net のような名前でアクセスできるようにする作業だった
    • /net/dns/net/cs の問い合わせを横取りする方法も議論された
    • 最終的に Russ が、特定の DNS suffix に対して代替 DNS サーバを指定できるよう Plan 9 を修正した
    • DNS 問い合わせが誤って negative cache される問題も 修正 された

Tailscale SSH とサービス収集

  • Tailscale SSH は tailscaled 内蔵の SSH サーバで、パケットに結び付いた WireGuard キーを通じて、既知の Tailscale identity として認証する
  • 最初は Plan 9 のシェルである /bin/rcos/exec.Command で実行し、stdin/stdout を接続した
    • シェルは実行されたが、echo、ナビゲーション、プロセス interrupt などが正しく動作しなかった
  • Russ は netshell example9fans/go に追加した
    • この例は非常に安全でない telnet サーバに近かったが、Tailscale SSH の背後に接続するには十分だった
    • その後、SSH で Plan 9 の /dev/snarf の内容を取得したり、ノート PC で Go テストを cross-compile した後に SSH で実行したりしやすくなった
  • Tailscale の任意機能である サービス収集も Plan 9 向けに検討された
    • /proc/NNN/fd を巡回して /net/tcp/clone を開いているプロセスを探す
    • fd の QID を /net/tcp/NNN/{status,local} と照合して、listening 状態かどうかとポートを確認する
    • QID から TCP 番号を計算する方式はカーネル実装の変化に弱く、惜しい部分として残っている

時間、Web デモ、v86

  • gVisor netstack が単調時刻(monotonic time)が戻ったと報告し、tailscaled がクラッシュする場合があった
    • Go の Plan 9 時刻実装が、単調時刻として wall time を使っていた
    • ntpd が時計を戻すと、netstack の単調時刻に関する前提が壊れる
  • Russ は Plan 9 の /dev/bintime単調時刻を追加し、Go がそれを使うよう 修正 した
  • Web 上で Plan 9 を実行するには v86 が使われた
    • v86 は WASM で 32 ビット OS を実行し、複数のネットワーク方式を提供する
    • これも GOARCH=386 に集中した理由の一つだった
  • 当初は Ethernet フレームを websocket relay へ送るため、Tailscale のネットワークシミュレーション環境に wsproxy protocol support を追加した
    • ARP、DHCP、DNS、NAT、control plane、DERP などを gVisor netstack で模倣する統合テスト環境で動作する
    • しかし DHCP の往復のため、relay が遠いと Plan 9 GUI である rio の起動が遅くなる
  • その後 WISP サーバも実装したが、本番化前に時間が足りず、copy.sh/v86 のデフォルトネットワーク relay 設定でリリースした
  • Tailscale と Plan 9 を入れたディスクイメージは 16MB で、Tailscale バイナリは展開後 23MB だった
    • 起動時に “gunzip…” 段階が見える理由はここにある
    • サンプルイメージは copy.sh/v86 の 9legacy プロファイルに含まれる

残された作業と実際の成果

1件のコメント

 
GN⁺ 2025-04-03
Hacker News のコメント
  • 気になることがあれば答えられる
    今、何人かが https://meet.google.com/qre-gydb-mkv でこの話をしている
    追記: 1時間たって全員退出した
    以前の 4月1日のブログ記事https://tailscale.com/blog/tailscale-enterprise-plan-9-suppo... だった

    • Plan 9 システムを一度も設定したことがないんだけど、これを使えば分散システムの通信を自分の Tailnet 経由で流せるようになるのかな?
  • Russ Cox がこの冗談を最後までやり切ったのは本当に伝説的

    • 誰か Russ を説得して、Plan 9 に完全な Web ブラウザを入れたらめちゃくちゃ面白いと伝えてほしい
  • 9fans のリストには、エイプリルフール用にこんなのが投稿されていた
    mips、386、arm、arm64、amd64 といった未成熟なコンピュータアーキテクチャの保守コストが大きすぎるため、より成熟して安定したアーキテクチャに集中することにした、という内容
    対象は power64 と itanium で、したがって power64 と itanium を除くすべてのアーキテクチャは凍結・保存され、EOL に昇格されるとのこと

  • 冗談ではなく、本当に Plan 9 Enterprise 版があったらいいのにと思う
    最近はスクリプトのほとんどを rc で書いているけど、うちは nix を使っていて dirnev で自動的に取り込めるので、同僚たちも目をつぶってくれているし、かなり良かった

    • 他の人が rc スクリプトを実行できるかより、それを読んで修正できるかを心配すると思う
    • rc の利点の一つはこれ[1]:
      「rc の設計で最も重要な原則は、マクロ処理器ではないという点だ。入力は字句・構文解析コードで決して2回以上スキャンされない」
      以前働いていた Unix 企業で、実行中のシェルスクリプトが修正されたせいで作業ディスクの大半を消したことがある。幸い日次バックアップをテープに保管していたし、およそ17年前の話だった
      [1] https://www.scs.stanford.edu/nyu/04fa/sched/readings/rc.pdf
    • Enterprise Plan 9」に具体的に何を期待しているのか、もう少し説明してもらえる?
  • 最初の記事を見逃していて、とにかく自分で試してみたいなら、この v86 イメージで動く:
    https://copy.sh/v86/?profile=custom&m=768&vram=16&hda.url=ht...
    VM 内で tailscaledtailscale を起動できる。プロキシの可用性が限られているため、オンラインになるまで少し時間がかかる場合がある
    追記: alt が第3ボタンとして機能する。ターミナルを起動するには、alt を押したまま右クリックして new を選び、alt から手を離して右クリックドラッグでターミナルウィンドウのサイズを調整すればよい

  • ウェビナーが進行中(Google Meet) https://ftp.plan9.ts.net/webinar

    • 関心があった人向けに言うと、たった今終わった
  • 冗談の前提は気に入ったけど、説明が長くなるほど急に気が滅入ってきた
    壊れているものが多すぎるし、複雑さも大きすぎる。結局何のためなのか、ネットワークトンネルを1つ作るため? この追加作業自体が冗談だったなら笑えたと思う

    • 新しい作業をするには Plan 9 側の作業が少し必要だったけど、実際の Tailscale 実装は他の Unix よりずっと作業量が少なかった
    • この作業のおかげで Go コンパイラも良くなったように聞こえる。コード内の Plan 9 特別扱いが減ったから
  • rsc、rob pike、bradfitz とは、特に Plan 9 の話で何時間でも捕まえて話していられそうだ。もちろん彼らの時間を完全に無駄にすることになるけど
    あのオペレーティングシステムは本当に魅力的だ
    キャリア初期に一緒に働いていた専門家が隣に座って、私が十分理解するまで辛抱強くやり方を見せ、質問に答えてくれたことを思い出す。深い水に落ちても泳げるようにしてくれるような感じで、3時間で特定分野の学士号を1つ取ったような、キャリアの中でも最速の成長の一つだった
    C も知らないし、Plan 9 を生産的に使えるほど知っているわけでもないけれど、現在の主要3大OSにはないことを惜しむためだけでも、もっと知って学びたい素晴らしく有用な機能がある
    お金があるなら、Go の知識を広げるために3人全員と直接話す時間を買い、ずっと望んでいたのに自力では得られなかった Plan 9 の理解のために rsc と rob pike の時間も買いたい

  • Plan 9 が本当に好きだ。その原則をたくさん取り入れて自分の OS を作るのが、引退後のプロジェクトであり人生の目標
    追記: このプロジェクト名は「chaos10」で予約してある。SerenityOS みたいに計画はないだろうから

  • これを動かすために Plan 9 カーネルまでパッチするとはまったく予想していなかった

    • なぜそうしないと? こんなことを誰も真面目にやったことがなかったのは明らかだから、抜けていた作業量は比較的少なかったように見える :)