From: Bobby Eshleman bobbyeshleman@meta.com
Add tests that validate vsock sockets are resilient to deleting namespaces or changing namespace modes from global to local. The vsock sockets should still function normally.
The function check_ns_changes_dont_break_connection() is added to re-use the step-by-step logic of 1) setup connections, 2) do something that would maybe break the connections, 3) check that the connections are still ok.
Signed-off-by: Bobby Eshleman bobbyeshleman@meta.com --- tools/testing/selftests/vsock/vmtest.sh | 123 ++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+)
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh index 0a5751c52fa8..f8fa8b16d6e3 100755 --- a/tools/testing/selftests/vsock/vmtest.sh +++ b/tools/testing/selftests/vsock/vmtest.sh @@ -62,6 +62,12 @@ readonly TEST_NAMES=( ns_same_local_loopback_ok ns_same_local_host_connect_to_local_vm_ok ns_same_local_vm_connect_to_local_host_ok + ns_mode_change_connection_continue_vm_ok + ns_mode_change_connection_continue_host_ok + ns_mode_change_connection_continue_both_ok + ns_delete_vm_ok + ns_delete_host_ok + ns_delete_both_ok ) readonly TEST_DESCS=( # vm_server_host_client @@ -129,6 +135,24 @@ readonly TEST_DESCS=(
# ns_same_local_vm_connect_to_local_host_ok "Run vsock_test client in VM in a local ns with server in same ns." + + # ns_mode_change_connection_continue_vm_ok + "Check that changing NS mode of VM namespace from global to local after a connection is established doesn't break the connection" + + # ns_mode_change_connection_continue_host_ok + "Check that changing NS mode of host namespace from global to local after a connection is established doesn't break the connection" + + # ns_mode_change_connection_continue_both_ok + "Check that changing NS mode of host and VM namespaces from global to local after a connection is established doesn't break the connection" + + # ns_delete_vm_ok + "Check that deleting the VM's namespace does not break the socket connection" + + # ns_delete_host_ok + "Check that deleting the host's namespace does not break the socket connection" + + # ns_delete_both_ok + "Check that deleting the VM and host's namespaces does not break the socket connection" )
readonly USE_SHARED_VM=(vm_server_host_client vm_client_host_server vm_loopback) @@ -1141,6 +1165,105 @@ test_vm_loopback() { return "${KSFT_PASS}" }
+check_ns_changes_dont_break_connection() { + local ns0="global0" + local ns1="global1" + local port=12345 + local pidfile + local outfile + local pids=() + local rc=0 + + init_namespaces + + pidfile=$(mktemp $PIDFILE_TEMPLATE) + if ! vm_start "${pidfile}" "${ns0}"; then + return "${KSFT_FAIL}" + fi + vm_wait_for_ssh "${ns0}" + + outfile=$(mktemp) + vm_ssh "${ns0}" -- \ + socat VSOCK-LISTEN:"${port}",fork STDOUT > "${outfile}" 2>/dev/null & + pids+=($!) + + # wait_for_listener() does not work for vsock because vsock does not + # export socket state to /proc/net/. Instead, we have no choice but to + # sleep for some hardcoded time. + sleep ${WAIT_PERIOD} + + # We use a pipe here so that we can echo into the pipe instead of + # using socat and a unix socket file. + local pipefile=$(mktemp -u /tmp/vmtest_pipe_XXXX) + ip netns exec "${ns1}" \ + socat PIPE:"${pipefile}" VSOCK-CONNECT:"${VSOCK_CID}":"${port}" & + pids+=($!) + + timeout ${WAIT_PERIOD} \ + bash -c 'while [[ ! -e '"${pipefile}"' ]]; do sleep 1; done; exit 0' + + if [[ $2 == "delete" ]]; then + if [[ "$1" == "vm" ]]; then + ip netns del "${ns0}" + elif [[ "$1" == "host" ]]; then + ip netns del "${ns1}" + elif [[ "$1" == "both" ]]; then + ip netns del "${ns0}" + ip netns del "${ns1}" + fi + elif [[ $2 == "change_mode" ]]; then + if [[ "$1" == "vm" ]]; then + ns_set_mode "${ns0}" "local" + elif [[ "$1" == "host" ]]; then + ns_set_mode "${ns1}" "local" + elif [[ "$1" == "both" ]]; then + ns_set_mode "${ns0}" "local" + ns_set_mode "${ns1}" "local" + fi + fi + + echo "TEST" > "${pipefile}" + + timeout ${WAIT_PERIOD} \ + bash -c 'while [[ ! -s '"${outfile}"' ]]; do sleep 1; done; exit 0' + + if grep -q "TEST" "${outfile}"; then + rc="${KSFT_PASS}" + else + rc="${KSFT_FAIL}" + fi + + terminate_pidfiles "${pidfile}" + terminate_pids "${pids[@]}" + rm -f "${outfile}" + + return "${rc}" +} + +test_ns_mode_change_connection_continue_vm_ok() { + check_ns_changes_dont_break_connection "vm" "change_mode" +} + +test_ns_mode_change_connection_continue_host_ok() { + check_ns_changes_dont_break_connection "host" "change_mode" +} + +test_ns_mode_change_connection_continue_both_ok() { + check_ns_changes_dont_break_connection "both" "change_mode" +} + +test_ns_delete_vm_ok() { + check_ns_changes_dont_break_connection "vm" "delete" +} + +test_ns_delete_host_ok() { + check_ns_changes_dont_break_connection "host" "delete" +} + +test_ns_delete_both_ok() { + check_ns_changes_dont_break_connection "both" "delete" +} + shared_vm_test() { local tname