Skip to content

Commit ef04aef

Browse files
committed
kernel/vsock: add in-svsm tests for VsockStream
Add a test that performs some basic checks on vsock functionalities: - double connection - recv a buffer from the host - send a buffer to the host - recv a buffer after local shutdown - send a buffer after local shutdown The vsock server is created on the host using ncat. Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
1 parent 0dbd05c commit ef04aef

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ SVSM_ARGS += --features ${FEATURES}
44
XBUILD_ARGS += -f ${FEATURES}
55
endif
66

7-
FEATURES_TEST ?= vtpm,virtio-drivers,block
7+
FEATURES_TEST ?= vtpm,virtio-drivers,block,vsock
88
SVSM_ARGS_TEST += --no-default-features
99
ifneq ($(FEATURES_TEST),)
1010
SVSM_ARGS_TEST += --features ${FEATURES_TEST}

kernel/src/testing.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ pub enum IORequest {
3939
GetLaunchMeasurement = 0x01,
4040
/// Virtio-blk tests: Get Sha256 hash of the svsm state disk image
4141
GetStateImageSha256 = 0x02,
42+
/// Virtio-vsock tests: Ask host to start a vsock server
43+
StartVsockServer = 0x03,
4244
}
4345

4446
/// Return the serial port to communicate with the host for a given request

kernel/src/vsock/stream.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,133 @@ impl Drop for VsockStream {
184184
let _ = VSOCK_DEVICE.force_shutdown(self.remote_cid, self.local_port, self.remote_port);
185185
}
186186
}
187+
188+
#[cfg(all(test, test_in_svsm))]
189+
mod tests {
190+
use crate::{testutils::has_test_iorequests, vsock::VMADDR_CID_HOST};
191+
192+
use super::*;
193+
194+
fn start_vsock_server_host() {
195+
use crate::serial::Terminal;
196+
use crate::testing::{IORequest, svsm_test_io};
197+
198+
let sp = svsm_test_io().unwrap();
199+
200+
sp.put_byte(IORequest::StartVsockServer as u8);
201+
202+
let _ = sp.get_byte();
203+
}
204+
205+
#[test]
206+
#[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")]
207+
fn test_virtio_vsock_double_connect() {
208+
if !has_test_iorequests() {
209+
return;
210+
}
211+
212+
start_vsock_server_host();
213+
214+
let remote_port: u32 = 12345;
215+
216+
let mut stream =
217+
VsockStream::connect(remote_port, VMADDR_CID_HOST).expect("connection failed");
218+
219+
VsockStream::connect(remote_port, VMADDR_CID_HOST)
220+
.expect_err("The second connection operation was expected to fail, but it succeeded.");
221+
222+
stream.shutdown().expect("shutdown failed");
223+
}
224+
225+
#[test]
226+
#[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")]
227+
fn test_virtio_vsock_write() {
228+
if !has_test_iorequests() {
229+
return;
230+
}
231+
232+
start_vsock_server_host();
233+
234+
let remote_port: u32 = 12345;
235+
236+
let mut stream =
237+
VsockStream::connect(remote_port, VMADDR_CID_HOST).expect("connection failed");
238+
239+
let buffer: &[u8] = b"Hello world!";
240+
241+
let n_bytes = stream.write(buffer).expect("write failed");
242+
assert!(n_bytes == buffer.len(), "Sent less bytes than requested");
243+
244+
stream.shutdown().expect("shutdown failed");
245+
}
246+
247+
#[test]
248+
#[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")]
249+
fn test_virtio_vsock_read() {
250+
if !has_test_iorequests() {
251+
return;
252+
}
253+
254+
start_vsock_server_host();
255+
256+
let remote_port: u32 = 12345;
257+
258+
let mut stream =
259+
VsockStream::connect(remote_port, VMADDR_CID_HOST).expect("connection failed");
260+
261+
let mut buffer: [u8; 11] = [0; 11];
262+
let n_bytes = stream.read(&mut buffer).expect("read failed");
263+
assert!(
264+
n_bytes == buffer.len(),
265+
"Received less bytes than requested"
266+
);
267+
268+
let string = core::str::from_utf8(&buffer).unwrap();
269+
log::info!("received: {string:?}");
270+
271+
stream.shutdown().expect("shutdown failed");
272+
}
273+
274+
#[test]
275+
#[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")]
276+
fn test_virtio_vsock_read_shutdown() {
277+
if !has_test_iorequests() {
278+
return;
279+
}
280+
281+
start_vsock_server_host();
282+
283+
let remote_port: u32 = 12345;
284+
285+
let mut stream =
286+
VsockStream::connect(remote_port, VMADDR_CID_HOST).expect("connection failed");
287+
288+
stream.shutdown().expect("shutdown failed");
289+
290+
let mut buffer: [u8; 11] = [0; 11];
291+
stream
292+
.read(&mut buffer)
293+
.expect_err("The read operation was expected to fail, but it succeeded");
294+
}
295+
296+
#[test]
297+
#[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")]
298+
fn test_virtio_vsock_write_shutdown() {
299+
if !has_test_iorequests() {
300+
return;
301+
}
302+
303+
start_vsock_server_host();
304+
305+
let remote_port: u32 = 12345;
306+
307+
let mut stream =
308+
VsockStream::connect(remote_port, VMADDR_CID_HOST).expect("connection failed");
309+
310+
stream.shutdown().expect("shutdown failed");
311+
312+
stream
313+
.write(b"hello world")
314+
.expect_err("The write operation was expected to fail, but it succeeded");
315+
}
316+
}

scripts/test-in-svsm.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ test_io(){
2828
"02")
2929
sha256sum "$TEST_DIR/svsm_state.raw" | cut -f 1 -d ' ' | xxd -p -r > "$PIPE_IN"
3030
;;
31+
"03")
32+
# virtio-vsock in svsm does not handle half duplex connections.
33+
echo -n "hello_world" | ncat --no-shutdown -l --vsock -p 12345 &
34+
sleep 1
35+
echo -n "0" > $PIPE_IN
36+
;;
3137
"")
3238
# skip EOF
3339
;;
@@ -69,6 +75,7 @@ done
6975

7076
$SCRIPT_DIR/launch_guest.sh --igvm $SCRIPT_DIR/../bin/coconut-test-qemu.igvm \
7177
--state "$TEST_DIR/svsm_state.raw" \
78+
--vsock 3 \
7279
--unit-tests $TEST_DIR/pipe \
7380
$LAUNCH_GUEST_ARGS "$@" || svsm_exit_code=$?
7481

0 commit comments

Comments
 (0)