⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/net/
device.rs

1//! Network device abstraction layer
2//!
3//! Defines the [`NetworkDevice`] trait and device registry for hardware
4//! network drivers. All network drivers (E1000, VirtIO-Net, etc.)
5//! implement this trait to provide a uniform interface for the IP stack.
6
7#![allow(clippy::derivable_impls)]
8
9use alloc::{boxed::Box, string::String, vec::Vec};
10
11use spin::Mutex;
12
13use super::{MacAddress, Packet};
14use crate::error::KernelError;
15
16/// Network device capabilities
17#[derive(Debug, Clone, Copy)]
18pub struct DeviceCapabilities {
19    pub max_transmission_unit: usize,
20    pub supports_vlan: bool,
21    pub supports_checksum_offload: bool,
22    pub supports_tso: bool, // TCP Segmentation Offload
23    pub supports_lro: bool, // Large Receive Offload
24}
25
26impl Default for DeviceCapabilities {
27    fn default() -> Self {
28        Self {
29            max_transmission_unit: 1500,
30            supports_vlan: false,
31            supports_checksum_offload: false,
32            supports_tso: false,
33            supports_lro: false,
34        }
35    }
36}
37
38/// Network device statistics
39#[derive(Debug, Clone, Copy)]
40pub struct DeviceStatistics {
41    pub rx_packets: u64,
42    pub tx_packets: u64,
43    pub rx_bytes: u64,
44    pub tx_bytes: u64,
45    pub rx_errors: u64,
46    pub tx_errors: u64,
47    pub rx_dropped: u64,
48    pub tx_dropped: u64,
49}
50
51impl Default for DeviceStatistics {
52    fn default() -> Self {
53        Self {
54            rx_packets: 0,
55            tx_packets: 0,
56            rx_bytes: 0,
57            tx_bytes: 0,
58            rx_errors: 0,
59            tx_errors: 0,
60            rx_dropped: 0,
61            tx_dropped: 0,
62        }
63    }
64}
65
66/// Network device state
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum DeviceState {
69    Down,
70    Up,
71    Dormant,
72    Testing,
73}
74
75/// Network device trait
76pub trait NetworkDevice: Send {
77    /// Get device name
78    fn name(&self) -> &str;
79
80    /// Get device MAC address
81    fn mac_address(&self) -> MacAddress;
82
83    /// Get device capabilities
84    fn capabilities(&self) -> DeviceCapabilities;
85
86    /// Get device state
87    fn state(&self) -> DeviceState;
88
89    /// Set device state
90    fn set_state(&mut self, state: DeviceState) -> Result<(), KernelError>;
91
92    /// Get device statistics
93    fn statistics(&self) -> DeviceStatistics;
94
95    /// Transmit a packet
96    fn transmit(&mut self, packet: &Packet) -> Result<(), KernelError>;
97
98    /// Receive a packet (non-blocking)
99    fn receive(&mut self) -> Result<Option<Packet>, KernelError>;
100
101    /// Get MTU
102    fn mtu(&self) -> usize {
103        self.capabilities().max_transmission_unit
104    }
105}
106
107/// Loopback device implementation
108pub struct LoopbackDevice {
109    name: String,
110    mac: MacAddress,
111    state: DeviceState,
112    stats: DeviceStatistics,
113    queue: Vec<Packet>,
114}
115
116impl LoopbackDevice {
117    pub fn new() -> Self {
118        Self {
119            name: String::from("lo0"),
120            mac: MacAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
121            state: DeviceState::Down,
122            stats: DeviceStatistics::default(),
123            queue: Vec::new(),
124        }
125    }
126}
127
128impl Default for LoopbackDevice {
129    fn default() -> Self {
130        Self::new()
131    }
132}
133
134impl NetworkDevice for LoopbackDevice {
135    fn name(&self) -> &str {
136        &self.name
137    }
138
139    fn mac_address(&self) -> MacAddress {
140        self.mac
141    }
142
143    fn capabilities(&self) -> DeviceCapabilities {
144        DeviceCapabilities {
145            max_transmission_unit: 65536,
146            supports_vlan: false,
147            supports_checksum_offload: true,
148            supports_tso: false,
149            supports_lro: false,
150        }
151    }
152
153    fn state(&self) -> DeviceState {
154        self.state
155    }
156
157    fn set_state(&mut self, state: DeviceState) -> Result<(), KernelError> {
158        self.state = state;
159        Ok(())
160    }
161
162    fn statistics(&self) -> DeviceStatistics {
163        self.stats
164    }
165
166    fn transmit(&mut self, packet: &Packet) -> Result<(), KernelError> {
167        if self.state != DeviceState::Up {
168            self.stats.tx_dropped += 1;
169            return Err(KernelError::InvalidState {
170                expected: "up",
171                actual: "not_up",
172            });
173        }
174
175        // Loopback: immediately queue for receive
176        self.queue.push(packet.clone());
177        self.stats.tx_packets += 1;
178        self.stats.tx_bytes += packet.len() as u64;
179
180        Ok(())
181    }
182
183    fn receive(&mut self) -> Result<Option<Packet>, KernelError> {
184        if self.state != DeviceState::Up {
185            return Ok(None);
186        }
187
188        if let Some(packet) = self.queue.pop() {
189            self.stats.rx_packets += 1;
190            self.stats.rx_bytes += packet.len() as u64;
191            Ok(Some(packet))
192        } else {
193            Ok(None)
194        }
195    }
196}
197
198/// Ethernet device (placeholder for real hardware)
199pub struct EthernetDevice {
200    name: String,
201    mac: MacAddress,
202    state: DeviceState,
203    stats: DeviceStatistics,
204    capabilities: DeviceCapabilities,
205}
206
207impl EthernetDevice {
208    pub fn new(name: String, mac: MacAddress) -> Self {
209        Self {
210            name,
211            mac,
212            state: DeviceState::Down,
213            stats: DeviceStatistics::default(),
214            capabilities: DeviceCapabilities::default(),
215        }
216    }
217}
218
219impl NetworkDevice for EthernetDevice {
220    fn name(&self) -> &str {
221        &self.name
222    }
223
224    fn mac_address(&self) -> MacAddress {
225        self.mac
226    }
227
228    fn capabilities(&self) -> DeviceCapabilities {
229        self.capabilities
230    }
231
232    fn state(&self) -> DeviceState {
233        self.state
234    }
235
236    fn set_state(&mut self, state: DeviceState) -> Result<(), KernelError> {
237        self.state = state;
238        // Hardware state is configured via DMA ring allocation in with_mmio() devices
239        Ok(())
240    }
241
242    fn statistics(&self) -> DeviceStatistics {
243        self.stats
244    }
245
246    fn transmit(&mut self, packet: &Packet) -> Result<(), KernelError> {
247        if self.state != DeviceState::Up {
248            self.stats.tx_dropped += 1;
249            return Err(KernelError::InvalidState {
250                expected: "up",
251                actual: "not_up",
252            });
253        }
254
255        // DMA TX is handled by with_mmio() EthernetDevice instances
256        self.stats.tx_packets += 1;
257        self.stats.tx_bytes += packet.len() as u64;
258
259        Ok(())
260    }
261
262    fn receive(&mut self) -> Result<Option<Packet>, KernelError> {
263        if self.state != DeviceState::Up {
264            return Ok(None);
265        }
266
267        // DMA RX is handled by with_mmio() EthernetDevice instances
268        Ok(None)
269    }
270}
271
272/// Device registry protected by Mutex for safe concurrent access
273static DEVICES: Mutex<Option<Vec<Box<dyn NetworkDevice>>>> = Mutex::new(None);
274
275/// Initialize device subsystem
276pub fn init() -> Result<(), KernelError> {
277    println!("[NETDEV] Initializing network device subsystem...");
278
279    let mut devices_lock = DEVICES.lock();
280    let mut device_list = Vec::new();
281
282    // Create and register loopback device
283    let mut lo = LoopbackDevice::new();
284    lo.set_state(DeviceState::Up)?;
285    device_list.push(Box::new(lo) as Box<dyn NetworkDevice>);
286
287    *devices_lock = Some(device_list);
288
289    println!("[NETDEV] Network device subsystem initialized");
290    Ok(())
291}
292
293/// Register a network device
294pub fn register_device(device: Box<dyn NetworkDevice>) -> Result<(), KernelError> {
295    let mut devices_lock = DEVICES.lock();
296    if let Some(ref mut devices) = *devices_lock {
297        println!("[NETDEV] Registering device: {}", device.name());
298        devices.push(device);
299        Ok(())
300    } else {
301        Err(KernelError::InvalidState {
302            expected: "initialized",
303            actual: "not_initialized",
304        })
305    }
306}
307
308/// Execute a closure with a device by name (immutable access)
309pub fn with_device<R, F: FnOnce(&dyn NetworkDevice) -> R>(name: &str, f: F) -> Option<R> {
310    let devices_lock = DEVICES.lock();
311    if let Some(ref devices) = *devices_lock {
312        devices
313            .iter()
314            .find(|d| d.name() == name)
315            .map(|d| f(d.as_ref()))
316    } else {
317        None
318    }
319}
320
321/// Execute a closure with a device by name (mutable access)
322pub fn with_device_mut<R, F: FnOnce(&mut dyn NetworkDevice) -> R>(name: &str, f: F) -> Option<R> {
323    let mut devices_lock = DEVICES.lock();
324    if let Some(ref mut devices) = *devices_lock {
325        devices
326            .iter_mut()
327            .find(|d| d.name() == name)
328            .map(|d| f(d.as_mut()))
329    } else {
330        None
331    }
332}
333
334/// List all device names
335pub fn list_devices() -> Vec<String> {
336    let devices_lock = DEVICES.lock();
337    if let Some(ref devices) = *devices_lock {
338        devices.iter().map(|d| String::from(d.name())).collect()
339    } else {
340        Vec::new()
341    }
342}
343
344#[cfg(test)]
345mod tests {
346    use super::*;
347
348    #[test]
349    fn test_loopback_device() {
350        let mut lo = LoopbackDevice::new();
351        assert_eq!(lo.state(), DeviceState::Down);
352
353        lo.set_state(DeviceState::Up).unwrap();
354        assert_eq!(lo.state(), DeviceState::Up);
355    }
356
357    #[test]
358    fn test_device_capabilities() {
359        let caps = DeviceCapabilities::default();
360        assert_eq!(caps.max_transmission_unit, 1500);
361        assert!(!caps.supports_vlan);
362    }
363}