pnet_datalink/
dummy.rs

1// Copyright (c) 2016 Linus Färnstrand <faern@faern.net>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Support for sending and receiving data link layer packets on a fake network managed
10//! by in memory FIFO queues. Useful for writing tests.
11
12use crate::{DataLinkReceiver, DataLinkSender, MacAddr, NetworkInterface};
13
14use std::io;
15use std::sync::mpsc::{self, Receiver, Sender};
16use std::thread;
17use std::time;
18
19/// Configuration for the dummy datalink backend. Contains `std::sync::mpsc`
20/// channels that are used to communicate with the fake network.
21#[derive(Debug)]
22pub struct Config {
23    receiver: Receiver<io::Result<Box<[u8]>>>,
24    inject_handle: Option<Sender<io::Result<Box<[u8]>>>>,
25
26    sender: Sender<Box<[u8]>>,
27    read_handle: Option<Receiver<Box<[u8]>>>,
28}
29
30impl Config {
31    /// Creates a new `Config` with the given channels as the backing network.
32    /// When using this constructor `inject_handle` and `read_handle` will return `None`.
33    /// Those handles must be kept track of elsewhere.
34    ///
35    /// The `DataLinkReceiver` created by the dummy backend will read packets from
36    /// `receiver`. Both network errors and data can be sent on this channel.
37    /// When the `receiver` channel is closed (`Sender` is dropped)
38    /// `DataLinkReceiver::next()` will sleep forever, simlating an idle network.
39    ///
40    /// The `DataLinkSender` created by the dummy backend will send all packets sent
41    /// through `build_and_send()` and `send_to()` to the `sender` channel.
42    pub fn new(receiver: Receiver<io::Result<Box<[u8]>>>, sender: Sender<Box<[u8]>>) -> Config {
43        Config {
44            receiver: receiver,
45            inject_handle: None,
46            sender: sender,
47            read_handle: None,
48        }
49    }
50
51    /// Get the `Sender` handle that can inject packets in the fake network.
52    /// Only usable with `Config`s generated from `default()`.
53    pub fn inject_handle(&mut self) -> Option<Sender<io::Result<Box<[u8]>>>> {
54        self.inject_handle.take()
55    }
56
57    /// Get the `Receiver` handle where packets sent to the fake network can be read.
58    /// Only usable with `Config`s generated from `default()`.
59    pub fn read_handle(&mut self) -> Option<Receiver<Box<[u8]>>> {
60        self.read_handle.take()
61    }
62}
63
64impl<'a> From<&'a super::Config> for Config {
65    /// Will not use the `super::Config`. This will simply call `dummy::Config::default()`.
66    fn from(_config: &super::Config) -> Config {
67        Config::default()
68    }
69}
70
71impl Default for Config {
72    /// Creates a default config with one input and one output channel. The handles used to inject
73    /// to and read form the network can be fetched with `inject_handle()` and `read_handle()`.
74    fn default() -> Config {
75        let (in_tx, in_rx) = mpsc::channel();
76        let (out_tx, out_rx) = mpsc::channel();
77        Config {
78            receiver: in_rx,
79            inject_handle: Some(in_tx),
80            sender: out_tx,
81            read_handle: Some(out_rx),
82        }
83    }
84}
85
86/// Create a data link channel backed by FIFO queues. Useful for debugging and testing.
87/// See `Config` for how to inject and read packets on this fake network.
88pub fn channel(_: &NetworkInterface, config: Config) -> io::Result<super::Channel> {
89    let sender = Box::new(MockDataLinkSender {
90        sender: config.sender,
91    });
92    let receiver = Box::new(MockDataLinkReceiver {
93        receiver: config.receiver,
94        used_packets: Vec::new(),
95    });
96
97    Ok(super::Channel::Ethernet(sender, receiver))
98}
99
100struct MockDataLinkSender {
101    sender: Sender<Box<[u8]>>,
102}
103
104impl DataLinkSender for MockDataLinkSender {
105    fn build_and_send(
106        &mut self,
107        num_packets: usize,
108        packet_size: usize,
109        func: &mut dyn FnMut(&mut [u8]),
110    ) -> Option<io::Result<()>> {
111        for _ in 0..num_packets {
112            let mut buffer = vec![0; packet_size];
113            func(&mut buffer);
114            // Send the data to the queue. Don't care if it's closed
115            self.sender.send(buffer.into_boxed_slice()).unwrap_or(());
116        }
117        Some(Ok(()))
118    }
119
120    fn send_to(&mut self, packet: &[u8], _dst: Option<NetworkInterface>) -> Option<io::Result<()>> {
121        let buffer = packet.to_vec();
122        self.sender.send(buffer.into_boxed_slice()).unwrap_or(());
123        Some(Ok(()))
124    }
125}
126
127struct MockDataLinkReceiver {
128    receiver: Receiver<io::Result<Box<[u8]>>>,
129    used_packets: Vec<Box<[u8]>>,
130}
131
132impl DataLinkReceiver for MockDataLinkReceiver {
133    fn next(&mut self) -> io::Result<&[u8]> {
134        match self.receiver.recv() {
135            Ok(result) => {
136                // A network event happened. Might be a packet or a simulated error
137                match result {
138                    Ok(buffer) => {
139                        self.used_packets.push(buffer);
140                        let buffer_ref = &*self.used_packets[self.used_packets.len() - 1];
141                        Ok(buffer_ref)
142                    }
143                    Err(e) => Err(e),
144                }
145            }
146            Err(_) => {
147                // The channel supplying fake packets is broken. The user lost/destroyed their
148                // inject_handle. This means there will never be any more packets sent to this
149                // dummy network. To simulate an idle network we block and sleep forever here.
150                loop {
151                    thread::sleep(time::Duration::new(10, 0));
152                }
153            }
154        }
155    }
156}
157
158/// Get three fake interfaces generated with `dummy_interface(0..3)`.
159pub fn interfaces() -> Vec<NetworkInterface> {
160    (0..3).map(|i| dummy_interface(i)).collect()
161}
162
163/// Generates a fake `NetworkInterface`.
164/// The name of the interface will be `ethX` where X is the integer `i`.
165/// The index will be `i`.
166/// The MAC will be `01:02:03:04:05:i`.
167pub fn dummy_interface(i: u8) -> NetworkInterface {
168    NetworkInterface {
169        name: format!("eth{}", i),
170        description: "".to_string(),
171        index: i as u32,
172        mac: Some(MacAddr::new(1, 2, 3, 4, 5, i)),
173        ips: Vec::new(),
174        flags: 0,
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use crate::{DataLinkReceiver, DataLinkSender};
181
182    use std::io;
183    use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
184    use std::thread::{sleep, spawn};
185    use std::time::Duration;
186
187    #[test]
188    fn send_nothing() {
189        let (_, read_handle, mut tx, _) = create_net();
190        // Check that sending zero packets yields zero packets
191        let mut builder = |_: &mut [u8]| {
192            panic!("Should not be called");
193        };
194        tx.build_and_send(0, 20, &mut builder).unwrap().unwrap();
195        assert!(read_handle.try_recv().is_err());
196    }
197
198    #[test]
199    fn send_one_packet() {
200        let (_, read_handle, mut tx, _) = create_net();
201        // Check that sending one packet yields one packet
202        let mut builder = |pkg: &mut [u8]| {
203            assert_eq!(pkg.len(), 20);
204            pkg[0] = 9;
205            pkg[19] = 201;
206        };
207        tx.build_and_send(1, 20, &mut builder).unwrap().unwrap();
208        let pkg = read_handle
209            .try_recv()
210            .expect("Expected one packet to be sent");
211        assert!(read_handle.try_recv().is_err());
212        assert_eq!(pkg.len(), 20);
213        assert_eq!(pkg[0], 9);
214        assert_eq!(pkg[19], 201);
215    }
216
217    #[test]
218    fn send_multiple_packets() {
219        let (_, read_handle, mut tx, _) = create_net();
220        // Check that sending multiple packets does the correct thing
221        let mut closure_counter = 0;
222        let mut builder = |pkg: &mut [u8]| {
223            pkg[0] = closure_counter;
224            closure_counter += 1;
225        };
226        tx.build_and_send(3, 20, &mut builder).unwrap().unwrap();
227        for i in 0..3 {
228            let pkg = read_handle.try_recv().expect("Expected a packet");
229            assert_eq!(pkg[0], i);
230        }
231        assert!(read_handle.try_recv().is_err());
232    }
233
234    #[test]
235    fn send_to() {
236        let (_, read_handle, mut tx, _) = create_net();
237        let mut buffer = vec![0; 20];
238        buffer[1] = 34;
239        buffer[18] = 76;
240
241        tx.send_to(&buffer, None).unwrap().unwrap();
242        let pkg = read_handle
243            .try_recv()
244            .expect("Expected one packet to be sent");
245        assert!(read_handle.try_recv().is_err());
246        assert_eq!(pkg.len(), 20);
247        assert_eq!(pkg[1], 34);
248        assert_eq!(pkg[18], 76);
249    }
250
251    #[test]
252    fn read_nothing() {
253        let (_, _, _, mut rx) = create_net();
254        let (control_tx, control_rx) = mpsc::channel();
255        spawn(move || {
256            rx.next().expect("Should not happen 1");
257            control_tx.send(()).expect("Should not happen 2");
258        });
259        sleep(Duration::new(0, 1_000_000));
260        match control_rx.try_recv() {
261            Ok(_) => panic!("Nothing should have arrived"),
262            Err(TryRecvError::Disconnected) => panic!("Thread should not have quit"),
263            Err(TryRecvError::Empty) => (),
264        }
265    }
266
267    #[test]
268    fn read_one_pkg() {
269        let (inject_handle, _, _, mut rx) = create_net();
270
271        let buffer = vec![0; 20];
272        inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();
273
274        let pkg = rx.next().expect("Expected a packet");
275        assert_eq!(pkg.len(), 20);
276    }
277
278    #[test]
279    fn read_multiple_pkgs() {
280        let (inject_handle, _, _, mut rx) = create_net();
281
282        for i in 0..3 {
283            let buffer = vec![i; 20];
284            inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();
285        }
286
287        {
288            let pkg1 = rx.next().expect("Expected a packet");
289            assert_eq!(pkg1[0], 0);
290        }
291        {
292            let pkg2 = rx.next().expect("Expected a packet");
293            assert_eq!(pkg2[0], 1);
294        }
295        {
296            let pkg3 = rx.next().expect("Expected a packet");
297            assert_eq!(pkg3[0], 2);
298        }
299    }
300
301    fn create_net() -> (
302        Sender<io::Result<Box<[u8]>>>,
303        Receiver<Box<[u8]>>,
304        Box<dyn DataLinkSender>,
305        Box<dyn DataLinkReceiver>,
306    ) {
307        let interface = super::dummy_interface(56);
308        let mut config = super::Config::default();
309        let inject_handle = config.inject_handle().unwrap();
310        let read_handle = config.read_handle().unwrap();
311
312        let channel = super::channel(&interface, config);
313        let (tx, rx) = match channel {
314            Ok(super::super::Channel::Ethernet(tx, rx)) => (tx, rx),
315            _ => panic!("Not a valid channel returned"),
316        };
317        (inject_handle, read_handle, tx, rx)
318    }
319}