mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-22 04:25:21 +00:00
vhost_rs: add config messge support
The previous definitions does not cover config space read/write
and only cover general message as below:
A vhost-user message consists of 3 header fields and a payload.
+---------+-------+------+---------+
| request | flags | size | payload |
+---------+-------+------+---------+
but for config space, the payload include:
Virtio device config space
^^^^^^^^^^^^^^^^^^^^^^^^^^
+--------+------+-------+---------+
| offset | size | flags | payload |
+--------+------+-------+---------+
:offset: a 32-bit offset of virtio device's configuration space
:size: a 32-bit configuration space access size in bytes
🎏 a 32-bit value:
- 0: Vhost master messages used for writeable fields
- 1: Vhost master messages used for live migration
:payload: Size bytes array holding the contents of the virtio
device's configuration space
This patch add specific functions for config message, which can
get/set config space from/to backend.
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
This commit is contained in:
parent
e05de4514d
commit
3e99098bf3
@ -197,6 +197,45 @@ impl<R: Req> Endpoint<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send a message with header, body and config info. Optional file descriptors may be attached to
|
||||
/// the message.
|
||||
///
|
||||
/// # Return:
|
||||
/// * - number of bytes sent on success
|
||||
/// * - SocketRetry: temporary error caused by signals or short of resources.
|
||||
/// * - SocketBroken: the underline socket is broken.
|
||||
/// * - SocketError: other socket related errors.
|
||||
/// * - PartialMessage: received a partial message.
|
||||
pub fn send_config_message(
|
||||
&mut self,
|
||||
hdr: &VhostUserMsgHeader<R>,
|
||||
user_config: &VhostUserConfig,
|
||||
buf: &mut [u8],
|
||||
fds: Option<&[RawFd]>,
|
||||
) -> Result<()> {
|
||||
// Safe because there can't be other mutable referance to hdr and body.
|
||||
let iovs = unsafe {
|
||||
[
|
||||
slice::from_raw_parts(
|
||||
hdr as *const VhostUserMsgHeader<R> as *const u8,
|
||||
mem::size_of::<VhostUserMsgHeader<R>>(),
|
||||
),
|
||||
slice::from_raw_parts(
|
||||
user_config as *const VhostUserConfig as *const u8,
|
||||
mem::size_of::<VhostUserConfig>(),
|
||||
),
|
||||
slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len()),
|
||||
]
|
||||
};
|
||||
let bytes = self.send_iovec(&iovs[..], fds)?;
|
||||
let total =
|
||||
mem::size_of::<VhostUserMsgHeader<R>>() + mem::size_of::<VhostUserConfig>() + buf.len();
|
||||
if bytes != total {
|
||||
return Err(Error::PartialMessage);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send a message with header, body and payload. Optional file descriptors
|
||||
/// may also be attached to the message.
|
||||
///
|
||||
|
@ -360,7 +360,7 @@ impl VhostUserMaster for Master {
|
||||
// "Master payload: virtio device config space"
|
||||
// But what content should the payload contains for a get_config() request?
|
||||
// So current implementation doesn't conform to the spec.
|
||||
let hdr = node.send_request_with_body(MasterReq::GET_CONFIG, &body, None)?;
|
||||
let hdr = node.send_request_with_config_body(MasterReq::GET_CONFIG, &body, None)?;
|
||||
let (reply, buf, rfds) = node.recv_reply_with_payload::<VhostUserConfig>(&hdr)?;
|
||||
if rfds.is_some() {
|
||||
Endpoint::<MasterReq>::close_rfds(rfds);
|
||||
@ -480,6 +480,27 @@ impl MasterInternal {
|
||||
Ok(hdr)
|
||||
}
|
||||
|
||||
fn send_request_with_config_body(
|
||||
&mut self,
|
||||
code: MasterReq,
|
||||
user_config: &VhostUserConfig,
|
||||
fds: Option<&[RawFd]>,
|
||||
) -> VhostUserResult<VhostUserMsgHeader<MasterReq>> {
|
||||
if mem::size_of::<VhostUserConfig>() + user_config.size as usize > MAX_MSG_SIZE {
|
||||
return Err(VhostUserError::InvalidParam);
|
||||
}
|
||||
self.check_state()?;
|
||||
|
||||
let hdr = Self::new_request_header(
|
||||
code,
|
||||
mem::size_of::<VhostUserConfig>() as u32 + user_config.size,
|
||||
);
|
||||
let mut buf = vec![0; user_config.size as usize];
|
||||
self.main_sock
|
||||
.send_config_message(&hdr, user_config, &mut buf, fds)?;
|
||||
Ok(hdr)
|
||||
}
|
||||
|
||||
fn send_request_with_payload<T: Sized, P: Sized>(
|
||||
&mut self,
|
||||
code: MasterReq,
|
||||
@ -555,7 +576,7 @@ impl MasterInternal {
|
||||
if !reply.is_reply_for(hdr)
|
||||
|| reply.get_size() as usize != mem::size_of::<T>() + bytes
|
||||
|| rfds.is_some()
|
||||
|| body.is_valid()
|
||||
|| !body.is_valid()
|
||||
{
|
||||
Endpoint::<MasterReq>::close_rfds(rfds);
|
||||
return Err(VhostUserError::InvalidMessage);
|
||||
|
Loading…
x
Reference in New Issue
Block a user