Skip to content

Commit

Permalink
Merge pull request #1053 from cagatay-y/virtqueue-trait
Browse files Browse the repository at this point in the history
Use a trait for the common Virtq interface
  • Loading branch information
mkroening authored Feb 29, 2024
2 parents 1d9d19c + a0c1b5a commit 044713e
Show file tree
Hide file tree
Showing 7 changed files with 1,312 additions and 2,397 deletions.
15 changes: 7 additions & 8 deletions src/drivers/fs/virtio_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use crate::drivers::virtio::error::VirtioFsError;
use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
#[cfg(feature = "pci")]
use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg};
use crate::drivers::virtio::virtqueue::split::SplitVq;
use crate::drivers::virtio::virtqueue::{
AsSliceU8, BuffSpec, BufferToken, Bytes, Virtq, VqIndex, VqSize, VqType,
AsSliceU8, BuffSpec, BufferToken, Bytes, Virtq, VqIndex, VqSize,
};
use crate::fs::fuse::{self, FuseInterface};

Expand All @@ -37,7 +38,7 @@ pub(crate) struct VirtioFsDriver {
pub(super) com_cfg: ComCfg,
pub(super) isr_stat: IsrStatus,
pub(super) notif_cfg: NotifCfg,
pub(super) vqueues: Vec<Rc<Virtq>>,
pub(super) vqueues: Vec<Rc<dyn Virtq>>,
pub(super) ready_queue: Vec<BufferToken>,
pub(super) irq: InterruptLine,
}
Expand Down Expand Up @@ -126,23 +127,21 @@ impl VirtioFsDriver {

// create the queues and tell device about them
for i in 0..vqnum as u16 {
let vq = Virtq::new(
let vq = SplitVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Split,
VqIndex::from(i),
self.dev_cfg.features.into(),
);
)
.unwrap();
self.vqueues.push(Rc::new(vq));
}

let cmd_spec = Some(BuffSpec::Single(Bytes::new(64 * 1024 + 128).unwrap()));
let rsp_spec = Some(BuffSpec::Single(Bytes::new(64 * 1024 + 128).unwrap()));

if let Ok(buff_tkn) =
self.vqueues[1].prep_buffer(Rc::clone(&self.vqueues[1]), cmd_spec, rsp_spec)
{
if let Ok(buff_tkn) = self.vqueues[1].clone().prep_buffer(cmd_spec, rsp_spec) {
self.ready_queue.push(buff_tkn);
// At this point the device is "live"
self.com_cfg.drv_ok();
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/net/virtio_mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ impl VirtioNetDriver {
notif_cfg,
ctrl_vq: CtrlQueue::new(None),
recv_vqs: RxQueues::new(
Vec::<Rc<Virtq>>::new(),
Vec::<Rc<dyn Virtq>>::new(),
Rc::new(RefCell::new(VecDeque::new())),
false,
),
send_vqs: TxQueues::new(
Vec::<Rc<Virtq>>::new(),
Vec::<Rc<dyn Virtq>>::new(),
Rc::new(RefCell::new(VecDeque::new())),
Vec::new(),
false,
Expand Down
105 changes: 55 additions & 50 deletions src/drivers/net/virtio_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ use crate::drivers::net::NetworkDriver;
use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
#[cfg(feature = "pci")]
use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg};
use crate::drivers::virtio::virtqueue::packed::PackedVq;
use crate::drivers::virtio::virtqueue::split::SplitVq;
use crate::drivers::virtio::virtqueue::{
BuffSpec, BufferToken, Bytes, Transfer, Virtq, VqIndex, VqSize, VqType,
BuffSpec, BufferToken, Bytes, Transfer, Virtq, VqIndex, VqSize,
};
use crate::executor::device::{RxToken, TxToken};

Expand Down Expand Up @@ -77,10 +79,10 @@ impl Default for VirtioNetHdr {
}
}

pub struct CtrlQueue(Option<Rc<Virtq>>);
pub struct CtrlQueue(Option<Rc<dyn Virtq>>);

impl CtrlQueue {
pub fn new(vq: Option<Rc<Virtq>>) -> Self {
pub fn new(vq: Option<Rc<dyn Virtq>>) -> Self {
CtrlQueue(vq)
}
}
Expand Down Expand Up @@ -153,14 +155,14 @@ enum MqCmd {
}

pub struct RxQueues {
vqs: Vec<Rc<Virtq>>,
vqs: Vec<Rc<dyn Virtq>>,
poll_queue: Rc<RefCell<VecDeque<Transfer>>>,
is_multi: bool,
}

impl RxQueues {
pub fn new(
vqs: Vec<Rc<Virtq>>,
vqs: Vec<Rc<dyn Virtq>>,
poll_queue: Rc<RefCell<VecDeque<Transfer>>>,
is_multi: bool,
) -> Self {
Expand Down Expand Up @@ -188,10 +190,7 @@ impl RxQueues {
/// Adds a given queue to the underlying vector and populates the queue with RecvBuffers.
///
/// Queues are all populated according to Virtio specification v1.1. - 5.1.6.3.1
fn add(&mut self, vq: Virtq, dev_cfg: &NetDevCfg) {
// Safe virtqueue
let rc_vq = Rc::new(vq);
let vq = &rc_vq;
fn add(&mut self, vq: Rc<dyn Virtq>, dev_cfg: &NetDevCfg) {
let num_buff: u16 = vq.size().into();

let rx_size = if dev_cfg
Expand All @@ -208,7 +207,7 @@ impl RxQueues {
//
let spec = BuffSpec::Single(Bytes::new(rx_size).unwrap());
for _ in 0..num_buff {
let buff_tkn = match vq.prep_buffer(Rc::clone(vq), None, Some(spec.clone())) {
let buff_tkn = match vq.clone().prep_buffer(None, Some(spec.clone())) {
Ok(tkn) => tkn,
Err(_vq_err) => {
error!("Setup of network queue failed, which should not happen!");
Expand All @@ -225,7 +224,7 @@ impl RxQueues {
}

// Safe virtqueue
self.vqs.push(rc_vq);
self.vqs.push(vq);

if self.vqs.len() > 1 {
self.is_multi = true;
Expand Down Expand Up @@ -277,7 +276,7 @@ impl RxQueues {
/// Structure which handles transmission of packets and delegation
/// to the respective queue structures.
pub struct TxQueues {
vqs: Vec<Rc<Virtq>>,
vqs: Vec<Rc<dyn Virtq>>,
poll_queue: Rc<RefCell<VecDeque<Transfer>>>,
ready_queue: Vec<BufferToken>,
/// Indicates, whether the Driver/Device are using multiple
Expand All @@ -287,7 +286,7 @@ pub struct TxQueues {

impl TxQueues {
pub fn new(
vqs: Vec<Rc<Virtq>>,
vqs: Vec<Rc<dyn Virtq>>,
poll_queue: Rc<RefCell<VecDeque<Transfer>>>,
ready_queue: Vec<BufferToken>,
is_multi: bool,
Expand Down Expand Up @@ -331,9 +330,9 @@ impl TxQueues {
}
}

fn add(&mut self, vq: Virtq, dev_cfg: &NetDevCfg) {
fn add(&mut self, vq: Rc<dyn Virtq>, dev_cfg: &NetDevCfg) {
// Safe virtqueue
self.vqs.push(Rc::new(vq));
self.vqs.push(vq.clone());
if self.vqs.len() == 1 {
// Unwrapping is safe, as one virtq will be definitely in the vector.
let vq = self.vqs.first().unwrap();
Expand All @@ -359,7 +358,8 @@ impl TxQueues {

for _ in 0..num_buff {
self.ready_queue.push(
vq.prep_buffer(Rc::clone(vq), Some(spec.clone()), None)
vq.clone()
.prep_buffer(Some(spec.clone()), None)
.unwrap()
.write_seq(Some(&VirtioNetHdr::default()), None::<&VirtioNetHdr>)
.unwrap(),
Expand All @@ -379,7 +379,8 @@ impl TxQueues {

for _ in 0..num_buff {
self.ready_queue.push(
vq.prep_buffer(Rc::clone(vq), Some(spec.clone()), None)
vq.clone()
.prep_buffer(Some(spec.clone()), None)
.unwrap()
.write_seq(Some(&VirtioNetHdr::default()), None::<&VirtioNetHdr>)
.unwrap(),
Expand Down Expand Up @@ -436,7 +437,7 @@ impl TxQueues {
// As usize is currently safe as the minimal usize is defined as 16bit in rust.
let spec = BuffSpec::Single(Bytes::new(len).unwrap());

match self.vqs[0].prep_buffer(Rc::clone(&self.vqs[0]), Some(spec), None) {
match self.vqs[0].clone().prep_buffer(Some(spec), None) {
Ok(tkn) => Some((tkn, 0)),
Err(_) => {
// Here it is possible if multiple queues are enabled to get another buffertoken from them!
Expand Down Expand Up @@ -975,23 +976,27 @@ impl VirtioNetDriver {
.features
.is_feature(Features::VIRTIO_F_RING_PACKED)
{
self.ctrl_vq = CtrlQueue(Some(Rc::new(Virtq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Packed,
VqIndex::from(self.num_vqs),
self.dev_cfg.features.into(),
))));
self.ctrl_vq = CtrlQueue(Some(Rc::new(
PackedVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqIndex::from(self.num_vqs),
self.dev_cfg.features.into(),
)
.unwrap(),
)));
} else {
self.ctrl_vq = CtrlQueue(Some(Rc::new(Virtq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Split,
VqIndex::from(self.num_vqs),
self.dev_cfg.features.into(),
))));
self.ctrl_vq = CtrlQueue(Some(Rc::new(
SplitVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqIndex::from(self.num_vqs),
self.dev_cfg.features.into(),
)
.unwrap(),
)));
}

self.ctrl_vq.0.as_ref().unwrap().enable_notifs();
Expand Down Expand Up @@ -1038,57 +1043,57 @@ impl VirtioNetDriver {
.features
.is_feature(Features::VIRTIO_F_RING_PACKED)
{
let vq = Virtq::new(
let vq = PackedVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Packed,
VqIndex::from(2 * i),
self.dev_cfg.features.into(),
);
)
.unwrap();
// Interrupt for receiving packets is wanted
vq.enable_notifs();

self.recv_vqs.add(vq, &self.dev_cfg);
self.recv_vqs.add(Rc::from(vq), &self.dev_cfg);

let vq = Virtq::new(
let vq = PackedVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Packed,
VqIndex::from(2 * i + 1),
self.dev_cfg.features.into(),
);
)
.unwrap();
// Interrupt for comunicating that a sended packet left, is not needed
vq.disable_notifs();

self.send_vqs.add(vq, &self.dev_cfg);
self.send_vqs.add(Rc::from(vq), &self.dev_cfg);
} else {
let vq = Virtq::new(
let vq = SplitVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Split,
VqIndex::from(2 * i),
self.dev_cfg.features.into(),
);
)
.unwrap();
// Interrupt for receiving packets is wanted
vq.enable_notifs();

self.recv_vqs.add(vq, &self.dev_cfg);
self.recv_vqs.add(Rc::from(vq), &self.dev_cfg);

let vq = Virtq::new(
let vq = SplitVq::new(
&mut self.com_cfg,
&self.notif_cfg,
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
VqType::Split,
VqIndex::from(2 * i + 1),
self.dev_cfg.features.into(),
);
)
.unwrap();
// Interrupt for comunicating that a sended packet left, is not needed
vq.disable_notifs();

self.send_vqs.add(vq, &self.dev_cfg);
self.send_vqs.add(Rc::from(vq), &self.dev_cfg);
}
}

Expand Down
9 changes: 2 additions & 7 deletions src/drivers/net/virtio_pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::drivers::pci::{PciCommand, PciDevice};
use crate::drivers::virtio::error::{self, VirtioError};
use crate::drivers::virtio::transport::pci;
use crate::drivers::virtio::transport::pci::{PciCap, UniCapsColl};
use crate::drivers::virtio::virtqueue::Virtq;

/// Virtio's network device configuration structure.
/// See specification v1.1. - 5.1.4
Expand Down Expand Up @@ -147,13 +146,9 @@ impl VirtioNetDriver {
notif_cfg,

ctrl_vq: CtrlQueue::new(None),
recv_vqs: RxQueues::new(
Vec::<Rc<Virtq>>::new(),
Rc::new(RefCell::new(VecDeque::new())),
false,
),
recv_vqs: RxQueues::new(Vec::new(), Rc::new(RefCell::new(VecDeque::new())), false),
send_vqs: TxQueues::new(
Vec::<Rc<Virtq>>::new(),
Vec::new(),
Rc::new(RefCell::new(VecDeque::new())),
Vec::new(),
false,
Expand Down
Loading

0 comments on commit 044713e

Please sign in to comment.