docs: queue status honest - attach path reached, purge lock assert documented as the blocker (caveats #9)

This commit is contained in:
lgcosta committed 2026-11-12 01:42:51 -03:00
1 parent ccad35b247
commit 4bade69cf9
4 files changed
+50 -2

No files matched your search

+24
View File
@@ -111,6 +111,30 @@ kernel prints `pfk: divert port N: no socket bound`. `log` needs
(256 records / 1 MiB) and drops. Neither is a stub any more, but neither does
anything until its consumer runs (see [pf-guide.md](pf-guide.md)).
### 9. Queue configuration hits a lock assertion in the purge path (open)
Loading a `queue` rule now reaches the scheduler (`pfq_alloc` succeeds, the
hfsc discipline is created), and `pf_commit_queues()` is exercised end to end.
Two bugs were found and fixed while getting there — the root-class handle
colliding with odd pf queue ids (`pfq_addqueue` returned EBUSY), and a NULL
discipline not being checked.
What still blocks queues: the port's purge timer can run while an ioctl holds
the write lock, and `pf_purge_expired_states()` asserts the opposite:
```
splassert: pf_purge_expired_states: expected 0, got 2
kernel BUG at compat/pfk_kern.c:51
```
OpenBSD serialises this with `splnet()`; the port replaced the spl layer with
rw-semas and a work queue, so the assertion is now a real race rather than a
formality. Until it is fixed (release the lock around the call, or give the
state tree its own lock as upstream does for `pf_state_lock`), a host that
configures queues can wedge the module in `Unloading`. **Do not enable
`queue` rules on a live host yet** — the 14 lab gates never configure queues,
which is why they stay green.
## Compat-layer deviations (from `docs/porting-notes.md`, M1 record)
These are deliberate, marked-in-code divergences of the compat layer; they
+1 -1
View File
@@ -60,7 +60,7 @@ As of 2026-11-11; source of per-row evidence: `out/test-logs/`,
|---|---|---|---|
| `route-to` / `dup-to` / `reply-to` | `pass in … route-to { 10.0.3.2 } keep state`, `reply-to { gw }` | M4 | **VERIFIED in lab** — gates `08-routeto.sh` (route-to leaves via the gateway's link, dup-to copies while keeping the flow) and `13-replyto.sh` (the reply of a flow is forced onto the gateway link instead of the client's). Deviation: the forced nexthop is installed by setting `rt_gw4`/`rt_gw_family` on the looked-up route (Linux only ARPs the gateway when the route declares one). `fail-to` is **not a keyword in OpenBSD 8.0** (removed upstream), so it is out of scope. |
| `divert-to` / `divert` tag | `pass in … divert-to <host> port <n>` | VERIFIED in lab | **Works end-to-end.** The module registers an `AF_DIVERT` socket family (`PF_DIVERT=32`) at runtime — no kernel-tree patch. A `divert-to` rule hands the packet to that family; with no listener the packet is dropped (`divs_noport`, BSD parity); with `tools/pdivert` running the packet is delivered to userspace, rewritten and reinjected (verified with a payload mutation + checksum fix, ping 0% loss). |
| Queues (`queue`, `queue on`, `pfctl -s queue -v`) | `queue root q1 bandwidth 1Mbit; queue on egress all ...` | M5 | **Back ends built into `pf.ko`, attachment pending** — OpenBSD's `hfsc.c` and `fq_codel.c` now compile and link (157 scheduler symbols, `hfsc_initialize`/`hfsc_pf_addqueue`/`fqcodel_pf_addqueue` reachable from `pf_ioctl`), and the full suite still passes with them in. The active scheduler remains the priq shim: nothing enqueues the reinjected packet into the queue yet, so **no bandwidth is enforced**. |
| Queues (`queue`, `queue on`, `pfctl -s queue -v`) | `queue root q1 bandwidth 1Mbit; queue on egress all ...` | M5 | **Back ends built into `pf.ko`, attachment pending** — OpenBSD's `hfsc.c` and `fq_codel.c` now compile and link (157 scheduler symbols, `hfsc_initialize`/`hfsc_pf_addqueue`/`fqcodel_pf_addqueue` reachable from `pf_ioctl`), and the full suite still passes with them in. The data path can now hand packets to an attached scheduler (`pf_kifq_input()` + a real `ifq_start()` that drains and transmits), but queues are **not safe to enable yet**: the purge path hits a lock assertion (see caveats #9), so no bandwidth is enforced and no gate covers it. |
| 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) |