From 92c015b97b9ae0d71b9ecf570f6873fb71ef864c Mon Sep 17 00:00:00 2001 From: lgcosta Date: Wed, 11 Nov 2026 21:53:55 -0300 Subject: [PATCH] docs: pflog verified (matrix EN+PT-BR, porting notes, README status) --- README.md | 14 +++++++------- docs/en/feature-matrix.md | 2 +- docs/porting-notes.md | 18 ++++++++++++++++++ docs/pt-BR/feature-matrix.md | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fbc29ef..583f611 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@ out-of-tree kernel module — the real PF engine (`pf.c`, `pf_norm.c`, real OpenBSD `pfctl` over the `/dev/pf` ioctl ABI. (A second module for the `pfq` qdisc arrives with M5.) -**Status:** the filter core, stateful filtering, tables, anchors, NAT and -`divert` are **verified in a real libvirt lab** (7/7 gates green). The -remaining features (route-to/dup-to, pflog, ALTQ/pfq, af-to) are still -pending — honest per-feature status: +**Status:** the filter core, stateful filtering, tables, anchors, NAT +(`nat-to`/`rdr-to`), `divert` and `pflog` are **verified in a real libvirt +lab** (9/9 gates green). The remaining features (binat-to, route-to/dup-to, +scrub e2e, ALTQ/pfq, af-to) are still pending — honest per-feature status: [`docs/en/feature-matrix.md`](docs/en/feature-matrix.md). Demo (asciinema): [`docs/en/demo.md`](docs/en/demo.md). Design: [`docs/superpowers/specs/2026-11-11-pf-linux-port-design.md`](docs/superpowers/specs/2026-11-11-pf-linux-port-design.md) @@ -22,8 +22,8 @@ Design: [`docs/superpowers/specs/2026-11-11-pf-linux-port-design.md`](docs/super | M0 | repo, scripts, kernel build, VM boots the custom kernel | done | | M1 | compat layer, `pf.ko` loads, `/dev/pf`, `pfctl -f` / `-s info` | done | | M2 | filter core: rules/states/tables/anchors, VM gates 01–04 | **done** — gates 01/02/03/04 green | -| M3 | NAT (`nat-to`), scrub e2e, pflog | **partial** — `nat-to` verified (gate 05); rdr/binat, scrub e2e and pflog pending | -| M4 | route-to/dup-to/fail-to, divert e2e | **partial** — divert e2e verified (gate 11); route-to/dup-to pending | +| M3 | NAT (`nat-to`/`rdr-to`/`binat-to`), scrub e2e | **partial** — `nat-to` (gate 05) and `rdr-to` incl. 2 MB integrity (gate 06) verified; `binat-to` and scrub e2e pending | +| M4 | route-to/dup-to/fail-to, divert e2e, pflog | **partial** — divert e2e (gate 11) and pflog (gate 12) verified; route-to/dup-to pending | | M5 | queues: HFSC/FQ-CoDel back ends + `pfq` qdisc | pending | | M6 | docs complete, patchset tidy, full suite green, tagged release | in progress (docs done, suite 7/7 green) | @@ -38,7 +38,7 @@ Design: [`docs/superpowers/specs/2026-11-11-pf-linux-port-design.md`](docs/super | QoS (ALTQ successor) | `queue`/`queue on` with OpenBSD 8.0 `ifq` schedulers: **default (priq), HFSC, FQ-CoDel**, attached via the `pfq` qdisc; `pfctl -s queue -v` stats | | Divert | `divert-to` / `divert` tag + `pdivert` relay over an in-module `PF_DIVERT` socket family (verified: packet to userspace and back) | | Route | `route-to` (pools rr/hash-source/hash-state, `fail-to`), `reply-to`, `dup-to` | -| Logging | `pflogd` via netlink pflog channel (DLT_PFLOG pcap) | +| Logging | `pflogd` via `/dev/pflog` (DLT_PFLOG pcap, OpenBSD record layout) | | Control | `/dev/pf` (0600), OpenBSD 8.0 ioctl ABI, Linux build of `pfctl` (single binary) | Not in scope: `pfsync`/CARP failover, IPsec/pfkey, `ftp-proxy`, per-netns PF diff --git a/docs/en/feature-matrix.md b/docs/en/feature-matrix.md index 13e69e6..2a98ce3 100644 --- a/docs/en/feature-matrix.md +++ b/docs/en/feature-matrix.md @@ -64,7 +64,7 @@ As of 2026-11-11; source of per-row evidence: `out/test-logs/`, | HFSC | `queue on wan { hfsc … }` | M5 | COMPILES-untested — **priq fallback until M5**; `pfsrc/hfsc.c` staged (real OpenBSD 8.0 code) but **not in the module object list** | | FQ-CoDel | `queue on wan { fq_codel … }` | M5 | COMPILES-untested — same as HFSC: staged, not built | | `pfq` qdisc (`tc qdisc … root pfq`) | n/a (Linux glue) | M5 | PENDING-M5 (does not exist in the tree yet) | -| pflog (`log`, `log all`, `block log`, `pfctl -s log`) + `pflogd` pcap (DLT_PFLOG) | `pass out quick log` | M4 | PENDING-M4 — `pflog_packet()` returns success **without logging** (one-time `pr_warn "packet not logged"`); `if_pflog.c` staged, not built; `pflogd` not ported yet | +| pflog (`log`, `log all`, `block log`) + `pflogd` pcap (DLT_PFLOG) | `pass out quick log` + `pflogd /tmp/x.pcap` | M4 | **VERIFIED in lab** — gate `12-pflog.sh`: logged packets are queued by the engine, read through `/dev/pflog` and written as a pcap with linktype DLT_PFLOG (117); the dump contains the real packet bytes. Deviation: a chardev instead of an if_pflog/bpf interface (Linux has no bpf over such a virtual interface here); record layout is byte-compatible with OpenBSD `pflog(4)`. `if_pflog.c` stays unbuilt. | ## Non-goals (explicit) diff --git a/docs/porting-notes.md b/docs/porting-notes.md index 5a00516..25846b8 100644 --- a/docs/porting-notes.md +++ b/docs/porting-notes.md @@ -921,3 +921,21 @@ made bulk transfers silently stall (the peer dropped every segment after the first) and starved `sshd` on the firewall — the box answered ping but not SSH. `tests/vm/06-rdr.sh` pulls 2 MB through a redirect and compares the size to catch it. + +## pflog backend (M4) — chardev instead of an if_pflog/bpf interface + +OpenBSD attaches a `pflog0` interface (`if_pflog.c`, `IFT_PFLOG`) and `pflogd` +reads it through `bpf(4)`. This port keeps `if_pflog.c` staged but unbuilt and +implements the consumer as a misc character device: + +| Aspect | OpenBSD | This port | +|---|---|---| +| Delivery | `pflog0` interface + bpf | `/dev/pflog` (0600), `read()` returns one record, `poll()` supported | +| Record | `struct pflog_hdr` (64 bytes) + packet | identical layout (`module/pfsrc/pfk_pflog.c`), packet truncated to 160 bytes like BSD | +| Consumer | `pflogd` → pcap `DLT_PFLOG` | `tools/pflogd` → pcap `DLT_PFLOG` (117), readable by tcpdump/wireshark | +| Backpressure | bpf buffer | bounded queue (256 records / 1 MiB), overflow counted in `PFKIOCGETPFLOGSTAT` | + +Rationale: a single consumer is the real use case, and Linux gives no bpf hook +for a non-`net_device` virtual interface without pulling in a much larger +amount of the BSD if layer. The on-disk format is unchanged, so existing +tooling works. diff --git a/docs/pt-BR/feature-matrix.md b/docs/pt-BR/feature-matrix.md index 1ba12cd..e2dffac 100644 --- a/docs/pt-BR/feature-matrix.md +++ b/docs/pt-BR/feature-matrix.md @@ -64,7 +64,7 @@ Estado em 2026-11-11; evidência por linha: `out/test-logs/`, | HFSC | `queue on wan { hfsc … }` | M5 | COMPILES-untested — **fallback priq até o M5**; `pfsrc/hfsc.c` staged (código real do OpenBSD 8.0) mas **fora da lista de objetos** do módulo | | FQ-CoDel | `queue on wan { fq_codel … }` | M5 | COMPILES-untested — igual ao HFSC: staged, não compilado | | Qdisc `pfq` (`tc qdisc … root pfq`) | n/a (glue Linux) | M5 | PENDING-M5 (ainda não existe na árvore) | -| pflog (`log`, `log all`, `block log`, `pfctl -s log`) + pcap do `pflogd` (DLT_PFLOG) | `pass out quick log` | M4 | PENDING-M4 — `pflog_packet()` retorna sucesso **sem logar** (`pr_warn "packet not logged"` uma única vez); `if_pflog.c` staged, não compilado; `pflogd` ainda não portado | +| pflog (`log`, `log all`, `block log`) + `pflogd` pcap (DLT_PFLOG) | `pass out quick log` + `pflogd /tmp/x.pcap` | M4 | **VERIFICADO em lab** — gate `12-pflog.sh`: os pacotes logados são enfileirados pelo engine, lidos via `/dev/pflog` e gravados como pcap com linktype DLT_PFLOG (117); o dump contém os bytes reais do pacote. Desvio: um chardev em vez de interface if_pflog/bpf (Linux não tem bpf sobre essa interface virtual aqui); o layout do registro é byte-compatível com `pflog(4)` do OpenBSD. `if_pflog.c` permanece fora do build. | ## Não-objetivos (explícitos)