All docsStellar LinkRF bench · by Stellar Systems v0.1.0

Tools & Utilities

Analysis & Reporting

Retrieving and keeping run reports, reading them with jq, checking provenance and traffic, and comparing runs.

Every scenario run produces a report: its events, its assertion verdicts and every telemetry sample taken during the run. This page shows how to get reports off the board and read them. The report format itself is described in Assertions and Reports.

Getting reports#

Shell
satlinkctl runs --limit 20                                    # recent runs and verdicts
curl -s $SATLINK_API/api/v1/reports | jq '.[0:5]'             # summaries
curl -s $SATLINK_API/api/v1/reports/<run-id> > run.json       # one full report
curl -s $SATLINK_API/api/v1/scenario-runs/<run-id>/events     # its events only

In the Web Console, Library → Reports lists runs; each report has its own page with the events, the assertions and the telemetry series, and an Export JSON button.

Reading a report#

Check these, in this order, before reading any verdict:

  1. Provenance. source must be pl: stub means no bitstream answered and nothing was measured.

    Shell
    jq '{status, verified, aborted, source, sample_interval_ms}' run.json
  2. Traffic. Did anything cross? tx_frames is cumulative, so look at its movement:

    Shell
    jq '[.metric_samples[].tx_frames | select(. != null)] | {first: .[0], last: .[-1]}' run.json

    A report showing lock: false for fifty samples cannot be read at all without this: "the link is broken" and "nothing was transmitted" look the same otherwise.

  3. Did the timeline do what the file says? Look for staged, refused or unavailable events:

    Shell
    jq -r '.events[] | select(.kind | test("staged|refused|unavailable")) | "\(.elapsed_ms)ms \(.kind): \(.description)"' run.json
  4. The assertions, with their measured values and windows:

    Shell
    jq -r '.assertions[] | "\(if .passed then "PASS" else "FAIL" end) \(if .verified then "" else "(NOT VERIFIED) " end)\(.name): \(.message)"' run.json

Useful extractions#

Frames delimited against frames sent, per sample:

Shell
jq -r '.metric_samples[] | [.elapsed_ms, .tx_frames, .rx_frames, .rx_frame_errors, .agc_gain, .lock, .carrier_lock] | @tsv' run.json

Fraction of samples locked (timing and carrier) over the whole run:

Shell
jq '[.metric_samples[]] | {n: length,
     timing: (map(select(.lock)) | length),
     carrier: (map(select(.carrier_lock)) | length)}' run.json

A watched register over time (here the deframer's matched rotation, bits [4:3]):

Shell
jq -r '.metric_samples[] | [.elapsed_ms, (((.watched["rx_demod.deframer.status"] // 0) / 8 | floor) % 4)] | @tsv' run.json

The channel emulator's active state around a step, to prove an impairment reached the link:

Shell
jq -r '.metric_samples[] | select(.elapsed_ms > 29000 and .elapsed_ms < 36000) | [.elapsed_ms, .chan_ctrl, .lock] | @tsv' run.json

Sample and event times are elapsed_ms since the start of the run and are reliable. started_at/ended_at come from the board's clock, which reads 1970 unless it has been set.

Comparing runs#

  • Fix the offered load. Give traffic steps a count so two runs send the same number of packets; otherwise you compare the throughput each run happened to get.
  • Repeat before concluding. This bench has boot-to-boot variability: the same configuration can behave differently on two boots. Repeat a measurement and its control a few times, across reboots, before attributing a difference.
  • Keep the controls in the same run. Running the reference condition first and last licenses reading the middle against them.
  • Beware of beautiful single results. A structured, convincing result from one run has turned out to be an acquisition transient more than once.

Received data is also available outside reports:

  • GET /api/v1/frames: a ring of recent RX blocks (boot-relative times, one entry per DMA block);
  • ws://<board>:8080/ws/frames: the live receive stream, per packet in slot framing;
  • the ZeroMQ frame.rx topic, whose margin field carries soft marker matches and Reed-Solomon corrections per block, and whose quality field carries the FECF verdict when transfer frames are configured (see ZeroMQ Link Service).

Campaign results#

satlinkctl campaign status <id> (or GET /api/v1/campaign-runs/{id}) gives each step's attempts and verdicts, and the scenario run id of every scenario step; fetch those reports as above. The campaign state itself persists across reboots; the scenario reports it points to do not.

Stellar Link · v0.1.0

↑↓ to moveEnter to open