Add ethernet feature-gate as default.

Disable ethernet-related features and framing based on a feature gate.

Add a no-ethernet option to Travis.

notes:
- allow(unused) is added when not using ethernet feature
- Don't run pretty-print doctest, ethernet is optional.

Closes: #308
Approved by: whitequark
This commit is contained in:
Ruben De Smet 2019-10-04 11:10:20 +02:00 committed by Homu
parent 0df7e51a9f
commit eebd8e431a
9 changed files with 48 additions and 23 deletions

View File

@ -12,32 +12,35 @@ matrix:
env: FEATURES='default' MODE='test' env: FEATURES='default' MODE='test'
### Test select feature permutations, chosen to be as orthogonal as possible ### Test select feature permutations, chosen to be as orthogonal as possible
- rust: nightly - rust: nightly
env: FEATURES='std phy-raw_socket proto-ipv6 socket-udp' MODE='test' env: FEATURES='std ethernet phy-raw_socket proto-ipv6 socket-udp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std phy-tap_interface proto-ipv6 socket-udp' MODE='test' env: FEATURES='std ethernet phy-tap_interface proto-ipv6 socket-udp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv4 proto-igmp socket-raw' MODE='test' env: FEATURES='std ethernet proto-ipv4 proto-igmp socket-raw' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv4 socket-udp socket-tcp' MODE='test' env: FEATURES='std ethernet proto-ipv4 socket-udp socket-tcp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv4 proto-dhcpv4 socket-udp' MODE='test' env: FEATURES='std ethernet proto-ipv4 proto-dhcpv4 socket-udp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv6 socket-udp' MODE='test' env: FEATURES='std ethernet proto-ipv6 socket-udp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv6 socket-tcp' MODE='test' env: FEATURES='std ethernet proto-ipv6 socket-tcp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv4 socket-icmp socket-tcp' MODE='test' env: FEATURES='std ethernet proto-ipv4 socket-icmp socket-tcp' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='std proto-ipv6 socket-icmp socket-tcp' MODE='test' env: FEATURES='std ethernet proto-ipv6 socket-icmp socket-tcp' MODE='test'
### Test select feature permutations, chosen to be as aggressive as possible ### Test select feature permutations, chosen to be as aggressive as possible
- rust: nightly - rust: nightly
env: FEATURES='proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp std' env: FEATURES='ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp std'
MODE='test'
- rust: nightly
env: FEATURES='ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc'
MODE='test' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc' env: FEATURES='proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc'
MODE='test' MODE='test'
- rust: nightly - rust: nightly
env: FEATURES='proto-ipv4 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp' env: FEATURES='ethernet proto-ipv4 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp'
MODE='build' MODE='build'
- rust: nightly - rust: nightly
env: MODE='fuzz run' ARGS='packet_parser -- -max_len=1536 -max_total_time=30' env: MODE='fuzz run' ARGS='packet_parser -- -max_len=1536 -max_total_time=30'

View File

@ -31,6 +31,7 @@ url = "1.0"
std = ["managed/std"] std = ["managed/std"]
alloc = ["managed/alloc"] alloc = ["managed/alloc"]
verbose = [] verbose = []
ethernet = []
"phy-raw_socket" = ["std", "libc"] "phy-raw_socket" = ["std", "libc"]
"phy-tap_interface" = ["std", "libc"] "phy-tap_interface" = ["std", "libc"]
"proto-ipv4" = [] "proto-ipv4" = []
@ -43,6 +44,7 @@ verbose = []
"socket-icmp" = [] "socket-icmp" = []
default = [ default = [
"std", "log", # needed for `cargo test --no-default-features --features default` :/ "std", "log", # needed for `cargo test --no-default-features --features default` :/
"ethernet",
"phy-raw_socket", "phy-tap_interface", "phy-raw_socket", "phy-tap_interface",
"proto-ipv4", "proto-igmp", "proto-ipv6", "proto-ipv4", "proto-igmp", "proto-ipv6",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp" "socket-raw", "socket-icmp", "socket-udp", "socket-tcp"

View File

@ -4,13 +4,19 @@ The `iface` module deals with the *network interfaces*. It filters incoming fram
provides lookup and caching of hardware addresses, and handles management packets. provides lookup and caching of hardware addresses, and handles management packets.
*/ */
#[cfg(feature = "ethernet")]
mod neighbor; mod neighbor;
mod route; mod route;
#[cfg(feature = "ethernet")]
mod ethernet; mod ethernet;
#[cfg(feature = "ethernet")]
pub use self::neighbor::Neighbor as Neighbor; pub use self::neighbor::Neighbor as Neighbor;
#[cfg(feature = "ethernet")]
pub(crate) use self::neighbor::Answer as NeighborAnswer; pub(crate) use self::neighbor::Answer as NeighborAnswer;
#[cfg(feature = "ethernet")]
pub use self::neighbor::Cache as NeighborCache; pub use self::neighbor::Cache as NeighborCache;
pub use self::route::{Route, Routes}; pub use self::route::{Route, Routes};
#[cfg(feature = "ethernet")]
pub use self::ethernet::{Interface as EthernetInterface, pub use self::ethernet::{Interface as EthernetInterface,
InterfaceBuilder as EthernetInterfaceBuilder}; InterfaceBuilder as EthernetInterfaceBuilder};

View File

@ -1,7 +1,7 @@
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![no_std] #![no_std]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![cfg_attr(any(feature = "proto-ipv4", feature = "proto-ipv6"), deny(unused))] #![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "ethernet"), deny(unused))]
//! The _smoltcp_ library is built in a layered structure, with the layers corresponding //! The _smoltcp_ library is built in a layered structure, with the layers corresponding
//! to the levels of API abstraction. Only the highest layers would be used by a typical //! to the levels of API abstraction. Only the highest layers would be used by a typical
@ -91,7 +91,7 @@ compile_error!("at least one socket needs to be enabled"); */
// FIXME(dlrobertson): clippy fails with this lint // FIXME(dlrobertson): clippy fails with this lint
#![cfg_attr(feature = "cargo-clippy", allow(if_same_then_else))] #![cfg_attr(feature = "cargo-clippy", allow(if_same_then_else))]
#[cfg(feature = "proto-ipv6")] #[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate byteorder; extern crate byteorder;

View File

@ -3,7 +3,9 @@
use core::str::FromStr; use core::str::FromStr;
use core::result; use core::result;
use wire::{EthernetAddress, IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "ethernet")]
use wire::EthernetAddress;
use wire::{IpAddress, IpCidr, IpEndpoint};
#[cfg(feature = "proto-ipv4")] #[cfg(feature = "proto-ipv4")]
use wire::{Ipv4Address, Ipv4Cidr}; use wire::{Ipv4Address, Ipv4Cidr};
#[cfg(feature = "proto-ipv6")] #[cfg(feature = "proto-ipv6")]
@ -116,6 +118,7 @@ impl<'a> Parser<'a> {
} }
} }
#[cfg(feature = "ethernet")]
fn accept_mac_joined_with(&mut self, separator: u8) -> Result<EthernetAddress> { fn accept_mac_joined_with(&mut self, separator: u8) -> Result<EthernetAddress> {
let mut octets = [0u8; 6]; let mut octets = [0u8; 6];
for n in 0..6 { for n in 0..6 {
@ -127,6 +130,7 @@ impl<'a> Parser<'a> {
Ok(EthernetAddress(octets)) Ok(EthernetAddress(octets))
} }
#[cfg(feature = "ethernet")]
fn accept_mac(&mut self) -> Result<EthernetAddress> { fn accept_mac(&mut self) -> Result<EthernetAddress> {
if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b'-')) { if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b'-')) {
return Ok(mac) return Ok(mac)
@ -344,6 +348,7 @@ impl<'a> Parser<'a> {
} }
} }
#[cfg(feature = "ethernet")]
impl FromStr for EthernetAddress { impl FromStr for EthernetAddress {
type Err = (); type Err = ();
@ -462,7 +467,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "proto-ipv4")] #[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
fn test_mac() { fn test_mac() {
assert_eq!(EthernetAddress::from_str(""), Err(())); assert_eq!(EthernetAddress::from_str(""), Err(()));
assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"), assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"),

View File

@ -115,6 +115,7 @@ pub use self::raw_socket::RawSocket;
#[cfg(all(feature = "phy-tap_interface", target_os = "linux"))] #[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
pub use self::tap_interface::TapInterface; pub use self::tap_interface::TapInterface;
#[cfg(feature = "ethernet")]
/// A tracer device for Ethernet frames. /// A tracer device for Ethernet frames.
pub type EthernetTracer<T> = Tracer<T, super::wire::EthernetFrame<&'static [u8]>>; pub type EthernetTracer<T> = Tracer<T, super::wire::EthernetFrame<&'static [u8]>>;

View File

@ -5,7 +5,9 @@ use {Error, Result};
use phy::ChecksumCapabilities; use phy::ChecksumCapabilities;
use super::ip::checksum; use super::ip::checksum;
use super::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr}; use super::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
use super::{MldRepr, NdiscRepr}; use super::MldRepr;
#[cfg(feature = "ethernet")]
use super::NdiscRepr;
enum_with_unknown! { enum_with_unknown! {
/// Internet protocol control message type. /// Internet protocol control message type.
@ -537,6 +539,7 @@ pub enum Repr<'a> {
seq_no: u16, seq_no: u16,
data: &'a [u8] data: &'a [u8]
}, },
#[cfg(feature = "ethernet")]
Ndisc(NdiscRepr<'a>), Ndisc(NdiscRepr<'a>),
Mld(MldRepr<'a>), Mld(MldRepr<'a>),
#[doc(hidden)] #[doc(hidden)]
@ -619,6 +622,7 @@ impl<'a> Repr<'a> {
data: packet.payload() data: packet.payload()
}) })
}, },
#[cfg(feature = "ethernet")]
(msg_type, 0) if msg_type.is_ndisc() => { (msg_type, 0) if msg_type.is_ndisc() => {
NdiscRepr::parse(packet).map(|repr| Repr::Ndisc(repr)) NdiscRepr::parse(packet).map(|repr| Repr::Ndisc(repr))
}, },
@ -640,6 +644,7 @@ impl<'a> Repr<'a> {
&Repr::EchoReply { data, .. } => { &Repr::EchoReply { data, .. } => {
field::ECHO_SEQNO.end + data.len() field::ECHO_SEQNO.end + data.len()
}, },
#[cfg(feature = "ethernet")]
&Repr::Ndisc(ndisc) => { &Repr::Ndisc(ndisc) => {
ndisc.buffer_len() ndisc.buffer_len()
}, },
@ -711,6 +716,7 @@ impl<'a> Repr<'a> {
packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len]) packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len])
}, },
#[cfg(feature = "ethernet")]
&Repr::Ndisc(ndisc) => { &Repr::Ndisc(ndisc) => {
ndisc.emit(packet) ndisc.emit(packet)
}, },

View File

@ -77,8 +77,9 @@ mod field {
pub mod pretty_print; pub mod pretty_print;
#[cfg(feature = "ethernet")]
mod ethernet; mod ethernet;
#[cfg(feature = "proto-ipv4")] #[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
mod arp; mod arp;
pub(crate) mod ip; pub(crate) mod ip;
#[cfg(feature = "proto-ipv4")] #[cfg(feature = "proto-ipv4")]
@ -101,9 +102,9 @@ mod icmpv6;
mod icmp; mod icmp;
#[cfg(feature = "proto-igmp")] #[cfg(feature = "proto-igmp")]
mod igmp; mod igmp;
#[cfg(feature = "proto-ipv6")] #[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
mod ndisc; mod ndisc;
#[cfg(feature = "proto-ipv6")] #[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
mod ndiscoption; mod ndiscoption;
#[cfg(feature = "proto-ipv6")] #[cfg(feature = "proto-ipv6")]
mod mld; mod mld;
@ -114,12 +115,13 @@ pub(crate) mod dhcpv4;
pub use self::pretty_print::PrettyPrinter; pub use self::pretty_print::PrettyPrinter;
#[cfg(feature = "ethernet")]
pub use self::ethernet::{EtherType as EthernetProtocol, pub use self::ethernet::{EtherType as EthernetProtocol,
Address as EthernetAddress, Address as EthernetAddress,
Frame as EthernetFrame, Frame as EthernetFrame,
Repr as EthernetRepr}; Repr as EthernetRepr};
#[cfg(feature = "proto-ipv4")] #[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
pub use self::arp::{Hardware as ArpHardware, pub use self::arp::{Hardware as ArpHardware,
Operation as ArpOperation, Operation as ArpOperation,
Packet as ArpPacket, Packet as ArpPacket,
@ -190,12 +192,12 @@ pub use self::icmpv6::{Message as Icmpv6Message,
pub use self::icmp::Repr as IcmpRepr; pub use self::icmp::Repr as IcmpRepr;
#[cfg(feature = "proto-ipv6")] #[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
pub use self::ndisc::{Repr as NdiscRepr, pub use self::ndisc::{Repr as NdiscRepr,
RouterFlags as NdiscRouterFlags, RouterFlags as NdiscRouterFlags,
NeighborFlags as NdiscNeighborFlags}; NeighborFlags as NdiscNeighborFlags};
#[cfg(feature = "proto-ipv6")] #[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
pub use self::ndiscoption::{NdiscOption, pub use self::ndiscoption::{NdiscOption,
Repr as NdiscOptionRepr, Repr as NdiscOptionRepr,
Type as NdiscOptionType, Type as NdiscOptionType,

View File

@ -7,7 +7,7 @@ easily human readable packet listings.
A packet can be formatted using the `PrettyPrinter` wrapper: A packet can be formatted using the `PrettyPrinter` wrapper:
```rust ```rust,ignore
use smoltcp::wire::*; use smoltcp::wire::*;
let buffer = vec![ let buffer = vec![
// Ethernet II // Ethernet II