mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 03:57:24 +00:00
net_util: Add windows slirp support
BUG=b:237011316 TEST=presubmit and tested in wine Change-Id: I1b6160142b8161d4b09d3fd98dfacde354e238b4 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3934818 Reviewed-by: Dennis Kempin <denniskempin@google.com> Commit-Queue: Vikram Auradkar <auradkar@google.com>
This commit is contained in:
parent
75dbd9763e
commit
c4a4dc9b23
14 changed files with 145 additions and 73 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1260,6 +1260,7 @@ dependencies = [
|
||||||
name = "net_util"
|
name = "net_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"base",
|
"base",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cros_async",
|
"cros_async",
|
||||||
|
@ -1269,6 +1270,7 @@ dependencies = [
|
||||||
"metrics",
|
"metrics",
|
||||||
"net_sys",
|
"net_sys",
|
||||||
"pcap-file",
|
"pcap-file",
|
||||||
|
"prebuilts",
|
||||||
"remain",
|
"remain",
|
||||||
"serde",
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
|
|
@ -130,7 +130,7 @@ all-linux = [
|
||||||
"wl-dmabuf",
|
"wl-dmabuf",
|
||||||
"x",
|
"x",
|
||||||
]
|
]
|
||||||
win64 = [ "balloon", "crash_report", "haxm", "stats" ]
|
win64 = [ "balloon", "crash_report", "haxm", "slirp", "stats" ]
|
||||||
arc_quota = ["devices/arc_quota"]
|
arc_quota = ["devices/arc_quota"]
|
||||||
audio = ["devices/audio"]
|
audio = ["devices/audio"]
|
||||||
audio_cras = ["devices/audio_cras"]
|
audio_cras = ["devices/audio_cras"]
|
||||||
|
@ -169,7 +169,7 @@ plugin = ["protos/plugin", "crosvm_plugin", "kvm", "kvm_sys", "protobuf"]
|
||||||
plugin-render-server = []
|
plugin-render-server = []
|
||||||
power-monitor-powerd = ["arch/power-monitor-powerd"]
|
power-monitor-powerd = ["arch/power-monitor-powerd"]
|
||||||
qcow = ["disk/qcow"]
|
qcow = ["disk/qcow"]
|
||||||
slirp = ["devices/slirp"]
|
slirp = ["devices/slirp", "net_util/slirp"]
|
||||||
stats = ["devices/stats"]
|
stats = ["devices/stats"]
|
||||||
tpm = ["devices/tpm"]
|
tpm = ["devices/tpm"]
|
||||||
usb = ["devices/usb"]
|
usb = ["devices/usb"]
|
||||||
|
|
|
@ -15,7 +15,6 @@ mod interrupt;
|
||||||
mod iommu;
|
mod iommu;
|
||||||
mod queue;
|
mod queue;
|
||||||
mod rng;
|
mod rng;
|
||||||
#[cfg(unix)]
|
|
||||||
mod sys;
|
mod sys;
|
||||||
#[cfg(any(feature = "tpm", feature = "vtpm"))]
|
#[cfg(any(feature = "tpm", feature = "vtpm"))]
|
||||||
mod tpm;
|
mod tpm;
|
||||||
|
@ -80,6 +79,8 @@ cfg_if::cfg_if! {
|
||||||
|
|
||||||
#[cfg(feature = "slirp")]
|
#[cfg(feature = "slirp")]
|
||||||
pub use self::net::*;
|
pub use self::net::*;
|
||||||
|
#[cfg(feature = "slirp")]
|
||||||
|
pub use self::sys::windows::NetExt;
|
||||||
pub use self::vsock::*;
|
pub use self::vsock::*;
|
||||||
} else {
|
} else {
|
||||||
compile_error!("Unsupported platform");
|
compile_error!("Unsupported platform");
|
||||||
|
|
|
@ -163,13 +163,11 @@ pub(in crate::virtio::vhost::user::device::net) fn start_queue<T: 'static + Into
|
||||||
let tap = ex
|
let tap = ex
|
||||||
.async_from(tap)
|
.async_from(tap)
|
||||||
.context("failed to create async tap device")?;
|
.context("failed to create async tap device")?;
|
||||||
let read_notifier = base::Event(
|
let read_notifier = overlapped_wrapper
|
||||||
overlapped_wrapper
|
.get_h_event_ref()
|
||||||
.get_h_event_ref()
|
.unwrap()
|
||||||
.unwrap()
|
.try_clone()
|
||||||
.try_clone()
|
.unwrap();
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
let read_notifier = EventAsync::new_without_reset(read_notifier, ex)
|
let read_notifier = EventAsync::new_without_reset(read_notifier, ex)
|
||||||
.context("failed to create async read notifier")?;
|
.context("failed to create async read notifier")?;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ cfg-if = "1.0.0"
|
||||||
cros_async = { path = "../cros_async" }
|
cros_async = { path = "../cros_async" }
|
||||||
data_model = { path = "../common/data_model" }
|
data_model = { path = "../common/data_model" }
|
||||||
libc = "*"
|
libc = "*"
|
||||||
libslirp-sys = { version = "4.2.1", optional = true }
|
|
||||||
|
|
||||||
net_sys = { path = "../net_sys" }
|
net_sys = { path = "../net_sys" }
|
||||||
pcap-file = { version = "1.1.0", optional = true }
|
pcap-file = { version = "1.1.0", optional = true }
|
||||||
|
@ -30,3 +29,8 @@ virtio_sys = { path = "../virtio_sys" }
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
metrics = { path = "../metrics" }
|
metrics = { path = "../metrics" }
|
||||||
winapi = { version = "*", features = ["everything", "std", "impl-default"] }
|
winapi = { version = "*", features = ["everything", "std", "impl-default"] }
|
||||||
|
libslirp-sys = { version = "4.2.1", optional = true }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
anyhow = "*"
|
||||||
|
prebuilts = { path = "../prebuilts" }
|
||||||
|
|
|
@ -2,33 +2,11 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#[cfg(all(feature = "slirp", windows))]
|
static PREBUILTS_VERSION_FILENAME: &str = "prebuilts_version";
|
||||||
mod win_slirp {
|
static SLIRP_LIB: &str = "libslirp.lib";
|
||||||
use std::env;
|
static SLIRP_DLL: &str = "libslirp-0.dll";
|
||||||
|
#[cfg(unix)]
|
||||||
pub(super) fn main() {
|
static GLIB_FILENAME: &str = "libglib-2.0.dll.a";
|
||||||
// This must be an absolute path or linking issues will result when a consuming crate
|
|
||||||
// tries to link since $PWD will be different.
|
|
||||||
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
let build_type = "debug";
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
let build_type = "release";
|
|
||||||
|
|
||||||
println!(
|
|
||||||
r#"cargo:rustc-link-search={}\..\..\..\third_party\libslirp\{}"#,
|
|
||||||
manifest_dir, build_type
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
r#"cargo:rustc-env=PATH={};{}\..\..\..\third_party\libslirp\{};"#,
|
|
||||||
env::var("PATH").unwrap(),
|
|
||||||
manifest_dir,
|
|
||||||
build_type,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// We (the Windows crosvm maintainers) submitted upstream patches to libslirp-sys so it doesn't
|
// We (the Windows crosvm maintainers) submitted upstream patches to libslirp-sys so it doesn't
|
||||||
|
@ -36,8 +14,27 @@ fn main() {
|
||||||
// to the build system that invokes Cargo (e.g. the crosvm jCI scripts that also produce the
|
// to the build system that invokes Cargo (e.g. the crosvm jCI scripts that also produce the
|
||||||
// required libslirp DLL & lib). The integration here (win_slirp::main) is specific to crosvm's
|
// required libslirp DLL & lib). The integration here (win_slirp::main) is specific to crosvm's
|
||||||
// build process.
|
// build process.
|
||||||
#[cfg(all(feature = "slirp", windows))]
|
if std::env::var("CARGO_CFG_WINDOWS").is_ok() {
|
||||||
win_slirp::main();
|
let version = std::fs::read_to_string(PREBUILTS_VERSION_FILENAME)
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.parse::<u32>()
|
||||||
|
.unwrap();
|
||||||
|
// TODO(b:242204245) build libslirp locally on windows from build.rs.
|
||||||
|
prebuilts::download_prebuilts(
|
||||||
|
"libslirp",
|
||||||
|
version,
|
||||||
|
&[
|
||||||
|
SLIRP_DLL,
|
||||||
|
SLIRP_LIB,
|
||||||
|
#[cfg(unix)]
|
||||||
|
// When compiling with mingw64 to run under wine64, we need glib as slirp links
|
||||||
|
// against it.
|
||||||
|
GLIB_FILENAME,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// For unix, libslirp-sys's build script will make the appropriate linking calls to pkg_config.
|
// For unix, libslirp-sys's build script will make the appropriate linking calls to pkg_config.
|
||||||
}
|
}
|
||||||
|
|
1
net_util/prebuilts_version
Normal file
1
net_util/prebuilts_version
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -33,6 +33,11 @@ use serde::Serialize;
|
||||||
pub use sys::TapT;
|
pub use sys::TapT;
|
||||||
use thiserror::Error as ThisError;
|
use thiserror::Error as ThisError;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "slirp"))]
|
||||||
|
pub mod slirp;
|
||||||
|
#[cfg(all(feature = "slirp", windows))]
|
||||||
|
pub use slirp::Slirp;
|
||||||
|
|
||||||
#[sorted]
|
#[sorted]
|
||||||
#[derive(ThisError, Debug)]
|
#[derive(ThisError, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -51,18 +56,23 @@ pub enum Error {
|
||||||
/// Couldn't open /dev/net/tun.
|
/// Couldn't open /dev/net/tun.
|
||||||
#[error("failed to open /dev/net/tun: {0}")]
|
#[error("failed to open /dev/net/tun: {0}")]
|
||||||
OpenTun(SysError),
|
OpenTun(SysError),
|
||||||
|
#[cfg(all(feature = "slirp", windows))]
|
||||||
|
#[error("slirp related error")]
|
||||||
|
Slirp(slirp::SlirpError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn sys_error(&self) -> SysError {
|
pub fn sys_error(&self) -> SysError {
|
||||||
match *self {
|
match &*self {
|
||||||
Error::CreateSocket(e) => e,
|
Error::CreateSocket(e) => *e,
|
||||||
Error::OpenTun(e) => e,
|
Error::OpenTun(e) => *e,
|
||||||
Error::CreateTap(e) => e,
|
Error::CreateTap(e) => *e,
|
||||||
Error::CloneTap(e) => e,
|
Error::CloneTap(e) => *e,
|
||||||
Error::IoctlError(e) => e,
|
Error::IoctlError(e) => *e,
|
||||||
|
#[cfg(all(feature = "slirp", windows))]
|
||||||
|
Error::Slirp(e) => e.sys_error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
//! level interfaces to libslirp that are used to implement that loop, and
|
//! level interfaces to libslirp that are used to implement that loop, and
|
||||||
//! diagnostic tools.
|
//! diagnostic tools.
|
||||||
|
|
||||||
|
#![cfg(windows)]
|
||||||
|
|
||||||
#[path = "../../third_party/libslirp-rs/src/context.rs"]
|
#[path = "../../third_party/libslirp-rs/src/context.rs"]
|
||||||
pub mod context;
|
pub mod context;
|
||||||
|
|
||||||
|
@ -15,6 +17,44 @@ pub mod packet_ring_buffer;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
pub use sys::Slirp;
|
pub use sys::Slirp;
|
||||||
|
|
||||||
|
use base::Error as SysError;
|
||||||
|
use remain::sorted;
|
||||||
|
use thiserror::Error as ThisError;
|
||||||
|
|
||||||
/// Length includes space for an ethernet frame & the vnet header. See the virtio spec for details:
|
/// Length includes space for an ethernet frame & the vnet header. See the virtio spec for details:
|
||||||
/// <http://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2050006>
|
/// <http://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2050006>
|
||||||
pub const ETHERNET_FRAME_SIZE: usize = 1526;
|
pub const ETHERNET_FRAME_SIZE: usize = 1526;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[sorted]
|
||||||
|
#[derive(ThisError, Debug)]
|
||||||
|
pub enum SlirpError {
|
||||||
|
#[error("pipe was closed: {0}")]
|
||||||
|
BrokenPipe(std::io::Error),
|
||||||
|
#[error("failed to clone object: {0}")]
|
||||||
|
CloneFailed(std::io::Error),
|
||||||
|
#[error("overlapped operation failed: {0}")]
|
||||||
|
OverlappedError(std::io::Error),
|
||||||
|
/// Error encountered while in a Slirp related poll operation.
|
||||||
|
#[error("slirp poll failed: {0}")]
|
||||||
|
SlirpIOPollError(std::io::Error),
|
||||||
|
/// Error encountered while in a Slirp related poll operation.
|
||||||
|
#[error("slirp poll failed: {0}")]
|
||||||
|
SlirpPollError(SysError),
|
||||||
|
#[error("WSAStartup failed with code: {0}")]
|
||||||
|
WSAStartupError(SysError),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
impl SlirpError {
|
||||||
|
pub fn sys_error(&self) -> SysError {
|
||||||
|
match &*self {
|
||||||
|
SlirpError::BrokenPipe(e) => SysError::new(e.raw_os_error().unwrap_or_default()),
|
||||||
|
SlirpError::CloneFailed(e) => SysError::new(e.raw_os_error().unwrap_or_default()),
|
||||||
|
SlirpError::OverlappedError(e) => SysError::new(e.raw_os_error().unwrap_or_default()),
|
||||||
|
SlirpError::SlirpIOPollError(e) => SysError::new(e.raw_os_error().unwrap_or_default()),
|
||||||
|
SlirpError::SlirpPollError(e) => *e,
|
||||||
|
SlirpError::WSAStartupError(e) => *e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ use cros_async::IntoAsync;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::slirp::SlirpError;
|
||||||
use crate::slirp::ETHERNET_FRAME_SIZE;
|
use crate::slirp::ETHERNET_FRAME_SIZE;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::MacAddress;
|
use crate::MacAddress;
|
||||||
|
@ -69,7 +70,7 @@ impl Slirp {
|
||||||
#[cfg(feature = "slirp-ring-capture")]
|
#[cfg(feature = "slirp-ring-capture")]
|
||||||
let slirp_capture_file_clone = slirp_capture_file.clone();
|
let slirp_capture_file_clone = slirp_capture_file.clone();
|
||||||
slirp_thread = thread::spawn(move || {
|
slirp_thread = thread::spawn(move || {
|
||||||
let disable_access_to_host = !cfg!("guest-to-host-net-loopback");
|
let disable_access_to_host = !cfg!(feature = "guest-to-host-net-loopback");
|
||||||
|
|
||||||
handler::start_slirp(
|
handler::start_slirp(
|
||||||
slirp_pipe,
|
slirp_pipe,
|
||||||
|
@ -100,7 +101,10 @@ impl Slirp {
|
||||||
|
|
||||||
fn try_clone(&self) -> Result<Self> {
|
fn try_clone(&self) -> Result<Self> {
|
||||||
Ok(Slirp {
|
Ok(Slirp {
|
||||||
guest_pipe: self.guest_pipe.try_clone().map_err(Error::CloneFailed)?,
|
guest_pipe: self
|
||||||
|
.guest_pipe
|
||||||
|
.try_clone()
|
||||||
|
.map_err(|e| Error::Slirp(SlirpError::CloneFailed(e)))?,
|
||||||
overlapped_wrapper: OverlappedWrapper::new(true).unwrap(),
|
overlapped_wrapper: OverlappedWrapper::new(true).unwrap(),
|
||||||
slirp_thread: None,
|
slirp_thread: None,
|
||||||
})
|
})
|
||||||
|
@ -122,7 +126,7 @@ impl Slirp {
|
||||||
// because libslirp logs *everything* as a debug entry.
|
// because libslirp logs *everything* as a debug entry.
|
||||||
std::env::set_var("G_MESSAGES_DEBUG", "all");
|
std::env::set_var("G_MESSAGES_DEBUG", "all");
|
||||||
|
|
||||||
let disable_access_to_host = !cfg!("guest-to-host-net-loopback");
|
let disable_access_to_host = !cfg!(feature = "guest-to-host-net-loopback");
|
||||||
|
|
||||||
info!("starting slirp loop...");
|
info!("starting slirp loop...");
|
||||||
match handler::start_slirp(
|
match handler::start_slirp(
|
||||||
|
@ -132,7 +136,9 @@ impl Slirp {
|
||||||
#[cfg(feature = "slirp-ring-capture")]
|
#[cfg(feature = "slirp-ring-capture")]
|
||||||
slirp_capture_file.take(),
|
slirp_capture_file.take(),
|
||||||
) {
|
) {
|
||||||
Err(Error::BrokenPipe(e)) => warn!("exited slirp listening loop: {}", e),
|
Err(Error::Slirp(SlirpError::BrokenPipe(e))) => {
|
||||||
|
warn!("exited slirp listening loop: {}", e)
|
||||||
|
}
|
||||||
Err(e) => panic!("error while running slirp listening loop: {}", e),
|
Err(e) => panic!("error while running slirp listening loop: {}", e),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +232,7 @@ impl TapTCommon for Slirp {
|
||||||
unimplemented!("not used by Slirp");
|
unimplemented!("not used by Slirp");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn if_flags(&self) -> i32 {
|
fn if_flags(&self) -> u32 {
|
||||||
// This function is unused by the Slirp code paths.
|
// This function is unused by the Slirp code paths.
|
||||||
unimplemented!("not used by Slirp");
|
unimplemented!("not used by Slirp");
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,20 +21,20 @@ use base::AsRawDescriptor;
|
||||||
use base::Descriptor;
|
use base::Descriptor;
|
||||||
use base::Error as SysError;
|
use base::Error as SysError;
|
||||||
use base::Event;
|
use base::Event;
|
||||||
|
use base::EventExt;
|
||||||
use base::EventToken;
|
use base::EventToken;
|
||||||
use base::EventWindows;
|
|
||||||
use base::RawDescriptor;
|
use base::RawDescriptor;
|
||||||
use base::Timer;
|
use base::Timer;
|
||||||
use base::WaitContext;
|
use base::WaitContext;
|
||||||
|
use base::WaitContextExt;
|
||||||
use data_model::DataInit;
|
use data_model::DataInit;
|
||||||
use data_model::Le16;
|
|
||||||
use metrics::MetricEventType;
|
use metrics::MetricEventType;
|
||||||
use metrics::PeriodicLogger;
|
use metrics::PeriodicLogger;
|
||||||
#[cfg(any(feature = "slirp-ring-capture", feature = "slirp-debug"))]
|
#[cfg(any(feature = "slirp-ring-capture", feature = "slirp-debug"))]
|
||||||
use pcap_file::pcap::PcapWriter;
|
use pcap_file::pcap::PcapWriter;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use virtio_sys::virtio_net_hdr;
|
use virtio_sys::virtio_net::virtio_net_hdr;
|
||||||
use virtio_sys::virtio_net_hdr_mrg_rxbuf;
|
use virtio_sys::virtio_net::virtio_net_hdr_mrg_rxbuf;
|
||||||
use winapi::shared::minwindef::MAKEWORD;
|
use winapi::shared::minwindef::MAKEWORD;
|
||||||
use winapi::um::winnt::LONG;
|
use winapi::um::winnt::LONG;
|
||||||
use winapi::um::winnt::SHORT;
|
use winapi::um::winnt::SHORT;
|
||||||
|
@ -61,6 +61,7 @@ use crate::slirp::context::Context;
|
||||||
use crate::slirp::context::PollEvents;
|
use crate::slirp::context::PollEvents;
|
||||||
#[cfg(feature = "slirp-ring-capture")]
|
#[cfg(feature = "slirp-ring-capture")]
|
||||||
use crate::slirp::packet_ring_buffer::PacketRingBuffer;
|
use crate::slirp::packet_ring_buffer::PacketRingBuffer;
|
||||||
|
use crate::slirp::SlirpError;
|
||||||
use crate::slirp::ETHERNET_FRAME_SIZE;
|
use crate::slirp::ETHERNET_FRAME_SIZE;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
@ -113,7 +114,7 @@ impl CallbackHandler for Handler {
|
||||||
hdr_len: 0,
|
hdr_len: 0,
|
||||||
csum_start: 0,
|
csum_start: 0,
|
||||||
csum_offset: 0,
|
csum_offset: 0,
|
||||||
gso_type: virtio_sys::VIRTIO_NET_HDR_GSO_NONE as u8,
|
gso_type: virtio_sys::virtio_net::VIRTIO_NET_HDR_GSO_NONE as u8,
|
||||||
},
|
},
|
||||||
num_buffers: 1,
|
num_buffers: 1,
|
||||||
};
|
};
|
||||||
|
@ -359,7 +360,7 @@ impl<'a> EventSelectedSocket<'a> {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
if res == SOCKET_ERROR {
|
if res == SOCKET_ERROR {
|
||||||
return Err(Error::SlirpIOPollError(last_wsa_error()));
|
return Err(Error::Slirp(SlirpError::SlirpIOPollError(last_wsa_error())));
|
||||||
}
|
}
|
||||||
Ok(EventSelectedSocket { socket, event })
|
Ok(EventSelectedSocket { socket, event })
|
||||||
}
|
}
|
||||||
|
@ -402,28 +403,32 @@ fn poll<'a>(
|
||||||
selected_sockets.push(EventSelectedSocket::new(*socket, socket_event_handle)?);
|
selected_sockets.push(EventSelectedSocket::new(*socket, socket_event_handle)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_ctx.clear().map_err(Error::SlirpPollError)?;
|
wait_ctx
|
||||||
|
.clear()
|
||||||
|
.map_err(|e| Error::Slirp(SlirpError::SlirpPollError(e)))?;
|
||||||
for (i, handle) in handles.iter().enumerate() {
|
for (i, handle) in handles.iter().enumerate() {
|
||||||
match wait_ctx.add(*handle, Token::EventHandleReady(i)) {
|
match wait_ctx.add(*handle, Token::EventHandleReady(i)) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::SlirpPollError(e));
|
return Err(Error::Slirp(SlirpError::SlirpPollError(e)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match wait_ctx.add(socket_event_handle, Token::SocketReady) {
|
match wait_ctx.add(socket_event_handle, Token::SocketReady) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::SlirpPollError(e));
|
return Err(Error::Slirp(SlirpError::SlirpPollError(e)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let events = if let Some(timeout) = timeout {
|
let events = if let Some(timeout) = timeout {
|
||||||
wait_ctx
|
wait_ctx
|
||||||
.wait_timeout(timeout)
|
.wait_timeout(timeout)
|
||||||
.map_err(Error::SlirpPollError)?
|
.map_err(|e| Error::Slirp(SlirpError::SlirpPollError(e)))?
|
||||||
} else {
|
} else {
|
||||||
wait_ctx.wait().map_err(Error::SlirpPollError)?
|
wait_ctx
|
||||||
|
.wait()
|
||||||
|
.map_err(|e| Error::Slirp(SlirpError::SlirpPollError(e)))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let tokens: Vec<Token> = events
|
let tokens: Vec<Token> = events
|
||||||
|
@ -446,7 +451,7 @@ fn poll<'a>(
|
||||||
let socket_results = if sockets.is_empty() {
|
let socket_results = if sockets.is_empty() {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else {
|
} else {
|
||||||
poll_sockets(sockets).map_err(Error::SlirpIOPollError)?
|
poll_sockets(sockets).map_err(|e| Error::Slirp(SlirpError::SlirpIOPollError(e)))?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((handle_results, socket_results))
|
Ok((handle_results, socket_results))
|
||||||
|
@ -466,7 +471,9 @@ impl WSAContext {
|
||||||
// Safe because ctx.data is guaranteed to exist, and we check the return code.
|
// Safe because ctx.data is guaranteed to exist, and we check the return code.
|
||||||
let err = unsafe { WSAStartup(MAKEWORD(2, 0), &mut ctx.data) };
|
let err = unsafe { WSAStartup(MAKEWORD(2, 0), &mut ctx.data) };
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
Err(Error::WSAStartupError(SysError::new(err)))
|
Err(Error::Slirp(SlirpError::WSAStartupError(SysError::new(
|
||||||
|
err,
|
||||||
|
))))
|
||||||
} else {
|
} else {
|
||||||
Ok(ctx)
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
@ -506,8 +513,10 @@ pub fn start_slirp(
|
||||||
let shutdown_event_handle = shutdown_event.as_raw_descriptor();
|
let shutdown_event_handle = shutdown_event.as_raw_descriptor();
|
||||||
|
|
||||||
// Stack data for the poll function.
|
// Stack data for the poll function.
|
||||||
let wait_ctx: WaitContext<Token> = WaitContext::new().map_err(Error::SlirpPollError)?;
|
let wait_ctx: WaitContext<Token> =
|
||||||
let socket_event_handle = Event::new_auto_reset().map_err(Error::SlirpPollError)?;
|
WaitContext::new().map_err(|e| Error::Slirp(SlirpError::SlirpPollError(e)))?;
|
||||||
|
let socket_event_handle =
|
||||||
|
Event::new_auto_reset().map_err(|e| Error::Slirp(SlirpError::SlirpPollError(e)))?;
|
||||||
|
|
||||||
'slirp: loop {
|
'slirp: loop {
|
||||||
// Request the FDs that we should poll from Slirp. Slirp provides them to us by way of a
|
// Request the FDs that we should poll from Slirp. Slirp provides them to us by way of a
|
||||||
|
|
|
@ -74,6 +74,7 @@ pub(crate) fn run_slirp(args: RunSlirpCommand) -> Result<()> {
|
||||||
|
|
||||||
let slirp_config = bootstrap_tube.recv::<SlirpStartupConfig>().unwrap();
|
let slirp_config = bootstrap_tube.recv::<SlirpStartupConfig>().unwrap();
|
||||||
|
|
||||||
|
#[cfg(feature = "sandbox")]
|
||||||
if let Some(mut target) = sandbox::TargetServices::get()
|
if let Some(mut target) = sandbox::TargetServices::get()
|
||||||
.exit_context(Exit::SandboxError, "sandbox operation failed")?
|
.exit_context(Exit::SandboxError, "sandbox operation failed")?
|
||||||
{
|
{
|
||||||
|
|
15
third_party/libslirp-rs/src/context.rs
vendored
15
third_party/libslirp-rs/src/context.rs
vendored
|
@ -52,6 +52,7 @@ use base::error;
|
||||||
use base::RawDescriptor;
|
use base::RawDescriptor;
|
||||||
use libslirp_sys::*;
|
use libslirp_sys::*;
|
||||||
|
|
||||||
|
use crate::slirp::SlirpError;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
|
@ -512,10 +513,10 @@ impl<H: CallbackHandler> Context<H> {
|
||||||
assert!(!slirp.is_null());
|
assert!(!slirp.is_null());
|
||||||
match ret.callback_handler.begin_read_from_guest() {
|
match ret.callback_handler.begin_read_from_guest() {
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
||||||
return Err(Error::BrokenPipe(e));
|
return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::OverlappedError(e));
|
return Err(Error::Slirp(SlirpError::OverlappedError(e)));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -545,15 +546,15 @@ impl<H: CallbackHandler> Context<H> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
||||||
return Err(Error::BrokenPipe(e));
|
return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
match self.callback_handler.begin_read_from_guest() {
|
match self.callback_handler.begin_read_from_guest() {
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
||||||
return Err(Error::BrokenPipe(e));
|
return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::OverlappedError(e));
|
return Err(Error::Slirp(SlirpError::OverlappedError(e)));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -562,10 +563,10 @@ impl<H: CallbackHandler> Context<H> {
|
||||||
}
|
}
|
||||||
match self.callback_handler.begin_read_from_guest() {
|
match self.callback_handler.begin_read_from_guest() {
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
|
||||||
return Err(Error::BrokenPipe(e));
|
return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::OverlappedError(e));
|
return Err(Error::Slirp(SlirpError::OverlappedError(e)));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,9 @@ sudo apt-get install --yes --no-install-recommends \
|
||||||
libdbus-1-dev \
|
libdbus-1-dev \
|
||||||
libdrm-dev \
|
libdrm-dev \
|
||||||
libepoxy-dev \
|
libepoxy-dev \
|
||||||
|
libglib2.0-dev \
|
||||||
libguestfs-tools \
|
libguestfs-tools \
|
||||||
|
libslirp-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libswscale-dev \
|
libswscale-dev \
|
||||||
libudev-dev \
|
libudev-dev \
|
||||||
|
|
Loading…
Reference in a new issue