Import vhost-user-backend Bug: 277909042 Test: build Change-Id: I51ab86da2303c2f28af854460a2826a22e530ca0
diff --git a/README.md b/README.md new file mode 100644 index 0000000..a526ab1 --- /dev/null +++ b/README.md
@@ -0,0 +1,117 @@ +# vhost-user-backend + +## Design + +The `vhost-user-backend` crate provides a framework to implement `vhost-user` backend services, +which includes following external public APIs: +- A daemon control object (`VhostUserDaemon`) to start and stop the service daemon. +- A vhost-user backend trait (`VhostUserBackendMut`) to handle vhost-user control messages and virtio + messages. +- A vring access trait (`VringT`) to access virtio queues, and three implementations of the trait: + `VringState`, `VringMutex` and `VringRwLock`. + +## Usage +The `vhost-user-backend` crate provides a framework to implement vhost-user backend services. The main interface provided by `vhost-user-backend` library is the `struct VhostUserDaemon`: +```rust +pub struct VhostUserDaemon<S, V, B = ()> +where + S: VhostUserBackend<V, B>, + V: VringT<GM<B>> + Clone + Send + Sync + 'static, + B: Bitmap + 'static, +{ + pub fn new(name: String, backend: S, atomic_mem: GuestMemoryAtomic<GuestMemoryMmap<B>>) -> Result<Self>; + pub fn start(&mut self, listener: Listener) -> Result<()>; + pub fn wait(&mut self) -> Result<()>; + pub fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, V, B>>>; +} +``` + +### 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 +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 +on the `listener`. Once a connection is ready, a main thread will be created to handle vhost-user +messages from the vhost-user master. + +### Stop the `VhostUserDaemon` +The `VhostUserDaemon::stop()` method waits for the main thread to exit. An exit event must be sent +to the main thread by writing to the `exit_event` EventFd before waiting for it to exit. + +### Threading Model +The main thread and virtio queue working threads will concurrently access the underlying virtio +queues, so all virtio queue in multi-threading model. But the main thread only accesses virtio +queues for configuration, so client could adopt locking policies to optimize for the virtio queue +working threads. + +## Example +Example code to handle virtio messages from a virtio queue: +```rust +impl VhostUserBackendMut for VhostUserService { + fn process_queue(&mut self, vring: &VringMutex) -> Result<bool> { + let mut used_any = false; + let mem = match &self.mem { + Some(m) => m.memory(), + None => return Err(Error::NoMemoryConfigured), + }; + + let mut vring_state = vring.get_mut(); + + while let Some(avail_desc) = vring_state + .get_queue_mut() + .iter() + .map_err(|_| Error::IterateQueue)? + .next() + { + // Process the request... + + if self.event_idx { + if vring_state.add_used(head_index, 0).is_err() { + warn!("Couldn't return used descriptors to the ring"); + } + + match vring_state.needs_notification() { + Err(_) => { + warn!("Couldn't check if queue needs to be notified"); + vring_state.signal_used_queue().unwrap(); + } + Ok(needs_notification) => { + if needs_notification { + vring_state.signal_used_queue().unwrap(); + } + } + } + } else { + if vring_state.add_used(head_index, 0).is_err() { + warn!("Couldn't return used descriptors to the ring"); + } + vring_state.signal_used_queue().unwrap(); + } + } + + Ok(used_any) + } +} +``` + +## Xen support + +Supporting Xen requires special handling while mapping the guest memory. The +`vm-memory` crate implements xen memory mapping support via a separate feature +`xen`, and this crate uses the same feature name to enable Xen support. + +Also, for xen mappings, the memory regions passed by the frontend contains few +extra fields as described in the vhost-user protocol documentation. + +It was decided by the `rust-vmm` maintainers to keep the interface simple and +build the crate for either standard Unix memory mapping or Xen, and not both. + +## License + +This project is licensed under + +- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0