Add medium-ip, medium-ethernet feature flags.

master
Dario Nieuwenhuis 2020-12-27 23:52:37 +01:00
parent 9ac2cac075
commit af4a1e6436
9 changed files with 119 additions and 94 deletions

View File

@ -26,23 +26,23 @@ jobs:
- std proto-ipv4
# Test features chosen to be as orthogonal as possible.
- std ethernet phy-raw_socket proto-ipv6 socket-udp
- std ethernet phy-tap_interface proto-ipv6 socket-udp
- std ethernet proto-ipv4 proto-igmp socket-raw
- std ethernet proto-ipv4 socket-udp socket-tcp
- std ethernet proto-ipv4 proto-dhcpv4 socket-udp
- std ethernet proto-ipv6 socket-udp
- std ethernet proto-ipv6 socket-tcp
- std ethernet proto-ipv4 socket-icmp socket-tcp
- std ethernet proto-ipv6 socket-icmp socket-tcp
- std medium-ethernet phy-raw_socket proto-ipv6 socket-udp
- std medium-ethernet phy-tap_interface proto-ipv6 socket-udp
- std medium-ethernet proto-ipv4 proto-igmp socket-raw
- std medium-ethernet proto-ipv4 socket-udp socket-tcp
- std medium-ethernet proto-ipv4 proto-dhcpv4 socket-udp
- std medium-ethernet proto-ipv6 socket-udp
- std medium-ethernet proto-ipv6 socket-tcp
- std medium-ethernet proto-ipv4 socket-icmp socket-tcp
- std medium-ethernet proto-ipv6 socket-icmp socket-tcp
# Test features chosen to be as aggressive as possible.
- std ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp async
- std medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp async
include:
# Test alloc feature which requires nightly.
- rust: nightly
features: alloc ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
features: alloc medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
- rust: nightly
features: alloc proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
steps:
@ -69,7 +69,7 @@ jobs:
features:
# These feature sets cannot run tests, so we only check they build.
- ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
- medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
steps:
- uses: actions/checkout@v2

View File

@ -32,7 +32,8 @@ url = "1.0"
std = ["managed/std"]
alloc = ["managed/alloc"]
verbose = []
ethernet = ["socket"]
"medium-ethernet" = ["socket"]
"medium-ip" = ["socket"]
"phy-raw_socket" = ["std", "libc", "ethernet"]
"phy-tap_interface" = ["std", "libc", "ethernet"]
"proto-ipv4" = []
@ -47,7 +48,7 @@ ethernet = ["socket"]
"async" = []
default = [
"std", "log", # needed for `cargo test --no-default-features --features default` :/
"ethernet",
"medium-ethernet", "medium-ip",
"phy-raw_socket", "phy-tap_interface",
"proto-ipv4", "proto-igmp", "proto-dhcpv4", "proto-ipv6",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp",

View File

@ -10,7 +10,7 @@ use crate::phy::{Device, DeviceCapabilities, RxToken, TxToken, Medium};
use crate::time::{Duration, Instant};
use crate::wire::*;
use crate::socket::*;
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
use crate::iface::{NeighborCache, NeighborAnswer};
use crate::iface::Routes;
@ -32,9 +32,9 @@ pub struct Interface<'a, DeviceT: for<'d> Device<'d>> {
/// methods on the `Interface` in this time (since its `device` field is borrowed
/// exclusively). However, it is still possible to call methods on its `inner` field.
struct InterfaceInner<'a> {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
neighbor_cache: Option<NeighborCache<'a>>,
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
ethernet_addr: Option<EthernetAddress>,
ip_addrs: ManagedSlice<'a, IpCidr>,
#[cfg(feature = "proto-ipv4")]
@ -51,9 +51,9 @@ struct InterfaceInner<'a> {
/// A builder structure used for creating a network interface.
pub struct InterfaceBuilder <'a, DeviceT: for<'d> Device<'d>> {
device: DeviceT,
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
ethernet_addr: Option<EthernetAddress>,
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
neighbor_cache: Option<NeighborCache<'a>>,
ip_addrs: ManagedSlice<'a, IpCidr>,
#[cfg(feature = "proto-ipv4")]
@ -68,7 +68,7 @@ impl<'a, DeviceT> InterfaceBuilder<'a, DeviceT>
where DeviceT: for<'d> Device<'d> {
/// Create a builder used for creating a network interface using the
/// given device and address.
#[cfg_attr(feature = "ethernet", doc = r##"
#[cfg_attr(feature = "medium-ethernet", doc = r##"
# Examples
```
@ -95,9 +95,9 @@ let iface = InterfaceBuilder::new(device)
pub fn new(device: DeviceT) -> Self {
InterfaceBuilder {
device: device,
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
ethernet_addr: None,
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
neighbor_cache: None,
ip_addrs: ManagedSlice::Borrowed(&mut []),
#[cfg(feature = "proto-ipv4")]
@ -115,7 +115,7 @@ let iface = InterfaceBuilder::new(device)
/// This function panics if the address is not unicast.
///
/// [ethernet_addr]: struct.Interface.html#method.ethernet_addr
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub fn ethernet_addr(mut self, addr: EthernetAddress) -> Self {
InterfaceInner::check_ethernet_addr(&addr);
self.ethernet_addr = Some(addr);
@ -187,7 +187,7 @@ let iface = InterfaceBuilder::new(device)
}
/// Set the Neighbor Cache the interface will use.
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'a>) -> Self {
self.neighbor_cache = Some(neighbor_cache);
self
@ -207,35 +207,31 @@ let iface = InterfaceBuilder::new(device)
pub fn finalize(self) -> Interface<'a, DeviceT> {
let device_capabilities = self.device.capabilities();
#[cfg(feature = "ethernet")]
let mut ethernet_addr = None;
#[cfg(feature = "ethernet")]
let mut neighbor_cache = None;
match device_capabilities.medium {
#[cfg(feature = "ethernet")]
Medium::Ethernet => {
ethernet_addr = Some(self.ethernet_addr.expect("ethernet_addr required option was not set"));
neighbor_cache = Some(self.neighbor_cache.expect("neighbor_cache required option was not set"));
}
#[cfg(feature = "medium-ethernet")]
let (ethernet_addr, neighbor_cache) = match device_capabilities.medium {
Medium::Ethernet => (
Some(self.ethernet_addr.expect("ethernet_addr required option was not set")),
Some(self.neighbor_cache.expect("neighbor_cache required option was not set"))
),
#[cfg(feature = "medium-ip")]
Medium::Ip => {
#[cfg(feature = "ethernet")]
assert!(self.ethernet_addr.is_none(), "ethernet_addr is set, but device medium is IP");
#[cfg(feature = "ethernet")]
assert!(self.neighbor_cache.is_none(), "neighbor_cache is set, but device medium is IP");
(None, None)
}
}
};
Interface {
device: self.device,
inner: InterfaceInner {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
ethernet_addr,
ip_addrs: self.ip_addrs,
#[cfg(feature = "proto-ipv4")]
any_ip: self.any_ip,
routes: self.routes,
device_capabilities,
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
neighbor_cache,
#[cfg(feature = "proto-igmp")]
ipv4_multicast_groups: self.ipv4_multicast_groups,
@ -247,7 +243,7 @@ let iface = InterfaceBuilder::new(device)
}
#[derive(Debug, PartialEq)]
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
enum EthernetPacket<'a> {
#[cfg(feature = "proto-ipv4")]
Arp(ArpRepr),
@ -371,7 +367,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
/// # Panics
/// This function panics if if the interface's medium is not Ethernet.
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub fn ethernet_addr(&self) -> EthernetAddress {
self.inner.ethernet_addr.unwrap()
}
@ -381,7 +377,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
/// # Panics
/// This function panics if the address is not unicast, or if the
/// interface's medium is not Ethernet.
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub fn set_ethernet_addr(&mut self, addr: EthernetAddress) {
assert!(self.device.capabilities().medium == Medium::Ethernet);
InterfaceInner::check_ethernet_addr(&addr);
@ -591,7 +587,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
};
rx_token.consume(timestamp, |frame| {
match inner.device_capabilities.medium {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => {
inner.process_ethernet(sockets, timestamp, &frame).map_err(|err| {
net_debug!("cannot process ingress packet: {}", err);
@ -611,6 +607,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
}
})
}
#[cfg(feature = "medium-ip")]
Medium::Ip => {
inner.process_ip(sockets, timestamp, &frame).map_err(|err| {
net_debug!("cannot process ingress packet: {}", err);
@ -638,12 +635,12 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
fn socket_egress(&mut self, sockets: &mut SocketSet, timestamp: Instant) -> Result<bool> {
let mut caps = self.device.capabilities();
match caps.medium {
#[cfg(feature = "ethernet")]
Medium::Ethernet =>
caps.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len(),
_ => {}
}
caps.max_transmission_unit = match caps.medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => caps.max_transmission_unit - EthernetFrame::<&[u8]>::header_len(),
#[cfg(feature = "medium-ip")]
Medium::Ip => caps.max_transmission_unit,
};
let mut emitted_any = false;
for mut socket in sockets.iter_mut() {
@ -768,7 +765,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
}
impl<'a> InterfaceInner<'a> {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
fn check_ethernet_addr(addr: &EthernetAddress) {
if addr.is_multicast() {
panic!("Ethernet address {} is not unicast", addr)
@ -836,7 +833,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
fn process_ethernet<'frame, T: AsRef<[u8]>>
(&mut self, sockets: &mut SocketSet, timestamp: Instant, frame: &'frame T) ->
Result<Option<EthernetPacket<'frame>>>
@ -887,6 +884,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(feature = "medium-ip")]
fn process_ip<'frame, T: AsRef<[u8]>>
(&mut self, sockets: &mut SocketSet, timestamp: Instant, ip_payload: &'frame T) ->
Result<Option<IpPacket<'frame>>>
@ -907,7 +905,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(all(feature = "ethernet", feature = "proto-ipv4"))]
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
fn process_arp<'frame, T: AsRef<[u8]>>
(&mut self, timestamp: Instant, eth_frame: &EthernetFrame<&'frame T>) ->
Result<Option<EthernetPacket<'frame>>>
@ -1215,7 +1213,7 @@ impl<'a> InterfaceInner<'a> {
Icmpv6Repr::EchoReply { .. } => Ok(None),
// Forward any NDISC packets to the ndisc packet handler
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr {
IpRepr::Ipv6(ipv6_repr) => self.process_ndisc(_timestamp, ipv6_repr, repr),
_ => Ok(None)
@ -1231,7 +1229,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(all(feature = "ethernet", feature = "proto-ipv6"))]
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))]
fn process_ndisc<'frame>(&mut self, timestamp: Instant, ip_repr: Ipv6Repr,
repr: NdiscRepr<'frame>) -> Result<Option<IpPacket<'frame>>> {
match repr {
@ -1503,7 +1501,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
fn dispatch<Tx>(&mut self, tx_token: Tx, timestamp: Instant,
packet: EthernetPacket) -> Result<()>
where Tx: TxToken
@ -1530,7 +1528,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
fn dispatch_ethernet<Tx, F>(&mut self, tx_token: Tx, timestamp: Instant,
buffer_len: usize, f: F) -> Result<()>
where Tx: TxToken, F: FnOnce(EthernetFrame<&mut [u8]>)
@ -1570,10 +1568,11 @@ impl<'a> InterfaceInner<'a> {
match self.route(addr, timestamp) {
Ok(_routed_addr) => {
match self.device_capabilities.medium {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => self.neighbor_cache.as_ref().unwrap()
.lookup(&_routed_addr, timestamp)
.found(),
#[cfg(feature = "medium-ip")]
Medium::Ip => true,
}
}
@ -1581,7 +1580,7 @@ impl<'a> InterfaceInner<'a> {
}
}
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
fn lookup_hardware_addr<Tx>(&mut self, tx_token: Tx, timestamp: Instant,
src_addr: &IpAddress, dst_addr: &IpAddress) ->
Result<(EthernetAddress, Tx)>
@ -1682,7 +1681,7 @@ impl<'a> InterfaceInner<'a> {
let caps = self.device_capabilities.clone();
match self.device_capabilities.medium {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => {
let (dst_hardware_addr, tx_token) =
self.lookup_hardware_addr(tx_token, timestamp,
@ -1704,6 +1703,7 @@ impl<'a> InterfaceInner<'a> {
packet.emit_payload(ip_repr, payload, &caps);
})
}
#[cfg(feature = "medium-ip")]
Medium::Ip => {
let tx_len = ip_repr.total_len();
tx_token.consume(timestamp, tx_len, |mut tx_buffer| {
@ -1773,6 +1773,15 @@ mod test {
use crate::phy::{Loopback, ChecksumCapabilities};
fn create_loopback<'a>() -> (Interface<'a, Loopback>, SocketSet<'a>) {
#[cfg(feature = "medium-ethernet")]
return create_loopback_ethernet();
#[cfg(not(feature = "medium-ethernet"))]
return create_loopback_ip();
}
#[cfg(all(feature = "medium-ip"))]
#[allow(unused)]
fn create_loopback_ip<'a>() -> (Interface<'a, Loopback>, SocketSet<'a>) {
// Create a basic device
let device = Loopback::new(Medium::Ip);
let ip_addrs = [
@ -1795,7 +1804,7 @@ mod test {
(iface, SocketSet::new(vec![]))
}
#[cfg(all(feature = "ethernet"))]
#[cfg(all(feature = "medium-ethernet"))]
fn create_loopback_ethernet<'a>() -> (Interface<'a, Loopback>, SocketSet<'a>) {
// Create a basic device
let device = Loopback::new(Medium::Ethernet);
@ -1845,7 +1854,7 @@ mod test {
#[test]
#[should_panic(expected = "ethernet_addr required option was not set")]
#[cfg(all(feature = "ethernet"))]
#[cfg(all(feature = "medium-ethernet"))]
fn test_builder_initialization_panic() {
InterfaceBuilder::new(Loopback::new(Medium::Ethernet)).finalize();
}
@ -2300,7 +2309,7 @@ mod test {
}
#[test]
#[cfg(all(feature = "ethernet", feature = "proto-ipv4"))]
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
fn test_handle_valid_arp_request() {
let (mut iface, mut socket_set) = create_loopback_ethernet();
@ -2345,7 +2354,7 @@ mod test {
}
#[test]
#[cfg(all(feature = "ethernet", feature = "proto-ipv6"))]
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))]
fn test_handle_valid_ndisc_request() {
let (mut iface, mut socket_set) = create_loopback_ethernet();
@ -2405,7 +2414,7 @@ mod test {
}
#[test]
#[cfg(all(feature = "ethernet", feature = "proto-ipv4"))]
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
fn test_handle_other_arp_request() {
let (mut iface, mut socket_set) = create_loopback_ethernet();
@ -2589,11 +2598,21 @@ mod test {
#[cfg(feature = "proto-igmp")]
fn test_handle_igmp() {
fn recv_igmp(mut iface: &mut Interface<'_, Loopback>, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> {
let checksum_caps = &iface.device.capabilities().checksum;
let caps = iface.device.capabilities();
let checksum_caps = &caps.checksum;
recv_all(&mut iface, timestamp)
.iter()
.filter_map(|frame| {
let ipv4_packet = Ipv4Packet::new_checked(frame).ok()?;
let ipv4_packet = match caps.medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => {
let eth_frame = EthernetFrame::new_checked(frame).ok()?;
Ipv4Packet::new_checked(eth_frame.payload()).ok()?
}
#[cfg(feature = "medium-ip")]
Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()?
};
let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, &checksum_caps).ok()?;
let ip_payload = ipv4_packet.payload();
let igmp_packet = IgmpPacket::new_checked(ip_payload).ok()?;

View File

@ -4,17 +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.
*/
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
mod neighbor;
mod route;
#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
mod interface;
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub use self::neighbor::Neighbor as Neighbor;
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub(crate) use self::neighbor::Answer as NeighborAnswer;
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
pub use self::neighbor::Cache as NeighborCache;
pub use self::route::{Route, Routes};
#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
pub use self::interface::{Interface, InterfaceBuilder};

View File

@ -1,6 +1,6 @@
#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![deny(unsafe_code)]
#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "ethernet"), deny(unused))]
#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "medium-ethernet"), deny(unused))]
//! 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

View File

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

View File

@ -11,7 +11,7 @@ and implementations of it:
[TapInterface](struct.TapInterface.html), to transmit and receive frames
on the host OS.
*/
#![cfg_attr(feature = "ethernet", doc = r##"
#![cfg_attr(feature = "medium-ethernet", doc = r##"
# Examples
An implementation of the [Device](trait.Device.html) trait for a simple hardware
@ -117,7 +117,7 @@ pub use self::raw_socket::RawSocket;
#[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
pub use self::tap_interface::TapInterface;
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
/// A tracer device for Ethernet frames.
pub type EthernetTracer<T> = Tracer<T, super::wire::EthernetFrame<&'static [u8]>>;
@ -238,23 +238,26 @@ pub enum Medium {
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
///
/// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Ethernet,
/// IP medium. Devices of this type send and receive IP frames, without an
/// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
///
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
#[cfg(feature = "medium-ip")]
Ip,
}
impl Default for Medium {
fn default() -> Medium {
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
return Medium::Ethernet;
#[cfg(not(feature = "ethernet"))]
#[cfg(all(feature = "medium-ip", not(feature = "medium-ethernet")))]
return Medium::Ip;
#[cfg(all(not(feature = "medium-ip"), not(feature = "medium-ethernet")))]
panic!("No medium enabled");
}
}

View File

@ -6,7 +6,7 @@ use crate::phy::ChecksumCapabilities;
use crate::wire::ip::checksum;
use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
use crate::wire::MldRepr;
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
use crate::wire::NdiscRepr;
enum_with_unknown! {
@ -536,7 +536,7 @@ pub enum Repr<'a> {
seq_no: u16,
data: &'a [u8]
},
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Ndisc(NdiscRepr<'a>),
Mld(MldRepr<'a>),
}
@ -617,7 +617,7 @@ impl<'a> Repr<'a> {
data: packet.payload()
})
},
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
(msg_type, 0) if msg_type.is_ndisc() => {
NdiscRepr::parse(packet).map(Repr::Ndisc)
},
@ -639,7 +639,7 @@ impl<'a> Repr<'a> {
&Repr::EchoReply { data, .. } => {
field::ECHO_SEQNO.end + data.len()
},
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
&Repr::Ndisc(ndisc) => {
ndisc.buffer_len()
},
@ -710,7 +710,7 @@ impl<'a> Repr<'a> {
packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len])
},
#[cfg(feature = "ethernet")]
#[cfg(feature = "medium-ethernet")]
Repr::Ndisc(ndisc) => {
ndisc.emit(packet)
},

View File

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