Trabajo de port de Tailscale a Plan 9
(tailscale.com)- El soporte para Plan 9, que comenzó como un anuncio del Día de los Inocentes, terminó convirtiéndose en un PR real y en cambios al kernel y a Go, hasta llegar al punto en que Tailscale funciona en Plan 9 al 2 de abril de 2025
- No fue solo un problema de compilación con
GOOS=plan9 GOARCH=386; primero aparecieron crashes del runtime y problemas de manejo especial en el compilador dentro del port de Go para Plan 9 - Gracias a cambios de Russ Cox en el kernel de Plan 9 y en el runtime y compilador de Go, también se resolvieron temas de SSE, contexto de punto flotante, tiempo monotónico, DNS y entorno de desarrollo
- Tailscale aprovechó la interfaz de archivos
/netde Plan 9 para integrar una implementación tipo TUN, enrutamiento, Tailscale SSH, MagicDNS y recolección de servicios, aunque algunas partes siguen siendo temporales o incompletas - El alcance validado por ahora se concentra sobre todo en 9legacy y
GOARCH=386; 9front, amd64, exit node y el soporte de Go paranet/netnsrequieren más validación o rediseño
Una broma del Día de los Inocentes terminó en un port real
- Tailscale anunció soporte para Plan 9 el 1 de abril de 2025 y al día siguiente explicó que ese anuncio estaba basado en un trabajo de port que realmente funcionaba
- El trabajo continuó con un PR de Tailscale y varios cambios en Plan 9 y Go
- El enfoque inicial partía de la expectativa de que bastaría con compilar los dos binarios de Go de Tailscale con
GOOS=plan9 GOARCH=386 go install ./cmd/tailscale{,d} - En el primer intento, en agosto de 2023, parte de la compilación avanzó, pero durante la ejecución ocurrieron crashes anómalos
- El port de Plan 9 en Go no era un port de primera clase, así que había regresiones desatendidas
- También es posible que Tailscale estuviera llevando a Go en Plan 9 más al límite que antes
- El port quedó detenido durante todo 2024 y se retomó en marzo de 2025 junto con la idea del Día de los Inocentes
SSE y el soporte de Go para Plan 9
- Las instrucciones SSE, introducidas con Intel Pentium III en 1999, fueron uno de los puntos de partida principales de este trabajo
- El compilador de Go intentaba evitar el uso de SSE en el objetivo Plan 9
- Esto se debía a que el kernel de Plan 9 no guardaba ni restauraba los registros SSE en el note handler
- Como el compilador de Go no puede saber qué código se ejecuta dentro del note handler, intentaba desactivar SSE de forma global
- Ese manejo especial se rompía con frecuencia y llenó al compilador de excepciones para
plan9
- Russ Cox modificó el kernel de Plan 9 para que el note handler manejara el contexto de punto flotante y SIMD
- En 386 se añadió el cambio sys/src/9: allow floating point in note handlers
- En el kernel amd64 9k también aparecieron problemas adicionales, como aliasing del estado FP después de
fork, SIMD en el note handler y pérdida de registros connoted(NCONT)
- Del lado de Go, al avanzar la eliminación del manejo especial en la generación de código para Plan 9,
tailscaledpudo mantenerse en ejecución por más tiempo
IPC y entorno de desarrollo
- Después de eso,
tailscaledempezó a fallar por falta de memoria en lugar de corrupción de stack - En un intento anterior del port a Plan 9, el paquete IPC
safesocketde Tailscale tenía un bug que creaba goroutines sin límite - El problema se resolvió por ahora al cambiar a TCP en localhost
- Encaja menos con el enfoque de Plan 9 de “todo es un archivo”, pero se confirmó que otros servicios de Plan 9 también usan TCP en localhost
- A futuro podría ser mejor montar la LocalAPI usando el paquete srv9p package, que Russ portó a Go
- La implementación actual no puede aplicar autenticación de localhost como en otras plataformas, así que se indica explícitamente que no debe usarse en máquinas Plan 9 compartidas
- El desarrollo inicial se hizo en una VM basada en una imagen de CD de 9legacy, y el ciclo de descargar binarios por HTTP y ejecutarlos era lento
- rsc/plan9, creado por Russ Cox, incluye el código fuente de Plan 9, binarios precompilados y un script
./boot/qemu- La VM de qemu arranca sin disco y usa como sistema de archivos raíz un repositorio Git servido por un servidor 9P en localhost
- Al compartir el sistema de archivos entre la máquina de desarrollo y Plan 9, el tiempo de iteración bajó de minutos a segundos
- qemu también usa virtio, así que va más rápido
Integración de red: TUN, enrutamiento y MagicDNS
- El primer Tailscale funcional usaba un modo de red en espacio de usuario que no dependía del stack de red del kernel
- TCP, UDP, ICMP y demás se procesaban mediante netstack de gVisor
- Para acceder al tailnet desde una máquina Plan 9 había que usar el proxy HTTP/SOCKS5 de
tailscaled - Como casi ningún programa de Plan 9 reconoce variables de entorno como
HTTP_PROXYoALL_PROXY, no era una solución ideal
- La implementación tipo TUN de Plan 9 resultó ser muy simple
- Se abre
/net/ipifc/cloney se lee el número de la nueva interfaz - Al escribir
"bind pkt\n"en el fd de control, aparece una nueva interfaz como/net/ipifc/2/* - Luego se abre
/net/ipifc/2/datapara leer y escribir paquetes IP directamente - No hacen falta
ioctlseparados ni framing por longitud
- Se abre
- La manipulación de la tabla de rutas también se hace mediante el archivo
/net/iproute- Se escribe
"tag tail\n"para etiquetar contaillas rutas que se agreguen después - Se agrega una ruta con un mensaje como
"add 100.64.0.0 /106 100.102.103.104" - Como internamente Plan 9 se centra en IPv6 y trata IPv4 como direcciones IPv6 con mapeo IPv4, el CGNAT
100.64.0.0/10se expresa como/106
- Se escribe
- MagicDNS implicó permitir en Plan 9 el acceso a peers por nombres como
fooofoo.tailnet-name.ts.net- También se discutió interceptar consultas a
/net/dnso/net/cs - Al final, Russ modificó Plan 9 para poder especificar un servidor DNS alternativo para ciertos sufijos DNS
- También se corrigió un problema en el que las consultas DNS quedaban mal almacenadas en caché negativa
- También se discutió interceptar consultas a
Tailscale SSH y recolección de servicios
- Tailscale SSH es un servidor SSH integrado en
tailscaledque autentica con una identidad conocida de Tailscale a partir de la clave WireGuard asociada al paquete y la conexión - Al principio se ejecutó el shell de Plan 9,
/bin/rc, conos/exec.Commandconectando stdin y stdout- El shell arrancaba, pero no funcionaban bien el echo, la navegación ni las interrupciones de procesos
- Russ añadió el ejemplo netshell a 9fans/go
- Este ejemplo se parecía más a un servidor telnet muy inseguro, pero era suficiente para usarlo detrás de Tailscale SSH
- Después de eso, se volvió fácil obtener por SSH el contenido de
/dev/snarfde Plan 9 o hacer cross-compile de pruebas de Go desde una laptop y ejecutarlas por SSH
- También se revisó la función opcional de Tailscale de recolección de servicios para adaptarla a Plan 9
- Se recorre
/proc/NNN/fdpara encontrar procesos que hayan abierto/net/tcp/clone - El QID del fd se compara con
/net/tcp/NNN/{status,local}para verificar si está en escucha y qué puerto usa - El método de calcular el número TCP a partir del QID sigue siendo frágil ante cambios en la implementación del kernel
- Se recorre
Tiempo, demo web y v86
- Hubo casos en que
tailscaledfallaba porque netstack de gVisor reportaba que el tiempo monotónico iba hacia atrás- La implementación de tiempo de Go para Plan 9 estaba usando el wall time como tiempo monotónico
- Si
ntpdatrasaba el reloj, se rompía la suposición de netstack sobre el tiempo monotónico
- Russ añadió tiempo monotónico a
/dev/bintimede Plan 9 y modificó Go para usarlo - Para ejecutar Plan 9 en la web se usó v86
- v86 ejecuta sistemas operativos de 32 bits en WASM y ofrece varios métodos de red
- Esa fue también una de las razones para concentrarse en
GOARCH=386
- Al principio se añadió soporte para el protocolo wsproxy al entorno de simulación de red de Tailscale para enviar tramas Ethernet por un relay websocket
- Funcionaba dentro de un entorno de pruebas integradas que emulaba ARP, DHCP, DNS, NAT, control plane y DERP con netstack de gVisor
- Pero por la ida y vuelta de DHCP, si el relay estaba lejos, el arranque de
rio, la GUI de Plan 9, se volvía lento
- Después también se implementó un servidor WISP, pero no hubo tiempo para llevarlo a producción antes del lanzamiento y se publicó usando la configuración de relay de red por defecto de copy.sh/v86
- La imagen de disco con Tailscale y Plan 9 ocupaba 16 MB, mientras que el binario de Tailscale pesaba 23 MB descomprimido
- Por eso durante el arranque se ve la etapa “gunzip…”
- La imagen de ejemplo está incluida en el perfil 9legacy de
copy.sh/v86
Trabajo pendiente y resultados reales
- El port de Tailscale a Plan 9 por ahora solo se ha probado en 9legacy
- Entre los principales forks de Plan 9 están 9legacy, con cambios mínimos, y 9front, con modificaciones más profundas
- Algunos parches que Russ escribió para 9legacy podrían necesitar portarse a 9front
- El soporte de 64 bits con
GOARCH=amd64todavía necesita validación - No están implementados el soporte para exit node ni para el paquete
net/netnsde Go- Para eso quizá haga falta replantear algo como la forma en que Tailscale se expone a sí mismo como un
/netseparado en Plan 9
- Para eso quizá haga falta replantear algo como la forma en que Tailscale se expone a sí mismo como un
- Este trabajo también mejoró el soporte de Go para Plan 9
- cmd/compile: use FMA on plan9, and drop UseFMA
- runtime: remove nextSampleNoFP from plan9
- cmd/compile, runtime: remove plan9 special case avoiding SSE
- net: fix parsing of interfaces on plan9 without associated devices
- os: guarantee min buffer size for ReadFile reads on /proc-like files
- net: unblock UDP Reads upon Close on plan9, add test
- runtime: fix plan9 monotonic time, crypto randomness
- En particular, al eliminar el manejo especial de Plan 9 en el compilador de Go, el compilador quedó más simple y más fácil de modificar
- Al momento de publicar la demo de v86, una broma del Día de los Inocentes del autor de v86 hacía que incluso la salida de texto VGA se mostrara como si fuera falso neerlandés, pero podía evitarse con el argumento de consulta
&nojoke
1 comentarios
Opiniones de Hacker News
Si tienen alguna pregunta, puedo responderla
Ahora mismo algunas personas estamos hablando de esto en https://meet.google.com/qre-gydb-mkv
Edición: pasó una hora y ya todos se fueron
La publicación anterior del 1 de abril fue https://tailscale.com/blog/tailscale-enterprise-plan-9-suppo...
Que Russ Cox haya llevado esta broma hasta el final es realmente legendario
En la lista de 9fans publicaron algo así para el Día de los Inocentes
Decía que el costo de mantener arquitecturas de computadoras inmaduras como mips, 386, arm, arm64 y amd64 era demasiado alto, así que decidieron enfocarse en arquitecturas más maduras y estables
Esas serían power64 e itanium, por lo que todas las arquitecturas excepto power64 e itanium quedarían congeladas y preservadas, y ascenderían a fin de vida
No como broma: de verdad me gustaría que existiera una versión empresarial de Plan 9
Últimamente escribo la mayoría de mis scripts en
rc; como usamos nix y podemos traerlo automáticamente con dirnev, mis compañeros lo toleran, y ha estado bastante bienrcque el hecho de que puedan ejecutarlosrces esta[1]:“El principio más importante en el diseño de rc es que no es un procesador de macros. La entrada nunca se escanea más de una vez por el código de análisis léxico y sintáctico”
Una vez, en una empresa Unix donde trabajaba, se modificó un script de shell que estaba en ejecución y terminó borrando la mayor parte del disco de trabajo. Por suerte teníamos respaldos diarios en cinta; eso fue hace unos 17 años
[1] https://www.scs.stanford.edu/nyu/04fa/sched/readings/rc.pdf
Si se perdieron la primera publicación y solo quieren probarlo directamente, funciona en esta imagen de v86:
https://copy.sh/v86/?profile=custom&m=768&vram=16&hda.url=ht...
Dentro de la VM pueden iniciar
tailscaledytailscale. La disponibilidad del proxy es limitada, así que puede tardar un poco en aparecer como en líneaEdición: alt funciona como tercer botón. Para iniciar una terminal, mantén presionada alt y haz clic derecho, elige new, suelta alt y redimensiona la ventana de la terminal arrastrando con clic derecho
Hay un webinar en curso (Google Meet) https://ftp.plan9.ts.net/webinar
Me gustó la premisa de la broma, pero mientras más larga se hacía la explicación, de pronto me deprimió
Hay demasiadas cosas rotas y demasiada complejidad. ¿Todo para qué, al final, para crear un túnel de red? Si este trabajo extra en sí hubiera sido la broma, me habría dado risa
Creo que podría quedarme horas hablando con rsc, rob pike y bradfitz, especialmente sobre Plan 9. Claro, sería una pérdida total de su tiempo
Ese sistema operativo es realmente fascinante
Recuerdo que, al inicio de mi carrera, un experto con quien trabajaba se sentaba a mi lado y me mostraba pacientemente cómo hacer las cosas y respondía mis preguntas hasta que yo entendía lo suficiente. Era como enseñarme a nadar aun estando en aguas profundas, y en tres horas sentí que había obtenido una licenciatura en un conocimiento específico; fue uno de los crecimientos más rápidos de mi carrera
No sé C ni conozco Plan 9 lo suficiente como para usarlo productivamente, pero tiene funciones geniales y útiles que quiero conocer y aprender mejor, aunque sea para lamentar que no existan en los tres sistemas operativos principales de hoy
Si tuviera dinero, compraría tiempo para hablar directamente con los tres y ampliar mis conocimientos de Go, y también compraría tiempo de rsc y rob pike para obtener esa comprensión de Plan 9 que siempre quise pero nunca logré conseguir por mi cuenta
Me encanta Plan 9. Tomar muchos de sus principios para crear mi propio sistema operativo es mi proyecto de jubilación y una meta de vida
Edición: ya reservé el nombre “chaos10” para este proyecto. Como SerenityOS, no tendrá un plan
Nunca esperé que fueran a parchear hasta el kernel de Plan 9 para que esto funcionara