bba48efd90
SocketCAN to yukart/can/raw and back, per frame or batched, with loss and latency from the kernel timestamp. No loss at a saturated 500 kbit/s bus; batched costs the broker ~1 % of a core. Report in docs/impl/reports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
60 lines
2.3 KiB
Bash
Executable File
60 lines
2.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Raw CAN over MQTT, measured on the car Orin against a vcan0 (project-yukart decision 4).
|
|
# Runs on the Orin; sudo once, to create vcan0. Prints one JSON line per run: the
|
|
# sink's and the bridge's reports, and mosquitto's CPU over the run.
|
|
#
|
|
# usage: bus-bench.sh BUS_BENCH_BINARY CAPTURE.log [secs]
|
|
# env: BATCHES batch windows in ms, 0 = one message per frame ("0 10")
|
|
# FLAGS extra options for both roles, e.g. --nagle
|
|
# GAP_MS cangen gap for the full-bus run (0.15: ~4500 frames/s here, past what
|
|
# 500 kbit/s can carry with 8-byte frames)
|
|
set -euo pipefail
|
|
|
|
BIN="$1"; CAPTURE="$2"; SECS="${3:-20}"
|
|
BATCHES="${BATCHES:-0 10}"; FLAGS="${FLAGS:-}"
|
|
|
|
if ! ip link show vcan0 >/dev/null 2>&1; then
|
|
sudo modprobe vcan
|
|
sudo ip link add vcan0 type vcan
|
|
fi
|
|
sudo ip link set vcan0 up txqueuelen 10000
|
|
|
|
ticks() { awk '{print $14 + $15}' "/proc/$1/stat"; }
|
|
HZ=$(getconf CLK_TCK)
|
|
OUT=$(mktemp -d)
|
|
|
|
# run NAME BATCH_MS GENERATOR...: the generator feeds vcan0 for a little over SECS seconds.
|
|
run() {
|
|
local name="$1" batch="$2"; shift 2
|
|
# shellcheck disable=SC2086
|
|
"$BIN" sink --secs "$SECS" $FLAGS > "$OUT/sink" 2>/dev/null &
|
|
local sink=$!
|
|
sleep 0.5
|
|
# shellcheck disable=SC2086
|
|
"$BIN" bridge --batch-ms "$batch" --secs $((SECS + 3)) $FLAGS > "$OUT/bridge" 2>/dev/null &
|
|
local bridge=$!
|
|
sleep 0.5
|
|
local broker m0 m1 t0 t1
|
|
broker=$(pgrep -x mosquitto); m0=$(ticks "$broker"); t0=$(date +%s.%N)
|
|
timeout "$((SECS + 1))" "$@" >/dev/null 2>&1 || true
|
|
m1=$(ticks "$broker"); t1=$(date +%s.%N)
|
|
wait "$sink" "$bridge"
|
|
python3 - "$name" "$batch" "$FLAGS" "$OUT" "$((m1 - m0))" "$HZ" "$t0" "$t1" <<'PY'
|
|
import json, sys
|
|
name, batch, flags, out, ticks, hz, t0, t1 = sys.argv[1:]
|
|
r = {"run": name, "batch_ms": int(batch), "flags": flags,
|
|
"sink": json.load(open(f"{out}/sink")), "bridge": json.load(open(f"{out}/bridge")),
|
|
"mosquitto_cpu_pct": round(100 * int(ticks) / int(hz) / (float(t1) - float(t0)), 1)}
|
|
for k in ("role",):
|
|
r["sink"].pop(k); r["bridge"].pop(k)
|
|
print(json.dumps(r))
|
|
PY
|
|
}
|
|
|
|
LOOPS=$(( (SECS + 9) / 10 + 1 )) # the capture is 10 s; loop past the run's end
|
|
for batch in $BATCHES; do
|
|
run "car replay" "$batch" canplayer -l "$LOOPS" -I "$CAPTURE" vcan0=can_pcan
|
|
run "full bus" "$batch" cangen vcan0 -g "${GAP_MS:-0.15}" -L 8
|
|
run "flood" "$batch" cangen vcan0 -g 0 -L 8
|
|
done
|