DEV Community

Michael Muriithi
Michael Muriithi

Posted on

AI-Routed Mesh Networking: 4 Layers of Intelligence

Routing in a mesh network is hard. Nodes move. Links break. Latency changes every second. Traditional routing protocols (OSPF, BGP) assume stable topology — mesh networks don't have that.

GhostWire solves this with a 4-layer AI routing system that adapts in real-time. Each layer handles a different timescale, from microseconds to minutes.

The 4 Layers

┌─────────────────────────────────────┐
│  Layer 4: PRoPHET (epidemic)        │  Minutes — delay-tolerant
├─────────────────────────────────────┤
│  Layer 3: GNN (graph neural net)    │  Seconds — topology-aware
├─────────────────────────────────────┤
│  Layer 2: Gemma 4 (LLM)            │  Sub-second — contextual
├─────────────────────────────────────┤
│  Layer 1: LightGBM (gradient boost) │  Microseconds — fast path
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The system tries Layer 1 first. If it's confident, done. If not, it escalates to Layer 2, then 3, then 4. Each layer is a fallback for the one above it.

Layer 1: LightGBM (Fast Path)

When: Every packet, microseconds budget
What: Predicts the best next hop based on 12 features

struct RoutingFeatures {
    hop_count: u8,
    link_quality: f32,      // RSSI-based
    node_uptime: u32,       // seconds since last seen
    queue_depth: u16,       // pending messages
    bandwidth_estimate: f32, // bytes/sec
    latency_estimate: f32,  // ms
    packet_loss: f32,       // 0.0 - 1.0
    node_battery: f32,      // 0.0 - 1.0
    transport_type: u8,     // TCP=0, BLE=1, LoRa=2, WebRTC=3
    encryption_level: u8,   // none=0, classical=1, pq_hybrid=2
    geodistance: f32,       // km (if GPS available)
    historical_success: f32, // past delivery rate
}
Enter fullscreen mode Exit fullscreen mode

The LightGBM model is trained on historical routing data from the mesh. It runs in <100μs on any hardware. Decision trees are fast.

fn predict_next_hop(features: &RoutingFeatures, model: &LGBMModel) -> NodeId {
    let prediction = model.predict(features.to_vector());
    // Returns probability distribution over candidate next hops
    prediction.argmax()
}
Enter fullscreen mode Exit fullscreen mode

Fallback: If LightGBM confidence < 0.7, escalate to Layer 2.

Layer 2: Gemma 4 (Contextual)

When: Unusual routing scenarios, sub-second budget
What: Uses a small LLM to reason about context

This is where it gets interesting. When the fast path isn't confident, we ask a small language model:

Given: Node A needs to reach Node H.
Available paths: A→B→D→H (3 hops, high latency), A→C→E→H (4 hops, low latency), A→F→G→H (3 hops, unknown).
Network state: B's battery at 15%, E's queue depth 50+, F last seen 2 hours ago.
Recommendation?
Enter fullscreen mode Exit fullscreen mode

Gemma 4 (4B parameters, quantized to INT4) runs on-device. It reasons about tradeoffs that a simple model can't:

  • "B has low battery — it might die mid-route, causing retransmission"
  • "E's queue is full — adding more messages will increase latency"
  • "F hasn't been seen in 2 hours — it might be offline"
async fn gemma_route(
    source: NodeId,
    dest: NodeId,
    candidates: Vec<Path>,
    network_state: NetworkState,
) -> Path {
    let prompt = format!(
        "Source: {}, Dest: {}. Candidates: {:?}. State: {:?}. Best path?",
        source, dest, candidates, network_state
    );

    let response = gemma4.complete(&prompt, MaxTokens(128)).await;
    parse_path_recommendation(response)
}
Enter fullscreen mode Exit fullscreen mode

Fallback: If Gemma 4 is unavailable (low memory, battery), escalate to Layer 3.

Layer 3: Graph Neural Network (Topology)

When: Topology changes, seconds budget
What: Models the entire mesh as a graph, predicts optimal paths

A GNN operates on the mesh topology graph where nodes are vertices and links are edges. It learns patterns like:

  • "Nodes in this cluster tend to have high packet loss"
  • "This bridge node is a single point of failure"
  • "These two nodes have correlated failures (same power source)"
struct MeshGNN {
    // Graph attention network
    attention_heads: usize,  // 8
    hidden_dim: usize,       // 128
    layers: usize,           // 3
}

impl MeshGNN {
    fn predict(&self, graph: &MeshGraph, source: NodeId, dest: NodeId) -> Vec<Path> {
        // Encode node features
        let node_embeddings = self.encode_nodes(graph);

        // Message passing (3 layers)
        let refined = self.message_passing(node_embeddings, graph.adjacency());

        // Predict path probabilities
        self.path_predictor.forward(refined, source, dest)
    }
}
Enter fullscreen mode Exit fullscreen mode

The GNN is retrained periodically on the local mesh's topology data. It learns the specific characteristics of your network, not generic routing patterns.

Fallback: If the graph is too dynamic (nodes moving fast), escalate to Layer 4.

Layer 4: PRoPHET (Epidemic)

When: No route exists, delay-tolerant, minutes budget
What: Flooding-based delivery with delivery predictability

PRoPHET (Probabilistic Routing Protocol using History of Transitivity) is the nuclear option. When no path exists, messages are carried by nodes and delivered when they encounter the destination.

struct ProphetState {
    delivery_predictability: HashMap<(NodeId, NodeId), f32>,
    last_encounter: HashMap<NodeId, Instant>,
    transitive_weight: f32, // 0.75
}

impl ProphetState {
    fn update_on_encounter(&mut self, me: NodeId, them: NodeId) {
        // Direct delivery probability
        let p_direct = 0.75; // Initial value
        let age = self.last_encounter[&them].elapsed().as_secs();
        let p_updated = p_direct * (0.98_f32).powf(age as f32);

        self.delivery_predictability
            .insert((me, them), p_updated);
        self.last_encounter.insert(them, Instant::now());

        // Transitivity: if A meets B, and B has met C,
        // then A's delivery probability to C increases
        for (other, &their_p) in &self.delivery_predictability {
            if *other != me && *other != them {
                let combined = 1.0 - (1.0 - p_updated) * (1.0 - their_p);
                self.delivery_predictability
                    .insert((me, *other), combined);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

PRoPHET is slow but reliable. Messages can take hours or days to deliver — but they will deliver, as long as there's a path (even an indirect one) through the mesh.

Putting It All Together

The routing decision happens in a single function:

async fn route_packet(
    packet: &Packet,
    mesh: &MeshState,
    lightgbm: &LGBMModel,
    gemma: &Gemma4,
    gnn: &MeshGNN,
    prophet: &ProphetState,
) -> NextHop {
    let features = extract_features(packet.dest, mesh);

    // Layer 1: Fast path
    let (hop, confidence) = lightgbm.predict(&features);
    if confidence > 0.7 {
        return NextHop::Direct(hop);
    }

    // Layer 2: Contextual
    if let Some(path) = gemma.route(packet.dest, mesh).await {
        return NextHop::Path(path);
    }

    // Layer 3: Topology
    let paths = gnn.predict(&mesh.graph, packet.source, packet.dest);
    if let Some(best) = paths.first() {
        return NextHop::Path(best.clone());
    }

    // Layer 4: Epidemic
    NextHop::Carry(prophet.next_carry_node(mesh))
}
Enter fullscreen mode Exit fullscreen mode

The whole decision takes <500μs in the common case (Layer 1 wins). Edge cases might take 1-2 seconds (Layer 2). The worst case (Layer 4) stores the message and waits.

What's Next

In the final article, we'll cover coercion resistance and censorship circumvention — duress PINs, panic wipe, dead man's switches, and how GhostWire's transport layer makes blocking difficult.

GitHub: github.com/Phantomojo/GhostWire-secure-mesh-communication

Website: ghostwire.cc


Built from Nairobi, under RVC.

Top comments (0)