vhost_user: Support sending msg larger than MAX_MSG_SIZE

Introduce another constant MAX_MSG_SIZE that is part of the MsgHeader
trait. For now this is only used for sending messages.
Consider using the more specific trait constant everywhere.

The VHOST_USER_GPU_UPDATE and VHOST_USER_GPU_CURSOR_UPDATE contain image
data and are larger than the existing MAX_MSG_SIZE.

The existing MAX_MSG_SIZE wasn't really a limitation of the protocol,
just an implementation detail limitation in this crate.

Signed-off-by: Matej Hrica <mhrica@redhat.com>
This commit is contained in:
Matej Hrica 2024-05-14 16:49:14 +02:00 committed by Sergio López
parent 9b24090faf
commit ab0c088bb6
3 changed files with 17 additions and 3 deletions

View file

@ -226,7 +226,7 @@ impl<H: MsgHeader> Endpoint<H> {
body: &T,
fds: Option<&[RawFd]>,
) -> Result<()> {
if mem::size_of::<T>() > MAX_MSG_SIZE {
if mem::size_of::<T>() > H::MAX_MSG_SIZE {
return Err(Error::OversizedMsg);
}
let bytes = self.send_iovec_all(&[hdr.as_slice(), body.as_slice()], fds)?;
@ -255,10 +255,10 @@ impl<H: MsgHeader> Endpoint<H> {
fds: Option<&[RawFd]>,
) -> Result<()> {
let len = payload.len();
if mem::size_of::<T>() > MAX_MSG_SIZE {
if mem::size_of::<T>() > H::MAX_MSG_SIZE {
return Err(Error::OversizedMsg);
}
if len > MAX_MSG_SIZE - mem::size_of::<T>() {
if len > H::MAX_MSG_SIZE - mem::size_of::<T>() {
return Err(Error::OversizedMsg);
}
if let Some(fd_arr) = fds {

View file

@ -168,4 +168,5 @@ impl<T: Req> VhostUserMsgValidator for VhostUserGpuMsgHeader<T> {
impl<R: Req> MsgHeader for VhostUserGpuMsgHeader<R> {
type Request = R;
const MAX_MSG_SIZE: usize = u32::MAX as usize;
}

View file

@ -25,6 +25,15 @@ use vm_memory::{GuestAddress, MmapRange, MmapXenFlags};
use super::{enum_value, Error, Result};
use crate::VringConfigData;
/*
TODO: Consider deprecating this. We don't actually have any preallocated buffers except in tests,
so we should be able to support u32::MAX normally.
Also this doesn't need to be public api, since Endpoint is private anyway, this doesn't seem
useful for consumers of this crate.
There are GPU specific messages (GpuBackendReq::UPDATE and CURSOR_UPDATE) that are larger than 4K.
We can use MsgHeader::MAX_MSG_SIZE, if we want to support larger messages only for GPU headers.
*/
/// The vhost-user specification uses a field of u32 to store message length.
/// On the other hand, preallocated buffers are needed to receive messages from the Unix domain
/// socket. To preallocating a 4GB buffer for each vhost-user message is really just an overhead.
@ -58,6 +67,9 @@ pub(super) trait Req:
pub(super) trait MsgHeader: ByteValued + Copy + Default + VhostUserMsgValidator {
type Request: Req;
/// The maximum size of a msg that can be encapsulated by this MsgHeader
const MAX_MSG_SIZE: usize;
}
enum_value! {
@ -228,6 +240,7 @@ pub(super) struct VhostUserMsgHeader<R: Req> {
impl<R: Req> MsgHeader for VhostUserMsgHeader<R> {
type Request = R;
const MAX_MSG_SIZE: usize = MAX_MSG_SIZE;
}
impl<R: Req> Debug for VhostUserMsgHeader<R> {