Browse Source

iface: remove all uses of crate::{Error, Result};

Dario Nieuwenhuis 2 years ago
parent
commit
050731b519

+ 1 - 7
examples/benchmark.rs

@@ -2,7 +2,6 @@
 
 mod utils;
 
-use log::debug;
 use std::cmp;
 use std::io::{Read, Write};
 use std::net::TcpStream;
@@ -114,12 +113,7 @@ fn main() {
     let mut processed = 0;
     while !CLIENT_DONE.load(Ordering::SeqCst) {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         // tcp:1234: emit data
         let socket = sockets.get_mut::<tcp::Socket>(tcp1_handle);

+ 1 - 6
examples/client.rs

@@ -76,12 +76,7 @@ fn main() {
     let mut tcp_active = false;
     loop {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
         if socket.is_active() && !tcp_active {

+ 1 - 3
examples/dhcp_client.rs

@@ -56,9 +56,7 @@ fn main() {
 
     loop {
         let timestamp = Instant::now();
-        if let Err(e) = iface.poll(timestamp, &mut device, &mut sockets) {
-            debug!("poll error: {}", e);
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         let event = sockets.get_mut::<dhcpv4::Socket>(dhcp_handle).poll();
         match event {

+ 1 - 6
examples/dns.rs

@@ -77,12 +77,7 @@ fn main() {
         let timestamp = Instant::now();
         debug!("timestamp {:?}", timestamp);
 
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         match sockets
             .get_mut::<dns::Socket>(dns_handle)

+ 1 - 6
examples/httpclient.rs

@@ -72,12 +72,7 @@ fn main() {
 
     loop {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
         let cx = iface.context();

+ 1 - 6
examples/loopback.rs

@@ -121,12 +121,7 @@ fn main() {
     let mut did_connect = false;
     let mut done = false;
     while !done && clock.elapsed() < Instant::from_millis(10_000) {
-        match iface.poll(clock.elapsed(), &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(clock.elapsed(), &mut device, &mut sockets);
 
         let mut socket = sockets.get_mut::<tcp::Socket>(server_handle);
         if !socket.is_active() && !socket.is_listening() {

+ 1 - 7
examples/multicast.rs

@@ -1,6 +1,5 @@
 mod utils;
 
-use log::debug;
 use std::os::unix::io::AsRawFd;
 
 use smoltcp::iface::{InterfaceBuilder, NeighborCache, SocketSet};
@@ -70,12 +69,7 @@ fn main() {
 
     loop {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         let socket = sockets.get_mut::<raw::Socket>(raw_handle);
 

+ 1 - 7
examples/ping.rs

@@ -1,7 +1,6 @@
 mod utils;
 
 use byteorder::{ByteOrder, NetworkEndian};
-use log::debug;
 use smoltcp::iface::SocketSet;
 use std::cmp;
 use std::collections::HashMap;
@@ -150,12 +149,7 @@ fn main() {
 
     loop {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         let timestamp = Instant::now();
         let socket = sockets.get_mut::<icmp::Socket>(icmp_handle);

+ 1 - 6
examples/server.rs

@@ -100,12 +100,7 @@ fn main() {
     let mut tcp_6970_active = false;
     loop {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         // udp:6969: respond "hello"
         let socket = sockets.get_mut::<udp::Socket>(udp_handle);

+ 1 - 11
examples/sixlowpan.rs

@@ -115,17 +115,7 @@ fn main() {
 
     loop {
         let timestamp = Instant::now();
-
-        let mut poll = true;
-        while poll {
-            match iface.poll(timestamp, &mut device, &mut sockets) {
-                Ok(r) => poll = r,
-                Err(e) => {
-                    debug!("poll error: {}", e);
-                    break;
-                }
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         // udp:6969: respond "hello"
         let socket = sockets.get_mut::<udp::Socket>(udp_handle);

+ 1 - 7
examples/sixlowpan_benchmark.rs

@@ -43,7 +43,6 @@
 
 mod utils;
 
-use log::debug;
 use std::os::unix::io::AsRawFd;
 use std::str;
 
@@ -188,12 +187,7 @@ fn main() {
 
     while !CLIENT_DONE.load(Ordering::SeqCst) {
         let timestamp = Instant::now();
-        match iface.poll(timestamp, &mut device, &mut sockets) {
-            Ok(_) => {}
-            Err(e) => {
-                debug!("poll error: {}", e);
-            }
-        }
+        iface.poll(timestamp, &mut device, &mut sockets);
 
         // tcp:1234: emit data
         let socket = sockets.get_mut::<tcp::Socket>(tcp1_handle);

+ 4 - 9
src/iface/interface/ethernet.rs

@@ -1,13 +1,13 @@
 use super::check;
+use super::DispatchError;
 use super::EthernetPacket;
 use super::FragmentsBuffer;
 use super::InterfaceInner;
 use super::SocketSet;
+use core::result::Result;
 
 use crate::phy::TxToken;
 use crate::wire::*;
-use crate::Error;
-use crate::Result;
 
 impl<'i> InterfaceInner<'i> {
     #[cfg(feature = "medium-ethernet")]
@@ -63,7 +63,7 @@ impl<'i> InterfaceInner<'i> {
         tx_token: Tx,
         buffer_len: usize,
         f: F,
-    ) -> Result<()>
+    ) -> Result<(), DispatchError>
     where
         Tx: TxToken,
         F: FnOnce(EthernetFrame<&mut [u8]>),
@@ -73,12 +73,7 @@ impl<'i> InterfaceInner<'i> {
             debug_assert!(tx_buffer.as_ref().len() == tx_len);
             let mut frame = EthernetFrame::new_unchecked(tx_buffer);
 
-            let src_addr = if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
-                addr
-            } else {
-                return Err(Error::Malformed);
-            };
-
+            let src_addr = self.hardware_addr.unwrap().ethernet_or_panic();
             frame.set_src_addr(src_addr);
 
             f(frame);

+ 50 - 20
src/iface/interface/igmp.rs

@@ -2,7 +2,20 @@ use super::{check, IgmpReportState, Interface, InterfaceInner, IpPacket};
 use crate::phy::Device;
 use crate::time::{Duration, Instant};
 use crate::wire::*;
-use crate::{Error, Result};
+
+use core::result::Result;
+
+/// Error type for `join_multicast_group`, `leave_multicast_group`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum MulticastError {
+    /// The hardware device transmit buffer is full. Try again later.
+    Exhausted,
+    /// The table of joined multicast groups is already full.
+    GroupTableFull,
+    /// IPv6 multicast is not yet supported.
+    Ipv6NotSupported,
+}
 
 impl<'a> Interface<'a> {
     /// Add an address to a list of subscribed multicast IP addresses.
@@ -14,7 +27,7 @@ impl<'a> Interface<'a> {
         device: &mut D,
         addr: T,
         timestamp: Instant,
-    ) -> Result<bool>
+    ) -> Result<bool, MulticastError>
     where
         D: Device + ?Sized,
     {
@@ -26,15 +39,20 @@ impl<'a> Interface<'a> {
                     .inner
                     .ipv4_multicast_groups
                     .insert(addr, ())
-                    .map_err(|_| Error::Exhausted)?
+                    .map_err(|_| MulticastError::GroupTableFull)?
                     .is_some();
                 if is_not_new {
                     Ok(false)
                 } else if let Some(pkt) = self.inner.igmp_report_packet(IgmpVersion::Version2, addr)
                 {
                     // Send initial membership report
-                    let tx_token = device.transmit(timestamp).ok_or(Error::Exhausted)?;
-                    self.inner.dispatch_ip(tx_token, pkt, None)?;
+                    let tx_token = device
+                        .transmit(timestamp)
+                        .ok_or(MulticastError::Exhausted)?;
+
+                    // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
+                    self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+
                     Ok(true)
                 } else {
                     Ok(false)
@@ -42,7 +60,7 @@ impl<'a> Interface<'a> {
             }
             // Multicast is not yet implemented for other address families
             #[allow(unreachable_patterns)]
-            _ => Err(Error::Unaddressable),
+            _ => Err(MulticastError::Ipv6NotSupported),
         }
     }
 
@@ -55,7 +73,7 @@ impl<'a> Interface<'a> {
         device: &mut D,
         addr: T,
         timestamp: Instant,
-    ) -> Result<bool>
+    ) -> Result<bool, MulticastError>
     where
         D: Device + ?Sized,
     {
@@ -68,8 +86,13 @@ impl<'a> Interface<'a> {
                     Ok(false)
                 } else if let Some(pkt) = self.inner.igmp_leave_packet(addr) {
                     // Send group leave packet
-                    let tx_token = device.transmit(timestamp).ok_or(Error::Exhausted)?;
-                    self.inner.dispatch_ip(tx_token, pkt, None)?;
+                    let tx_token = device
+                        .transmit(timestamp)
+                        .ok_or(MulticastError::Exhausted)?;
+
+                    // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
+                    self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+
                     Ok(true)
                 } else {
                     Ok(false)
@@ -77,7 +100,7 @@ impl<'a> Interface<'a> {
             }
             // Multicast is not yet implemented for other address families
             #[allow(unreachable_patterns)]
-            _ => Err(Error::Unaddressable),
+            _ => Err(MulticastError::Ipv6NotSupported),
         }
     }
 
@@ -88,7 +111,7 @@ impl<'a> Interface<'a> {
 
     /// Depending on `igmp_report_state` and the therein contained
     /// timeouts, send IGMP membership reports.
-    pub(crate) fn igmp_egress<D>(&mut self, device: &mut D) -> Result<bool>
+    pub(crate) fn igmp_egress<D>(&mut self, device: &mut D) -> bool
     where
         D: Device + ?Sized,
     {
@@ -100,12 +123,16 @@ impl<'a> Interface<'a> {
             } if self.inner.now >= timeout => {
                 if let Some(pkt) = self.inner.igmp_report_packet(version, group) {
                     // Send initial membership report
-                    let tx_token = device.transmit(self.inner.now).ok_or(Error::Exhausted)?;
-                    self.inner.dispatch_ip(tx_token, pkt, None)?;
+                    if let Some(tx_token) = device.transmit(self.inner.now) {
+                        // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
+                        self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+                    } else {
+                        return false;
+                    }
                 }
 
                 self.inner.igmp_report_state = IgmpReportState::Inactive;
-                Ok(true)
+                true
             }
             IgmpReportState::ToGeneralQuery {
                 version,
@@ -124,9 +151,12 @@ impl<'a> Interface<'a> {
                     Some(addr) => {
                         if let Some(pkt) = self.inner.igmp_report_packet(version, addr) {
                             // Send initial membership report
-                            let tx_token =
-                                device.transmit(self.inner.now).ok_or(Error::Exhausted)?;
-                            self.inner.dispatch_ip(tx_token, pkt, None)?;
+                            if let Some(tx_token) = device.transmit(self.inner.now) {
+                                // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
+                                self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+                            } else {
+                                return false;
+                            }
                         }
 
                         let next_timeout = (timeout + interval).max(self.inner.now);
@@ -136,16 +166,16 @@ impl<'a> Interface<'a> {
                             interval,
                             next_index: next_index + 1,
                         };
-                        Ok(true)
+                        true
                     }
 
                     None => {
                         self.inner.igmp_report_state = IgmpReportState::Inactive;
-                        Ok(false)
+                        false
                     }
                 }
             }
-            _ => Ok(false),
+            _ => false,
         }
     }
 }

+ 5 - 13
src/iface/interface/ipv4.rs

@@ -18,7 +18,8 @@ use crate::socket::icmp;
 use crate::socket::AnySocket;
 
 use crate::phy::{Medium, TxToken};
-use crate::{time::*, wire::*, Error, Result};
+use crate::time::{Duration, Instant};
+use crate::wire::*;
 
 impl<'a> InterfaceInner<'a> {
     pub(super) fn process_ipv4<'output, 'payload: 'output, T: AsRef<[u8]> + ?Sized>(
@@ -348,7 +349,7 @@ impl<'a> InterfaceInner<'a> {
         &mut self,
         tx_token: Tx,
         out_packet: &mut Ipv4OutPacket,
-    ) -> Result<()> {
+    ) {
         let Ipv4OutPacket {
             buffer,
             packet_len,
@@ -381,12 +382,7 @@ impl<'a> InterfaceInner<'a> {
         let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
             let mut frame = EthernetFrame::new_unchecked(tx_buffer);
 
-            let src_addr = if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
-                addr
-            } else {
-                return Err(Error::Malformed);
-            };
-
+            let src_addr = self.hardware_addr.unwrap().ethernet_or_panic();
             frame.set_src_addr(src_addr);
             frame.set_dst_addr(*dst_hardware_addr);
 
@@ -396,14 +392,12 @@ impl<'a> InterfaceInner<'a> {
                 #[cfg(feature = "proto-ipv6")]
                 IpVersion::Ipv6 => frame.set_ethertype(EthernetProtocol::Ipv6),
             }
-
-            Ok(())
         };
 
         tx_token.consume(tx_len, |mut tx_buffer| {
             #[cfg(feature = "medium-ethernet")]
             if matches!(self.caps.medium, Medium::Ethernet) {
-                emit_ethernet(&IpRepr::Ipv4(*repr), tx_buffer)?;
+                emit_ethernet(&IpRepr::Ipv4(*repr), tx_buffer);
                 tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
             }
 
@@ -424,8 +418,6 @@ impl<'a> InterfaceInner<'a> {
 
             // Update the frag offset for the next fragment.
             *frag_offset += payload_len as u16;
-
-            Ok(())
         })
     }
 

+ 95 - 111
src/iface/interface/mod.rs

@@ -20,6 +20,7 @@ mod igmp;
 
 use core::cmp;
 use core::marker::PhantomData;
+use core::result::Result;
 use heapless::{LinearMap, Vec};
 use managed::ManagedSlice;
 
@@ -36,7 +37,6 @@ use crate::socket::dns;
 use crate::socket::*;
 use crate::time::{Duration, Instant};
 use crate::wire::*;
-use crate::{Error, Result};
 
 const MAX_IP_ADDR_COUNT: usize = 5;
 #[cfg(feature = "proto-igmp")]
@@ -953,23 +953,12 @@ impl<'a> Interface<'a> {
     /// This function returns a boolean value indicating whether any packets were
     /// processed or emitted, and thus, whether the readiness of any socket might
     /// have changed.
-    ///
-    /// # Errors
-    /// This method will routinely return errors in response to normal network
-    /// activity as well as certain boundary conditions such as buffer exhaustion.
-    /// These errors are provided as an aid for troubleshooting, and are meant
-    /// to be logged and ignored.
-    ///
-    /// As a special case, `Err(Error::Unrecognized)` is returned in response to
-    /// packets containing any unsupported protocol, option, or form, which is
-    /// a very common occurrence and on a production system it should not even
-    /// be logged.
     pub fn poll<D>(
         &mut self,
         timestamp: Instant,
         device: &mut D,
         sockets: &mut SocketSet<'_>,
-    ) -> Result<bool>
+    ) -> bool
     where
         D: Device + ?Sized,
     {
@@ -982,42 +971,35 @@ impl<'a> Interface<'a> {
         self.fragments.sixlowpan_fragments.remove_expired(timestamp);
 
         #[cfg(feature = "proto-ipv4-fragmentation")]
-        match self.ipv4_egress(device) {
-            Ok(true) => return Ok(true),
-            Err(e) => {
-                net_debug!("failed to transmit: {}", e);
-                return Err(e);
-            }
-            _ => (),
+        if self.ipv4_egress(device) {
+            return true;
         }
 
         #[cfg(feature = "proto-sixlowpan-fragmentation")]
-        match self.sixlowpan_egress(device) {
-            Ok(true) => return Ok(true),
-            Err(e) => {
-                net_debug!("failed to transmit: {}", e);
-                return Err(e);
-            }
-            _ => (),
+        if self.sixlowpan_egress(device) {
+            return true;
         }
 
         let mut readiness_may_have_changed = false;
 
         loop {
-            let processed_any = self.socket_ingress(device, sockets);
-            let emitted_any = self.socket_egress(device, sockets);
+            let mut did_something = false;
+            did_something |= self.socket_ingress(device, sockets);
+            did_something |= self.socket_egress(device, sockets);
 
             #[cfg(feature = "proto-igmp")]
-            self.igmp_egress(device)?;
+            {
+                did_something |= self.igmp_egress(device);
+            }
 
-            if processed_any || emitted_any {
+            if did_something {
                 readiness_may_have_changed = true;
             } else {
                 break;
             }
         }
 
-        Ok(readiness_may_have_changed)
+        readiness_may_have_changed
     }
 
     /// Return a _soft deadline_ for calling [poll] the next time.
@@ -1089,7 +1071,7 @@ impl<'a> Interface<'a> {
                                 self.inner
                                     .dispatch(tx_token, packet, Some(&mut self.out_packets))
                             {
-                                net_debug!("Failed to send response: {}", err);
+                                net_debug!("Failed to send response: {:?}", err);
                             }
                         }
                     }
@@ -1103,7 +1085,7 @@ impl<'a> Interface<'a> {
                                 packet,
                                 Some(&mut self.out_packets),
                             ) {
-                                net_debug!("Failed to send response: {}", err);
+                                net_debug!("Failed to send response: {:?}", err);
                             }
                         }
                     }
@@ -1118,7 +1100,7 @@ impl<'a> Interface<'a> {
                                 packet,
                                 Some(&mut self.out_packets),
                             ) {
-                                net_debug!("Failed to send response: {}", err);
+                                net_debug!("Failed to send response: {:?}", err);
                             }
                         }
                     }
@@ -1136,6 +1118,11 @@ impl<'a> Interface<'a> {
     {
         let _caps = device.capabilities();
 
+        enum EgressError {
+            Exhausted,
+            Dispatch(DispatchError),
+        }
+
         let mut emitted_any = false;
         for item in sockets.items_mut() {
             if !item
@@ -1149,21 +1136,25 @@ impl<'a> Interface<'a> {
             let mut respond = |inner: &mut InterfaceInner, response: IpPacket| {
                 neighbor_addr = Some(response.ip_repr().dst_addr());
                 let t = device.transmit(inner.now).ok_or_else(|| {
-                    net_debug!("failed to transmit IP: {}", Error::Exhausted);
-                    Error::Exhausted
+                    net_debug!("failed to transmit IP: device exhausted");
+                    EgressError::Exhausted
                 })?;
 
                 #[cfg(any(
                     feature = "proto-ipv4-fragmentation",
                     feature = "proto-sixlowpan-fragmentation"
                 ))]
-                inner.dispatch_ip(t, response, Some(&mut self.out_packets))?;
+                inner
+                    .dispatch_ip(t, response, Some(&mut self.out_packets))
+                    .map_err(EgressError::Dispatch)?;
 
                 #[cfg(not(any(
                     feature = "proto-ipv4-fragmentation",
                     feature = "proto-sixlowpan-fragmentation"
                 )))]
-                inner.dispatch_ip(t, response, None)?;
+                inner
+                    .dispatch_ip(t, response, None)
+                    .map_err(EgressError::Dispatch)?;
 
                 emitted_any = true;
 
@@ -1210,8 +1201,8 @@ impl<'a> Interface<'a> {
             };
 
             match result {
-                Err(Error::Exhausted) => break, // Device buffer full.
-                Err(Error::Unaddressable) => {
+                Err(EgressError::Exhausted) => break, // Device buffer full.
+                Err(EgressError::Dispatch(_)) => {
                     // `NeighborCache` already takes care of rate limiting the neighbor discovery
                     // requests from the socket. However, without an additional rate limiting
                     // mechanism, we would spin on every socket that has yet to discover its
@@ -1220,14 +1211,6 @@ impl<'a> Interface<'a> {
                         self.inner.now,
                         neighbor_addr.expect("non-IP response packet"),
                     );
-                    break;
-                }
-                Err(err) => {
-                    net_debug!(
-                        "{}: cannot dispatch egress packet: {}",
-                        item.meta.handle,
-                        err
-                    );
                 }
                 Ok(()) => {}
             }
@@ -1241,7 +1224,7 @@ impl<'a> Interface<'a> {
     /// processed or emitted, and thus, whether the readiness of any socket might
     /// have changed.
     #[cfg(feature = "proto-ipv4-fragmentation")]
-    fn ipv4_egress<D>(&mut self, device: &mut D) -> Result<bool>
+    fn ipv4_egress<D>(&mut self, device: &mut D) -> bool
     where
         D: Device + ?Sized,
     {
@@ -1251,7 +1234,7 @@ impl<'a> Interface<'a> {
         }
 
         if self.out_packets.ipv4_out_packet.is_empty() {
-            return Ok(false);
+            return false;
         }
 
         let Ipv4OutPacket {
@@ -1261,16 +1244,13 @@ impl<'a> Interface<'a> {
         } = &self.out_packets.ipv4_out_packet;
 
         if *packet_len > *sent_bytes {
-            match device.transmit(self.inner.now) {
-                Some(tx_token) => self
-                    .inner
-                    .dispatch_ipv4_out_packet(tx_token, &mut self.out_packets.ipv4_out_packet),
-                None => Err(Error::Exhausted),
+            if let Some(tx_token) = device.transmit(self.inner.now) {
+                self.inner
+                    .dispatch_ipv4_out_packet(tx_token, &mut self.out_packets.ipv4_out_packet);
+                return true;
             }
-            .map(|_| true)
-        } else {
-            Ok(false)
         }
+        false
     }
 
     /// Process fragments that still need to be sent for 6LoWPAN packets.
@@ -1279,7 +1259,7 @@ impl<'a> Interface<'a> {
     /// processed or emitted, and thus, whether the readiness of any socket might
     /// have changed.
     #[cfg(feature = "proto-sixlowpan-fragmentation")]
-    fn sixlowpan_egress<D>(&mut self, device: &mut D) -> Result<bool>
+    fn sixlowpan_egress<D>(&mut self, device: &mut D) -> bool
     where
         D: Device + ?Sized,
     {
@@ -1289,7 +1269,7 @@ impl<'a> Interface<'a> {
         }
 
         if self.out_packets.sixlowpan_out_packet.is_empty() {
-            return Ok(false);
+            return false;
         }
 
         let SixlowpanOutPacket {
@@ -1299,17 +1279,15 @@ impl<'a> Interface<'a> {
         } = &self.out_packets.sixlowpan_out_packet;
 
         if *packet_len > *sent_bytes {
-            match device.transmit(self.inner.now) {
-                Some(tx_token) => self.inner.dispatch_ieee802154_out_packet(
+            if let Some(tx_token) = device.transmit(self.inner.now) {
+                self.inner.dispatch_ieee802154_out_packet(
                     tx_token,
                     &mut self.out_packets.sixlowpan_out_packet,
-                ),
-                None => Err(Error::Exhausted),
+                );
+                return true;
             }
-            .map(|_| true)
-        } else {
-            Ok(false)
         }
+        false
     }
 }
 
@@ -1729,7 +1707,7 @@ impl<'a> InterfaceInner<'a> {
         tx_token: Tx,
         packet: EthernetPacket,
         _out_packet: Option<&mut OutPackets<'_>>,
-    ) -> Result<()>
+    ) -> Result<(), DispatchError>
     where
         Tx: TxToken,
     {
@@ -1759,22 +1737,19 @@ impl<'a> InterfaceInner<'a> {
         self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr))
     }
 
-    fn route(&self, addr: &IpAddress, timestamp: Instant) -> Result<IpAddress> {
+    fn route(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> {
         // Send directly.
         if self.in_same_network(addr) || addr.is_broadcast() {
-            return Ok(*addr);
+            return Some(*addr);
         }
 
         // Route via a router.
-        match self.routes.lookup(addr, timestamp) {
-            Some(router_addr) => Ok(router_addr),
-            None => Err(Error::Unaddressable),
-        }
+        self.routes.lookup(addr, timestamp)
     }
 
     fn has_neighbor(&self, addr: &IpAddress) -> bool {
         match self.route(addr, self.now) {
-            Ok(_routed_addr) => match self.caps.medium {
+            Some(_routed_addr) => match self.caps.medium {
                 #[cfg(feature = "medium-ethernet")]
                 Medium::Ethernet => self
                     .neighbor_cache
@@ -1792,7 +1767,7 @@ impl<'a> InterfaceInner<'a> {
                 #[cfg(feature = "medium-ip")]
                 Medium::Ip => true,
             },
-            Err(_) => false,
+            None => false,
         }
     }
 
@@ -1802,7 +1777,7 @@ impl<'a> InterfaceInner<'a> {
         tx_token: Tx,
         src_addr: &IpAddress,
         dst_addr: &IpAddress,
-    ) -> Result<(HardwareAddress, Tx)>
+    ) -> Result<(HardwareAddress, Tx), DispatchError>
     where
         Tx: TxToken,
     {
@@ -1852,7 +1827,9 @@ impl<'a> InterfaceInner<'a> {
             return Ok((hardware_addr, tx_token));
         }
 
-        let dst_addr = self.route(dst_addr, self.now)?;
+        let dst_addr = self
+            .route(dst_addr, self.now)
+            .ok_or(DispatchError::NoRoute)?;
 
         match self
             .neighbor_cache
@@ -1861,7 +1838,7 @@ impl<'a> InterfaceInner<'a> {
             .lookup(&dst_addr, self.now)
         {
             NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)),
-            NeighborAnswer::RateLimited => return Err(Error::Unaddressable),
+            NeighborAnswer::RateLimited => return Err(DispatchError::NeighborPending),
             _ => (), // XXX
         }
 
@@ -1872,12 +1849,7 @@ impl<'a> InterfaceInner<'a> {
                     "address {} not in neighbor cache, sending ARP request",
                     dst_addr
                 );
-                let src_hardware_addr =
-                    if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
-                        addr
-                    } else {
-                        return Err(Error::Malformed);
-                    };
+                let src_hardware_addr = self.hardware_addr.unwrap().ethernet_or_panic();
 
                 let arp_repr = ArpRepr::EthernetIpv4 {
                     operation: ArpOperation::Request,
@@ -1887,12 +1859,17 @@ impl<'a> InterfaceInner<'a> {
                     target_protocol_addr: dst_addr,
                 };
 
-                self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
-                    frame.set_dst_addr(EthernetAddress::BROADCAST);
-                    frame.set_ethertype(EthernetProtocol::Arp);
+                if let Err(e) =
+                    self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
+                        frame.set_dst_addr(EthernetAddress::BROADCAST);
+                        frame.set_ethertype(EthernetProtocol::Arp);
 
-                    arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
-                })?;
+                        arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
+                    })
+                {
+                    net_debug!("Failed to dispatch ARP request: {:?}", e);
+                    return Err(DispatchError::NeighborPending);
+                }
             }
 
             #[cfg(feature = "proto-ipv6")]
@@ -1918,15 +1895,19 @@ impl<'a> InterfaceInner<'a> {
                     solicit,
                 ));
 
-                self.dispatch_ip(tx_token, packet, None)?;
+                if let Err(e) = self.dispatch_ip(tx_token, packet, None) {
+                    net_debug!("Failed to dispatch NDISC solicit: {:?}", e);
+                    return Err(DispatchError::NeighborPending);
+                }
             }
 
             #[allow(unreachable_patterns)]
             _ => (),
         }
+
         // The request got dispatched, limit the rate on the cache.
         self.neighbor_cache.as_mut().unwrap().limit_rate(self.now);
-        Err(Error::Unaddressable)
+        Err(DispatchError::NeighborPending)
     }
 
     fn flush_cache(&mut self) {
@@ -1941,7 +1922,7 @@ impl<'a> InterfaceInner<'a> {
         tx_token: Tx,
         packet: IpPacket,
         _out_packet: Option<&mut OutPackets<'_>>,
-    ) -> Result<()> {
+    ) -> Result<(), DispatchError> {
         let mut ip_repr = packet.ip_repr();
         assert!(!ip_repr.dst_addr().is_unspecified());
 
@@ -1949,16 +1930,12 @@ impl<'a> InterfaceInner<'a> {
 
         #[cfg(feature = "medium-ieee802154")]
         if matches!(self.caps.medium, Medium::Ieee802154) {
-            let (dst_hardware_addr, tx_token) = match self.lookup_hardware_addr(
-                tx_token,
-                &ip_repr.src_addr(),
-                &ip_repr.dst_addr(),
-            )? {
-                (HardwareAddress::Ieee802154(addr), tx_token) => (addr, tx_token),
-                _ => unreachable!(),
-            };
+            let (addr, tx_token) =
+                self.lookup_hardware_addr(tx_token, &ip_repr.src_addr(), &ip_repr.dst_addr())?;
+            let addr = addr.ieee802154_or_panic();
 
-            return self.dispatch_ieee802154(dst_hardware_addr, tx_token, packet, _out_packet);
+            self.dispatch_ieee802154(addr, tx_token, packet, _out_packet);
+            return Ok(());
         }
 
         // Dispatch IP/Ethernet:
@@ -1999,12 +1976,7 @@ impl<'a> InterfaceInner<'a> {
         let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
             let mut frame = EthernetFrame::new_unchecked(tx_buffer);
 
-            let src_addr = if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
-                addr
-            } else {
-                return Err(Error::Malformed);
-            };
-
+            let src_addr = self.hardware_addr.unwrap().ethernet_or_panic();
             frame.set_src_addr(src_addr);
             frame.set_dst_addr(dst_hardware_addr);
 
@@ -2056,10 +2028,10 @@ impl<'a> InterfaceInner<'a> {
 
                         if buffer.len() < first_frag_ip_len {
                             net_debug!(
-                                "Fragmentation buffer is too small, at least {} needed",
+                                "Fragmentation buffer is too small, at least {} needed. Dropping",
                                 first_frag_ip_len
                             );
-                            return Err(Error::Exhausted);
+                            return Ok(());
                         }
 
                         #[cfg(feature = "medium-ethernet")]
@@ -2146,3 +2118,15 @@ impl<'a> InterfaceInner<'a> {
         }
     }
 }
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+enum DispatchError {
+    /// No route to dispatch this packet. Retrying won't help unless
+    /// configuration is changed.
+    NoRoute,
+    /// We do have a route to dispatch this packet, but we haven't discovered
+    /// the neighbor for it yet. Discovery has been initiated, dispatch
+    /// should be retried later.
+    NeighborPending,
+}

+ 23 - 30
src/iface/interface/sixlowpan.rs

@@ -11,8 +11,6 @@ use super::SixlowpanOutPacket;
 use crate::phy::ChecksumCapabilities;
 use crate::phy::TxToken;
 use crate::wire::*;
-use crate::Error;
-use crate::Result;
 
 // Max len of non-fragmented packets after decompression (including ipv6 header and payload)
 // TODO: lower. Should be (6lowpan mtu) - (min 6lowpan header size) + (max ipv6 header size)
@@ -277,24 +275,21 @@ impl<'a> InterfaceInner<'a> {
         tx_token: Tx,
         packet: IpPacket,
         _out_packet: Option<&mut OutPackets>,
-    ) -> Result<()> {
+    ) {
         // We first need to convert the IPv6 packet to a 6LoWPAN compressed packet.
         // Whenever this packet is to big to fit in the IEEE802.15.4 packet, then we need to
         // fragment it.
-        let ll_src_a = self.hardware_addr.map_or_else(
-            || Err(Error::Malformed),
-            |addr| match addr {
-                HardwareAddress::Ieee802154(addr) => Ok(addr),
-                _ => Err(Error::Malformed),
-            },
-        )?;
+        let ll_src_a = self.hardware_addr.unwrap().ieee802154_or_panic();
 
         let ip_repr = packet.ip_repr();
 
         let (src_addr, dst_addr) = match (ip_repr.src_addr(), ip_repr.dst_addr()) {
             (IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => (src_addr, dst_addr),
             #[allow(unreachable_patterns)]
-            _ => return Err(Error::Unaddressable),
+            _ => {
+                net_debug!("dispatch_ieee802154: dropping because src or dst addrs are not ipv6.");
+                return;
+            }
         };
 
         // Create the IEEE802.15.4 header.
@@ -325,7 +320,10 @@ impl<'a> InterfaceInner<'a> {
                 #[cfg(feature = "socket-udp")]
                 IpPacket::Udp(_) => SixlowpanNextHeader::Compressed,
                 #[allow(unreachable_patterns)]
-                _ => return Err(Error::Unrecognized),
+                _ => {
+                    net_debug!("dispatch_ieee802154: dropping, unhandled protocol.");
+                    return;
+                }
             },
             hop_limit: ip_repr.hop_limit(),
             ecn: None,
@@ -340,7 +338,6 @@ impl<'a> InterfaceInner<'a> {
         let mut _compressed_headers_len = iphc_repr.buffer_len();
         let mut _uncompressed_headers_len = ip_repr.header_len();
 
-        #[allow(unreachable_patterns)]
         match packet {
             #[cfg(feature = "socket-udp")]
             IpPacket::Udp((_, udpv6_repr, payload)) => {
@@ -357,7 +354,8 @@ impl<'a> InterfaceInner<'a> {
             IpPacket::Icmpv6((_, icmp_repr)) => {
                 total_size += icmp_repr.buffer_len();
             }
-            _ => return Err(Error::Unrecognized),
+            #[allow(unreachable_patterns)]
+            _ => unreachable!(),
         }
 
         let ieee_len = ieee_repr.buffer_len();
@@ -390,10 +388,10 @@ impl<'a> InterfaceInner<'a> {
                     managed::ManagedSlice::Borrowed(buffer) => {
                         if buffer.len() < total_size {
                             net_debug!(
-                                "6LoWPAN: Fragmentation buffer is too small, at least {} needed",
+                                "dispatch_ieee802154: dropping, fragmentation buffer is too small, at least {} needed",
                                 total_size
                             );
-                            return Err(Error::Exhausted);
+                            return;
                         }
                     }
                     #[cfg(feature = "alloc")]
@@ -409,7 +407,6 @@ impl<'a> InterfaceInner<'a> {
 
                 let b = &mut buffer[iphc_repr.buffer_len()..];
 
-                #[allow(unreachable_patterns)]
                 match packet {
                     #[cfg(feature = "socket-udp")]
                     IpPacket::Udp((_, udpv6_repr, payload)) => {
@@ -447,7 +444,8 @@ impl<'a> InterfaceInner<'a> {
                             &self.caps.checksum,
                         );
                     }
-                    _ => return Err(Error::Unrecognized),
+                    #[allow(unreachable_patterns)]
+                    _ => unreachable!(),
                 }
 
                 *packet_len = total_size;
@@ -501,9 +499,7 @@ impl<'a> InterfaceInner<'a> {
 
                     // Add the buffer part.
                     tx_buf[..frag1_size].copy_from_slice(&buffer[..frag1_size]);
-
-                    Ok(())
-                })
+                });
             }
 
             #[cfg(not(feature = "proto-sixlowpan-fragmentation"))]
@@ -511,7 +507,7 @@ impl<'a> InterfaceInner<'a> {
                 net_debug!(
                     "Enable the `proto-sixlowpan-fragmentation` feature for fragmentation support."
                 );
-                Ok(())
+                return;
             }
         } else {
             // We don't need fragmentation, so we emit everything to the TX token.
@@ -525,7 +521,6 @@ impl<'a> InterfaceInner<'a> {
                 iphc_repr.emit(&mut iphc_packet);
                 tx_buf = &mut tx_buf[iphc_repr.buffer_len()..];
 
-                #[allow(unreachable_patterns)]
                 match packet {
                     #[cfg(feature = "socket-udp")]
                     IpPacket::Udp((_, udpv6_repr, payload)) => {
@@ -563,10 +558,10 @@ impl<'a> InterfaceInner<'a> {
                             &self.caps.checksum,
                         );
                     }
-                    _ => return Err(Error::Unrecognized),
+                    #[allow(unreachable_patterns)]
+                    _ => unreachable!(),
                 }
-                Ok(())
-            })
+            });
         }
     }
 
@@ -578,7 +573,7 @@ impl<'a> InterfaceInner<'a> {
         &mut self,
         tx_token: Tx,
         out_packet: &mut SixlowpanOutPacket,
-    ) -> Result<()> {
+    ) {
         let SixlowpanOutPacket {
             buffer,
             packet_len,
@@ -634,9 +629,7 @@ impl<'a> InterfaceInner<'a> {
 
                 *sent_bytes += frag_size;
                 *datagram_offset += frag_size;
-
-                Ok(())
             },
-        )
+        );
     }
 }

+ 26 - 32
src/iface/interface/tests.rs

@@ -898,7 +898,7 @@ fn test_handle_other_arp_request() {
             &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])),
             &IpAddress::Ipv4(remote_ip_addr)
         ),
-        Err(Error::Unaddressable)
+        Err(DispatchError::NeighborPending)
     );
 }
 
@@ -1558,15 +1558,12 @@ fn test_echo_request_sixlowpan_128_bytes() {
     );
 
     let tx_token = device.transmit(Instant::now()).unwrap();
-    iface
-        .inner
-        .dispatch_ieee802154(
-            Ieee802154Address::default(),
-            tx_token,
-            result.unwrap(),
-            Some(&mut iface.out_packets),
-        )
-        .unwrap();
+    iface.inner.dispatch_ieee802154(
+        Ieee802154Address::default(),
+        tx_token,
+        result.unwrap(),
+        Some(&mut iface.out_packets),
+    );
 
     assert_eq!(
         device.queue[0],
@@ -1698,28 +1695,25 @@ fn test_sixlowpan_udp_with_fragmentation() {
     );
 
     let tx_token = device.transmit(Instant::now()).unwrap();
-    iface
-        .inner
-        .dispatch_ieee802154(
-            Ieee802154Address::default(),
-            tx_token,
-            IpPacket::Udp((
-                IpRepr::Ipv6(Ipv6Repr {
-                    src_addr: Ipv6Address::default(),
-                    dst_addr: Ipv6Address::default(),
-                    next_header: IpProtocol::Udp,
-                    payload_len: udp_data.len(),
-                    hop_limit: 64,
-                }),
-                UdpRepr {
-                    src_port: 1234,
-                    dst_port: 1234,
-                },
-                udp_data,
-            )),
-            Some(&mut iface.out_packets),
-        )
-        .unwrap();
+    iface.inner.dispatch_ieee802154(
+        Ieee802154Address::default(),
+        tx_token,
+        IpPacket::Udp((
+            IpRepr::Ipv6(Ipv6Repr {
+                src_addr: Ipv6Address::default(),
+                dst_addr: Ipv6Address::default(),
+                next_header: IpProtocol::Udp,
+                payload_len: udp_data.len(),
+                hop_limit: 64,
+            }),
+            UdpRepr {
+                src_port: 1234,
+                dst_port: 1234,
+            },
+            udp_data,
+        )),
+        Some(&mut iface.out_packets),
+    );
 
     iface.poll(Instant::now(), &mut device, &mut sockets);
 

+ 18 - 0
src/wire/mod.rs

@@ -312,6 +312,24 @@ impl HardwareAddress {
             HardwareAddress::Ieee802154(addr) => addr.is_broadcast(),
         }
     }
+
+    #[cfg(feature = "medium-ethernet")]
+    pub(crate) fn ethernet_or_panic(&self) -> EthernetAddress {
+        match self {
+            HardwareAddress::Ethernet(addr) => *addr,
+            #[allow(unreachable_patterns)]
+            _ => panic!("HardwareAddress is not Ethernet."),
+        }
+    }
+
+    #[cfg(feature = "medium-ieee802154")]
+    pub(crate) fn ieee802154_or_panic(&self) -> Ieee802154Address {
+        match self {
+            HardwareAddress::Ieee802154(addr) => *addr,
+            #[allow(unreachable_patterns)]
+            _ => panic!("HardwareAddress is not Ethernet."),
+        }
+    }
 }
 
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]