Add medium-ip, medium-ethernet feature flags.
parent
9ac2cac075
commit
af4a1e6436
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue