Echo and Crossover Modes¶
A unit is always in exactly one of three modes (mode= in its config —
see Configuration Reference): echo,
crossover, or replay (covered separately in
Replay and Record). This page covers the two
live-traffic modes.
Defaults¶
- Unit 0 and every other unconfigured unit: standalone echo.
- Units 2 and 3: paired crossover by default (
peer=3andpeer=2respectively) — a config file can override either half of this.
Echo mode¶
A CMD_WRITE on an echo-mode unit delivers to the same unit — whatever
you write comes back to a reader on that same open (or a different open of
the same unit; SANA-II has no concept of "my own" vs "someone else's"
reader on one unit). Addresses are swapped for a plain CMD_WRITE: the
reader sees whatever address you wrote to as the source, and the unit's
own station address as the destination. This is deliberate — there's no
real second party to ask "what's your address", so the simplest useful
behavior is letting the write specify what the reader should see as its
sender.
S2_BROADCAST and S2_MULTICAST on an echo unit use real, unswapped
addressing instead: the source is the unit's actual station address, and
the destination is the real broadcast/multicast address, so a reader's
SANA2IOF_BCAST/SANA2IOF_MCAST flags mean something.
Echo mode does no destination filtering — every reader sees everything,
regardless of S2_ADDMULTICASTADDRESS membership or promiscuous mode.
There's no separate peer to have misaddressed a packet at, so filtering
would only get in the way of the simplest test case.
Crossover mode¶
A crossover pair is two units, each configured with peer=<the other
unit's number>. A CMD_WRITE on one delivers to the peer, with real,
unswapped addressing: the source is the writer's own actual station
address, the destination is exactly what was written. This is what makes
crossover useful for testing real protocol handshakes — each side sees a
real address on the other end, not a self-referential echo.
Crossover mode enforces standard 802.3-style receive filtering on the
peer's side: a candidate reader only receives a packet if its
destination is the peer's own current station address, the broadcast
address (all-1s), a multicast group the peer has joined
(S2_ADDMULTICASTADDRESS), or that specific reader opened with
SANA2OPF_PROM (promiscuous — accepts everything regardless of
destination).
Both halves of a pair must be configured for mode=crossover with a real,
distinct peer — a unit configured mode=crossover with no peer=, or a
peer= pointing at itself, fails to open.
Example¶
# ENV:sana2loop/unit4.config
mode=crossover
peer=5
# ENV:sana2loop/unit5.config
mode=crossover
peer=4
Open unit 5, queue a read, then open unit 4 and write to unit 5's station address — the read on unit 5 completes with the real source address of unit 4, not a self-echo.
Delivery precedence (both modes)¶
Whichever unit a packet resolves to (itself for echo, the peer for crossover), delivery follows the same precedence, strictly:
- Every typed
CMD_READwhoseios2_PacketTypematches, fanned out to every distinct open that has one queued — see "Multiple opens and monitoring" below. First priority, per SANA-II's own typing convention. - Else (no typed reader anywhere claimed it) a queued untyped
S2_READORPHAN("give me whatever's next") — single delivery, to whichever orphan reader wants it. - Else, only if
rxqueueis nonzero, a bounded convenience queue. - Else the packet is dropped and
Sana2DeviceStats.UnknownTypesReceivedis incremented.
rxqueue defaults to 0 — strict drop, no buffering — matching the
teaching point that real SANA-II drivers hold no internal buffers of their
own. See Configuration Reference if you want
a convenience queue instead.
Multiple opens and monitoring¶
Open the same unit more than once (a stack plus a passive monitor, for
example — the same pattern Aminet's sanamon uses against a real driver)
and every open with a matching typed read gets its own independent
copy of each packet, not just whichever opened first. Concretely:
- A packet is delivered once per distinct open with a matching typed
CMD_READ— at most one fill per open per packet, even if that open has several reads of the same type pipelined (queue more to catch the next ones, not duplicates of this one). S2_READORPHANdeliberately stays single-delivery and global: it's the unclaimed-type catch-all SANA-II itself defines it as, not a general sniffing tool — if any open anywhere has a matching typed read queued, every orphan read is skipped entirely for that packet, exactly as if only one reader existed.- An
S2_PacketFilterhook (see SANA-II Conformance), if an open negotiated one, runs per candidate, before the copy hook — a candidate whose filter rejects a packet simply stays queued for a future one; delivery continues to the next candidate exactly as if that reader hadn't matched at all. - Crossover's own destination filtering (station address, broadcast, a
joined multicast group, or
SANA2OPF_PROM) still applies per candidate, unchanged — fan-out and crossover filtering compose normally. rxqueueis only ever consulted if nobody — typed or orphan — received the packet, so a stack-plus-monitor setup should keeprxqueue=0regardless: buffering a packet that was already delivered elsewhere would just hand a later reader a stale duplicate.Sana2DeviceStats/S2_GETTYPESTATScounts describe traffic arriving at the interface, once per packet, regardless of how many opens got a copy — not a per-listener multiplier.
SANA2OPF_MINE (exclusive access)¶
Opening with SANA2OPF_MINE claims the unit exclusively: the open
succeeds only if the unit has no other opens, and no further opens
(MINE or not) succeed until this one closes — OpenDevice() fails
IOERR_UNITBUSY either way. Useful for a consumer that specifically
needs to rule out the fan-out/monitoring behavior above for its own
session.