use ruvix_types::KernelError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u16)]
pub enum NetError {
PacketTooShort = 1,
PacketTooLarge = 2,
InvalidEthernetFrame = 3,
UnsupportedEtherType = 4,
InvalidIpv4Header = 5,
Ipv4ChecksumError = 6,
InvalidIpVersion = 7,
InvalidIpHeaderLength = 8,
TtlExpired = 9,
InvalidUdpHeader = 10,
UdpChecksumError = 11,
InvalidIcmpHeader = 12,
InvalidArpPacket = 13,
ArpNotFound = 14,
ArpCacheFull = 15,
SocketNotBound = 16,
PortInUse = 17,
NoPortsAvailable = 18,
DestinationUnreachable = 19,
DeviceError = 20,
BufferTooSmall = 21,
WouldBlock = 22,
InvalidPort = 23,
FragmentationNotSupported = 24,
KernelError(u16) = 255,
}
impl NetError {
#[inline]
#[must_use]
pub const fn as_str(&self) -> &'static str {
match self {
Self::PacketTooShort => "Packet too short for header",
Self::PacketTooLarge => "Packet exceeds maximum size",
Self::InvalidEthernetFrame => "Invalid Ethernet frame format",
Self::UnsupportedEtherType => "Unsupported EtherType",
Self::InvalidIpv4Header => "Invalid IPv4 header",
Self::Ipv4ChecksumError => "IPv4 checksum mismatch",
Self::InvalidIpVersion => "Invalid IP version (expected 4)",
Self::InvalidIpHeaderLength => "Invalid IP header length",
Self::TtlExpired => "TTL expired",
Self::InvalidUdpHeader => "Invalid UDP header",
Self::UdpChecksumError => "UDP checksum mismatch",
Self::InvalidIcmpHeader => "Invalid ICMP header",
Self::InvalidArpPacket => "Invalid ARP packet",
Self::ArpNotFound => "ARP entry not found",
Self::ArpCacheFull => "ARP cache full",
Self::SocketNotBound => "Socket not bound",
Self::PortInUse => "Port already in use",
Self::NoPortsAvailable => "No ephemeral ports available",
Self::DestinationUnreachable => "Destination unreachable",
Self::DeviceError => "Network device error",
Self::BufferTooSmall => "Buffer too small",
Self::WouldBlock => "Operation would block",
Self::InvalidPort => "Invalid port number",
Self::FragmentationNotSupported => "IP fragmentation not supported",
Self::KernelError(_) => "Kernel error",
}
}
#[inline]
#[must_use]
pub const fn code(&self) -> u16 {
match self {
Self::PacketTooShort => 1,
Self::PacketTooLarge => 2,
Self::InvalidEthernetFrame => 3,
Self::UnsupportedEtherType => 4,
Self::InvalidIpv4Header => 5,
Self::Ipv4ChecksumError => 6,
Self::InvalidIpVersion => 7,
Self::InvalidIpHeaderLength => 8,
Self::TtlExpired => 9,
Self::InvalidUdpHeader => 10,
Self::UdpChecksumError => 11,
Self::InvalidIcmpHeader => 12,
Self::InvalidArpPacket => 13,
Self::ArpNotFound => 14,
Self::ArpCacheFull => 15,
Self::SocketNotBound => 16,
Self::PortInUse => 17,
Self::NoPortsAvailable => 18,
Self::DestinationUnreachable => 19,
Self::DeviceError => 20,
Self::BufferTooSmall => 21,
Self::WouldBlock => 22,
Self::InvalidPort => 23,
Self::FragmentationNotSupported => 24,
Self::KernelError(code) => *code,
}
}
#[inline]
#[must_use]
pub const fn from_u16(code: u16) -> Option<Self> {
match code {
1 => Some(Self::PacketTooShort),
2 => Some(Self::PacketTooLarge),
3 => Some(Self::InvalidEthernetFrame),
4 => Some(Self::UnsupportedEtherType),
5 => Some(Self::InvalidIpv4Header),
6 => Some(Self::Ipv4ChecksumError),
7 => Some(Self::InvalidIpVersion),
8 => Some(Self::InvalidIpHeaderLength),
9 => Some(Self::TtlExpired),
10 => Some(Self::InvalidUdpHeader),
11 => Some(Self::UdpChecksumError),
12 => Some(Self::InvalidIcmpHeader),
13 => Some(Self::InvalidArpPacket),
14 => Some(Self::ArpNotFound),
15 => Some(Self::ArpCacheFull),
16 => Some(Self::SocketNotBound),
17 => Some(Self::PortInUse),
18 => Some(Self::NoPortsAvailable),
19 => Some(Self::DestinationUnreachable),
20 => Some(Self::DeviceError),
21 => Some(Self::BufferTooSmall),
22 => Some(Self::WouldBlock),
23 => Some(Self::InvalidPort),
24 => Some(Self::FragmentationNotSupported),
_ => None,
}
}
}
impl From<KernelError> for NetError {
fn from(err: KernelError) -> Self {
Self::KernelError(err as u16)
}
}
pub type NetResult<T> = Result<T, NetError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_roundtrip() {
let errors = [
NetError::PacketTooShort,
NetError::InvalidEthernetFrame,
NetError::ArpNotFound,
NetError::WouldBlock,
];
for err in errors {
let code = err.code();
let parsed = NetError::from_u16(code).unwrap();
assert_eq!(err, parsed);
}
}
#[test]
fn test_error_as_str() {
assert_eq!(NetError::PacketTooShort.as_str(), "Packet too short for header");
assert_eq!(NetError::ArpNotFound.as_str(), "ARP entry not found");
}
#[test]
fn test_kernel_error_conversion() {
let kernel_err = KernelError::OutOfMemory;
let net_err: NetError = kernel_err.into();
assert!(matches!(net_err, NetError::KernelError(5)));
}
}