os/device/net/
net_device.rs

1/// 网络设备错误
2#[derive(Debug)]
3pub enum NetDeviceError {
4    IoError,
5    DeviceNotReady,
6    NotSupported,
7    QueueFull,
8    QueueEmpty,
9    AllocationFailed,
10}
11
12/// 网络设备接口
13pub trait NetDevice: Send + Sync {
14    /// 发送数据包
15    fn send(&self, packet: &[u8]) -> Result<(), NetDeviceError>;
16
17    /// 接收数据包
18    fn receive(&self, buf: &mut [u8]) -> Result<usize, NetDeviceError>;
19
20    /// 获取设备标识符
21    fn device_id(&self) -> usize;
22
23    /// 获取最大传输单元(MTU)
24    fn mtu(&self) -> usize;
25
26    /// 获取设备名称
27    fn name(&self) -> &str;
28
29    /// 获取MAC地址
30    fn mac_address(&self) -> [u8; 6];
31}
32
33use crate::device::virtio_hal::VirtIOHal;
34use crate::sync::SpinLock;
35use alloc::boxed::Box;
36use alloc::sync::Arc;
37use virtio_drivers::{
38    device::net::{TxBuffer, VirtIONet},
39    transport::Transport,
40};
41
42/// 使用 virtio-drivers 0.12.0 实现的 Virtio 网络设备
43pub struct VirtioNetDevice<T: Transport + Send + Sync> {
44    // 使用SpinLock包装UnsafeCell以实现线程安全的内部可变性
45    virtio_net: SpinLock<Option<Box<VirtIONet<VirtIOHal, T, 256>>>>,
46    device_id: usize,
47    name: &'static str,
48    mac: [u8; 6],
49    mtu: usize,
50}
51
52impl<T: Transport + Send + Sync> VirtioNetDevice<T> {
53    /// 创建新的 Virtio 网络设备实例
54    ///
55    /// # 参数
56    /// * `transport` - VirtIO 设备传输层
57    /// * `device_id` - 设备标识符
58    pub fn new(transport: T, device_id: usize) -> Result<Arc<Self>, NetDeviceError> {
59        let virtio_net = VirtIONet::<VirtIOHal, T, 256>::new(transport, 0)
60            .map_err(|_| NetDeviceError::DeviceNotReady)?;
61
62        // 从 VirtIONet 中获取 MAC 地址和 MTU
63        let mac = virtio_net.mac_address();
64        let mtu = 1500; // 默认以太网 MTU
65
66        Ok(Arc::new(Self {
67            virtio_net: SpinLock::new(Some(Box::new(virtio_net))),
68            device_id,
69            name: "virtio-net",
70            mac,
71            mtu,
72        }))
73    }
74}
75
76impl<T: Transport + Send + Sync> NetDevice for VirtioNetDevice<T> {
77    /// 发送数据包
78    fn send(&self, packet: &[u8]) -> Result<(), NetDeviceError> {
79        if packet.len() > self.mtu {
80            // 18 字节用于以太网头部和尾部
81            return Err(NetDeviceError::QueueFull);
82        }
83
84        // 使用SpinLock的RAII模式,自动处理锁的获取和释放
85        if let Some(ref mut virtio_net) = *self.virtio_net.lock() {
86            let tx_buffer = TxBuffer::from(packet);
87            match virtio_net.send(tx_buffer) {
88                Ok(_) => Ok(()),
89                Err(_) => Err(NetDeviceError::QueueFull),
90            }
91        } else {
92            Err(NetDeviceError::DeviceNotReady)
93        }
94    }
95
96    /// 接收数据包
97    fn receive(&self, buf: &mut [u8]) -> Result<usize, NetDeviceError> {
98        // 使用SpinLock的RAII模式,自动处理锁的获取和释放
99        if let Some(ref mut virtio_net) = *self.virtio_net.lock() {
100            match virtio_net.receive() {
101                Ok(rx_buffer) => {
102                    // 使用packet()方法获取实际的网络数据包(不包括头部)
103                    let packet = rx_buffer.packet();
104                    let actual_len = core::cmp::min(packet.len(), buf.len());
105                    buf[..actual_len].copy_from_slice(&packet[..actual_len]);
106                    Ok(actual_len)
107                }
108                Err(_) => Err(NetDeviceError::QueueEmpty),
109            }
110        } else {
111            Err(NetDeviceError::DeviceNotReady)
112        }
113    }
114
115    /// 获取设备标识符
116    fn device_id(&self) -> usize {
117        self.device_id
118    }
119
120    /// 获取最大传输单元(MTU)
121    fn mtu(&self) -> usize {
122        self.mtu
123    }
124
125    /// 获取设备名称
126    fn name(&self) -> &str {
127        self.name
128    }
129
130    /// 获取MAC地址
131    fn mac_address(&self) -> [u8; 6] {
132        self.mac
133    }
134}