mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Integrate discovery protocol into data plane for multi-hop routing
Wire the discovery protocol into the data plane path so that find_next_hop() consults route_cache as a fallback when coord_cache has no entry. When session initiation fails due to missing routes, trigger discovery (initiate_lookup) instead of immediately sending ICMPv6 Destination Unreachable. On discovery completion, retry session initiation for any pending TUN packets. Changes: - find_next_hop() falls back to route_cache when coord_cache misses - handle_tun_outbound() triggers discovery on session failure - handle_lookup_response() retries session after discovery completes - handle_coords_required() triggers discovery for missing coordinates - Add pending_lookups deduplication with 10-second timeout - Periodic cleanup of stale lookups in tick handler - New test: route_cache fallback verification in find_next_hop
This commit is contained in:
@@ -258,6 +258,65 @@ fn test_routing_bloom_hit_without_coords_returns_none() {
|
||||
assert!(node.find_next_hop(&dest).is_none());
|
||||
}
|
||||
|
||||
// === Route cache fallback ===
|
||||
|
||||
#[test]
|
||||
fn test_routing_route_cache_fallback() {
|
||||
// Verify that find_next_hop() falls back to route_cache when
|
||||
// coord_cache has no entry. This is the key change that enables
|
||||
// discovery-based routing: initiate_lookup() populates route_cache,
|
||||
// and find_next_hop() now consults it.
|
||||
let mut node = make_node();
|
||||
let transport_id = TransportId::new(1);
|
||||
let my_addr = *node.node_addr();
|
||||
|
||||
// Create a peer
|
||||
let link_id = LinkId::new(1);
|
||||
let (conn, id) = make_completed_connection(&mut node, link_id, transport_id, 1000);
|
||||
let peer_addr = *id.node_addr();
|
||||
node.add_connection(conn).unwrap();
|
||||
node.promote_connection(link_id, id, 2000).unwrap();
|
||||
|
||||
// Set up tree: we are root, peer is our child
|
||||
let peer_coords = TreeCoordinate::from_addrs(vec![peer_addr, my_addr]).unwrap();
|
||||
node.tree_state_mut().update_peer(
|
||||
ParentDeclaration::new(peer_addr, my_addr, 1, 1000),
|
||||
peer_coords,
|
||||
);
|
||||
|
||||
// Create a destination "behind" the peer in the tree
|
||||
let dest = make_node_addr(99);
|
||||
let dest_coords = TreeCoordinate::from_addrs(vec![dest, peer_addr, my_addr]).unwrap();
|
||||
|
||||
// Put dest in peer's bloom filter so there's a candidate
|
||||
let peer = node.get_peer_mut(&peer_addr).unwrap();
|
||||
let mut filter = BloomFilter::new();
|
||||
filter.insert(&dest);
|
||||
peer.update_filter(filter, 1, 3000);
|
||||
|
||||
// Verify: coord_cache has nothing for dest
|
||||
let now_ms = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map(|d| d.as_millis() as u64)
|
||||
.unwrap_or(0);
|
||||
assert!(node.coord_cache().get(&dest, now_ms).is_none());
|
||||
|
||||
// Without route_cache entry, should return None (same as before)
|
||||
assert!(node.find_next_hop(&dest).is_none());
|
||||
|
||||
// Now populate route_cache (as discovery would do)
|
||||
node.route_cache_mut().insert(dest, dest_coords, now_ms);
|
||||
|
||||
// find_next_hop should succeed via route_cache fallback
|
||||
let result = node.find_next_hop(&dest);
|
||||
assert!(result.is_some(), "Should route via route_cache fallback");
|
||||
assert_eq!(
|
||||
result.unwrap().node_addr(),
|
||||
&peer_addr,
|
||||
"Should pick peer with bloom filter hit"
|
||||
);
|
||||
}
|
||||
|
||||
// === Integration: converged network ===
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user