mirror of
https://github.com/lgcosta/pf-linux-port.git
synced 2026-11-12 23:38:03 -03:00
test(vm): add stress gate 16 and its report runner
Gate 16 asserts invariants under load: states tracked under concurrent connections and drained again, 200 ruleset reloads without failure, 2000 table entries flushed back to zero, 2 MB intact through NAT under a concurrent stream, no kernel faults. Throughput is measured and reported rather than gated, and the traffic phases run at a bounded rate because the PF workqueue backlog exhausts a 1 GB guest above ~1 Gbit/s. The runner writes out/stress/<timestamp>/report.md and captures the guest serial console so a panic stays diagnosable.
This commit is contained in:
1 parent
131672d6ce
commit
45ba489672
4 files changed
+506
-1
No files matched your search
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env bash
|
||||
# run-stress.sh — drive the PF stress test (tests/vm/16-stress.sh) against the
|
||||
# libvirt lab and turn the metrics into a report.
|
||||
#
|
||||
# ./scripts/stress/run-stress.sh # default profile
|
||||
# ./scripts/stress/run-stress.sh --quick # smaller profile (smoke)
|
||||
# ./scripts/stress/run-stress.sh --seconds 30 --connections 1000
|
||||
#
|
||||
# Output: out/stress/<timestamp>/report.md (+ the raw gate log).
|
||||
# Exit status: 0 when every stress phase passed, 1 otherwise.
|
||||
set -uo pipefail
|
||||
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
DEB="${DEB:-root@192.168.1.242}"
|
||||
PF0_IP=192.168.122.8
|
||||
TS="$(date +%Y%m%d-%H%M%S)"
|
||||
OUTD="$REPO/out/stress/$TS"
|
||||
mkdir -p "$OUTD"
|
||||
|
||||
SECS=10
|
||||
PAR=4
|
||||
RATE=100M
|
||||
CONNS=300
|
||||
RELOADS=200
|
||||
RULES=200
|
||||
TENTRIES=2000
|
||||
MAXOH=30
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--quick) SECS=5; CONNS=100; RELOADS=50; RULES=50; TENTRIES=500; shift ;;
|
||||
--seconds) SECS=$2; shift 2 ;;
|
||||
--parallel) PAR=$2; shift 2 ;;
|
||||
--rate) RATE=$2; shift 2 ;;
|
||||
--connections) CONNS=$2; shift 2 ;;
|
||||
--reloads) RELOADS=$2; shift 2 ;;
|
||||
--rules) RULES=$2; shift 2 ;;
|
||||
--table-entries) TENTRIES=$2; shift 2 ;;
|
||||
--max-overhead) MAXOH=$2; shift 2 ;;
|
||||
-h|--help) sed -n '2,12p' "$0"; exit 0 ;;
|
||||
*) echo "unknown option: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
SSH="ssh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=8 -i /root/.ssh/pflab_ed root@$PF0_IP"
|
||||
|
||||
echo "pflab stress: profile seconds=$SECS parallel=$PAR rate/stream=$RATE connections=$CONNS reloads=$RELOADS rules=$RULES table_entries=$TENTRIES max_overhead=$MAXOH%"
|
||||
|
||||
echo "pflab stress: resetting pftest-pf0"
|
||||
ssh "$DEB" "virsh destroy pftest-pf0 >/dev/null 2>&1; virsh start pftest-pf0 >/dev/null" || {
|
||||
echo "pflab stress FAIL: cannot restart pftest-pf0" >&2; exit 1; }
|
||||
up=0
|
||||
for i in $(seq 1 20); do
|
||||
sleep 6
|
||||
if ssh "$DEB" "$SSH true" 2>/dev/null; then up=1; break; fi
|
||||
done
|
||||
[ "$up" = 1 ] || { echo "pflab stress FAIL: pf0 never came back" >&2; exit 1; }
|
||||
|
||||
echo "pflab stress: deploying pf.ko + pfctl to pf0:/opt/pf"
|
||||
for i in 1 2 3; do
|
||||
if scp -q -o ProxyJump=root@192.168.1.242 -o StrictHostKeyChecking=accept-new \
|
||||
-i "$HOME/.ssh/pflab_ed" "$REPO/module/pf.ko" "$REPO/tools/out/pfctl" \
|
||||
"$REPO/tools/out/pdivert" "$REPO/tools/out/pflogd" pf0:/tmp/ 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
ssh "$DEB" "$SSH 'mkdir -p /opt/pf; mv /tmp/pf.ko /tmp/pfctl /tmp/pdivert /tmp/pflogd /opt/pf/ 2>/dev/null; chmod +x /opt/pf/pfctl 2>/dev/null; true'" >/dev/null
|
||||
ssh "$DEB" "$SSH 'test -s /opt/pf/pf.ko && test -x /opt/pf/pfctl'" >/dev/null 2>&1 || {
|
||||
echo "pflab stress FAIL: pf.ko/pfctl missing on pf0" >&2; exit 1; }
|
||||
|
||||
echo "pflab stress: running the stress gate"
|
||||
# The guest's serial console is a pty: a panic or a hang is lost when the VM
|
||||
# reboots. Capture it on the hypervisor (the redirect happens *there*) and
|
||||
# copy it back when the run ends.
|
||||
REMOTE_CONSOLE="/tmp/pf0-console-$TS.log"
|
||||
ssh "$DEB" "PTY=\$(virsh ttyconsole pftest-pf0); setsid nohup timeout 1800 cat \$PTY >$REMOTE_CONSOLE 2>&1 </dev/null &" >/dev/null 2>&1
|
||||
sleep 2
|
||||
export STRESS_SECS="$SECS" STRESS_PARALLEL="$PAR" STRESS_RATE="$RATE" STRESS_CONNS="$CONNS" \
|
||||
STRESS_RELOADS="$RELOADS" STRESS_RULES="$RULES" \
|
||||
STRESS_TABLE_ENTRIES="$TENTRIES" STRESS_MAX_OVERHEAD_PCT="$MAXOH"
|
||||
bash "$REPO/tests/vm/16-stress.sh" >"$OUTD/16-stress.sh.log" 2>&1
|
||||
RC=$?
|
||||
|
||||
# --- report ----------------------------------------------------------------
|
||||
scp -q -o BatchMode=yes -o StrictHostKeyChecking=accept-new "$DEB:$REMOTE_CONSOLE" \
|
||||
"$OUTD/pf0-console.log" 2>/dev/null || true
|
||||
{
|
||||
echo "# PF-on-Linux — stress report"
|
||||
echo
|
||||
echo "- date: $(date -Is)"
|
||||
echo "- profile: seconds=$SECS parallel=$PAR rate/stream=$RATE connections=$CONNS reloads=$RELOADS rules=$RULES table_entries=$TENTRIES max_overhead=${MAXOH}%"
|
||||
echo "- exit status: $RC"
|
||||
echo "- guest serial console: \`pf0-console.log\` (kernel messages during the run)"
|
||||
echo
|
||||
echo "## Phases"
|
||||
echo
|
||||
echo '```'
|
||||
grep '^STRESS ' "$OUTD/16-stress.sh.log" || echo "(no metrics captured)"
|
||||
echo '```'
|
||||
echo
|
||||
echo "## Assertions"
|
||||
echo
|
||||
echo '```'
|
||||
grep -E '^(OK|NOT OK)' "$OUTD/16-stress.sh.log" || echo "(no assertions)"
|
||||
echo '```'
|
||||
} >"$OUTD/report.md"
|
||||
|
||||
echo
|
||||
echo "pflab stress: report -> out/stress/$TS/report.md"
|
||||
grep '^STRESS ' "$OUTD/16-stress.sh.log" || true
|
||||
echo
|
||||
if [ $RC -eq 0 ]; then
|
||||
echo "STRESS RESULT: PASS"
|
||||
else
|
||||
echo "STRESS RESULT: FAIL (rc=$RC)"
|
||||
sed -n '/^NOT OK/p' "$OUTD/16-stress.sh.log" | sed 's/^/ /'
|
||||
fi
|
||||
exit $RC
|
||||
Reference in new issue
Block a user