Files
fips/testing/static/scripts/iperf-test.sh
T
Johnathan Corgan fa49dc1210 Retire the mesh-public static test topology
The mesh-public profile ran in neither runner: ci-local's static suite
list carries only static-mesh and static-chain, and the GitHub matrix has
only mesh and chain. It also added no coverage over static-mesh.
ping-test.sh and iperf-test.sh branched mesh and mesh-public together and
exercised the same 20 directed pairs among node-a through node-e, and no
script referenced the external node at all. The convergence waits even
used mesh's peer counts rather than mesh-public's, so the extra link to
the public node was never counted, let alone asserted.

Running it would therefore have added a dependency on a live internet
host (test-us01.fips.network) in exchange for zero additional assertions.
Remove the topology, its five compose services, the script branches that
aliased it to mesh, and the documentation rows. An invocation using the
old profile name now fails on ping-test.sh's unknown-profile guard
instead of silently behaving as mesh.

The config generator's external-node support (external_ip,
is_external_node) stays. It has no consumer now, but it is woven into the
config path every remaining topology uses, so removing it would put the
gating suites at risk for no present gain.
2026-07-26 13:54:14 +00:00

134 lines
4.6 KiB
Bash
Executable File

#!/bin/bash
# End-to-end iperf3 bandwidth test between FIPS nodes via DNS resolution.
# Usage: ./iperf-test.sh [mesh|chain] [--live]
#
# Requires containers to be running:
# docker compose --profile mesh up -d
# ./scripts/iperf-test.sh mesh
# ./scripts/iperf-test.sh mesh --live # Show live iperf3 output
set -e
# Exit entire script on Ctrl+C
trap 'echo ""; echo "Test interrupted"; exit 130' INT
PROFILE="${1:-mesh}"
LIVE_OUTPUT=false
if [ "$2" = "--live" ] || [ "$1" = "--live" ]; then
LIVE_OUTPUT=true
[ "$1" = "--live" ] && PROFILE="mesh"
fi
DURATION="${DURATION:-10}"
PARALLEL="${PARALLEL:-8}"
SETTLE_SECONDS="${SETTLE_SECONDS:-3}"
IPERF_TIMEOUT="${IPERF_TIMEOUT:-$((DURATION + 30))}"
PASSED=0
FAILED=0
# Node identities (from generated env file)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../generated-configs${FIPS_CI_NAME_SUFFIX:-}/npubs.env"
if [ ! -f "$ENV_FILE" ]; then
echo "Error: $ENV_FILE not found. Run generate-configs.sh first." >&2
exit 1
fi
# shellcheck source=../generated-configs/npubs.env
source "$ENV_FILE"
iperf_test() {
local server_node="$1"
local client_node="$2"
local dest_npub="$3"
local label="$4"
echo ""
echo "=== $label ==="
# iperf3 server is already running in daemon mode in each container
if [ "$LIVE_OUTPUT" = true ]; then
# Show live output
echo "Running iperf3 test (live output):"
if docker exec "fips-${client_node}${FIPS_CI_NAME_SUFFIX:-}" timeout "$IPERF_TIMEOUT" iperf3 -c "${dest_npub}.fips" -t "$DURATION" -P "$PARALLEL"; then
PASSED=$((PASSED + 1))
else
echo "FAIL"
FAILED=$((FAILED + 1))
fi
else
# Capture and summarize output
echo -n "Running iperf3 test... "
local output
if output=$(docker exec "fips-${client_node}${FIPS_CI_NAME_SUFFIX:-}" timeout "$IPERF_TIMEOUT" iperf3 -c "${dest_npub}.fips" -t "$DURATION" -P "$PARALLEL" 2>&1); then
# Check if we got valid results
if echo "$output" | grep -q "sender"; then
# Extract and display results (get SUM line for aggregate bandwidth)
local bandwidth=$(echo "$output" | grep "\[SUM\].*sender" | tail -1 | awk '{for(i=1;i<=NF;i++) if($i ~ /bits\/sec/) {print $(i-1), $i; exit}}')
echo "OK"
echo "Bandwidth: $bandwidth"
PASSED=$((PASSED + 1))
else
echo "FAIL (no bandwidth data)"
echo "Output: $output"
FAILED=$((FAILED + 1))
fi
else
echo "FAIL"
echo "Error output:"
echo "$output" | head -10
FAILED=$((FAILED + 1))
fi
fi
}
echo "=== FIPS iperf3 Bandwidth Test ($PROFILE topology) ==="
echo ""
# Print topology so the operator can see the configured routing
# context. The bench measures iperf3 throughput between the named
# nodes — labels DO NOT encode hop count, since peer discovery
# converges every same-subnet pair onto a direct UDP path within a
# few ticks regardless of the static `peers:` list.
if [ "$PROFILE" = "mesh" ]; then
echo "Topology (static \`peers:\` from mesh.yaml):"
echo " A peers with: D, E"
echo " B peers with: C"
echo " C peers with: B, D, E"
echo " D peers with: A, C, E"
echo " E peers with: A, C, D"
echo " (Same docker-bridge subnet — discovery converges every"
echo " pair onto a direct UDP path; static \`peers:\` only seeds"
echo " the initial mesh, not the steady-state routing.)"
elif [ "$PROFILE" = "chain" ]; then
echo "Topology (static chain): A — B — C — D — E"
echo " (Same docker-bridge subnet — see mesh note above.)"
fi
echo ""
# Wait for nodes to converge
echo "Waiting ${SETTLE_SECONDS}s for mesh convergence..."
sleep "$SETTLE_SECONDS"
if [ "$PROFILE" = "mesh" ]; then
echo ""
echo "Testing mesh topology paths:"
iperf_test node-d node-a "$NPUB_D" "A→D"
iperf_test node-e node-a "$NPUB_E" "A→E"
iperf_test node-b node-a "$NPUB_B" "A→B"
iperf_test node-c node-a "$NPUB_C" "A→C"
iperf_test node-a node-e "$NPUB_A" "E→A"
elif [ "$PROFILE" = "chain" ]; then
echo ""
echo "Testing chain topology paths:"
iperf_test node-b node-a "$NPUB_B" "A→B"
iperf_test node-c node-a "$NPUB_C" "A→C"
iperf_test node-d node-a "$NPUB_D" "A→D"
iperf_test node-e node-a "$NPUB_E" "A→E"
iperf_test node-a node-e "$NPUB_A" "E→A"
fi
echo ""
echo "=== Results: $PASSED passed, $FAILED failed ==="
[ "$FAILED" -eq 0 ] && exit 0 || exit 1