Protocol Deep Dive MeshCore Routing Architecture MeshCore Routing Architecture MeshCore uses a hybrid flood-then-direct routing scheme. Unlike a route-first protocol, MeshCore floods the first actual message to a destination; the path is recorded during that flood and returned to the sender, who then uses it for direct (path-based) routing on later messages. There is no separate route-establishment phase preceding data transmission. Path Discovery Mechanism Path discovery happens as a byproduct of the first message: When Node A first messages Node D, it sends the message flood-routed ( ROUTE_TYPE_FLOOD); there is no dedicated Route Request packet. Each repeater that rebroadcasts the flooded message appends its short path hash (a 1-3 byte prefix of its public key), building a path record as the packet propagates. When the flooded message reaches Node D, D sends a path-return packet ( PAYLOAD_TYPE_PATH, optionally bundling an ACK) back to A along the reverse of the recorded path. Node A receives the path-return and now has the learned path: A → B → C → D. Path Caching Learned paths are stored per contact. Subsequent messages to the same destination use the stored path directly ( ROUTE_TYPE_DIRECT) without re-flooding, reducing overhead on established links. Path Maintenance MeshCore has no explicit Route Error (RERR) message. When a direct-routed message is not acknowledged, the original sender treats the path as failed and re-floods (resets the path to flood). Repeaters do not generate route-error control packets. When a path fails (no ACK), the contact's path is reset to flood; the next message re-discovers a route, letting the network self-heal after topology changes. Advantages Over Pure Flooding After a path is learned, only the repeaters on the stored path forward the message - significantly less airtime consumption for repeated unicast traffic. For repeated unicast traffic in a stable topology, MeshCore can use less channel capacity than flooding. Group/broadcast messages still flood, and unstable topologies erode the advantage. No specific node-count guarantee should be inferred. Repeater nodes can handle more traffic since they are not blindly rebroadcasting everything once paths are established. Disadvantages The first message to a new destination floods the mesh, adding airtime and latency before a path is learned. Stored paths require memory on each node. Topology changes can invalidate a learned path, requiring a re-flood. A single learned path provides no redundancy, so there is a silent dead-window until the stale path triggers a re-flood. Forwarding vs. Endpoint Roles MeshCore's roles are Companion, Repeater, Room Server, and Sensor - not a clean two-way split. Forwarding behavior differs by role: Repeater (and Room Server) nodes: participate in forwarding and carry the network's routing load. Companion (client) and Sensor nodes: generate and receive messages but do not forward traffic for others. (The firmware term is "Companion"; the app/CLI labels contact type 1 "client".) Because clients never relay, a deployment with only client nodes provides no multi-hop coverage - it is point-to-point only. At least one repeater or room-server is required for any node-to-node relaying. Plan repeater infrastructure before relying on the network. MeshCore Packet Format and Encryption This page covers MeshCore's packet encryption as verified from docs/packet_format.md, docs/payloads.md, and src/Utils.cpp in the official MeshCore repository. Encryption at the Packet Level Encrypted payload types (text, group, request/response) use AES-128 in ECB mode with a 2-byte truncated HMAC-SHA256 MAC, in an encrypt-then-MAC construction. Crucially, the 2-byte MAC is prepended to the ciphertext (it precedes the encrypted data), not appended. Note that advertisements ( PAYLOAD_TYPE_ADVERT) and control packets are sent unencrypted, so not all traffic is confidential. The ECB mode and 16-bit MAC limit the strength of this protection - see the security/encryption overview for caveats. Direct message payload: [dest hash (1 byte)] [src hash (1 byte)] [2-byte cipher MAC] [AES-128-ECB ciphertext] Group message payload: [channel hash (1 byte)] [2-byte cipher MAC] [AES-128-ECB ciphertext] In both layouts the 2-byte cipher MAC precedes the AES-128 ciphertext, and a hash prefix (destination/source hash for direct messages, channel hash for group messages) comes before the MAC. This matches Utils::encryptThenMAC (which writes the MAC to the first bytes and the ciphertext after it) and the field order in docs/payloads.md. Route Types Packets carry one of four route types (from packet_format.md): ROUTE_TYPE_FLOOD - broadcast to all repeaters; used for initial contact and group messages ROUTE_TYPE_DIRECT - embeds a specific repeater path; only listed repeaters forward the packet ROUTE_TYPE_TRANSPORT_FLOOD - flood with transport/region code prefix ROUTE_TYPE_TRANSPORT_DIRECT - direct-routed with transport/region code Path Learning (How Direct Routing Works) MeshCore uses a flood-then-direct-route mechanism (not AODV path discovery/acknowledgment): First message to a new destination is flood-routed The destination node returns a PAYLOAD_TYPE_PATH packet containing the full repeater path it received the message through The sender stores this path and uses ROUTE_TYPE_DIRECT for subsequent messages, embedding the learned path Only the specific repeaters in the path forward the packet - all others ignore it This mechanism reduces channel load significantly compared to pure flooding once paths are established. This benefit assumes a stable topology with repeated traffic between the same pairs. In mobile or rapidly-changing deployments (common in emergencies), learned paths break frequently, forcing re-floods and reducing or eliminating the savings - in the worst case the network can degrade toward continuous flooding plus failed direct sends. Source: docs/packet_format.md, docs/payloads.md, and src/Utils.cpp in the official MeshCore repository. MeshCore Network Topology Best Practices MeshCore Network Topology Best Practices Backbone vs. Client Layer A well-designed MeshCore network is organized into two distinct layers: Backbone layer: dedicated repeaters placed on elevated sites with clear line-of-sight between them. These form the routing backbone that carries traffic across the network. They are the infrastructure - always on, high antenna, fixed location. Client layer: user devices (phones, handhelds, base stations) that connect to the nearest backbone node. In MeshCore, companion (client) nodes are endpoints, not relays - per the MeshCore FAQ, clients do not repeat traffic for other nodes. This two-layer separation keeps the forwarding load on the backbone. Clients add no forwarding load, but they still transmit their own messages, advertisements, and path-discovery floods on the shared channel, all of which consume airtime. So adding clients does not add relay load to the backbone, but a very dense client population can still congest the shared channel and indirectly affect performance. Repeater Placement Guidelines The numbers below are rules of thumb for planning, not protocol limits - tune them to your terrain and traffic. Aim for 3 - 5 repeaters per coverage zone, each with line-of-sight to at least 2 others in the backbone. Avoid single points of failure - if one repeater goes offline, the network should remain functional via alternate paths. Ensure overlapping coverage between adjacent repeaters so that clients are never more than 1 hop from the backbone. High sites (hilltops, building rooftops, water towers) dramatically extend backbone range - prioritize elevation over raw transmit power. Hop Budget MeshCore supports up to 64 hops (the protocol ceiling). As a planning rule of thumb, aim for no message traversing more than 6 - 8 backbone hops. Beyond this: Per-hop latency accumulates noticeably. Each additional hop adds another potential failure point. Route re-discovery after a link failure takes longer with more hops in the chain. For wide-area networks that would otherwise require long hop chains, use room servers as message hubs rather than relying on extended peer-to-peer relay chains. Advertisement Tuning Flood advertisements (visible network-wide) should be infrequent - every 12 hours is appropriate for stable infrastructure nodes. Frequent floods waste airtime and provide no benefit when the topology is static. Zero-hop advertisements (local only, for client discovery) can be more frequent - every few minutes is reasonable. Review your advertisement intervals if you observe unexplained airtime congestion on the channel. Mesh Segmentation for Large Networks In a very large network (50+ repeaters), avoid trying to relay everything peer-to-peer across the entire mesh. Instead: Use room servers as message hubs for cross-region delivery. Room servers provide message storage and delivery confirmation. Segment the mesh into regional clusters, each with its own backbone, connected via room servers at the regional boundaries. This reduces the hop count needed for cross-region delivery and localizes the impact of any regional topology change. Monitoring Topology Health The MeshCore app includes a network map feature that shows which repeaters a node can see and the routes between them. Use this to: Verify backbone connections are healthy after deployment. Identify repeaters that have lost contact with their neighbors (indicates a failure or coverage gap). Confirm that new repeaters have been discovered and integrated into the routing fabric. Check hop counts for key routes and identify bottleneck nodes carrying disproportionate traffic.