Skip to content

Commit

Permalink
Introduce VirtIONetRaw to allow custom NIC buffer management and used…
Browse files Browse the repository at this point in the history
… buffer notification suppression (#111)

* Introduce `VirtIONetRaw` to allow custom NIC buffer management

* wip: add used buffer notification suppression but do not work

* feat: disable_interrupts by disable_dev_notify of both xmit_queue and recv_queue

* feat: rebase new-netdev to master and support netdev used buffer notification suppression

* fix: cargo fmt

* fix: workflow test bugs

* fix: combine enable_dev_notify and disable_dev_notify

* fix: delete transmit_wait

* feat: rebase to master

* fix: cargo fmt in examples

* feat: add RING_EVENT_IDX feature in net dev

* feat: modify can send, delete can_recv

* Implement can_recv in terms of poll_receive.

* Fix typos.

---------

Co-authored-by: Yuekai Jia <[email protected]>
Co-authored-by: Andrew Walbran <[email protected]>
  • Loading branch information
3 people authored Nov 14, 2023
1 parent 1be3d47 commit 3da64ea
Show file tree
Hide file tree
Showing 13 changed files with 760 additions and 467 deletions.
17 changes: 16 additions & 1 deletion examples/aarch64/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use virtio_drivers::{
blk::VirtIOBlk,
console::VirtIOConsole,
gpu::VirtIOGpu,
net::VirtIONetRaw,
socket::{
VirtIOSocket, VsockAddr, VsockConnectionManager, VsockEventType, VMADDR_CID_HOST,
},
Expand Down Expand Up @@ -137,7 +138,7 @@ fn virtio_device(transport: impl Transport) {
match transport.device_type() {
DeviceType::Block => virtio_blk(transport),
DeviceType::GPU => virtio_gpu(transport),
// DeviceType::Network => virtio_net(transport), // currently is unsupported without alloc
DeviceType::Network => virtio_net(transport),
DeviceType::Console => virtio_console(transport),
DeviceType::Socket => match virtio_socket(transport) {
Ok(()) => info!("virtio-socket test finished successfully"),
Expand Down Expand Up @@ -192,6 +193,20 @@ fn virtio_gpu<T: Transport>(transport: T) {
info!("virtio-gpu test finished");
}

fn virtio_net<T: Transport>(transport: T) {
let mut net =
VirtIONetRaw::<HalImpl, T, 16>::new(transport).expect("failed to create net driver");
let mut buf = [0u8; 2048];
let (hdr_len, pkt_len) = net.receive_wait(&mut buf).expect("failed to recv");
info!(
"recv {} bytes: {:02x?}",
pkt_len,
&buf[hdr_len..hdr_len + pkt_len]
);
net.send(&buf[..hdr_len + pkt_len]).expect("failed to send");
info!("virtio-net test finished");
}

fn virtio_console<T: Transport>(transport: T) {
let mut console =
VirtIOConsole::<HalImpl, T>::new(transport).expect("Failed to create console driver");
Expand Down
45 changes: 24 additions & 21 deletions examples/riscv/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use core::ptr::NonNull;
use fdt::{node::FdtNode, standard_nodes::Compatible, Fdt};
use log::LevelFilter;
use virtio_drivers::{
device::{blk::VirtIOBlk, gpu::VirtIOGpu, input::VirtIOInput, net::VirtIONet},
device::{blk::VirtIOBlk, gpu::VirtIOGpu, input::VirtIOInput},
transport::{
mmio::{MmioTransport, VirtIOHeader},
DeviceType, Transport,
Expand All @@ -26,7 +26,6 @@ mod virtio_impl;
#[cfg(feature = "tcp")]
mod tcp;

const NET_BUFFER_LEN: usize = 2048;
const NET_QUEUE_SIZE: usize = 16;

#[no_mangle]
Expand Down Expand Up @@ -146,29 +145,33 @@ fn virtio_input<T: Transport>(transport: T) {
}

fn virtio_net<T: Transport>(transport: T) {
let net = VirtIONet::<HalImpl, T, NET_QUEUE_SIZE>::new(transport, NET_BUFFER_LEN)
.expect("failed to create net driver");
info!("MAC address: {:02x?}", net.mac_address());

#[cfg(not(feature = "tcp"))]
{
let mut net = net;
loop {
match net.receive() {
Ok(buf) => {
info!("RECV {} bytes: {:02x?}", buf.packet_len(), buf.packet());
let tx_buf = virtio_drivers::device::net::TxBuffer::from(buf.packet());
net.send(tx_buf).expect("failed to send");
net.recycle_rx_buffer(buf).unwrap();
break;
}
Err(virtio_drivers::Error::NotReady) => continue,
Err(err) => panic!("failed to recv: {:?}", err),
}
}
let mut net =
virtio_drivers::device::net::VirtIONetRaw::<HalImpl, T, NET_QUEUE_SIZE>::new(transport)
.expect("failed to create net driver");
info!("MAC address: {:02x?}", net.mac_address());

let mut buf = [0u8; 2048];
let (hdr_len, pkt_len) = net.receive_wait(&mut buf).expect("failed to recv");
info!(
"recv {} bytes: {:02x?}",
pkt_len,
&buf[hdr_len..hdr_len + pkt_len]
);
net.send(&buf[..hdr_len + pkt_len]).expect("failed to send");
info!("virtio-net test finished");
}

#[cfg(feature = "tcp")]
tcp::test_echo_server(net);
{
const NET_BUFFER_LEN: usize = 2048;
let net = virtio_drivers::device::net::VirtIONet::<HalImpl, T, NET_QUEUE_SIZE>::new(
transport,
NET_BUFFER_LEN,
)
.expect("failed to create net driver");
info!("MAC address: {:02x?}", net.mac_address());
tcp::test_echo_server(net);
}
}
4 changes: 2 additions & 2 deletions examples/riscv/src/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use smoltcp::iface::{Config, Interface, SocketSet};
use smoltcp::phy::{Device, DeviceCapabilities, Medium, RxToken, TxToken};
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use smoltcp::{socket::tcp, time::Instant};
use virtio_drivers::device::net::{RxBuffer, VirtIONet};
use virtio_drivers::device::net::{NetBuffer, VirtIONet};
use virtio_drivers::{transport::Transport, Error};

use super::{HalImpl, NET_QUEUE_SIZE};
Expand Down Expand Up @@ -64,7 +64,7 @@ impl<T: Transport> Device for DeviceWrapper<T> {
}
}

struct VirtioRxToken<T: Transport>(Rc<RefCell<DeviceImpl<T>>>, RxBuffer);
struct VirtioRxToken<T: Transport>(Rc<RefCell<DeviceImpl<T>>>, NetBuffer);
struct VirtioTxToken<T: Transport>(Rc<RefCell<DeviceImpl<T>>>);

impl<T: Transport> RxToken for VirtioRxToken<T> {
Expand Down
7 changes: 1 addition & 6 deletions examples/x86_64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ target := x86_64-unknown-none
mode := release
kernel := target/$(target)/$(mode)/$(arch)
img := target/$(target)/$(mode)/img
accel := on
accel ?= on
tcp ?= off

sysroot := $(shell rustc --print sysroot)
Expand All @@ -20,11 +20,6 @@ else
BUILD_ARGS += --no-default-features
endif

VSOCK_BUILD_ARGS =
ifeq ($(mode), release)
VSOCK_BUILD_ARGS += --release
endif

QEMU_ARGS += \
-machine q35 \
-serial mon:stdio \
Expand Down
45 changes: 24 additions & 21 deletions examples/x86_64/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod tcp;

use self::hal::HalImpl;
use virtio_drivers::{
device::{blk::VirtIOBlk, gpu::VirtIOGpu, net::VirtIONet},
device::{blk::VirtIOBlk, gpu::VirtIOGpu},
transport::{
pci::{
bus::{BarInfo, Cam, Command, DeviceFunction, PciRoot},
Expand All @@ -35,7 +35,6 @@ use virtio_drivers::{
/// TODO: get it from ACPI MCFG table.
const MMCONFIG_BASE: usize = 0xB000_0000;

const NET_BUFFER_LEN: usize = 2048;
const NET_QUEUE_SIZE: usize = 16;

fn system_off() -> ! {
Expand Down Expand Up @@ -117,31 +116,35 @@ fn virtio_gpu<T: Transport>(transport: T) {
}

fn virtio_net<T: Transport>(transport: T) {
let net = VirtIONet::<HalImpl, T, NET_QUEUE_SIZE>::new(transport, NET_BUFFER_LEN)
.expect("failed to create net driver");
info!("MAC address: {:02x?}", net.mac_address());

#[cfg(not(feature = "tcp"))]
{
let mut net = net;
loop {
match net.receive() {
Ok(buf) => {
info!("RECV {} bytes: {:02x?}", buf.packet_len(), buf.packet());
let tx_buf = virtio_drivers::device::net::TxBuffer::from(buf.packet());
net.send(tx_buf).expect("failed to send");
net.recycle_rx_buffer(buf).unwrap();
break;
}
Err(virtio_drivers::Error::NotReady) => continue,
Err(err) => panic!("failed to recv: {:?}", err),
}
}
let mut net =
virtio_drivers::device::net::VirtIONetRaw::<HalImpl, T, NET_QUEUE_SIZE>::new(transport)
.expect("failed to create net driver");
info!("MAC address: {:02x?}", net.mac_address());

let mut buf = [0u8; 2048];
let (hdr_len, pkt_len) = net.receive_wait(&mut buf).expect("failed to recv");
info!(
"recv {} bytes: {:02x?}",
pkt_len,
&buf[hdr_len..hdr_len + pkt_len]
);
net.send(&buf[..hdr_len + pkt_len]).expect("failed to send");
info!("virtio-net test finished");
}

#[cfg(feature = "tcp")]
tcp::test_echo_server(net);
{
const NET_BUFFER_LEN: usize = 2048;
let net = virtio_drivers::device::net::VirtIONet::<HalImpl, T, NET_QUEUE_SIZE>::new(
transport,
NET_BUFFER_LEN,
)
.expect("failed to create net driver");
info!("MAC address: {:02x?}", net.mac_address());
tcp::test_echo_server(net);
}
}

fn enumerate_pci(mmconfig_base: *mut u8) {
Expand Down
4 changes: 2 additions & 2 deletions examples/x86_64/src/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Simple echo server over TCP.
//!
//! Ref: https://github.com/smoltcp-rs/smoltcp/blob/master/examples/server.rs
//! Ref: <https://github.com/smoltcp-rs/smoltcp/blob/master/examples/server.rs>
use alloc::{borrow::ToOwned, rc::Rc, vec, vec::Vec};
use core::{cell::RefCell, str::FromStr};
Expand Down Expand Up @@ -93,7 +93,7 @@ impl<T: Transport> TxToken for VirtioTxToken<T> {
let mut tx_buf = dev.new_tx_buffer(len);
let result = f(tx_buf.packet_mut());
trace!("SEND {} bytes: {:02X?}", len, tx_buf.packet());
dev.send(tx_buf).unwrap();
dev.transmit(tx_buf).unwrap();
result
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ pub mod console;
pub mod gpu;
#[cfg(feature = "alloc")]
pub mod input;
#[cfg(feature = "alloc")]

pub mod net;

pub mod socket;

pub(crate) mod common;
Loading

0 comments on commit 3da64ea

Please sign in to comment.