jacquard_batman_classic/
lib.rs1#![forbid(unsafe_code)]
33
34mod gossip;
35mod planner;
36mod planner_model;
37mod private_state;
38mod public_state;
39mod runtime;
40mod scoring;
41#[cfg(test)]
42mod validation;
43
44use std::collections::BTreeMap;
45
46use gossip::LearnedAdvertisement;
47use jacquard_core::{
48 Configuration, ConnectivityPosture, NodeId, Observation, RouteId, RoutePartitionClass,
49 RouteProtectionClass, RouteRepairClass, RouteShapeVisibility, RoutingEngineCapabilities,
50 RoutingEngineId,
51};
52pub use planner::{admit_route_from_snapshot, candidate_routes_from_snapshot};
53pub use planner_model::{
54 backend_route_id as batman_classic_backend_route_id, selected_neighbor_from_backend_route_id,
55 BatmanClassicPlannerModel, BatmanClassicPlannerSeed,
56};
57use public_state::{
58 ActiveBatmanClassicRoute, NeighborRanking, OgmReceiveWindow, OriginatorObservationTable,
59 ReceivedOgmInfo,
60};
61pub use public_state::{BatmanClassicPlannerSnapshot, BestNextHop, DecayWindow};
62
63pub const BATMAN_CLASSIC_ENGINE_ID: RoutingEngineId =
64 RoutingEngineId::from_contract_bytes(*b"jacquard.batmanc");
65
66pub const BATMAN_CLASSIC_CAPABILITIES: RoutingEngineCapabilities = RoutingEngineCapabilities {
67 engine: BATMAN_CLASSIC_ENGINE_ID,
68 max_protection: RouteProtectionClass::LinkProtected,
69 max_connectivity: ConnectivityPosture {
70 repair: RouteRepairClass::Repairable,
71 partition: RoutePartitionClass::ConnectedOnly,
72 },
73 repair_support: jacquard_core::RepairSupport::Unsupported,
74 hold_support: jacquard_core::HoldSupport::Unsupported,
75 decidable_admission: jacquard_core::DecidableSupport::Supported,
76 quantitative_bounds: jacquard_core::QuantitativeBoundSupport::ProductiveOnly,
77 reconfiguration_support: jacquard_core::ReconfigurationSupport::ReplaceOnly,
78 route_shape_visibility: RouteShapeVisibility::NextHopOnly,
79};
80
81pub struct BatmanClassicEngine<Transport, Effects> {
82 local_node_id: NodeId,
83 transport: Transport,
84 effects: Effects,
85 latest_topology: Option<Observation<Configuration>>,
87 decay_window: DecayWindow,
88 originator_receive_windows: BTreeMap<NodeId, BTreeMap<NodeId, OgmReceiveWindow>>,
91 received_ogm_info: BTreeMap<NodeId, BTreeMap<NodeId, ReceivedOgmInfo>>,
95 bidirectional_receive_windows: BTreeMap<NodeId, OgmReceiveWindow>,
99 learned_advertisements: BTreeMap<NodeId, LearnedAdvertisement>,
101 originator_observations: OriginatorObservationTable,
102 neighbor_rankings: BTreeMap<NodeId, NeighborRanking>,
103 best_next_hops: BTreeMap<NodeId, BestNextHop>,
104 active_routes: BTreeMap<RouteId, ActiveBatmanClassicRoute>,
105}
106
107impl<Transport, Effects> BatmanClassicEngine<Transport, Effects> {
108 #[must_use]
109 pub fn new(local_node_id: NodeId, transport: Transport, effects: Effects) -> Self {
110 Self::with_decay_window(local_node_id, transport, effects, DecayWindow::default())
111 }
112
113 #[must_use]
114 pub fn with_decay_window(
115 local_node_id: NodeId,
116 transport: Transport,
117 effects: Effects,
118 decay_window: DecayWindow,
119 ) -> Self {
120 Self {
121 local_node_id,
122 transport,
123 effects,
124 latest_topology: None,
125 decay_window,
126 originator_receive_windows: BTreeMap::new(),
127 received_ogm_info: BTreeMap::new(),
128 bidirectional_receive_windows: BTreeMap::new(),
129 learned_advertisements: BTreeMap::new(),
130 originator_observations: BTreeMap::new(),
131 neighbor_rankings: BTreeMap::new(),
132 best_next_hops: BTreeMap::new(),
133 active_routes: BTreeMap::new(),
134 }
135 }
136
137 pub(crate) fn planner_snapshot(&self) -> BatmanClassicPlannerSnapshot {
138 BatmanClassicPlannerSnapshot {
139 local_node_id: self.local_node_id,
140 stale_after_ticks: self.decay_window.stale_after_ticks,
141 best_next_hops: self.best_next_hops.clone(),
142 }
143 }
144}