diff --git a/.buildkite/custom-tests.json b/.buildkite/custom-tests.json index b0da5ad6..892cbb5b 100644 --- a/.buildkite/custom-tests.json +++ b/.buildkite/custom-tests.json @@ -8,15 +8,15 @@ ] }, { - "test_name": "build-vhost-user-master", - "command": "cargo build --features=vhost-user-master", + "test_name": "build-vhost-user-frontend", + "command": "cargo build --features=vhost-user-frontend", "platform": [ "x86_64" ] }, { - "test_name": "build-vhost-user-slave", - "command": "cargo build --features=vhost-user-slave", + "test_name": "build-vhost-user-backend", + "command": "cargo build --features=vhost-user-backend", "platform": [ "x86_64" ] diff --git a/coverage_config_aarch64.json b/coverage_config_aarch64.json index 089bc196..12a512d9 100644 --- a/coverage_config_aarch64.json +++ b/coverage_config_aarch64.json @@ -1,5 +1,5 @@ { "coverage_score": 39.8, "exclude_path": "", - "crate_features": "vhost/vhost-vsock,vhost/vhost-kern,vhost/vhost-user-master,vhost/vhost-user-slave" + "crate_features": "vhost/vhost-vsock,vhost/vhost-kern,vhost/vhost-user-frontend,vhost/vhost-user-backend" } diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index f270b64f..944803a1 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { "coverage_score": 84.0, "exclude_path": "vhost/src/vhost_kern/", - "crate_features": "vhost/vhost-user-master,vhost/vhost-user-slave" + "crate_features": "vhost/vhost-user-frontend,vhost/vhost-user-backend" } diff --git a/crates/vhost-user-backend/CHANGELOG.md b/crates/vhost-user-backend/CHANGELOG.md index 4ae24f3f..033e8b5d 100644 --- a/crates/vhost-user-backend/CHANGELOG.md +++ b/crates/vhost-user-backend/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added ### Changed +- Change uses of master/slave for frontend/backend in the codebase. ### Fixed diff --git a/crates/vhost-user-backend/Cargo.toml b/crates/vhost-user-backend/Cargo.toml index a42ea78d..8080850f 100644 --- a/crates/vhost-user-backend/Cargo.toml +++ b/crates/vhost-user-backend/Cargo.toml @@ -14,7 +14,7 @@ xen = ["vm-memory/xen", "vhost/xen"] [dependencies] libc = "0.2.39" log = "0.4.17" -vhost = { path = "../vhost", version = "0.8", features = ["vhost-user-slave"] } +vhost = { path = "../vhost", version = "0.8", features = ["vhost-user-backend"] } virtio-bindings = "0.2.1" virtio-queue = "0.9.0" vm-memory = { version = "0.12.0", features = ["backend-mmap", "backend-atomic"] } @@ -22,6 +22,6 @@ vmm-sys-util = "0.11.0" [dev-dependencies] nix = "0.26" -vhost = { path = "../vhost", version = "0.8", features = ["test-utils", "vhost-user-master", "vhost-user-slave"] } +vhost = { path = "../vhost", version = "0.8", features = ["test-utils", "vhost-user-frontend", "vhost-user-backend"] } vm-memory = { version = "0.12.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } tempfile = "3.2.0" diff --git a/crates/vhost-user-backend/README.md b/crates/vhost-user-backend/README.md index a526ab12..a4e51a83 100644 --- a/crates/vhost-user-backend/README.md +++ b/crates/vhost-user-backend/README.md @@ -29,14 +29,14 @@ where ### Create a `VhostUserDaemon` Instance The `VhostUserDaemon::new()` creates an instance of `VhostUserDaemon` object. The client needs to pass in an `VhostUserBackend` object, which will be used to configure the `VhostUserDaemon` -instance, handle control messages from the vhost-user master and handle virtio requests from +instance, handle control messages from the vhost-user frontend and handle virtio requests from virtio queues. A group of working threads will be created to handle virtio requests from configured virtio queues. ### Start the `VhostUserDaemon` -The `VhostUserDaemon::start()` method waits for an incoming connection from the vhost-user masters +The `VhostUserDaemon::start()` method waits for an incoming connection from the vhost-user frontends on the `listener`. Once a connection is ready, a main thread will be created to handle vhost-user -messages from the vhost-user master. +messages from the vhost-user frontend. ### Stop the `VhostUserDaemon` The `VhostUserDaemon::stop()` method waits for the main thread to exit. An exit event must be sent diff --git a/crates/vhost-user-backend/src/backend.rs b/crates/vhost-user-backend/src/backend.rs index 43ab7b95..3610f4d7 100644 --- a/crates/vhost-user-backend/src/backend.rs +++ b/crates/vhost-user-backend/src/backend.rs @@ -23,7 +23,7 @@ use std::ops::Deref; use std::sync::{Arc, Mutex, RwLock}; use vhost::vhost_user::message::VhostUserProtocolFeatures; -use vhost::vhost_user::Slave; +use vhost::vhost_user::Backend; use vm_memory::bitmap::Bitmap; use vmm_sys_util::epoll::EventSet; use vmm_sys_util::eventfd::EventFd; @@ -76,11 +76,11 @@ where /// Update guest memory regions. fn update_memory(&self, mem: GM) -> Result<()>; - /// Set handler for communicating with the master by the slave communication channel. + /// Set handler for communicating with the frontend by the backend communication channel. /// /// A default implementation is provided as we cannot expect all backends to implement this /// function. - fn set_slave_req_fd(&self, _slave: Slave) {} + fn set_backend_req_fd(&self, _backend: Backend) {} /// Get the map to map queue index to worker thread index. /// @@ -157,11 +157,11 @@ where /// Update guest memory regions. fn update_memory(&mut self, mem: GM) -> Result<()>; - /// Set handler for communicating with the master by the slave communication channel. + /// Set handler for communicating with the frontend by the backend communication channel. /// /// A default implementation is provided as we cannot expect all backends to implement this /// function. - fn set_slave_req_fd(&mut self, _slave: Slave) {} + fn set_backend_req_fd(&mut self, _backend: Backend) {} /// Get the map to map queue index to worker thread index. /// @@ -236,8 +236,8 @@ where self.deref().update_memory(mem) } - fn set_slave_req_fd(&self, slave: Slave) { - self.deref().set_slave_req_fd(slave) + fn set_backend_req_fd(&self, backend: Backend) { + self.deref().set_backend_req_fd(backend) } fn queues_per_thread(&self) -> Vec { @@ -301,8 +301,8 @@ where self.lock().unwrap().update_memory(mem) } - fn set_slave_req_fd(&self, slave: Slave) { - self.lock().unwrap().set_slave_req_fd(slave) + fn set_backend_req_fd(&self, backend: Backend) { + self.lock().unwrap().set_backend_req_fd(backend) } fn queues_per_thread(&self) -> Vec { @@ -367,8 +367,8 @@ where self.write().unwrap().update_memory(mem) } - fn set_slave_req_fd(&self, slave: Slave) { - self.write().unwrap().set_slave_req_fd(slave) + fn set_backend_req_fd(&self, backend: Backend) { + self.write().unwrap().set_backend_req_fd(backend) } fn queues_per_thread(&self) -> Vec { @@ -459,7 +459,7 @@ pub mod tests { Ok(()) } - fn set_slave_req_fd(&mut self, _slave: Slave) {} + fn set_backend_req_fd(&mut self, _backend: Backend) {} fn queues_per_thread(&self) -> Vec { vec![1, 1] diff --git a/crates/vhost-user-backend/src/handler.rs b/crates/vhost-user-backend/src/handler.rs index 262bf6c4..85e20d5b 100644 --- a/crates/vhost-user-backend/src/handler.rs +++ b/crates/vhost-user-backend/src/handler.rs @@ -16,7 +16,7 @@ use vhost::vhost_user::message::{ VhostUserVringState, }; use vhost::vhost_user::{ - Error as VhostUserError, Result as VhostUserResult, Slave, VhostUserSlaveReqHandlerMut, + Backend, Error as VhostUserError, Result as VhostUserResult, VhostUserBackendReqHandlerMut, }; use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use virtio_queue::{Error as VirtQueError, QueueT}; @@ -218,7 +218,7 @@ where } } -impl VhostUserSlaveReqHandlerMut for VhostUserHandler +impl VhostUserBackendReqHandlerMut for VhostUserHandler where S: VhostUserBackend, V: VringT>, @@ -362,7 +362,7 @@ where // be to receive the 'used' index in SET_VRING_BASE, as is done when using packed VQs. let idx = self.vrings[index as usize] .queue_used_idx() - .map_err(|_| VhostUserError::SlaveInternalError)?; + .map_err(|_| VhostUserError::BackendInternalError)?; self.vrings[index as usize].set_queue_next_used(idx); Ok(()) @@ -461,7 +461,7 @@ where } fn set_protocol_features(&mut self, features: u64) -> VhostUserResult<()> { - // Note: slave that reported VHOST_USER_F_PROTOCOL_FEATURES must + // Note: backend that reported VHOST_USER_F_PROTOCOL_FEATURES must // support this message even before VHOST_USER_SET_FEATURES was // called. self.acked_protocol_features = features; @@ -481,7 +481,7 @@ where return Err(VhostUserError::InvalidParam); } - // Slave must not pass data to/from the backend until ring is + // Backend must not pass data to/from the backend until ring is // enabled by VHOST_USER_SET_VRING_ENABLE with parameter 1, // or after it has been disabled by VHOST_USER_SET_VRING_ENABLE // with parameter 0. @@ -510,12 +510,12 @@ where .map_err(VhostUserError::ReqHandlerError) } - fn set_slave_req_fd(&mut self, slave: Slave) { + fn set_backend_req_fd(&mut self, backend: Backend) { if self.acked_protocol_features & VhostUserProtocolFeatures::REPLY_ACK.bits() != 0 { - slave.set_reply_ack_flag(true); + backend.set_reply_ack_flag(true); } - self.backend.set_slave_req_fd(slave); + self.backend.set_backend_req_fd(backend); } fn get_inflight_fd( diff --git a/crates/vhost-user-backend/src/lib.rs b/crates/vhost-user-backend/src/lib.rs index c65a19ee..5919a602 100644 --- a/crates/vhost-user-backend/src/lib.rs +++ b/crates/vhost-user-backend/src/lib.rs @@ -12,7 +12,7 @@ use std::fmt::{Display, Formatter}; use std::sync::{Arc, Mutex}; use std::thread; -use vhost::vhost_user::{Error as VhostUserError, Listener, SlaveListener, SlaveReqHandler}; +use vhost::vhost_user::{BackendListener, BackendReqHandler, Error as VhostUserError, Listener}; use vm_memory::bitmap::Bitmap; use vm_memory::mmap::NewBitmap; use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap}; @@ -41,10 +41,10 @@ type GM = GuestMemoryAtomic>; pub enum Error { /// Failed to create a new vhost-user handler. NewVhostUserHandler(VhostUserHandlerError), - /// Failed creating vhost-user slave listener. - CreateSlaveListener(VhostUserError), - /// Failed creating vhost-user slave handler. - CreateSlaveReqHandler(VhostUserError), + /// Failed creating vhost-user backend listener. + CreateBackendListener(VhostUserError), + /// Failed creating vhost-user backend handler. + CreateBackendReqHandler(VhostUserError), /// Failed starting daemon thread. StartDaemon(std::io::Error), /// Failed waiting for daemon thread. @@ -57,8 +57,10 @@ impl Display for Error { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { match self { Error::NewVhostUserHandler(e) => write!(f, "cannot create vhost user handler: {}", e), - Error::CreateSlaveListener(e) => write!(f, "cannot create slave listener: {}", e), - Error::CreateSlaveReqHandler(e) => write!(f, "cannot create slave req handler: {}", e), + Error::CreateBackendListener(e) => write!(f, "cannot create backend listener: {}", e), + Error::CreateBackendReqHandler(e) => { + write!(f, "cannot create backend req handler: {}", e) + } Error::StartDaemon(e) => write!(f, "failed to start daemon: {}", e), Error::WaitDaemon(_e) => write!(f, "failed to wait for daemon exit"), Error::HandleRequest(e) => write!(f, "failed to handle request: {}", e), @@ -114,7 +116,7 @@ where /// it acts as a client or a server. fn start_daemon( &mut self, - mut handler: SlaveReqHandler>>, + mut handler: BackendReqHandler>>, ) -> Result<()> { let handle = thread::Builder::new() .name(self.name.clone()) @@ -133,9 +135,9 @@ where /// that should be terminating once the other end of the socket (the VMM) /// hangs up. pub fn start_client(&mut self, socket_path: &str) -> Result<()> { - let slave_handler = SlaveReqHandler::connect(socket_path, self.handler.clone()) - .map_err(Error::CreateSlaveReqHandler)?; - self.start_daemon(slave_handler) + let backend_handler = BackendReqHandler::connect(socket_path, self.handler.clone()) + .map_err(Error::CreateBackendReqHandler)?; + self.start_daemon(backend_handler) } /// Listen to the vhost-user socket and run a dedicated thread handling all requests coming @@ -146,19 +148,19 @@ where // TODO: the current implementation has limitations that only one incoming connection will be // handled from the listener. Should it be enhanced to support reconnection? pub fn start(&mut self, listener: Listener) -> Result<()> { - let mut slave_listener = SlaveListener::new(listener, self.handler.clone()) - .map_err(Error::CreateSlaveListener)?; - let slave_handler = self.accept(&mut slave_listener)?; - self.start_daemon(slave_handler) + let mut backend_listener = BackendListener::new(listener, self.handler.clone()) + .map_err(Error::CreateBackendListener)?; + let backend_handler = self.accept(&mut backend_listener)?; + self.start_daemon(backend_handler) } fn accept( &self, - slave_listener: &mut SlaveListener>>, - ) -> Result>>> { + backend_listener: &mut BackendListener>>, + ) -> Result>>> { loop { - match slave_listener.accept() { - Err(e) => return Err(Error::CreateSlaveListener(e)), + match backend_listener.accept() { + Err(e) => return Err(Error::CreateBackendListener(e)), Ok(Some(v)) => return Ok(v), Ok(None) => continue, } diff --git a/crates/vhost-user-backend/src/vring.rs b/crates/vhost-user-backend/src/vring.rs index 13e08ac4..948f6878 100644 --- a/crates/vhost-user-backend/src/vring.rs +++ b/crates/vhost-user-backend/src/vring.rs @@ -46,7 +46,7 @@ pub trait VringT: /// Add an used descriptor into the used queue. fn add_used(&self, desc_index: u16, len: u32) -> Result<(), VirtQueError>; - /// Notify the vhost-user master that used descriptors have been put into the used queue. + /// Notify the vhost-user frontend that used descriptors have been put into the used queue. fn signal_used_queue(&self) -> io::Result<()>; /// Enable event notification for queue. @@ -145,7 +145,7 @@ impl VringState { .add_used(self.mem.memory().deref(), desc_index, len) } - /// Notify the vhost-user master that used descriptors have been put into the used queue. + /// Notify the vhost-user frontend that used descriptors have been put into the used queue. pub fn signal_used_queue(&self) -> io::Result<()> { if let Some(call) = self.call.as_ref() { call.write(1) diff --git a/crates/vhost-user-backend/tests/vhost-user-server.rs b/crates/vhost-user-backend/tests/vhost-user-server.rs index f6fdea7f..1ae98813 100644 --- a/crates/vhost-user-backend/tests/vhost-user-server.rs +++ b/crates/vhost-user-backend/tests/vhost-user-server.rs @@ -10,7 +10,7 @@ use std::thread; use vhost::vhost_user::message::{ VhostUserConfigFlags, VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures, }; -use vhost::vhost_user::{Listener, Master, Slave, VhostUserMaster}; +use vhost::vhost_user::{Backend, Frontend, Listener, VhostUserFrontend}; use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData}; use vhost_user_backend::{VhostUserBackendMut, VhostUserDaemon, VringRwLock}; use vm_memory::{ @@ -81,7 +81,7 @@ impl VhostUserBackendMut for MockVhostBackend { Ok(()) } - fn set_slave_req_fd(&mut self, _slave: Slave) {} + fn set_backend_req_fd(&mut self, _backend: Backend) {} fn queues_per_thread(&self) -> Vec { vec![1, 1] @@ -106,46 +106,46 @@ impl VhostUserBackendMut for MockVhostBackend { } } -fn setup_master(path: &Path, barrier: Arc) -> Master { +fn setup_frontend(path: &Path, barrier: Arc) -> Frontend { barrier.wait(); - let mut master = Master::connect(path, 1).unwrap(); - master.set_hdr_flags(VhostUserHeaderFlag::NEED_REPLY); + let mut frontend = Frontend::connect(path, 1).unwrap(); + frontend.set_hdr_flags(VhostUserHeaderFlag::NEED_REPLY); // Wait before issue service requests. barrier.wait(); - let features = master.get_features().unwrap(); - let proto = master.get_protocol_features().unwrap(); - master.set_features(features).unwrap(); - master.set_protocol_features(proto).unwrap(); + let features = frontend.get_features().unwrap(); + let proto = frontend.get_protocol_features().unwrap(); + frontend.set_features(features).unwrap(); + frontend.set_protocol_features(proto).unwrap(); assert!(proto.contains(VhostUserProtocolFeatures::REPLY_ACK)); - master + frontend } fn vhost_user_client(path: &Path, barrier: Arc) { barrier.wait(); - let mut master = Master::connect(path, 1).unwrap(); - master.set_hdr_flags(VhostUserHeaderFlag::NEED_REPLY); + let mut frontend = Frontend::connect(path, 1).unwrap(); + frontend.set_hdr_flags(VhostUserHeaderFlag::NEED_REPLY); // Wait before issue service requests. barrier.wait(); - let features = master.get_features().unwrap(); - let proto = master.get_protocol_features().unwrap(); - master.set_features(features).unwrap(); - master.set_protocol_features(proto).unwrap(); + let features = frontend.get_features().unwrap(); + let proto = frontend.get_protocol_features().unwrap(); + frontend.set_features(features).unwrap(); + frontend.set_protocol_features(proto).unwrap(); assert!(proto.contains(VhostUserProtocolFeatures::REPLY_ACK)); - let queue_num = master.get_queue_num().unwrap(); + let queue_num = frontend.get_queue_num().unwrap(); assert_eq!(queue_num, 2); - master.set_owner().unwrap(); - //master.set_owner().unwrap_err(); - master.reset_owner().unwrap(); - master.reset_owner().unwrap(); - master.set_owner().unwrap(); + frontend.set_owner().unwrap(); + //frontend.set_owner().unwrap_err(); + frontend.reset_owner().unwrap(); + frontend.reset_owner().unwrap(); + frontend.set_owner().unwrap(); - master.set_features(features).unwrap(); - master.set_protocol_features(proto).unwrap(); + frontend.set_features(features).unwrap(); + frontend.set_protocol_features(proto).unwrap(); assert!(proto.contains(VhostUserProtocolFeatures::REPLY_ACK)); let memfd = nix::sys::memfd::memfd_create( @@ -173,9 +173,9 @@ fn vhost_user_client(path: &Path, barrier: Arc) { 0, fd.file().as_raw_fd(), )]; - master.set_mem_table(®ions).unwrap(); + frontend.set_mem_table(®ions).unwrap(); - master.set_vring_num(0, 256).unwrap(); + frontend.set_vring_num(0, 256).unwrap(); let config = VringConfigData { queue_max_size: 256, @@ -186,33 +186,33 @@ fn vhost_user_client(path: &Path, barrier: Arc) { avail_ring_addr: addr + 0x20000, log_addr: None, }; - master.set_vring_addr(0, &config).unwrap(); + frontend.set_vring_addr(0, &config).unwrap(); let eventfd = EventFd::new(0).unwrap(); - master.set_vring_kick(0, &eventfd).unwrap(); - master.set_vring_call(0, &eventfd).unwrap(); - master.set_vring_err(0, &eventfd).unwrap(); - master.set_vring_enable(0, true).unwrap(); + frontend.set_vring_kick(0, &eventfd).unwrap(); + frontend.set_vring_call(0, &eventfd).unwrap(); + frontend.set_vring_err(0, &eventfd).unwrap(); + frontend.set_vring_enable(0, true).unwrap(); let buf = [0u8; 8]; - let (_cfg, data) = master + let (_cfg, data) = frontend .get_config(0x200, 8, VhostUserConfigFlags::empty(), &buf) .unwrap(); assert_eq!(&data, &[0xa5u8; 8]); - master + frontend .set_config(0x200, VhostUserConfigFlags::empty(), &data) .unwrap(); let (tx, _rx) = UnixStream::pair().unwrap(); - master.set_slave_request_fd(&tx).unwrap(); + frontend.set_backend_request_fd(&tx).unwrap(); - let state = master.get_vring_base(0).unwrap(); - master.set_vring_base(0, state as u16).unwrap(); + let state = frontend.get_vring_base(0).unwrap(); + frontend.set_vring_base(0, state as u16).unwrap(); - assert_eq!(master.get_max_mem_slots().unwrap(), 32); + assert_eq!(frontend.get_max_mem_slots().unwrap(), 32); let region = VhostUserMemoryRegionInfo::new(0x800000, 0x100000, addr, 0, fd.file().as_raw_fd()); - master.add_mem_region(®ion).unwrap(); - master.remove_mem_region(®ion).unwrap(); + frontend.add_mem_region(®ion).unwrap(); + frontend.remove_mem_region(®ion).unwrap(); } fn vhost_user_server(cb: fn(&Path, Arc)) { @@ -244,9 +244,9 @@ fn test_vhost_user_server() { } fn vhost_user_enable(path: &Path, barrier: Arc) { - let master = setup_master(path, barrier); - master.set_owner().unwrap(); - master.set_owner().unwrap_err(); + let frontend = setup_frontend(path, barrier); + frontend.set_owner().unwrap(); + frontend.set_owner().unwrap_err(); } #[test] @@ -255,7 +255,7 @@ fn test_vhost_user_enable() { } fn vhost_user_set_inflight(path: &Path, barrier: Arc) { - let mut master = setup_master(path, barrier); + let mut frontend = setup_frontend(path, barrier); let eventfd = EventFd::new(0).unwrap(); // No implementation for inflight_fd yet. let inflight = VhostUserInflight { @@ -264,7 +264,7 @@ fn vhost_user_set_inflight(path: &Path, barrier: Arc) { num_queues: 1, queue_size: 256, }; - master + frontend .set_inflight_fd(&inflight, eventfd.as_raw_fd()) .unwrap_err(); } @@ -275,7 +275,7 @@ fn test_vhost_user_set_inflight() { } fn vhost_user_get_inflight(path: &Path, barrier: Arc) { - let mut master = setup_master(path, barrier); + let mut frontend = setup_frontend(path, barrier); // No implementation for inflight_fd yet. let inflight = VhostUserInflight { mmap_size: 0x100000, @@ -283,7 +283,7 @@ fn vhost_user_get_inflight(path: &Path, barrier: Arc) { num_queues: 1, queue_size: 256, }; - assert!(master.get_inflight_fd(&inflight).is_err()); + assert!(frontend.get_inflight_fd(&inflight).is_err()); } #[test] diff --git a/crates/vhost/CHANGELOG.md b/crates/vhost/CHANGELOG.md index af8c4307..6175b405 100644 --- a/crates/vhost/CHANGELOG.md +++ b/crates/vhost/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added ### Changed +- Change uses of master/slave for frontend/backend in the codebase. ### Fixed diff --git a/crates/vhost/Cargo.toml b/crates/vhost/Cargo.toml index 3ed9d09a..d57dc8a2 100644 --- a/crates/vhost/Cargo.toml +++ b/crates/vhost/Cargo.toml @@ -21,8 +21,8 @@ vhost-kern = [] vhost-vdpa = ["vhost-kern"] vhost-net = ["vhost-kern"] vhost-user = [] -vhost-user-master = ["vhost-user"] -vhost-user-slave = ["vhost-user"] +vhost-user-frontend = ["vhost-user"] +vhost-user-backend = ["vhost-user"] xen = ["vm-memory/xen"] [dependencies] diff --git a/crates/vhost/README.md b/crates/vhost/README.md index 6f5f0e5a..731ad0a2 100644 --- a/crates/vhost/README.md +++ b/crates/vhost/README.md @@ -26,9 +26,9 @@ to establish virtqueue sharing with a user space process on the same host. It uses communication over a Unix domain socket to share file descriptors in the ancillary data of the message. -The protocol defines two sides of the communication, master and slave. -Master is the application that shares its virtqueues, slave is the consumer -of the virtqueues. Master and slave can be either a client (i.e. connecting) +The protocol defines two sides of the communication, frontend and backend. +Frontend is the application that shares its virtqueues, backend is the consumer +of the virtqueues. Frontend and backend can be either a client (i.e. connecting) or server (listening) in the socket communication. ## Xen support diff --git a/crates/vhost/docs/vhost_architecture.drawio b/crates/vhost/docs/vhost_architecture.drawio index 8c669d8f..610aff41 100644 --- a/crates/vhost/docs/vhost_architecture.drawio +++ b/crates/vhost/docs/vhost_architecture.drawio @@ -13,10 +13,10 @@ - + - + @@ -27,10 +27,10 @@ - + - + @@ -39,13 +39,13 @@ - + - + - + @@ -63,7 +63,7 @@ - + @@ -126,7 +126,7 @@ - + diff --git a/crates/vhost/src/lib.rs b/crates/vhost/src/lib.rs index f8be913f..1c828610 100644 --- a/crates/vhost/src/lib.rs +++ b/crates/vhost/src/lib.rs @@ -26,8 +26,8 @@ //! vhost implementation in the Linux kernel. It implements the control plane needed to establish //! virtqueues sharing with a user space process on the same host. It uses communication over a //! Unix domain socket to share file descriptors in the ancillary data of the message. -//! The protocol defines 2 sides of the communication, master and slave. Master is the application -//! that shares its virtqueues. Slave is the consumer of the virtqueues. Master and slave can be +//! The protocol defines 2 sides of the communication, frontend and backend. Frontend is the application +//! that shares its virtqueues. Backend is the consumer of the virtqueues. Frontend and backend can be //! either a client (i.e. connecting) or server (listening) in the socket communication. #![deny(missing_docs)] diff --git a/crates/vhost/src/vhost_user/backend.rs b/crates/vhost/src/vhost_user/backend.rs new file mode 100644 index 00000000..48e44571 --- /dev/null +++ b/crates/vhost/src/vhost_user/backend.rs @@ -0,0 +1,86 @@ +// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Traits and Structs for vhost-user backend. + +use std::sync::Arc; + +use super::connection::{Endpoint, Listener}; +use super::message::*; +use super::{BackendReqHandler, Result, VhostUserBackendReqHandler}; + +/// Vhost-user backend side connection listener. +pub struct BackendListener { + listener: Listener, + backend: Option>, +} + +/// Sets up a listener for incoming frontend connections, and handles construction +/// of a Backend on success. +impl BackendListener { + /// Create a unix domain socket for incoming frontend connections. + pub fn new(listener: Listener, backend: Arc) -> Result { + Ok(BackendListener { + listener, + backend: Some(backend), + }) + } + + /// Accept an incoming connection from the frontend, returning Some(Backend) on + /// success, or None if the socket is nonblocking and no incoming connection + /// was detected + pub fn accept(&mut self) -> Result>> { + if let Some(fd) = self.listener.accept()? { + return Ok(Some(BackendReqHandler::new( + Endpoint::::from_stream(fd), + self.backend.take().unwrap(), + ))); + } + Ok(None) + } + + /// Change blocking status on the listener. + pub fn set_nonblocking(&self, block: bool) -> Result<()> { + self.listener.set_nonblocking(block) + } +} + +#[cfg(test)] +mod tests { + use std::sync::Mutex; + + use super::*; + use crate::vhost_user::dummy_backend::DummyBackendReqHandler; + + #[test] + fn test_backend_listener_set_nonblocking() { + let backend = Arc::new(Mutex::new(DummyBackendReqHandler::new())); + let listener = + Listener::new("/tmp/vhost_user_lib_unit_test_backend_nonblocking", true).unwrap(); + let backend_listener = BackendListener::new(listener, backend).unwrap(); + + backend_listener.set_nonblocking(true).unwrap(); + backend_listener.set_nonblocking(false).unwrap(); + backend_listener.set_nonblocking(false).unwrap(); + backend_listener.set_nonblocking(true).unwrap(); + backend_listener.set_nonblocking(true).unwrap(); + } + + #[cfg(feature = "vhost-user-frontend")] + #[test] + fn test_backend_listener_accept() { + use super::super::Frontend; + + let path = "/tmp/vhost_user_lib_unit_test_backend_accept"; + let backend = Arc::new(Mutex::new(DummyBackendReqHandler::new())); + let listener = Listener::new(path, true).unwrap(); + let mut backend_listener = BackendListener::new(listener, backend).unwrap(); + + backend_listener.set_nonblocking(true).unwrap(); + assert!(backend_listener.accept().unwrap().is_none()); + assert!(backend_listener.accept().unwrap().is_none()); + + let _frontend = Frontend::connect(path, 1).unwrap(); + let _backend = backend_listener.accept().unwrap().unwrap(); + } +} diff --git a/crates/vhost/src/vhost_user/slave_req.rs b/crates/vhost/src/vhost_user/backend_req.rs similarity index 52% rename from crates/vhost/src/vhost_user/slave_req.rs rename to crates/vhost/src/vhost_user/backend_req.rs index ade1e91b..b43982f0 100644 --- a/crates/vhost/src/vhost_user/slave_req.rs +++ b/crates/vhost/src/vhost_user/backend_req.rs @@ -9,12 +9,12 @@ use std::sync::{Arc, Mutex, MutexGuard}; use super::connection::Endpoint; use super::message::*; -use super::{Error, HandlerResult, Result, VhostUserMasterReqHandler}; +use super::{Error, HandlerResult, Result, VhostUserFrontendReqHandler}; use vm_memory::ByteValued; -struct SlaveInternal { - sock: Endpoint, +struct BackendInternal { + sock: Endpoint, // Protocol feature VHOST_USER_PROTOCOL_F_REPLY_ACK has been negotiated. reply_ack_negotiated: bool, @@ -23,7 +23,7 @@ struct SlaveInternal { error: Option, } -impl SlaveInternal { +impl BackendInternal { fn check_state(&self) -> Result { match self.error { Some(e) => Err(Error::SocketBroken(std::io::Error::from_raw_os_error(e))), @@ -33,7 +33,7 @@ impl SlaveInternal { fn send_message( &mut self, - request: SlaveReq, + request: BackendReq, body: &T, fds: Option<&[RawFd]>, ) -> Result { @@ -49,7 +49,7 @@ impl SlaveInternal { self.wait_for_ack(&hdr) } - fn wait_for_ack(&mut self, hdr: &VhostUserMsgHeader) -> Result { + fn wait_for_ack(&mut self, hdr: &VhostUserMsgHeader) -> Result { self.check_state()?; if !self.reply_ack_negotiated { return Ok(0); @@ -60,32 +60,32 @@ impl SlaveInternal { return Err(Error::InvalidMessage); } if body.value != 0 { - return Err(Error::MasterInternalError); + return Err(Error::FrontendInternalError); } Ok(body.value) } } -/// Request proxy to send vhost-user slave requests to the master through the slave +/// Request proxy to send vhost-user backend requests to the frontend through the backend /// communication channel. /// -/// The [Slave] acts as a message proxy to forward vhost-user slave requests to the -/// master through the vhost-user slave communication channel. The forwarded messages will be -/// handled by the [MasterReqHandler] server. +/// The [Backend] acts as a message proxy to forward vhost-user backend requests to the +/// frontend through the vhost-user backend communication channel. The forwarded messages will be +/// handled by the [FrontendReqHandler] server. /// -/// [Slave]: struct.Slave.html -/// [MasterReqHandler]: struct.MasterReqHandler.html +/// [Backend]: struct.Backend.html +/// [FrontendReqHandler]: struct.FrontendReqHandler.html #[derive(Clone)] -pub struct Slave { +pub struct Backend { // underlying Unix domain socket for communication - node: Arc>, + node: Arc>, } -impl Slave { - fn new(ep: Endpoint) -> Self { - Slave { - node: Arc::new(Mutex::new(SlaveInternal { +impl Backend { + fn new(ep: Endpoint) -> Self { + Backend { + node: Arc::new(Mutex::new(BackendInternal { sock: ep, reply_ack_negotiated: false, error: None, @@ -93,13 +93,13 @@ impl Slave { } } - fn node(&self) -> MutexGuard { + fn node(&self) -> MutexGuard { self.node.lock().unwrap() } fn send_message( &self, - request: SlaveReq, + request: BackendReq, body: &T, fds: Option<&[RawFd]>, ) -> io::Result { @@ -110,13 +110,13 @@ impl Slave { /// Create a new instance from a `UnixStream` object. pub fn from_stream(sock: UnixStream) -> Self { - Self::new(Endpoint::::from_stream(sock)) + Self::new(Endpoint::::from_stream(sock)) } /// Set the negotiation state of the `VHOST_USER_PROTOCOL_F_REPLY_ACK` protocol feature. /// /// When the `VHOST_USER_PROTOCOL_F_REPLY_ACK` protocol feature has been negotiated, - /// the "REPLY_ACK" flag will be set in the message header for every slave to master request + /// the "REPLY_ACK" flag will be set in the message header for every backend to frontend request /// message. pub fn set_reply_ack_flag(&self, enable: bool) { self.node().reply_ack_negotiated = enable; @@ -128,15 +128,15 @@ impl Slave { } } -impl VhostUserMasterReqHandler for Slave { - /// Forward vhost-user-fs map file requests to the slave. - fn fs_slave_map(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult { - self.send_message(SlaveReq::FS_MAP, fs, Some(&[fd.as_raw_fd()])) +impl VhostUserFrontendReqHandler for Backend { + /// Forward vhost-user-fs map file requests to the backend. + fn fs_backend_map(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult { + self.send_message(BackendReq::FS_MAP, fs, Some(&[fd.as_raw_fd()])) } - /// Forward vhost-user-fs unmap file requests to the master. - fn fs_slave_unmap(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult { - self.send_message(SlaveReq::FS_UNMAP, fs, None) + /// Forward vhost-user-fs unmap file requests to the frontend. + fn fs_backend_unmap(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult { + self.send_message(BackendReq::FS_UNMAP, fs, None) } } @@ -147,73 +147,73 @@ mod tests { use super::*; #[test] - fn test_slave_req_set_failed() { + fn test_backend_req_set_failed() { let (p1, _p2) = UnixStream::pair().unwrap(); - let slave = Slave::from_stream(p1); + let backend = Backend::from_stream(p1); - assert!(slave.node().error.is_none()); - slave.set_failed(libc::EAGAIN); - assert_eq!(slave.node().error, Some(libc::EAGAIN)); + assert!(backend.node().error.is_none()); + backend.set_failed(libc::EAGAIN); + assert_eq!(backend.node().error, Some(libc::EAGAIN)); } #[test] - fn test_slave_req_send_failure() { + fn test_backend_req_send_failure() { let (p1, p2) = UnixStream::pair().unwrap(); - let slave = Slave::from_stream(p1); + let backend = Backend::from_stream(p1); - slave.set_failed(libc::ECONNRESET); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &p2) + backend.set_failed(libc::ECONNRESET); + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &p2) .unwrap_err(); - slave - .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) + backend + .fs_backend_unmap(&VhostUserFSBackendMsg::default()) .unwrap_err(); - slave.node().error = None; + backend.node().error = None; } #[test] - fn test_slave_req_recv_negative() { + fn test_backend_req_recv_negative() { let (p1, p2) = UnixStream::pair().unwrap(); - let slave = Slave::from_stream(p1); - let mut master = Endpoint::::from_stream(p2); + let backend = Backend::from_stream(p1); + let mut frontend = Endpoint::::from_stream(p2); - let len = mem::size_of::(); + let len = mem::size_of::(); let mut hdr = VhostUserMsgHeader::new( - SlaveReq::FS_MAP, + BackendReq::FS_MAP, VhostUserHeaderFlag::REPLY.bits(), len as u32, ); let body = VhostUserU64::new(0); - master - .send_message(&hdr, &body, Some(&[master.as_raw_fd()])) + frontend + .send_message(&hdr, &body, Some(&[frontend.as_raw_fd()])) .unwrap(); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &master) + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &frontend) .unwrap(); - slave.set_reply_ack_flag(true); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &master) + backend.set_reply_ack_flag(true); + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &frontend) .unwrap_err(); - hdr.set_code(SlaveReq::FS_UNMAP); - master.send_message(&hdr, &body, None).unwrap(); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &master) + hdr.set_code(BackendReq::FS_UNMAP); + frontend.send_message(&hdr, &body, None).unwrap(); + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &frontend) .unwrap_err(); - hdr.set_code(SlaveReq::FS_MAP); + hdr.set_code(BackendReq::FS_MAP); let body = VhostUserU64::new(1); - master.send_message(&hdr, &body, None).unwrap(); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &master) + frontend.send_message(&hdr, &body, None).unwrap(); + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &frontend) .unwrap_err(); let body = VhostUserU64::new(0); - master.send_message(&hdr, &body, None).unwrap(); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &master) + frontend.send_message(&hdr, &body, None).unwrap(); + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &frontend) .unwrap(); } } diff --git a/crates/vhost/src/vhost_user/slave_req_handler.rs b/crates/vhost/src/vhost_user/backend_req_handler.rs similarity index 82% rename from crates/vhost/src/vhost_user/slave_req_handler.rs rename to crates/vhost/src/vhost_user/backend_req_handler.rs index e9983398..feb763db 100644 --- a/crates/vhost/src/vhost_user/slave_req_handler.rs +++ b/crates/vhost/src/vhost_user/backend_req_handler.rs @@ -10,33 +10,33 @@ use std::sync::{Arc, Mutex}; use vm_memory::ByteValued; +use super::backend_req::Backend; use super::connection::Endpoint; use super::message::*; -use super::slave_req::Slave; use super::{take_single_file, Error, Result}; -/// Services provided to the master by the slave with interior mutability. +/// Services provided to the frontend by the backend with interior mutability. /// -/// The [VhostUserSlaveReqHandler] trait defines the services provided to the master by the slave. -/// And the [VhostUserSlaveReqHandlerMut] trait is a helper mirroring [VhostUserSlaveReqHandler], +/// The [VhostUserBackendReqHandler] trait defines the services provided to the frontend by the backend. +/// And the [VhostUserBackendReqHandlerMut] trait is a helper mirroring [VhostUserBackendReqHandler], /// but without interior mutability. -/// The vhost-user specification defines a master communication channel, by which masters could -/// request services from slaves. The [VhostUserSlaveReqHandler] trait defines services provided by -/// slaves, and it's used both on the master side and slave side. +/// The vhost-user specification defines a frontend communication channel, by which frontends could +/// request services from backends. The [VhostUserBackendReqHandler] trait defines services provided by +/// backends, and it's used both on the frontend side and backend side. /// -/// - on the master side, a stub forwarder implementing [VhostUserSlaveReqHandler] will proxy -/// service requests to slaves. -/// - on the slave side, the [SlaveReqHandler] will forward service requests to a handler -/// implementing [VhostUserSlaveReqHandler]. +/// - on the frontend side, a stub forwarder implementing [VhostUserBackendReqHandler] will proxy +/// service requests to backends. +/// - on the backend side, the [BackendReqHandler] will forward service requests to a handler +/// implementing [VhostUserBackendReqHandler]. /// -/// The [VhostUserSlaveReqHandler] trait is design with interior mutability to improve performance +/// The [VhostUserBackendReqHandler] trait is design with interior mutability to improve performance /// for multi-threading. /// -/// [VhostUserSlaveReqHandler]: trait.VhostUserSlaveReqHandler.html -/// [VhostUserSlaveReqHandlerMut]: trait.VhostUserSlaveReqHandlerMut.html -/// [SlaveReqHandler]: struct.SlaveReqHandler.html +/// [VhostUserBackendReqHandler]: trait.VhostUserBackendReqHandler.html +/// [VhostUserBackendReqHandlerMut]: trait.VhostUserBackendReqHandlerMut.html +/// [BackendReqHandler]: struct.BackendReqHandler.html #[allow(missing_docs)] -pub trait VhostUserSlaveReqHandler { +pub trait VhostUserBackendReqHandler { fn set_owner(&self) -> Result<()>; fn reset_owner(&self) -> Result<()>; fn get_features(&self) -> Result; @@ -64,7 +64,7 @@ pub trait VhostUserSlaveReqHandler { fn set_vring_enable(&self, index: u32, enable: bool) -> Result<()>; fn get_config(&self, offset: u32, size: u32, flags: VhostUserConfigFlags) -> Result>; fn set_config(&self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>; - fn set_slave_req_fd(&self, _slave: Slave) {} + fn set_backend_req_fd(&self, _backend: Backend) {} fn get_inflight_fd(&self, inflight: &VhostUserInflight) -> Result<(VhostUserInflight, File)>; fn set_inflight_fd(&self, inflight: &VhostUserInflight, file: File) -> Result<()>; fn get_max_mem_slots(&self) -> Result; @@ -72,11 +72,11 @@ pub trait VhostUserSlaveReqHandler { fn remove_mem_region(&self, region: &VhostUserSingleMemoryRegion) -> Result<()>; } -/// Services provided to the master by the slave without interior mutability. +/// Services provided to the frontend by the backend without interior mutability. /// -/// This is a helper trait mirroring the [VhostUserSlaveReqHandler] trait. +/// This is a helper trait mirroring the [VhostUserBackendReqHandler] trait. #[allow(missing_docs)] -pub trait VhostUserSlaveReqHandlerMut { +pub trait VhostUserBackendReqHandlerMut { fn set_owner(&mut self) -> Result<()>; fn reset_owner(&mut self) -> Result<()>; fn get_features(&mut self) -> Result; @@ -109,7 +109,7 @@ pub trait VhostUserSlaveReqHandlerMut { flags: VhostUserConfigFlags, ) -> Result>; fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>; - fn set_slave_req_fd(&mut self, _slave: Slave) {} + fn set_backend_req_fd(&mut self, _backend: Backend) {} fn get_inflight_fd( &mut self, inflight: &VhostUserInflight, @@ -120,7 +120,7 @@ pub trait VhostUserSlaveReqHandlerMut { fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()>; } -impl VhostUserSlaveReqHandler for Mutex { +impl VhostUserBackendReqHandler for Mutex { fn set_owner(&self) -> Result<()> { self.lock().unwrap().set_owner() } @@ -203,8 +203,8 @@ impl VhostUserSlaveReqHandler for Mutex { self.lock().unwrap().set_config(offset, buf, flags) } - fn set_slave_req_fd(&self, slave: Slave) { - self.lock().unwrap().set_slave_req_fd(slave) + fn set_backend_req_fd(&self, backend: Backend) { + self.lock().unwrap().set_backend_req_fd(backend) } fn get_inflight_fd(&self, inflight: &VhostUserInflight) -> Result<(VhostUserInflight, File)> { @@ -228,20 +228,20 @@ impl VhostUserSlaveReqHandler for Mutex { } } -/// Server to handle service requests from masters from the master communication channel. +/// Server to handle service requests from frontends from the frontend communication channel. /// -/// The [SlaveReqHandler] acts as a server on the slave side, to handle service requests from -/// masters on the master communication channel. It's actually a proxy invoking the registered -/// handler implementing [VhostUserSlaveReqHandler] to do the real work. +/// The [BackendReqHandler] acts as a server on the backend side, to handle service requests from +/// frontends on the frontend communication channel. It's actually a proxy invoking the registered +/// handler implementing [VhostUserBackendReqHandler] to do the real work. /// -/// The lifetime of the SlaveReqHandler object should be the same as the underline Unix Domain +/// The lifetime of the BackendReqHandler object should be the same as the underline Unix Domain /// Socket, so it gets simpler to recover from disconnect. /// -/// [VhostUserSlaveReqHandler]: trait.VhostUserSlaveReqHandler.html -/// [SlaveReqHandler]: struct.SlaveReqHandler.html -pub struct SlaveReqHandler { +/// [VhostUserBackendReqHandler]: trait.VhostUserBackendReqHandler.html +/// [BackendReqHandler]: struct.BackendReqHandler.html +pub struct BackendReqHandler { // underlying Unix domain socket for communication - main_sock: Endpoint, + main_sock: Endpoint, // the vhost-user backend device object backend: Arc, @@ -256,10 +256,10 @@ pub struct SlaveReqHandler { error: Option, } -impl SlaveReqHandler { - /// Create a vhost-user slave endpoint. - pub(super) fn new(main_sock: Endpoint, backend: Arc) -> Self { - SlaveReqHandler { +impl BackendReqHandler { + /// Create a vhost-user backend endpoint. + pub(super) fn new(main_sock: Endpoint, backend: Arc) -> Self { + BackendReqHandler { main_sock, backend, virtio_features: 0, @@ -287,18 +287,18 @@ impl SlaveReqHandler { } } - /// Create a vhost-user slave endpoint from a connected socket. + /// Create a vhost-user backend endpoint from a connected socket. pub fn from_stream(socket: UnixStream, backend: Arc) -> Self { Self::new(Endpoint::from_stream(socket), backend) } - /// Create a new vhost-user slave endpoint. + /// Create a new vhost-user backend endpoint. /// /// # Arguments /// * - `path` - path of Unix domain socket listener to connect to - /// * - `backend` - handler for requests from the master to the slave + /// * - `backend` - handler for requests from the frontend to the backend pub fn connect(path: &str, backend: Arc) -> Result { - Ok(Self::new(Endpoint::::connect(path)?, backend)) + Ok(Self::new(Endpoint::::connect(path)?, backend)) } /// Mark endpoint as failed with specified error code. @@ -306,9 +306,9 @@ impl SlaveReqHandler { self.error = Some(error); } - /// Main entrance to server slave request from the slave communication channel. + /// Main entrance to server backend request from the backend communication channel. /// - /// Receive and handle one incoming request message from the master. The caller needs to: + /// Receive and handle one incoming request message from the frontend. The caller needs to: /// - serialize calls to this function /// - decide what to do when error happens /// - optional recover from failure @@ -340,17 +340,17 @@ impl SlaveReqHandler { }; match hdr.get_code() { - Ok(MasterReq::SET_OWNER) => { + Ok(FrontendReq::SET_OWNER) => { self.check_request_size(&hdr, size, 0)?; let res = self.backend.set_owner(); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::RESET_OWNER) => { + Ok(FrontendReq::RESET_OWNER) => { self.check_request_size(&hdr, size, 0)?; let res = self.backend.reset_owner(); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::GET_FEATURES) => { + Ok(FrontendReq::GET_FEATURES) => { self.check_request_size(&hdr, size, 0)?; let features = self.backend.get_features()?; let msg = VhostUserU64::new(features); @@ -358,23 +358,23 @@ impl SlaveReqHandler { self.virtio_features = features; self.update_reply_ack_flag(); } - Ok(MasterReq::SET_FEATURES) => { + Ok(FrontendReq::SET_FEATURES) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; let res = self.backend.set_features(msg.value); self.acked_virtio_features = msg.value; self.update_reply_ack_flag(); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_MEM_TABLE) => { + Ok(FrontendReq::SET_MEM_TABLE) => { let res = self.set_mem_table(&hdr, size, &buf, files); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_VRING_NUM) => { + Ok(FrontendReq::SET_VRING_NUM) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; let res = self.backend.set_vring_num(msg.index, msg.num); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_VRING_ADDR) => { + Ok(FrontendReq::SET_VRING_ADDR) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; let flags = match VhostUserVringAddrFlags::from_bits(msg.flags) { Some(val) => val, @@ -390,35 +390,35 @@ impl SlaveReqHandler { ); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_VRING_BASE) => { + Ok(FrontendReq::SET_VRING_BASE) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; let res = self.backend.set_vring_base(msg.index, msg.num); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::GET_VRING_BASE) => { + Ok(FrontendReq::GET_VRING_BASE) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; let reply = self.backend.get_vring_base(msg.index)?; self.send_reply_message(&hdr, &reply)?; } - Ok(MasterReq::SET_VRING_CALL) => { + Ok(FrontendReq::SET_VRING_CALL) => { self.check_request_size(&hdr, size, mem::size_of::())?; let (index, file) = self.handle_vring_fd_request(&buf, files)?; let res = self.backend.set_vring_call(index, file); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_VRING_KICK) => { + Ok(FrontendReq::SET_VRING_KICK) => { self.check_request_size(&hdr, size, mem::size_of::())?; let (index, file) = self.handle_vring_fd_request(&buf, files)?; let res = self.backend.set_vring_kick(index, file); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_VRING_ERR) => { + Ok(FrontendReq::SET_VRING_ERR) => { self.check_request_size(&hdr, size, mem::size_of::())?; let (index, file) = self.handle_vring_fd_request(&buf, files)?; let res = self.backend.set_vring_err(index, file); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::GET_PROTOCOL_FEATURES) => { + Ok(FrontendReq::GET_PROTOCOL_FEATURES) => { self.check_request_size(&hdr, size, 0)?; let features = self.backend.get_protocol_features()?; @@ -431,7 +431,7 @@ impl SlaveReqHandler { self.protocol_features = features; self.update_reply_ack_flag(); } - Ok(MasterReq::SET_PROTOCOL_FEATURES) => { + Ok(FrontendReq::SET_PROTOCOL_FEATURES) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; let res = self.backend.set_protocol_features(msg.value); self.acked_protocol_features = msg.value; @@ -441,14 +441,14 @@ impl SlaveReqHandler { #[cfg(feature = "xen")] self.check_proto_feature(VhostUserProtocolFeatures::XEN_MMAP)?; } - Ok(MasterReq::GET_QUEUE_NUM) => { + Ok(FrontendReq::GET_QUEUE_NUM) => { self.check_proto_feature(VhostUserProtocolFeatures::MQ)?; self.check_request_size(&hdr, size, 0)?; let num = self.backend.get_queue_num()?; let msg = VhostUserU64::new(num); self.send_reply_message(&hdr, &msg)?; } - Ok(MasterReq::SET_VRING_ENABLE) => { + Ok(FrontendReq::SET_VRING_ENABLE) => { let msg = self.extract_request_body::(&hdr, size, &buf)?; self.check_feature(VhostUserVirtioFeatures::PROTOCOL_FEATURES)?; let enable = match msg.num { @@ -460,24 +460,24 @@ impl SlaveReqHandler { let res = self.backend.set_vring_enable(msg.index, enable); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::GET_CONFIG) => { + Ok(FrontendReq::GET_CONFIG) => { self.check_proto_feature(VhostUserProtocolFeatures::CONFIG)?; self.check_request_size(&hdr, size, hdr.get_size() as usize)?; self.get_config(&hdr, &buf)?; } - Ok(MasterReq::SET_CONFIG) => { + Ok(FrontendReq::SET_CONFIG) => { self.check_proto_feature(VhostUserProtocolFeatures::CONFIG)?; self.check_request_size(&hdr, size, hdr.get_size() as usize)?; let res = self.set_config(size, &buf); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::SET_SLAVE_REQ_FD) => { - self.check_proto_feature(VhostUserProtocolFeatures::SLAVE_REQ)?; + Ok(FrontendReq::SET_BACKEND_REQ_FD) => { + self.check_proto_feature(VhostUserProtocolFeatures::BACKEND_REQ)?; self.check_request_size(&hdr, size, hdr.get_size() as usize)?; - let res = self.set_slave_req_fd(files); + let res = self.set_backend_req_fd(files); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::GET_INFLIGHT_FD) => { + Ok(FrontendReq::GET_INFLIGHT_FD) => { self.check_proto_feature(VhostUserProtocolFeatures::INFLIGHT_SHMFD)?; let msg = self.extract_request_body::(&hdr, size, &buf)?; @@ -486,21 +486,21 @@ impl SlaveReqHandler { self.main_sock .send_message(&reply_hdr, &inflight, Some(&[file.as_raw_fd()]))?; } - Ok(MasterReq::SET_INFLIGHT_FD) => { + Ok(FrontendReq::SET_INFLIGHT_FD) => { self.check_proto_feature(VhostUserProtocolFeatures::INFLIGHT_SHMFD)?; let file = take_single_file(files).ok_or(Error::IncorrectFds)?; let msg = self.extract_request_body::(&hdr, size, &buf)?; let res = self.backend.set_inflight_fd(&msg, file); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::GET_MAX_MEM_SLOTS) => { + Ok(FrontendReq::GET_MAX_MEM_SLOTS) => { self.check_proto_feature(VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS)?; self.check_request_size(&hdr, size, 0)?; let num = self.backend.get_max_mem_slots()?; let msg = VhostUserU64::new(num); self.send_reply_message(&hdr, &msg)?; } - Ok(MasterReq::ADD_MEM_REG) => { + Ok(FrontendReq::ADD_MEM_REG) => { self.check_proto_feature(VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS)?; let mut files = files.ok_or(Error::InvalidParam)?; if files.len() != 1 { @@ -511,7 +511,7 @@ impl SlaveReqHandler { let res = self.backend.add_mem_region(&msg, files.swap_remove(0)); self.send_ack_message(&hdr, res)?; } - Ok(MasterReq::REM_MEM_REG) => { + Ok(FrontendReq::REM_MEM_REG) => { self.check_proto_feature(VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS)?; let msg = @@ -528,7 +528,7 @@ impl SlaveReqHandler { fn set_mem_table( &mut self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, size: usize, buf: &[u8], files: Option>, @@ -575,7 +575,7 @@ impl SlaveReqHandler { self.backend.set_mem_table(regions, files) } - fn get_config(&mut self, hdr: &VhostUserMsgHeader, buf: &[u8]) -> Result<()> { + fn get_config(&mut self, hdr: &VhostUserMsgHeader, buf: &[u8]) -> Result<()> { let payload_offset = mem::size_of::(); if buf.len() > MAX_MSG_SIZE || buf.len() < payload_offset { return Err(Error::InvalidMessage); @@ -594,9 +594,9 @@ impl SlaveReqHandler { }; let res = self.backend.get_config(msg.offset, msg.size, flags); - // vhost-user slave's payload size MUST match master's request + // vhost-user backend's payload size MUST match frontend's request // on success, uses zero length of payload to indicate an error - // to vhost-user master. + // to vhost-user frontend. match res { Ok(ref buf) if buf.len() == msg.size as usize => { let reply = VhostUserConfig::new(msg.offset, buf.len() as u32, flags); @@ -632,14 +632,14 @@ impl SlaveReqHandler { .set_config(msg.offset, &buf[mem::size_of::()..], flags) } - fn set_slave_req_fd(&mut self, files: Option>) -> Result<()> { + fn set_backend_req_fd(&mut self, files: Option>) -> Result<()> { let file = take_single_file(files).ok_or(Error::InvalidMessage)?; // SAFETY: Safe because we have ownership of the files that were // checked when received. We have to trust that they are Unix sockets // since we have no way to check this. If not, it will fail later. let sock = unsafe { UnixStream::from_raw_fd(file.into_raw_fd()) }; - let slave = Slave::from_stream(sock); - self.backend.set_slave_req_fd(slave); + let backend = Backend::from_stream(sock); + self.backend.set_backend_req_fd(backend); Ok(()) } @@ -682,7 +682,7 @@ impl SlaveReqHandler { fn check_request_size( &self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, size: usize, expected: usize, ) -> Result<()> { @@ -698,20 +698,20 @@ impl SlaveReqHandler { fn check_attached_files( &self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, files: &Option>, ) -> Result<()> { match hdr.get_code() { Ok( - MasterReq::SET_MEM_TABLE - | MasterReq::SET_VRING_CALL - | MasterReq::SET_VRING_KICK - | MasterReq::SET_VRING_ERR - | MasterReq::SET_LOG_BASE - | MasterReq::SET_LOG_FD - | MasterReq::SET_SLAVE_REQ_FD - | MasterReq::SET_INFLIGHT_FD - | MasterReq::ADD_MEM_REG, + FrontendReq::SET_MEM_TABLE + | FrontendReq::SET_VRING_CALL + | FrontendReq::SET_VRING_KICK + | FrontendReq::SET_VRING_ERR + | FrontendReq::SET_LOG_BASE + | FrontendReq::SET_LOG_FD + | FrontendReq::SET_BACKEND_REQ_FD + | FrontendReq::SET_INFLIGHT_FD + | FrontendReq::ADD_MEM_REG, ) => Ok(()), _ if files.is_some() => Err(Error::InvalidMessage), _ => Ok(()), @@ -720,7 +720,7 @@ impl SlaveReqHandler { fn extract_request_body( &self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, size: usize, buf: &[u8], ) -> Result { @@ -748,9 +748,9 @@ impl SlaveReqHandler { fn new_reply_header( &self, - req: &VhostUserMsgHeader, + req: &VhostUserMsgHeader, payload_size: usize, - ) -> Result> { + ) -> Result> { if mem::size_of::() > MAX_MSG_SIZE || payload_size > MAX_MSG_SIZE || mem::size_of::() + payload_size > MAX_MSG_SIZE @@ -767,7 +767,7 @@ impl SlaveReqHandler { fn send_ack_message( &mut self, - req: &VhostUserMsgHeader, + req: &VhostUserMsgHeader, res: Result<()>, ) -> Result<()> { if self.reply_ack_enabled && req.is_need_reply() { @@ -784,7 +784,7 @@ impl SlaveReqHandler { fn send_reply_message( &mut self, - req: &VhostUserMsgHeader, + req: &VhostUserMsgHeader, msg: &T, ) -> Result<()> { let hdr = self.new_reply_header::(req, 0)?; @@ -794,7 +794,7 @@ impl SlaveReqHandler { fn send_reply_with_payload( &mut self, - req: &VhostUserMsgHeader, + req: &VhostUserMsgHeader, msg: &T, payload: &[u8], ) -> Result<()> { @@ -805,7 +805,7 @@ impl SlaveReqHandler { } } -impl AsRawFd for SlaveReqHandler { +impl AsRawFd for BackendReqHandler { fn as_raw_fd(&self) -> RawFd { self.main_sock.as_raw_fd() } @@ -816,14 +816,14 @@ mod tests { use std::os::unix::io::AsRawFd; use super::*; - use crate::vhost_user::dummy_slave::DummySlaveReqHandler; + use crate::vhost_user::dummy_backend::DummyBackendReqHandler; #[test] - fn test_slave_req_handler_new() { + fn test_backend_req_handler_new() { let (p1, _p2) = UnixStream::pair().unwrap(); - let endpoint = Endpoint::::from_stream(p1); - let backend = Arc::new(Mutex::new(DummySlaveReqHandler::new())); - let mut handler = SlaveReqHandler::new(endpoint, backend); + let endpoint = Endpoint::::from_stream(p1); + let backend = Arc::new(Mutex::new(DummyBackendReqHandler::new())); + let mut handler = BackendReqHandler::new(endpoint, backend); handler.check_state().unwrap(); handler.set_failed(libc::EAGAIN); diff --git a/crates/vhost/src/vhost_user/connection.rs b/crates/vhost/src/vhost_user/connection.rs index 4a62e124..3edda339 100644 --- a/crates/vhost/src/vhost_user/connection.rs +++ b/crates/vhost/src/vhost_user/connection.rs @@ -669,23 +669,23 @@ mod tests { let path = temp_path(); let listener = Listener::new(&path, true).unwrap(); listener.set_nonblocking(true).unwrap(); - let mut master = Endpoint::::connect(&path).unwrap(); + let mut frontend = Endpoint::::connect(&path).unwrap(); let sock = listener.accept().unwrap().unwrap(); - let mut slave = Endpoint::::from_stream(sock); + let mut backend = Endpoint::::from_stream(sock); let buf1 = vec![0x1, 0x2, 0x3, 0x4]; - let mut len = master.send_slice(&buf1[..], None).unwrap(); + let mut len = frontend.send_slice(&buf1[..], None).unwrap(); assert_eq!(len, 4); - let (bytes, buf2, _) = slave.recv_into_buf(0x1000).unwrap(); + let (bytes, buf2, _) = backend.recv_into_buf(0x1000).unwrap(); assert_eq!(bytes, 4); assert_eq!(&buf1[..], &buf2[..bytes]); - len = master.send_slice(&buf1[..], None).unwrap(); + len = frontend.send_slice(&buf1[..], None).unwrap(); assert_eq!(len, 4); - let (bytes, buf2, _) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, _) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[..2], &buf2[..]); - let (bytes, buf2, _) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, _) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[2..], &buf2[..]); } @@ -695,21 +695,21 @@ mod tests { let path = temp_path(); let listener = Listener::new(&path, true).unwrap(); listener.set_nonblocking(true).unwrap(); - let mut master = Endpoint::::connect(&path).unwrap(); + let mut frontend = Endpoint::::connect(&path).unwrap(); let sock = listener.accept().unwrap().unwrap(); - let mut slave = Endpoint::::from_stream(sock); + let mut backend = Endpoint::::from_stream(sock); let mut fd = TempFile::new().unwrap().into_file(); write!(fd, "test").unwrap(); // Normal case for sending/receiving file descriptors let buf1 = vec![0x1, 0x2, 0x3, 0x4]; - let len = master + let len = frontend .send_slice(&buf1[..], Some(&[fd.as_raw_fd()])) .unwrap(); assert_eq!(len, 4); - let (bytes, buf2, files) = slave.recv_into_buf(4).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(4).unwrap(); assert_eq!(bytes, 4); assert_eq!(&buf1[..], &buf2[..]); assert!(files.is_some()); @@ -726,7 +726,7 @@ mod tests { // Following communication pattern should work: // Sending side: data(header, body) with fds // Receiving side: data(header) with fds, data(body) - let len = master + let len = frontend .send_slice( &buf1[..], Some(&[fd.as_raw_fd(), fd.as_raw_fd(), fd.as_raw_fd()]), @@ -734,7 +734,7 @@ mod tests { .unwrap(); assert_eq!(len, 4); - let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[..2], &buf2[..]); assert!(files.is_some()); @@ -747,7 +747,7 @@ mod tests { file.read_to_string(&mut content).unwrap(); assert_eq!(content, "test"); } - let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[2..], &buf2[..]); assert!(files.is_none()); @@ -755,7 +755,7 @@ mod tests { // Following communication pattern should not work: // Sending side: data(header, body) with fds // Receiving side: data(header), data(body) with fds - let len = master + let len = frontend .send_slice( &buf1[..], Some(&[fd.as_raw_fd(), fd.as_raw_fd(), fd.as_raw_fd()]), @@ -763,10 +763,10 @@ mod tests { .unwrap(); assert_eq!(len, 4); - let (bytes, buf4) = slave.recv_data(2).unwrap(); + let (bytes, buf4) = backend.recv_data(2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[..2], &buf4[..]); - let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[2..], &buf2[..]); assert!(files.is_none()); @@ -774,9 +774,9 @@ mod tests { // Following communication pattern should work: // Sending side: data, data with fds // Receiving side: data, data with fds - let len = master.send_slice(&buf1[..], None).unwrap(); + let len = frontend.send_slice(&buf1[..], None).unwrap(); assert_eq!(len, 4); - let len = master + let len = frontend .send_slice( &buf1[..], Some(&[fd.as_raw_fd(), fd.as_raw_fd(), fd.as_raw_fd()]), @@ -784,12 +784,12 @@ mod tests { .unwrap(); assert_eq!(len, 4); - let (bytes, buf2, files) = slave.recv_into_buf(0x4).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(0x4).unwrap(); assert_eq!(bytes, 4); assert_eq!(&buf1[..], &buf2[..]); assert!(files.is_none()); - let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[..2], &buf2[..]); assert!(files.is_some()); @@ -802,7 +802,7 @@ mod tests { file.read_to_string(&mut content).unwrap(); assert_eq!(content, "test"); } - let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap(); + let (bytes, buf2, files) = backend.recv_into_buf(0x2).unwrap(); assert_eq!(bytes, 2); assert_eq!(&buf1[2..], &buf2[..]); assert!(files.is_none()); @@ -810,9 +810,9 @@ mod tests { // Following communication pattern should not work: // Sending side: data1, data2 with fds // Receiving side: data + partial of data2, left of data2 with fds - let len = master.send_slice(&buf1[..], None).unwrap(); + let len = frontend.send_slice(&buf1[..], None).unwrap(); assert_eq!(len, 4); - let len = master + let len = frontend .send_slice( &buf1[..], Some(&[fd.as_raw_fd(), fd.as_raw_fd(), fd.as_raw_fd()]), @@ -820,15 +820,15 @@ mod tests { .unwrap(); assert_eq!(len, 4); - let (bytes, _) = slave.recv_data(5).unwrap(); + let (bytes, _) = backend.recv_data(5).unwrap(); assert_eq!(bytes, 5); - let (bytes, _, files) = slave.recv_into_buf(0x4).unwrap(); + let (bytes, _, files) = backend.recv_into_buf(0x4).unwrap(); assert_eq!(bytes, 3); assert!(files.is_none()); // If the target fd array is too small, extra file descriptors will get lost. - let len = master + let len = frontend .send_slice( &buf1[..], Some(&[fd.as_raw_fd(), fd.as_raw_fd(), fd.as_raw_fd()]), @@ -836,7 +836,7 @@ mod tests { .unwrap(); assert_eq!(len, 4); - let (bytes, _, files) = slave.recv_into_buf(0x4).unwrap(); + let (bytes, _, files) = backend.recv_into_buf(0x4).unwrap(); assert_eq!(bytes, 4); assert!(files.is_some()); } @@ -846,15 +846,15 @@ mod tests { let path = temp_path(); let listener = Listener::new(&path, true).unwrap(); listener.set_nonblocking(true).unwrap(); - let mut master = Endpoint::::connect(&path).unwrap(); + let mut frontend = Endpoint::::connect(&path).unwrap(); let sock = listener.accept().unwrap().unwrap(); - let mut slave = Endpoint::::from_stream(sock); + let mut backend = Endpoint::::from_stream(sock); let mut hdr1 = - VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0, mem::size_of::() as u32); + VhostUserMsgHeader::new(FrontendReq::GET_FEATURES, 0, mem::size_of::() as u32); hdr1.set_need_reply(true); let features1 = 0x1u64; - master.send_message(&hdr1, &features1, None).unwrap(); + frontend.send_message(&hdr1, &features1, None).unwrap(); let mut features2 = 0u64; @@ -865,14 +865,14 @@ mod tests { mem::size_of::(), ) }; - let (hdr2, bytes, files) = slave.recv_body_into_buf(slice).unwrap(); + let (hdr2, bytes, files) = backend.recv_body_into_buf(slice).unwrap(); assert_eq!(hdr1, hdr2); assert_eq!(bytes, 8); assert_eq!(features1, features2); assert!(files.is_none()); - master.send_header(&hdr1, None).unwrap(); - let (hdr2, files) = slave.recv_header().unwrap(); + frontend.send_header(&hdr1, None).unwrap(); + let (hdr2, files) = backend.recv_header().unwrap(); assert_eq!(hdr1, hdr2); assert!(files.is_none()); } @@ -881,13 +881,13 @@ mod tests { fn partial_message() { let path = temp_path(); let listener = Listener::new(&path, true).unwrap(); - let mut master = UnixStream::connect(&path).unwrap(); + let mut frontend = UnixStream::connect(&path).unwrap(); let sock = listener.accept().unwrap().unwrap(); - let mut slave = Endpoint::::from_stream(sock); + let mut backend = Endpoint::::from_stream(sock); - write!(master, "a").unwrap(); - drop(master); - assert!(matches!(slave.recv_header(), Err(Error::PartialMessage))); + write!(frontend, "a").unwrap(); + drop(frontend); + assert!(matches!(backend.recv_header(), Err(Error::PartialMessage))); } #[test] @@ -896,8 +896,8 @@ mod tests { let listener = Listener::new(&path, true).unwrap(); let _ = UnixStream::connect(&path).unwrap(); let sock = listener.accept().unwrap().unwrap(); - let mut slave = Endpoint::::from_stream(sock); + let mut backend = Endpoint::::from_stream(sock); - assert!(matches!(slave.recv_header(), Err(Error::Disconnected))); + assert!(matches!(backend.recv_header(), Err(Error::Disconnected))); } } diff --git a/crates/vhost/src/vhost_user/dummy_slave.rs b/crates/vhost/src/vhost_user/dummy_backend.rs similarity index 96% rename from crates/vhost/src/vhost_user/dummy_slave.rs rename to crates/vhost/src/vhost_user/dummy_backend.rs index ae728a02..060a3441 100644 --- a/crates/vhost/src/vhost_user/dummy_slave.rs +++ b/crates/vhost/src/vhost_user/dummy_backend.rs @@ -12,7 +12,7 @@ pub const MAX_MEM_SLOTS: usize = 32; pub const VIRTIO_FEATURES: u64 = 0x40000003; #[derive(Default)] -pub struct DummySlaveReqHandler { +pub struct DummyBackendReqHandler { pub owned: bool, pub features_acked: bool, pub acked_features: u64, @@ -28,9 +28,9 @@ pub struct DummySlaveReqHandler { pub inflight_file: Option, } -impl DummySlaveReqHandler { +impl DummyBackendReqHandler { pub fn new() -> Self { - DummySlaveReqHandler { + DummyBackendReqHandler { queue_num: MAX_QUEUE_NUM, ..Default::default() } @@ -55,7 +55,7 @@ impl DummySlaveReqHandler { } } -impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler { +impl VhostUserBackendReqHandlerMut for DummyBackendReqHandler { fn set_owner(&mut self) -> Result<()> { if self.owned { return Err(Error::InvalidOperation("already claimed")); @@ -193,10 +193,10 @@ impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler { } fn set_protocol_features(&mut self, features: u64) -> Result<()> { - // Note: slave that reported VHOST_USER_F_PROTOCOL_FEATURES must + // Note: backend that reported VHOST_USER_F_PROTOCOL_FEATURES must // support this message even before VHOST_USER_SET_FEATURES was // called. - // What happens if the master calls set_features() with + // What happens if the frontend calls set_features() with // VHOST_USER_F_PROTOCOL_FEATURES cleared after calling this // interface? self.acked_protocol_features = features; @@ -216,7 +216,7 @@ impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler { return Err(Error::InvalidParam); } - // Slave must not pass data to/from the backend until ring is + // Backend must not pass data to/from the backend until ring is // enabled by VHOST_USER_SET_VRING_ENABLE with parameter 1, // or after it has been disabled by VHOST_USER_SET_VRING_ENABLE // with parameter 0. diff --git a/crates/vhost/src/vhost_user/master.rs b/crates/vhost/src/vhost_user/frontend.rs similarity index 77% rename from crates/vhost/src/vhost_user/master.rs rename to crates/vhost/src/vhost_user/frontend.rs index 030e8947..af2f2bbd 100644 --- a/crates/vhost/src/vhost_user/master.rs +++ b/crates/vhost/src/vhost_user/frontend.rs @@ -1,7 +1,7 @@ // Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -//! Traits and Struct for vhost-user master. +//! Traits and Struct for vhost-user frontend. use std::fs::File; use std::mem; @@ -21,8 +21,8 @@ use crate::backend::{ }; use crate::{Error, Result}; -/// Trait for vhost-user master to provide extra methods not covered by the VhostBackend yet. -pub trait VhostUserMaster: VhostBackend { +/// Trait for vhost-user frontend to provide extra methods not covered by the VhostBackend yet. +pub trait VhostUserFrontend: VhostBackend { /// Get the protocol feature bitmask from the underlying vhost implementation. fn get_protocol_features(&mut self) -> Result; @@ -32,9 +32,9 @@ pub trait VhostUserMaster: VhostBackend { /// Query how many queues the backend supports. fn get_queue_num(&mut self) -> Result; - /// Signal slave to enable or disable corresponding vring. + /// Signal backend to enable or disable corresponding vring. /// - /// Slave must not pass data to/from the backend until ring is enabled by + /// Backend must not pass data to/from the backend until ring is enabled by /// VHOST_USER_SET_VRING_ENABLE with parameter 1, or after it has been /// disabled by VHOST_USER_SET_VRING_ENABLE with parameter 0. fn set_vring_enable(&mut self, queue_index: usize, enable: bool) -> Result<()>; @@ -52,8 +52,8 @@ pub trait VhostUserMaster: VhostBackend { /// destination host to set readonly configuration space fields. fn set_config(&mut self, offset: u32, flags: VhostUserConfigFlags, buf: &[u8]) -> Result<()>; - /// Setup slave communication channel. - fn set_slave_request_fd(&mut self, fd: &dyn AsRawFd) -> Result<()>; + /// Setup backend communication channel. + fn set_backend_request_fd(&mut self, fd: &dyn AsRawFd) -> Result<()>; /// Retrieve shared buffer for inflight I/O tracking. fn get_inflight_fd( @@ -78,17 +78,17 @@ fn error_code(err: VhostUserError) -> Result { Err(Error::VhostUserProtocol(err)) } -/// Struct for the vhost-user master endpoint. +/// Struct for the vhost-user frontend endpoint. #[derive(Clone)] -pub struct Master { - node: Arc>, +pub struct Frontend { + node: Arc>, } -impl Master { +impl Frontend { /// Create a new instance. - fn new(ep: Endpoint, max_queue_num: u64) -> Self { - Master { - node: Arc::new(Mutex::new(MasterInternal { + fn new(ep: Endpoint, max_queue_num: u64) -> Self { + Frontend { + node: Arc::new(Mutex::new(FrontendInternal { main_sock: ep, virtio_features: 0, acked_virtio_features: 0, @@ -102,16 +102,16 @@ impl Master { } } - fn node(&self) -> MutexGuard { + fn node(&self) -> MutexGuard { self.node.lock().unwrap() } /// Create a new instance from a Unix stream socket. pub fn from_stream(sock: UnixStream, max_queue_num: u64) -> Self { - Self::new(Endpoint::::from_stream(sock), max_queue_num) + Self::new(Endpoint::::from_stream(sock), max_queue_num) } - /// Create a new vhost-user master endpoint. + /// Create a new vhost-user frontend endpoint. /// /// Will retry as the backend may not be ready to accept the connection. /// @@ -120,7 +120,7 @@ impl Master { pub fn connect>(path: P, max_queue_num: u64) -> Result { let mut retry_count = 5; let endpoint = loop { - match Endpoint::::connect(&path) { + match Endpoint::::connect(&path) { Ok(endpoint) => break Ok(endpoint), Err(e) => match &e { VhostUserError::SocketConnect(why) => { @@ -147,11 +147,11 @@ impl Master { } } -impl VhostBackend for Master { +impl VhostBackend for Frontend { /// Get from the underlying vhost implementation the feature bitmask. fn get_features(&self) -> Result { let mut node = self.node(); - let hdr = node.send_request_header(MasterReq::GET_FEATURES, None)?; + let hdr = node.send_request_header(FrontendReq::GET_FEATURES, None)?; let val = node.recv_reply::(&hdr)?; node.virtio_features = val.value; Ok(node.virtio_features) @@ -161,27 +161,27 @@ impl VhostBackend for Master { fn set_features(&self, features: u64) -> Result<()> { let mut node = self.node(); let val = VhostUserU64::new(features); - let hdr = node.send_request_with_body(MasterReq::SET_FEATURES, &val, None)?; + let hdr = node.send_request_with_body(FrontendReq::SET_FEATURES, &val, None)?; node.acked_virtio_features = features & node.virtio_features; node.wait_for_ack(&hdr).map_err(|e| e.into()) } - /// Set the current Master as an owner of the session. + /// Set the current Frontend as an owner of the session. fn set_owner(&self) -> Result<()> { // We unwrap() the return value to assert that we are not expecting threads to ever fail // while holding the lock. let mut node = self.node(); - let hdr = node.send_request_header(MasterReq::SET_OWNER, None)?; + let hdr = node.send_request_header(FrontendReq::SET_OWNER, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } fn reset_owner(&self) -> Result<()> { let mut node = self.node(); - let hdr = node.send_request_header(MasterReq::RESET_OWNER, None)?; + let hdr = node.send_request_header(FrontendReq::RESET_OWNER, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } - /// Set the memory map regions on the slave so it can translate the vring + /// Set the memory map regions on the backend so it can translate the vring /// addresses. In the ancillary data there is an array of file descriptors fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> { if regions.is_empty() || regions.len() > MAX_ATTACHED_FD_ENTRIES { @@ -202,7 +202,7 @@ impl VhostBackend for Master { // SAFETY: Safe because ctx.regions is a valid Vec() at this point. let (_, payload, _) = unsafe { ctx.regions.align_to::() }; let hdr = node.send_request_with_payload( - MasterReq::SET_MEM_TABLE, + FrontendReq::SET_MEM_TABLE, &body, payload, Some(ctx.fds.as_slice()), @@ -225,13 +225,13 @@ impl VhostBackend for Master { mmap_offset: region.mmap_offset, }; let hdr = node.send_request_with_body( - MasterReq::SET_LOG_BASE, + FrontendReq::SET_LOG_BASE, &log, Some(&[region.mmap_handle]), )?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } else { - let _ = node.send_request_with_body(MasterReq::SET_LOG_BASE, &val, None)?; + let _ = node.send_request_with_body(FrontendReq::SET_LOG_BASE, &val, None)?; Ok(()) } } @@ -239,7 +239,7 @@ impl VhostBackend for Master { fn set_log_fd(&self, fd: RawFd) -> Result<()> { let mut node = self.node(); let fds = [fd]; - let hdr = node.send_request_header(MasterReq::SET_LOG_FD, Some(&fds))?; + let hdr = node.send_request_header(FrontendReq::SET_LOG_FD, Some(&fds))?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -251,7 +251,7 @@ impl VhostBackend for Master { } let val = VhostUserVringState::new(queue_index as u32, num.into()); - let hdr = node.send_request_with_body(MasterReq::SET_VRING_NUM, &val, None)?; + let hdr = node.send_request_with_body(FrontendReq::SET_VRING_NUM, &val, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -265,7 +265,7 @@ impl VhostBackend for Master { } let val = VhostUserVringAddr::from_config_data(queue_index as u32, config_data); - let hdr = node.send_request_with_body(MasterReq::SET_VRING_ADDR, &val, None)?; + let hdr = node.send_request_with_body(FrontendReq::SET_VRING_ADDR, &val, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -277,7 +277,7 @@ impl VhostBackend for Master { } let val = VhostUserVringState::new(queue_index as u32, base.into()); - let hdr = node.send_request_with_body(MasterReq::SET_VRING_BASE, &val, None)?; + let hdr = node.send_request_with_body(FrontendReq::SET_VRING_BASE, &val, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -288,7 +288,7 @@ impl VhostBackend for Master { } let req = VhostUserVringState::new(queue_index as u32, 0); - let hdr = node.send_request_with_body(MasterReq::GET_VRING_BASE, &req, None)?; + let hdr = node.send_request_with_body(FrontendReq::GET_VRING_BASE, &req, None)?; let reply = node.recv_reply::(&hdr)?; Ok(reply.num) } @@ -302,7 +302,8 @@ impl VhostBackend for Master { if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } - let hdr = node.send_fd_for_vring(MasterReq::SET_VRING_CALL, queue_index, fd.as_raw_fd())?; + let hdr = + node.send_fd_for_vring(FrontendReq::SET_VRING_CALL, queue_index, fd.as_raw_fd())?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -315,7 +316,8 @@ impl VhostBackend for Master { if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } - let hdr = node.send_fd_for_vring(MasterReq::SET_VRING_KICK, queue_index, fd.as_raw_fd())?; + let hdr = + node.send_fd_for_vring(FrontendReq::SET_VRING_KICK, queue_index, fd.as_raw_fd())?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -327,16 +329,17 @@ impl VhostBackend for Master { if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } - let hdr = node.send_fd_for_vring(MasterReq::SET_VRING_ERR, queue_index, fd.as_raw_fd())?; + let hdr = + node.send_fd_for_vring(FrontendReq::SET_VRING_ERR, queue_index, fd.as_raw_fd())?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } } -impl VhostUserMaster for Master { +impl VhostUserFrontend for Frontend { fn get_protocol_features(&mut self) -> Result { let mut node = self.node(); node.check_feature(VhostUserVirtioFeatures::PROTOCOL_FEATURES)?; - let hdr = node.send_request_header(MasterReq::GET_PROTOCOL_FEATURES, None)?; + let hdr = node.send_request_header(FrontendReq::GET_PROTOCOL_FEATURES, None)?; let val = node.recv_reply::(&hdr)?; node.protocol_features = val.value; // Should we support forward compatibility? @@ -351,7 +354,7 @@ impl VhostUserMaster for Master { let mut node = self.node(); node.check_feature(VhostUserVirtioFeatures::PROTOCOL_FEATURES)?; let val = VhostUserU64::new(features.bits()); - let hdr = node.send_request_with_body(MasterReq::SET_PROTOCOL_FEATURES, &val, None)?; + let hdr = node.send_request_with_body(FrontendReq::SET_PROTOCOL_FEATURES, &val, None)?; // Don't wait for ACK here because the protocol feature negotiation process hasn't been // completed yet. node.acked_protocol_features = features.bits(); @@ -363,7 +366,7 @@ impl VhostUserMaster for Master { let mut node = self.node(); node.check_proto_feature(VhostUserProtocolFeatures::MQ)?; - let hdr = node.send_request_header(MasterReq::GET_QUEUE_NUM, None)?; + let hdr = node.send_request_header(FrontendReq::GET_QUEUE_NUM, None)?; let val = node.recv_reply::(&hdr)?; if val.value > VHOST_USER_MAX_VRINGS { return error_code(VhostUserError::InvalidMessage); @@ -385,7 +388,7 @@ impl VhostUserMaster for Master { let flag = enable.into(); let val = VhostUserVringState::new(queue_index as u32, flag); - let hdr = node.send_request_with_body(MasterReq::SET_VRING_ENABLE, &val, None)?; + let hdr = node.send_request_with_body(FrontendReq::SET_VRING_ENABLE, &val, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -406,15 +409,15 @@ impl VhostUserMaster for Master { node.check_proto_feature(VhostUserProtocolFeatures::CONFIG)?; // vhost-user spec states that: - // "Master payload: virtio device config space" - // "Slave payload: virtio device config space" - let hdr = node.send_request_with_payload(MasterReq::GET_CONFIG, &body, buf, None)?; + // "Frontend payload: virtio device config space" + // "Backend payload: virtio device config space" + let hdr = node.send_request_with_payload(FrontendReq::GET_CONFIG, &body, buf, None)?; let (body_reply, buf_reply, rfds) = node.recv_reply_with_payload::(&hdr)?; if rfds.is_some() { return error_code(VhostUserError::InvalidMessage); } else if body_reply.size == 0 { - return error_code(VhostUserError::SlaveInternalError); + return error_code(VhostUserError::BackendInternalError); } else if body_reply.size != body.size || body_reply.size as usize != buf.len() || body_reply.offset != body.offset @@ -438,15 +441,15 @@ impl VhostUserMaster for Master { // depends on VhostUserProtocolFeatures::CONFIG node.check_proto_feature(VhostUserProtocolFeatures::CONFIG)?; - let hdr = node.send_request_with_payload(MasterReq::SET_CONFIG, &body, buf, None)?; + let hdr = node.send_request_with_payload(FrontendReq::SET_CONFIG, &body, buf, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } - fn set_slave_request_fd(&mut self, fd: &dyn AsRawFd) -> Result<()> { + fn set_backend_request_fd(&mut self, fd: &dyn AsRawFd) -> Result<()> { let mut node = self.node(); - node.check_proto_feature(VhostUserProtocolFeatures::SLAVE_REQ)?; + node.check_proto_feature(VhostUserProtocolFeatures::BACKEND_REQ)?; let fds = [fd.as_raw_fd()]; - let hdr = node.send_request_header(MasterReq::SET_SLAVE_REQ_FD, Some(&fds))?; + let hdr = node.send_request_header(FrontendReq::SET_BACKEND_REQ_FD, Some(&fds))?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -457,7 +460,7 @@ impl VhostUserMaster for Master { let mut node = self.node(); node.check_proto_feature(VhostUserProtocolFeatures::INFLIGHT_SHMFD)?; - let hdr = node.send_request_with_body(MasterReq::GET_INFLIGHT_FD, inflight, None)?; + let hdr = node.send_request_with_body(FrontendReq::GET_INFLIGHT_FD, inflight, None)?; let (inflight, files) = node.recv_reply_with_files::(&hdr)?; match take_single_file(files) { @@ -475,7 +478,8 @@ impl VhostUserMaster for Master { return error_code(VhostUserError::InvalidParam); } - let hdr = node.send_request_with_body(MasterReq::SET_INFLIGHT_FD, inflight, Some(&[fd]))?; + let hdr = + node.send_request_with_body(FrontendReq::SET_INFLIGHT_FD, inflight, Some(&[fd]))?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -483,7 +487,7 @@ impl VhostUserMaster for Master { let mut node = self.node(); node.check_proto_feature(VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS)?; - let hdr = node.send_request_header(MasterReq::GET_MAX_MEM_SLOTS, None)?; + let hdr = node.send_request_header(FrontendReq::GET_MAX_MEM_SLOTS, None)?; let val = node.recv_reply::(&hdr)?; Ok(val.value) @@ -498,7 +502,7 @@ impl VhostUserMaster for Master { let body = region.to_single_region(); let fds = [region.mmap_handle]; - let hdr = node.send_request_with_body(MasterReq::ADD_MEM_REG, &body, Some(&fds))?; + let hdr = node.send_request_with_body(FrontendReq::ADD_MEM_REG, &body, Some(&fds))?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } @@ -510,19 +514,19 @@ impl VhostUserMaster for Master { } let body = region.to_single_region(); - let hdr = node.send_request_with_body(MasterReq::REM_MEM_REG, &body, None)?; + let hdr = node.send_request_with_body(FrontendReq::REM_MEM_REG, &body, None)?; node.wait_for_ack(&hdr).map_err(|e| e.into()) } } -impl AsRawFd for Master { +impl AsRawFd for Frontend { fn as_raw_fd(&self) -> RawFd { let node = self.node(); node.main_sock.as_raw_fd() } } -/// Context object to pass guest memory configuration to VhostUserMaster::set_mem_table(). +/// Context object to pass guest memory configuration to VhostUserFrontend::set_mem_table(). struct VhostUserMemoryContext { regions: VhostUserMemoryPayload, fds: Vec, @@ -544,20 +548,20 @@ impl VhostUserMemoryContext { } } -struct MasterInternal { - // Used to send requests to the slave. - main_sock: Endpoint, - // Cached virtio features from the slave. +struct FrontendInternal { + // Used to send requests to the backend. + main_sock: Endpoint, + // Cached virtio features from the backend. virtio_features: u64, // Cached acked virtio features from the driver. acked_virtio_features: u64, - // Cached vhost-user protocol features from the slave. + // Cached vhost-user protocol features from the backend. protocol_features: u64, // Cached vhost-user protocol features. acked_protocol_features: u64, // Cached vhost-user protocol features are ready to use. protocol_features_ready: bool, - // Cached maxinum number of queues supported from the slave. + // Cached maxinum number of queues supported from the backend. max_queue_num: u64, // Internal flag to mark failure state. error: Option, @@ -565,12 +569,12 @@ struct MasterInternal { hdr_flags: VhostUserHeaderFlag, } -impl MasterInternal { +impl FrontendInternal { fn send_request_header( &mut self, - code: MasterReq, + code: FrontendReq, fds: Option<&[RawFd]>, - ) -> VhostUserResult> { + ) -> VhostUserResult> { self.check_state()?; let hdr = self.new_request_header(code, 0); self.main_sock.send_header(&hdr, fds)?; @@ -579,10 +583,10 @@ impl MasterInternal { fn send_request_with_body( &mut self, - code: MasterReq, + code: FrontendReq, msg: &T, fds: Option<&[RawFd]>, - ) -> VhostUserResult> { + ) -> VhostUserResult> { if mem::size_of::() > MAX_MSG_SIZE { return Err(VhostUserError::InvalidParam); } @@ -595,11 +599,11 @@ impl MasterInternal { fn send_request_with_payload( &mut self, - code: MasterReq, + code: FrontendReq, msg: &T, payload: &[u8], fds: Option<&[RawFd]>, - ) -> VhostUserResult> { + ) -> VhostUserResult> { let len = mem::size_of::() + payload.len(); if len > MAX_MSG_SIZE { return Err(VhostUserError::InvalidParam); @@ -619,10 +623,10 @@ impl MasterInternal { fn send_fd_for_vring( &mut self, - code: MasterReq, + code: FrontendReq, queue_index: usize, fd: RawFd, - ) -> VhostUserResult> { + ) -> VhostUserResult> { if queue_index as u64 >= self.max_queue_num { return Err(VhostUserError::InvalidParam); } @@ -639,7 +643,7 @@ impl MasterInternal { fn recv_reply( &mut self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, ) -> VhostUserResult { if mem::size_of::() > MAX_MSG_SIZE || hdr.is_reply() { return Err(VhostUserError::InvalidParam); @@ -655,7 +659,7 @@ impl MasterInternal { fn recv_reply_with_files( &mut self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, ) -> VhostUserResult<(T, Option>)> { if mem::size_of::() > MAX_MSG_SIZE || hdr.is_reply() { return Err(VhostUserError::InvalidParam); @@ -671,7 +675,7 @@ impl MasterInternal { fn recv_reply_with_payload( &mut self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, ) -> VhostUserResult<(T, Vec, Option>)> { if mem::size_of::() > MAX_MSG_SIZE || hdr.get_size() as usize <= mem::size_of::() @@ -696,7 +700,7 @@ impl MasterInternal { Ok((body, buf, files)) } - fn wait_for_ack(&mut self, hdr: &VhostUserMsgHeader) -> VhostUserResult<()> { + fn wait_for_ack(&mut self, hdr: &VhostUserMsgHeader) -> VhostUserResult<()> { if self.acked_protocol_features & VhostUserProtocolFeatures::REPLY_ACK.bits() == 0 || !hdr.is_need_reply() { @@ -709,7 +713,7 @@ impl MasterInternal { return Err(VhostUserError::InvalidMessage); } if body.value != 0 { - return Err(VhostUserError::SlaveInternalError); + return Err(VhostUserError::BackendInternalError); } Ok(()) } @@ -740,7 +744,11 @@ impl MasterInternal { } #[inline] - fn new_request_header(&self, request: MasterReq, size: u32) -> VhostUserMsgHeader { + fn new_request_header( + &self, + request: FrontendReq, + size: u32, + ) -> VhostUserMsgHeader { VhostUserMsgHeader::new(request, self.hdr_flags.bits() | 0x1, size) } } @@ -760,36 +768,36 @@ mod tests { )) } - fn create_pair>(path: P) -> (Master, Endpoint) { + fn create_pair>(path: P) -> (Frontend, Endpoint) { let listener = Listener::new(&path, true).unwrap(); listener.set_nonblocking(true).unwrap(); - let master = Master::connect(path, 2).unwrap(); - let slave = listener.accept().unwrap().unwrap(); - (master, Endpoint::from_stream(slave)) + let frontend = Frontend::connect(path, 2).unwrap(); + let backend = listener.accept().unwrap().unwrap(); + (frontend, Endpoint::from_stream(backend)) } #[test] - fn create_master() { + fn create_frontend() { let path = temp_path(); let listener = Listener::new(&path, true).unwrap(); listener.set_nonblocking(true).unwrap(); - let master = Master::connect(&path, 1).unwrap(); - let mut slave = Endpoint::::from_stream(listener.accept().unwrap().unwrap()); + let frontend = Frontend::connect(&path, 1).unwrap(); + let mut backend = Endpoint::::from_stream(listener.accept().unwrap().unwrap()); - assert!(master.as_raw_fd() > 0); + assert!(frontend.as_raw_fd() > 0); // Send two messages continuously - master.set_owner().unwrap(); - master.reset_owner().unwrap(); + frontend.set_owner().unwrap(); + frontend.reset_owner().unwrap(); - let (hdr, rfds) = slave.recv_header().unwrap(); - assert_eq!(hdr.get_code().unwrap(), MasterReq::SET_OWNER); + let (hdr, rfds) = backend.recv_header().unwrap(); + assert_eq!(hdr.get_code().unwrap(), FrontendReq::SET_OWNER); assert_eq!(hdr.get_size(), 0); assert_eq!(hdr.get_version(), 0x1); assert!(rfds.is_none()); - let (hdr, rfds) = slave.recv_header().unwrap(); - assert_eq!(hdr.get_code().unwrap(), MasterReq::RESET_OWNER); + let (hdr, rfds) = backend.recv_header().unwrap(); + assert_eq!(hdr.get_code().unwrap(), FrontendReq::RESET_OWNER); assert_eq!(hdr.get_size(), 0); assert_eq!(hdr.get_version(), 0x1); assert!(rfds.is_none()); @@ -800,134 +808,134 @@ mod tests { let path = temp_path(); let _ = Listener::new(&path, true).unwrap(); let _ = Listener::new(&path, false).is_err(); - assert!(Master::connect(&path, 1).is_err()); + assert!(Frontend::connect(&path, 1).is_err()); let listener = Listener::new(&path, true).unwrap(); assert!(Listener::new(&path, false).is_err()); listener.set_nonblocking(true).unwrap(); - let _master = Master::connect(&path, 1).unwrap(); - let _slave = listener.accept().unwrap().unwrap(); + let _frontend = Frontend::connect(&path, 1).unwrap(); + let _backend = listener.accept().unwrap().unwrap(); } #[test] fn test_features() { let path = temp_path(); - let (master, mut peer) = create_pair(path); + let (frontend, mut peer) = create_pair(path); - master.set_owner().unwrap(); + frontend.set_owner().unwrap(); let (hdr, rfds) = peer.recv_header().unwrap(); - assert_eq!(hdr.get_code().unwrap(), MasterReq::SET_OWNER); + assert_eq!(hdr.get_code().unwrap(), FrontendReq::SET_OWNER); assert_eq!(hdr.get_size(), 0); assert_eq!(hdr.get_version(), 0x1); assert!(rfds.is_none()); - let hdr = VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0x4, 8); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_FEATURES, 0x4, 8); let msg = VhostUserU64::new(0x15); peer.send_message(&hdr, &msg, None).unwrap(); - let features = master.get_features().unwrap(); + let features = frontend.get_features().unwrap(); assert_eq!(features, 0x15u64); let (_hdr, rfds) = peer.recv_header().unwrap(); assert!(rfds.is_none()); - let hdr = VhostUserMsgHeader::new(MasterReq::SET_FEATURES, 0x4, 8); + let hdr = VhostUserMsgHeader::new(FrontendReq::SET_FEATURES, 0x4, 8); let msg = VhostUserU64::new(0x15); peer.send_message(&hdr, &msg, None).unwrap(); - master.set_features(0x15).unwrap(); + frontend.set_features(0x15).unwrap(); let (_hdr, msg, rfds) = peer.recv_body::().unwrap(); assert!(rfds.is_none()); let val = msg.value; assert_eq!(val, 0x15); - let hdr = VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0x4, 8); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_FEATURES, 0x4, 8); let msg = 0x15u32; peer.send_message(&hdr, &msg, None).unwrap(); - assert!(master.get_features().is_err()); + assert!(frontend.get_features().is_err()); } #[test] fn test_protocol_features() { let path = temp_path(); - let (mut master, mut peer) = create_pair(path); + let (mut frontend, mut peer) = create_pair(path); - master.set_owner().unwrap(); + frontend.set_owner().unwrap(); let (hdr, rfds) = peer.recv_header().unwrap(); - assert_eq!(hdr.get_code().unwrap(), MasterReq::SET_OWNER); + assert_eq!(hdr.get_code().unwrap(), FrontendReq::SET_OWNER); assert!(rfds.is_none()); - assert!(master.get_protocol_features().is_err()); - assert!(master + assert!(frontend.get_protocol_features().is_err()); + assert!(frontend .set_protocol_features(VhostUserProtocolFeatures::all()) .is_err()); let vfeatures = 0x15 | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(); - let hdr = VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0x4, 8); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_FEATURES, 0x4, 8); let msg = VhostUserU64::new(vfeatures); peer.send_message(&hdr, &msg, None).unwrap(); - let features = master.get_features().unwrap(); + let features = frontend.get_features().unwrap(); assert_eq!(features, vfeatures); let (_hdr, rfds) = peer.recv_header().unwrap(); assert!(rfds.is_none()); - master.set_features(vfeatures).unwrap(); + frontend.set_features(vfeatures).unwrap(); let (_hdr, msg, rfds) = peer.recv_body::().unwrap(); assert!(rfds.is_none()); let val = msg.value; assert_eq!(val, vfeatures); let pfeatures = VhostUserProtocolFeatures::all(); - let hdr = VhostUserMsgHeader::new(MasterReq::GET_PROTOCOL_FEATURES, 0x4, 8); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_PROTOCOL_FEATURES, 0x4, 8); let msg = VhostUserU64::new(pfeatures.bits()); peer.send_message(&hdr, &msg, None).unwrap(); - let features = master.get_protocol_features().unwrap(); + let features = frontend.get_protocol_features().unwrap(); assert_eq!(features, pfeatures); let (_hdr, rfds) = peer.recv_header().unwrap(); assert!(rfds.is_none()); - master.set_protocol_features(pfeatures).unwrap(); + frontend.set_protocol_features(pfeatures).unwrap(); let (_hdr, msg, rfds) = peer.recv_body::().unwrap(); assert!(rfds.is_none()); let val = msg.value; assert_eq!(val, pfeatures.bits()); - let hdr = VhostUserMsgHeader::new(MasterReq::SET_PROTOCOL_FEATURES, 0x4, 8); + let hdr = VhostUserMsgHeader::new(FrontendReq::SET_PROTOCOL_FEATURES, 0x4, 8); let msg = VhostUserU64::new(pfeatures.bits()); peer.send_message(&hdr, &msg, None).unwrap(); - assert!(master.get_protocol_features().is_err()); + assert!(frontend.get_protocol_features().is_err()); } #[test] - fn test_master_set_config_negative() { + fn test_frontend_set_config_negative() { let path = temp_path(); - let (mut master, _peer) = create_pair(path); + let (mut frontend, _peer) = create_pair(path); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - master + frontend .set_config(0x100, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .unwrap_err(); { - let mut node = master.node(); + let mut node = frontend.node(); node.virtio_features = 0xffff_ffff; node.acked_virtio_features = 0xffff_ffff; node.protocol_features = 0xffff_ffff; node.acked_protocol_features = 0xffff_ffff; } - master + frontend .set_config(0, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .unwrap(); - master + frontend .set_config( VHOST_USER_CONFIG_SIZE, VhostUserConfigFlags::WRITABLE, &buf[0..4], ) .unwrap_err(); - master + frontend .set_config(0x1000, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .unwrap_err(); - master + frontend .set_config( 0x100, // SAFETY: This is a negative test, so we are setting unexpected flags. @@ -935,176 +943,176 @@ mod tests { &buf[0..4], ) .unwrap_err(); - master + frontend .set_config(VHOST_USER_CONFIG_SIZE, VhostUserConfigFlags::WRITABLE, &buf) .unwrap_err(); - master + frontend .set_config(VHOST_USER_CONFIG_SIZE, VhostUserConfigFlags::WRITABLE, &[]) .unwrap_err(); } - fn create_pair2() -> (Master, Endpoint) { + fn create_pair2() -> (Frontend, Endpoint) { let path = temp_path(); - let (master, peer) = create_pair(path); + let (frontend, peer) = create_pair(path); { - let mut node = master.node(); + let mut node = frontend.node(); node.virtio_features = 0xffff_ffff; node.acked_virtio_features = 0xffff_ffff; node.protocol_features = 0xffff_ffff; node.acked_protocol_features = 0xffff_ffff; } - (master, peer) + (frontend, peer) } #[test] - fn test_master_get_config_negative0() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative0() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let mut hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let mut hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); - hdr.set_code(MasterReq::GET_FEATURES); + hdr.set_code(FrontendReq::GET_FEATURES); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_err()); - hdr.set_code(MasterReq::GET_CONFIG); + hdr.set_code(FrontendReq::GET_CONFIG); } #[test] - fn test_master_get_config_negative1() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative1() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let mut hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let mut hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); hdr.set_reply(false); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_err()); } #[test] - fn test_master_get_config_negative2() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative2() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); } #[test] - fn test_master_get_config_negative3() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative3() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); msg.offset = 0; peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_err()); } #[test] - fn test_master_get_config_negative4() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative4() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); msg.offset = 0x101; peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_err()); } #[test] - fn test_master_get_config_negative5() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative5() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); msg.offset = (MAX_MSG_SIZE + 1) as u32; peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_err()); } #[test] - fn test_master_get_config_negative6() { - let (mut master, mut peer) = create_pair2(); + fn test_frontend_get_config_negative6() { + let (mut frontend, mut peer) = create_pair2(); let buf = vec![0x0; MAX_MSG_SIZE + 1]; - let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let hdr = VhostUserMsgHeader::new(FrontendReq::GET_CONFIG, 0x4, 16); let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_ok()); msg.size = 6; peer.send_message_with_payload(&hdr, &msg, &buf[0..6], None) .unwrap(); - assert!(master + assert!(frontend .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) .is_err()); } #[test] fn test_maset_set_mem_table_failure() { - let (master, _peer) = create_pair2(); + let (frontend, _peer) = create_pair2(); - master.set_mem_table(&[]).unwrap_err(); + frontend.set_mem_table(&[]).unwrap_err(); let tables = vec![VhostUserMemoryRegionInfo::default(); MAX_ATTACHED_FD_ENTRIES + 1]; - master.set_mem_table(&tables).unwrap_err(); + frontend.set_mem_table(&tables).unwrap_err(); } } diff --git a/crates/vhost/src/vhost_user/master_req_handler.rs b/crates/vhost/src/vhost_user/frontend_req_handler.rs similarity index 60% rename from crates/vhost/src/vhost_user/master_req_handler.rs rename to crates/vhost/src/vhost_user/frontend_req_handler.rs index c9c528b8..fb2dc16f 100644 --- a/crates/vhost/src/vhost_user/master_req_handler.rs +++ b/crates/vhost/src/vhost_user/frontend_req_handler.rs @@ -11,45 +11,45 @@ use super::connection::Endpoint; use super::message::*; use super::{Error, HandlerResult, Result}; -/// Define services provided by masters for the slave communication channel. +/// Define services provided by frontends for the backend communication channel. /// -/// The vhost-user specification defines a slave communication channel, by which slaves could -/// request services from masters. The [VhostUserMasterReqHandler] trait defines services provided -/// by masters, and it's used both on the master side and slave side. -/// - on the slave side, a stub forwarder implementing [VhostUserMasterReqHandler] will proxy -/// service requests to masters. The [Slave] is an example stub forwarder. -/// - on the master side, the [MasterReqHandler] will forward service requests to a handler -/// implementing [VhostUserMasterReqHandler]. +/// The vhost-user specification defines a backend communication channel, by which backends could +/// request services from frontends. The [VhostUserFrontendReqHandler] trait defines services provided +/// by frontends, and it's used both on the frontend side and backend side. +/// - on the backend side, a stub forwarder implementing [VhostUserFrontendReqHandler] will proxy +/// service requests to frontends. The [Backend] is an example stub forwarder. +/// - on the frontend side, the [FrontendReqHandler] will forward service requests to a handler +/// implementing [VhostUserFrontendReqHandler]. /// -/// The [VhostUserMasterReqHandler] trait is design with interior mutability to improve performance +/// The [VhostUserFrontendReqHandler] trait is design with interior mutability to improve performance /// for multi-threading. /// -/// [VhostUserMasterReqHandler]: trait.VhostUserMasterReqHandler.html -/// [MasterReqHandler]: struct.MasterReqHandler.html -/// [Slave]: struct.Slave.html -pub trait VhostUserMasterReqHandler { +/// [VhostUserFrontendReqHandler]: trait.VhostUserFrontendReqHandler.html +/// [FrontendReqHandler]: struct.FrontendReqHandler.html +/// [Backend]: struct.Backend.html +pub trait VhostUserFrontendReqHandler { /// Handle device configuration change notifications. fn handle_config_change(&self) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs map file requests. - fn fs_slave_map(&self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawFd) -> HandlerResult { + fn fs_backend_map(&self, _fs: &VhostUserFSBackendMsg, _fd: &dyn AsRawFd) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs unmap file requests. - fn fs_slave_unmap(&self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult { + fn fs_backend_unmap(&self, _fs: &VhostUserFSBackendMsg) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs sync file requests. - fn fs_slave_sync(&self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult { + fn fs_backend_sync(&self, _fs: &VhostUserFSBackendMsg) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs file IO requests. - fn fs_slave_io(&self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawFd) -> HandlerResult { + fn fs_backend_io(&self, _fs: &VhostUserFSBackendMsg, _fd: &dyn AsRawFd) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } @@ -57,32 +57,40 @@ pub trait VhostUserMasterReqHandler { // fn handle_vring_host_notifier(&mut self, area: VhostUserVringArea, fd: &dyn AsRawFd); } -/// A helper trait mirroring [VhostUserMasterReqHandler] but without interior mutability. +/// A helper trait mirroring [VhostUserFrontendReqHandler] but without interior mutability. /// -/// [VhostUserMasterReqHandler]: trait.VhostUserMasterReqHandler.html -pub trait VhostUserMasterReqHandlerMut { +/// [VhostUserFrontendReqHandler]: trait.VhostUserFrontendReqHandler.html +pub trait VhostUserFrontendReqHandlerMut { /// Handle device configuration change notifications. fn handle_config_change(&mut self) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs map file requests. - fn fs_slave_map(&mut self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawFd) -> HandlerResult { + fn fs_backend_map( + &mut self, + _fs: &VhostUserFSBackendMsg, + _fd: &dyn AsRawFd, + ) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs unmap file requests. - fn fs_slave_unmap(&mut self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult { + fn fs_backend_unmap(&mut self, _fs: &VhostUserFSBackendMsg) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs sync file requests. - fn fs_slave_sync(&mut self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult { + fn fs_backend_sync(&mut self, _fs: &VhostUserFSBackendMsg) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } /// Handle virtio-fs file IO requests. - fn fs_slave_io(&mut self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawFd) -> HandlerResult { + fn fs_backend_io( + &mut self, + _fs: &VhostUserFSBackendMsg, + _fd: &dyn AsRawFd, + ) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } @@ -90,39 +98,39 @@ pub trait VhostUserMasterReqHandlerMut { // fn handle_vring_host_notifier(&mut self, area: VhostUserVringArea, fd: RawFd); } -impl VhostUserMasterReqHandler for Mutex { +impl VhostUserFrontendReqHandler for Mutex { fn handle_config_change(&self) -> HandlerResult { self.lock().unwrap().handle_config_change() } - fn fs_slave_map(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult { - self.lock().unwrap().fs_slave_map(fs, fd) + fn fs_backend_map(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult { + self.lock().unwrap().fs_backend_map(fs, fd) } - fn fs_slave_unmap(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult { - self.lock().unwrap().fs_slave_unmap(fs) + fn fs_backend_unmap(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult { + self.lock().unwrap().fs_backend_unmap(fs) } - fn fs_slave_sync(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult { - self.lock().unwrap().fs_slave_sync(fs) + fn fs_backend_sync(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult { + self.lock().unwrap().fs_backend_sync(fs) } - fn fs_slave_io(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult { - self.lock().unwrap().fs_slave_io(fs, fd) + fn fs_backend_io(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult { + self.lock().unwrap().fs_backend_io(fs, fd) } } -/// Server to handle service requests from slaves from the slave communication channel. +/// Server to handle service requests from backends from the backend communication channel. /// -/// The [MasterReqHandler] acts as a server on the master side, to handle service requests from -/// slaves on the slave communication channel. It's actually a proxy invoking the registered -/// handler implementing [VhostUserMasterReqHandler] to do the real work. +/// The [FrontendReqHandler] acts as a server on the frontend side, to handle service requests from +/// backends on the backend communication channel. It's actually a proxy invoking the registered +/// handler implementing [VhostUserFrontendReqHandler] to do the real work. /// -/// [MasterReqHandler]: struct.MasterReqHandler.html -/// [VhostUserMasterReqHandler]: trait.VhostUserMasterReqHandler.html -pub struct MasterReqHandler { +/// [FrontendReqHandler]: struct.FrontendReqHandler.html +/// [VhostUserFrontendReqHandler]: trait.VhostUserFrontendReqHandler.html +pub struct FrontendReqHandler { // underlying Unix domain socket for communication - sub_sock: Endpoint, + sub_sock: Endpoint, tx_sock: UnixStream, // Protocol feature VHOST_USER_PROTOCOL_F_REPLY_ACK has been negotiated. reply_ack_negotiated: bool, @@ -132,20 +140,20 @@ pub struct MasterReqHandler { error: Option, } -impl MasterReqHandler { - /// Create a server to handle service requests from slaves on the slave communication channel. +impl FrontendReqHandler { + /// Create a server to handle service requests from backends on the backend communication channel. /// - /// This opens a pair of connected anonymous sockets to form the slave communication channel. - /// The socket fd returned by [Self::get_tx_raw_fd()] should be sent to the slave by - /// [VhostUserMaster::set_slave_request_fd()]. + /// This opens a pair of connected anonymous sockets to form the backend communication channel. + /// The socket fd returned by [Self::get_tx_raw_fd()] should be sent to the backend by + /// [VhostUserFrontend::set_backend_request_fd()]. /// - /// [Self::get_tx_raw_fd()]: struct.MasterReqHandler.html#method.get_tx_raw_fd - /// [VhostUserMaster::set_slave_request_fd()]: trait.VhostUserMaster.html#tymethod.set_slave_request_fd + /// [Self::get_tx_raw_fd()]: struct.FrontendReqHandler.html#method.get_tx_raw_fd + /// [VhostUserFrontend::set_backend_request_fd()]: trait.VhostUserFrontend.html#tymethod.set_backend_request_fd pub fn new(backend: Arc) -> Result { let (tx, rx) = UnixStream::pair().map_err(Error::SocketError)?; - Ok(MasterReqHandler { - sub_sock: Endpoint::::from_stream(rx), + Ok(FrontendReqHandler { + sub_sock: Endpoint::::from_stream(rx), tx_sock: tx, reply_ack_negotiated: false, backend, @@ -153,11 +161,11 @@ impl MasterReqHandler { }) } - /// Get the socket fd for the slave to communication with the master. + /// Get the socket fd for the backend to communication with the frontend. /// - /// The returned fd should be sent to the slave by [VhostUserMaster::set_slave_request_fd()]. + /// The returned fd should be sent to the backend by [VhostUserFrontend::set_backend_request_fd()]. /// - /// [VhostUserMaster::set_slave_request_fd()]: trait.VhostUserMaster.html#tymethod.set_slave_request_fd + /// [VhostUserFrontend::set_backend_request_fd()]: trait.VhostUserFrontend.html#tymethod.set_backend_request_fd pub fn get_tx_raw_fd(&self) -> RawFd { self.tx_sock.as_raw_fd() } @@ -165,7 +173,7 @@ impl MasterReqHandler { /// Set the negotiation state of the `VHOST_USER_PROTOCOL_F_REPLY_ACK` protocol feature. /// /// When the `VHOST_USER_PROTOCOL_F_REPLY_ACK` protocol feature has been negotiated, - /// the "REPLY_ACK" flag will be set in the message header for every slave to master request + /// the "REPLY_ACK" flag will be set in the message header for every backend to frontend request /// message. pub fn set_reply_ack_flag(&mut self, enable: bool) { self.reply_ack_negotiated = enable; @@ -180,7 +188,7 @@ impl MasterReqHandler { } } - /// Main entrance to server slave request from the slave communication channel. + /// Main entrance to server backend request from the backend communication channel. /// /// The caller needs to: /// - serialize calls to this function @@ -216,36 +224,36 @@ impl MasterReqHandler { }; let res = match hdr.get_code() { - Ok(SlaveReq::CONFIG_CHANGE_MSG) => { + Ok(BackendReq::CONFIG_CHANGE_MSG) => { self.check_msg_size(&hdr, size, 0)?; self.backend .handle_config_change() .map_err(Error::ReqHandlerError) } - Ok(SlaveReq::FS_MAP) => { - let msg = self.extract_msg_body::(&hdr, size, &buf)?; + Ok(BackendReq::FS_MAP) => { + let msg = self.extract_msg_body::(&hdr, size, &buf)?; // check_attached_files() has validated files self.backend - .fs_slave_map(&msg, &files.unwrap()[0]) + .fs_backend_map(&msg, &files.unwrap()[0]) .map_err(Error::ReqHandlerError) } - Ok(SlaveReq::FS_UNMAP) => { - let msg = self.extract_msg_body::(&hdr, size, &buf)?; + Ok(BackendReq::FS_UNMAP) => { + let msg = self.extract_msg_body::(&hdr, size, &buf)?; self.backend - .fs_slave_unmap(&msg) + .fs_backend_unmap(&msg) .map_err(Error::ReqHandlerError) } - Ok(SlaveReq::FS_SYNC) => { - let msg = self.extract_msg_body::(&hdr, size, &buf)?; + Ok(BackendReq::FS_SYNC) => { + let msg = self.extract_msg_body::(&hdr, size, &buf)?; self.backend - .fs_slave_sync(&msg) + .fs_backend_sync(&msg) .map_err(Error::ReqHandlerError) } - Ok(SlaveReq::FS_IO) => { - let msg = self.extract_msg_body::(&hdr, size, &buf)?; + Ok(BackendReq::FS_IO) => { + let msg = self.extract_msg_body::(&hdr, size, &buf)?; // check_attached_files() has validated files self.backend - .fs_slave_io(&msg, &files.unwrap()[0]) + .fs_backend_io(&msg, &files.unwrap()[0]) .map_err(Error::ReqHandlerError) } _ => Err(Error::InvalidMessage), @@ -265,7 +273,7 @@ impl MasterReqHandler { fn check_msg_size( &self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, size: usize, expected: usize, ) -> Result<()> { @@ -281,11 +289,11 @@ impl MasterReqHandler { fn check_attached_files( &self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, files: &Option>, ) -> Result<()> { match hdr.get_code() { - Ok(SlaveReq::FS_MAP | SlaveReq::FS_IO) => { + Ok(BackendReq::FS_MAP | BackendReq::FS_IO) => { // Expect a single file is passed. match files { Some(files) if files.len() == 1 => Ok(()), @@ -299,7 +307,7 @@ impl MasterReqHandler { fn extract_msg_body( &self, - hdr: &VhostUserMsgHeader, + hdr: &VhostUserMsgHeader, size: usize, buf: &[u8], ) -> Result { @@ -314,8 +322,8 @@ impl MasterReqHandler { fn new_reply_header( &self, - req: &VhostUserMsgHeader, - ) -> Result> { + req: &VhostUserMsgHeader, + ) -> Result> { if mem::size_of::() > MAX_MSG_SIZE { return Err(Error::InvalidParam); } @@ -329,7 +337,7 @@ impl MasterReqHandler { fn send_ack_message( &mut self, - req: &VhostUserMsgHeader, + req: &VhostUserMsgHeader, res: &Result, ) -> Result<()> { if self.reply_ack_negotiated && req.is_need_reply() { @@ -352,7 +360,7 @@ impl MasterReqHandler { } } -impl AsRawFd for MasterReqHandler { +impl AsRawFd for FrontendReqHandler { fn as_raw_fd(&self) -> RawFd { self.sub_sock.as_raw_fd() } @@ -362,33 +370,33 @@ impl AsRawFd for MasterReqHandler { mod tests { use super::*; - #[cfg(feature = "vhost-user-slave")] - use crate::vhost_user::Slave; - #[cfg(feature = "vhost-user-slave")] + #[cfg(feature = "vhost-user-backend")] + use crate::vhost_user::Backend; + #[cfg(feature = "vhost-user-backend")] use std::os::unix::io::FromRawFd; - struct MockMasterReqHandler {} + struct MockFrontendReqHandler {} - impl VhostUserMasterReqHandlerMut for MockMasterReqHandler { - /// Handle virtio-fs map file requests from the slave. - fn fs_slave_map( + impl VhostUserFrontendReqHandlerMut for MockFrontendReqHandler { + /// Handle virtio-fs map file requests from the backend. + fn fs_backend_map( &mut self, - _fs: &VhostUserFSSlaveMsg, + _fs: &VhostUserFSBackendMsg, _fd: &dyn AsRawFd, ) -> HandlerResult { Ok(0) } - /// Handle virtio-fs unmap file requests from the slave. - fn fs_slave_unmap(&mut self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult { + /// Handle virtio-fs unmap file requests from the backend. + fn fs_backend_unmap(&mut self, _fs: &VhostUserFSBackendMsg) -> HandlerResult { Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) } } #[test] - fn test_new_master_req_handler() { - let backend = Arc::new(Mutex::new(MockMasterReqHandler {})); - let mut handler = MasterReqHandler::new(backend).unwrap(); + fn test_new_frontend_req_handler() { + let backend = Arc::new(Mutex::new(MockFrontendReqHandler {})); + let mut handler = FrontendReqHandler::new(backend).unwrap(); assert!(handler.get_tx_raw_fd() >= 0); assert!(handler.as_raw_fd() >= 0); @@ -400,11 +408,11 @@ mod tests { handler.check_state().unwrap_err(); } - #[cfg(feature = "vhost-user-slave")] + #[cfg(feature = "vhost-user-backend")] #[test] - fn test_master_slave_req_handler() { - let backend = Arc::new(Mutex::new(MockMasterReqHandler {})); - let mut handler = MasterReqHandler::new(backend).unwrap(); + fn test_frontend_backend_req_handler() { + let backend = Arc::new(Mutex::new(MockFrontendReqHandler {})); + let mut handler = FrontendReqHandler::new(backend).unwrap(); // SAFETY: Safe because `handler` contains valid fds, and we are // checking if `dup` returns a valid fd. @@ -414,7 +422,7 @@ mod tests { } // SAFETY: Safe because we checked if fd is valid. let stream = unsafe { UnixStream::from_raw_fd(fd) }; - let slave = Slave::from_stream(stream); + let backend = Backend::from_stream(stream); std::thread::spawn(move || { let res = handler.handle_request().unwrap(); @@ -422,21 +430,21 @@ mod tests { handler.handle_request().unwrap_err(); }); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &fd) + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &fd) .unwrap(); - // When REPLY_ACK has not been negotiated, the master has no way to detect failure from - // slave side. - slave - .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) + // When REPLY_ACK has not been negotiated, the frontend has no way to detect failure from + // backend side. + backend + .fs_backend_unmap(&VhostUserFSBackendMsg::default()) .unwrap(); } - #[cfg(feature = "vhost-user-slave")] + #[cfg(feature = "vhost-user-backend")] #[test] - fn test_master_slave_req_handler_with_ack() { - let backend = Arc::new(Mutex::new(MockMasterReqHandler {})); - let mut handler = MasterReqHandler::new(backend).unwrap(); + fn test_frontend_backend_req_handler_with_ack() { + let backend = Arc::new(Mutex::new(MockFrontendReqHandler {})); + let mut handler = FrontendReqHandler::new(backend).unwrap(); handler.set_reply_ack_flag(true); // SAFETY: Safe because `handler` contains valid fds, and we are @@ -447,7 +455,7 @@ mod tests { } // SAFETY: Safe because we checked if fd is valid. let stream = unsafe { UnixStream::from_raw_fd(fd) }; - let slave = Slave::from_stream(stream); + let backend = Backend::from_stream(stream); std::thread::spawn(move || { let res = handler.handle_request().unwrap(); @@ -455,12 +463,12 @@ mod tests { handler.handle_request().unwrap_err(); }); - slave.set_reply_ack_flag(true); - slave - .fs_slave_map(&VhostUserFSSlaveMsg::default(), &fd) + backend.set_reply_ack_flag(true); + backend + .fs_backend_map(&VhostUserFSBackendMsg::default(), &fd) .unwrap(); - slave - .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) + backend + .fs_backend_unmap(&VhostUserFSBackendMsg::default()) .unwrap_err(); } } diff --git a/crates/vhost/src/vhost_user/message.rs b/crates/vhost/src/vhost_user/message.rs index 03db8838..db427766 100644 --- a/crates/vhost/src/vhost_user/message.rs +++ b/crates/vhost/src/vhost_user/message.rs @@ -55,21 +55,21 @@ pub(super) trait Req: fn is_valid(value: u32) -> bool; } -/// Type of requests sending from masters to slaves. +/// Type of requests sending from frontends to backends. #[repr(u32)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum MasterReq { +pub enum FrontendReq { /// Null operation. NOOP = 0, /// Get from the underlying vhost implementation the features bit mask. GET_FEATURES = 1, /// Enable features in the underlying vhost implementation using a bit mask. SET_FEATURES = 2, - /// Set the current Master as an owner of the session. + /// Set the current Frontend as an owner of the session. SET_OWNER = 3, /// No longer used. RESET_OWNER = 4, - /// Set the memory map regions on the slave so it can translate the vring addresses. + /// Set the memory map regions on the backend so it can translate the vring addresses. SET_MEM_TABLE = 5, /// Set logging shared memory space. SET_LOG_BASE = 6, @@ -95,15 +95,15 @@ pub enum MasterReq { SET_PROTOCOL_FEATURES = 16, /// Query how many queues the backend supports. GET_QUEUE_NUM = 17, - /// Signal slave to enable or disable corresponding vring. + /// Signal backend to enable or disable corresponding vring. SET_VRING_ENABLE = 18, /// Ask vhost user backend to broadcast a fake RARP to notify the migration is terminated /// for guest that does not support GUEST_ANNOUNCE. SEND_RARP = 19, /// Set host MTU value exposed to the guest. NET_SET_MTU = 20, - /// Set the socket file descriptor for slave initiated requests. - SET_SLAVE_REQ_FD = 21, + /// Set the socket file descriptor for backend initiated requests. + SET_BACKEND_REQ_FD = 21, /// Send IOTLB messages with struct vhost_iotlb_msg as payload. IOTLB_MSG = 22, /// Set the endianness of a VQ for legacy devices. @@ -116,15 +116,15 @@ pub enum MasterReq { CREATE_CRYPTO_SESSION = 26, /// Close a session for crypto operation. CLOSE_CRYPTO_SESSION = 27, - /// Advise slave that a migration with postcopy enabled is underway. + /// Advise backend that a migration with postcopy enabled is underway. POSTCOPY_ADVISE = 28, - /// Advise slave that a transition to postcopy mode has happened. + /// Advise backend that a transition to postcopy mode has happened. POSTCOPY_LISTEN = 29, /// Advise that postcopy migration has now completed. POSTCOPY_END = 30, - /// Get a shared buffer from slave. + /// Get a shared buffer from backend. GET_INFLIGHT_FD = 31, - /// Send the shared inflight buffer back to slave. + /// Send the shared inflight buffer back to backend. SET_INFLIGHT_FD = 32, /// Sets the GPU protocol socket file descriptor. GPU_SET_SOCKET = 33, @@ -150,22 +150,22 @@ pub enum MasterReq { MAX_CMD = 41, } -impl From for u32 { - fn from(req: MasterReq) -> u32 { +impl From for u32 { + fn from(req: FrontendReq) -> u32 { req as u32 } } -impl Req for MasterReq { +impl Req for FrontendReq { fn is_valid(value: u32) -> bool { - (value > MasterReq::NOOP as u32) && (value < MasterReq::MAX_CMD as u32) + (value > FrontendReq::NOOP as u32) && (value < FrontendReq::MAX_CMD as u32) } } -/// Type of requests sending from slaves to masters. +/// Type of requests sending from backends to frontends. #[repr(u32)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum SlaveReq { +pub enum BackendReq { /// Null operation. NOOP = 0, /// Send IOTLB messages with struct vhost_iotlb_msg as payload. @@ -190,15 +190,15 @@ pub enum SlaveReq { MAX_CMD = 10, } -impl From for u32 { - fn from(req: SlaveReq) -> u32 { +impl From for u32 { + fn from(req: BackendReq) -> u32 { req as u32 } } -impl Req for SlaveReq { +impl Req for BackendReq { fn is_valid(value: u32) -> bool { - (value > SlaveReq::NOOP as u32) && (value < SlaveReq::MAX_CMD as u32) + (value > BackendReq::NOOP as u32) && (value < BackendReq::MAX_CMD as u32) } } @@ -403,19 +403,19 @@ bitflags! { const REPLY_ACK = 0x0000_0008; /// Support setting MTU for virtio-net devices. const MTU = 0x0000_0010; - /// Allow the slave to send requests to the master by an optional communication channel. - const SLAVE_REQ = 0x0000_0020; - /// Support setting slave endian by SET_VRING_ENDIAN. + /// Allow the backend to send requests to the frontend by an optional communication channel. + const BACKEND_REQ = 0x0000_0020; + /// Support setting backend endian by SET_VRING_ENDIAN. const CROSS_ENDIAN = 0x0000_0040; /// Support crypto operations. const CRYPTO_SESSION = 0x0000_0080; - /// Support sending userfault_fd from slaves to masters. + /// Support sending userfault_fd from backends to frontends. const PAGEFAULT = 0x0000_0100; /// Support Virtio device configuration. const CONFIG = 0x0000_0200; - /// Allow the slave to send fds (at most 8 descriptors in each message) to the master. - const SLAVE_SEND_FD = 0x0000_0400; - /// Allow the slave to register a host notifier. + /// Allow the backend to send fds (at most 8 descriptors in each message) to the frontend. + const BACKEND_SEND_FD = 0x0000_0400; + /// Allow the backend to register a host notifier. const HOST_NOTIFIER = 0x0000_0800; /// Support inflight shmfd. const INFLIGHT_SHMFD = 0x0000_1000; @@ -778,9 +778,9 @@ impl VhostUserMsgValidator for VhostUserVringAddr { bitflags! { /// Flags for the device configuration message. pub struct VhostUserConfigFlags: u32 { - /// Vhost master messages used for writeable fields. + /// Vhost frontend messages used for writeable fields. const WRITABLE = 0x1; - /// Vhost master messages used for live migration. + /// Vhost frontend messages used for live migration. const LIVE_MIGRATION = 0x2; } } @@ -927,11 +927,11 @@ pub struct VhostUserIotlb { } */ -// Bit mask for flags in virtio-fs slave messages +// Bit mask for flags in virtio-fs backend messages bitflags! { #[derive(Default)] - /// Flags for virtio-fs slave messages. - pub struct VhostUserFSSlaveMsgFlags: u64 { + /// Flags for virtio-fs backend messages. + pub struct VhostUserFSBackendMsgFlags: u64 { /// Empty permission. const EMPTY = 0x0; /// Read permission. @@ -941,30 +941,30 @@ bitflags! { } } -/// Max entries in one virtio-fs slave request. -pub const VHOST_USER_FS_SLAVE_ENTRIES: usize = 8; +/// Max entries in one virtio-fs backend request. +pub const VHOST_USER_FS_BACKEND_ENTRIES: usize = 8; -/// Slave request message to update the MMIO window. +/// Backend request message to update the MMIO window. #[repr(packed)] #[derive(Copy, Clone, Default)] -pub struct VhostUserFSSlaveMsg { +pub struct VhostUserFSBackendMsg { /// File offset. - pub fd_offset: [u64; VHOST_USER_FS_SLAVE_ENTRIES], + pub fd_offset: [u64; VHOST_USER_FS_BACKEND_ENTRIES], /// Offset into the DAX window. - pub cache_offset: [u64; VHOST_USER_FS_SLAVE_ENTRIES], + pub cache_offset: [u64; VHOST_USER_FS_BACKEND_ENTRIES], /// Size of region to map. - pub len: [u64; VHOST_USER_FS_SLAVE_ENTRIES], + pub len: [u64; VHOST_USER_FS_BACKEND_ENTRIES], /// Flags for the mmap operation - pub flags: [VhostUserFSSlaveMsgFlags; VHOST_USER_FS_SLAVE_ENTRIES], + pub flags: [VhostUserFSBackendMsgFlags; VHOST_USER_FS_BACKEND_ENTRIES], } -// SAFETY: Safe because all fields of VhostUserFSSlaveMsg are POD. -unsafe impl ByteValued for VhostUserFSSlaveMsg {} +// SAFETY: Safe because all fields of VhostUserFSBackendMsg are POD. +unsafe impl ByteValued for VhostUserFSBackendMsg {} -impl VhostUserMsgValidator for VhostUserFSSlaveMsg { +impl VhostUserMsgValidator for VhostUserFSBackendMsg { fn is_valid(&self) -> bool { - for i in 0..VHOST_USER_FS_SLAVE_ENTRIES { - if ({ self.flags[i] }.bits() & !VhostUserFSSlaveMsgFlags::all().bits()) != 0 + for i in 0..VHOST_USER_FS_BACKEND_ENTRIES { + if ({ self.flags[i] }.bits() & !VhostUserFSBackendMsgFlags::all().bits()) != 0 || self.fd_offset[i].checked_add(self.len[i]).is_none() || self.cache_offset[i].checked_add(self.len[i]).is_none() { @@ -1126,33 +1126,33 @@ mod tests { } #[test] - fn check_master_request_code() { - assert!(!MasterReq::is_valid(MasterReq::NOOP as _)); - assert!(!MasterReq::is_valid(MasterReq::MAX_CMD as _)); - assert!(MasterReq::MAX_CMD > MasterReq::NOOP); - let code = MasterReq::GET_FEATURES; - assert!(MasterReq::is_valid(code as _)); + fn check_frontend_request_code() { + assert!(!FrontendReq::is_valid(FrontendReq::NOOP as _)); + assert!(!FrontendReq::is_valid(FrontendReq::MAX_CMD as _)); + assert!(FrontendReq::MAX_CMD > FrontendReq::NOOP); + let code = FrontendReq::GET_FEATURES; + assert!(FrontendReq::is_valid(code as _)); assert_eq!(code, code.clone()); - assert!(!MasterReq::is_valid(10000)); + assert!(!FrontendReq::is_valid(10000)); } #[test] - fn check_slave_request_code() { - assert!(!SlaveReq::is_valid(SlaveReq::NOOP as _)); - assert!(!SlaveReq::is_valid(SlaveReq::MAX_CMD as _)); - assert!(SlaveReq::MAX_CMD > SlaveReq::NOOP); - let code = SlaveReq::CONFIG_CHANGE_MSG; - assert!(SlaveReq::is_valid(code as _)); + fn check_backend_request_code() { + assert!(!BackendReq::is_valid(BackendReq::NOOP as _)); + assert!(!BackendReq::is_valid(BackendReq::MAX_CMD as _)); + assert!(BackendReq::MAX_CMD > BackendReq::NOOP); + let code = BackendReq::CONFIG_CHANGE_MSG; + assert!(BackendReq::is_valid(code as _)); assert_eq!(code, code.clone()); - assert!(!SlaveReq::is_valid(10000)); + assert!(!BackendReq::is_valid(10000)); } #[test] fn msg_header_ops() { - let mut hdr = VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0, 0x100); - assert_eq!(hdr.get_code().unwrap(), MasterReq::GET_FEATURES); - hdr.set_code(MasterReq::SET_FEATURES); - assert_eq!(hdr.get_code().unwrap(), MasterReq::SET_FEATURES); + let mut hdr = VhostUserMsgHeader::new(FrontendReq::GET_FEATURES, 0, 0x100); + assert_eq!(hdr.get_code().unwrap(), FrontendReq::GET_FEATURES); + hdr.set_code(FrontendReq::SET_FEATURES); + assert_eq!(hdr.get_code().unwrap(), FrontendReq::SET_FEATURES); assert_eq!(hdr.get_version(), 0x1); @@ -1181,7 +1181,7 @@ mod tests { hdr.set_size(0x100); assert_eq!(hdr.get_size(), 0x100); assert!(hdr.is_valid()); - hdr.set_size((MAX_MSG_SIZE - mem::size_of::>()) as u32); + hdr.set_size((MAX_MSG_SIZE - mem::size_of::>()) as u32); assert!(hdr.is_valid()); hdr.set_size(0x0); assert!(hdr.is_valid()); @@ -1388,19 +1388,19 @@ mod tests { } #[test] - fn test_vhost_user_fs_slave() { - let mut fs_slave = VhostUserFSSlaveMsg::default(); + fn test_vhost_user_fs_backend() { + let mut fs_backend = VhostUserFSBackendMsg::default(); - assert!(fs_slave.is_valid()); + assert!(fs_backend.is_valid()); - fs_slave.fd_offset[0] = 0xffff_ffff_ffff_ffff; - fs_slave.len[0] = 0x1; - assert!(!fs_slave.is_valid()); + fs_backend.fd_offset[0] = 0xffff_ffff_ffff_ffff; + fs_backend.len[0] = 0x1; + assert!(!fs_backend.is_valid()); assert_ne!( - VhostUserFSSlaveMsgFlags::MAP_R, - VhostUserFSSlaveMsgFlags::MAP_W + VhostUserFSBackendMsgFlags::MAP_R, + VhostUserFSBackendMsgFlags::MAP_W ); - assert_eq!(VhostUserFSSlaveMsgFlags::EMPTY.bits(), 0); + assert_eq!(VhostUserFSBackendMsgFlags::EMPTY.bits(), 0); } } diff --git a/crates/vhost/src/vhost_user/mod.rs b/crates/vhost/src/vhost_user/mod.rs index 7df51f6a..c7aed411 100644 --- a/crates/vhost/src/vhost_user/mod.rs +++ b/crates/vhost/src/vhost_user/mod.rs @@ -2,18 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 //! The protocol for vhost-user is based on the existing implementation of vhost for the Linux -//! Kernel. The protocol defines two sides of the communication, master and slave. Master is -//! the application that shares its virtqueues. Slave is the consumer of the virtqueues. +//! Kernel. The protocol defines two sides of the communication, frontend and backend. Frontend is +//! the application that shares its virtqueues. Backend is the consumer of the virtqueues. //! -//! The communication channel between the master and the slave includes two sub channels. One is -//! used to send requests from the master to the slave and optional replies from the slave to the -//! master. This sub channel is created on master startup by connecting to the slave service -//! endpoint. The other is used to send requests from the slave to the master and optional replies -//! from the master to the slave. This sub channel is created by the master issuing a -//! VHOST_USER_SET_SLAVE_REQ_FD request to the slave with an auxiliary file descriptor. +//! The communication channel between the frontend and the backend includes two sub channels. One is +//! used to send requests from the frontend to the backend and optional replies from the backend to the +//! frontend. This sub channel is created on frontend startup by connecting to the backend service +//! endpoint. The other is used to send requests from the backend to the frontend and optional replies +//! from the frontend to the backend. This sub channel is created by the frontend issuing a +//! VHOST_USER_SET_BACKEND_REQ_FD request to the backend with an auxiliary file descriptor. //! -//! Unix domain socket is used as the underlying communication channel because the master needs to -//! send file descriptors to the slave. +//! Unix domain socket is used as the underlying communication channel because the frontend needs to +//! send file descriptors to the backend. //! //! Most messages that can be sent via the Unix domain socket implementing vhost-user have an //! equivalent ioctl to the kernel implementation. @@ -27,31 +27,31 @@ pub use self::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures}; mod connection; pub use self::connection::Listener; -#[cfg(feature = "vhost-user-master")] -mod master; -#[cfg(feature = "vhost-user-master")] -pub use self::master::{Master, VhostUserMaster}; +#[cfg(feature = "vhost-user-frontend")] +mod frontend; +#[cfg(feature = "vhost-user-frontend")] +pub use self::frontend::{Frontend, VhostUserFrontend}; #[cfg(feature = "vhost-user")] -mod master_req_handler; +mod frontend_req_handler; #[cfg(feature = "vhost-user")] -pub use self::master_req_handler::{ - MasterReqHandler, VhostUserMasterReqHandler, VhostUserMasterReqHandlerMut, +pub use self::frontend_req_handler::{ + FrontendReqHandler, VhostUserFrontendReqHandler, VhostUserFrontendReqHandlerMut, }; -#[cfg(feature = "vhost-user-slave")] -mod slave; -#[cfg(feature = "vhost-user-slave")] -pub use self::slave::SlaveListener; -#[cfg(feature = "vhost-user-slave")] -mod slave_req_handler; -#[cfg(feature = "vhost-user-slave")] -pub use self::slave_req_handler::{ - SlaveReqHandler, VhostUserSlaveReqHandler, VhostUserSlaveReqHandlerMut, +#[cfg(feature = "vhost-user-backend")] +mod backend; +#[cfg(feature = "vhost-user-backend")] +pub use self::backend::BackendListener; +#[cfg(feature = "vhost-user-backend")] +mod backend_req_handler; +#[cfg(feature = "vhost-user-backend")] +pub use self::backend_req_handler::{ + BackendReqHandler, VhostUserBackendReqHandler, VhostUserBackendReqHandlerMut, }; -#[cfg(feature = "vhost-user-slave")] -mod slave_req; -#[cfg(feature = "vhost-user-slave")] -pub use self::slave_req::Slave; +#[cfg(feature = "vhost-user-backend")] +mod backend_req; +#[cfg(feature = "vhost-user-backend")] +pub use self::backend_req::Backend; /// Errors for vhost-user operations #[derive(Debug)] @@ -82,10 +82,10 @@ pub enum Error { SocketBroken(std::io::Error), /// Should retry the socket operation again. SocketRetry(std::io::Error), - /// Failure from the slave side. - SlaveInternalError, - /// Failure from the master side. - MasterInternalError, + /// Failure from the backend side. + BackendInternalError, + /// Failure from the frontend side. + FrontendInternalError, /// Virtio/protocol features mismatch. FeatureMismatch, /// Error from request handler @@ -116,8 +116,8 @@ impl std::fmt::Display for Error { Error::SocketConnect(e) => write!(f, "can't connect to peer: {}", e), Error::SocketBroken(e) => write!(f, "socket is broken: {}", e), Error::SocketRetry(e) => write!(f, "temporary socket error: {}", e), - Error::SlaveInternalError => write!(f, "slave internal error"), - Error::MasterInternalError => write!(f, "Master internal error"), + Error::BackendInternalError => write!(f, "backend internal error"), + Error::FrontendInternalError => write!(f, "Frontend internal error"), Error::FeatureMismatch => write!(f, "virtio/protocol features mismatch"), Error::ReqHandlerError(e) => write!(f, "handler failed to handle request: {}", e), Error::MemFdCreateError => { @@ -144,10 +144,10 @@ impl Error { Error::PartialMessage => true, // Should reconnect because the underline socket is broken. Error::SocketBroken(_) => true, - // Slave internal error, hope it recovers on reconnect. - Error::SlaveInternalError => true, - // Master internal error, hope it recovers on reconnect. - Error::MasterInternalError => true, + // Backend internal error, hope it recovers on reconnect. + Error::BackendInternalError => true, + // Frontend internal error, hope it recovers on reconnect. + Error::FrontendInternalError => true, // Should just retry the IO operation instead of rebuilding the underline connection. Error::SocketRetry(_) => false, // Looks like the peer deliberately disconnected the socket. @@ -218,10 +218,10 @@ pub(crate) fn take_single_file(files: Option>) -> Option { Some(files.swap_remove(0)) } -#[cfg(all(test, feature = "vhost-user-slave"))] -mod dummy_slave; +#[cfg(all(test, feature = "vhost-user-backend"))] +mod dummy_backend; -#[cfg(all(test, feature = "vhost-user-master", feature = "vhost-user-slave"))] +#[cfg(all(test, feature = "vhost-user-frontend", feature = "vhost-user-backend"))] mod tests { use std::fs::File; use std::os::unix::io::AsRawFd; @@ -231,7 +231,7 @@ mod tests { use vmm_sys_util::rand::rand_alphanumerics; use vmm_sys_util::tempfile::TempFile; - use super::dummy_slave::{DummySlaveReqHandler, VIRTIO_FEATURES}; + use super::dummy_backend::{DummyBackendReqHandler, VIRTIO_FEATURES}; use super::message::*; use super::*; use crate::backend::VhostBackend; @@ -244,38 +244,38 @@ mod tests { )) } - fn create_slave(path: P, backend: Arc) -> (Master, SlaveReqHandler) + fn create_backend(path: P, backend: Arc) -> (Frontend, BackendReqHandler) where P: AsRef, - S: VhostUserSlaveReqHandler, + S: VhostUserBackendReqHandler, { let listener = Listener::new(&path, true).unwrap(); - let mut slave_listener = SlaveListener::new(listener, backend).unwrap(); - let master = Master::connect(&path, 1).unwrap(); - (master, slave_listener.accept().unwrap().unwrap()) + let mut backend_listener = BackendListener::new(listener, backend).unwrap(); + let frontend = Frontend::connect(&path, 1).unwrap(); + (frontend, backend_listener.accept().unwrap().unwrap()) } #[test] - fn create_dummy_slave() { - let slave = Arc::new(Mutex::new(DummySlaveReqHandler::new())); + fn create_dummy_backend() { + let backend = Arc::new(Mutex::new(DummyBackendReqHandler::new())); - slave.set_owner().unwrap(); - assert!(slave.set_owner().is_err()); + backend.set_owner().unwrap(); + assert!(backend.set_owner().is_err()); } #[test] fn test_set_owner() { - let slave_be = Arc::new(Mutex::new(DummySlaveReqHandler::new())); + let backend_be = Arc::new(Mutex::new(DummyBackendReqHandler::new())); let path = temp_path(); - let (master, mut slave) = create_slave(path, slave_be.clone()); - - assert!(!slave_be.lock().unwrap().owned); - master.set_owner().unwrap(); - slave.handle_request().unwrap(); - assert!(slave_be.lock().unwrap().owned); - master.set_owner().unwrap(); - assert!(slave.handle_request().is_err()); - assert!(slave_be.lock().unwrap().owned); + let (frontend, mut backend) = create_backend(path, backend_be.clone()); + + assert!(!backend_be.lock().unwrap().owned); + frontend.set_owner().unwrap(); + backend.handle_request().unwrap(); + assert!(backend_be.lock().unwrap().owned); + frontend.set_owner().unwrap(); + assert!(backend.handle_request().is_err()); + assert!(backend_be.lock().unwrap().owned); } #[test] @@ -283,68 +283,68 @@ mod tests { let mbar = Arc::new(Barrier::new(2)); let sbar = mbar.clone(); let path = temp_path(); - let slave_be = Arc::new(Mutex::new(DummySlaveReqHandler::new())); - let (mut master, mut slave) = create_slave(path, slave_be.clone()); + let backend_be = Arc::new(Mutex::new(DummyBackendReqHandler::new())); + let (mut frontend, mut backend) = create_backend(path, backend_be.clone()); thread::spawn(move || { - slave.handle_request().unwrap(); - assert!(slave_be.lock().unwrap().owned); + backend.handle_request().unwrap(); + assert!(backend_be.lock().unwrap().owned); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); assert_eq!( - slave_be.lock().unwrap().acked_features, + backend_be.lock().unwrap().acked_features, VIRTIO_FEATURES & !0x1 ); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); assert_eq!( - slave_be.lock().unwrap().acked_protocol_features, + backend_be.lock().unwrap().acked_protocol_features, VhostUserProtocolFeatures::all().bits() ); sbar.wait(); }); - master.set_owner().unwrap(); + frontend.set_owner().unwrap(); // set virtio features - let features = master.get_features().unwrap(); + let features = frontend.get_features().unwrap(); assert_eq!(features, VIRTIO_FEATURES); - master.set_features(VIRTIO_FEATURES & !0x1).unwrap(); + frontend.set_features(VIRTIO_FEATURES & !0x1).unwrap(); // set vhost protocol features - let features = master.get_protocol_features().unwrap(); + let features = frontend.get_protocol_features().unwrap(); assert_eq!(features.bits(), VhostUserProtocolFeatures::all().bits()); - master.set_protocol_features(features).unwrap(); + frontend.set_protocol_features(features).unwrap(); mbar.wait(); } #[test] - fn test_master_slave_process() { + fn test_frontend_backend_process() { let mbar = Arc::new(Barrier::new(2)); let sbar = mbar.clone(); let path = temp_path(); - let slave_be = Arc::new(Mutex::new(DummySlaveReqHandler::new())); - let (mut master, mut slave) = create_slave(path, slave_be.clone()); + let backend_be = Arc::new(Mutex::new(DummyBackendReqHandler::new())); + let (mut frontend, mut backend) = create_backend(path, backend_be.clone()); thread::spawn(move || { // set_own() - slave.handle_request().unwrap(); - assert!(slave_be.lock().unwrap().owned); + backend.handle_request().unwrap(); + assert!(backend_be.lock().unwrap().owned); // get/set_features() - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); assert_eq!( - slave_be.lock().unwrap().acked_features, + backend_be.lock().unwrap().acked_features, VIRTIO_FEATURES & !0x1 ); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); let mut features = VhostUserProtocolFeatures::all(); @@ -354,64 +354,64 @@ mod tests { } assert_eq!( - slave_be.lock().unwrap().acked_protocol_features, + backend_be.lock().unwrap().acked_protocol_features, features.bits() ); // get_inflight_fd() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // set_inflight_fd() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // get_queue_num() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // set_mem_table() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // get/set_config() - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); - // set_slave_request_fd - slave.handle_request().unwrap(); + // set_backend_request_fd + backend.handle_request().unwrap(); // set_vring_enable - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // set_log_base,set_log_fd() - slave.handle_request().unwrap_err(); - slave.handle_request().unwrap_err(); + backend.handle_request().unwrap_err(); + backend.handle_request().unwrap_err(); // set_vring_xxx - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); + backend.handle_request().unwrap(); // get_max_mem_slots() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // add_mem_region() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); // remove_mem_region() - slave.handle_request().unwrap(); + backend.handle_request().unwrap(); sbar.wait(); }); - master.set_owner().unwrap(); + frontend.set_owner().unwrap(); // set virtio features - let features = master.get_features().unwrap(); + let features = frontend.get_features().unwrap(); assert_eq!(features, VIRTIO_FEATURES); - master.set_features(VIRTIO_FEATURES & !0x1).unwrap(); + frontend.set_features(VIRTIO_FEATURES & !0x1).unwrap(); // set vhost protocol features - let mut features = master.get_protocol_features().unwrap(); + let mut features = frontend.get_protocol_features().unwrap(); assert_eq!(features.bits(), VhostUserProtocolFeatures::all().bits()); // Disable Xen mmap feature. @@ -419,10 +419,10 @@ mod tests { features.remove(VhostUserProtocolFeatures::XEN_MMAP); } - master.set_protocol_features(features).unwrap(); + frontend.set_protocol_features(features).unwrap(); // Retrieve inflight I/O tracking information - let (inflight_info, inflight_file) = master + let (inflight_info, inflight_file) = frontend .get_inflight_fd(&VhostUserInflight { num_queues: 2, queue_size: 256, @@ -430,11 +430,11 @@ mod tests { }) .unwrap(); // Set the buffer back to the backend - master + frontend .set_inflight_fd(&inflight_info, inflight_file.as_raw_fd()) .unwrap(); - let num = master.get_queue_num().unwrap(); + let num = frontend.get_queue_num().unwrap(); assert_eq!(num, 2); let eventfd = vmm_sys_util::eventfd::EventFd::new(0).unwrap(); @@ -445,23 +445,23 @@ mod tests { 0, eventfd.as_raw_fd(), )]; - master.set_mem_table(&mem).unwrap(); + frontend.set_mem_table(&mem).unwrap(); - master + frontend .set_config(0x100, VhostUserConfigFlags::WRITABLE, &[0xa5u8; 4]) .unwrap(); let buf = [0x0u8; 4]; - let (reply_body, reply_payload) = master + let (reply_body, reply_payload) = frontend .get_config(0x100, 4, VhostUserConfigFlags::empty(), &buf) .unwrap(); let offset = reply_body.offset; assert_eq!(offset, 0x100); assert_eq!(&reply_payload, &[0xa5; 4]); - master.set_slave_request_fd(&eventfd).unwrap(); - master.set_vring_enable(0, true).unwrap(); + frontend.set_backend_request_fd(&eventfd).unwrap(); + frontend.set_vring_enable(0, true).unwrap(); - master + frontend .set_log_base( 0, Some(VhostUserDirtyLogRegion { @@ -471,10 +471,10 @@ mod tests { }), ) .unwrap(); - master.set_log_fd(eventfd.as_raw_fd()).unwrap(); + frontend.set_log_fd(eventfd.as_raw_fd()).unwrap(); - master.set_vring_num(0, 256).unwrap(); - master.set_vring_base(0, 0).unwrap(); + frontend.set_vring_num(0, 256).unwrap(); + frontend.set_vring_base(0, 0).unwrap(); let config = VringConfigData { queue_max_size: 256, queue_size: 128, @@ -484,20 +484,20 @@ mod tests { avail_ring_addr: 0x3000, log_addr: Some(0x4000), }; - master.set_vring_addr(0, &config).unwrap(); - master.set_vring_call(0, &eventfd).unwrap(); - master.set_vring_kick(0, &eventfd).unwrap(); - master.set_vring_err(0, &eventfd).unwrap(); + frontend.set_vring_addr(0, &config).unwrap(); + frontend.set_vring_call(0, &eventfd).unwrap(); + frontend.set_vring_kick(0, &eventfd).unwrap(); + frontend.set_vring_err(0, &eventfd).unwrap(); - let max_mem_slots = master.get_max_mem_slots().unwrap(); + let max_mem_slots = frontend.get_max_mem_slots().unwrap(); assert_eq!(max_mem_slots, 32); let region_file: File = TempFile::new().unwrap().into_file(); let region = VhostUserMemoryRegionInfo::new(0x10_0000, 0x10_0000, 0, 0, region_file.as_raw_fd()); - master.add_mem_region(®ion).unwrap(); + frontend.add_mem_region(®ion).unwrap(); - master.remove_mem_region(®ion).unwrap(); + frontend.remove_mem_region(®ion).unwrap(); mbar.wait(); } @@ -514,8 +514,8 @@ mod tests { #[test] fn test_should_reconnect() { assert!(Error::PartialMessage.should_reconnect()); - assert!(Error::SlaveInternalError.should_reconnect()); - assert!(Error::MasterInternalError.should_reconnect()); + assert!(Error::BackendInternalError.should_reconnect()); + assert!(Error::FrontendInternalError.should_reconnect()); assert!(!Error::InvalidParam.should_reconnect()); assert!(!Error::InvalidOperation("reason").should_reconnect()); assert!( diff --git a/crates/vhost/src/vhost_user/slave.rs b/crates/vhost/src/vhost_user/slave.rs deleted file mode 100644 index fb65c41b..00000000 --- a/crates/vhost/src/vhost_user/slave.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -//! Traits and Structs for vhost-user slave. - -use std::sync::Arc; - -use super::connection::{Endpoint, Listener}; -use super::message::*; -use super::{Result, SlaveReqHandler, VhostUserSlaveReqHandler}; - -/// Vhost-user slave side connection listener. -pub struct SlaveListener { - listener: Listener, - backend: Option>, -} - -/// Sets up a listener for incoming master connections, and handles construction -/// of a Slave on success. -impl SlaveListener { - /// Create a unix domain socket for incoming master connections. - pub fn new(listener: Listener, backend: Arc) -> Result { - Ok(SlaveListener { - listener, - backend: Some(backend), - }) - } - - /// Accept an incoming connection from the master, returning Some(Slave) on - /// success, or None if the socket is nonblocking and no incoming connection - /// was detected - pub fn accept(&mut self) -> Result>> { - if let Some(fd) = self.listener.accept()? { - return Ok(Some(SlaveReqHandler::new( - Endpoint::::from_stream(fd), - self.backend.take().unwrap(), - ))); - } - Ok(None) - } - - /// Change blocking status on the listener. - pub fn set_nonblocking(&self, block: bool) -> Result<()> { - self.listener.set_nonblocking(block) - } -} - -#[cfg(test)] -mod tests { - use std::sync::Mutex; - - use super::*; - use crate::vhost_user::dummy_slave::DummySlaveReqHandler; - - #[test] - fn test_slave_listener_set_nonblocking() { - let backend = Arc::new(Mutex::new(DummySlaveReqHandler::new())); - let listener = - Listener::new("/tmp/vhost_user_lib_unit_test_slave_nonblocking", true).unwrap(); - let slave_listener = SlaveListener::new(listener, backend).unwrap(); - - slave_listener.set_nonblocking(true).unwrap(); - slave_listener.set_nonblocking(false).unwrap(); - slave_listener.set_nonblocking(false).unwrap(); - slave_listener.set_nonblocking(true).unwrap(); - slave_listener.set_nonblocking(true).unwrap(); - } - - #[cfg(feature = "vhost-user-master")] - #[test] - fn test_slave_listener_accept() { - use super::super::Master; - - let path = "/tmp/vhost_user_lib_unit_test_slave_accept"; - let backend = Arc::new(Mutex::new(DummySlaveReqHandler::new())); - let listener = Listener::new(path, true).unwrap(); - let mut slave_listener = SlaveListener::new(listener, backend).unwrap(); - - slave_listener.set_nonblocking(true).unwrap(); - assert!(slave_listener.accept().unwrap().is_none()); - assert!(slave_listener.accept().unwrap().is_none()); - - let _master = Master::connect(path, 1).unwrap(); - let _slave = slave_listener.accept().unwrap().unwrap(); - } -}