• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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