Table of Contents
MOSH Transport Layer
The MOSH transport layer is responsible for moving MOSH frames between physical transports, fragmenting large messages, reassembling inbound fragments, and deciding whether a frame should be processed locally or forwarded to another link.
In the current implementation, the transport layer supports both a data plane and a control plane.
Overview
A MOSH transport can currently operate in one of these modes:
- `NATIVE`
- `HOST_BACKED`
- `EXCLUDE`
The intended meanings are:
- `NATIVE`
- The transport directly owns a MOSH data network.
- Frames can be transmitted onto that network.
- Examples: ESP-NOW, WiFi, LoRa, etc.
- `HOST_BACKED`
- The transport is an uplink to a controlling host, such as a USB serial connection to a bridge.
- The host owns the higher-level protocol behavior.
- The attached MCU acts as a radio coprocessor and forwards frames between the host and native transports.
- `EXCLUDE`
- Reserved for transports that should not participate in normal routing.
Physical vs Logical Behavior
The transport layer separates two concerns:
- Physical transport
- Serial, ESP-NOW, WiFi, etc.
- Logical routing
- Which control node should receive a control-plane frame
- Which transport owns a given data network
This lets a device act as:
- a local MOSH endpoint for control messages
- a forwarding node for host-backed traffic
- a native network egress point for one or more data networks
Control Plane
The control plane uses:
- `network_id = 0`
The control plane is intended for:
- radio configuration
- transport configuration
- diagnostics
- status requests
- firmware-level control messages
Control-plane routing is based on control node ID, not on data network ownership.
Each control-plane destination is represented by a control route entry.
A control route defines:
- the control node ID
- whether that control node is local to this device
- which uplink should be used if the control node is remote
Example conceptually:
- `0/1` = local ESP32 radio control endpoint
- `0/2` = downstream radio reachable through another uplink
Data Plane
The data plane uses:
- any `network_id != 0`
The data plane is intended for normal MOSH network traffic.
Data-plane routing is based on network ownership.
Each data route defines:
- the data network ID
- which control node owns that network
- which native transport should be used if the network is local to this device
Example conceptually:
- network `10` is owned locally and transmitted on ESP-NOW
- network `20` is owned by another control node and must be forwarded toward that node
Routing Tables
The current transport manager contains two explicit routing tables:
- Control route table
- Data route table
Control Route Table
Each control route entry contains:
- `controlNodeID`
- `local`
- `uplink`
If `local == true`:
- control-plane frames for that node are delivered to the local RX queue
If `local == false`:
- control-plane frames for that node are forwarded through the configured uplink
Data Route Table
Each data route entry contains:
- `networkID`
- `ownerControlNodeID`
- `nativeTransport`
If `nativeTransport != null`:
- this device owns that data network locally
- outbound data-plane frames are sent through that native transport
If `nativeTransport == null`:
- the data network is owned remotely
- outbound data-plane frames are forwarded toward the owning control node
Queue Model
The transport manager currently maintains:
- a TX queue of logical `MOSH_Frame` objects
- an RX queue of completed logical `MOSH_Frame` objects
TX Queue
The TX queue contains logical outbound frames generated locally by the MCU.
When processed:
- control-plane frames are routed by control node
- data-plane frames are routed by network ownership
- large frames are fragmented if needed before transmission
RX Queue
The RX queue contains inbound logical frames that are ready for local processing.
A frame reaches the RX queue only after:
- raw frame reception
- successful decode
- fragment reassembly if needed
- local delivery decision
`MOSH_Core` drains this RX queue and performs higher-level protocol handling.
Fragmentation
The MOSH wire protocol currently uses a maximum encoded frame size of:
- `1470 bytes`
That full encoded frame contains:
- 13-byte header
- payload
- 2-byte CRC footer
This means the maximum single-frame payload is:
- `1455 bytes`
Any logical payload larger than that must be fragmented.
Fragment Header
When a frame is fragmented, the fragment payload begins with a 4-byte fragment header:
- byte 0: fragment index
- byte 1: fragment count
- byte 2: original payload length low byte
- byte 3: original payload length high byte
The remaining bytes are fragment data.
Reassembly
Inbound fragments are stored in a reassembly buffer keyed by:
- source network ID
- source node ID
- message ID
A complete logical frame is delivered only when:
- all fragments are present
- fragment metadata matches
- the reassembled payload length matches the declared original length
Expired fragment sets are discarded after the configured timeout.
Forwarding Rules
The transport layer now distinguishes between local delivery and forwarding.
Control-Plane Ingress
If an inbound frame is on control network `0`:
- if the destination control node is local:
- deliver to local RX queue
- if the destination control node is remote:
- forward to the configured uplink
- if no route exists:
- drop the frame
Data-Plane Ingress
If an inbound frame is on a non-zero data network:
- if the destination network is locally owned:
- send to the local native transport
- if the destination network is remotely owned:
- forward toward the owning control node
- if no explicit data route exists:
- fallback behavior is used
Fallback Behavior
The current implementation still keeps a compatibility fallback for cases where explicit routing-table entries have not yet been registered.
If no explicit data or control route is found:
- host-backed ingress will still try to forward data-plane frames to a matching native network
- native ingress will still try to forward data-plane frames upward to a host-backed uplink
- local control-plane TX may still use the host-backed source-node fallback
This is useful during transition, but the preferred long-term model is to explicitly populate control and data route tables.
TTL Handling
TTL is now managed consistently.
Rule
- Locally originated frames keep their original TTL
- Any frame forwarded from one transport to another has TTL decremented by exactly 1
This applies to:
- control-plane forwarding
- data-plane forwarding
- host-backed to native forwarding
- native to host-backed forwarding
If a frame has `TTL = 0` at the moment it would need to be forwarded:
- it is not forwarded
Local delivery does not decrement TTL.
Host-Backed Mode
`HOST_BACKED` mode is intended for the case where a bridge controls one or more radios through attached MCUs.
In this model:
- the bridge owns protocol behavior
- the MCU provides radio I/O and forwarding
- the control plane is used to configure the radio itself
- the data plane is used for normal MOSH network traffic
This allows one MCU to act as:
- a local control endpoint
- a forwarder for host-injected data traffic
- a bridge to additional downstream radios
Registration API
The current transport manager exposes APIs for registering route ownership:
- `RegisterLocalControlNode(…)`
- `RegisterRemoteControlNode(…)`
- `RegisterLocalDataNetwork(…)`
- `RegisterRemoteDataNetwork(…)`
These APIs are also exposed through `MOSH_Core`.
They are intended to describe the topology explicitly, for example:
- which control nodes are local
- which control nodes are downstream
- which data networks are locally owned
- which data networks belong to downstream radios
Current Limitations
The current transport layer is functional, but still evolving.
Known limitations include:
- fallback behavior is still present alongside the explicit route tables
- upstream selection for multiple host-backed uplinks is not yet fully topology-driven unless the route tables are populated correctly
- control-plane opcodes and higher-level radio-management messages are not fully implemented yet
- transport ownership discovery is not yet automatic
Intended Next Step
The next planned step is to allow MOSH radios to exchange control-plane MOSH messages that advertise or discover remote data-network ownership.
That would allow routing tables to be learned dynamically rather than fully hard-coded.
