Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/virtio/vsock/sys/linux.rs
5394 views
1
// Copyright 2023 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::path::Path;
6
use std::path::PathBuf;
7
8
use serde::Deserialize;
9
use serde::Serialize;
10
use serde_keyvalue::FromKeyValues;
11
12
static VHOST_VSOCK_DEFAULT_PATH: &str = "/dev/vhost-vsock";
13
14
fn default_vsock_path() -> PathBuf {
15
PathBuf::from(VHOST_VSOCK_DEFAULT_PATH)
16
}
17
18
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, FromKeyValues)]
19
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
20
/// Configuration for a Vsock device.
21
pub struct VsockConfig {
22
/// CID to be used for this vsock device.
23
pub cid: u64,
24
/// Path to the vhost-vsock device.
25
#[serde(default = "default_vsock_path", rename = "device")]
26
pub vhost_device: PathBuf,
27
#[serde(default)]
28
pub max_queue_sizes: Option<[u16; 3]>,
29
}
30
31
impl VsockConfig {
32
/// Create a new vsock configuration. If `vhost_device` is `None`, the default vhost-vsock
33
/// device path will be used.
34
pub fn new<P: AsRef<Path>>(cid: u64, vhost_device: Option<P>) -> Self {
35
Self {
36
cid,
37
#[cfg(any(target_os = "android", target_os = "linux"))]
38
vhost_device: vhost_device
39
.map(|p| PathBuf::from(p.as_ref()))
40
.unwrap_or_else(|| PathBuf::from(VHOST_VSOCK_DEFAULT_PATH)),
41
max_queue_sizes: None,
42
}
43
}
44
}
45
46
#[cfg(test)]
47
mod tests {
48
use serde_keyvalue::from_key_values;
49
use serde_keyvalue::ErrorKind;
50
use serde_keyvalue::ParseError;
51
52
use super::*;
53
54
fn from_vsock_arg(options: &str) -> Result<VsockConfig, ParseError> {
55
from_key_values(options)
56
}
57
58
#[test]
59
fn params_from_key_values() {
60
// Default device
61
assert_eq!(
62
from_vsock_arg("cid=56").unwrap(),
63
VsockConfig {
64
vhost_device: VHOST_VSOCK_DEFAULT_PATH.into(),
65
cid: 56,
66
max_queue_sizes: None,
67
}
68
);
69
70
// No argument
71
assert_eq!(
72
from_vsock_arg("").unwrap_err(),
73
ParseError {
74
kind: ErrorKind::SerdeError("missing field `cid`".into()),
75
pos: 0
76
}
77
);
78
79
// CID passed without key
80
assert_eq!(
81
from_vsock_arg("78").unwrap(),
82
VsockConfig {
83
#[cfg(any(target_os = "android", target_os = "linux"))]
84
vhost_device: VHOST_VSOCK_DEFAULT_PATH.into(),
85
cid: 78,
86
max_queue_sizes: None,
87
}
88
);
89
90
// CID passed twice
91
assert_eq!(
92
from_vsock_arg("cid=42,cid=56").unwrap_err(),
93
ParseError {
94
kind: ErrorKind::SerdeError("duplicate field `cid`".into()),
95
pos: 0,
96
}
97
);
98
99
// Invalid argument
100
assert_eq!(
101
from_vsock_arg("invalid=foo").unwrap_err(),
102
ParseError {
103
kind: ErrorKind::SerdeError(
104
"unknown field `invalid`, expected one of `cid`, `device`, `max-queue-sizes`"
105
.into()
106
),
107
pos: 0,
108
}
109
);
110
111
// Path device
112
assert_eq!(
113
from_vsock_arg("device=/some/path,cid=56").unwrap(),
114
VsockConfig {
115
vhost_device: "/some/path".into(),
116
cid: 56,
117
max_queue_sizes: None,
118
}
119
);
120
121
// CID passed without key
122
assert_eq!(
123
from_vsock_arg("56,device=/some/path").unwrap(),
124
VsockConfig {
125
vhost_device: "/some/path".into(),
126
cid: 56,
127
max_queue_sizes: None,
128
}
129
);
130
131
// Missing cid
132
assert_eq!(
133
from_vsock_arg("device=42").unwrap_err(),
134
ParseError {
135
kind: ErrorKind::SerdeError("missing field `cid`".into()),
136
pos: 0,
137
}
138
);
139
140
// Device passed twice
141
assert_eq!(
142
from_vsock_arg("cid=56,device=42,device=/some/path").unwrap_err(),
143
ParseError {
144
kind: ErrorKind::SerdeError("duplicate field `device`".into()),
145
pos: 0,
146
}
147
);
148
149
// Queue sizes
150
assert_eq!(
151
from_vsock_arg("cid=56,max-queue-sizes=[1,2,4]").unwrap(),
152
VsockConfig {
153
vhost_device: VHOST_VSOCK_DEFAULT_PATH.into(),
154
cid: 56,
155
max_queue_sizes: Some([1, 2, 4]),
156
}
157
);
158
}
159
}
160
161