Files
pf-linux-port/docs/pt-BR/feature-matrix.md
T
lgcosta dff2185b20 Docs: bring the documentation in line with the code
- Demo docs replaced by the screencast docs (single source of truth): the
  legacy demo-session.sh/demo-record.py and the v0.9 renderer were removed
  instead of being kept as a second convention.
- feature-matrix: stale 'M2-in-progress' vocabulary gone; the rows the 15
  gates prove now say VERIFIED-in-VM and name the gate; af-to is now an
  explicit non-goal row (INET6 0 in this build).
- guide: the queues/divert/pflog sections described a state that no longer
  exists (priq-only, divert dropping packets, pflog logging nothing); they
  now describe the shipped behaviour.
- vm-lab: the 15 real gates with what each proves, 15/15 green, and the
  pf0 -> cli/srv/gw2 ssh setup the screencasts rely on.
- install/build: pdivert and pflogd are built and ported (docs said
  otherwise); module object list now includes hfsc.c, fq_codel.c, pfk_pflog.c;
  the screencast pipeline is an optional build stage.
- pf-guide: the 'M2 scope only' framing is gone; honest gaps listed.
- caveats: three new sections about the screencast pipeline (MiniMax video
  generation blocked by the account tier, narration as a separate track, a
  video frame is not a verdict).
- porting-notes: what the recording taught us.
- README/README.pt-BR: status, milestones, layout and video section updated.

All internal doc links verified.
2026-11-12 11:51:25 -03:00

84 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Matriz de features
Inglês: [docs/en/feature-matrix.md](../en/feature-matrix.md).
Vocabulário de status (idêntico nos dois idiomas):
- **VERIFIED-in-VM** — exercitado de ponta a ponta no lab libvirt (veja [vm-lab.md](vm-lab.md)); o gate que prova está nomeado.
- **VERIFIED-offline** — provado por um teste de fixture/ABI, não por tráfego (ex.: `make -C tools test`).
- **COMPILES-untested** — compilado dentro do `pf.ko`/`pfctl`; nenhum gate exercitou ainda.
- **NOT-ENABLED** — o código existe mas a feature está desligada neste build (ex.: `af-to`, que depende dos caminhos `INET6`).
- **OUT-OF-SCOPE** — fora de escopo por desenho (spec §3).
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`).
## Plano de controle e ferramentas
| Feature | Sintaxe upstream | Milestone | Status |
|---|---|---|---|
| Carga do módulo, `/dev/pf` (0600) | `insmod pf.ko` | M1 | VERIFIED-in-VM (gate `02-ativacao.sh`) |
| Habilitar/desabilitar | `pfctl -e`, `pfctl -d` | M1 | VERIFIED-in-VM |
| Carga de ruleset | `pfctl -f file` | M2 | VERIFIED-in-VM (todo gate carrega um ruleset real) |
| Checagem só de parse | `pfctl -n -f file` | M1 | VERIFIED-offline (`make -C tools test`) |
| Status/contadores | `pfctl -s info [-v]` | M1 | VERIFIED-in-VM |
| Listagem de regras | `pfctl -s rules [-v]`, `pfctl -sr` | M2 | VERIFIED-in-VM (gates 02–06) |
| Listagem de estados | `pfctl -s states [-v]`, `pfctl -ss` | M2 | VERIFIED-in-VM (gate `01-state.sh`) |
| Listagem/operações de tabelas | `pfctl -s tables`, `-t t -T show/add/del/kill` | M2 | VERIFIED-in-VM (gate `03-tables.sh`, incluindo um `-T delete` ao vivo liberando o fluxo) |
| Anchors | `pfctl -a anchor -f file`, `-s anchors` | M2 | VERIFIED-in-VM (gate `04-anchors.sh`) |
| Listagem de filas | `pfctl -s queue -v` | M5 | VERIFIED-in-VM (gate `15-queue.sh`: as duas classes com estatísticas) |
| Paridade da ABI ioctl | `make -C tools abi` (tabelas do abitest) | M1 | VERIFIED-offline (tabela do userland); o diff do lado do kernel é um passo de integração em aberto (`tools/UPSTREAM.md`) |
## Núcleo de filtragem
| Feature | Sintaxe upstream | Milestone | Status |
|---|---|---|---|
| `pass`/`match`, quick, on-interface/proto/addr/port | `pass in quick on wan proto tcp from 10/8 to port 80` | M2 | VERIFIED-in-VM (gate `01-state.sh`: ping de trânsito atravessando o firewall) |
| `block drop` | `block drop in quick …` | M2 | VERIFIED-in-VM (gate `02-block.sh`: o ping morre e os contadores provam) |
| `block return` / `return-rst` / `return-rst after quarter` | `block return-rst in quick proto tcp …` | M2 | VERIFIED-in-VM (gate `02-block.sh`: o `nc` do cliente recebe RST) |
| `keep state` (icmp/tcp/udp), tabela de estados, purger | `… keep state` | M2 | VERIFIED-in-VM (gate `01-state.sh`; o estado aparece no `pfctl -ss`) |
| `set state-policy`, `allow-opts`, etc. | opções `set …` | M2 | COMPILES-untested |
| Syncookies (caminho de overflow de estados) | `set syncookies always` | M2 | COMPILES-untested |
| Tabelas pfr (radix/hash) | `table <blk> persist { 1.2.3.4 }`, `-T add …` | M2 | VERIFIED-in-VM (gate `03-tables.sh`) |
| Anchors + include + precedência de quick | `anchor "x"`, `load anchor …` | M2 | VERIFIED-in-VM (gate `04-anchors.sh`) |
| IPv6 para tudo acima | mesma sintaxe, v6 | M2+ | COMPILES-untested — o engine é completo para v6 por construção, mas o caminho v6 não é exercitado por gate |
| Tráfego não-IPv4/IPv6 (ARP…) | — | M2 | PFLINUX por construção: só os hooks netfilter IPv4/IPv6 — ARP nunca entra no caminho do PF (sem gate) |
## NAT / normalização (M3)
| Feature | Sintaxe upstream | Milestone | Status |
|---|---|---|---|
| `nat-to` (pools de portas, sticky-port, static-port) | `pass out … nat-to (eth1:0)` | M3 | **VERIFIED-in-VM** — gate `05-nat.sh`: o NAT de origem funciona de ponta a ponta (prova por tcpdump), a resposta é des-NATeada e re-encaminhada para o cliente, e o estado mostra as duas tuplas (`10.0.2.1:59335 (10.0.1.10:4380) -> 10.0.2.20:8`). |
| `rdr-to` | `pass in … to <fw> port 8080 rdr-to <srv> port 80 keep state` | M3 | **VERIFIED-in-VM** — gate `06-rdr.sh`: o cliente fala com o endereço do firewall, o pf reescreve o destino, re-encaminha o pacote, e a resposta é des-redirecionada. O gate também puxa 2 MB pelo redirect e confere a integridade byte a byte (guarda de regressão GSO/TSO). |
| `binat-to` | `pass quick proto icmp from 10.0.2.20 to 10.0.1.10 binat-to 10.0.2.50 keep state` | M3 | **VERIFIED-in-VM** — gate `07-binat.sh`. O pfctl expande uma regra `binat-to` no par documentado (`pass out … nat-to <mapped> static-port` + `pass in … rdr-to <real>`), e as duas metades funcionam: o par vê o endereço mapeado, o original nunca vaza, e a resposta é traduzida de volta. |
| Pools de NAT (`round-robin`, `source-hash`) | `nat-to { 10.0.2.1, 10.0.3.1 } round-robin` | M4 | **VERIFIED-in-VM** — gate `10-pools.sh`, e visível no screencast: o round-robin alterna o endereço de origem entre os membros (3 pacotes cada), o source-hash mantém uma origem em um membro só. |
| Scrub/normalize: remontagem, `fragment drop-overlap`, `min-ttl`, `max-mss`, `df`/`no-df`, `random-id`, `set reassemble yes` | `match in all scrub (min-ttl 100 max-mss 500)` | M3 | **VERIFIED-in-VM** — gate `09-scrub.sh`: o `min-ttl` aumenta o TTL (egresso mostra 99 depois do decremento do forward) e o `max-mss` limita a opção MSS do SYN, ambos medidos no egresso do próprio firewall. Os caminhos de remontagem/overlap compilam e são alcançados, mas não têm gate. |
| Fingerprint de OS nos estados | `pass … set os A` + `/etc/pf.os` | bonus | COMPILES-untested (`pf_osfp.c` compilado; ainda sem o pacote de fingerprints — a ausência de `/etc/pf.os` é tolerada) |
## Roteamento / divert / filas / logging
| Feature | Sintaxe upstream | Milestone | Status |
|---|---|---|---|
| `route-to` / `dup-to` / `reply-to` | `pass in … route-to { 10.0.3.2 } keep state`, `reply-to { gw }` | M4 | **VERIFIED-in-VM** — gates `08-routeto.sh` (o route-to sai pelo link do gateway, o dup-to copia mantendo o fluxo) e `13-replyto.sh` (a resposta de um fluxo é forçada para o link do gateway em vez do cliente). Divergência: o próximo salto forçado é instalado definindo `rt_gw4`/`rt_gw_family` na rota consultada (o Linux só faz ARP do gateway quando a rota declara um). `fail-to` **não é palavra-chave no OpenBSD 8.0** (removido upstream), logo está fora de escopo. |
| `divert-to` / tag `divert` | `pass in … divert-to <host> port <n>` | M4 | **VERIFIED-in-VM** — gate `11-divert.sh`. O módulo registra uma família de sockets `AF_DIVERT` (`PF_DIVERT=32`) em runtime — sem patch no kernel. Uma regra `divert-to` entrega o pacote a essa família; sem listener o pacote é descartado (`divs_noport`, paridade com o BSD); com o `tools/pdivert` rodando o pacote vai para o userspace, é reescrito e reinjetado (verificado com mutação do payload + correção de checksum, ping com 0% de perda). |
| Filas (`queue`, `queue on`, `pfctl -s queue -v`) | `queue rootq on eth2 bandwidth 10Mbit` + `queue leafq on eth2 bandwidth 2Mbit parent rootq default` | M5 | **VERIFIED-in-VM** — gate `15-queue.sh`: a configuração de filas carrega, a disciplina hfsc é anexada à interface, `pfctl -s queue -v` lista as duas classes com estatísticas, um fluxo de 2 MB pela fila completa, e o contador de pacotes da classe avança (o escalonador está no caminho de dados). Note que `bandwidth` é *linkshare* do HFSC — garantia sob contenção, não teto: o pf.conf do OpenBSD 8.0 não tem `minimum`/`maximum`, então um fluxo isolado não é limitado, nem no Linux nem no OpenBSD. |
| HFSC | `queue on wan { hfsc … }` | M5 | **VERIFIED-in-VM** — o `pfsrc/hfsc.c` (código real do OpenBSD 8.0) está na lista de objetos do módulo e é a disciplina que o gate exercita. As classes usam o `net/hfsc.h` vendorizado (classe raiz `0x10000`, classe default `0x1000`) compartilhado com o `pfctl`, então a ABI de estatísticas bate nos dois lados. |
| FQ-CoDel | `queue on wan { fq_codel … }` | M5 | COMPILES-untested — o `pfsrc/fq_codel.c` é compilado dentro do `pf.ko` e o `net/fq_codel.h` vendorizado é compartilhado com o `pfctl`, mas nenhum gate o exercita. |
| Interface `pfq` | n/a (interfaces BSD `ifq`/`pfq`, não um qdisc `tc` do Linux) | M5 | **VERIFIED-in-VM** — o port mantém a forma do BSD: `compat/pfk_ifq.c` implementa as interfaces `ifq_ops`/`pfq_ops` e os back ends do OpenBSD se plugam nelas (`pfq` nunca foi um qdisc `tc` do Linux, nem nunca pretendeu ser). priq é a disciplina default. |
| pflog (`log`, `log all`, `block log`) + pcap do `pflogd` (DLT_PFLOG) | `pass out quick log` + `pflogd /tmp/x.pcap` | M4 | **VERIFIED-in-VM** — gate `12-pflog.sh`: os pacotes logados são enfileirados pelo engine, lidos por `/dev/pflog` e escritos como pcap com linktype DLT_PFLOG (117); o dump contém os bytes reais do pacote. Divergência: um chardev em vez de uma interface if_pflog/bpf (o Linux não tem bpf sobre uma interface virtual dessas aqui); o layout do registro é byte a byte compatível com o `pflog(4)` do OpenBSD. O `if_pflog.c` continua fora da build. |
## Fora de escopo (explícito)
| Item | Motivo |
|---|---|
| Failover `pfsync` / CARP | fora de escopo (spec §3) |
| IPsec / pfkey | fora de escopo |
| `ftp-proxy` e daemons de userland | fora de escopo |
| Instâncias PF por netns | port fiel = uma instância global no `init_net` |
| Agendadores exclusivos do ALTQ clássico (cbq/wfq/red…) | removidos upstream antes do OpenBSD 8.0 — impossíveis de portar a partir da base |
| Routing labels (`route-label`) | fora de escopo; a camada de ioctl rejeita regras com label |
| `af-to` (tradução IPv4↔IPv6) | o código está sob `#ifdef INET6` e este build tem `INET6 0`; habilitá-lo é um milestone à parte, não uma feature faltando na base |