Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/virtio/net/sys/windows.rs
5394 views
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
use std::sync::Arc;
10
use std::sync::MutexGuard;
11
12
use base::error;
13
use base::named_pipes::OverlappedWrapper;
14
use base::warn;
15
use base::Event;
16
use base::ReadNotifier;
17
use base::WaitContext;
18
use libc::EEXIST;
19
use net_util::TapT;
20
use sync::Mutex;
21
use virtio_sys::virtio_net;
22
use vm_memory::GuestMemory;
23
24
use super::super::super::base_features;
25
use super::super::super::net::Net;
26
use super::super::super::net::NetError;
27
use super::super::super::net::Token;
28
use super::super::super::net::Worker;
29
use super::super::super::net::MAX_BUFFER_SIZE;
30
use super::super::super::Interrupt;
31
use super::super::super::ProtectionType;
32
use super::super::super::Queue;
33
use super::super::super::Reader;
34
use super::PendingBuffer;
35
36
// This file should not be included at virtio mod level if slirp is not include. In case it is,
37
// throw a user friendly message.
38
#[cfg(not(feature = "slirp"))]
39
compile_error!("Net device without slirp not supported on windows");
40
41
pub fn validate_and_configure_tap<T: TapT>(_tap: &T, _vq_pairs: u16) -> Result<(), NetError> {
42
// No-op for slirp on windows
43
Ok(())
44
}
45
46
pub fn virtio_features_to_tap_offload(_features: u64) -> u32 {
47
// slirp does not support offloads
48
0
49
}
50
51
// Copies a single frame from `self.rx_buf` into the guest. Returns true
52
// if a buffer was used, and false if the frame must be deferred until a buffer
53
// is made available by the driver.
54
fn rx_single_frame(rx_queue: &mut Queue, rx_buf: &mut [u8], rx_count: usize) -> bool {
55
let mut desc_chain = match rx_queue.pop() {
56
Some(desc) => desc,
57
None => return false,
58
};
59
60
match desc_chain.writer.write_all(&rx_buf[0..rx_count]) {
61
Ok(()) => (),
62
Err(ref e) if e.kind() == io::ErrorKind::WriteZero => {
63
warn!(
64
"net: rx: buffer is too small to hold frame of size {}",
65
rx_count
66
);
67
}
68
Err(e) => {
69
warn!("net: rx: failed to write slice: {}", e);
70
}
71
};
72
73
rx_queue.add_used(desc_chain);
74
75
true
76
}
77
78
pub fn process_mrg_rx<T: TapT>(
79
rx_queue: &mut Queue,
80
tap: &mut T,
81
pending_buffer: &mut Option<PendingBuffer>,
82
) -> result::Result<(), NetError> {
83
unimplemented!("Unimplemented on Windows")
84
}
85
86
pub fn process_rx<T: TapT>(
87
rx_queue: &mut Queue,
88
tap: &mut T,
89
rx_buf: &mut [u8],
90
deferred_rx: &mut bool,
91
rx_count: &mut usize,
92
overlapped_wrapper: &mut OverlappedWrapper,
93
) -> bool {
94
let mut needs_interrupt = false;
95
let mut first_frame = true;
96
97
// Read as many frames as possible.
98
loop {
99
let res = if *deferred_rx {
100
// The existing buffer still needs to be sent to the rx queue.
101
Ok(*rx_count)
102
} else {
103
tap.try_read_result(overlapped_wrapper)
104
};
105
match res {
106
Ok(count) => {
107
*rx_count = count;
108
if !rx_single_frame(rx_queue, rx_buf, *rx_count) {
109
*deferred_rx = true;
110
break;
111
} else if first_frame {
112
rx_queue.trigger_interrupt();
113
first_frame = false;
114
} else {
115
needs_interrupt = true;
116
}
117
118
// SAFETY: safe because rx_buf & overlapped_wrapper live until
119
// the overlapped operation completes and are not used in any
120
// other operations until that time.
121
match unsafe { tap.read_overlapped(rx_buf, overlapped_wrapper) } {
122
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
123
warn!("net: rx: read_overlapped failed: {}", e);
124
break;
125
}
126
Err(e) => {
127
panic!("read_overlapped failed: {e}");
128
}
129
_ => {}
130
}
131
132
// We were able to dispatch a frame to the guest, so we can resume normal RX
133
// service.
134
*deferred_rx = false;
135
}
136
Err(e) => {
137
// `try_read_result()` shouldn't return any error other than
138
// `ERROR_IO_INCOMPLETE`. If it does, we need to retry the
139
// overlapped operation.
140
if e.kind() != std::io::ErrorKind::WouldBlock {
141
warn!("net: rx: failed to read tap: {}", e);
142
// SAFETY: safe because rx_buf & overlapped_wrapper live until
143
// the overlapped operation completes and are not used in any
144
// other operations until that time.
145
match unsafe { tap.read_overlapped(rx_buf, overlapped_wrapper) } {
146
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
147
warn!("net: rx: read_overlapped failed: {}", e);
148
break;
149
}
150
Err(e) => {
151
panic!("read_overlapped failed: {e}");
152
}
153
_ => {}
154
}
155
}
156
break;
157
}
158
}
159
}
160
161
needs_interrupt
162
}
163
164
pub fn process_tx<T: TapT>(tx_queue: &mut Queue, tap: &mut T) {
165
// Reads up to `buf.len()` bytes or until there is no more data in `r`, whichever
166
// is smaller.
167
fn read_to_end(r: &mut Reader, buf: &mut [u8]) -> io::Result<usize> {
168
let mut count = 0;
169
while count < buf.len() {
170
match r.read(&mut buf[count..]) {
171
Ok(0) => break,
172
Ok(n) => count += n,
173
Err(e) => return Err(e),
174
}
175
}
176
177
Ok(count)
178
}
179
180
while let Some(mut desc_chain) = tx_queue.pop() {
181
let mut frame = [0u8; MAX_BUFFER_SIZE];
182
match read_to_end(&mut desc_chain.reader, &mut frame[..]) {
183
Ok(len) => {
184
// We need to copy frame into continuous buffer before writing it to
185
// slirp because tap requires frame to complete in a single write.
186
if let Err(err) = tap.write_all(&frame[..len]) {
187
error!("net: tx: failed to write to tap: {}", err);
188
}
189
}
190
Err(e) => error!("net: tx: failed to read frame into buffer: {}", e),
191
}
192
193
tx_queue.add_used(desc_chain);
194
}
195
196
tx_queue.trigger_interrupt();
197
}
198
199
impl<T> Worker<T>
200
where
201
T: TapT + ReadNotifier,
202
{
203
pub(super) fn process_rx_slirp(&mut self) -> bool {
204
process_rx(
205
&mut self.rx_queue,
206
&mut self.tap,
207
&mut self.rx_buf,
208
&mut self.deferred_rx,
209
&mut self.rx_count,
210
&mut self.overlapped_wrapper,
211
)
212
}
213
214
pub(in crate::virtio) fn handle_rx_token(
215
&mut self,
216
wait_ctx: &WaitContext<Token>,
217
_pending_buffer: &mut PendingBuffer,
218
) -> result::Result<(), NetError> {
219
let mut needs_interrupt = false;
220
// Process a deferred frame first if available. Don't read from tap again
221
// until we manage to receive this deferred frame.
222
if self.deferred_rx {
223
if rx_single_frame(&mut self.rx_queue, &mut self.rx_buf, self.rx_count) {
224
self.deferred_rx = false;
225
needs_interrupt = true;
226
} else {
227
// There is an outstanding deferred frame and the guest has not yet
228
// made any buffers available. Remove the tapfd from the poll
229
// context until more are made available.
230
wait_ctx
231
.delete(&self.tap)
232
.map_err(NetError::EventRemoveTap)?;
233
return Ok(());
234
}
235
}
236
needs_interrupt |= self.process_rx_slirp();
237
if needs_interrupt {
238
self.rx_queue.trigger_interrupt();
239
}
240
Ok(())
241
}
242
243
pub(in crate::virtio) fn handle_rx_queue(
244
&mut self,
245
wait_ctx: &WaitContext<Token>,
246
_tap_polling_enabled: bool,
247
) -> result::Result<(), NetError> {
248
// There should be a buffer available now to receive the frame into.
249
if self.deferred_rx && rx_single_frame(&mut self.rx_queue, &mut self.rx_buf, self.rx_count)
250
{
251
// The guest has made buffers available, so add the tap back to the
252
// poll context in case it was removed.
253
match wait_ctx.add(&self.tap, Token::RxTap) {
254
Ok(_) => {}
255
Err(e) if e.errno() == EEXIST => {}
256
Err(e) => {
257
return Err(NetError::EventAddTap(e));
258
}
259
}
260
self.deferred_rx = false;
261
self.rx_queue.trigger_interrupt();
262
}
263
Ok(())
264
}
265
}
266
267