diff --git a/scripts/gc-testlink.sh b/scripts/gc-testlink.sh new file mode 100755 index 0000000..7cd7334 --- /dev/null +++ b/scripts/gc-testlink.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# Configure a PC ethernet interface for the direct link to the re-bba-rb board. +# +# The board's socket-3 UDP test identity and the ARP the on-console test suite +# sends both assume a point-to-point 10.0.0.0/24 link: +# +# PC 10.0.0.50 <-- this script +# board 10.0.0.99 <-- baked into the gateware at synth time +# +# The address matters: the GC test app's TX test ARPs for 10.0.0.50, and the +# kernel answers ARP for an address it actually holds -- no listener process is +# needed. That reply is what makes the suite's RX test pass, so without this +# configuration RX fails legitimately for lack of traffic. +# +# Run this ON THE PC (not in the devcontainer). +# +# sudo ./scripts/gc-testlink.sh up # configure (auto-detects the NIC) +# sudo ./scripts/gc-testlink.sh up eth0 # ...or name it explicitly +# sudo ./scripts/gc-testlink.sh status +# sudo ./scripts/gc-testlink.sh down # undo, hand the NIC back +# sudo ./scripts/gc-testlink.sh watch # configure, then tcpdump the link +set -euo pipefail + +PC_IP=10.0.0.50 +PREFIX=24 +BOARD_IP=10.0.0.99 +STATE_DIR=/run/gc-testlink + +die() { echo "error: $*" >&2; exit 1; } +need_root() { [ "$(id -u)" -eq 0 ] || die "must run as root (use sudo)"; } +command -v ip >/dev/null 2>&1 || die "'ip' not found (iproute2). Run this on the PC, not in the devcontainer." + +# Pick a wired interface: prefer one with a carrier, else the first en*/eth*. +detect_iface() { + local candidates=() i + for i in /sys/class/net/*; do + i=$(basename "$i") + case "$i" in + lo|docker*|veth*|br-*|virbr*|tap*|wl*|tun*) continue ;; + esac + [ -e "/sys/class/net/$i/device" ] || continue + candidates+=("$i") + done + [ ${#candidates[@]} -gt 0 ] || die "no wired interface found; pass one explicitly" + for i in "${candidates[@]}"; do + if [ "$(cat "/sys/class/net/$i/carrier" 2>/dev/null || echo 0)" = "1" ]; then + echo "$i"; return + fi + done + echo "${candidates[0]}" +} + +nm_present() { command -v nmcli >/dev/null 2>&1 && systemctl is-active --quiet NetworkManager 2>/dev/null; } + +do_up() { + local IF="$1" + echo "==> interface: $IF" + + # NetworkManager will strip a hand-added address (often within seconds, and + # silently). Take the device out of its control first and remember that we + # did, so `down` can hand it back. + mkdir -p "$STATE_DIR" + if nm_present && [ "$(nmcli -g GENERAL.STATE device show "$IF" 2>/dev/null | head -1)" != "" ] \ + && nmcli -g GENERAL.STATE device show "$IF" 2>/dev/null | grep -qv unmanaged; then + echo "==> NetworkManager manages $IF -- setting it unmanaged" + echo " NOTE: this drops any existing connection on $IF (DHCP lease," + echo " routes, DNS). If $IF is your only network interface you" + echo " will lose internet until '$0 down $IF'." + nmcli device set "$IF" managed no + touch "$STATE_DIR/$IF.was-managed" + fi + + ip link set "$IF" up + if ip -4 addr show dev "$IF" | grep -q "inet $PC_IP/$PREFIX"; then + echo "==> $PC_IP/$PREFIX already present" + else + ip addr add "$PC_IP/$PREFIX" dev "$IF" + touch "$STATE_DIR/$IF.addr-added" + echo "==> added $PC_IP/$PREFIX" + fi + + echo + do_status "$IF" + cat < interface: $IF" + if ip -4 addr show dev "$IF" | grep -q "inet $PC_IP/$PREFIX"; then + ip addr del "$PC_IP/$PREFIX" dev "$IF" && echo "==> removed $PC_IP/$PREFIX" + else + echo "==> $PC_IP/$PREFIX not present, nothing to remove" + fi + rm -f "$STATE_DIR/$IF.addr-added" + if [ -f "$STATE_DIR/$IF.was-managed" ]; then + echo "==> handing $IF back to NetworkManager" + nmcli device set "$IF" managed yes || true + rm -f "$STATE_DIR/$IF.was-managed" + fi +} + +do_status() { + local IF="$1" carrier speed + carrier=$(cat "/sys/class/net/$IF/carrier" 2>/dev/null || echo "?") + speed=$(cat "/sys/class/net/$IF/speed" 2>/dev/null || echo "?") + echo " link carrier : $carrier (1 = cable up)" + echo " link speed : ${speed} Mb/s (expect 100 - the W5100S is 100BASE-TX)" + echo " addresses : $(ip -4 -br addr show dev "$IF" | tr -s ' ')" + if [ "$carrier" != "1" ]; then + echo " ** no carrier -- check the cable, and that the console is powered" + echo " (the W5100S rail is gated off GC_ON, so it is dead with the GC off)" + fi + if ip -4 addr show dev "$IF" | grep -q "inet $PC_IP/$PREFIX"; then + echo " config : OK, $PC_IP/$PREFIX is set" + else + echo " config : NOT configured -- run '$0 up $IF'" + fi + echo " board should be reachable at $BOARD_IP once its socket-3 test runs" +} + +ACTION="${1:-up}" +IFACE="${2:-}" +[ -n "$IFACE" ] || IFACE=$(detect_iface) +[ -e "/sys/class/net/$IFACE" ] || die "no such interface: $IFACE" + +case "$ACTION" in + up) need_root; do_up "$IFACE" ;; + down) need_root; do_down "$IFACE" ;; + status) do_status "$IFACE" ;; + watch) need_root; do_up "$IFACE" + echo; echo "==> tcpdump on $IFACE (ctrl-C to stop)"; echo + exec tcpdump -ni "$IFACE" -e ;; + *) die "usage: $0 {up|down|status|watch} [interface]" ;; +esac