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

9.9 KiB
Raw Blame History

Matriz de features

Inglês: docs/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); 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) 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