Struct vmm_vhost::BackendServer
source · pub struct BackendServer<S: Backend> {
connection: Connection<FrontendReq>,
backend: S,
virtio_features: u64,
acked_virtio_features: u64,
protocol_features: VhostUserProtocolFeatures,
acked_protocol_features: u64,
reply_ack_enabled: bool,
}
Expand description
Handles requests from a vhost-user connection by dispatching them to [Backend] methods.
Fields§
§connection: Connection<FrontendReq>
Underlying connection for communication.
backend: S
§virtio_features: u64
§acked_virtio_features: u64
§protocol_features: VhostUserProtocolFeatures
§acked_protocol_features: u64
§reply_ack_enabled: bool
Sending ack for messages without payload.
Implementations§
source§impl<S: Backend> BackendServer<S>
impl<S: Backend> BackendServer<S>
pub fn new(connection: Connection<FrontendReq>, backend: S) -> Self
sourcepub fn recv_header(
&mut self
) -> Result<(VhostUserMsgHeader<FrontendReq>, Vec<File>)>
pub fn recv_header( &mut self ) -> Result<(VhostUserMsgHeader<FrontendReq>, Vec<File>)>
Receives and validates a vhost-user message header and optional files.
Since the length of vhost-user messages are different among message types, regular
vhost-user messages are sent via an underlying communication channel in stream mode.
(e.g. SOCK_STREAM
in UNIX)
So, the logic of receiving and handling a message consists of the following steps:
- Receives a message header and optional attached file.
- Validates the message header.
- Check if optional payloads is expected.
- Wait for the optional payloads.
- Receives optional payloads.
- Processes the message.
This method BackendServer::recv_header()
is in charge of the step (1) and (2),
BackendServer::needs_wait_for_payload()
is (3), and
BackendServer::process_message()
is (5) and (6). We need to have the three method
separately for multi-platform supports; BackendServer::recv_header()
and
BackendServer::process_message()
need to be separated because the way of waiting for
incoming messages differs between Unix and Windows so it’s the caller’s responsibility to
wait before BackendServer::process_message()
.
Note that some vhost-user protocol variant such as VVU doesn’t assume stream mode. In this
case, a message header and its body are sent together so the step (4) is skipped. We handle
this case in BackendServer::needs_wait_for_payload()
.
The following pseudo code describes how a caller should process incoming vhost-user messages:
loop {
// block until a message header comes.
// The actual code differs, depending on platforms.
connection.wait_readable().unwrap();
// (1) and (2)
let (hdr, files) = backend_server.recv_header();
// (3)
if backend_server.needs_wait_for_payload(&hdr) {
// (4) block until a payload comes if needed.
connection.wait_readable().unwrap();
}
// (5) and (6)
backend_server.process_message(&hdr, &files).unwrap();
}
sourcepub fn needs_wait_for_payload(
&self,
hdr: &VhostUserMsgHeader<FrontendReq>
) -> bool
pub fn needs_wait_for_payload( &self, hdr: &VhostUserMsgHeader<FrontendReq> ) -> bool
Returns whether the caller needs to wait for the incoming message before calling
BackendServer::process_message
.
See BackendServer::recv_header
’s doc comment for the usage.
sourcepub fn process_message(
&mut self,
hdr: VhostUserMsgHeader<FrontendReq>,
files: Vec<File>
) -> Result<()>
pub fn process_message( &mut self, hdr: VhostUserMsgHeader<FrontendReq>, files: Vec<File> ) -> Result<()>
Main entrance to request from the communication channel.
Receive and handle one incoming request message from the frontend.
See BackendServer::recv_header
’s doc comment for the usage.
§Return:
Ok(())
: one request was successfully handled.Err(ClientExit)
: the frontend closed the connection properly. This isn’t an actual failure.Err(Disconnect)
: the connection was closed unexpectedly.Err(InvalidMessage)
: the vmm sent a illegal message.- other errors: failed to handle a request.
fn new_reply_header<T: Sized>( &self, req: &VhostUserMsgHeader<FrontendReq>, payload_size: usize ) -> Result<VhostUserMsgHeader<FrontendReq>>
sourcefn send_ack_message(
&mut self,
req: &VhostUserMsgHeader<FrontendReq>,
success: bool
) -> Result<()>
fn send_ack_message( &mut self, req: &VhostUserMsgHeader<FrontendReq>, success: bool ) -> Result<()>
Sends reply back to Vhost frontend in response to a message.
fn send_reply_message<T: Sized + AsBytes>( &mut self, req: &VhostUserMsgHeader<FrontendReq>, msg: &T ) -> Result<()>
fn send_reply_with_payload<T: Sized + AsBytes>( &mut self, req: &VhostUserMsgHeader<FrontendReq>, msg: &T, payload: &[u8] ) -> Result<()>
fn set_mem_table( &mut self, hdr: &VhostUserMsgHeader<FrontendReq>, size: usize, buf: &[u8], files: Vec<File> ) -> Result<()>
fn get_config( &mut self, hdr: &VhostUserMsgHeader<FrontendReq>, buf: &[u8] ) -> Result<()>
fn set_config(&mut self, buf: &[u8]) -> Result<()>
fn set_backend_req_fd(&mut self, files: Vec<File>) -> Result<()>
sourcefn handle_vring_fd_request(
&mut self,
buf: &[u8],
files: Vec<File>
) -> Result<(u8, Option<File>)>
fn handle_vring_fd_request( &mut self, buf: &[u8], files: Vec<File> ) -> Result<(u8, Option<File>)>
Parses an incoming |SET_VRING_KICK| or |SET_VRING_CALL| message into a Vring number and an fd.