diff --git a/.agent/skills/network-throughput/SKILL.md b/.agent/skills/network-throughput/SKILL.md index 9cd3996..55a86ca 100644 --- a/.agent/skills/network-throughput/SKILL.md +++ b/.agent/skills/network-throughput/SKILL.md @@ -42,7 +42,8 @@ Terminology: - Ask before starting any privileged capture or firewall-visible test. - Use one test download only. Do not run Firefox/browser downloads in parallel. -- Use project-local scratch directories, not system `/tmp` or `/var/tmp`. +- On FreeBSD/Clawdie, use project-local scratch directories, not system `/tmp` or `/var/tmp`. +- On Linux/debby/Hermes, prefer `~/.local/state/hermes/net-tests/`; project-root `tmp/` is also acceptable when running inside a specific repo. - On FreeBSD, run root commands in the visible tmux root window when one is available. - Do not leave large pcaps or duplicate downloaded images behind after analysis. - Do not change PF during the measurement unless the purpose of the test is explicitly PF comparison. @@ -66,11 +67,13 @@ DURATION_SEC="600" ### Linux client / debby / Hermes -Run from the Hermes project/repo root, then keep artifacts under that repo `tmp/` directory: +Prefer the Hermes state directory for Hermes-run artifacts. If running inside a specific project repo, project-root `tmp/network-tests/$TEST_ID` is also acceptable. ```sh TEST_ID="osa-clean-download-$(date -u +%Y%m%dT%H%M%SZ)" -CLIENT_DIR="$PWD/tmp/network-tests/$TEST_ID" +CLIENT_DIR="$HOME/.local/state/hermes/net-tests/$TEST_ID" +# Alternative when running inside a repo: +# CLIENT_DIR="$PWD/tmp/network-tests/$TEST_ID" URL="https://osa.smilepowered.org/downloads/iso/clawdie-xfce-operator-usb-fbsd15.0-amd64-15.maj.2026.img.gz" SHA_URL="$URL.sha256" SERVER_IP="51.83.197.148" @@ -109,7 +112,7 @@ date -u '+client_preflight_utc=%Y-%m-%dT%H:%M:%SZ' | tee "$CLIENT_DIR/timestamps df -h . > "$CLIENT_DIR/df-before.txt" ip addr > "$CLIENT_DIR/ip-addr.txt" ip route > "$CLIENT_DIR/ip-route.txt" -curl -4 -s https://ifconfig.me > "$CLIENT_DIR/public-ip.txt" +curl -4 -sS --max-time 10 https://ifconfig.me > "$CLIENT_DIR/public-ip.txt" || true ip route get "$SERVER_IP" > "$CLIENT_DIR/route-to-osa-public.txt" ``` @@ -123,6 +126,17 @@ CLIENT_IF="" Start both captures before the download. Wait until tcpdump prints `listening on ...` on both sides. +Operational order: + +1. start server pcap +2. start client pcap +3. start client latency monitor +4. start download +5. stop download if bounded +6. stop latency monitor +7. stop pcaps +8. collect after-counters + Avoid tiny rotating pcap rings. For a 5-10 minute test, either use a single non-overwriting pcap or enough ring files to preserve the beginning/SYN. ### Server capture @@ -151,7 +165,9 @@ date -u '+server_pcap_start_utc=%Y-%m-%dT%H:%M:%SZ' | tee -a "$SERVER_DIR/timest ### Linux client capture -Run in a root shell or with sudo, but store output under the Hermes project `tmp/` directory: +Run in a root shell or with sudo. Prefer writing directly to `CLIENT_DIR`; if permissions get in the way, stage in a root-writable capture directory and then move/chown into `CLIENT_DIR` after capture. + +Direct-to-artifact-dir form: ```sh date -u '+client_pcap_start_utc=%Y-%m-%dT%H:%M:%SZ' | tee -a "$CLIENT_DIR/timestamps.txt" @@ -162,23 +178,47 @@ sudo /usr/bin/timeout 900 tcpdump -ni "$CLIENT_IF" \ "host $SERVER_IP and (tcp port 443 or icmp or icmp6)" ``` -## Client Latency Monitor - -Run this on debby while the download runs. It helps identify access-path/bufferbloat symptoms. +Staged form, if root tcpdump cannot write directly to `CLIENT_DIR`: ```sh -GW=$(ip route show default | awk '{print $3; exit}') -while true; do - date -u '+utc=%Y-%m-%dT%H:%M:%SZ' - for t in "$GW" 1.1.1.1 "$SERVER_TS_IP" 100.103.255.41; do - echo "### $t" - ping -c 5 -i 0.2 -W 2 "$t" - done - sleep 5 -done | tee "$CLIENT_DIR/ping-monitor.log" +CAPTURE_TMP="$HOME/.local/state/hermes/net-tests/root-pcap-staging-$TEST_ID" +mkdir -p "$CAPTURE_TMP" +date -u '+client_pcap_start_utc=%Y-%m-%dT%H:%M:%SZ' | tee -a "$CLIENT_DIR/timestamps.txt" +sudo /usr/bin/timeout 900 tcpdump -ni "$CLIENT_IF" \ + -s 0 \ + -C 200 -W 20 \ + -w "$CAPTURE_TMP/debby-osa-public.pcap" \ + "host $SERVER_IP and (tcp port 443 or icmp or icmp6)" +sudo chown "$USER:$USER" "$CAPTURE_TMP"/debby-osa-public.pcap* +mv "$CAPTURE_TMP"/debby-osa-public.pcap* "$CLIENT_DIR"/ +rmdir "$CAPTURE_TMP" 2>/dev/null || true ``` -Stop it when the download stops. +## Client Latency Monitor + +Start this on debby before the download and stop it after the download stops. It helps identify access-path/bufferbloat symptoms. + +```sh +( + GW=$(ip route show default | awk '{print $3; exit}') + while true; do + date -u '+utc=%Y-%m-%dT%H:%M:%SZ' + for t in "$GW" 1.1.1.1 "$SERVER_TS_IP" 100.103.255.41; do + echo "### $t" + ping -c 5 -i 0.2 -W 2 "$t" + done + sleep 5 + done +) | tee "$CLIENT_DIR/ping-monitor.log" & +PING_MON_PID=$! +echo "$PING_MON_PID" > "$CLIENT_DIR/ping-monitor.pid" +``` + +Stop it after the download stops: + +```sh +kill "$(cat "$CLIENT_DIR/ping-monitor.pid")" 2>/dev/null || true +``` ## Download Test @@ -237,14 +277,16 @@ ls -lh "$SERVER_DIR" > "$SERVER_DIR/ls.txt" ```sh ls -lh "$CLIENT_DIR" > "$CLIENT_DIR/ls.txt" -curl -L --fail -o "$CLIENT_DIR/expected.sha256" "$SHA_URL" +curl -L --fail --max-time 30 -o "$CLIENT_DIR/expected.sha256" "$SHA_URL" ``` -If the full image completed, verify checksum: +If the full image completed, verify checksum without depending on the filename inside the `.sha256` file: ```sh -cd "$CLIENT_DIR" -sha256sum -c expected.sha256 +EXPECTED=$(awk '{print $1; exit}' "$CLIENT_DIR/expected.sha256") +ACTUAL=$(sha256sum "$CLIENT_DIR/clawdie-test.img.gz" | awk '{print $1}') +printf 'expected=%s\nactual=%s\n' "$EXPECTED" "$ACTUAL" | tee "$CLIENT_DIR/checksum-result.txt" +test "$EXPECTED" = "$ACTUAL" ``` ## Summary-First Exchange