shadow_rs/network/router/
mod.rs1use std::cell::RefCell;
2use std::net::Ipv4Addr;
3
4use self::codel_queue::CoDelQueue;
5use crate::core::worker::Worker;
6use crate::network::PacketDevice;
7use crate::network::packet::PacketRc;
8use crate::utility::{Magic, ObjectCounter};
9mod codel_queue;
10
11use shadow_shim_helper_rs::emulated_time::EmulatedTime;
12
13pub struct Router {
16 magic: Magic<Self>,
17 _counter: ObjectCounter,
18 address: Ipv4Addr,
19 inbound_packets: RefCell<CoDelQueue>,
21}
22
23impl Router {
24 pub fn new(address: Ipv4Addr) -> Router {
28 Router {
29 magic: Magic::new(),
30 address,
31 _counter: ObjectCounter::new("Router"),
32 inbound_packets: RefCell::new(CoDelQueue::new()),
33 }
34 }
35
36 fn push_inner(&self, packet: PacketRc, now: EmulatedTime) {
37 self.magic.debug_check();
38 self.inbound_packets.borrow_mut().push(packet, now);
39 }
40
41 fn pop_inner(&self, now: EmulatedTime) -> Option<PacketRc> {
42 self.magic.debug_check();
43 self.inbound_packets.borrow_mut().pop(now)
44 }
45
46 fn route_outgoing_packet(&self, packet: PacketRc) {
49 Worker::with_active_host(|src_host| Worker::send_packet(src_host, packet)).unwrap();
51 }
52
53 pub fn route_incoming_packet(&self, packet: PacketRc) {
56 self.push_inner(packet, Worker::current_time().unwrap())
57 }
58}
59
60impl PacketDevice for Router {
61 fn get_address(&self) -> Ipv4Addr {
62 self.address
63 }
64
65 fn pop(&self) -> Option<PacketRc> {
66 self.pop_inner(Worker::current_time().unwrap())
68 }
69
70 fn push(&self, packet: PacketRc) {
71 self.route_outgoing_packet(packet);
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::network::tests::mock_time_millis;
80
81 #[test]
82 fn empty() {
83 let now = mock_time_millis(1000);
84 let router = Router::new(Ipv4Addr::UNSPECIFIED);
85 assert!(router.inbound_packets.borrow().peek().is_none());
86 assert!(router.pop_inner(now).is_none());
87 }
88
89 #[test]
90 #[cfg_attr(miri, ignore)]
92 fn push_pop_simple() {
93 let now = mock_time_millis(1000);
94 let router = Router::new(Ipv4Addr::UNSPECIFIED);
95
96 const N: usize = 10;
97
98 for _ in 1..=N {
99 router.push_inner(PacketRc::new_ipv4_udp_mock(), now);
100 assert!(router.inbound_packets.borrow().peek().is_some());
101 }
102 for _ in 1..=N {
103 assert!(router.inbound_packets.borrow().peek().is_some());
104 assert!(router.pop_inner(now).is_some());
105 }
106
107 assert!(router.inbound_packets.borrow().peek().is_none());
108 assert!(router.pop_inner(now).is_none());
109 }
110}