virtio_net/
tcp.rs

1//! Simple echo server over TCP.
2//!
3//! Ref: <https://github.com/smoltcp-rs/smoltcp/blob/master/examples/server.rs>
4use std::sync::{Arc, Mutex};
5
6use smoltcp::wire::EthernetAddress;
7use twizzler::error::TwzError;
8use twizzler_abi::syscall::{ObjectCreate, ThreadSync};
9use twizzler_driver::device::Device;
10use twizzler_net::{
11    drivers::{NetDriver, Packet, QueueHandle, WorkItems},
12    packet::PacketObject,
13};
14use virtio_drivers::{
15    device::net::{RxBuffer, TxBuffer, VirtIONet},
16    transport::Transport,
17};
18
19use crate::{hal::TwzHal, transport::TwizzlerTransport};
20
21const NET_QUEUE_SIZE: usize = 64;
22
23type DeviceImpl<T> = VirtIONet<TwzHal, T, NET_QUEUE_SIZE>;
24
25const NET_BUFFER_LEN: usize = 4096;
26
27pub struct DeviceWrapper<T: Transport> {
28    inner: Arc<Mutex<DeviceImpl<T>>>,
29    rx_po: PacketObject,
30    tx_po: PacketObject,
31    tt_device: Arc<twizzler_driver::device::Device>,
32}
33
34impl<T: Transport> Clone for DeviceWrapper<T> {
35    fn clone(&self) -> Self {
36        Self {
37            inner: self.inner.clone(),
38            rx_po: self.rx_po.clone(),
39            tx_po: self.tx_po.clone(),
40            tt_device: self.tt_device.clone(),
41        }
42    }
43}
44
45impl<T: Transport> DeviceWrapper<T> {
46    fn new(
47        dev: DeviceImpl<T>,
48        rx_po: PacketObject,
49        tt_device: Arc<twizzler_driver::device::Device>,
50    ) -> Self {
51        DeviceWrapper {
52            inner: Arc::new(Mutex::new(dev)),
53            rx_po,
54            tx_po: PacketObject::new(ObjectCreate::default(), NET_QUEUE_SIZE, NET_BUFFER_LEN)
55                .unwrap(),
56            tt_device,
57        }
58    }
59
60    pub fn mac_address(&self) -> EthernetAddress {
61        EthernetAddress(self.inner.lock().unwrap().mac_address())
62    }
63
64    pub fn has_work(&self) -> bool {
65        self.tt_device.repr().check_for_interrupt(0).is_some()
66    }
67
68    pub fn get_sleep(&self) -> ThreadSync {
69        ThreadSync::new_sleep(self.tt_device.repr().setup_interrupt_sleep(0))
70    }
71
72    pub fn get_rx(&self) -> Option<RxBuffer> {
73        self.inner.lock().unwrap().receive().ok()
74    }
75
76    pub fn recycle(&self, rx: RxBuffer) {
77        self.inner.lock().unwrap().recycle_rx_buffer(rx).unwrap();
78    }
79
80    pub fn transmit(&self, tx: TxBuffer) {
81        self.inner.lock().unwrap().send(tx).unwrap();
82    }
83}
84
85impl NetDriver for DeviceWrapper<TwizzlerTransport> {
86    fn device(&self) -> &Device {
87        todo!()
88    }
89
90    fn device_mut(&mut self) -> &mut Device {
91        todo!()
92    }
93
94    fn setup_rx_queue(&mut self, _len: usize) -> Result<QueueHandle, TwzError> {
95        todo!()
96    }
97
98    fn destroy_rx_queue(&mut self, _queue: QueueHandle) -> Result<(), TwzError> {
99        todo!()
100    }
101
102    fn setup_tx_queue(&mut self, _len: usize) -> Result<QueueHandle, TwzError> {
103        todo!()
104    }
105
106    fn destroy_tx_queue(&mut self, _queue: QueueHandle) -> Result<(), TwzError> {
107        todo!()
108    }
109
110    fn tx_queues(&self) -> Vec<QueueHandle> {
111        todo!()
112    }
113
114    fn rx_queues(&self) -> Vec<QueueHandle> {
115        todo!()
116    }
117
118    fn mac_address(&self, _queue: QueueHandle) -> Result<[u8; 6], TwzError> {
119        todo!()
120    }
121
122    fn recv_packets(
123        &mut self,
124        _queue: QueueHandle,
125        _packets: &mut [Packet],
126    ) -> Result<usize, TwzError> {
127        todo!()
128    }
129
130    fn send_packets(
131        &mut self,
132        _queue: QueueHandle,
133        _packets: &mut [Packet],
134    ) -> Result<usize, TwzError> {
135        todo!()
136    }
137
138    fn has_work(&self, _queue: QueueHandle) -> WorkItems {
139        todo!()
140    }
141
142    fn waitpoint(&self, _queue: QueueHandle) -> twizzler_abi::syscall::ThreadSync {
143        todo!()
144    }
145
146    fn rx_packet_buffer(&self, _queue: QueueHandle) -> &twizzler_net::drivers::DmaPacketObject {
147        todo!()
148    }
149
150    fn tx_packet_buffer(&self, _queue: QueueHandle) -> &twizzler_net::drivers::DmaPacketObject {
151        todo!()
152    }
153}
154/*
155impl<T: Transport> Device for DeviceWrapper<T> {
156    type RxToken<'a>
157        = VirtioRxToken<'a, T>
158    where
159        Self: 'a;
160    type TxToken<'a>
161        = VirtioTxToken<'a, T>
162    where
163        Self: 'a;
164
165    fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
166        match self.inner.lock().unwrap().receive() {
167            Ok(buf) => Some((VirtioRxToken(self, buf), VirtioTxToken(self))),
168            Err(Error::NotReady) => None,
169            Err(err) => panic!("receive failed: {}", err),
170        }
171    }
172
173    fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
174        Some(VirtioTxToken(self))
175    }
176
177    fn capabilities(&self) -> DeviceCapabilities {
178        let mut caps = DeviceCapabilities::default();
179        caps.max_transmission_unit = 1514;
180        caps.max_burst_size = Some(1);
181        caps.medium = Medium::Ethernet;
182        caps
183    }
184}
185
186pub struct VirtioRxToken<'a, T: Transport>(&'a DeviceWrapper<T>, RxBuffer);
187pub struct VirtioTxToken<'a, T: Transport>(&'a DeviceWrapper<T>);
188
189impl<'a, T: Transport> RxToken for VirtioRxToken<'a, T> {
190    fn consume<R, F>(self, f: F) -> R
191    where
192        F: FnOnce(&mut [u8]) -> R,
193    {
194        let mut rx_buf = self.1;
195        let result = f(rx_buf.packet_mut());
196        self.0
197            .inner
198            .lock()
199            .unwrap()
200            .recycle_rx_buffer(rx_buf)
201            .unwrap();
202        result
203    }
204}
205
206impl<'a, T: Transport> TxToken for VirtioTxToken<'a, T> {
207    fn consume<R, F>(self, len: usize, f: F) -> R
208    where
209        F: FnOnce(&mut [u8]) -> R,
210    {
211        let mut tx_buf = TxBuffer::new(self.0.tx_po.clone(), len);
212        let result = f(tx_buf.packet_mut());
213        let mut dev = self.0.inner.lock().unwrap();
214        dev.send(tx_buf).unwrap();
215        result
216    }
217}
218
219*/
220
221// Gets the Virtio Net struct which implements the device used for smoltcp. Use this to create a
222// smoltcp interface to send and receive packets. NOTE: Only the first device used will work
223// properly
224pub fn get_device() -> DeviceWrapper<TwizzlerTransport> {
225    let rx_po = PacketObject::new(ObjectCreate::default(), NET_QUEUE_SIZE, NET_BUFFER_LEN).unwrap();
226    let tt = TwizzlerTransport::new().unwrap();
227    let tt_device = tt.device();
228    let net = VirtIONet::<TwzHal, TwizzlerTransport, NET_QUEUE_SIZE>::new(
229        tt,
230        NET_BUFFER_LEN,
231        rx_po.clone(),
232    )
233    .expect("failed to create net driver");
234    DeviceWrapper::<TwizzlerTransport>::new(net, rx_po, tt_device)
235}