elks-enhanced
public
Read
Owner: themaster
Branch: master
Commits: 6893
Updated: 2026-04-19 00:15
Git CLI clone URL
git clone https://www.xt-emporium.com/git/elks-enhanced.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
elks-enhanced
/
qemu-uip-udp-test.sh
File editor
#!/bin/sh set -eu SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) MFS=${MFS:-"$SCRIPT_DIR/elks/tools/bin/mfs"} IMAGE=${IMAGE:-"$SCRIPT_DIR/image/fd1440.img"} HOST_IP=${HOST_IP:-192.168.7.1} GUEST_IP=${GUEST_IP:-192.168.7.2} NETMASK=${NETMASK:-255.255.255.0} BAUD=${BAUD:-38400} MTU=${MTU:-296} WORKDIR=${WORKDIR:-$(mktemp -d /tmp/elks-uip-udp.XXXXXX)} UDP_REPLY_WINDOW=${UDP_REPLY_WINDOW:-20} POST_PHASE_SLEEP=${POST_PHASE_SLEEP:-20} QEMU_PID= QEMU_LOG= QEMU_PTY= SLATTACH_PID= SL_IFACE= UDP_HELPER_PID= UDP_HELPER_LOG= usage() { echo "Usage: $0 [slip|cslip|both|slip-inbound|cslip-inbound]" exit 1 } find_qemu() { if [ -n "${QEMU:-}" ]; then printf '%s\n' "$QEMU" return fi for bin in qemu-system-i386 qemu-system-x86_64; do if command -v "$bin" >/dev/null 2>&1; then command -v "$bin" return fi done echo "QEMU system emulator not found" >&2 exit 1 } QEMU_BIN=$(find_qemu) list_sl_ifaces() { ip -o link show 2>/dev/null | awk -F': ' '/^[0-9]+: sl[0-9]+:/{print $2}' } cleanup_phase() { if [ -n "${UDP_HELPER_PID:-}" ]; then kill "$UDP_HELPER_PID" >/dev/null 2>&1 || true wait "$UDP_HELPER_PID" 2>/dev/null || true UDP_HELPER_PID= fi UDP_HELPER_LOG= if [ -n "${SLATTACH_PID:-}" ]; then sudo -n kill "$SLATTACH_PID" >/dev/null 2>&1 || true wait "$SLATTACH_PID" 2>/dev/null || true SLATTACH_PID= fi if [ -n "${SL_IFACE:-}" ]; then sudo -n ip addr flush dev "$SL_IFACE" >/dev/null 2>&1 || true sudo -n ip link set dev "$SL_IFACE" down >/dev/null 2>&1 || true SL_IFACE= fi if [ -n "${QEMU_PID:-}" ]; then kill "$QEMU_PID" >/dev/null 2>&1 || true wait "$QEMU_PID" 2>/dev/null || true QEMU_PID= fi QEMU_PTY= QEMU_LOG= } cleanup_all() { cleanup_phase } trap cleanup_all EXIT INT TERM require_host_tools() { if ! command -v sudo >/dev/null 2>&1; then echo "sudo not found" >&2 exit 1 fi if ! sudo -n true >/dev/null 2>&1; then echo "passwordless sudo is required for slattach/ip setup" >&2 exit 1 fi if ! command -v ip >/dev/null 2>&1; then echo "ip command not found" >&2 exit 1 fi if ! command -v python3 >/dev/null 2>&1; then echo "python3 not found" >&2 exit 1 fi if [ ! -x "$MFS" ]; then echo "mfs tool not found at $MFS" >&2 exit 1 fi if [ ! -f "$IMAGE" ]; then echo "image not found at $IMAGE" >&2 exit 1 fi } pick_port() { python3 - <<'PY' import socket with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: sock.bind(("0.0.0.0", 0)) print(sock.getsockname()[1]) PY } render_rc() { rcfile=$1 protocol=$2 mode=$3 host_port=$4 guest_port=$5 message=$6 cat >"$rcfile" <<EOF # System initialization script for qemu $protocol UDP testing exec > /boot.log 2>&1 umask 022 export PATH=/bin export UIP_TRACE=/tmp/uip.trace source /etc/profile clock -s -u echo "starting uip" uip -b -p $protocol -m $MTU -s $BAUD -l /dev/ttyS0 $GUEST_IP $HOST_IP $NETMASK > /uip.start 2>&1 || { echo $? > /uip.start.status sync exit 1 } echo 0 > /uip.start.status sync sleep 6 EOF case "$mode" in outbound) cat >>"$rcfile" <<EOF echo outbound > /udp.ready sync touch /udp.out sync udpcheck $HOST_IP $host_port $guest_port "$message" >> /udp.out 2>&1 status=\$? echo \$status > /udp.status sync sleep 20 EOF ;; inbound) cat >>"$rcfile" <<EOF echo inbound > /udp.ready sync touch /udp.in sync udpcheck -l $guest_port "$message" /udp.listen.ready >> /udp.in 2>&1 echo \$? > /udp.status sync sleep 20 EOF ;; *) echo "unknown rc mode: $mode" >&2 exit 1 ;; esac } prepare_image() { base_image=$1 out_image=$2 protocol=$3 mode=$4 host_port=$5 guest_port=$6 message=$7 rcfile=$WORKDIR/rc.${protocol}.${mode} cp "$base_image" "$out_image" render_rc "$rcfile" "$protocol" "$mode" "$host_port" "$guest_port" "$message" "$MFS" "$out_image" rm /etc/rc.sys >/dev/null 2>&1 || true "$MFS" "$out_image" cp "$rcfile" /etc/rc.sys } start_qemu() { image_file=$1 name=$2 QEMU_LOG=$WORKDIR/${name}.qemu.log "$QEMU_BIN" \ -nodefaults \ -machine isapc \ -cpu 486,tsc \ -m 8M \ -rtc base=utc \ -display none \ -monitor none \ -serial none \ -chardev pty,id=slip0 \ -device isa-serial,chardev=slip0,id=ser0 \ -drive file="$image_file",if=floppy,format=raw \ -boot a >"$QEMU_LOG" 2>&1 & QEMU_PID=$! for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do QEMU_PTY=$(grep -o '/dev/pts/[0-9][0-9]*' "$QEMU_LOG" | tail -n 1 || true) if [ -n "$QEMU_PTY" ]; then return fi sleep 1 done echo "failed to locate qemu pty for $name" >&2 exit 1 } attach_slip() { protocol=$1 before_ifaces=$(list_sl_ifaces | tr '\n' ' ') sudo -n /sbin/slattach -p "$protocol" -L -s "$BAUD" "$QEMU_PTY" >/dev/null 2>&1 & SLATTACH_PID=$! for _ in 1 2 3 4 5 6 7 8 9 10; do for iface in $(list_sl_ifaces); do case " $before_ifaces " in *" $iface "*) ;; *) SL_IFACE=$iface break ;; esac done if [ -n "${SL_IFACE:-}" ]; then break fi sleep 1 done if [ -z "${SL_IFACE:-}" ]; then SL_IFACE=$(list_sl_ifaces | tail -n 1 || true) fi if [ -z "${SL_IFACE:-}" ]; then echo "failed to create slip interface for $protocol" >&2 exit 1 fi sudo -n ip addr flush dev "$SL_IFACE" >/dev/null 2>&1 || true sudo -n ip link set dev "$SL_IFACE" mtu "$MTU" up sudo -n ip addr add "$HOST_IP" peer "$GUEST_IP" dev "$SL_IFACE" } extract_guest_file() { image_file=$1 guest_path=$2 host_path=$3 if "$MFS" -f "$image_file" cat "$guest_path" >"$host_path" 2>/dev/null; then return 0 fi : >"$host_path" return 1 } wait_for_guest_marker() { image_file=$1 guest_path=$2 expected=$3 tmpfile=$WORKDIR/guest.marker count=0 while [ $count -lt 40 ] do if "$MFS" -f "$image_file" cat "$guest_path" >"$tmpfile" 2>/dev/null then if [ -z "$expected" ] || grep -q "^$expected\$" "$tmpfile" then rm -f "$tmpfile" return 0 fi fi count=`expr $count + 1` sleep 1 done rm -f "$tmpfile" return 1 } collect_phase_artifacts() { image_file=$1 protocol=$2 mode=$3 extract_guest_file "$image_file" /boot.log "$WORKDIR/${protocol}.${mode}.boot.log" || true extract_guest_file "$image_file" /tmp/uip.trace "$WORKDIR/${protocol}.${mode}.trace" || true } fail_phase() { message=$1 image_file=$2 protocol=$3 mode=$4 cleanup_phase collect_phase_artifacts "$image_file" "$protocol" "$mode" echo "$message" >&2 exit 1 } start_udp_echo_server() { host_port=$1 message_file=$2 UDP_HELPER_LOG=$WORKDIR/$3.outbound.helper.log python3 - "$HOST_IP" "$host_port" "$message_file" "$UDP_REPLY_WINDOW" >"$UDP_HELPER_LOG" 2>&1 <<'PY' & import socket import sys import time host = sys.argv[1] port = int(sys.argv[2]) outfile = sys.argv[3] reply_window = int(sys.argv[4]) with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: sock.bind((host, port)) sock.settimeout(40) data, addr = sock.recvfrom(2048) print(f"recvfrom={addr[0]}:{addr[1]}") with open(outfile, "wb") as out: out.write(data) deadline = time.time() + reply_window while time.time() < deadline: print(f"sendto={addr[0]}:{addr[1]}") sock.sendto(data, addr) time.sleep(0.5) PY UDP_HELPER_PID=$! sleep 1 if ! kill -0 "$UDP_HELPER_PID" >/dev/null 2>&1; then wait "$UDP_HELPER_PID" 2>/dev/null || true return 1 fi } run_udp_probe() { host_port=$1 guest_port=$2 message=$3 message_file=$4 reply_file=$5 log_name=$6 UDP_HELPER_LOG=$WORKDIR/$log_name.inbound.helper.log python3 - "$HOST_IP" "$host_port" "$GUEST_IP" "$guest_port" "$message" "$message_file" "$reply_file" >"$UDP_HELPER_LOG" 2>&1 <<'PY' import socket import sys import time host_ip = sys.argv[1] host_port = int(sys.argv[2]) guest_ip = sys.argv[3] guest_port = int(sys.argv[4]) message = sys.argv[5].encode("utf-8") message_file = sys.argv[6] reply_file = sys.argv[7] deadline = time.time() + 40 with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: sock.bind((host_ip, host_port)) sock.settimeout(1) while time.time() < deadline: sock.sendto(message, (guest_ip, guest_port)) try: data, _ = sock.recvfrom(2048) except socket.timeout: time.sleep(1) continue with open(message_file, "wb") as out: out.write(message) with open(reply_file, "wb") as out: out.write(data) if data != message: raise SystemExit(2) raise SystemExit(0) raise SystemExit(1) PY } run_outbound() { protocol=$1 host_port=$(pick_port) guest_port=20001 message="uip udp $protocol outbound test" image_file=$WORKDIR/${protocol}.udp.outbound.img status_file=$WORKDIR/${protocol}.udp.out.status output_file=$WORKDIR/${protocol}.udp.out host_file=$WORKDIR/${protocol}.udp.host.out prepare_image "$IMAGE" "$image_file" "$protocol" outbound "$host_port" "$guest_port" "$message" start_qemu "$image_file" "${protocol}.udp.outbound" attach_slip "$protocol" if ! start_udp_echo_server "$host_port" "$host_file" "$protocol"; then fail_phase "$protocol outbound UDP failed: host echo server did not start" \ "$image_file" "$protocol" outbound fi if ! wait "$UDP_HELPER_PID"; then UDP_HELPER_PID= fail_phase "$protocol outbound UDP failed: host echo server did not complete" \ "$image_file" "$protocol" outbound fi UDP_HELPER_PID= sleep "$POST_PHASE_SLEEP" cleanup_phase extract_guest_file "$image_file" /udp.status "$status_file" || true extract_guest_file "$image_file" /udp.out "$output_file" || true collect_phase_artifacts "$image_file" "$protocol" outbound if ! grep -q "$message" "$output_file"; then echo "$protocol outbound UDP failed: missing echoed payload in guest output" >&2 exit 1 fi if ! grep -q "$message" "$host_file"; then echo "$protocol outbound UDP failed: host did not receive expected payload" >&2 exit 1 fi if [ -s "$status_file" ] && [ "$(tr -d '\r\n' <"$status_file")" != "0" ]; then echo "$protocol outbound UDP failed: guest reported status $(tr -d '\r\n' <"$status_file")" >&2 exit 1 fi echo "$protocol outbound UDP: ok" } run_inbound() { protocol=$1 host_port=$(pick_port) guest_port=20002 message="uip udp $protocol inbound test" image_file=$WORKDIR/${protocol}.udp.inbound.img status_file=$WORKDIR/${protocol}.udp.in.status input_file=$WORKDIR/${protocol}.udp.in host_send_file=$WORKDIR/${protocol}.udp.host.sent host_reply_file=$WORKDIR/${protocol}.udp.host.reply prepare_image "$IMAGE" "$image_file" "$protocol" inbound "$host_port" "$guest_port" "$message" start_qemu "$image_file" "${protocol}.udp.inbound" attach_slip "$protocol" if ! wait_for_guest_marker "$image_file" /udp.listen.ready ready; then fail_phase "$protocol inbound UDP failed: guest did not signal readiness" \ "$image_file" "$protocol" inbound fi if ! run_udp_probe "$host_port" "$guest_port" "$message" \ "$host_send_file" "$host_reply_file" "$protocol"; then fail_phase "$protocol inbound UDP failed: host probe did not receive echoed reply" \ "$image_file" "$protocol" inbound fi sleep "$POST_PHASE_SLEEP" cleanup_phase extract_guest_file "$image_file" /udp.status "$status_file" || true extract_guest_file "$image_file" /udp.in "$input_file" || true collect_phase_artifacts "$image_file" "$protocol" inbound if ! grep -q "$message" "$input_file"; then echo "$protocol inbound UDP failed: guest did not read expected payload" >&2 exit 1 fi if ! grep -q "$message" "$host_reply_file"; then echo "$protocol inbound UDP failed: host reply did not match expected payload" >&2 exit 1 fi if [ -s "$status_file" ] && [ "$(tr -d '\r\n' <"$status_file")" != "0" ]; then echo "$protocol inbound UDP failed: guest reported status $(tr -d '\r\n' <"$status_file")" >&2 exit 1 fi echo "$protocol inbound UDP: ok" } run_protocol() { protocol=$1 echo "Testing UDP over $protocol in $WORKDIR" run_outbound "$protocol" run_inbound "$protocol" } require_host_tools case "${1:-both}" in slip) run_protocol slip ;; cslip) run_protocol cslip ;; slip-inbound) echo "Testing UDP inbound over slip in $WORKDIR" run_inbound slip ;; cslip-inbound) echo "Testing UDP inbound over cslip in $WORKDIR" run_inbound cslip ;; both) run_protocol slip run_protocol cslip ;; *) usage ;; esac echo "Artifacts saved in $WORKDIR"
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
master
Visibility
public
Your access
Read
Remote
Configured
File activity
View file history