From 80396e0b36bfe2154877b61b2263337b352f5ddb Mon Sep 17 00:00:00 2001 From: lgcosta Date: Wed, 11 Nov 2026 23:37:02 -0300 Subject: [PATCH] docs: patches helpers are in tree (verified PATCHES_APPLIED=0 / UNPATCH_DONE); route pool gate 10 written --- docs/en/patches.md | 10 +++---- docs/pt-BR/patches.md | 10 +++---- tests/vm/10-pools.sh | 66 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 10 deletions(-) create mode 100755 tests/vm/10-pools.sh diff --git a/docs/en/patches.md b/docs/en/patches.md index 8475e0c..8f06563 100644 --- a/docs/en/patches.md +++ b/docs/en/patches.md @@ -20,11 +20,11 @@ used. `patches/kernel/` therefore contains no `000N-*.patch` today, and applying the (empty) set is a no-op. -> Honest note: install.md and the design mention `scripts/apply-patches.sh`, -> `scripts/unpatch.sh` and `patches/kernel/series`. Those helpers are **not -> in the tree yet**; until they land, "apply the patch set" is by definition -> nothing to do. When a real patch is needed, the first commit that adds it -> MUST also add the two scripts and the `series` file (see rules below). +> Honest note: `scripts/apply-patches.sh`, `scripts/unpatch.sh` and +> `patches/kernel/series` **are in the tree** and are exercised by +> `make test`-adjacent scripts; the series is empty by design, so applying it +> is a verified no-op (`PATCHES_APPLIED=0`). When a real patch is needed, the +> commit that adds it MUST also extend the series file and the rules below. ## The mechanism (how the set is meant to work) diff --git a/docs/pt-BR/patches.md b/docs/pt-BR/patches.md index 7d12e6e..6c13407 100644 --- a/docs/pt-BR/patches.md +++ b/docs/pt-BR/patches.md @@ -21,11 +21,11 @@ Portanto, `patches/kernel/` não contém nenhum `000N-*.patch` hoje, e aplicar o conjunto (vazio) é um no-op. > Nota honesta: o install.md e o design mencionam `scripts/apply-patches.sh`, -> `scripts/unpatch.sh` e `patches/kernel/series`. Esses helpers **ainda não -> estão na árvore**; até entrarem, "aplicar o conjunto de patches" é, por -> definição, nada a fazer. Quando um patch real for necessário, o primeiro -> commit que o adicionar DEVE também adicionar os dois scripts e o arquivo -> `series` (ver as regras abaixo). +> Nota honesta: `scripts/apply-patches.sh`, `scripts/unpatch.sh` e +> `patches/kernel/series` **estão na árvore**. O `series` é vazio por projeto, +> então aplicá-lo é um no-op verificado (`PATCHES_APPLIED=0`). Quando um patch +> real for necessário, o commit que o adiciona também atualiza o `series` e +> as regras abaixo. ## O mecanismo (como o conjunto deve funcionar) diff --git a/tests/vm/10-pools.sh b/tests/vm/10-pools.sh new file mode 100755 index 0000000..42eee88 --- /dev/null +++ b/tests/vm/10-pools.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# M4 gate: route-to pools - round-robin vs source-hash (pf_lb). +# +# Two gateways live on two different firewall links: +# 10.0.3.2 via $IF_GW (gw2's 10.0.3 side) +# 10.0.2.2 via $IF_SRV (gw2's 10.0.2 side) +# Each ping is a separate flow (own state), so the pool choice is made per +# flow: round-robin must spread the flows over both links, source-hash must +# keep them on one (same source address -> same bucket). +set -uo pipefail; cd "$(dirname "$0")"; . ./lib.sh + +GW1=$GW2_IP # 10.0.3.2 +GW2=10.0.2.2 + +pf0 'insmod /opt/pf/pf.ko 2>/dev/null || insmod /tmp/pf.ko; true' +pf0 '/opt/pf/pfctl -e; /opt/pf/pfctl -f /dev/null' >/dev/null + +IF_GW=$(pf0 "ip route get $GW1 | grep -o 'dev [a-z0-9]*' | cut -d' ' -f2") +IF_SRV=$(pf0 "ip route get $SRV_IP | grep -o 'dev [a-z0-9]*' | cut -d' ' -f2") +[ -n "$IF_GW" ] && [ -n "$IF_SRV" ] || { bad "interface resolution"; finish; } +[ "$IF_GW" != "$IF_SRV" ] || { bad "the two gateways share a link"; finish; } +ok "pool links: $IF_GW ($GW1) and $IF_SRV ($GW2)" + +count_on() { # count echo requests captured on an interface + local n + n=$(pf0 "grep -c '$CLI_IP > $SRV_IP' /tmp/pool_$1.td 2>/dev/null; true" | tr -dc '0-9') + [ -n "$n" ] || n=0 + printf '%s' "$n" +} + +run_flows() { # $1 = ruleset file, four separate ICMP flows + pf0 "pkill tcpdump; (tcpdump -ni $IF_GW -c 8 -e icmp > /tmp/pool_gw.td 2>&1 &); (tcpdump -ni $IF_SRV -c 8 -e icmp > /tmp/pool_srv.td 2>&1 &); sleep 1" >/dev/null + cli "for i in 1 2 3 4; do ping -c1 -W2 $SRV_IP >/dev/null 2>&1; done" + sleep 2 +} + +# --- round-robin: the flows must spread over both links --- +cat > /tmp/g10a.conf < /tmp/g10b.conf </dev/null +finish