Skip to content

Let only the wire write the Tx row: the driver's echo, not the send - #538

Merged
thebhef merged 1 commit into
mainfrom
task121-echo-row
Oct 14, 2026
Merged

thebhef merged 1 commit into
mainfrom
task121-echo-row

Conversation

@thebhef

@thebhef thebhef commented Oct 3, 2026

Copy link
Copy Markdown
Owner

A transmit used to append its Tx row the moment the session's channel
accepted the frame, an answer that fails only when the channel is
closed. Every consumer reads trace rows, so a dead bus (a pulled
cable under RBS) kept showing healthy outgoing traffic in the trace,
the plots, the per-message counts, fps.tx, the logger and saved
captures. Now an accepted send appends nothing. The frame enters the
trace when the bus carries it: the driver's post-transmission echo
arrives on the ordinary receive path as a DIRECTION_TX frame and is
ingested like any other. A frame the bus will not carry leaves no row
and is not retried. The enqueue-refused row stays, marked Tx ✗, since
there the queue did say no.

  • Sidecar: every python-can bus is opened with receive_own_messages
    (off only for listen-only). The shared interface fans the echo out
    to every session on the adapter as DIRECTION_TX (owner ruling: the
    sessions on one adapter are one node). The "sent=" tx stat is
    renamed queued_to_driver, which is what it counts.
  • cannet-python-wire: message_to_frame read Message.is_tx, which
    python-can does not have, so every echo would have mapped to Rx; it
    reads is_rx.
  • cannet-core SharedBus: the arbitration winner's frame is echoed to
    its originator as Tx, with the arbitration timestamp, only when it
    reached at least one recipient (none stays NoAcknowledger). So the
    in-process vbus and cannet-server debug vbus show a participant's
    own frames as Tx. Bridge ingress drops Tx frames: they are the far
    side's echo of the bridge's own egress, already carried here, and
    would otherwise reach every participant twice.
  • Python client: CannetBus follows python-can's convention. It takes
    receive_own_messages (default False) and drops the session's own
    echoes (is_rx False) unless asked for them.
  • GUI host: append_tx_row becomes append_refused_tx_row, called only
    on refusal. The manual-send IPC drops tx_confirm_index (its one UI
    caller ignores the return) and Sent becomes Accepted. The ingest
    path is unchanged. It already appends frames in their wire
    direction, and the ADR 0027 verifier already exempts Tx. The
    bus-health error tally now counts only Rx error frames, so the echo
    of an error frame we injected is not tallied as a fault, as before.

Docs, corrected in place: ADR 0021 (fan-out, bridges, NoAck), ADR 0022
(echo is now normalised; the known unknown is gone), ADR 0027, ADR
0039 (plus a dated amendment; the bus-off premise is left for its own
correction), README's transmit and adapter-unavailable passages, the
perf README's tx rate, a Tx row entry in CONTEXT.md, and the proto's
direction comment.

Review: the bridge drop also stops a co-subscriber's transmits on a
bridged adapter, and a bridged replay server's recorded Tx frames,
from fanning in. fps.tx is now the echo rate, so a backend without
echo support reads ~0.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

This was referenced Oct 3, 2026

thebhef commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner Author

Merge activity

  • Oct 14, 9:10 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Oct 14, 11:34 PM UTC: Graphite rebased this pull request as part of a merge.
  • Oct 14, 11:37 PM UTC: @thebhef merged this pull request with Graphite.

@thebhef
thebhef changed the base branch from fix-plot-marker-refresh to graphite-base/538 October 14, 2026 23:28
@thebhef
thebhef changed the base branch from graphite-base/538 to main October 14, 2026 23:32
A transmit used to append its Tx row the moment the session's channel
accepted the frame, an answer that fails only when the channel is
closed. Every consumer reads trace rows, so a dead bus (a pulled
cable under RBS) kept showing healthy outgoing traffic in the trace,
the plots, the per-message counts, fps.tx, the logger and saved
captures. Now an accepted send appends nothing. The frame enters the
trace when the bus carries it: the driver's post-transmission echo
arrives on the ordinary receive path as a DIRECTION_TX frame and is
ingested like any other. A frame the bus will not carry leaves no row
and is not retried. The enqueue-refused row stays, marked Tx ✗, since
there the queue did say no.

- Sidecar: every python-can bus is opened with receive_own_messages
  (off only for listen-only). The shared interface fans the echo out
  to every session on the adapter as DIRECTION_TX (owner ruling: the
  sessions on one adapter are one node). The "sent=" tx stat is
  renamed queued_to_driver, which is what it counts.
- cannet-python-wire: message_to_frame read Message.is_tx, which
  python-can does not have, so every echo would have mapped to Rx; it
  reads is_rx.
- cannet-core SharedBus: the arbitration winner's frame is echoed to
  its originator as Tx, with the arbitration timestamp, only when it
  reached at least one recipient (none stays NoAcknowledger). So the
  in-process vbus and `cannet-server debug vbus` show a participant's
  own frames as Tx. Bridge ingress drops Tx frames: they are the far
  side's echo of the bridge's own egress, already carried here, and
  would otherwise reach every participant twice.
- Python client: CannetBus follows python-can's convention. It takes
  receive_own_messages (default False) and drops the session's own
  echoes (is_rx False) unless asked for them.
- GUI host: append_tx_row becomes append_refused_tx_row, called only
  on refusal. The manual-send IPC drops tx_confirm_index (its one UI
  caller ignores the return) and Sent becomes Accepted. The ingest
  path is unchanged. It already appends frames in their wire
  direction, and the ADR 0027 verifier already exempts Tx. The
  bus-health error tally now counts only Rx error frames, so the echo
  of an error frame we injected is not tallied as a fault, as before.

Docs, corrected in place: ADR 0021 (fan-out, bridges, NoAck), ADR 0022
(echo is now normalised; the known unknown is gone), ADR 0027, ADR
0039 (plus a dated amendment; the bus-off premise is left for its own
correction), README's transmit and adapter-unavailable passages, the
perf README's tx rate, a Tx row entry in CONTEXT.md, and the proto's
direction comment.

Review: the bridge drop also stops a co-subscriber's transmits on a
bridged adapter, and a bridged replay server's recorded Tx frames,
from fanning in. fps.tx is now the echo rate, so a backend without
echo support reads ~0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thebhef
thebhef merged commit f529618 into main Oct 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant