1use netrun_sim::graph::{
11 Edge, Graph, MaxSalvos, Node, PacketCount, Port, PortRef, PortSlotSpec, PortState, PortType,
12 SalvoCondition, SalvoConditionTerm,
13};
14use netrun_sim::net::{
15 NetAction, NetActionResponse, NetActionResponseData, NetSim, PacketLocation,
16};
17use std::collections::HashMap;
18
19fn main() {
20 let graph = create_linear_graph();
22 println!("Created graph with {} nodes", graph.nodes().len());
23
24 let mut net = NetSim::new(graph);
26
27 let packet_id = match net.do_action(&NetAction::CreatePacket(None)) {
29 NetActionResponse::Success(NetActionResponseData::Packet(id), _) => {
30 println!("Created packet: {}", id);
31 id
32 }
33 _ => panic!("Failed to create packet"),
34 };
35
36 let edge_a_b = PacketLocation::Edge(Edge {
38 source: PortRef {
39 node_name: "A".to_string(),
40 port_type: PortType::Output,
41 port_name: "out".to_string(),
42 },
43 target: PortRef {
44 node_name: "B".to_string(),
45 port_type: PortType::Input,
46 port_name: "in".to_string(),
47 },
48 });
49 net.do_action(&NetAction::TransportPacketToLocation(
50 packet_id.clone(),
51 edge_a_b,
52 ));
53 println!("Placed packet on edge A -> B");
54
55 net.run_until_blocked();
57 println!("Ran network until blocked");
58
59 let startable = net.get_startable_epochs();
61 println!("Startable epochs: {}", startable.len());
62
63 if let Some(epoch_id) = startable.first() {
64 match net.do_action(&NetAction::StartEpoch(epoch_id.clone())) {
66 NetActionResponse::Success(NetActionResponseData::StartedEpoch(epoch), _) => {
67 println!("Started epoch {} on node {}", epoch.id, epoch.node_name);
68
69 net.do_action(&NetAction::ConsumePacket(packet_id));
74 println!("Consumed input packet");
75
76 let output_packet =
78 match net.do_action(&NetAction::CreatePacket(Some(epoch.id.clone()))) {
79 NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
80 _ => panic!("Failed to create output packet"),
81 };
82 println!("Created output packet: {}", output_packet);
83
84 net.do_action(&NetAction::LoadPacketIntoOutputPort(
86 output_packet.clone(),
87 "out".to_string(),
88 ));
89 println!("Loaded packet into output port");
90
91 net.do_action(&NetAction::SendOutputSalvo(
93 epoch.id.clone(),
94 "default".to_string(),
95 ));
96 println!("Sent output salvo - packet is now on edge B -> C");
97
98 net.do_action(&NetAction::FinishEpoch(epoch.id));
100 println!("Finished epoch");
101
102 net.run_until_blocked();
104 println!("Ran network until blocked again");
105
106 let startable_c = net.get_startable_epochs();
108 println!(
109 "New startable epochs (should be at C): {}",
110 startable_c.len()
111 );
112 }
113 _ => panic!("Failed to start epoch"),
114 }
115 }
116
117 println!("\nLinear flow example complete!");
118}
119
120fn create_linear_graph() -> Graph {
122 let nodes = vec![
123 create_node("A", vec![], vec!["out"]),
124 create_node("B", vec!["in"], vec!["out"]),
125 create_node("C", vec!["in"], vec![]),
126 ];
127
128 let edges = vec![
129 create_edge("A", "out", "B", "in"),
130 create_edge("B", "out", "C", "in"),
131 ];
132
133 let graph = Graph::new(nodes, edges);
134 assert!(graph.validate().is_empty(), "Graph validation failed");
135 graph
136}
137
138fn create_node(name: &str, in_ports: Vec<&str>, out_ports: Vec<&str>) -> Node {
139 let in_ports_map: HashMap<String, Port> = in_ports
140 .iter()
141 .map(|p| {
142 (
143 p.to_string(),
144 Port {
145 slots_spec: PortSlotSpec::Infinite,
146 },
147 )
148 })
149 .collect();
150
151 let out_ports_map: HashMap<String, Port> = out_ports
152 .iter()
153 .map(|p| {
154 (
155 p.to_string(),
156 Port {
157 slots_spec: PortSlotSpec::Infinite,
158 },
159 )
160 })
161 .collect();
162
163 let mut in_salvo_conditions = HashMap::new();
165 if !in_ports.is_empty() {
166 in_salvo_conditions.insert(
167 "default".to_string(),
168 SalvoCondition {
169 max_salvos: MaxSalvos::Finite(1),
170 ports: in_ports
171 .iter()
172 .map(|s| (s.to_string(), PacketCount::All))
173 .collect(),
174 term: SalvoConditionTerm::Port {
175 port_name: in_ports[0].to_string(),
176 state: PortState::NonEmpty,
177 },
178 },
179 );
180 }
181
182 let mut out_salvo_conditions = HashMap::new();
184 if !out_ports.is_empty() {
185 out_salvo_conditions.insert(
186 "default".to_string(),
187 SalvoCondition {
188 max_salvos: MaxSalvos::Infinite,
189 ports: out_ports
190 .iter()
191 .map(|s| (s.to_string(), PacketCount::All))
192 .collect(),
193 term: SalvoConditionTerm::Port {
194 port_name: out_ports[0].to_string(),
195 state: PortState::NonEmpty,
196 },
197 },
198 );
199 }
200
201 Node {
202 name: name.to_string(),
203 in_ports: in_ports_map,
204 out_ports: out_ports_map,
205 in_salvo_conditions,
206 out_salvo_conditions,
207 }
208}
209
210fn create_edge(src_node: &str, src_port: &str, tgt_node: &str, tgt_port: &str) -> Edge {
211 Edge {
212 source: PortRef {
213 node_name: src_node.to_string(),
214 port_type: PortType::Output,
215 port_name: src_port.to_string(),
216 },
217 target: PortRef {
218 node_name: tgt_node.to_string(),
219 port_type: PortType::Input,
220 port_name: tgt_port.to_string(),
221 },
222 }
223}