Skip to content

Commit 7b3507d

Browse files
committed
Add the up/down Device and Interface methods
Add up/down methods to Device and Interface for placing the underlying device in a up or down state. This interface will also be handy when adding support for MLDv2. Signed-off-by: Dan Robertson <[email protected]>
1 parent ef6c268 commit 7b3507d

File tree

5 files changed

+98
-22
lines changed

5 files changed

+98
-22
lines changed

fuzz/fuzz_targets/tcp_headers.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod utils {
2020
mod mock {
2121
use std::sync::Arc;
2222
use std::sync::atomic::{Ordering, AtomicUsize};
23-
use smoltcp::time::{Duration, Instant};
23+
use smoltcp::time::{Duration, Instant};
2424

2525
// should be AtomicU64 but that's unstable
2626
#[derive(Debug, Clone)]
@@ -119,8 +119,8 @@ fuzz_target!(|data: &[u8]| {
119119
utils::add_middleware_options(&mut opts, &mut free);
120120

121121
let mut matches = utils::parse_options(&opts, free);
122-
let device = utils::parse_middleware_options(&mut matches, Loopback::new(Medium::Ethernet),
123-
/*loopback=*/true);
122+
let loopback = Loopback::new(Medium::Ethernet);
123+
let device = utils::parse_middleware_options(&mut matches, loopback, /*loopback=*/ true);
124124

125125
smoltcp::phy::FuzzInjector::new(device,
126126
EmptyFuzzer(),
@@ -165,6 +165,9 @@ fuzz_target!(|data: &[u8]| {
165165
let mut did_listen = false;
166166
let mut did_connect = false;
167167
let mut done = false;
168+
169+
iface.up().expect("Failed to set device up");
170+
168171
while !done && clock.elapsed() < Instant::from_millis(4_000) {
169172
let _ = iface.poll(&mut socket_set, clock.elapsed());
170173

fuzz/utils.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::env;
1111
use std::process;
1212
use getopts::{Options, Matches};
1313

14-
use smoltcp::phy::{Device, EthernetTracer, FaultInjector};
14+
use smoltcp::phy::{Device, Tracer, FaultInjector};
1515
use smoltcp::phy::{PcapWriter, PcapSink, PcapMode, PcapLinkType};
1616
use smoltcp::time::Duration;
1717

@@ -52,7 +52,7 @@ pub fn add_middleware_options(opts: &mut Options, _free: &mut Vec<&str>) {
5252
}
5353

5454
pub fn parse_middleware_options<D>(matches: &mut Matches, device: D, loopback: bool)
55-
-> FaultInjector<EthernetTracer<PcapWriter<D, Rc<PcapSink>>>>
55+
-> FaultInjector<Tracer<PcapWriter<D, Rc<PcapSink>>>>
5656
where D: for<'a> Device<'a>
5757
{
5858
let drop_chance = matches.opt_str("drop-chance").map(|s| u8::from_str(&s).unwrap())
@@ -78,9 +78,8 @@ pub fn parse_middleware_options<D>(matches: &mut Matches, device: D, loopback: b
7878
let seed = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().subsec_nanos();
7979

8080
let device = PcapWriter::new(device, Rc::new(RefCell::new(pcap_writer)) as Rc<PcapSink>,
81-
if loopback { PcapMode::TxOnly } else { PcapMode::Both },
82-
PcapLinkType::Ethernet);
83-
let device = EthernetTracer::new(device, |_timestamp, _printer| {
81+
if loopback { PcapMode::TxOnly } else { PcapMode::Both });
82+
let device = Tracer::new(device, |_timestamp, _printer| {
8483
#[cfg(feature = "log")]
8584
trace!("{}", _printer);
8685
});

src/iface/interface.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,24 @@ where
568568
&mut self.inner.routes
569569
}
570570

571+
/// Trigger the startup sequence for the interface.
572+
///
573+
/// This method will call [Device::up] on the backing device.
574+
///
575+
/// [Device::up]: ../phy/trait.Device.html#method.up
576+
pub fn up(&mut self) -> Result<()> {
577+
self.device.up()
578+
}
579+
580+
/// Trigger the shutdown sequence for the interface.
581+
///
582+
/// This method will call [Device::down] on the backing device.
583+
///
584+
/// [Device::down]: ../phy/trait.Device.html#method.down
585+
pub fn down(&mut self) -> Result<()> {
586+
self.device.down()
587+
}
588+
571589
/// Transmit packets queued in the given sockets, and receive packets queued
572590
/// in the device.
573591
///
@@ -2107,7 +2125,9 @@ mod test {
21072125
let iface_builder = InterfaceBuilder::new(device).ip_addrs(ip_addrs);
21082126
#[cfg(feature = "proto-igmp")]
21092127
let iface_builder = iface_builder.ipv4_multicast_groups(BTreeMap::new());
2110-
let iface = iface_builder.finalize();
2128+
let mut iface = iface_builder.finalize();
2129+
2130+
iface.up().expect("Failed to bring device up!");
21112131

21122132
(iface, SocketSet::new(vec![]))
21132133
}
@@ -2131,7 +2151,9 @@ mod test {
21312151
.ip_addrs(ip_addrs);
21322152
#[cfg(feature = "proto-igmp")]
21332153
let iface_builder = iface_builder.ipv4_multicast_groups(BTreeMap::new());
2134-
let iface = iface_builder.finalize();
2154+
let mut iface = iface_builder.finalize();
2155+
2156+
iface.up().expect("Failed to bring device up!");
21352157

21362158
(iface, SocketSet::new(vec![]))
21372159
}
@@ -2169,6 +2191,36 @@ mod test {
21692191
InterfaceBuilder::new(Loopback::new(Medium::Ethernet)).finalize();
21702192
}
21712193

2194+
#[test]
2195+
#[cfg(feature = "medium-ethernet")]
2196+
fn test_iface_updown() {
2197+
let (mut iface, _) = create_loopback_ethernet();
2198+
2199+
iface.down().unwrap();
2200+
2201+
assert!(iface.device_mut().transmit().is_none());
2202+
2203+
iface.up().unwrap();
2204+
2205+
let tx_token = match iface.device_mut().transmit() {
2206+
Some(token) => token,
2207+
None => panic!("Failed to bring up device!"),
2208+
};
2209+
2210+
let buf = [0x00; 42];
2211+
2212+
tx_token
2213+
.consume(Instant::from_millis(0), buf.len(), |tx_buf| {
2214+
tx_buf.copy_from_slice(&buf[..]);
2215+
Ok(())
2216+
})
2217+
.unwrap();
2218+
2219+
iface.down().unwrap();
2220+
2221+
assert!(iface.device_mut().receive().is_none());
2222+
}
2223+
21722224
#[test]
21732225
#[cfg(feature = "proto-ipv4")]
21742226
fn test_no_icmp_no_unicast_ipv4() {

src/phy/loopback.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::Result;
1111
/// A loopback device.
1212
#[derive(Debug)]
1313
pub struct Loopback {
14-
queue: VecDeque<Vec<u8>>,
14+
queue: Option<VecDeque<Vec<u8>>>,
1515
medium: Medium,
1616
}
1717

@@ -23,7 +23,7 @@ impl Loopback {
2323
/// in FIFO order.
2424
pub fn new(medium: Medium) -> Loopback {
2525
Loopback {
26-
queue: VecDeque::new(),
26+
queue: None,
2727
medium,
2828
}
2929
}
@@ -42,19 +42,31 @@ impl<'a> Device<'a> for Loopback {
4242
}
4343

4444
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
45-
self.queue.pop_front().map(move |buffer| {
46-
let rx = RxToken { buffer };
47-
let tx = TxToken {
48-
queue: &mut self.queue,
49-
};
50-
(rx, tx)
51-
})
45+
match self.queue {
46+
Some(ref mut queue) => queue.pop_front().map(move |buffer| {
47+
let rx = RxToken { buffer };
48+
let tx = TxToken { queue: queue };
49+
(rx, tx)
50+
}),
51+
None => None,
52+
}
5253
}
5354

5455
fn transmit(&'a mut self) -> Option<Self::TxToken> {
55-
Some(TxToken {
56-
queue: &mut self.queue,
57-
})
56+
match self.queue {
57+
Some(ref mut queue) => Some(TxToken { queue: queue }),
58+
None => None,
59+
}
60+
}
61+
62+
fn up(&'a mut self) -> Result<()> {
63+
self.queue = Some(VecDeque::new());
64+
Ok(())
65+
}
66+
67+
fn down(&'a mut self) -> Result<()> {
68+
self.queue = None;
69+
Ok(())
5870
}
5971
}
6072

src/phy/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,16 @@ pub trait Device<'a> {
310310

311311
/// Get a description of device capabilities.
312312
fn capabilities(&self) -> DeviceCapabilities;
313+
314+
/// Place the device in a on or running state.
315+
fn up(&'a mut self) -> Result<()> {
316+
Ok(())
317+
}
318+
319+
/// Place the device in a off or idle state.
320+
fn down(&'a mut self) -> Result<()> {
321+
Ok(())
322+
}
313323
}
314324

315325
/// A token to receive a single network packet.

0 commit comments

Comments
 (0)