sel4_virtio_net/
lib.rs

1//
2// Copyright 2023, Colias Group, LLC
3// Copyright (c) 2019-2020 rCore Developers
4//
5// SPDX-License-Identifier: MIT
6//
7
8#![no_std]
9
10extern crate alloc;
11
12use alloc::rc::Rc;
13use core::cell::RefCell;
14use core::convert::Infallible;
15
16use log::trace;
17use sel4_driver_interfaces::net::{GetNetDeviceMeta, MacAddress};
18use sel4_driver_interfaces::HandleInterrupt;
19use smoltcp::phy::{Device, DeviceCapabilities, Medium, RxToken, TxToken};
20use smoltcp::time::Instant;
21use virtio_drivers::device::net::{RxBuffer, VirtIONet};
22use virtio_drivers::{transport::Transport, Error, Hal};
23
24pub const NET_QUEUE_SIZE: usize = 16;
25
26pub type DeviceImpl<H, T> = VirtIONet<H, T, NET_QUEUE_SIZE>;
27
28pub struct DeviceWrapper<H: Hal, T: Transport> {
29    inner: Rc<RefCell<DeviceImpl<H, T>>>,
30}
31
32impl<H: Hal, T: Transport> DeviceWrapper<H, T> {
33    pub fn new(dev: DeviceImpl<H, T>) -> Self {
34        DeviceWrapper {
35            inner: Rc::new(RefCell::new(dev)),
36        }
37    }
38}
39
40impl<H: Hal, T: Transport> HandleInterrupt for DeviceWrapper<H, T> {
41    fn handle_interrupt(&mut self) {
42        self.inner.borrow_mut().ack_interrupt();
43    }
44}
45
46impl<H: Hal, T: Transport> GetNetDeviceMeta for DeviceWrapper<H, T> {
47    type Error = Infallible;
48
49    fn get_mac_address(&mut self) -> Result<MacAddress, Self::Error> {
50        Ok(MacAddress(self.inner.borrow().mac_address()))
51    }
52}
53
54impl<H: Hal, T: Transport> Device for DeviceWrapper<H, T> {
55    type RxToken<'a>
56        = VirtioRxToken<H, T>
57    where
58        Self: 'a;
59    type TxToken<'a>
60        = VirtioTxToken<H, T>
61    where
62        Self: 'a;
63
64    fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
65        match self.inner.borrow_mut().receive() {
66            Ok(buf) => Some((
67                VirtioRxToken(self.inner.clone(), buf),
68                VirtioTxToken(self.inner.clone()),
69            )),
70            Err(Error::NotReady) => None,
71            Err(err) => panic!("receive failed: {}", err),
72        }
73    }
74
75    fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
76        Some(VirtioTxToken(self.inner.clone()))
77    }
78
79    fn capabilities(&self) -> DeviceCapabilities {
80        let mut caps = DeviceCapabilities::default();
81        caps.max_transmission_unit = 1536;
82        caps.max_burst_size = Some(1);
83        caps.medium = Medium::Ethernet;
84        caps
85    }
86}
87
88pub struct VirtioRxToken<H: Hal, T: Transport>(Rc<RefCell<DeviceImpl<H, T>>>, RxBuffer);
89
90impl<H: Hal, T: Transport> RxToken for VirtioRxToken<H, T> {
91    fn consume<R, F>(self, f: F) -> R
92    where
93        F: FnOnce(&mut [u8]) -> R,
94    {
95        let mut rx_buf = self.1;
96        trace!(
97            "RECV {} bytes: {:02X?}",
98            rx_buf.packet_len(),
99            rx_buf.packet()
100        );
101        let result = f(rx_buf.packet_mut());
102        self.0.borrow_mut().recycle_rx_buffer(rx_buf).unwrap();
103        result
104    }
105}
106
107pub struct VirtioTxToken<H: Hal, T: Transport>(Rc<RefCell<DeviceImpl<H, T>>>);
108
109impl<H: Hal, T: Transport> TxToken for VirtioTxToken<H, T> {
110    fn consume<R, F>(self, len: usize, f: F) -> R
111    where
112        F: FnOnce(&mut [u8]) -> R,
113    {
114        let mut dev = self.0.borrow_mut();
115        let mut tx_buf = dev.new_tx_buffer(len);
116        let result = f(tx_buf.packet_mut());
117        trace!("SEND {} bytes: {:02X?}", len, tx_buf.packet());
118        dev.send(tx_buf).unwrap();
119        result
120    }
121}