testing: add admission-cap integration suite for inbound silent-drop gate

New integration scenario verifying the early-gate silent-drop behavior
of the inbound max_peers admission check at sustained scale, using the
existing 5-node mesh topology with one node's node.limits.max_peers
lowered to 1. This forces 2 of the cap'd node's 3 configured peers
into a sustained denied state, and asserts via tcpdump that no Msg2
responses go back to those denied peers across a 60s capture window.

A background load-driver restarts the denied peer containers every 15s
to reset their auto-reconnect exponential backoff (5s base / 300s cap),
producing fresh Msg1 bursts each cycle. Without this loop the gate
fires ~3-4 times per denied peer in a 60s window; with restarts the
observed rate is 15 per denied peer (~30 total firings), high enough
that any Msg2 leakage would be caught with strong statistical
confidence.

Local run on this branch: cap'd node-c converged to peer_count=1 with
node-b admitted; nodes d and e sustained-retried as denied; tcpdump
captured 30 inbound Msg1 (len 84) packets from the denied pair and 0
outbound Msg2 (len 104) packets, with final peer_count unchanged.

Files:
  testing/static/scripts/admission-cap-test.sh — new test script with
    inject-config subcommand (sets node.limits.max_peers) and a
    3-phase test driver (converge, capture-with-load, per-peer assert)
  testing/ci-local.sh — register admission-cap as a new suite category
    (ADMISSION_SUITES), wire run_admission_cap function, add to
    run_suite dispatch, list_suites, and the default integration sweep

Together with the existing unit-level coverage in src/node/tests/unit.rs
(handle_msg1_silent_drops_at_cap_for_new_peer with mock-transport Msg2
discriminator, and handle_msg1_admits_existing_peer_at_cap as the
bypass regression guard), the gate's silent-drop behavior is now
verified both at single-firing wire-observable resolution and at
sustained multi-firing cross-process scale.
This commit is contained in:
Johnathan Corgan
2026-05-26 20:34:42 +00:00
parent 5b229c03bf
commit d575c1f986
2 changed files with 244 additions and 0 deletions
+39
View File
@@ -57,6 +57,7 @@ ONLY_SUITE=""
# All integration suites matching ci.yml
STATIC_SUITES=(static-mesh static-chain)
REKEY_SUITES=(rekey rekey-accept-off rekey-outbound-only)
ADMISSION_SUITES=(admission-cap)
# Each entry: "display-name scenario [--flag value ...]"
CHAOS_SUITES=(
"smoke-10 smoke-10"
@@ -111,6 +112,9 @@ list_suites() {
echo " Rekey:"
for s in "${REKEY_SUITES[@]}"; do echo " $s"; done
echo ""
echo " Admission cap:"
for s in "${ADMISSION_SUITES[@]}"; do echo " $s"; done
echo ""
echo " Gateway:"
for s in "${GATEWAY_SUITES[@]}"; do echo " $s"; done
echo ""
@@ -320,6 +324,34 @@ run_rekey() {
record "rekey" $rc
}
# Run the admission-cap integration test
# Verifies the inbound max_peers early-gate silent-drops at scale by
# lowering node.max_peers on one mesh node and asserting via tcpdump
# that no Msg2 responses go to the sustained-retrying denied peers.
run_admission_cap() {
local compose="testing/static/docker-compose.yml"
local rc=0
info "[admission-cap] Generating configs"
bash testing/static/scripts/generate-configs.sh mesh || { record "admission-cap" 1; return; }
bash testing/static/scripts/admission-cap-test.sh inject-config || { record "admission-cap" 1; return; }
info "[admission-cap] Starting containers (mesh profile)"
docker compose -f "$compose" --profile mesh up -d || { record "admission-cap" 1; return; }
info "[admission-cap] Running admission-cap test"
if bash testing/static/scripts/admission-cap-test.sh; then
rc=0
else
rc=1
info "[admission-cap] Collecting failure logs"
docker compose -f "$compose" --profile mesh logs --no-color 2>&1 | tail -100
fi
docker compose -f "$compose" --profile mesh down --volumes --remove-orphans 2>/dev/null
record "admission-cap" $rc
}
# Run a chaos scenario
run_chaos() {
local name="$1"
@@ -568,6 +600,11 @@ run_integration() {
run_rekey_accept_off
run_rekey_outbound_only
# Admission cap (mesh profile, max_peers=1 on one node)
for _suite in "${ADMISSION_SUITES[@]}"; do
run_admission_cap
done
# Gateway
run_gateway
@@ -670,6 +707,8 @@ run_suite() {
run_rekey_accept_off ;;
rekey-outbound-only)
run_rekey_outbound_only ;;
admission-cap)
run_admission_cap ;;
gateway)
run_gateway ;;
acl-allowlist)