virtio_drivers/device/net/
dev.rs

1use alloc::vec;
2
3use super::net_buf::{RxBuffer, TxBuffer};
4use super::{EthernetAddress, VirtIONetRaw};
5use crate::transport::InterruptStatus;
6use crate::{hal::Hal, transport::Transport, Error, Result};
7
8/// Driver for a VirtIO network device.
9///
10/// Unlike [`VirtIONetRaw`], it uses [`RxBuffer`]s for transmission and
11/// reception rather than the raw slices. On initialization, it pre-allocates
12/// all receive buffers and puts them all in the receive queue.
13///
14/// The virtio network device is a virtual ethernet card.
15///
16/// It has enhanced rapidly and demonstrates clearly how support for new
17/// features are added to an existing device.
18/// Empty buffers are placed in one virtqueue for receiving packets, and
19/// outgoing packets are enqueued into another for transmission in that order.
20/// A third command queue is used to control advanced filtering features.
21pub struct VirtIONet<H: Hal, T: Transport, const QUEUE_SIZE: usize> {
22    inner: VirtIONetRaw<H, T, QUEUE_SIZE>,
23    rx_buffers: [Option<RxBuffer>; QUEUE_SIZE],
24}
25
26impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE> {
27    /// Create a new VirtIO-Net driver.
28    pub fn new(transport: T, buf_len: usize) -> Result<Self> {
29        let mut inner = VirtIONetRaw::new(transport)?;
30
31        const NONE_BUF: Option<RxBuffer> = None;
32        let mut rx_buffers = [NONE_BUF; QUEUE_SIZE];
33        for (i, rx_buf_place) in rx_buffers.iter_mut().enumerate() {
34            let mut rx_buf = RxBuffer::new(i, buf_len, inner.legacy_header);
35            // SAFETY: The buffer lives as long as the queue.
36            let token = unsafe { inner.receive_begin(rx_buf.as_bytes_mut())? };
37            assert_eq!(token, i as u16);
38            *rx_buf_place = Some(rx_buf);
39        }
40
41        Ok(VirtIONet { inner, rx_buffers })
42    }
43
44    /// Acknowledge interrupt.
45    pub fn ack_interrupt(&mut self) -> InterruptStatus {
46        self.inner.ack_interrupt()
47    }
48
49    /// Disable interrupts.
50    pub fn disable_interrupts(&mut self) {
51        self.inner.disable_interrupts()
52    }
53
54    /// Enable interrupts.
55    pub fn enable_interrupts(&mut self) {
56        self.inner.enable_interrupts()
57    }
58
59    /// Get MAC address.
60    pub fn mac_address(&self) -> EthernetAddress {
61        self.inner.mac_address()
62    }
63
64    /// Whether can send packet.
65    pub fn can_send(&self) -> bool {
66        self.inner.can_send()
67    }
68
69    /// Whether can receive packet.
70    pub fn can_recv(&self) -> bool {
71        self.inner.poll_receive().is_some()
72    }
73
74    /// Receives a [`RxBuffer`] from network. If currently no data, returns an
75    /// error with type [`Error::NotReady`].
76    ///
77    /// It will try to pop a buffer that completed data reception in the
78    /// NIC queue.
79    pub fn receive(&mut self) -> Result<RxBuffer> {
80        if let Some(token) = self.inner.poll_receive() {
81            let mut rx_buf = self.rx_buffers[token as usize]
82                .take()
83                .ok_or(Error::WrongToken)?;
84            if token != rx_buf.idx {
85                return Err(Error::WrongToken);
86            }
87
88            // SAFETY: `token` == `rx_buf.idx`, so we are passing the same
89            // buffer as we passed to `VirtQueue::add` and it is still valid.
90            let (_hdr_len, pkt_len) =
91                unsafe { self.inner.receive_complete(token, rx_buf.as_bytes_mut())? };
92            rx_buf.set_packet_len(pkt_len);
93            Ok(rx_buf)
94        } else {
95            Err(Error::NotReady)
96        }
97    }
98
99    /// Gives back the ownership of `rx_buf`, and recycles it for next use.
100    ///
101    /// It will add the buffer back to the NIC queue.
102    pub fn recycle_rx_buffer(&mut self, mut rx_buf: RxBuffer) -> Result {
103        // SAFETY: We take the ownership of `rx_buf` back to `rx_buffers`,
104        // so it lives as long as the queue.
105        let new_token = unsafe { self.inner.receive_begin(rx_buf.as_bytes_mut()) }?;
106        // `rx_buffers[new_token]` is expected to be `None` since it was taken
107        // away at `Self::receive()` and has not been added back.
108        if self.rx_buffers[new_token as usize].is_some() {
109            return Err(Error::WrongToken);
110        }
111        rx_buf.idx = new_token;
112        self.rx_buffers[new_token as usize] = Some(rx_buf);
113        Ok(())
114    }
115
116    /// Allocate a new buffer for transmitting.
117    pub fn new_tx_buffer(&self, buf_len: usize) -> TxBuffer {
118        TxBuffer(vec![0; buf_len])
119    }
120
121    /// Sends a [`TxBuffer`] to the network, and blocks until the request
122    /// completed.
123    pub fn send(&mut self, tx_buf: TxBuffer) -> Result {
124        self.inner.send(tx_buf.packet())
125    }
126}