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