Files

117 lines
6.0 KiB
Markdown
Raw Permalink 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.
# VM validation lab (libvirt / Alpine)
Português: [docs/pt-BR/vm-lab.md](../pt-BR/vm-lab.md).
All commands below were read from the scripts in `scripts/` (they are the
source of truth); the lab has been created and run during M0–M2 — a full-suite
green run is the M2+ gate and is still in progress (see §6).
## 1. Where it lives
| Host | Role |
|---|---|
| laptop (this repo) | builds kernel/module/tools; drives everything over ssh |
| **deb** — `root@192.168.1.242` | libvirt hypervisor; runs the 4 `pftest-*` Alpine VMs |
The lab never needs NAT to the outside; the only external access is the
libvirt `default` network (192.168.122.0/24, mgmt+DHCP) used for cloud-init
package installs and test ssh. The existing `sms-vm` on deb is never touched.
## 2. Topology (single source: `lab/ips.env`)
| VM | Role | NICs | Kernel |
|---|---|---|---|
| `pftest-pf0` | filter under test (runs `pf.ko`) | `mgmt` (dhcp, default net), `lan` 10.0.1.1/24, `wan` 10.0.2.1/24, `wan2` 10.0.3.1/24 | stock Alpine via image-extracted direct boot; **or** the self-built 7.3.4 `bzImage` with `--pf0-kernel=` (`root=/dev/vda2 ro console=ttyS0,115200n8`, no initrd) |
| `pftest-cli` | client | `mgmt` dhcp (routes disabled), `lan` 10.0.1.10/24, gw 10.0.1.1 (pf0) | Alpine stock |
| `pftest-srv` | server | `mgmt` dhcp (routes disabled), `wan` 10.0.2.20/24, gw 10.0.2.1 (pf0), 10.0.3.0/24 via gw2 | Alpine stock |
| `pftest-gw2` | second-path gateway (ip_forward=1) | `wan2` 10.0.3.2/24, `wan` 10.0.2.2/24 (no mgmt NIC) | Alpine stock |
All VMs get `net.ipv4.ip_forward=1` and `rp_filter=0` via cloud-init, root
password `pftest` plus an injected lab keypair (`/root/.ssh/pflab_ed` on deb,
copy on the laptop for ProxyJump), and packages
`iperf3 tcpdump python3 scapy bash iptables` (Alpine name is `scapy`; the
image also needs `iptables` for pf0 masquerade experiments).
libvirt networks: `default` (kept as-is, started+autostarted for packages) and
isolated bridges `pf-lan` 10.0.1.0/24, `pf-wan` 10.0.2.0/24, `pf-wan2`
10.0.3.0/24 — `forward="none"`, no DHCP, plus host-side bridge IPs
`10.0.x.254` on deb so deb can ssh into every guest's data NIC. VM sizing:
2 vCPU / 1 GB each. Disks are per-VM qcow2 **backing** a shared immutable
`/var/lib/libvirt/images/alpine-base.qcow2` (synced from
`_vendor/images/alpine-3.22-x86_64-cloud.qcow2` by sha256).
> Boot note: the Alpine cloud image is not BIOS/UEFI bootable in QEMU as
> delivered (empty ESP), so *all* VMs use direct kernel boot from the image's
> own extracted kernel; `--pf0-kernel=` only swaps pf0's kernel for the
> built one.
## 3. Recreate / deploy / destroy
```sh
./scripts/vm-create.sh # idempotent: tears down and rebuilds pftest-* domains + seeds
./scripts/vm-create.sh --pf0-kernel=out/linux-7.3.4-bzImage # pf0 boots the built kernel (T6)
./scripts/vm-create.sh --recreate-base # force base-image re-sync
./scripts/vm-deploy.sh # laptop→deb ($DEPLOY_DIR)→pf0:/opt/pf:
# out/*bzImage, module/*.ko, tools/out/*
./scripts/vm-destroy.sh # domains, disks, seeds, pf-* nets, ssh fragments
./scripts/vm-destroy.sh --purge-base --purge-keys # + base image + lab keypair
```
`vm-create.sh` ends by validating `ssh pf0 'ip -br a'` and leaves all VMs
running. Laptop ssh aliases (`pf0|cli|srv|gw2`, ProxyJump via deb) are
generated into `~/.ssh/config.d/pflab`.
## 4. Running the suite
```sh
./scripts/vm-run-tests.sh # or: make test
```
Deterministic by design: **before every gate** the runner destroys and
restarts `pftest-pf0` (fresh disk delta + no leftover module), waits for ssh
on the mgmt DHCP address `192.168.122.8`, re-deploys `pf.ko`/`pfctl`/`*.conf`
into the guest, then runs the gate script from the **laptop** (gates talk to
the VMs through deb with nested ssh — `tests/vm/lib.sh`). Per-gate output is
captured to `out/test-logs/<gate>.sh.log`; the runner prints
`PASS <gate>` / `FAIL <gate> (rc=...)` per test, a summary `PASS=n FAIL=m`,
and exits non-zero if anything failed.
## 5. What each gate proves today
| Gate | Scenario (asserted with real traffic, not exit codes) |
|---|---|
| `01-state.sh` | `pass in/out quick proto icmp keep state` → cli pings srv **through** pf0 (transit); pf0 then lists an icmp state via `pfctl -s states` |
| `02-block.sh` | `block drop in quick proto icmp` → cli ping fails; `block return-rst in quick proto tcp … port 8080` → cli's `nc` to srv:8080 is refused (RST), checked via nc exit |
| `03-tables.sh` | `table <blk> { 10.0.1.10 }` + `block in quick from <blk>` → `pfctl -t blk -T show` lists it; cli ping blocked; live `-T delete` unblocks the same flow |
| `04-anchors.sh` | anchor rule (`-a restricted -f`) passing icmp is evaluated **before** a later main-ruleset `block` (quick/top-placement); `pfctl -s Anchors` lists the anchor |
Planned gates per the plan document (T11–T18): 05-nat, 06-rdr, 07-binat,
08-scrub (scapy), 09-routeto, 10-dup-fail, 11-divert, 12-queues (iperf rate
tolerance ±15%), 13-pflog, 14-soak (reload under traffic + rmmod cycle +
kmemleak). IPv6 is smoke-only for state/block/nat66/scrub. `bench-basic.sh`
(planned, not in the tree yet) is informational; there is no numeric perf gate.
## 6. Current suite status (2026-11-11, honestly)
The M2 gates 01–04 exist and run, but **are not all green yet** — the data
path (netisr workqueue model) and state visibility are being fixed in the M2
gate work. The latest captured run (`out/test-logs/`) shows the mixed state:
transit ping OK / state listing failing on 01, icmp-blocked OK on 02, partial
results on 03, 04 aborted. Treat "VERIFIED-in-VM" in the
[feature matrix](feature-matrix.md) as reserved for gates that pass in a
full clean run; nothing beyond M1 is claimed VERIFIED until then.
## 7. Manual poking
```sh
ssh pf0 # via laptop alias (ProxyJump deb)
insmod /opt/pf/pf.ko
/opt/pf/pfctl -e
/opt/pf/pfctl -f /tmp/g1.conf
/opt/pf/pfctl -s info ; /opt/pf/pfctl -s states -v
dmesg | grep pfk
```
Artifacts of future full runs (log + pcaps) are meant to ship with the Gitea
release (spec §7).