use std::{os::fd::RawFd, sync::Arc};
use msb_krun::backends::net::{NetBackend, ReadError, WriteError};
use crate::shared::SharedState;
const VIRTIO_NET_HDR_LEN: usize = 12;
pub struct SmoltcpBackend {
shared: Arc<SharedState>,
}
impl SmoltcpBackend {
pub fn new(shared: Arc<SharedState>) -> Self {
Self { shared }
}
}
impl NetBackend for SmoltcpBackend {
fn write_frame(&mut self, hdr_len: usize, buf: &mut [u8]) -> Result<(), WriteError> {
let ethernet_frame = buf[hdr_len..].to_vec();
self.shared.add_tx_bytes(ethernet_frame.len());
self.shared
.tx_ring
.push(ethernet_frame)
.map_err(|_| WriteError::NothingWritten)?;
self.shared.tx_wake.wake();
Ok(())
}
fn read_frame(&mut self, buf: &mut [u8]) -> Result<usize, ReadError> {
let frame = self.shared.rx_ring.pop().ok_or(ReadError::NothingRead)?;
let total_len = VIRTIO_NET_HDR_LEN + frame.len();
if total_len > buf.len() {
tracing::debug!(
frame_len = frame.len(),
buf_len = buf.len(),
"dropping oversized frame from rx_ring"
);
return Err(ReadError::NothingRead);
}
buf[..VIRTIO_NET_HDR_LEN].fill(0);
buf[VIRTIO_NET_HDR_LEN..total_len].copy_from_slice(&frame);
Ok(total_len)
}
fn has_unfinished_write(&self) -> bool {
false
}
fn try_finish_write(&mut self, _hdr_len: usize, _buf: &[u8]) -> Result<(), WriteError> {
Ok(())
}
fn raw_socket_fd(&self) -> RawFd {
self.shared.rx_wake.as_raw_fd()
}
}