vmm_vhost/
frontend_client.rs1use std::mem;
5use std::string::ToString;
6
7use base::AsRawDescriptor;
8use base::RawDescriptor;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11
12use crate::message::*;
13use crate::BackendReq;
14use crate::Connection;
15use crate::Error;
16use crate::Frontend;
17use crate::HandlerResult;
18use crate::Result;
19
20pub struct FrontendClient {
22 sock: Connection<BackendReq>,
23
24 reply_ack_negotiated: bool,
26}
27
28impl FrontendClient {
29 pub fn new(ep: Connection<BackendReq>) -> Self {
31 FrontendClient {
32 sock: ep,
33 reply_ack_negotiated: false,
34 }
35 }
36
37 fn send_message<T>(
38 &mut self,
39 request: BackendReq,
40 msg: &T,
41 fds: Option<&[RawDescriptor]>,
42 ) -> HandlerResult<u64>
43 where
44 T: IntoBytes + Immutable,
45 {
46 let len = mem::size_of::<T>();
47 let mut hdr = VhostUserMsgHeader::new(request, 0, len as u32);
48 if self.reply_ack_negotiated {
49 hdr.set_need_reply(true);
50 }
51 self.sock
52 .send_message(&hdr, msg, fds)
53 .map_err(|e| std::io::Error::other(e.to_string()))?;
54
55 self.wait_for_reply(&hdr)
56 .map_err(|e| std::io::Error::other(e.to_string()))
57 }
58
59 fn wait_for_reply(&mut self, hdr: &VhostUserMsgHeader<BackendReq>) -> Result<u64> {
60 let code = hdr.get_code().map_err(|_| Error::InvalidMessage)?;
61 if code != BackendReq::SHMEM_MAP
62 && code != BackendReq::SHMEM_UNMAP
63 && code != BackendReq::GPU_MAP
64 && code != BackendReq::EXTERNAL_MAP
65 && !self.reply_ack_negotiated
66 {
67 return Ok(0);
68 }
69
70 let (reply, body, rfds) = self.sock.recv_message::<VhostUserU64>()?;
71 if !reply.is_valid() || !reply.is_reply_for(hdr) || !rfds.is_empty() || !body.is_valid() {
72 return Err(Error::InvalidMessage);
73 }
74 if body.value != 0 {
75 return Err(Error::FrontendInternalError);
76 }
77
78 Ok(body.value)
79 }
80
81 pub fn set_reply_ack_flag(&mut self, enable: bool) {
87 self.reply_ack_negotiated = enable;
88 }
89}
90
91impl Frontend for FrontendClient {
92 fn shmem_map(
94 &mut self,
95 req: &VhostUserShmemMapMsg,
96 fd: &dyn AsRawDescriptor,
97 ) -> HandlerResult<u64> {
98 self.send_message(BackendReq::SHMEM_MAP, req, Some(&[fd.as_raw_descriptor()]))
99 }
100
101 fn shmem_unmap(&mut self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
103 self.send_message(BackendReq::SHMEM_UNMAP, req, None)
104 }
105
106 fn handle_config_change(&mut self) -> HandlerResult<u64> {
108 self.send_message(BackendReq::CONFIG_CHANGE_MSG, &VhostUserEmptyMessage, None)
109 }
110
111 fn gpu_map(
113 &mut self,
114 req: &VhostUserGpuMapMsg,
115 descriptor: &dyn AsRawDescriptor,
116 ) -> HandlerResult<u64> {
117 self.send_message(
118 BackendReq::GPU_MAP,
119 req,
120 Some(&[descriptor.as_raw_descriptor()]),
121 )
122 }
123
124 fn external_map(&mut self, req: &VhostUserExternalMapMsg) -> HandlerResult<u64> {
126 self.send_message(BackendReq::EXTERNAL_MAP, req, None)
127 }
128}