blob: a526ab12df1691397516b91cbfffc79ac9034e43 [file] [log] [blame] [view]
Jeongik Cha777a4132023-09-14 16:36:02 +09001# vhost-user-backend
2
3## Design
4
5The `vhost-user-backend` crate provides a framework to implement `vhost-user` backend services,
6which includes following external public APIs:
7- A daemon control object (`VhostUserDaemon`) to start and stop the service daemon.
8- A vhost-user backend trait (`VhostUserBackendMut`) to handle vhost-user control messages and virtio
9 messages.
10- A vring access trait (`VringT`) to access virtio queues, and three implementations of the trait:
11 `VringState`, `VringMutex` and `VringRwLock`.
12
13## Usage
14The `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`:
15```rust
16pub struct VhostUserDaemon<S, V, B = ()>
17where
18 S: VhostUserBackend<V, B>,
19 V: VringT<GM<B>> + Clone + Send + Sync + 'static,
20 B: Bitmap + 'static,
21{
22 pub fn new(name: String, backend: S, atomic_mem: GuestMemoryAtomic<GuestMemoryMmap<B>>) -> Result<Self>;
23 pub fn start(&mut self, listener: Listener) -> Result<()>;
24 pub fn wait(&mut self) -> Result<()>;
25 pub fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, V, B>>>;
26}
27```
28
29### Create a `VhostUserDaemon` Instance
30The `VhostUserDaemon::new()` creates an instance of `VhostUserDaemon` object. The client needs to
31pass in an `VhostUserBackend` object, which will be used to configure the `VhostUserDaemon`
32instance, handle control messages from the vhost-user master and handle virtio requests from
33virtio queues. A group of working threads will be created to handle virtio requests from configured
34virtio queues.
35
36### Start the `VhostUserDaemon`
37The `VhostUserDaemon::start()` method waits for an incoming connection from the vhost-user masters
38on the `listener`. Once a connection is ready, a main thread will be created to handle vhost-user
39messages from the vhost-user master.
40
41### Stop the `VhostUserDaemon`
42The `VhostUserDaemon::stop()` method waits for the main thread to exit. An exit event must be sent
43to the main thread by writing to the `exit_event` EventFd before waiting for it to exit.
44
45### Threading Model
46The main thread and virtio queue working threads will concurrently access the underlying virtio
47queues, so all virtio queue in multi-threading model. But the main thread only accesses virtio
48queues for configuration, so client could adopt locking policies to optimize for the virtio queue
49working threads.
50
51## Example
52Example code to handle virtio messages from a virtio queue:
53```rust
54impl VhostUserBackendMut for VhostUserService {
55 fn process_queue(&mut self, vring: &VringMutex) -> Result<bool> {
56 let mut used_any = false;
57 let mem = match &self.mem {
58 Some(m) => m.memory(),
59 None => return Err(Error::NoMemoryConfigured),
60 };
61
62 let mut vring_state = vring.get_mut();
63
64 while let Some(avail_desc) = vring_state
65 .get_queue_mut()
66 .iter()
67 .map_err(|_| Error::IterateQueue)?
68 .next()
69 {
70 // Process the request...
71
72 if self.event_idx {
73 if vring_state.add_used(head_index, 0).is_err() {
74 warn!("Couldn't return used descriptors to the ring");
75 }
76
77 match vring_state.needs_notification() {
78 Err(_) => {
79 warn!("Couldn't check if queue needs to be notified");
80 vring_state.signal_used_queue().unwrap();
81 }
82 Ok(needs_notification) => {
83 if needs_notification {
84 vring_state.signal_used_queue().unwrap();
85 }
86 }
87 }
88 } else {
89 if vring_state.add_used(head_index, 0).is_err() {
90 warn!("Couldn't return used descriptors to the ring");
91 }
92 vring_state.signal_used_queue().unwrap();
93 }
94 }
95
96 Ok(used_any)
97 }
98}
99```
100
101## Xen support
102
103Supporting Xen requires special handling while mapping the guest memory. The
104`vm-memory` crate implements xen memory mapping support via a separate feature
105`xen`, and this crate uses the same feature name to enable Xen support.
106
107Also, for xen mappings, the memory regions passed by the frontend contains few
108extra fields as described in the vhost-user protocol documentation.
109
110It was decided by the `rust-vmm` maintainers to keep the interface simple and
111build the crate for either standard Unix memory mapping or Xen, and not both.
112
113## License
114
115This project is licensed under
116
117- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0