Skip to content

Commit ec6a56d

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.
1 parent 027f255 commit ec6a56d

File tree

6 files changed

+99
-21
lines changed

6 files changed

+99
-21
lines changed

examples/loopback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ mod mock {
4343
mod mock {
4444
use std::sync::Arc;
4545
use std::sync::atomic::{Ordering, AtomicUsize};
46-
use smoltcp::time::{Duration, Instant};
46+
use smoltcp::time::{Duration, Instant};
4747

4848
// should be AtomicU64 but that's unstable
4949
#[derive(Debug, Clone)]

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: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,24 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
517517
&mut self.inner.routes
518518
}
519519

520+
/// Trigger the startup sequence for the interface.
521+
///
522+
/// This method will call [Device::up] on the backing device.
523+
///
524+
/// [Device::up]: ../phy/trait.Device.html#method.up
525+
pub fn up(&mut self) -> Result<()> {
526+
self.device.up()
527+
}
528+
529+
/// Trigger the shutdown sequence for the interface.
530+
///
531+
/// This method will call [Device::down] on the backing device.
532+
///
533+
/// [Device::down]: ../phy/trait.Device.html#method.down
534+
pub fn down(&mut self) -> Result<()> {
535+
self.device.down()
536+
}
537+
520538
/// Transmit packets queued in the given sockets, and receive packets queued
521539
/// in the device.
522540
///
@@ -1862,9 +1880,11 @@ mod test {
18621880
#[cfg(feature = "proto-igmp")]
18631881
let iface_builder = iface_builder
18641882
.ipv4_multicast_groups(BTreeMap::new());
1865-
let iface = iface_builder
1883+
let mut iface = iface_builder
18661884
.finalize();
18671885

1886+
iface.up().expect("Failed to bring device up!");
1887+
18681888
(iface, SocketSet::new(vec![]))
18691889
}
18701890

@@ -1888,9 +1908,11 @@ mod test {
18881908
#[cfg(feature = "proto-igmp")]
18891909
let iface_builder = iface_builder
18901910
.ipv4_multicast_groups(BTreeMap::new());
1891-
let iface = iface_builder
1911+
let mut iface = iface_builder
18921912
.finalize();
18931913

1914+
iface.up().expect("Failed to bring device up!");
1915+
18941916
(iface, SocketSet::new(vec![]))
18951917
}
18961918

@@ -1924,6 +1946,34 @@ mod test {
19241946
InterfaceBuilder::new(Loopback::new(Medium::Ethernet)).finalize();
19251947
}
19261948

1949+
#[test]
1950+
#[cfg(feature = "medium-ethernet")]
1951+
fn test_iface_updown() {
1952+
let (mut iface, _) = create_loopback_ethernet();
1953+
1954+
iface.down().unwrap();
1955+
1956+
assert!(iface.device_mut().transmit().is_none());
1957+
1958+
iface.up().unwrap();
1959+
1960+
let tx_token = match iface.device_mut().transmit() {
1961+
Some(token) => token,
1962+
None => panic!("Failed to bring up device!"),
1963+
};
1964+
1965+
let buf = [0x00; 42];
1966+
1967+
tx_token.consume(Instant::from_millis(0), buf.len(), |tx_buf| {
1968+
tx_buf.copy_from_slice(&buf[..]);
1969+
Ok(())
1970+
}).unwrap();
1971+
1972+
iface.down().unwrap();
1973+
1974+
assert!(iface.device_mut().receive().is_none());
1975+
}
1976+
19271977
#[test]
19281978
#[cfg(feature = "proto-ipv4")]
19291979
fn test_no_icmp_no_unicast_ipv4() {

src/phy/loopback.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::time::Instant;
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,17 +42,33 @@ 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 { queue: &mut self.queue };
48-
(rx, tx)
49-
})
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+
}
5053
}
5154

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

src/phy/mod.rs

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

284284
/// Get a description of device capabilities.
285285
fn capabilities(&self) -> DeviceCapabilities;
286+
287+
/// Place the device in a on or running state.
288+
fn up(&'a mut self) -> Result<()> {
289+
Ok(())
290+
}
291+
292+
/// Place the device in a off or idle state.
293+
fn down(&'a mut self) -> Result<()> {
294+
Ok(())
295+
}
286296
}
287297

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

0 commit comments

Comments
 (0)