Skip to content

Commit 63c70ee

Browse files
authored
feat: add support for vsock connections (#623)
This allows connecting to [VSOCK] address family, which is used in VMs. The change adds support for vsock connections in both `console-subscriber` and `tokio-console`. [VSOCK]: https://man7.org/linux/man-pages/man7/vsock.7.html
1 parent 1aa5185 commit 63c70ee

File tree

9 files changed

+186
-35
lines changed

9 files changed

+186
-35
lines changed

Diff for: Cargo.lock

+61-27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ Arguments:
191191
scheme that specifies the path to a Unix domain socket, as in
192192
`file://localhost/path/to/socket`.
193193
194+
When the `vsock` feature is enabled, this may also be a URI
195+
with the `vsock` scheme that specifies a vsock connection, as
196+
in `vsock://2:6669` to connect to CID 2 port 6669.
197+
194198
[default: http://127.0.0.1:6669]
195199
196200
Options:

Diff for: console-subscriber/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ default = ["env-filter"]
2929
parking_lot = ["dep:parking_lot", "tracing-subscriber/parking_lot"]
3030
env-filter = ["tracing-subscriber/env-filter"]
3131
grpc-web = ["dep:tonic-web"]
32+
vsock = ["dep:tokio-vsock"]
3233

3334
[dependencies]
3435
crossbeam-utils = "0.8.7"
@@ -54,7 +55,10 @@ serde_json = "1"
5455
crossbeam-channel = "0.5"
5556

5657
# Only for the web feature:
57-
tonic-web = { version = "0.12", optional = true }
58+
tonic-web = { version = "0.13", optional = true }
59+
60+
# Only for the vsock feature:
61+
tokio-vsock = { version = "0.7.1", optional = true, features = ["tonic013"]}
5862

5963
[dev-dependencies]
6064
tokio = { version = "1.34", features = ["full", "rt-multi-thread"] }

Diff for: console-subscriber/src/builder.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,11 @@ impl Builder {
152152
/// before falling back on constructing a socket address from those
153153
/// defaults.
154154
///
155-
/// The socket address can be either a TCP socket address or a
156-
/// [Unix domain socket] (UDS) address. Unix domain sockets are only
157-
/// supported on Unix-compatible operating systems, such as Linux, BSDs,
158-
/// and macOS.
155+
/// The socket address can be either a TCP socket address, a
156+
/// [Unix domain socket] (UDS) address, or a [Vsock] address.
157+
/// Unix domain sockets are only supported on Unix-compatible operating systems,
158+
/// such as Linux, BSDs, and macOS. Vsock addresses are only available when the
159+
/// "vsock" feature is enabled and are supported on platforms with vsock capability.
159160
///
160161
/// Each call to this method will overwrite the previously set value.
161162
///
@@ -181,8 +182,17 @@ impl Builder {
181182
/// let builder = Builder::default().server_addr(Path::new("/tmp/tokio-console"));
182183
/// ```
183184
///
185+
/// Connect using a vsock connection (requires the "vsock" feature):
186+
///
187+
/// ```
188+
/// # use console_subscriber::Builder;
189+
/// # #[cfg(feature = "vsock")]
190+
/// let builder = Builder::default().server_addr((tokio_vsock::VMADDR_CID_ANY, 6669));
191+
/// ```
192+
///
184193
/// [environment variable]: `Builder::with_default_env`
185194
/// [Unix domain socket]: https://en.wikipedia.org/wiki/Unix_domain_socket
195+
/// [Vsock]: https://docs.rs/tokio-vsock/latest/tokio_vsock/
186196
pub fn server_addr(self, server_addr: impl Into<ServerAddr>) -> Self {
187197
Self {
188198
server_addr: server_addr.into(),
@@ -574,6 +584,9 @@ pub enum ServerAddr {
574584
/// A Unix socket address.
575585
#[cfg(unix)]
576586
Unix(PathBuf),
587+
/// A vsock address.
588+
#[cfg(feature = "vsock")]
589+
Vsock(tokio_vsock::VsockAddr),
577590
}
578591

579592
impl From<SocketAddr> for ServerAddr {
@@ -617,6 +630,13 @@ impl<'a> From<&'a Path> for ServerAddr {
617630
}
618631
}
619632

633+
#[cfg(feature = "vsock")]
634+
impl From<tokio_vsock::VsockAddr> for ServerAddr {
635+
fn from(addr: tokio_vsock::VsockAddr) -> ServerAddr {
636+
ServerAddr::Vsock(addr)
637+
}
638+
}
639+
620640
/// Initializes the console [tracing `Subscriber`][sub] and starts the console
621641
/// subscriber [`Server`] on its own background thread.
622642
///

Diff for: console-subscriber/src/lib.rs

+15
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
use console_api as proto;
33
use proto::{instrument::instrument_server::InstrumentServer, resources::resource};
44
use serde::Serialize;
5+
#[cfg(feature = "vsock")]
6+
use tokio_vsock::VsockListener;
7+
58
use std::{
69
cell::RefCell,
710
fmt,
@@ -955,6 +958,12 @@ impl Server {
955958
let serve = router.serve_with_incoming(UnixListenerStream::new(incoming));
956959
spawn_named(serve, "console::serve").await
957960
}
961+
#[cfg(feature = "vsock")]
962+
ServerAddr::Vsock(addr) => {
963+
let incoming = VsockListener::bind(addr)?.incoming();
964+
let serve = router.serve_with_incoming(incoming);
965+
spawn_named(serve, "console::serve").await
966+
}
958967
};
959968
aggregate.abort();
960969
res?.map_err(Into::into)
@@ -1082,6 +1091,12 @@ impl Server {
10821091
let serve = router.serve_with_incoming(UnixListenerStream::new(incoming));
10831092
spawn_named(serve, "console::serve").await
10841093
}
1094+
#[cfg(feature = "vsock")]
1095+
ServerAddr::Vsock(addr) => {
1096+
let incoming = VsockListener::bind(addr)?.incoming();
1097+
let serve = router.serve_with_incoming(incoming);
1098+
spawn_named(serve, "console::serve").await
1099+
}
10851100
};
10861101
aggregate.abort();
10871102
res?.map_err(Into::into)

Diff for: tokio-console/Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,17 @@ hdrhistogram = { version = "7.4.0", default-features = false, features = ["seria
5454
h2 = "0.4.6"
5555
regex = "1.11"
5656
once_cell = "1.17.1"
57+
cfg-if = "1.0.0"
5758
humantime = "2.1.0"
5859
serde = { version = "1.0.145", features = ["derive"] }
5960
toml = "0.5"
6061
dirs = "5"
6162
hyper-util = { version = "0.1.6", features = ["tokio"] }
63+
tokio-vsock = { version = "0.7.1", features = ["tonic013"], optional = true }
64+
65+
[features]
66+
# Enable support for VSOCK address family, used in VMs
67+
vsock = ["dep:tokio-vsock"]
6268

6369
[dev-dependencies]
6470
trycmd = "0.15.4"

Diff for: tokio-console/src/config.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::state::tasks::Task;
22
use crate::view::Palette;
33
use crate::warnings;
4+
use cfg_if::cfg_if;
45
use clap::builder::{PossibleValuesParser, TypedValueParser};
56
use clap::{ArgAction, ArgGroup, CommandFactory, Parser as Clap, Subcommand, ValueHint};
67
use clap_complete::Shell;
@@ -35,6 +36,9 @@ pub struct Config {
3536
/// specifies the path to a Unix domain socket, as in
3637
/// `file://localhost/path/to/socket`.
3738
///
39+
/// When the `vsock` feature is enabled, this may also be a URI with the `vsock` scheme that
40+
/// specifies a vsock connection, as in `vsock://2:6669` to connect to CID 2 port 6669.
41+
///
3842
/// [default: http://127.0.0.1:6669]
3943
#[clap(value_hint = ValueHint::Url)]
4044
pub(crate) target_addr: Option<Uri>,
@@ -528,11 +532,30 @@ impl Config {
528532
.clone();
529533
match target_addr.scheme_str() {
530534
Some("file" | "http" | "https") => {}
535+
#[cfg(feature = "vsock")]
536+
Some("vsock") => {}
537+
#[cfg(not(feature = "vsock"))]
538+
Some("vsock") => {
539+
return Err(color_eyre::eyre::eyre!(
540+
"vsock scheme detected in target address {:?}, but tokio-console was not compiled with the 'vsock' feature. \
541+
Please recompile with '--features vsock' to enable vsock support",
542+
target_addr
543+
));
544+
}
531545
_ => {
546+
// List of supported protocols is defined in the cfg_if block below
547+
cfg_if! {
548+
if #[cfg(feature = "vsock")] {
549+
let protocols_display = "file, http, https, or vsock";
550+
} else {
551+
let protocols_display = "file, http, or https";
552+
}
553+
}
532554
return Err(color_eyre::eyre::eyre!(
533-
"invalid scheme for target address {:?}, must be one of 'file', 'http', or 'https'",
534-
target_addr
535-
))
555+
"invalid scheme for target address {:?}, must be one of {}",
556+
target_addr,
557+
protocols_display
558+
));
536559
}
537560
}
538561
Ok(target_addr)

0 commit comments

Comments
 (0)