1 // Copyright 2022 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 use std::io;
6 use std::io::Read;
7 use std::io::Write;
8 use std::result;
9
10 use base::error;
11 use base::named_pipes::OverlappedWrapper;
12 use base::warn;
13 use base::Event;
14 use base::ReadNotifier;
15 use base::WaitContext;
16 use libc::EEXIST;
17 use net_util::TapT;
18 use virtio_sys::virtio_net;
19 use vm_memory::GuestMemory;
20
21 use super::super::super::base_features;
22 use super::super::super::net::Net;
23 use super::super::super::net::NetError;
24 use super::super::super::net::Token;
25 use super::super::super::net::Worker;
26 use super::super::super::net::MAX_BUFFER_SIZE;
27 use super::super::super::ProtectionType;
28 use super::super::super::Queue;
29 use super::super::super::Reader;
30 use super::super::super::SignalableInterrupt;
31 use super::super::super::Writer;
32
33 // Copies a single frame from `self.rx_buf` into the guest. Returns true
34 // if a buffer was used, and false if the frame must be deferred until a buffer
35 // is made available by the driver.
rx_single_frame( rx_queue: &mut Queue, mem: &GuestMemory, rx_buf: &mut [u8], rx_count: usize, ) -> bool36 fn rx_single_frame(
37 rx_queue: &mut Queue,
38 mem: &GuestMemory,
39 rx_buf: &mut [u8],
40 rx_count: usize,
41 ) -> bool {
42 let desc_chain = match rx_queue.pop(mem) {
43 Some(desc) => desc,
44 None => return false,
45 };
46
47 let index = desc_chain.index;
48 let bytes_written = match Writer::new(mem.clone(), desc_chain) {
49 Ok(mut writer) => {
50 match writer.write_all(&rx_buf[0..rx_count]) {
51 Ok(()) => (),
52 Err(ref e) if e.kind() == io::ErrorKind::WriteZero => {
53 warn!(
54 "net: rx: buffer is too small to hold frame of size {}",
55 rx_count
56 );
57 }
58 Err(e) => {
59 warn!("net: rx: failed to write slice: {}", e);
60 }
61 };
62
63 writer.bytes_written() as u32
64 }
65 Err(e) => {
66 error!("net: failed to create Writer: {}", e);
67 0
68 }
69 };
70
71 rx_queue.add_used(mem, index, bytes_written);
72
73 true
74 }
75
process_rx<I: SignalableInterrupt, T: TapT>( interrupt: &I, rx_queue: &mut Queue, mem: &GuestMemory, tap: &mut T, rx_buf: &mut [u8], deferred_rx: &mut bool, rx_count: &mut usize, overlapped_wrapper: &mut OverlappedWrapper, ) -> bool76 pub fn process_rx<I: SignalableInterrupt, T: TapT>(
77 interrupt: &I,
78 rx_queue: &mut Queue,
79 mem: &GuestMemory,
80 tap: &mut T,
81 rx_buf: &mut [u8],
82 deferred_rx: &mut bool,
83 rx_count: &mut usize,
84 overlapped_wrapper: &mut OverlappedWrapper,
85 ) -> bool {
86 let mut needs_interrupt = false;
87 let mut first_frame = true;
88
89 // Read as many frames as possible.
90 loop {
91 let res = if *deferred_rx {
92 // The existing buffer still needs to be sent to the rx queue.
93 Ok(*rx_count)
94 } else {
95 tap.try_read_result(overlapped_wrapper)
96 };
97 match res {
98 Ok(count) => {
99 *rx_count = count;
100 if !rx_single_frame(rx_queue, mem, rx_buf, *rx_count) {
101 *deferred_rx = true;
102 break;
103 } else if first_frame {
104 interrupt.signal_used_queue(rx_queue.vector());
105 first_frame = false;
106 } else {
107 needs_interrupt = true;
108 }
109
110 // SAFETY: safe because rx_buf & overlapped_wrapper live until
111 // the overlapped operation completes and are not used in any
112 // other operations until that time.
113 match unsafe { tap.read_overlapped(rx_buf, overlapped_wrapper) } {
114 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
115 warn!("net: rx: read_overlapped failed: {}", e);
116 break;
117 }
118 Err(e) => {
119 panic!("read_overlapped failed: {}", e);
120 }
121 _ => {}
122 }
123
124 // We were able to dispatch a frame to the guest, so we can resume normal RX
125 // service.
126 *deferred_rx = false;
127 }
128 Err(e) => {
129 // `try_read_result()` shouldn't return any error other than
130 // `ERROR_IO_INCOMPLETE`. If it does, we need to retry the
131 // overlapped operation.
132 if e.kind() != std::io::ErrorKind::WouldBlock {
133 warn!("net: rx: failed to read tap: {}", e);
134 // SAFETY: safe because rx_buf & overlapped_wrapper live until
135 // the overlapped operation completes and are not used in any
136 // other operations until that time.
137 match unsafe { tap.read_overlapped(rx_buf, overlapped_wrapper) } {
138 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
139 warn!("net: rx: read_overlapped failed: {}", e);
140 break;
141 }
142 Err(e) => {
143 panic!("read_overlapped failed: {}", e);
144 }
145 _ => {}
146 }
147 }
148 break;
149 }
150 }
151 }
152
153 needs_interrupt
154 }
155
process_tx<I: SignalableInterrupt, T: TapT>( interrupt: &I, tx_queue: &mut Queue, mem: &GuestMemory, tap: &mut T, )156 pub fn process_tx<I: SignalableInterrupt, T: TapT>(
157 interrupt: &I,
158 tx_queue: &mut Queue,
159 mem: &GuestMemory,
160 tap: &mut T,
161 ) {
162 // Reads up to `buf.len()` bytes or until there is no more data in `r`, whichever
163 // is smaller.
164 fn read_to_end(mut r: Reader, buf: &mut [u8]) -> io::Result<usize> {
165 let mut count = 0;
166 while count < buf.len() {
167 match r.read(&mut buf[count..]) {
168 Ok(0) => break,
169 Ok(n) => count += n,
170 Err(e) => return Err(e),
171 }
172 }
173
174 Ok(count)
175 }
176
177 while let Some(desc_chain) = tx_queue.pop(mem) {
178 let index = desc_chain.index;
179
180 match Reader::new(mem.clone(), desc_chain) {
181 Ok(reader) => {
182 let mut frame = [0u8; MAX_BUFFER_SIZE];
183 match read_to_end(reader, &mut frame[..]) {
184 Ok(len) => {
185 // We need to copy frame into continuous buffer before writing it to
186 // slirp because tap requires frame to complete in a single write.
187 if let Err(err) = tap.write_all(&frame[..len]) {
188 error!("net: tx: failed to write to tap: {}", err);
189 }
190 }
191 Err(e) => error!("net: tx: failed to read frame into buffer: {}", e),
192 }
193 }
194 Err(e) => error!("net: failed to create Reader: {}", e),
195 }
196
197 tx_queue.add_used(mem, index, 0);
198 }
199
200 tx_queue.trigger_interrupt(mem, interrupt);
201 }
202
203 pub trait NetExt {
new_slirp( #[cfg(feature = "slirp-ring-capture")] slirp_capture_file: &Option<String>, ) -> Result<Net<net_util::Slirp>, NetError>204 fn new_slirp(
205 #[cfg(feature = "slirp-ring-capture")] slirp_capture_file: &Option<String>,
206 ) -> Result<Net<net_util::Slirp>, NetError>;
207 }
208
209 impl<T> NetExt for Net<T>
210 where
211 T: TapT + ReadNotifier,
212 {
213 /// Creates a new virtio network device from a pseudo-TAP device, provided by Slirp.
new_slirp( #[cfg(feature = "slirp-ring-capture")] slirp_capture_file: &Option<String>, ) -> Result<Net<net_util::Slirp>, NetError>214 fn new_slirp(
215 #[cfg(feature = "slirp-ring-capture")] slirp_capture_file: &Option<String>,
216 ) -> Result<Net<net_util::Slirp>, NetError> {
217 let avail_features =
218 base_features(ProtectionType::Unprotected) | 1 << virtio_net::VIRTIO_NET_F_CTRL_VQ;
219 let slirp_kill_evt = Event::new().map_err(NetError::CreateKillEvent)?;
220 let slirp = net_util::Slirp::new(
221 slirp_kill_evt
222 .try_clone()
223 .map_err(NetError::CreateKillEvent)?,
224 #[cfg(feature = "slirp-ring-capture")]
225 slirp_capture_file,
226 )
227 .map_err(NetError::SlirpCreateError)?;
228
229 Net::new_internal(
230 vec![slirp],
231 avail_features,
232 1500,
233 None,
234 Some(slirp_kill_evt),
235 )
236 }
237 }
238
239 impl<T> Worker<T>
240 where
241 T: TapT + ReadNotifier,
242 {
process_rx_slirp(&mut self) -> bool243 pub(super) fn process_rx_slirp(&mut self) -> bool {
244 process_rx(
245 &self.interrupt,
246 &mut self.rx_queue,
247 &self.mem,
248 &mut self.tap,
249 &mut self.rx_buf,
250 &mut self.deferred_rx,
251 &mut self.rx_count,
252 &mut self.overlapped_wrapper,
253 )
254 }
255
handle_rx_token( &mut self, wait_ctx: &WaitContext<Token>, ) -> result::Result<(), NetError>256 pub(in crate::virtio) fn handle_rx_token(
257 &mut self,
258 wait_ctx: &WaitContext<Token>,
259 ) -> result::Result<(), NetError> {
260 let mut needs_interrupt = false;
261 // Process a deferred frame first if available. Don't read from tap again
262 // until we manage to receive this deferred frame.
263 if self.deferred_rx {
264 if rx_single_frame(
265 &mut self.rx_queue,
266 &self.mem,
267 &mut self.rx_buf,
268 self.rx_count,
269 ) {
270 self.deferred_rx = false;
271 needs_interrupt = true;
272 } else {
273 // There is an outstanding deferred frame and the guest has not yet
274 // made any buffers available. Remove the tapfd from the poll
275 // context until more are made available.
276 wait_ctx
277 .delete(&self.tap)
278 .map_err(NetError::EventRemoveTap)?;
279 return Ok(());
280 }
281 }
282 needs_interrupt |= self.process_rx_slirp();
283 if needs_interrupt {
284 self.interrupt.signal_used_queue(self.rx_queue.vector());
285 }
286 Ok(())
287 }
288
handle_rx_queue( &mut self, wait_ctx: &WaitContext<Token>, _tap_polling_enabled: bool, ) -> result::Result<(), NetError>289 pub(in crate::virtio) fn handle_rx_queue(
290 &mut self,
291 wait_ctx: &WaitContext<Token>,
292 _tap_polling_enabled: bool,
293 ) -> result::Result<(), NetError> {
294 // There should be a buffer available now to receive the frame into.
295 if self.deferred_rx
296 && rx_single_frame(
297 &mut self.rx_queue,
298 &self.mem,
299 &mut self.rx_buf,
300 self.rx_count,
301 )
302 {
303 // The guest has made buffers available, so add the tap back to the
304 // poll context in case it was removed.
305 match wait_ctx.add(&self.tap, Token::RxTap) {
306 Ok(_) => {}
307 Err(e) if e.errno() == EEXIST => {}
308 Err(e) => {
309 return Err(NetError::EventAddTap(e));
310 }
311 }
312 self.deferred_rx = false;
313 self.interrupt.signal_used_queue(self.rx_queue.vector());
314 }
315 Ok(())
316 }
317 }
318