mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2025-12-26 06:32:44 +00:00
vhost-device-console: Being able to specify max queue size
Some hypervisors, e.g. UML, negotiate a queue size larger than `QUEUE_SIZE` (128), which results in failures. This patch allows users to specify it using `--max-queue-size <size>`. Signed-off-by: Xuewei Niu <niuxuewei.nxw@antgroup.com>
This commit is contained in:
parent
bc07d3ef7a
commit
04c30f700a
@ -3,6 +3,8 @@
|
||||
|
||||
### Added
|
||||
|
||||
- [#811](https://github.com/rust-vmm/vhost-device/pull/811) Being able to specify max queue size
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -47,6 +47,11 @@ vhost-device-console --socket-path=<SOCKET_PATH>
|
||||
Note: The nested backend is selected by default and can be used only when
|
||||
socket_count equals 1.
|
||||
|
||||
.. option:: -q, --max-queue-size=SIZE
|
||||
|
||||
The maximum size of virtqueues. It is optional, and the default value is
|
||||
128. The size must be greater than 0 and a power of 2.
|
||||
|
||||
## Limitations
|
||||
|
||||
This device is still work-in-progress (WIP). The current version has been tested
|
||||
|
||||
@ -50,6 +50,7 @@ pub struct VuConsoleConfig {
|
||||
pub backend: BackendType,
|
||||
pub tcp_port: String,
|
||||
pub socket_count: u32,
|
||||
pub max_queue_size: usize,
|
||||
}
|
||||
|
||||
impl VuConsoleConfig {
|
||||
@ -86,12 +87,18 @@ impl VuConsoleConfig {
|
||||
|
||||
/// This is the public API through which an external program starts the
|
||||
/// vhost-device-console backend server.
|
||||
pub fn start_backend_server(socket: PathBuf, tcp_addr: String, backend: BackendType) -> Result<()> {
|
||||
pub fn start_backend_server(
|
||||
socket: PathBuf,
|
||||
tcp_addr: String,
|
||||
backend: BackendType,
|
||||
max_queue_size: usize,
|
||||
) -> Result<()> {
|
||||
loop {
|
||||
let controller = ConsoleController::new(backend);
|
||||
let arc_controller = Arc::new(RwLock::new(controller));
|
||||
let vu_console_backend = Arc::new(RwLock::new(
|
||||
VhostUserConsoleBackend::new(arc_controller).map_err(Error::CouldNotCreateBackend)?,
|
||||
VhostUserConsoleBackend::new(max_queue_size, arc_controller)
|
||||
.map_err(Error::CouldNotCreateBackend)?,
|
||||
));
|
||||
|
||||
vu_console_backend
|
||||
@ -127,6 +134,7 @@ pub fn start_backend(config: VuConsoleConfig) -> Result<()> {
|
||||
let (senders, receiver) = std::sync::mpsc::channel();
|
||||
let tcp_addrs = config.generate_tcp_addrs();
|
||||
let backend = config.backend;
|
||||
let max_queue_size = config.max_queue_size;
|
||||
|
||||
for (thread_id, (socket, tcp_addr)) in config
|
||||
.generate_socket_paths()
|
||||
@ -143,7 +151,7 @@ pub fn start_backend(config: VuConsoleConfig) -> Result<()> {
|
||||
.name(name.clone())
|
||||
.spawn(move || {
|
||||
let result = std::panic::catch_unwind(move || {
|
||||
start_backend_server(socket, tcp_addr.to_string(), backend)
|
||||
start_backend_server(socket, tcp_addr.to_string(), backend, max_queue_size)
|
||||
});
|
||||
|
||||
// Notify the main thread that we are done.
|
||||
@ -173,7 +181,7 @@ mod tests {
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
use super::*;
|
||||
use crate::ConsoleArgs;
|
||||
use crate::{ConsoleArgs, DEFAULT_QUEUE_SIZE};
|
||||
|
||||
#[test]
|
||||
fn test_console_valid_configuration_nested() {
|
||||
@ -182,6 +190,7 @@ mod tests {
|
||||
backend: BackendType::Nested,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 1,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
VuConsoleConfig::try_from(args).unwrap();
|
||||
@ -194,6 +203,7 @@ mod tests {
|
||||
backend: BackendType::Nested,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 0,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
assert_matches!(
|
||||
@ -209,6 +219,7 @@ mod tests {
|
||||
backend: BackendType::Nested,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 2,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
assert_matches!(
|
||||
@ -224,6 +235,7 @@ mod tests {
|
||||
backend: BackendType::Network,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 1,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
VuConsoleConfig::try_from(args).unwrap();
|
||||
@ -236,6 +248,7 @@ mod tests {
|
||||
backend: BackendType::Network,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 2,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
VuConsoleConfig::try_from(args).unwrap();
|
||||
@ -246,13 +259,14 @@ mod tests {
|
||||
|
||||
let tcp_addrs = config.generate_tcp_addrs();
|
||||
let backend = config.backend;
|
||||
let max_queue_size = config.max_queue_size;
|
||||
|
||||
for (socket, tcp_addr) in config
|
||||
.generate_socket_paths()
|
||||
.into_iter()
|
||||
.zip(tcp_addrs.iter())
|
||||
{
|
||||
start_backend_server(socket, tcp_addr.to_string(), backend)?;
|
||||
start_backend_server(socket, tcp_addr.to_string(), backend, max_queue_size)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -264,6 +278,7 @@ mod tests {
|
||||
backend: BackendType::Network,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 1,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
assert!(test_backend_start_and_stop(args).is_err());
|
||||
@ -276,6 +291,7 @@ mod tests {
|
||||
backend: BackendType::Network,
|
||||
tcp_port: String::from("12346"),
|
||||
socket_count: 1,
|
||||
max_queue_size: DEFAULT_QUEUE_SIZE,
|
||||
};
|
||||
|
||||
assert!(start_backend(config).is_err());
|
||||
|
||||
@ -44,6 +44,8 @@ use crate::console::BackendType;
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
use crate::backend::{start_backend, Error, VuConsoleConfig};
|
||||
|
||||
const DEFAULT_QUEUE_SIZE: usize = 128;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct ConsoleArgs {
|
||||
@ -65,6 +67,10 @@ struct ConsoleArgs {
|
||||
/// `tcp_port + 1`, ... , `tcp_port + (N - 1)`.
|
||||
#[clap(short = 'p', long, value_name = "PORT", default_value = "12345")]
|
||||
tcp_port: String,
|
||||
|
||||
/// Specify the maximum size of virtqueue, the default is 128.
|
||||
#[clap(short = 'q', long, default_value_t = DEFAULT_QUEUE_SIZE)]
|
||||
max_queue_size: usize,
|
||||
}
|
||||
|
||||
impl TryFrom<ConsoleArgs> for VuConsoleConfig {
|
||||
@ -84,6 +90,7 @@ impl TryFrom<ConsoleArgs> for VuConsoleConfig {
|
||||
backend,
|
||||
tcp_port,
|
||||
socket_count,
|
||||
max_queue_size,
|
||||
} = args;
|
||||
|
||||
Ok(Self {
|
||||
@ -91,6 +98,7 @@ impl TryFrom<ConsoleArgs> for VuConsoleConfig {
|
||||
backend,
|
||||
tcp_port,
|
||||
socket_count,
|
||||
max_queue_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,6 +124,7 @@ impl<T: Read + Write> ReadWrite for T {}
|
||||
unsafe impl ByteValued for VirtioConsoleControl {}
|
||||
|
||||
pub struct VhostUserConsoleBackend {
|
||||
max_queue_size: usize,
|
||||
controller: Arc<RwLock<ConsoleController>>,
|
||||
acked_features: u64,
|
||||
event_idx: bool,
|
||||
@ -147,11 +148,11 @@ type ConsoleDescriptorChain = DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMm
|
||||
|
||||
impl VhostUserConsoleBackend {
|
||||
// Virtio configuration
|
||||
pub const QUEUE_SIZE: usize = 128;
|
||||
pub const NUM_QUEUES: u16 = 4;
|
||||
|
||||
pub fn new(controller: Arc<RwLock<ConsoleController>>) -> Result<Self> {
|
||||
pub fn new(max_queue_size: usize, controller: Arc<RwLock<ConsoleController>>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
max_queue_size,
|
||||
controller,
|
||||
event_idx: false,
|
||||
rx_ctrl_fifo: Queue::new(),
|
||||
@ -698,7 +699,7 @@ impl VhostUserBackendMut for VhostUserConsoleBackend {
|
||||
}
|
||||
|
||||
fn max_queue_size(&self) -> usize {
|
||||
Self::QUEUE_SIZE
|
||||
self.max_queue_size
|
||||
}
|
||||
|
||||
fn features(&self) -> u64 {
|
||||
@ -863,12 +864,14 @@ mod tests {
|
||||
use vm_memory::{Bytes, GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};
|
||||
|
||||
use super::*;
|
||||
use crate::DEFAULT_QUEUE_SIZE;
|
||||
|
||||
#[test]
|
||||
fn test_vhost_user_console_backend_creation() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let vhost_user_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let vhost_user_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
assert_eq!(vhost_user_console_backend.acked_features, 0);
|
||||
assert!(!vhost_user_console_backend.event_idx);
|
||||
@ -879,8 +882,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_empty_handle_request() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryAtomic::new(
|
||||
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap(),
|
||||
@ -926,8 +930,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_empty_requests() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryAtomic::new(
|
||||
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap(),
|
||||
@ -985,8 +990,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_ctrl_rx_request() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
@ -1059,8 +1065,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_ctrl_tx_request() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
@ -1109,8 +1116,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_handle_control_msg() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem_1 = GuestMemoryAtomic::new(mem.clone());
|
||||
@ -1162,8 +1170,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_tx_request() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
@ -1217,8 +1226,9 @@ mod tests {
|
||||
fn test_virtio_console_tx_request_network() {
|
||||
let console_controller =
|
||||
Arc::new(RwLock::new(ConsoleController::new(BackendType::Network)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let desc_chain = build_desc_chain(&mem, 1, vec![0], 0x200);
|
||||
@ -1258,8 +1268,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_rx_request() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
@ -1331,8 +1342,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_virtio_console_start_nested_console_thread() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem = GuestMemoryAtomic::new(mem);
|
||||
@ -1360,8 +1372,9 @@ mod tests {
|
||||
fn test_virtio_console_tcp_console_read_func() {
|
||||
let console_controller =
|
||||
Arc::new(RwLock::new(ConsoleController::new(BackendType::Network)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem = GuestMemoryAtomic::new(mem);
|
||||
@ -1389,8 +1402,9 @@ mod tests {
|
||||
fn test_virtio_console_tcp_console_write_func() {
|
||||
let console_controller =
|
||||
Arc::new(RwLock::new(ConsoleController::new(BackendType::Network)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
let mut vu_console_backend =
|
||||
VhostUserConsoleBackend::new(DEFAULT_QUEUE_SIZE, console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem = GuestMemoryAtomic::new(mem);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user