Skip to content

Commit cbe6860

Browse files
committed
Split media features into provides/requires pairs
1 parent 904cf42 commit cbe6860

File tree

13 files changed

+119
-76
lines changed

13 files changed

+119
-76
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ std = ["managed/std", "alloc", "smoltcp-device/std"]
4848
alloc = ["managed/alloc", "defmt?/alloc"]
4949
verbose = []
5050
defmt = ["dep:defmt", "heapless/defmt-03", "smoltcp-device/defmt"]
51-
"medium-ethernet" = ["socket", "smoltcp-device/medium-ethernet"]
52-
"medium-ip" = ["socket", "smoltcp-device/medium-ip"]
53-
"medium-ieee802154" = ["socket", "proto-sixlowpan", "smoltcp-device/medium-ieee802154"]
51+
"medium-ethernet" = ["socket", "smoltcp-device/requires-medium-ethernet"]
52+
"medium-ip" = ["socket", "smoltcp-device/requires-medium-ip"]
53+
"medium-ieee802154" = ["socket", "proto-sixlowpan", "smoltcp-device/requires-medium-ieee802154"]
5454

55-
"phy-raw_socket" = ["std", "libc"]
55+
"phy-raw_socket" = ["std", "libc", "smoltcp-device/provides-medium-ethernet", "smoltcp-device/provides-medium-ieee802154", "smoltcp-device/provides-medium-ip", "medium-ethernet", "medium-ieee802154", "medium-ip"]
5656
"phy-tuntap_interface" = ["std", "libc", "medium-ethernet"]
5757

5858
"proto-ipv4" = []

ci.sh

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,35 @@ RUSTC_VERSIONS=(
1515
FEATURES_TEST=(
1616
"default"
1717
"std,proto-ipv4"
18-
"std,medium-ethernet,phy-raw_socket,proto-ipv6,socket-udp,socket-dns"
19-
"std,medium-ethernet,phy-tuntap_interface,proto-ipv6,socket-udp"
20-
"std,medium-ethernet,proto-ipv4,proto-ipv4-fragmentation,socket-raw,socket-dns"
21-
"std,medium-ethernet,proto-ipv4,multicast,socket-raw,socket-dns"
22-
"std,medium-ethernet,proto-ipv4,socket-udp,socket-tcp,socket-dns"
23-
"std,medium-ethernet,proto-ipv4,proto-dhcpv4,socket-udp"
24-
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv6,multicast,proto-rpl,socket-udp,socket-dns"
25-
"std,medium-ethernet,proto-ipv6,socket-tcp"
26-
"std,medium-ethernet,medium-ip,proto-ipv4,socket-icmp,socket-tcp"
27-
"std,medium-ip,proto-ipv6,socket-icmp,socket-tcp"
28-
"std,medium-ieee802154,proto-sixlowpan,socket-udp"
29-
"std,medium-ieee802154,proto-sixlowpan,proto-sixlowpan-fragmentation,socket-udp"
30-
"std,medium-ieee802154,proto-rpl,proto-sixlowpan,proto-sixlowpan-fragmentation,socket-udp"
31-
"std,medium-ip,proto-ipv4,proto-ipv6,socket-tcp,socket-udp"
32-
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv4,proto-ipv6,multicast,proto-rpl,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
33-
"std,medium-ip,proto-ipv4,proto-ipv6,multicast,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
34-
"std,medium-ieee802154,medium-ip,proto-ipv4,socket-raw"
35-
"std,medium-ethernet,proto-ipv4,proto-ipsec,socket-raw"
18+
"std,medium-ethernet,phy-raw_socket,proto-ipv6,socket-udp,socket-dns,smoltcp-device/provides-medium-ethernet"
19+
"std,medium-ethernet,phy-tuntap_interface,proto-ipv6,socket-udp,smoltcp-device/provides-medium-ethernet"
20+
"std,medium-ethernet,proto-ipv4,proto-ipv4-fragmentation,socket-raw,socket-dns,smoltcp-device/provides-medium-ethernet"
21+
"std,medium-ethernet,proto-ipv4,multicast,socket-raw,socket-dns,smoltcp-device/provides-medium-ethernet"
22+
"std,medium-ethernet,proto-ipv4,socket-udp,socket-tcp,socket-dns,smoltcp-device/provides-medium-ethernet"
23+
"std,medium-ethernet,proto-ipv4,proto-dhcpv4,socket-udp,smoltcp-device/provides-medium-ethernet"
24+
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv6,multicast,proto-rpl,socket-udp,socket-dns,smoltcp-device/provides-medium-ethernet,smoltcp-device/provides-medium-ip,smoltcp-device/provides-medium-ieee802154"
25+
"std,medium-ethernet,proto-ipv6,socket-tcp,smoltcp-device/provides-medium-ethernet"
26+
"std,medium-ethernet,medium-ip,proto-ipv4,socket-icmp,socket-tcp,smoltcp-device/provides-medium-ethernet,smoltcp-device/provides-medium-ip"
27+
"std,medium-ip,proto-ipv6,socket-icmp,socket-tcp,smoltcp-device/provides-medium-ip"
28+
"std,medium-ieee802154,proto-sixlowpan,socket-udp,smoltcp-device/provides-medium-ieee802154"
29+
"std,medium-ieee802154,proto-sixlowpan,proto-sixlowpan-fragmentation,socket-udp,smoltcp-device/provides-medium-ieee802154"
30+
"std,medium-ieee802154,proto-rpl,proto-sixlowpan,proto-sixlowpan-fragmentation,socket-udp,smoltcp-device/provides-medium-ieee802154"
31+
"std,medium-ip,proto-ipv4,proto-ipv6,socket-tcp,socket-udp,smoltcp-device/provides-medium-ip"
32+
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv4,proto-ipv6,multicast,proto-rpl,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async,smoltcp-device/provides-medium-ethernet,smoltcp-device/provides-medium-ip,smoltcp-device/provides-medium-ieee802154"
33+
"std,medium-ip,proto-ipv4,proto-ipv6,multicast,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async,smoltcp-device/provides-medium-ip"
34+
"std,medium-ieee802154,medium-ip,proto-ipv4,socket-raw,smoltcp-device/provides-medium-ieee802154,smoltcp-device/provides-medium-ip"
35+
"std,medium-ethernet,proto-ipv4,proto-ipsec,socket-raw,smoltcp-device/provides-medium-ethernet"
3636
)
3737

3838
FEATURES_TEST_NIGHTLY=(
39-
"alloc,medium-ethernet,proto-ipv4,proto-ipv6,socket-raw,socket-udp,socket-tcp,socket-icmp"
39+
"alloc,medium-ethernet,proto-ipv4,proto-ipv6,socket-raw,socket-udp,socket-tcp,socket-icmp,smoltcp-device/provides-medium-ethernet"
4040
)
4141

4242
FEATURES_CHECK=(
43-
"medium-ip,medium-ethernet,medium-ieee802154,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,proto-ipsec,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
44-
"defmt,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
45-
"defmt,alloc,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
46-
"medium-ieee802154,proto-sixlowpan,socket-dns"
43+
"medium-ip,medium-ethernet,medium-ieee802154,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,proto-ipsec,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async,smoltcp-device/provides-medium-ethernet,smoltcp-device/provides-medium-ip,smoltcp-device/provides-medium-ieee802154"
44+
"defmt,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async,smoltcp-device/provides-medium-ethernet,smoltcp-device/provides-medium-ip"
45+
"defmt,alloc,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async,smoltcp-device/provides-medium-ethernet,smoltcp-device/provides-medium-ip"
46+
"medium-ieee802154,proto-sixlowpan,socket-dns,smoltcp-device/provides-medium-ieee802154"
4747
)
4848

4949
test() {

smoltcp-device/Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ defmt = ["dep:defmt"]
1212

1313
std = []
1414

15-
"medium-ethernet" = []
16-
"medium-ip" = []
17-
"medium-ieee802154" = []
15+
# Set by device driver crates
16+
"provides-medium-ethernet" = []
17+
"provides-medium-ip" = []
18+
"provides-medium-ieee802154" = []
19+
20+
# Set by smoltcp
21+
"requires-medium-ethernet" = []
22+
"requires-medium-ip" = []
23+
"requires-medium-ieee802154" = []
1824

1925
"packetmeta-id" = []

smoltcp-device/src/lib.rs

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This crate deals with the *network devices*. It provides a trait
77
for transmitting and receiving frames, [Device](trait.Device.html).
88
*/
99
#![cfg_attr(
10-
feature = "medium-ethernet",
10+
feature = "provides-medium-ethernet",
1111
doc = r##"
1212
# Examples
1313
@@ -46,10 +46,9 @@ impl smoltcp_device::Device for StmPhy {
4646
}
4747
4848
fn capabilities(&self) -> DeviceCapabilities {
49-
let mut caps = DeviceCapabilities::default();
49+
let mut caps = DeviceCapabilities::new(Medium::Ethernet);
5050
caps.max_transmission_unit = 1536;
5151
caps.max_burst_size = Some(1);
52-
caps.medium = Medium::Ethernet;
5352
caps
5453
}
5554
}
@@ -89,6 +88,41 @@ impl<'a> smoltcp_device::TxToken for StmPhyTxToken<'a> {
8988
#![allow(clippy::unit_arg)]
9089
#![allow(clippy::new_without_default)]
9190

91+
// Check that required media are provided
92+
#[cfg(all(feature = "requires-medium-ip", not(feature = "provides-medium-ip")))]
93+
compile_error!("smoltcp requires the IP medium, but no network device implementation in the project supports it. Either disable the medium in smoltcp, or add a device implementation that provides it.");
94+
95+
#[cfg(all(
96+
feature = "requires-medium-ethernet",
97+
not(feature = "provides-medium-ethernet")
98+
))]
99+
compile_error!("smoltcp requires the Ethernet medium, but no network device implementation in the project supports it. Either disable the medium in smoltcp, or add a device implementation that provides it.");
100+
101+
#[cfg(all(
102+
feature = "requires-medium-ieee802154",
103+
not(feature = "provides-medium-ieee802154")
104+
))]
105+
compile_error!(
106+
"smoltcp requires the IEEE 802.15.4 medium, but no network device implementation in the project supports it. Either disable the medium in smoltcp, or add a device implementation that provides it."
107+
);
108+
109+
// Check that provided media are required. This ensures that smoltcp includes all code necessary to handle the media.
110+
111+
#[cfg(all(feature = "provides-medium-ip", not(feature = "requires-medium-ip")))]
112+
compile_error!("A smoltcp network device provides the IP medium, but smoltcp is not configured to support it. Either disable the medium in your network devices, or enable it in smoltcp.");
113+
114+
#[cfg(all(
115+
feature = "provides-medium-ethernet",
116+
not(feature = "requires-medium-ethernet"),
117+
))]
118+
compile_error!("A smoltcp network device provides the Ethernet medium, but smoltcp is not configured to support it. Either disable the medium in your network devices, or enable it in smoltcp.");
119+
120+
#[cfg(all(
121+
feature = "provides-medium-ieee802154",
122+
not(feature = "requires-medium-ieee802154"),
123+
))]
124+
compile_error!("A smoltcp network device provides the IEEE 802.15.4 medium, but smoltcp is not configured to support it. Either disable the medium in your network devices, or enable it in smoltcp.");
125+
92126
pub mod time;
93127

94128
use time::Instant;
@@ -156,7 +190,7 @@ impl ChecksumCapabilities {
156190
///
157191
/// Higher-level protocols may achieve higher throughput or lower latency if they consider
158192
/// the bandwidth or packet size limitations.
159-
#[derive(Debug, Clone, Default)]
193+
#[derive(Debug, Clone)]
160194
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
161195
#[non_exhaustive]
162196
pub struct DeviceCapabilities {
@@ -197,6 +231,18 @@ pub struct DeviceCapabilities {
197231
pub checksum: ChecksumCapabilities,
198232
}
199233

234+
impl DeviceCapabilities {
235+
/// Creates a new `DeviceCapabilities` struct using the given `medium`.
236+
pub fn new(medium: Medium) -> Self {
237+
Self {
238+
medium,
239+
max_transmission_unit: Default::default(),
240+
max_burst_size: Default::default(),
241+
checksum: Default::default(),
242+
}
243+
}
244+
}
245+
200246
/// Type of medium of a device.
201247
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
202248
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -205,41 +251,20 @@ pub enum Medium {
205251
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
206252
///
207253
/// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
208-
#[cfg(feature = "medium-ethernet")]
254+
#[cfg(feature = "provides-medium-ethernet")]
209255
Ethernet,
210256

211257
/// IP medium. Devices of this type send and receive IP frames, without an
212258
/// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
213259
///
214260
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
215-
#[cfg(feature = "medium-ip")]
261+
#[cfg(feature = "provides-medium-ip")]
216262
Ip,
217263

218-
#[cfg(feature = "medium-ieee802154")]
264+
#[cfg(feature = "provides-medium-ieee802154")]
219265
Ieee802154,
220266
}
221267

222-
impl Default for Medium {
223-
fn default() -> Medium {
224-
#[cfg(feature = "medium-ethernet")]
225-
return Medium::Ethernet;
226-
#[cfg(all(feature = "medium-ip", not(feature = "medium-ethernet")))]
227-
return Medium::Ip;
228-
#[cfg(all(
229-
feature = "medium-ieee802154",
230-
not(feature = "medium-ip"),
231-
not(feature = "medium-ethernet")
232-
))]
233-
return Medium::Ieee802154;
234-
#[cfg(all(
235-
not(feature = "medium-ip"),
236-
not(feature = "medium-ethernet"),
237-
not(feature = "medium-ieee802154")
238-
))]
239-
return panic!("No medium enabled");
240-
}
241-
}
242-
243268
/// An interface for sending and receiving raw network frames.
244269
///
245270
/// The interface is based on _tokens_, which are types that allow to receive/transmit a

src/iface/interface/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ use core::result::Result;
3030
use heapless::Vec;
3131

3232
#[cfg(feature = "_proto-fragmentation")]
33-
use super::fragmentation::FragKey;
34-
#[cfg(any(feature = "proto-ipv4", feature = "proto-sixlowpan"))]
35-
use super::fragmentation::PacketAssemblerSet;
33+
use super::fragmentation::{FragKey, PacketAssemblerSet};
3634
use super::fragmentation::{Fragmenter, FragmentsBuffer};
3735

3836
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]

src/iface/interface/tests/ipv6.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,9 +1258,9 @@ fn get_source_address_empty_interface() {
12581258

12591259
#[rstest]
12601260
#[case(Medium::Ip)]
1261-
#[cfg(feature = "medium-ip")]
1261+
#[cfg(all(feature = "multicast", feature = "medium-ip"))]
12621262
#[case(Medium::Ethernet)]
1263-
#[cfg(feature = "medium-ethernet")]
1263+
#[cfg(all(feature = "multicast", feature = "medium-ethernet"))]
12641264
fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
12651265
fn recv_icmpv6(
12661266
device: &mut crate::tests::TestingDevice,

src/phy/loopback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl Device for Loopback {
3131
type TxToken<'a> = TxToken<'a>;
3232

3333
fn capabilities(&self) -> DeviceCapabilities {
34-
let mut capabilities = DeviceCapabilities::default();
34+
let mut capabilities = DeviceCapabilities::new(self.medium);
3535

3636
capabilities.max_transmission_unit = 65535;
3737
capabilities.medium = self.medium;

src/phy/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ impl phy::Device for StmPhy {
5151
}
5252
5353
fn capabilities(&self) -> DeviceCapabilities {
54-
let mut caps = DeviceCapabilities::default();
54+
let mut caps = DeviceCapabilities::new(Medium::Ethernet);
55+
5556
caps.max_transmission_unit = 1536;
5657
caps.max_burst_size = Some(1);
57-
caps.medium = Medium::Ethernet;
58+
5859
caps
5960
}
6061
}

src/phy/raw_socket.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,9 @@ impl Device for RawSocket {
6969
Self: 'a;
7070

7171
fn capabilities(&self) -> DeviceCapabilities {
72-
let mut capabilities = DeviceCapabilities::default();
72+
let mut capabilities = DeviceCapabilities::new(self.medium);
7373

7474
capabilities.max_transmission_unit = self.mtu;
75-
capabilities.medium = self.medium;
7675

7776
capabilities
7877
}

src/phy/tracer.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ mod tests {
216216

217217
use super::*;
218218

219-
use crate::phy::ChecksumCapabilities;
220219
use crate::{
221220
phy::{Device, Loopback, RxToken, TxToken},
222221
time::Instant,
@@ -235,7 +234,22 @@ mod tests {
235234
}
236235
TRACE_EVENTS.replace(VecDeque::new());
237236

238-
let medium = Medium::default();
237+
fn default_medium() -> Medium {
238+
#[cfg(feature = "medium-ethernet")]
239+
return Medium::Ethernet;
240+
241+
#[cfg(all(feature = "medium-ip", not(feature = "medium-ethernet")))]
242+
return Medium::Ip;
243+
244+
#[cfg(all(
245+
feature = "medium-ieee802154",
246+
not(feature = "medium-ip"),
247+
not(feature = "medium-ethernet")
248+
))]
249+
return Medium::Ieee802154;
250+
}
251+
252+
let medium = default_medium();
239253

240254
let loopback_device = Loopback::new(medium);
241255
let mut tracer_device = Tracer::new(loopback_device, |instant, packet| {
@@ -325,6 +339,7 @@ mod tests {
325339
#[cfg(all(feature = "medium-ip", feature = "proto-ipv4"))]
326340
#[test]
327341
fn test_tracer_packet_display_ip() {
342+
use crate::phy::ChecksumCapabilities;
328343
use crate::wire::{IpProtocol, Ipv4Address, Ipv4Repr};
329344

330345
let repr = Ipv4Repr {

0 commit comments

Comments
 (0)