docs: record the stress findings and the 16-gate suite
caveats §13 documents the capacity ceiling the stress test found: the workqueue backlog grows with the offered rate and OOM-panics a 1 GB guest above ~1 Gbit/s. Gate count, suite status and the doc indexes move to 16/16 green.
This commit is contained in:
1 parent
928322edf7
commit
0a8ba69340
15 files changed
+191
-30
No files matched your search
@@ -14,8 +14,9 @@ de `/dev/pf`.
|
||||
|---|---|
|
||||
| [guide.md](guide.md) | Arquitetura em uma página: componentes, caminho de dados, plano de controle, milestones |
|
||||
| [install.md](install.md) | Receita de apply/build/install (kernel, módulo, ferramentas) |
|
||||
| [debian13.md](debian13.md) | Implementação completa do zero no Debian 13 (trixie): preparar host, compilar kernel/módulo/ferramentas, lab libvirt, teste de stress |
|
||||
| [build.md](build.md) | Pipeline de build em detalhe: fetch → vendorize → kernel → módulo → pfctl |
|
||||
| [vm-lab.md](vm-lab.md) | O lab de validação em libvirt: topologia, recriar/rodar, o que cada um dos 15 gates prova |
|
||||
| [vm-lab.md](vm-lab.md) | O lab de validação em libvirt: topologia, recriar/rodar, o que cada um dos 16 gates prova |
|
||||
| [feature-matrix.md](feature-matrix.md) | Status por feature: VERIFIED-in-VM / VERIFIED-offline / COMPILES-untested / NOT-ENABLED |
|
||||
| [pf-guide.md](pf-guide.md) | Uso diário: o que funciona hoje em `/etc/pf.conf` e as divergências a conhecer |
|
||||
| [screencast.md](screencast.md) | Os vídeos narrados (inglês e português): fases, pipeline, como regravar |
|
||||
@@ -39,4 +40,4 @@ Vocabulário de status usado nestes docs:
|
||||
- **NOT-ENABLED** — o código existe mas a feature está desligada neste build.
|
||||
- **OUT-OF-SCOPE** — fora de escopo por desenho (spec §3).
|
||||
|
||||
A suíte do lab está **15/15 verde** (`./scripts/vm-run-tests.sh`).
|
||||
A suíte do lab está **16/16 verde** (`./scripts/vm-run-tests.sh`).
|
||||
@@ -191,6 +191,45 @@ lab (`scripts/vm-run-tests.sh`) é a autoridade para PASS/FAIL, e os logs
|
||||
dela ficam em `out/test-logs/`. Os screencasts mostram os mesmos comandos,
|
||||
mas um quadro de vídeo não é um veredito.
|
||||
|
||||
## Achados de capacidade (2026-11-12, a partir de `scripts/stress/run-stress.sh`)
|
||||
|
||||
### 13. O backlog da workqueue cresce com a taxa oferecida: acima de ~1 Gbit/s a VM dá OOM-panic
|
||||
|
||||
Esta é a consequência mais dura da §1 e ela é **reproduzível**, não teórica.
|
||||
O PF rouba cada skb para uma única workqueue ordenada e roda o engine em
|
||||
contexto de processo, então o número de pacotes em voo só é limitado pela
|
||||
memória que o backlog consome.
|
||||
|
||||
Medido no lab (guest Alpine, **1 GB** de RAM, 4 fluxos TCP por um ruleset
|
||||
stateful):
|
||||
|
||||
| Taxa oferecida (por fluxo × 4) | Resultado |
|
||||
|---|---|
|
||||
| 50 Mbit/s (200 Mbit/s no total) | estável |
|
||||
| 100 Mbit/s (400 Mbit/s no total) | estável |
|
||||
| 250 Mbit/s (**1 Gbit/s** no total) | **kernel panic: "System is deadlocked on memory"** |
|
||||
|
||||
O panic é um OOM sem processo matável; o slab naquele momento mostra
|
||||
`kmalloc-8k` ≈ 50 MB, `skbuff_head_cache` ≈ 18 MB e `files_cache` ≈ 40 MB —
|
||||
ou seja, o backlog comeu o 1 GB. A VM reinicia (watchdog de 120 s) e todas as
|
||||
conexões que passavam pelo firewall caem junto.
|
||||
|
||||
Consequências práticas:
|
||||
|
||||
- **Limite a taxa que você aponta para o PF** e dimensione a máquina para o
|
||||
backlog: a memória necessária cresce com a taxa oferecida, não com o
|
||||
número de fluxos concorrentes.
|
||||
- Por isso o teste de stress (`tests/vm/16-stress.sh`) roda as fases de
|
||||
tráfego a uma taxa **limitada** (padrão: 100 Mbit/s por fluxo = 400 Mbit/s
|
||||
no total) — o regime que este port suporta — e reporta o teto
|
||||
separadamente, em vez de dar OOM no firewall sob teste.
|
||||
- Os gates funcionais (01-15) não são afetados: eles movem megabytes, não gigabits
|
||||
por segundo.
|
||||
|
||||
O que resolveria isso é um fast path de verdade (avaliar `pf_test()` inline em
|
||||
softirq, como o OpenBSD faz) ou uma fila limitada com política de drop — as
|
||||
duas são mudanças de design fora do escopo deste port.
|
||||
|
||||
## O que *não* é ressalva
|
||||
|
||||
ARP e outros EtherTypes não-IPv4/IPv6 nunca entram nos hooks netfilter de
|
||||
|
||||
@@ -14,7 +14,7 @@ Atualizado em 2026-11-12; fonte da evidência por linha: `out/test-logs/`,
|
||||
`docs/porting-notes.md`, commits dos milestones e os screencasts
|
||||
([screencast.md](screencast.md)) para a prova visível.
|
||||
|
||||
A suíte está **15/15 verde** (`./scripts/vm-run-tests.sh`).
|
||||
A suíte está **16/16 verde** (`./scripts/vm-run-tests.sh`).
|
||||
|
||||
## Plano de controle e ferramentas
|
||||
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ tamanho embutido na codificação `_IOR/_IOW` OpenBSD e despacha para o
|
||||
| M3 | NAT (`nat-to`/`rdr-to`/`binat-to`), scrub, pflog | **pronto** — gates 05/06/07/09 (incl. integridade de 2 MB via redirect) e pflog gate 12 |
|
||||
| M4 | route-to/dup-to/reply-to, pools, divert e2e | **pronto** — gates 08/10/13 e divert gate 11 |
|
||||
| M5 | filas: back ends ifq (hfsc/fq_codel) | **concluído (mecânico)** — gate 15: o hfsc é anexado, `pfctl -s queue -v` mostra as stats das classes, um fluxo de 2 MB pela fila é contado pela classe. `bandwidth` = linkshare do HFSC (garantia sob contenção, não teto) |
|
||||
| M6 | docs completas, patchset limpo, suíte verde, releases com tag | **concluído** — docs EN+PT-BR, suíte 15/15 verde, tag `v1.0.0` |
|
||||
| M6 | docs completas, patchset limpo, suíte verde, releases com tag | **concluído** — docs EN+PT-BR, suíte 16/16 verde, tag `v1.0.0` |
|
||||
|
||||
## Próximas leituras
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Este é o guia do "o que dá para rodar hoje". Ele segue a
|
||||
[matriz de features](feature-matrix.md): o núcleo de filtragem
|
||||
(pass/block/quick/keep state/tabelas/anchors), a família de NAT, o scrub, o
|
||||
roteamento forçado, os pools, o `divert`, o `pflog` e as filas do OpenBSD
|
||||
8.0 têm todos **evidência em VM** — os 15 gates do lab estão verdes. O que
|
||||
8.0 têm todos **evidência em VM** — os 16 gates do lab estão verdes. O que
|
||||
*não* tem gate está listado explicitamente abaixo. Instalação/build ficam em
|
||||
[install.md](install.md) e [build.md](build.md).
|
||||
|
||||
|
||||
+15
-6
@@ -102,7 +102,7 @@ de saída: o pacote chega, é descartado ou é traduzido, e a prova é lida de
|
||||
volta nos contadores do próprio firewall, na tabela de estados, em capturas de
|
||||
pacote ou no par.
|
||||
|
||||
A lista completa está na §6 (15 gates, todos verdes). Cada gate é um script
|
||||
A lista completa está na §6 (16 gates, todos verdes). Cada gate é um script
|
||||
shell em `tests/vm/` que fala com as VMs através do deb com ssh aninhado,
|
||||
usando os helpers de `tests/vm/lib.sh` (`pf0`, `cli`, `srv`, `gw2`, `pfput`,
|
||||
`pfload`, `ok`, `bad`). O `scripts/vm-run-tests.sh` roda tudo em ordem e
|
||||
@@ -114,15 +114,23 @@ compila dentro do `pf.ko`, mas nenhum gate os exercita. O FQ-CoDel compila e
|
||||
compartilha o header de estatísticas com o `pfctl`, mas só a disciplina
|
||||
**hfsc** é exercitada.
|
||||
|
||||
**Não existe gate numérico de performance**: o `bench-basic.sh` não está na
|
||||
árvore e nenhuma meta de vazão é reivindicada.
|
||||
**Não existe gate numérico de performance**: a decisão de design (spec §7) é
|
||||
que *os gates funcionais são a régua* — um contrato de performance forçaria um
|
||||
shim reescrito, pouco fiel. O que existe é um **teste de stress**
|
||||
(`tests/vm/16-stress.sh`, disparado por `scripts/stress/run-stress.sh`) que
|
||||
afere **invariantes sob carga** — sem vazamento de estados/tabelas, sem falha
|
||||
de carga de regras, payload idêntico sob um stream saturando o link, sem
|
||||
`BUG/WARNING/Oops`, o firewall ainda roteando — e **reporta** a comparação de
|
||||
vazão (baseline sem o módulo vs. com PF ligado) como informação, sem meta
|
||||
numérica de pass/fail. O relatório e o log bruto ficam em
|
||||
`out/stress/<timestamp>/`.
|
||||
|
||||
## 6. Status atual da suíte (2026-11-12)
|
||||
|
||||
**15/15 gates verdes.** Uma rodada completa e limpa
|
||||
(`./scripts/vm-run-tests.sh`, ~9 min) recria e reinicia o `pftest-pf0` antes
|
||||
**16/16 gates verdes.** Uma rodada completa e limpa
|
||||
(`./scripts/vm-run-tests.sh`, ~13 min) recria e reinicia o `pftest-pf0` antes
|
||||
de cada gate, reimplanta o módulo e as ferramentas, e termina com
|
||||
`PASS=15 FAIL=0`. Os logs capturados ficam em
|
||||
`PASS=16 FAIL=0`. Os logs capturados ficam em
|
||||
`out/test-logs/<gate>.sh.log`.
|
||||
|
||||
| Gate | O que prova hoje |
|
||||
@@ -142,6 +150,7 @@ de cada gate, reimplanta o módulo e as ferramentas, e termina com
|
||||
| `13-replyto.sh` | `reply-to` força a resposta para o link do gateway |
|
||||
| `14-soak.sh` | reload de ruleset sob tráfego, ciclo de `rmmod`, checagem de vazamento |
|
||||
| `15-queue.sh` | filas hfsc: anexação, estatísticas da classe, um fluxo de 2 MB contado pela classe |
|
||||
| `16-stress.sh` | stress: vazão baseline vs. PF, churn de estados/regras/tabelas com verificação de vazamento, 2 MB por NAT sob stream saturante, saúde do dmesg (rodado por `scripts/stress/run-stress.sh`, que grava um relatório) |
|
||||
|
||||
Os screencasts ([screencast.md](screencast.md)) mostram boa parte desses
|
||||
gates sendo executados, com o diagrama de rede do lab desenhado sobre o
|
||||
|
||||
Reference in new issue
Block a user