Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.altnautica.com/llms.txt

Use this file to discover all available pages before exploring further.

Local Mesh (batman-adv)

Distributed Receive needs a way for two or three Ground Agents to find each other and exchange WFB-ng fragments without a central router. We use batman-adv (Better Approach To Mobile Ad-hoc Networking, advanced) - a Linux kernel mesh routing layer that has shipped with mainline since 2011. batman-adv handles every layer-2 routing decision: who can talk to whom, what the best path is when there are multiple hops, when a neighbor has gone silent, and which node should advertise the cloud uplink. It runs as a kernel module (modprobe batman-adv) and exposes a virtual bat0 interface that looks like an ordinary Ethernet bridge to userspace.

Why batman-adv

Three other options were on the table:
OptionWhy we did not pick it
Ad-hoc IPv4 + manual routesNo self-healing, no auto-rejoin, fragile
ZeroTier or Tailscale (overlay VPN)Requires public internet to bootstrap; fails in the field
Custom userspace routerReinventing well-trodden ground; batman-adv has been in the kernel for 14 years
batman-adv gives us self-healing, automatic neighbor discovery, multi-hop routing, and cloud-gateway election out of the box. It handles a node leaving and rejoining the mesh in 3 to 5 seconds without operator action.

The second USB WiFi dongle

batman-adv runs on a second RTL8812EU adapter, separate from the primary RTL8812EU that handles WFB-ng to the drone. Two adapters, same chipset, two jobs:
AdapterRoleDefault channel
Primary RTL8812EUWFB-ng monitor mode for the drone link5 GHz, channel 149
Mesh carrier RTL8812EUbatman-adv mesh between Ground Agents5 GHz, channel 36
The two adapters sit on separated 5 GHz channels so they do not interfere. If you change either channel, plan around it. Both adapters use the same RTL8812EU chipset. One driver, one antenna ecosystem, one inventory. See the supported-hardware page for the current adapter list.

Carrier: 802.11s or IBSS

batman-adv carries traffic over either 802.11s (the IEEE mesh spec, with proper authentication via SAE) or IBSS (ad-hoc, no authentication, fallback for drivers that lack 802.11s support). The default is 802.11s. Configurable in /etc/ados/config.yaml:
ground_station:
  mesh:
    carrier: "802.11s"   # or "ibss"
    channel: 1           # 2.4 GHz channel for the mesh dongle
    bat_iface: "bat0"
802.11s requires the wpasupplicant-mesh-sae (or wpad-mesh-wolfssl) package, which the ground-station install path tries to pull in by default. If neither is available on your distro, fall back to IBSS by setting carrier: ibss.

Mesh ID and PSK

Two adjacent deployments on the same channel must not see each other’s traffic. batman-adv uses two pieces of identity:
  • mesh_id - a short string like ados-XXXXXXXXXX shared by every node in the deployment. It becomes the 802.11s SSID (or IBSS name).
  • mesh_psk - a 32-byte shared key that authenticates 802.11s mesh peers via SAE.
Both are generated automatically on the receiver when the mesh services first come up. The mesh_id is derived from the receiver’s device_id via SHA-256 truncation; the PSK is 32 random bytes from secrets.token_bytes(32) saved to /etc/ados/mesh/psk.key (mode 0600). Relays do not generate these. They receive both as part of the encrypted invite bundle during pairing and write them into the same locations on disk.

What runs on the box

When a node transitions to relay or receiver role, the supervisor starts ados-batman.service, which runs the mesh_manager.py service. That service:
  1. modprobe batman-adv
  2. Brings the second USB WiFi dongle up in mesh or IBSS mode at the configured channel
  3. Joins the deployment by mesh_id and authenticates with the shared PSK
  4. Attaches the wireless interface to bat0 via batctl if add
  5. Brings bat0 up
  6. Sets the gateway mode (batctl gw_mode server or gw_mode client) based on the node’s role and uplink state
  7. Polls batctl n -H and batctl gwl -H every 2 seconds for neighbors and gateways
  8. Publishes mesh state to /run/ados/mesh-state.json so the REST API and the GCS can read it
  9. Publishes MeshEvents on the event bus when neighbors join or leave, when partition is detected, and when the selected gateway changes

Cloud gateway election

Any node on the mesh can carry an internet uplink (4G, Ethernet, WiFi client). batman-adv’s gateway election picks one node to advertise as the gateway and the rest of the mesh routes their cloud-bound traffic through it. mesh_manager enables gw server on a node when:
  • ground_station.cloud_uplink: force_on
  • OR cloud_uplink: auto and /run/ados/uplink-active exists (uplink_router has confirmed the node has a working uplink)
The receiver runs gw client and picks the highest-TQ gateway. When the active gateway dies, batman-adv evicts it within a few seconds and the next-best gateway takes over. The GCS Hardware tab Mesh sub-view shows the gateway list, their bandwidth class, their TQ, and which one is selected. You can pin a specific gateway:
curl -X PUT http://localhost:8080/api/v1/ground-station/mesh/gateway_preference \
  -H "Content-Type: application/json" \
  -d '{"mode": "pinned", "pinned_mac": "AA:BB:CC:DD:EE:01"}'
Or release the pin and go back to auto:
curl -X PUT http://localhost:8080/api/v1/ground-station/mesh/gateway_preference \
  -H "Content-Type: application/json" \
  -d '{"mode": "auto"}'

Diagnostics

# what the agent thinks the mesh state is
curl http://localhost:8080/api/v1/ground-station/mesh

# raw batman-adv views
sudo batctl n           # neighbors
sudo batctl o           # originators (full routing table)
sudo batctl gwl         # advertised gateways
sudo batctl tg          # transglobal table

# is bat0 even up?
ip link show bat0
ip addr show bat0
The mesh_manager service writes its working snapshot to /run/ados/mesh-state.json. The REST /api/v1/ground-station/mesh route reads from that file, not from batctl directly, so a fresh batctl query and a stale REST snapshot can disagree by up to 2 seconds (the poll interval).

Where to next