Files
PFVCluster/scripts/lacp-rx-distribution.sh
mrcharles 422999bf3c chore: initialize repo with full project state
Performance optimization engagement for a 7-host Proxmox R&D cluster.
Captures the accumulated work across host tuning, network analysis,
fleet assessment, and kubernetes architecture planning.

Contents:
- Host-side tunings (scripts/): CPU governor, swappiness, BBR, NFS
  nconnect, tuned profiles -- complete on 5 of 7 hosts
- Validation + benchmarking scripts: iperf matrix, bond/NFS fixes
- Collected host data (returned-logs/): check.sh output from all 7
  hosts + iperf results, including newly-validated pfv-tsys9
- AGENTS.md: operating context for AI agents
- PROJECT.md: board-ready fleet assessment with VM placement and
  storage redundancy analysis (40 VMs across 7 hosts)
- K8S.md: kubernetes architecture deep-dive covering cnode/wnode
  distribution, StorageClass design, and ETL/HPC workload planning

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-07-27 11:31:29 -05:00

154 lines
5.8 KiB
Bash
Executable File

#!/usr/bin/env bash
###############################################################################
# lacp-rx-distribution.sh (HOST-NATIVE version)
#
# Runs ON a host (tsys6 or tsys7). Auto-detects role by hostname:
# - On tsys6 (receiver): starts iperf3 -s -1 (one-shot), snapshots local
# bond0 slave RX counters before+after, writes verdict + log.
# - On tsys7 (sender): snapshots local bond0 slave TX counters before+
# after, runs iperf3 -c <peer> -P 8 -t 12.
#
# Each side writes only its own counters. No inter-host SSH required.
# iperf3 -s -1 (one-shot) handles client/server coordination.
#
# Output: /root/lacp-rx-{receiver,sender}.log
###############################################################################
set -uo pipefail
DURATION="${LACP_TEST_SECS:-12}"
STREAMS="${LACP_STREAMS:-8}"
PEER_RX_IP="10.100.100.6" # tsys6 storage IP (receiver)
PEER_TX_IP="10.100.100.7" # tsys7 storage IP (sender)
LOG_DIR="/root"
BOND="bond0"
# Snapshot per-slave byte counters from $BOND. Output: "<slave> rx tx\n" sorted.
snapshot() {
awk '/^Slave Interface:/{print $3}' "/proc/net/bonding/$BOND" | while read -r s; do
[ -n "$s" ] || continue
rx=$(cat "/sys/class/net/$s/statistics/rx_bytes" 2>/dev/null || echo 0)
tx=$(cat "/sys/class/net/$s/statistics/tx_bytes" 2>/dev/null || echo 0)
printf '%s %s %s\n' "$s" "$rx" "$tx"
done | sort
}
# Compute per-slave deltas. $1=label, $2=col(2=rx,3=tx), $3=before, $4=after.
analyze() {
local label="$1" col="$2" before="$3" after="$4"
join "$before" "$after" | awk -v col="$col" -v lbl="$label" '
{
slave=$1
b = (col==2 ? $2 : $3)+0
a = (col==2 ? $4 : $5)+0
d = a - b; if (d < 0) d = 0
delta[slave]=d; bef[slave]=b; aft[slave]=a
order[++n]=slave; total+=d
}
END {
printf "\n--- %s (bytes) ---\n", lbl
printf " %-12s %14s %14s %14s %8s\n", "SLAVE", "BEFORE", "AFTER", "DELTA", "PCT"
for (i=1;i<=n;i++){
s=order[i]
pct = (total>0 ? 100*delta[s]/total : 0)
printf " %-12s %14d %14d %14d %7.1f%%\n", s, bef[s], aft[s], delta[s], pct
}
printf " %-12s %14s %14s %14d %8s\n", "TOTAL", "", "", total, "100.0%"
}'
}
# Dominant-slave pct for the verdict line. $1=col, $2=before, $3=after.
dominant() {
join "$2" "$3" | awk -v col="$1" '
{ b=(col==2?$2:$3)+0; a=(col==2?$4:$5)+0; d=a-b; if(d<0)d=0; tot+=d; delta[$1]=d }
END { m=0; ms=""; for (s in delta){ if (delta[s]>m){m=delta[s]; ms=s} }
printf "%.1f %s", (tot>0?100*m/tot:0), ms }'
}
HOST="$(uname -n)"
HOST="${HOST%%.*}"
case "$HOST" in
*tsys6) ROLE="receiver"; LOG="$LOG_DIR/lacp-rx-receiver.log" ;;
*tsys7) ROLE="sender"; LOG="$LOG_DIR/lacp-rx-sender.log" ;;
*) echo "ERROR: not running on tsys6 or tsys7 (hostname=$HOST)"; exit 2 ;;
esac
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
{
echo "=== LACP per-slave distribution ($ROLE) ==="
echo "Host: $HOST Role: $ROLE"
echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "Bond: $BOND"
echo ""
echo "--- $BOND state ---"
grep -E "Bonding Mode|Transmit Hash|Number of ports|Partner Mac|Slave Interface|Link" \
"/proc/net/bonding/$BOND" 2>&1
echo ""
} | tee "$LOG"
snapshot > "$TMP/before"
if [ "$ROLE" = "receiver" ]; then
echo "[receiver] starting one-shot iperf3 server on $PEER_RX_IP ..."
pkill -x iperf3 2>/dev/null; sleep 0.5
nohup iperf3 -s -1 -B "$PEER_RX_IP" > "$TMP/iperf.out" 2>&1 &
SRV_PID=$!
# Wait for the server to be ready (brief), then wait for it to exit
# (one-shot server exits after serving one client).
for _ in $(seq 1 60); do
kill -0 "$SRV_PID" 2>/dev/null || break
sleep 1
done
wait "$SRV_PID" 2>/dev/null
echo "[receiver] iperf3 server finished."
else
# sender: wait briefly for receiver to be listening, then run client.
echo "[sender] waiting 3s for receiver to listen, then running iperf3 client..."
sleep 3
iperf3 -c "$PEER_RX_IP" -B "$PEER_TX_IP" -P "$STREAMS" -t "$DURATION" -l 128k -O 2 \
> "$TMP/iperf.out" 2>&1
echo "[sender] iperf3 client finished (exit=$?)."
fi
snapshot > "$TMP/after"
{
echo ""
echo "--- iperf3 output (raw tail) ---"
tail -25 "$TMP/iperf.out"
echo ""
if [ "$ROLE" = "receiver" ]; then
analyze "Receiver RX (THE key column)" 2 "$TMP/before" "$TMP/after"
dom="$(dominant 2 "$TMP/before" "$TMP/after")"
pct=${dom%% *}; top=${dom##* }
echo ""
echo "==================================================================="
if awk -v p="$pct" 'BEGIN{exit !(p>=90)}'; then
echo " VERDICT: SWITCH NOT distributing across $HOST's two ports"
echo " Dominant slave '$top' = ${pct}% of RX -> hash not effective"
echo " on this LAG. Action: verify/bounce pfv-r3-tor-stor port-channel."
else
echo " VERDICT: switch IS distributing (top slave '$top' = ${pct}%)."
echo " Cap is host-side: softirq/CPU/bridge/NIC coalescing."
fi
echo "==================================================================="
else
analyze "Sender TX (control: should split if host hash=layer3+4)" 3 "$TMP/before" "$TMP/after"
dom="$(dominant 3 "$TMP/before" "$TMP/after")"
pct=${dom%% *}; top=${dom##* }
echo ""
echo "==================================================================="
if awk -v p="$pct" 'BEGIN{exit !(p>=90)}'; then
echo " VERDICT: host TX NOT distributing (top slave '$top' = ${pct}%)."
echo " Host xmit_hash_policy is NOT effective despite /proc/net/bonding."
else
echo " VERDICT: host TX distributing OK (top slave '$top' = ${pct}%)."
fi
echo "==================================================================="
fi
} | tee -a "$LOG"
echo ""
echo "Log written: $LOG"