• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 pub mod sys;
6 
7 use anyhow::anyhow;
8 use anyhow::bail;
9 use anyhow::Context;
10 use base::error;
11 use base::AsRawDescriptors;
12 use cros_async::EventAsync;
13 use cros_async::Executor;
14 use cros_async::IntoAsync;
15 use cros_async::TaskHandle;
16 use futures::channel::oneshot;
17 use futures::pin_mut;
18 use futures::select_biased;
19 use futures::FutureExt;
20 use net_util::TapT;
21 use once_cell::sync::OnceCell;
22 use serde::Deserialize;
23 use serde::Serialize;
24 pub use sys::start_device as run_net_device;
25 pub use sys::Options;
26 use vm_memory::GuestMemory;
27 use vmm_vhost::message::VhostUserProtocolFeatures;
28 use zerocopy::AsBytes;
29 
30 use crate::virtio;
31 use crate::virtio::net::build_config;
32 use crate::virtio::net::process_ctrl;
33 use crate::virtio::net::process_tx;
34 use crate::virtio::net::virtio_features_to_tap_offload;
35 use crate::virtio::vhost::user::device::handler::DeviceRequestHandler;
36 use crate::virtio::vhost::user::device::handler::Error as DeviceError;
37 use crate::virtio::vhost::user::device::handler::VhostUserDevice;
38 use crate::virtio::vhost::user::VhostUserDeviceBuilder;
39 use crate::virtio::Interrupt;
40 use crate::virtio::Queue;
41 
42 thread_local! {
43     pub(crate) static NET_EXECUTOR: OnceCell<Executor> = OnceCell::new();
44 }
45 
46 // TODO(b/188947559): Come up with better way to include these constants. Compiler errors happen
47 // if they are kept in the trait.
48 const MAX_QUEUE_NUM: usize = 3; /* rx, tx, ctrl */
49 
run_tx_queue<T: TapT>( mut queue: Queue, mut tap: T, doorbell: Interrupt, kick_evt: EventAsync, mut stop_rx: oneshot::Receiver<()>, ) -> Queue50 async fn run_tx_queue<T: TapT>(
51     mut queue: Queue,
52     mut tap: T,
53     doorbell: Interrupt,
54     kick_evt: EventAsync,
55     mut stop_rx: oneshot::Receiver<()>,
56 ) -> Queue {
57     let kick_evt_future = kick_evt.next_val().fuse();
58     pin_mut!(kick_evt_future);
59     loop {
60         select_biased! {
61             kick = kick_evt_future => {
62                 kick_evt_future.set(kick_evt.next_val().fuse());
63                 if let Err(e) = kick {
64                     error!("Failed to read kick event for tx queue: {}", e);
65                     break;
66                 }
67             }
68             _ = stop_rx => {
69                 break;
70             }
71         }
72 
73         process_tx(&doorbell, &mut queue, &mut tap);
74     }
75     queue
76 }
77 
run_ctrl_queue<T: TapT>( mut queue: Queue, mut tap: T, doorbell: Interrupt, kick_evt: EventAsync, acked_features: u64, vq_pairs: u16, mut stop_rx: oneshot::Receiver<()>, ) -> Queue78 async fn run_ctrl_queue<T: TapT>(
79     mut queue: Queue,
80     mut tap: T,
81     doorbell: Interrupt,
82     kick_evt: EventAsync,
83     acked_features: u64,
84     vq_pairs: u16,
85     mut stop_rx: oneshot::Receiver<()>,
86 ) -> Queue {
87     let kick_evt_future = kick_evt.next_val().fuse();
88     pin_mut!(kick_evt_future);
89     loop {
90         select_biased! {
91             kick = kick_evt_future => {
92                 kick_evt_future.set(kick_evt.next_val().fuse());
93                 if let Err(e) = kick {
94                     error!("Failed to read kick event for tx queue: {}", e);
95                     break;
96                 }
97             }
98             _ = stop_rx => {
99                 break;
100             }
101         }
102 
103         if let Err(e) = process_ctrl(&doorbell, &mut queue, &mut tap, acked_features, vq_pairs) {
104             error!("Failed to process ctrl queue: {}", e);
105             break;
106         }
107     }
108     queue
109 }
110 
111 pub struct NetBackend<T: TapT + IntoAsync> {
112     tap: T,
113     avail_features: u64,
114     acked_features: u64,
115     acked_protocol_features: VhostUserProtocolFeatures,
116     mtu: u16,
117     #[cfg(all(windows, feature = "slirp"))]
118     slirp_kill_event: base::Event,
119     workers: [Option<(TaskHandle<Queue>, oneshot::Sender<()>)>; MAX_QUEUE_NUM],
120 }
121 
122 #[derive(Serialize, Deserialize)]
123 pub struct NetBackendSnapshot {
124     acked_feature: u64,
125 }
126 
127 impl<T: 'static> NetBackend<T>
128 where
129     T: TapT + IntoAsync,
130 {
max_vq_pairs() -> usize131     fn max_vq_pairs() -> usize {
132         MAX_QUEUE_NUM / 2
133     }
134 }
135 
136 impl<T: 'static> AsRawDescriptors for NetBackend<T>
137 where
138     T: TapT + IntoAsync + AsRawDescriptors,
139 {
as_raw_descriptors(&self) -> Vec<base::RawDescriptor>140     fn as_raw_descriptors(&self) -> Vec<base::RawDescriptor> {
141         self.tap.as_raw_descriptors()
142     }
143 }
144 
145 impl<T: 'static> VhostUserDevice for NetBackend<T>
146 where
147     T: TapT + IntoAsync,
148 {
max_queue_num(&self) -> usize149     fn max_queue_num(&self) -> usize {
150         MAX_QUEUE_NUM
151     }
152 
features(&self) -> u64153     fn features(&self) -> u64 {
154         self.avail_features
155     }
156 
ack_features(&mut self, value: u64) -> anyhow::Result<()>157     fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
158         let unrequested_features = value & !self.avail_features;
159         if unrequested_features != 0 {
160             bail!("invalid features are given: {:#x}", unrequested_features);
161         }
162 
163         self.acked_features |= value;
164 
165         self.tap
166             .set_offload(virtio_features_to_tap_offload(self.acked_features))
167             .context("failed to set tap offload to match features")?;
168 
169         Ok(())
170     }
171 
acked_features(&self) -> u64172     fn acked_features(&self) -> u64 {
173         self.acked_features
174     }
175 
protocol_features(&self) -> VhostUserProtocolFeatures176     fn protocol_features(&self) -> VhostUserProtocolFeatures {
177         VhostUserProtocolFeatures::CONFIG
178     }
179 
ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()>180     fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
181         let features = VhostUserProtocolFeatures::from_bits(features)
182             .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
183         let supported = self.protocol_features();
184         self.acked_protocol_features = features & supported;
185         Ok(())
186     }
187 
acked_protocol_features(&self) -> u64188     fn acked_protocol_features(&self) -> u64 {
189         self.acked_protocol_features.bits()
190     }
191 
read_config(&self, offset: u64, data: &mut [u8])192     fn read_config(&self, offset: u64, data: &mut [u8]) {
193         let config_space = build_config(Self::max_vq_pairs() as u16, self.mtu, None);
194         virtio::copy_config(data, 0, config_space.as_bytes(), offset);
195     }
196 
reset(&mut self)197     fn reset(&mut self) {}
198 
start_queue( &mut self, idx: usize, queue: virtio::Queue, mem: GuestMemory, doorbell: Interrupt, ) -> anyhow::Result<()>199     fn start_queue(
200         &mut self,
201         idx: usize,
202         queue: virtio::Queue,
203         mem: GuestMemory,
204         doorbell: Interrupt,
205     ) -> anyhow::Result<()> {
206         sys::start_queue(self, idx, queue, mem, doorbell)
207     }
208 
stop_queue(&mut self, idx: usize) -> anyhow::Result<virtio::Queue>209     fn stop_queue(&mut self, idx: usize) -> anyhow::Result<virtio::Queue> {
210         if let Some((task, stop_tx)) = self.workers.get_mut(idx).and_then(Option::take) {
211             if stop_tx.send(()).is_err() {
212                 return Err(anyhow!("Failed to request stop for net queue future"));
213             }
214 
215             // Wait for queue_task to be aborted.
216             let queue = NET_EXECUTOR
217                 .with(|ex| {
218                     let ex = ex.get().expect("Executor not initialized");
219                     ex.run_until(task)
220                 })
221                 .context("Failed to resolve queue worker future")?;
222 
223             Ok(queue)
224         } else {
225             Err(anyhow::Error::new(DeviceError::WorkerNotFound))
226         }
227     }
228 
snapshot(&self) -> anyhow::Result<Vec<u8>>229     fn snapshot(&self) -> anyhow::Result<Vec<u8>> {
230         serde_json::to_vec(&NetBackendSnapshot {
231             acked_feature: self.acked_features,
232         })
233         .context("Failed to serialize NetBackendSnapshot")
234     }
235 
restore(&mut self, data: Vec<u8>) -> anyhow::Result<()>236     fn restore(&mut self, data: Vec<u8>) -> anyhow::Result<()> {
237         let net_backend_snapshot: NetBackendSnapshot =
238             serde_json::from_slice(&data).context("Failed to deserialize NetBackendSnapshot")?;
239         self.acked_features = net_backend_snapshot.acked_feature;
240         Ok(())
241     }
242 }
243 
244 impl<T> VhostUserDeviceBuilder for NetBackend<T>
245 where
246     T: TapT + IntoAsync + 'static,
247 {
build(self: Box<Self>, ex: &Executor) -> anyhow::Result<Box<dyn vmm_vhost::Backend>>248     fn build(self: Box<Self>, ex: &Executor) -> anyhow::Result<Box<dyn vmm_vhost::Backend>> {
249         NET_EXECUTOR.with(|thread_ex| {
250             let _ = thread_ex.set(ex.clone());
251         });
252         let handler = DeviceRequestHandler::new(*self);
253 
254         Ok(Box::new(handler))
255     }
256 }
257