use alloc::{boxed::Box, vec::Vec};
pub(crate) const ETH_ZLEN: usize = 60;
pub(crate) const ETHERNET_FRAME_CAPACITY: usize = 2048;
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
pub enum NetDeviceError {
#[error("network frame port should be retried")]
Again,
#[error("network frame port is stopped")]
Stopped,
#[error("invalid network frame size")]
InvalidParam,
#[error("network frame port I/O failed")]
Io,
#[error("network frame port memory allocation failed")]
NoMemory,
}
pub type NetDeviceResult<T = ()> = Result<T, NetDeviceError>;
pub struct ProtocolEthernetFrame {
bytes: [u8; ETHERNET_FRAME_CAPACITY],
len: usize,
}
impl ProtocolEthernetFrame {
pub fn new(len: usize) -> NetDeviceResult<Self> {
if len > ETHERNET_FRAME_CAPACITY {
return Err(NetDeviceError::InvalidParam);
}
Ok(Self {
bytes: [0; ETHERNET_FRAME_CAPACITY],
len,
})
}
pub fn packet(&self) -> &[u8] {
&self.bytes[..self.len]
}
pub fn packet_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..self.len]
}
pub fn packet_len(&self) -> usize {
self.len
}
pub(crate) fn copy_from_slice(packet: &[u8]) -> NetDeviceResult<Self> {
let mut frame = Self::new(packet.len())?;
frame.packet_mut().copy_from_slice(packet);
Ok(frame)
}
}
pub trait EthernetFramePort: Send + 'static {
fn device_name(&self) -> &str;
fn mac_address(&self) -> [u8; 6];
fn transmit(&mut self, frame: &ProtocolEthernetFrame) -> NetDeviceResult;
fn receive(&mut self) -> NetDeviceResult<ProtocolEthernetFrame>;
}
pub type EthernetFramePortList = Vec<Box<dyn EthernetFramePort>>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn network_device_errors_have_domain_messages() {
assert_eq!(
alloc::format!("{}", NetDeviceError::NoMemory),
"network frame port memory allocation failed"
);
}
}