Trabalho de port do Tailscale para o Plan 9
(tailscale.com)- O suporte ao Plan 9, iniciado como um anúncio de 1º de abril, acabou levando a um PR real e a correções no kernel e no Go; em 2 de abril de 2025, chegou ao ponto em que o Tailscale funciona no Plan 9
- Não foi apenas uma questão de compilar com
GOOS=plan9 GOARCH=386: primeiro vieram à tona crashes no runtime e problemas de tratamento especial no compilador no port do Go para Plan 9 - Com correções de Russ Cox no kernel do Plan 9 e no runtime e compilador do Go, problemas de SSE, contexto de ponto flutuante, tempo monotônico, DNS e ambiente de desenvolvimento foram resolvidos em conjunto
- O Tailscale aproveitou a interface de arquivos
/netdo Plan 9 para adicionar uma implementação semelhante a TUN, roteamento, Tailscale SSH, MagicDNS e coleta de serviços, embora algumas partes sejam provisórias ou ainda incompletas - A validação atual cobre principalmente 9legacy e
GOARCH=386; 9front, amd64, exit node e suporte anet/netnsdo Go exigem validação adicional ou redesenho
Uma brincadeira de 1º de abril virou um port real
- A Tailscale anunciou suporte ao Plan 9 em 1º de abril de 2025 e, no dia seguinte, revelou que o anúncio se baseava em um trabalho de port realmente funcional
- O trabalho resultou em um PR da Tailscale e em várias correções no Plan 9 e no Go
- A abordagem inicial partiu da expectativa de que bastaria compilar os dois binários Go da Tailscale com
GOOS=plan9 GOARCH=386 go install ./cmd/tailscale{,d} - Na primeira tentativa, em agosto de 2023, parte da compilação avançou, mas ocorreram crashes anormais durante a execução
- O port para Plan 9 do Go não era um port de primeira classe, então regressões haviam sido deixadas de lado
- Também é possível que a Tailscale tenha forçado o Go no Plan 9 mais do que usos anteriores
- O port ficou parado ao longo de 2024 e foi retomado em março de 2025, junto com a ideia de 1º de abril
SSE e a organização do suporte do Go ao Plan 9
- As instruções SSE, introduzidas no Intel Pentium III em 1999, foram um dos principais pontos de partida deste trabalho
- O compilador Go tentava evitar o uso de SSE no alvo Plan 9
- Isso acontecia porque o kernel do Plan 9 não salvava nem restaurava registradores SSE no note handler
- Como o compilador Go não conseguia saber que código era executado dentro do note handler, ele tentava desativar SSE globalmente
- Esse tratamento especial quebrava com frequência, e as exceções para
plan9se multiplicaram pelo compilador
- Russ Cox modificou o kernel do Plan 9 para lidar com contexto de ponto flutuante e SIMD no note handler
- No lado 386, entrou a correção sys/src/9: allow floating point in note handlers
- No kernel amd64 9k, foram encontrados problemas adicionais, como aliasing de estado FP após fork, SIMD no note handler e perda de registradores em
noted(NCONT)
- No lado do Go, a remoção do tratamento especial na geração de código para Plan 9 fez com que o
tailscaledpudesse rodar por mais tempo
IPC e ambiente de desenvolvimento
- Depois disso, o
tailscaledpassou a crashar por falta de memória, em vez de corrupção de pilha - Havia, em uma tentativa anterior de portar para Plan 9, um bug no pacote IPC
safesocketda Tailscale que criava goroutines infinitamente - O problema foi resolvido, por ora, trocando para TCP em localhost
- Isso combina menos com o modelo “tudo é arquivo” do Plan 9, mas foi confirmado que outros serviços do Plan 9 também usam TCP em localhost
- No futuro, pode ser melhor colocar a LocalAPI sobre o pacote srv9p, que Russ portou para Go
- A implementação atual não consegue adicionar autenticação em localhost como em outras plataformas, então fica explícito que ela não deve ser usada em máquinas Plan 9 compartilhadas
- O desenvolvimento inicial foi feito em uma VM baseada na imagem de CD do 9legacy, e o ciclo de baixar binários por HTTP e executá-los era lento
- O rsc/plan9, criado por Russ Cox, inclui o código-fonte do Plan 9, binários pré-compilados e o script
./boot/qemu- A VM qemu inicializa sem disco e usa como sistema de arquivos raiz um repositório Git servido por um servidor 9P em localhost
- Ao compartilhar o sistema de arquivos do Plan 9 com a máquina de desenvolvimento, o tempo de iteração caiu de minutos para segundos
- O qemu também usa virtio, ficando ainda mais rápido
Integração de rede: TUN, roteamento e MagicDNS
- O primeiro Tailscale que funcionou estava no modo de rede em espaço de usuário, sem usar a pilha de rede do kernel
- TCP, UDP, ICMP etc. eram tratados pelo netstack do gVisor
- Para acessar a tailnet a partir de uma máquina Plan 9, era preciso usar o proxy HTTP/SOCKS5 do
tailscaled - Isso não era ideal, pois quase nenhum programa do Plan 9 reconhece as variáveis de ambiente
HTTP_PROXYouALL_PROXY
- A implementação semelhante a TUN no Plan 9 era muito simples
- Abre-se
/net/ipifc/clonee lê-se o número da nova interface - Ao escrever
"bind pkt\n"no fd de controle, surge uma nova interface como/net/ipifc/2/* - Abre-se
/net/ipifc/2/datapara ler e escrever pacotes IP diretamente - Não é necessário nenhum ioctl separado nem framing de comprimento
- Abre-se
- A manipulação da tabela de roteamento também é feita pelo arquivo
/net/iproute- Escreve-se
"tag tail\n"para anexar a tagtailàs rotas adicionadas dali em diante - Rotas são adicionadas com mensagens como
"add 100.64.0.0 /106 100.102.103.104" - Como o interior do Plan 9 é centrado em IPv6 e trata IPv4 como endereços IPv6 mapeados para IPv4, o CGNAT
100.64.0.0/10é representado como/106
- Escreve-se
- O MagicDNS consistia em permitir que, no Plan 9, peers fossem acessados por nomes como
foooufoo.tailnet-name.ts.net- Também foram discutidas formas de interceptar consultas a
/net/dnsou/net/cs - No fim, Russ modificou o Plan 9 para permitir especificar um servidor DNS alternativo para um sufixo DNS específico
- Um problema em que consultas DNS eram colocadas incorretamente em cache negativo também foi corrigido
- Também foram discutidas formas de interceptar consultas a
Tailscale SSH e coleta de serviços
- O Tailscale SSH é um servidor SSH embutido no
tailscaled, que autentica com uma identidade Tailscale conhecida por meio da chave WireGuard associada ao pacote - No começo, ele executava o shell do Plan 9,
/bin/rc, comos/exec.Commande conectava stdin/stdout- O shell executava, mas echo, navegação e interrupção de processos não funcionavam corretamente
- Russ adicionou o exemplo netshell ao 9fans/go
- Esse exemplo era quase um servidor telnet muito inseguro, mas era suficiente para ficar atrás do Tailscale SSH
- Depois disso, ficou mais fácil obter o conteúdo de
/dev/snarfdo Plan 9 via SSH ou cross-compilar testes Go no notebook e executá-los via SSH
- O recurso opcional da Tailscale de coleta de serviços também foi analisado para o Plan 9
- Ele percorre
/proc/NNN/fdpara encontrar processos que abriram/net/tcp/clone - Compara o QID do fd com
/net/tcp/NNN/{status,local}para verificar se está em listening e qual é a porta - O método de calcular o número TCP a partir do QID é frágil diante de mudanças na implementação do kernel, o que ficou como um ponto insatisfatório
- Ele percorre
Tempo, demo web e v86
- Houve casos em que o
tailscaledcrashava porque o netstack do gVisor informava que o tempo monotônico havia andado para trás- A implementação de tempo do Go para Plan 9 usava wall time como tempo monotônico
- Quando o ntpd ajustava o relógio para trás, a suposição de tempo monotônico do netstack quebrava
- Russ adicionou tempo monotônico a
/dev/bintimedo Plan 9 e corrigiu o Go para usá-lo - Para executar o Plan 9 na web, foi usado o v86
- O v86 executa sistemas operacionais de 32 bits em WASM e oferece vários modos de rede
- Esse também foi um dos motivos para focar em
GOARCH=386
- No início, para enviar frames Ethernet por um relay websocket, foi adicionado suporte ao protocolo wsproxy ao ambiente de simulação de rede da Tailscale
- Ele funciona em um ambiente de teste integrado que simula ARP, DHCP, DNS, NAT, control plane, DERP etc. com o netstack do gVisor
- Porém, por causa das idas e vindas do DHCP, se o relay estivesse longe, a inicialização da GUI
riodo Plan 9 ficava lenta
- Depois também foi implementado um servidor WISP, mas faltou tempo para colocá-lo em produção, então o lançamento saiu com a configuração padrão de relay de rede do copy.sh/v86
- A imagem de disco com Tailscale e Plan 9 tinha 16 MB, e o binário da Tailscale tinha 23 MB após descompactado
- É por isso que a etapa “gunzip…” aparece durante o boot
- A imagem de exemplo está incluída no perfil 9legacy do
copy.sh/v86
Trabalho restante e resultados práticos
- No momento, o port da Tailscale para Plan 9 foi testado apenas no 9legacy
- Entre os principais forks do Plan 9 estão o 9legacy, mais minimalista, e o 9front, mais modificado
- Alguns patches que Russ escreveu para o 9legacy talvez precisem ser portados para o 9front
- O suporte de 64 bits com
GOARCH=amd64ainda precisa ser validado - O suporte a exit node e ao pacote
net/netnsdo Go não foi implementado- Para isso, talvez seja necessário reconsiderar uma abordagem em que a Tailscale se exponha como uma
/netseparada no Plan 9
- Para isso, talvez seja necessário reconsiderar uma abordagem em que a Tailscale se exponha como uma
- Este trabalho também melhorou o suporte do Go ao 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
- Em especial, remover o tratamento especial para Plan 9 do compilador Go deixou o compilador mais simples e mais fácil de corrigir
- No momento da publicação da demo em v86, havia um problema causado por uma brincadeira de 1º de abril do autor do v86, que fazia até a saída de texto VGA aparecer como um falso neerlandês, mas isso podia ser evitado com o argumento de query
&nojoke
1 comentários
Comentários do Hacker News
Se alguém tiver curiosidade, posso responder perguntas
Tem algumas pessoas conversando sobre isso agora em https://meet.google.com/qre-gydb-mkv
Edit: depois de uma hora, todo mundo saiu
O post de blog de 1º de abril anterior era https://tailscale.com/blog/tailscale-enterprise-plan-9-suppo...
É realmente lendário que Russ Cox tenha levado essa piada até o fim
Na lista 9fans apareceu isso como brincadeira de 1º de abril
Dizia que o custo de manutenção de arquiteturas de computador imaturas como mips, 386, arm, arm64 e amd64 estava alto demais, então decidiram focar em arquiteturas mais maduras e estáveis
Essas arquiteturas seriam power64 e itanium, e portanto todas as arquiteturas exceto power64 e itanium seriam congeladas, preservadas e promovidas a fim de vida útil
Sem brincadeira, eu adoraria se existisse uma versão enterprise do Plan 9 de verdade
Hoje em dia escrevo a maioria dos meus scripts em
rc, e como usamos nix e podemos empurrar isso automaticamente com dirnev, meus colegas estão relevando, e tem sido bem bomrce mais com se elas conseguem ler e modificar esses scriptsrcé esta[1]:“O princípio mais importante do projeto do rc é que ele não é um processador de macros. A entrada nunca é examinada mais de uma vez pelo código de análise léxica e sintática”
Numa empresa Unix onde trabalhei antigamente, uma vez editaram um script de shell enquanto ele estava em execução e isso apagou a maior parte do disco de trabalho. Felizmente guardávamos backups diários em fita, e isso foi há uns 17 anos
[1] https://www.scs.stanford.edu/nyu/04fa/sched/readings/rc.pdf
Caso tenha deixado passar no post original e só queira testar por conta própria, funciona nesta imagem v86:
https://copy.sh/v86/?profile=custom&m=768&vram=16&hda.url=ht...
Dentro da VM, dá para iniciar
tailscaledetailscale. A disponibilidade de proxy é limitada, então pode demorar um pouco até ficar onlineEdit: alt funciona como o terceiro botão. Para abrir um terminal, segure alt e clique com o botão direito, escolha new, solte alt e ajuste o tamanho da janela do terminal arrastando com o botão direito
O webinar está acontecendo (Google Meet) https://ftp.plan9.ts.net/webinar
Gostei da premissa da piada, mas conforme a explicação foi ficando mais longa, de repente bateu uma tristeza
Tem coisa demais quebrada e complexidade demais. No fim, para quê, para criar um único túnel de rede? Se esse trabalho extra em si fosse a piada, teria sido engraçado
Acho que eu conseguiria passar horas conversando com rsc, rob pike e bradfitz especialmente sobre Plan 9. Claro, estaria desperdiçando completamente o tempo deles
Esse sistema operacional é realmente fascinante
Lembro de um especialista com quem trabalhei no começo da carreira sentado ao meu lado, me mostrando pacientemente como fazer as coisas e respondendo minhas perguntas até eu entender o suficiente. Era o tipo de coisa que te ensina a nadar mesmo te jogando na parte funda, e em três horas parecia que eu tinha ganho um diploma numa área específica de conhecimento — um dos crescimentos mais rápidos da minha carreira
Eu nem sei C nem conheço Plan 9 o bastante para usá-lo de forma produtiva, mas há recursos legais e úteis que eu gostaria de conhecer e aprender nem que seja só para sentir falta deles nos três principais sistemas operacionais de hoje
Se eu tivesse dinheiro, pagaria para ter tempo presencial com os três para ampliar meu conhecimento de Go, e também compraria tempo do rsc e do rob pike para ter a compreensão de Plan 9 que sempre quis, mas nunca consegui por conta própria
Plan 9 é bom demais. Meu projeto de aposentadoria e objetivo de vida é criar meu próprio sistema operacional pegando muitos dos princípios dele
Edit: já reservei o nome “chaos10” para esse projeto. Não vai ter plano nenhum, tipo SerenityOS
Eu realmente não esperava que fossem até o ponto de aplicar patch no kernel do Plan 9 para fazer isso funcionar