diff --git a/examples/benchmark.rs b/examples/benchmark.rs index 9f908987..b0cedcfb 100644 --- a/examples/benchmark.rs +++ b/examples/benchmark.rs @@ -88,11 +88,14 @@ fn main() { let tcp2_tx_buffer = tcp::SocketBuffer::new(vec![0; 65535]); let tcp2_socket = tcp::Socket::new(tcp2_rx_buffer, tcp2_tx_buffer); - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/client.rs b/examples/client.rs index 8543ae06..5422aded 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -29,11 +29,14 @@ fn main() { let port = u16::from_str(&matches.free[1]).expect("invalid port format"); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/dhcp_client.rs b/examples/dhcp_client.rs index 96654241..d118219d 100644 --- a/examples/dhcp_client.rs +++ b/examples/dhcp_client.rs @@ -28,11 +28,14 @@ fn main() { utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); // Create sockets diff --git a/examples/dns.rs b/examples/dns.rs index 8bf8b2c8..da066aaf 100644 --- a/examples/dns.rs +++ b/examples/dns.rs @@ -24,11 +24,14 @@ fn main() { let name = &matches.free[0]; // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/httpclient.rs b/examples/httpclient.rs index 1e5a2186..751916da 100644 --- a/examples/httpclient.rs +++ b/examples/httpclient.rs @@ -29,11 +29,14 @@ fn main() { let url = Url::parse(&matches.free[1]).expect("invalid url format"); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/loopback.rs b/examples/loopback.rs index 1a4dee88..9bca85e5 100644 --- a/examples/loopback.rs +++ b/examples/loopback.rs @@ -10,7 +10,7 @@ use core::str; use log::{debug, error, info}; use smoltcp::iface::{Config, Interface, SocketSet}; -use smoltcp::phy::{Loopback, Medium}; +use smoltcp::phy::{Device, Loopback, Medium}; use smoltcp::socket::tcp; use smoltcp::time::{Duration, Instant}; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; @@ -83,8 +83,13 @@ fn main() { }; // Create interface - let mut config = Config::new(); - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/multicast.rs b/examples/multicast.rs index 639fa432..ec7ff435 100644 --- a/examples/multicast.rs +++ b/examples/multicast.rs @@ -28,11 +28,14 @@ fn main() { utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/ping.rs b/examples/ping.rs index beac5625..7e6cbdb0 100644 --- a/examples/ping.rs +++ b/examples/ping.rs @@ -105,11 +105,14 @@ fn main() { ); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/server.rs b/examples/server.rs index f2bbc803..67df6392 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -24,11 +24,15 @@ fn main() { utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => todo!(), + }; + config.random_seed = rand::random(); - if device.capabilities().medium == Medium::Ethernet { - config.hardware_addr = Some(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()); - } let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { diff --git a/examples/sixlowpan.rs b/examples/sixlowpan.rs index 964a8562..5b41116c 100644 --- a/examples/sixlowpan.rs +++ b/examples/sixlowpan.rs @@ -47,11 +47,11 @@ use std::os::unix::io::AsRawFd; use std::str; use smoltcp::iface::{Config, Interface, SocketSet}; -use smoltcp::phy::{wait as phy_wait, Medium, RawSocket}; +use smoltcp::phy::{wait as phy_wait, Device, Medium, RawSocket}; use smoltcp::socket::tcp; use smoltcp::socket::udp; use smoltcp::time::Instant; -use smoltcp::wire::{Ieee802154Address, Ieee802154Pan, IpAddress, IpCidr}; +use smoltcp::wire::{EthernetAddress, Ieee802154Address, Ieee802154Pan, IpAddress, IpCidr}; fn main() { utils::setup_logging(""); @@ -67,10 +67,16 @@ fn main() { utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => Config::new( + Ieee802154Address::Extended([0x1a, 0x0b, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42]).into(), + ), + }; config.random_seed = rand::random(); - config.hardware_addr = - Some(Ieee802154Address::Extended([0x1a, 0x0b, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42]).into()); config.pan_id = Some(Ieee802154Pan(0xbeef)); let mut iface = Interface::new(config, &mut device); diff --git a/examples/sixlowpan_benchmark.rs b/examples/sixlowpan_benchmark.rs index 8b9cf842..a389ca94 100644 --- a/examples/sixlowpan_benchmark.rs +++ b/examples/sixlowpan_benchmark.rs @@ -47,9 +47,9 @@ use std::os::unix::io::AsRawFd; use std::str; use smoltcp::iface::{Config, Interface, SocketSet}; -use smoltcp::phy::{wait as phy_wait, Medium, RawSocket}; +use smoltcp::phy::{wait as phy_wait, Device, Medium, RawSocket}; use smoltcp::socket::tcp; -use smoltcp::wire::{Ieee802154Address, Ieee802154Pan, IpAddress, IpCidr}; +use smoltcp::wire::{EthernetAddress, Ieee802154Address, Ieee802154Pan, IpAddress, IpCidr}; //For benchmark use smoltcp::time::{Duration, Instant}; @@ -147,10 +147,16 @@ fn main() { }; // Create interface - let mut config = Config::new(); + let mut config = match device.capabilities().medium { + Medium::Ethernet => { + Config::new(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()) + } + Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip), + Medium::Ieee802154 => Config::new( + Ieee802154Address::Extended([0x1a, 0x0b, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42]).into(), + ), + }; config.random_seed = rand::random(); - config.hardware_addr = - Some(Ieee802154Address::Extended([0x1a, 0x0b, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42]).into()); config.pan_id = Some(Ieee802154Pan(0xbeef)); let mut iface = Interface::new(config, &mut device); diff --git a/src/iface/interface/ethernet.rs b/src/iface/interface/ethernet.rs index b769909c..bf8496fe 100644 --- a/src/iface/interface/ethernet.rs +++ b/src/iface/interface/ethernet.rs @@ -22,7 +22,7 @@ impl InterfaceInner { // Ignore any packets not directed to our hardware address or any of the multicast groups. if !eth_frame.dst_addr().is_broadcast() && !eth_frame.dst_addr().is_multicast() - && HardwareAddress::Ethernet(eth_frame.dst_addr()) != self.hardware_addr.unwrap() + && HardwareAddress::Ethernet(eth_frame.dst_addr()) != self.hardware_addr { return None; } @@ -64,7 +64,7 @@ impl InterfaceInner { debug_assert!(tx_buffer.as_ref().len() == tx_len); let mut frame = EthernetFrame::new_unchecked(tx_buffer); - let src_addr = self.hardware_addr.unwrap().ethernet_or_panic(); + let src_addr = self.hardware_addr.ethernet_or_panic(); frame.set_src_addr(src_addr); f(frame); diff --git a/src/iface/interface/ieee802154.rs b/src/iface/interface/ieee802154.rs index 19faed79..78023001 100644 --- a/src/iface/interface/ieee802154.rs +++ b/src/iface/interface/ieee802154.rs @@ -44,7 +44,7 @@ impl InterfaceInner { packet: IpPacket, frag: &mut Fragmenter, ) { - let ll_src_a = self.hardware_addr.unwrap().ieee802154_or_panic(); + let ll_src_a = self.hardware_addr.ieee802154_or_panic(); // Create the IEEE802.15.4 header. let ieee_repr = Ieee802154Repr { diff --git a/src/iface/interface/ipv4.rs b/src/iface/interface/ipv4.rs index bd1d6e1d..50aff283 100644 --- a/src/iface/interface/ipv4.rs +++ b/src/iface/interface/ipv4.rs @@ -74,7 +74,9 @@ impl InterfaceInner { #[cfg(feature = "socket-dhcpv4")] { - if ipv4_repr.next_header == IpProtocol::Udp && self.hardware_addr.is_some() { + if ipv4_repr.next_header == IpProtocol::Udp + && matches!(self.caps.medium, Medium::Ethernet) + { let udp_packet = check!(UdpPacket::new_checked(ip_payload)); if let Some(dhcp_socket) = sockets .items_mut() @@ -206,17 +208,14 @@ impl InterfaceInner { // We fill from requests too because if someone is requesting our address they // are probably going to talk to us, so we avoid having to request their address // when we later reply to them. - self.neighbor_cache.as_mut().unwrap().fill( + self.neighbor_cache.fill( source_protocol_addr.into(), source_hardware_addr.into(), timestamp, ); if operation == ArpOperation::Request { - let src_hardware_addr = match self.hardware_addr { - Some(HardwareAddress::Ethernet(addr)) => addr, - _ => unreachable!(), - }; + let src_hardware_addr = self.hardware_addr.ethernet_or_panic(); Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 { operation: ArpOperation::Reply, @@ -352,7 +351,7 @@ impl InterfaceInner { let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| { let mut frame = EthernetFrame::new_unchecked(tx_buffer); - let src_addr = self.hardware_addr.unwrap().ethernet_or_panic(); + let src_addr = self.hardware_addr.ethernet_or_panic(); frame.set_src_addr(src_addr); frame.set_dst_addr(frag.ipv4.dst_hardware_addr); diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index 220ee13b..c57e0691 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -192,17 +192,9 @@ impl InterfaceInner { return None; } if flags.contains(NdiscNeighborFlags::OVERRIDE) - || !self - .neighbor_cache - .as_mut() - .unwrap() - .lookup(&ip_addr, self.now) - .found() + || !self.neighbor_cache.lookup(&ip_addr, self.now).found() { - self.neighbor_cache - .as_mut() - .unwrap() - .fill(ip_addr, lladdr, self.now) + self.neighbor_cache.fill(ip_addr, lladdr, self.now) } } None @@ -217,11 +209,8 @@ impl InterfaceInner { if !lladdr.is_unicast() || !target_addr.is_unicast() { return None; } - self.neighbor_cache.as_mut().unwrap().fill( - ip_repr.src_addr.into(), - lladdr, - self.now, - ); + self.neighbor_cache + .fill(ip_repr.src_addr.into(), lladdr, self.now); } if self.has_solicited_node(ip_repr.dst_addr) && self.has_ip_addr(target_addr) { @@ -229,7 +218,7 @@ impl InterfaceInner { flags: NdiscNeighborFlags::SOLICITED, target_addr, #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - lladdr: Some(self.hardware_addr.unwrap().into()), + lladdr: Some(self.hardware_addr.into()), }); let ip_repr = Ipv6Repr { src_addr: target_addr, diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index 7ab5b553..34ad4bd2 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -240,9 +240,8 @@ pub struct InterfaceInner { rand: Rand, #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - neighbor_cache: Option, - #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - hardware_addr: Option, + neighbor_cache: NeighborCache, + hardware_addr: HardwareAddress, #[cfg(feature = "medium-ieee802154")] sequence_no: u8, #[cfg(feature = "medium-ieee802154")] @@ -280,8 +279,7 @@ pub struct Config { /// /// # Panics /// Creating the interface panics if the address is not unicast. - #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - pub hardware_addr: Option, + pub hardware_addr: HardwareAddress, /// Set the IEEE802.15.4 PAN ID the interface will use. /// @@ -291,23 +289,16 @@ pub struct Config { } impl Config { - pub fn new() -> Self { + pub fn new(hardware_addr: HardwareAddress) -> Self { Config { random_seed: 0, - #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - hardware_addr: None, + hardware_addr, #[cfg(feature = "medium-ieee802154")] pan_id: None, } } } -impl Default for Config { - fn default() -> Self { - Self::new() - } -} - #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(feature = "medium-ethernet")] @@ -476,29 +467,11 @@ impl Interface { { let caps = device.capabilities(); - #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - let hardware_addr = match caps.medium { - #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => Some( - config - .hardware_addr - .expect("hardware_addr required option was not set"), - ), - #[cfg(feature = "medium-ip")] - Medium::Ip => { - assert!( - config.hardware_addr.is_none(), - "hardware_addr is set, but device medium is IP" - ); - None - } - #[cfg(feature = "medium-ieee802154")] - Medium::Ieee802154 => Some( - config - .hardware_addr - .expect("hardware_addr required option was not set"), - ), - }; + assert_eq!( + config.hardware_addr.medium(), + caps.medium, + "The hardware address does not match the medium of the interface." + ); let mut rand = Rand::new(config.random_seed); @@ -548,14 +521,13 @@ impl Interface { inner: InterfaceInner { now: Instant::from_secs(0), caps, - #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - hardware_addr, + hardware_addr: config.hardware_addr, ip_addrs: Vec::new(), #[cfg(feature = "proto-ipv4")] any_ip: false, routes: Routes::new(), #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - neighbor_cache: Some(NeighborCache::new()), + neighbor_cache: NeighborCache::new(), #[cfg(feature = "proto-igmp")] ipv4_multicast_groups: LinearMap::new(), #[cfg(feature = "proto-igmp")] @@ -599,7 +571,7 @@ impl Interface { || self.inner.caps.medium == Medium::Ieee802154 ); - self.inner.hardware_addr.unwrap() + self.inner.hardware_addr } /// Set the HardwareAddress address of the interface. @@ -621,7 +593,7 @@ impl Interface { ); InterfaceInner::check_hardware_addr(&addr); - self.inner.hardware_addr = Some(addr); + self.inner.hardware_addr = addr; } /// Get the IP addresses of the interface. @@ -1050,7 +1022,7 @@ impl InterfaceInner { #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] #[allow(unused)] // unused depending on which sockets are enabled - pub(crate) fn hardware_addr(&self) -> Option { + pub(crate) fn hardware_addr(&self) -> HardwareAddress { self.hardware_addr } @@ -1169,19 +1141,31 @@ impl InterfaceInner { #[cfg(feature = "proto-ipv4-fragmentation")] ipv4_id: 1, + #[cfg(all( + feature = "medium-ip", + not(feature = "medium-ethernet"), + not(feature = "medium-ieee802154") + ))] + hardware_addr: crate::wire::HardwareAddress::Ip, + #[cfg(feature = "medium-ethernet")] - hardware_addr: Some(crate::wire::HardwareAddress::Ethernet( - crate::wire::EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]), - )), - #[cfg(all(not(feature = "medium-ethernet"), feature = "medium-ieee802154"))] - hardware_addr: Some(crate::wire::HardwareAddress::Ieee802154( + hardware_addr: crate::wire::HardwareAddress::Ethernet(crate::wire::EthernetAddress([ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + ])), + + #[cfg(all( + not(feature = "medium-ip"), + not(feature = "medium-ethernet"), + feature = "medium-ieee802154" + ))] + hardware_addr: crate::wire::HardwareAddress::Ieee802154( crate::wire::Ieee802154Address::Extended([ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x2, 0x2, ]), - )), + ), #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - neighbor_cache: None, + neighbor_cache: NeighborCache::new(), #[cfg(feature = "proto-igmp")] igmp_report_state: IgmpReportState::Inactive, @@ -1199,7 +1183,7 @@ impl InterfaceInner { #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] fn check_hardware_addr(addr: &HardwareAddress) { if !addr.is_unicast() { - panic!("Ethernet address {addr} is not unicast") + panic!("Hardware address {addr} is not unicast") } } @@ -1503,19 +1487,9 @@ impl InterfaceInner { match self.route(addr, self.now) { Some(_routed_addr) => match self.caps.medium { #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => self - .neighbor_cache - .as_ref() - .unwrap() - .lookup(&_routed_addr, self.now) - .found(), + Medium::Ethernet => self.neighbor_cache.lookup(&_routed_addr, self.now).found(), #[cfg(feature = "medium-ieee802154")] - Medium::Ieee802154 => self - .neighbor_cache - .as_ref() - .unwrap() - .lookup(&_routed_addr, self.now) - .found(), + Medium::Ieee802154 => self.neighbor_cache.lookup(&_routed_addr, self.now).found(), #[cfg(feature = "medium-ip")] Medium::Ip => true, }, @@ -1584,12 +1558,7 @@ impl InterfaceInner { .route(dst_addr, self.now) .ok_or(DispatchError::NoRoute)?; - match self - .neighbor_cache - .as_mut() - .unwrap() - .lookup(&dst_addr, self.now) - { + match self.neighbor_cache.lookup(&dst_addr, self.now) { NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)), NeighborAnswer::RateLimited => return Err(DispatchError::NeighborPending), _ => (), // XXX @@ -1602,7 +1571,7 @@ impl InterfaceInner { "address {} not in neighbor cache, sending ARP request", dst_addr ); - let src_hardware_addr = self.hardware_addr.unwrap().ethernet_or_panic(); + let src_hardware_addr = self.hardware_addr.ethernet_or_panic(); let arp_repr = ArpRepr::EthernetIpv4 { operation: ArpOperation::Request, @@ -1634,7 +1603,7 @@ impl InterfaceInner { let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit { target_addr: dst_addr, - lladdr: Some(self.hardware_addr.unwrap().into()), + lladdr: Some(self.hardware_addr.into()), }); let packet = IpPacket::Icmpv6(( @@ -1659,15 +1628,13 @@ impl InterfaceInner { } // The request got dispatched, limit the rate on the cache. - self.neighbor_cache.as_mut().unwrap().limit_rate(self.now); + self.neighbor_cache.limit_rate(self.now); Err(DispatchError::NeighborPending) } fn flush_cache(&mut self) { #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - if let Some(cache) = self.neighbor_cache.as_mut() { - cache.flush() - } + self.neighbor_cache.flush() } fn dispatch_ip( @@ -1722,8 +1689,7 @@ impl InterfaceInner { frag, )? { (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token), - #[cfg(feature = "medium-ieee802154")] - (HardwareAddress::Ieee802154(_), _) => unreachable!(), + (_, _) => unreachable!(), } } _ => (EthernetAddress([0; 6]), tx_token), @@ -1734,7 +1700,7 @@ impl InterfaceInner { let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| { let mut frame = EthernetFrame::new_unchecked(tx_buffer); - let src_addr = self.hardware_addr.unwrap().ethernet_or_panic(); + let src_addr = self.hardware_addr.ethernet_or_panic(); frame.set_src_addr(src_addr); frame.set_dst_addr(dst_hardware_addr); diff --git a/src/iface/interface/tests.rs b/src/iface/interface/tests.rs index cf4c655f..3345dae7 100644 --- a/src/iface/interface/tests.rs +++ b/src/iface/interface/tests.rs @@ -39,7 +39,7 @@ fn create_ip<'a>() -> (Interface, SocketSet<'a>, Loopback) { // Create a basic device let mut device = Loopback::new(Medium::Ip); - let mut config = Config::new(); + let config = Config::new(HardwareAddress::Ip); let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { #[cfg(feature = "proto-ipv4")] @@ -64,8 +64,7 @@ fn create_ethernet<'a>() -> (Interface, SocketSet<'a>, Loopback) { // Create a basic device let mut device = Loopback::new(Medium::Ethernet); - let mut config = Config::new(); - config.hardware_addr = Some(EthernetAddress::default().into()); + let config = Config::new(HardwareAddress::Ethernet(EthernetAddress::default())); let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { #[cfg(feature = "proto-ipv4")] @@ -90,8 +89,7 @@ fn create_ieee802154<'a>() -> (Interface, SocketSet<'a>, Loopback) { // Create a basic device let mut device = Loopback::new(Medium::Ieee802154); - let mut config = Config::new(); - config.hardware_addr = Some(Ieee802154Address::default().into()); + let config = Config::new(HardwareAddress::Ieee802154(Ieee802154Address::default())); let mut iface = Interface::new(config, &mut device); iface.update_ip_addrs(|ip_addrs| { #[cfg(feature = "proto-ipv6")] @@ -133,11 +131,11 @@ impl TxToken for MockTxToken { } #[test] -#[should_panic(expected = "hardware_addr required option was not set")] -#[cfg(all(feature = "medium-ethernet"))] +#[should_panic(expected = "The hardware address does not match the medium of the interface.")] +#[cfg(all(feature = "medium-ip", feature = "medium-ethernet"))] fn test_new_panic() { let mut device = Loopback::new(Medium::Ethernet); - let config = Config::new(); + let config = Config::new(HardwareAddress::Ip); Interface::new(config, &mut device); } @@ -1377,7 +1375,7 @@ fn test_echo_request_sixlowpan_128_bytes() { assert_eq!(iface.inner.caps.medium, Medium::Ieee802154); let now = iface.inner.now(); - iface.inner.neighbor_cache.as_mut().unwrap().fill( + iface.inner.neighbor_cache.fill( Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0, 0]).into(), HardwareAddress::Ieee802154(Ieee802154Address::default()), now, @@ -1503,7 +1501,7 @@ fn test_echo_request_sixlowpan_128_bytes() { ))) ); - iface.inner.neighbor_cache.as_mut().unwrap().fill( + iface.inner.neighbor_cache.fill( IpAddress::Ipv6(Ipv6Address([ 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb, 0x1a, ])), diff --git a/src/socket/dhcpv4.rs b/src/socket/dhcpv4.rs index d796efaa..2609621e 100644 --- a/src/socket/dhcpv4.rs +++ b/src/socket/dhcpv4.rs @@ -317,7 +317,7 @@ impl<'a> Socket<'a> { } }; - let Some(HardwareAddress::Ethernet(ethernet_addr)) = cx.hardware_addr() else { + let HardwareAddress::Ethernet(ethernet_addr) = cx.hardware_addr() else { panic!("using DHCPv4 socket with a non-ethernet hardware address."); }; @@ -542,7 +542,7 @@ impl<'a> Socket<'a> { { // note: Dhcpv4Socket is only usable in ethernet mediums, so the // unwrap can never fail. - let Some(HardwareAddress::Ethernet(ethernet_addr)) = cx.hardware_addr() else { + let HardwareAddress::Ethernet(ethernet_addr) = cx.hardware_addr() else { panic!("using DHCPv4 socket with a non-ethernet hardware address."); }; diff --git a/src/wire/mod.rs b/src/wire/mod.rs index 6a308a9f..616af949 100644 --- a/src/wire/mod.rs +++ b/src/wire/mod.rs @@ -275,20 +275,32 @@ impl fmt::Display for Error { pub type Result = core::result::Result; /// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address. -#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] +#[cfg(any( + feature = "medium-ip", + feature = "medium-ethernet", + feature = "medium-ieee802154" +))] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum HardwareAddress { + #[cfg(feature = "medium-ip")] + Ip, #[cfg(feature = "medium-ethernet")] Ethernet(EthernetAddress), #[cfg(feature = "medium-ieee802154")] Ieee802154(Ieee802154Address), } -#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] +#[cfg(any( + feature = "medium-ip", + feature = "medium-ethernet", + feature = "medium-ieee802154" +))] impl HardwareAddress { pub const fn as_bytes(&self) -> &[u8] { match self { + #[cfg(feature = "medium-ip")] + HardwareAddress::Ip => unreachable!(), #[cfg(feature = "medium-ethernet")] HardwareAddress::Ethernet(addr) => addr.as_bytes(), #[cfg(feature = "medium-ieee802154")] @@ -299,6 +311,8 @@ impl HardwareAddress { /// Query wether the address is an unicast address. pub fn is_unicast(&self) -> bool { match self { + #[cfg(feature = "medium-ip")] + HardwareAddress::Ip => unreachable!(), #[cfg(feature = "medium-ethernet")] HardwareAddress::Ethernet(addr) => addr.is_unicast(), #[cfg(feature = "medium-ieee802154")] @@ -309,6 +323,8 @@ impl HardwareAddress { /// Query wether the address is a broadcast address. pub fn is_broadcast(&self) -> bool { match self { + #[cfg(feature = "medium-ip")] + HardwareAddress::Ip => unreachable!(), #[cfg(feature = "medium-ethernet")] HardwareAddress::Ethernet(addr) => addr.is_broadcast(), #[cfg(feature = "medium-ieee802154")] @@ -333,12 +349,30 @@ impl HardwareAddress { _ => panic!("HardwareAddress is not Ethernet."), } } + + #[inline] + pub(crate) fn medium(&self) -> Medium { + match self { + #[cfg(feature = "medium-ip")] + HardwareAddress::Ip => Medium::Ip, + #[cfg(feature = "medium-ethernet")] + HardwareAddress::Ethernet(_) => Medium::Ethernet, + #[cfg(feature = "medium-ieee802154")] + HardwareAddress::Ieee802154(_) => Medium::Ieee802154, + } + } } -#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] +#[cfg(any( + feature = "medium-ip", + feature = "medium-ethernet", + feature = "medium-ieee802154" +))] impl core::fmt::Display for HardwareAddress { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match self { + #[cfg(feature = "medium-ip")] + HardwareAddress::Ip => write!(f, "no hardware addr"), #[cfg(feature = "medium-ethernet")] HardwareAddress::Ethernet(addr) => write!(f, "{addr}"), #[cfg(feature = "medium-ieee802154")]