* [PATCH v3 01/11] test: Correctly match "background" with "wait" commands
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 02/11] test: Context execution helpers David Gibson
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 4021 bytes --]
Our test DSL has a number of paired commands to run something in the
background in a pane, then later to wait for it to complete. However, in
some of the tests we have these mismatched - starting a command in one
pane, then waiting for it in another.
We appear to get away with this for some reason, but it's not correct and
future changes make it cause more problems.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/tcp/passt_in_ns | 8 ++++----
test/tcp/pasta | 1 -
test/udp/passt_in_ns | 4 ++--
test/udp/pasta | 1 -
4 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/test/tcp/passt_in_ns b/test/tcp/passt_in_ns
index ab22485..976e4e9 100644
--- a/test/tcp/passt_in_ns
+++ b/test/tcp/passt_in_ns
@@ -44,7 +44,7 @@ check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: guest to ns: big transfer
nsb socat -u TCP4-LISTEN:10002 OPEN:__TEMP_BIG__,create,trunc
guest socat -u OPEN:test_big.bin TCP4:__GW__:10002
-hostw
+nsw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
@@ -108,7 +108,7 @@ check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: guest to ns: small transfer
nsb socat -u TCP4-LISTEN:10002 OPEN:__TEMP_SMALL__,create,trunc
guest socat -u OPEN:test_small.bin TCP4:__GW__:10002
-hostw
+nsw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
@@ -167,7 +167,7 @@ check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: guest to ns: big transfer
nsb socat -u TCP6-LISTEN:10002 OPEN:__TEMP_BIG__,create,trunc
guest socat -u OPEN:test_big.bin TCP6:[__GW6__%__IFNAME__]:10002
-hostw
+nsw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
@@ -227,7 +227,7 @@ check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: guest to ns: small transfer
nsb socat -u TCP6-LISTEN:10002 OPEN:__TEMP_SMALL__
guest socat -u OPEN:test_small.bin TCP6:[__GW6__%__IFNAME__]:10002
-hostw
+nsw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
diff --git a/test/tcp/pasta b/test/tcp/pasta
index 0d6c729..a13a2ff 100644
--- a/test/tcp/pasta
+++ b/test/tcp/pasta
@@ -80,7 +80,6 @@ ns socat -u OPEN:__TEMP_NS_BIG__ TCP6:[::1]:10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
-nsw
test TCP/IPv6: ns to host (via tap): big transfer
hostb socat -u TCP6-LISTEN:10003 OPEN:__TEMP_BIG__,create,trunc
diff --git a/test/udp/passt_in_ns b/test/udp/passt_in_ns
index 8f8090b..f5ea402 100644
--- a/test/udp/passt_in_ns
+++ b/test/udp/passt_in_ns
@@ -45,7 +45,7 @@ check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv4: guest to ns
nsb (socat -u UDP4-LISTEN:10002 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
guest socat -u OPEN:test.bin UDP4:__GW__:10002
-hostw
+nsw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
@@ -106,7 +106,7 @@ check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv6: guest to ns
nsb (socat -u UDP6-LISTEN:10002 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
guest socat -u OPEN:test.bin UDP6:[__GW6__%__IFNAME__]:10002
-hostw
+nsw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
diff --git a/test/udp/pasta b/test/udp/pasta
index 25063ea..0767e0b 100644
--- a/test/udp/pasta
+++ b/test/udp/pasta
@@ -58,7 +58,6 @@ ns socat -u OPEN:__TEMP_NS__ UDP6:[::1]:10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
-nsw
test UDP/IPv6: ns to host (via tap)
hostb (socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
--
@@ -58,7 +58,6 @@ ns socat -u OPEN:__TEMP_NS__ UDP6:[::1]:10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
-nsw
test UDP/IPv6: ns to host (via tap)
hostb (socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 02/11] test: Context execution helpers
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
2022-09-12 10:56 ` [PATCH v3 01/11] test: Correctly match "background" with "wait" commands David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 03/11] test: Allow a tmux pane to watch commands executed in contexts David Gibson
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 3448 bytes --]
For the tests, we need to run commands in various contexts: in the host,
in a guest or in a namespace. Currently we do this by running each context
in a tmux pane, and using tmux commands to type the commands into the
relevant pane, then screen-scrape the output for the results if we need
them.
This is very fragile, because we have to make various assumptions to parse
the output. Those can break if a shell doesn't have the prompt we expect,
if the tmux pane is too small or in various other conditions.
This starts some library functions for a new "context" system, that
provides a common way to invoke commands in a given context, in a way that
properly preserves stdout, stderr and the process return code.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/context | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
create mode 100644 test/lib/context
diff --git a/test/lib/context b/test/lib/context
new file mode 100644
index 0000000..babf59a
--- /dev/null
+++ b/test/lib/context
@@ -0,0 +1,80 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# PASST - Plug A Simple Socket Transport
+# for qemu/UNIX domain socket mode
+#
+# PASTA - Pack A Subtle Tap Abstraction
+# for network namespace/tap device mode
+#
+# test/lib/context - Run commands in different contexts (host, guest, namespace etc.)
+#
+# Copyright Red Hat
+# Author: David Gibson <david(a)gibson.dropbear.id.au>
+
+# context_setup_host() - Create a new context for running commands on the host
+# $1: Context name
+context_setup_host() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ echo sh -c > "${__prefix}.enter"
+ echo -n "${__name}$ " > "${__prefix}.log"
+}
+
+# context_teardown() - Remove a context (leave log files intact)
+# $1: Context name
+context_teardown() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ rm -f "${__prefix}.enter"
+}
+
+# context_exists() - Test if a context currently exists
+# $1: Context name
+context_exists() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ [ -f "${__prefix}.enter" ]
+}
+
+# context_run() - Run a shell command in a context, and wait for it to finish
+# $1: Context name
+# $*: Command to start
+context_run() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ __enter="$(cat "${__prefix}.enter")"
+ shift
+ echo "$*" >> "${__prefix}.log"
+ mkfifo "${__prefix}.stdout" "${__prefix}.stderr"
+ tee -a "${__prefix}.log" < "${__prefix}.stdout" &
+ tee -a "${__prefix}.log" < "${__prefix}.stderr" >&2 &
+ ${__enter} "$*" >> "${__prefix}.stdout" 2>> "${__prefix}.stderr"
+ rc=$?
+ rm "${__prefix}.stdout" "${__prefix}.stderr"
+ [ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__prefix}.log"
+ echo -n "${__name}$ " >> "${__prefix}.log"
+ return $rc
+}
+
+# context_run_bg() - Start a shell command in a context
+# $1: Context name
+# $*: Command to start
+context_run_bg() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ context_run "$@" &
+ echo $! > "${__prefix}.pid"
+}
+
+# context_wait() - Wait for background command in a context to complete
+# $1: Context name
+# Returns the status of the completed command
+context_wait() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ __pid=$(cat "${__prefix}.pid")
+ rm "${__prefix}.pid"
+ wait ${__pid}
+}
--
@@ -0,0 +1,80 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# PASST - Plug A Simple Socket Transport
+# for qemu/UNIX domain socket mode
+#
+# PASTA - Pack A Subtle Tap Abstraction
+# for network namespace/tap device mode
+#
+# test/lib/context - Run commands in different contexts (host, guest, namespace etc.)
+#
+# Copyright Red Hat
+# Author: David Gibson <david(a)gibson.dropbear.id.au>
+
+# context_setup_host() - Create a new context for running commands on the host
+# $1: Context name
+context_setup_host() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ echo sh -c > "${__prefix}.enter"
+ echo -n "${__name}$ " > "${__prefix}.log"
+}
+
+# context_teardown() - Remove a context (leave log files intact)
+# $1: Context name
+context_teardown() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ rm -f "${__prefix}.enter"
+}
+
+# context_exists() - Test if a context currently exists
+# $1: Context name
+context_exists() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ [ -f "${__prefix}.enter" ]
+}
+
+# context_run() - Run a shell command in a context, and wait for it to finish
+# $1: Context name
+# $*: Command to start
+context_run() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ __enter="$(cat "${__prefix}.enter")"
+ shift
+ echo "$*" >> "${__prefix}.log"
+ mkfifo "${__prefix}.stdout" "${__prefix}.stderr"
+ tee -a "${__prefix}.log" < "${__prefix}.stdout" &
+ tee -a "${__prefix}.log" < "${__prefix}.stderr" >&2 &
+ ${__enter} "$*" >> "${__prefix}.stdout" 2>> "${__prefix}.stderr"
+ rc=$?
+ rm "${__prefix}.stdout" "${__prefix}.stderr"
+ [ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__prefix}.log"
+ echo -n "${__name}$ " >> "${__prefix}.log"
+ return $rc
+}
+
+# context_run_bg() - Start a shell command in a context
+# $1: Context name
+# $*: Command to start
+context_run_bg() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ context_run "$@" &
+ echo $! > "${__prefix}.pid"
+}
+
+# context_wait() - Wait for background command in a context to complete
+# $1: Context name
+# Returns the status of the completed command
+context_wait() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ __pid=$(cat "${__prefix}.pid")
+ rm "${__prefix}.pid"
+ wait ${__pid}
+}
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 03/11] test: Allow a tmux pane to watch commands executed in contexts
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
2022-09-12 10:56 ` [PATCH v3 01/11] test: Correctly match "background" with "wait" commands David Gibson
2022-09-12 10:56 ` [PATCH v3 02/11] test: Context execution helpers David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 04/11] test: Integration of old-style pane execution and new context execution David Gibson
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 1611 bytes --]
We're moving to a new way of the tests dispatching commands to running in
contexts (host, guest, namespace, etc.). As we make this transition,
though, we still want the user to be able to watch the commands running
in a context, as they previously could from the commands issued in the
pane.
Add a helper to set up a pane to watch a context's log to allow this. In
some cases we currently issue commands from several different logical
contexts in the same pane, so allow a pane to watch several contexts at
once. Also use tail's --retry option to allow starting the watch before
we've initialized the context which will be useful in some cases.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/term | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/test/lib/term b/test/lib/term
index ddabf8d..78700f5 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -241,6 +241,24 @@ pane_status() {
return ${__status}
}
+# pane_watch_context() - Set up pane to watch commands executing in context(s)
+# $1: Pane number
+# $2: Description (for pane label)
+# $@: Context name or names
+pane_watch_contexts() {
+ __pane_number="${1}"
+ __desc="${2}"
+ shift 2
+ __name="${2}"
+
+ tmux select-pane -t ${__pane_number} -T "${__desc}"
+ __cmd="tail -f --retry"
+ for c; do
+ __cmd="${__cmd} ${LOGDIR}/context_${c}.log"
+ done
+ cmd_write ${__pane_number} "${__cmd}"
+}
+
# status_file_end() - Display and log messages when tests from one file are done
status_file_end() {
[ -z "${STATUS_FILE}" ] && return
--
@@ -241,6 +241,24 @@ pane_status() {
return ${__status}
}
+# pane_watch_context() - Set up pane to watch commands executing in context(s)
+# $1: Pane number
+# $2: Description (for pane label)
+# $@: Context name or names
+pane_watch_contexts() {
+ __pane_number="${1}"
+ __desc="${2}"
+ shift 2
+ __name="${2}"
+
+ tmux select-pane -t ${__pane_number} -T "${__desc}"
+ __cmd="tail -f --retry"
+ for c; do
+ __cmd="${__cmd} ${LOGDIR}/context_${c}.log"
+ done
+ cmd_write ${__pane_number} "${__cmd}"
+}
+
# status_file_end() - Display and log messages when tests from one file are done
status_file_end() {
[ -z "${STATUS_FILE}" ] && return
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 04/11] test: Integration of old-style pane execution and new context execution
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (2 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 03/11] test: Allow a tmux pane to watch commands executed in contexts David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 05/11] test: Issue host commands via context for most tests David Gibson
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 12123 bytes --]
We're creating a system for tests to more reliably execute commands in
various contexts (e.g. host, guest, namespace). That transition is going
to happen over a number of steps though, so in the meantime we need to deal
with both the old-style issuing of commands via typing into and screen
scraping tmux panels, and the new-style system for executing commands in
context.
Introduce some transitional helpers which will issue a command via context
if the requested context is initialized, but will otherwise fall back to
the old style tmux panel based method. Re-implement the various test DSL
commands in terms of these new helpers.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/term | 63 +++++++++++++++++++++++
test/lib/test | 138 +++++++++++++++++++++-----------------------------
test/run | 1 +
3 files changed, 121 insertions(+), 81 deletions(-)
diff --git a/test/lib/term b/test/lib/term
index 78700f5..fc229f1 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -259,6 +259,69 @@ pane_watch_contexts() {
cmd_write ${__pane_number} "${__cmd}"
}
+# pane_or_context_run() - Issue a command in given context or pane
+# $1: Context or lower-case pane name
+# $@: Command to issue
+pane_or_context_run() {
+ __name="${1}"
+ shift
+ if context_exists "${__name}"; then
+ context_run "${__name}" "$@" >/dev/null 2>&1
+ else
+ __uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+ pane_run "${__uc}" "$@"
+ pane_status "${__uc}"
+ fi
+}
+
+# pane_or_context_run_bg() - Issue a background command in given context or pane
+# $1: Context or lower-case pane name
+# $@: Command to issue
+pane_or_context_run_bg() {
+ __name="${1}"
+ shift
+ if context_exists "${__name}"; then
+ context_run_bg "${__name}" "$@" >/dev/null 2>&1
+ else
+ __uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+ pane_run "${__uc}" "$@"
+ fi
+}
+
+# pane_or_context_output() - Get output from a command in a context or pane
+# $1: Context or lower-case pane name
+# $@: Command to issue
+pane_or_context_output() {
+ __name="${1}"
+ shift
+ if context_exists "${__name}"; then
+ __output=$(context_run "${__name}" "$@" 2>/dev/null)
+ if [ -z "${__output}" ]; then
+ echo "@EMPTY@"
+ else
+ echo "${__output}"
+ fi
+ else
+ __uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+ pane_run "${__uc}" "$@"
+ pane_wait "${__uc}"
+ pane_parse "${__uc}"
+ fi
+}
+
+# pane_or_context_wait() - Wait for a command to be done in a context or pane
+# $1: Context or lower-case pane name
+pane_or_context_wait() {
+ __name="${1}"
+ shift
+ if context_exists "${__name}"; then
+ context_wait "${__name}"
+ else
+ __uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+ pane_wait "${__uc}"
+ fi
+}
+
# status_file_end() - Display and log messages when tests from one file are done
status_file_end() {
[ -z "${STATUS_FILE}" ] && return
diff --git a/test/lib/test b/test/lib/test
index 5a6c01c..0d06afd 100755
--- a/test/lib/test
+++ b/test/lib/test
@@ -15,8 +15,8 @@
# test_iperf3() - Ugly helper for iperf3 directive
# $1: Variable name: to put the measure bandwidth into
-# $2: Source/client pane name, can be lowercase
-# $3: Destination/server pane name, can be lowercase
+# $2: Source/client context
+# $3: Destination/server context
# $4: Destination name or address for client
# $5: Port number, ${i} is translated to process index
# $6: Number of processes to run in parallel
@@ -24,14 +24,14 @@
# $@: Client options
test_iperf3() {
__var="${1}"; shift
- __cpane="$(echo "${1}" | tr [a-z] [A-Z])"; shift
- __spane="$(echo "${1}" | tr [a-z] [A-Z])"; shift
+ __cctx="${1}"; shift
+ __sctx="${1}"; shift
__dest="${1}"; shift
__port="${1}"; shift
__procs="$((${1} - 1))"; shift
__time="${1}"; shift
- pane_run "${__spane}" \
+ pane_or_context_run_bg "${__sctx}" \
'(' \
' for i in $(seq 0 '${__procs}'); do' \
' iperf3 -s1J -p'${__port}' -i'${__time} \
@@ -40,7 +40,9 @@ test_iperf3() {
' wait' \
')'
- pane_run "${__cpane}" \
+ sleep 1 # Wait for server to be ready
+
+ pane_or_context_run "${__cctx}" \
'(' \
' for i in $(seq 0 '${__procs}'); do' \
' iperf3 -c '${__dest}' -p '${__port} \
@@ -49,8 +51,7 @@ test_iperf3() {
' wait' \
')'
- pane_status "${__cpane}"
- pane_status "${__spane}"
+ pane_or_context_wait "${__sctx}"
__jval=".end.sum_received.bits_per_second"
for __opt in ${@}; do
@@ -58,14 +59,10 @@ test_iperf3() {
[ "${__opt}" = "-u" ] && __jval=".intervals[0].sum.bits_per_second"
done
- pane_run "${__spane}" \
- 'cat s*.json | jq -rMs "map('${__jval}') | add"'
- pane_wait "${__spane}"
- __bw="$(pane_parse "${__spane}")"
-
- pane_run "${__spane}" \
+ __bw=$(pane_or_context_output "${__sctx}" \
+ 'cat s*.json | jq -rMs "map('${__jval}') | add"')
+ pane_or_context_run "${__sctx}" \
'for i in $(seq 0 '${__procs}'); do rm s${i}.json; done'
- pane_status "${__spane}"
TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__var}__" "${__bw}" )"
}
@@ -122,155 +119,134 @@ test_one_line() {
TEST_ONE_perf_nok=0
;;
"host")
- pane_run HOST "${__arg}"
- pane_status HOST || TEST_ONE_nok=1
+ pane_or_context_run host "${__arg}" || TEST_ONE_nok=1
;;
"hostb")
- pane_run HOST "${__arg}"
+ pane_or_context_run_bg host "${__arg}"
;;
"hostw")
- pane_status HOST || TEST_ONE_nok=1
+ pane_or_context_wait host || TEST_ONE_nok=1
;;
"hint")
tmux send-keys -t ${PANE_HOST} "C-c"
;;
"htools")
- pane_run HOST 'which '"${__arg}"' >/dev/null'
- pane_status HOST || TEST_ONE_skip=1
+ pane_or_context_run host 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
;;
"passt")
- pane_run PASST "${__arg}"
- pane_status PASST || TEST_ONE_nok=1
+ pane_or_context_run passt "${__arg}" || TEST_ONE_nok=1
;;
"passtb")
- pane_run PASST "${__arg}"
+ pane_or_context_run_bg passt "${__arg}"
;;
"passtw")
- pane_status PASST || TEST_ONE_nok=1
+ pane_or_context_wait passt || TEST_ONE_nok=1
;;
"pout")
__varname="${__arg%% *}"
- pane_run PASST "${__arg#* }"
- pane_wait PASST
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse PASST)")"
+ __output="$(pane_or_context_output passt "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"guest")
- pane_run GUEST "${__arg}"
- pane_status GUEST || TEST_ONE_nok=1
+ pane_or_context_run guest "${__arg}" || TEST_ONE_nok=1
;;
"guestb")
- pane_run GUEST "${__arg}"
+ pane_or_context_run_bg guest "${__arg}"
;;
"guestw")
- pane_status GUEST || TEST_ONE_nok=1
+ pane_or_context_wait guest || TEST_ONE_nok=1
;;
"guest1")
- pane_run GUEST_1 "${__arg}"
- pane_status GUEST_1 || TEST_ONE_nok=1
+ pane_or_context_run guest_1 "${__arg}" || TEST_ONE_nok=1
;;
"guest1b")
- pane_run GUEST_1 "${__arg}"
+ pane_or_context_run_bg guest_1 "${__arg}"
;;
"guest1w")
- pane_status GUEST_1 || TEST_ONE_nok=1
+ pane_or_context_wait guest_1 || TEST_ONE_nok=1
;;
"gtools")
- pane_run GUEST 'which '"${__arg}"' >/dev/null'
- pane_status GUEST || TEST_ONE_skip=1
+ pane_or_context_run guest 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
;;
"g1tools")
- pane_run GUEST_1 'which '"${__arg}"' >/dev/null'
- pane_status GUEST_1 || TEST_ONE_skip=1
+ pane_or_context_run guest_1 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
;;
"g2tools")
- pane_run GUEST_2 'which '"${__arg}"' >/dev/null'
- pane_status GUEST_2 || TEST_ONE_skip=1
+ pane_or_context_run guest_2 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
;;
"guest2")
- pane_run GUEST_2 "${__arg}"
- pane_status GUEST_2 || TEST_ONE_nok=1
+ pane_or_context_run guest_2 "${__arg}" || TEST_ONE_nok=1
;;
"guest2b")
- pane_run GUEST_2 "${__arg}"
+ pane_or_context_run_bg guest_2 "${__arg}"
;;
"guest2w")
- pane_status GUEST_2 || TEST_ONE_nok=1
+ pane_or_context_wait guest_2 || TEST_ONE_nok=1
;;
"ns")
- pane_run NS "${__arg}"
- pane_status NS || TEST_ONE_nok=1
+ pane_or_context_run ns "${__arg}" || TEST_ONE_nok=1
;;
"ns1")
- pane_run NS1 "${__arg}"
- pane_status NS1 || TEST_ONE_nok=1
+ pane_or_context_run ns1 "${__arg}" || TEST_ONE_nok=1
;;
"ns2")
- pane_run NS2 "${__arg}"
- pane_status NS2 || TEST_ONE_nok=1
+ pane_or_context_run ns2 "${__arg}" || TEST_ONE_nok=1
;;
"nsb")
- pane_run NS "${__arg}"
+ pane_or_context_run_bg ns "${__arg}"
;;
"ns1b")
- pane_run NS1 "${__arg}"
+ pane_or_context_run_bg ns1 "${__arg}"
;;
"ns2b")
- pane_run NS2 "${__arg}"
+ pane_or_context_run_bg ns2 "${__arg}"
;;
"nsw")
- pane_status NS || TEST_ONE_nok=1
+ pane_or_context_wait ns || TEST_ONE_nok=1
;;
"ns1w")
- pane_status NS1 || TEST_ONE_nok=1
+ pane_or_context_wait ns1 || TEST_ONE_nok=1
;;
"ns2w")
- pane_status NS2 || TEST_ONE_nok=1
+ pane_or_context_wait ns2 || TEST_ONE_nok=1
;;
"nstools")
- pane_run NS 'which '"${__arg}"' >/dev/null'
- pane_status NS || TEST_ONE_skip=1
+ pane_or_context_run ns 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
;;
"gout")
__varname="${__arg%% *}"
- pane_run GUEST "${__arg#* }"
- pane_wait GUEST
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse GUEST)")"
+ __output="$(pane_or_context_output guest "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"g1out")
__varname="${__arg%% *}"
- pane_run GUEST_1 "${__arg#* }"
- pane_wait GUEST_1
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse GUEST_1)")"
+ __output="$(pane_or_context_output guest_1 "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"g2out")
__varname="${__arg%% *}"
- pane_run GUEST_2 "${__arg#* }"
- pane_wait GUEST_2
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse GUEST_2)")"
+ __output="$(pane_or_context_output guest_2 "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"hout")
__varname="${__arg%% *}"
- pane_run HOST "${__arg#* }"
- pane_wait HOST
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse HOST)")"
+ __output="$(pane_or_context_output host "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"nsout")
__varname="${__arg%% *}"
- pane_run NS "${__arg#* }"
- pane_wait NS
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse NS)")"
+ __output="$(pane_or_context_output ns "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"ns1out")
__varname="${__arg%% *}"
- pane_run NS1 "${__arg#* }"
- pane_wait NS1
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse NS1)")"
+ __output="$(pane_or_context_output ns1 "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"ns2out")
__varname="${__arg%% *}"
- pane_run NS2 "${__arg#* }"
- pane_wait NS2
- TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse NS2)")"
+ __output="$(pane_or_context_output ns2 "${__arg#* }")"
+ TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
;;
"check")
info_check "${__arg}"
diff --git a/test/run b/test/run
index aa9a380..0ec1334 100755
--- a/test/run
+++ b/test/run
@@ -39,6 +39,7 @@ COMMIT="$(git log --oneline --no-decorate -1)"
. lib/util
. lib/setup
+. lib/context
. lib/term
. lib/perf_report
. lib/layout
--
@@ -39,6 +39,7 @@ COMMIT="$(git log --oneline --no-decorate -1)"
. lib/util
. lib/setup
+. lib/context
. lib/term
. lib/perf_report
. lib/layout
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 05/11] test: Issue host commands via context for most tests
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (3 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 04/11] test: Integration of old-style pane execution and new context execution David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 06/11] test: Use new-style contexts for passt pane in the pasta and passt tests David Gibson
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 6197 bytes --]
Convert most of the tests to use the new-style system for issuing commands
for all host commands. We leave the distro tests for now: they use
the same pane for both host and guest commands which we'll need some more
things to deal with.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/layout | 20 ++++++++++----------
test/lib/setup | 47 ++++++++++++++++++++++++++++++++---------------
2 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/test/lib/layout b/test/lib/layout
index 2d6b197..09c213a 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -31,8 +31,12 @@ layout_host() {
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
- tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
- tmux select-pane -t ${PANE_HOST} -T "host"
+ if context_exists host; then
+ pane_watch_contexts 0 host host
+ else
+ tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
+ tmux select-pane -t ${PANE_HOST} -T "host"
+ fi
info_layout "host commands only"
@@ -64,8 +68,7 @@ layout_pasta() {
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
- tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
- tmux select-pane -t ${PANE_HOST} -T "host"
+ pane_watch_contexts ${PANE_HOST} host host
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "pasta"
@@ -100,8 +103,7 @@ layout_passt() {
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
- tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
- tmux select-pane -t ${PANE_HOST} -T "host"
+ pane_watch_contexts ${PANE_HOST} host host
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "passt"
@@ -141,8 +143,7 @@ layout_passt_in_pasta() {
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
- tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
- tmux select-pane -t ${PANE_HOST} -T "host"
+ pane_watch_contexts ${PANE_HOST} host host
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "passt in pasta (namespace)"
@@ -189,8 +190,7 @@ layout_two_guests() {
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
- tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
- tmux select-pane -t ${PANE_HOST} -T "host"
+ pane_watch_contexts ${PANE_HOST} host host
tmux pipe-pane -O -t ${PANE_PASST_1} "cat >> ${LOGDIR}/pane_passt_1.log"
tmux select-pane -t ${PANE_PASST_1} -T "passt #1 in namespace #1"
diff --git a/test/lib/setup b/test/lib/setup
index 42f03c1..09608dd 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -20,6 +20,8 @@ VMEM="$((${__mem_kib} / 1024 / 4))"
# setup_build() - Set up pane layout for build tests
setup_build() {
+ context_setup_host host
+
layout_host
}
@@ -30,6 +32,8 @@ setup_distro() {
# setup_passt() - Start qemu and passt
setup_passt() {
+ context_setup_host host
+
layout_passt
# Ports:
@@ -63,17 +67,12 @@ setup_passt() {
" -netdev socket,fd=5,id=hostnet0" \
' -pidfile passt_qemu.pid'
pane_status GUEST
-
- # Set things up to reduce problems parsing host command output
- pane_run HOST "PS1='$ '"
- pane_wait HOST
- # Non-bash shells will fail this, but also don't need it, so ignore errors
- pane_run HOST "bind 'set enable-bracketed-paste off'"
- pane_wait HOST
}
# setup_pasta() - Create a network and user namespace, connect pasta to it
setup_pasta() {
+ context_setup_host host
+
layout_pasta
pane_run NS 'echo $$'
@@ -105,6 +104,8 @@ setup_pasta() {
# setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
setup_passt_in_ns() {
+ context_setup_host host
+
layout_passt_in_pasta
# Ports:
@@ -182,17 +183,12 @@ setup_passt_in_ns() {
" -netdev socket,fd=5,id=hostnet0" \
' -pidfile passt_in_ns_qemu.pid'
pane_status GUEST
-
- # Set things up to reduce problems parsing host command output
- pane_run HOST "PS1='$ '"
- pane_wait HOST
- # Non-bash shells will fail this, but also don't need it, so ignore errors
- pane_run HOST "bind 'set enable-bracketed-paste off'"
- pane_wait HOST
}
# setup_two_guests() - Set up two namespace, run qemu and passt in both of them
setup_two_guests() {
+ context_setup_host host
+
layout_two_guests
# Ports:
@@ -290,9 +286,21 @@ setup_two_guests() {
pane_status GUEST_2
}
+# teardown_context_watch() - Remove contexts and stop panes watching them
+# $1: Pane number watching
+# $@: Context names
+teardown_context_watch() {
+ __pane="$1"
+ shift
+ for __c; do
+ context_teardown "${__c}"
+ done
+ tmux send-keys -t ${__pane} "C-c"
+}
+
# teardown_build() - Nothing to do, yet
teardown_build() {
- :
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_distro() - Nothing to do, yet
@@ -303,14 +311,19 @@ teardown_distro() {
# teardown_passt() - Kill qemu, remove passt PID file
teardown_passt() {
kill $(cat passt_qemu.pid)
+
pane_wait GUEST
rm passt.pid
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_passt() - Exit namespace, kill pasta process
teardown_pasta() {
tmux send-keys -t ${PANE_NS} "C-d"
pane_wait NS
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
@@ -326,6 +339,8 @@ teardown_passt_in_ns() {
pane_wait PASST
rm passt.pid
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
@@ -350,6 +365,8 @@ teardown_two_guests() {
pane_wait GUEST_2
pane_wait PASST_1
pane_wait PASST_2
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
--
@@ -20,6 +20,8 @@ VMEM="$((${__mem_kib} / 1024 / 4))"
# setup_build() - Set up pane layout for build tests
setup_build() {
+ context_setup_host host
+
layout_host
}
@@ -30,6 +32,8 @@ setup_distro() {
# setup_passt() - Start qemu and passt
setup_passt() {
+ context_setup_host host
+
layout_passt
# Ports:
@@ -63,17 +67,12 @@ setup_passt() {
" -netdev socket,fd=5,id=hostnet0" \
' -pidfile passt_qemu.pid'
pane_status GUEST
-
- # Set things up to reduce problems parsing host command output
- pane_run HOST "PS1='$ '"
- pane_wait HOST
- # Non-bash shells will fail this, but also don't need it, so ignore errors
- pane_run HOST "bind 'set enable-bracketed-paste off'"
- pane_wait HOST
}
# setup_pasta() - Create a network and user namespace, connect pasta to it
setup_pasta() {
+ context_setup_host host
+
layout_pasta
pane_run NS 'echo $$'
@@ -105,6 +104,8 @@ setup_pasta() {
# setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
setup_passt_in_ns() {
+ context_setup_host host
+
layout_passt_in_pasta
# Ports:
@@ -182,17 +183,12 @@ setup_passt_in_ns() {
" -netdev socket,fd=5,id=hostnet0" \
' -pidfile passt_in_ns_qemu.pid'
pane_status GUEST
-
- # Set things up to reduce problems parsing host command output
- pane_run HOST "PS1='$ '"
- pane_wait HOST
- # Non-bash shells will fail this, but also don't need it, so ignore errors
- pane_run HOST "bind 'set enable-bracketed-paste off'"
- pane_wait HOST
}
# setup_two_guests() - Set up two namespace, run qemu and passt in both of them
setup_two_guests() {
+ context_setup_host host
+
layout_two_guests
# Ports:
@@ -290,9 +286,21 @@ setup_two_guests() {
pane_status GUEST_2
}
+# teardown_context_watch() - Remove contexts and stop panes watching them
+# $1: Pane number watching
+# $@: Context names
+teardown_context_watch() {
+ __pane="$1"
+ shift
+ for __c; do
+ context_teardown "${__c}"
+ done
+ tmux send-keys -t ${__pane} "C-c"
+}
+
# teardown_build() - Nothing to do, yet
teardown_build() {
- :
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_distro() - Nothing to do, yet
@@ -303,14 +311,19 @@ teardown_distro() {
# teardown_passt() - Kill qemu, remove passt PID file
teardown_passt() {
kill $(cat passt_qemu.pid)
+
pane_wait GUEST
rm passt.pid
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_passt() - Exit namespace, kill pasta process
teardown_pasta() {
tmux send-keys -t ${PANE_NS} "C-d"
pane_wait NS
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
@@ -326,6 +339,8 @@ teardown_passt_in_ns() {
pane_wait PASST
rm passt.pid
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
@@ -350,6 +365,8 @@ teardown_two_guests() {
pane_wait GUEST_2
pane_wait PASST_1
pane_wait PASST_2
+
+ teardown_context_watch ${PANE_HOST} host
}
# teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 06/11] test: Use new-style contexts for passt pane in the pasta and passt tests
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (4 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 05/11] test: Issue host commands via context for most tests David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 07/11] test: Add nsholder utility David Gibson
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 4308 bytes --]
Convert the pasta and passt tests to use new-style context execution
for the things that run in the "passt" frame. Don't touch the
passt_in_ns or two_guests tests yet, because they run passt inside a
namespace which introduces some additional complications we have yet
to handle.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/layout | 8 ++------
test/lib/setup | 19 +++++++++----------
test/shutdown/passt | 4 +---
3 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/test/lib/layout b/test/lib/layout
index 09c213a..95bd035 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -69,9 +69,7 @@ layout_pasta() {
tmux select-pane -t ${PANE_INFO} -T "test log"
pane_watch_contexts ${PANE_HOST} host host
-
- tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
- tmux select-pane -t ${PANE_PASST} -T "pasta"
+ pane_watch_contexts ${PANE_PASST} pasta passt
info_layout "single pasta instance with namespace"
@@ -104,9 +102,7 @@ layout_passt() {
tmux select-pane -t ${PANE_INFO} -T "test log"
pane_watch_contexts ${PANE_HOST} host host
-
- tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
- tmux select-pane -t ${PANE_PASST} -T "passt"
+ pane_watch_contexts ${PANE_PASST} passt passt
info_layout "single passt instance with guest"
diff --git a/test/lib/setup b/test/lib/setup
index 09608dd..6598422 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -33,6 +33,7 @@ setup_distro() {
# setup_passt() - Start qemu and passt
setup_passt() {
context_setup_host host
+ context_setup_host passt
layout_passt
@@ -48,11 +49,9 @@ setup_passt() {
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST "make clean"
- pane_status PASST
- pane_run PASST "make valgrind"
- pane_status PASST
- pane_run PASST "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
+ context_run passt "make clean"
+ context_run passt "make valgrind"
+ context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
sleep 5
pane_run GUEST './qrap 5 qemu-system-$(uname -m)' \
@@ -72,6 +71,7 @@ setup_passt() {
# setup_pasta() - Create a network and user namespace, connect pasta to it
setup_pasta() {
context_setup_host host
+ context_setup_host passt
layout_pasta
@@ -82,9 +82,7 @@ setup_pasta() {
pane_run NS "unshare -rUnpf /bin/sh"
pane_status NS
- pane_run PASST "pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p'"
- pane_wait PASST
- __target_pid="$(pane_parse PASST)"
+ __target_pid=$(pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p')
# Ports:
#
@@ -98,7 +96,7 @@ setup_pasta() {
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P passt.pid ${__target_pid}"
+ context_run_bg passt "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P passt.pid ${__target_pid}"
sleep 1
}
@@ -311,11 +309,11 @@ teardown_distro() {
# teardown_passt() - Kill qemu, remove passt PID file
teardown_passt() {
kill $(cat passt_qemu.pid)
-
pane_wait GUEST
rm passt.pid
teardown_context_watch ${PANE_HOST} host
+ teardown_context_watch ${PANE_PASST} passt
}
# teardown_passt() - Exit namespace, kill pasta process
@@ -324,6 +322,7 @@ teardown_pasta() {
pane_wait NS
teardown_context_watch ${PANE_HOST} host
+ teardown_context_watch ${PANE_PASST} passt
}
# teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
diff --git a/test/shutdown/passt b/test/shutdown/passt
index 4a7b702..ac8ff08 100644
--- a/test/shutdown/passt
+++ b/test/shutdown/passt
@@ -17,6 +17,4 @@ test shutdown: exit code
hout PASST_PID cat passt.pid
host kill __PASST_PID__
sleep 1
-
-pout EXIT echo $?
-check [ "__EXIT__" = "0" ]
+passtw
--
@@ -17,6 +17,4 @@ test shutdown: exit code
hout PASST_PID cat passt.pid
host kill __PASST_PID__
sleep 1
-
-pout EXIT echo $?
-check [ "__EXIT__" = "0" ]
+passtw
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 07/11] test: Add nsholder utility
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (5 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 06/11] test: Use new-style contexts for passt pane in the pasta and passt tests David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 08/11] test: Extend context system to run commands in namespace for pasta tests David Gibson
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 5830 bytes --]
In our test scripts we need to do some ugly parsing of /proc and/or pstree
output in order to get the PIDs of processes running in namespaces so that
we can connect to those namespaces with nsenter or pasta.
This is actually a pretty tricky problem with standard tools. To determine
the PID from the outside of the namespace we need to know how the process
of interest is related to the unshare or pasta process (child? one of
several children? grandchild?) as well as then parsing /proc or ps output.
This is slightly awkward now, and will get worse with future changes I'd
like to make to have processes are dispatched.
The obvious solution would be to have the process of interest (which we
control) report its own PID, but that doesn't work easily, because it is in
a PID namepace and sees only its local PID not the global PID we need to
address it from outside.
To handle this, add a small custom tool, "nsholder". This takes a path
and a mode parameter. In "hold" mode it will create a unix domain socket
bound to the path and listening. In "pid" mode it will get the "hold"ing
process's pid via the unix socket using SO_PEERCRED, which translates
between PID namespaces. In "stop" mode it will send a message to the
socket causing the "hold"ing process to clean up and exit.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/.gitignore | 1 +
test/Makefile | 8 ++-
test/nsholder.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 147 insertions(+), 1 deletion(-)
create mode 100644 test/nsholder.c
diff --git a/test/.gitignore b/test/.gitignore
index 129ddc0..d477a42 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -10,3 +10,4 @@ QEMU_EFI.fd
*.start
*.stop
*.js
+nsholder
diff --git a/test/Makefile b/test/Makefile
index f11c4b5..e0dc7ac 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -56,10 +56,13 @@ DOWNLOAD_ASSETS = mbuto \
$(DEBIAN_IMGS) $(FEDORA_IMGS) $(OPENSUSE_IMGS) $(UBUNTU_IMGS)
LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \
$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
- $(UBUNTU_NEW_IMGS:%=prepared-%)
+ $(UBUNTU_NEW_IMGS:%=prepared-%) \
+ nsholder
ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS)
+CFLAGS = -Wall -Werror
+
assets: $(ASSETS)
mbuto:
@@ -68,6 +71,9 @@ mbuto:
mbuto.img: passt.mbuto mbuto
./mbuto/mbuto -p ./$< -c lz4 -f $@
+nsholder: nsholder.c
+ $(CC) $(CFLAGS) -o $@ $^
+
QEMU_EFI.fd:
./find-arm64-firmware.sh $@
diff --git a/test/nsholder.c b/test/nsholder.c
new file mode 100644
index 0000000..aac901b
--- /dev/null
+++ b/test/nsholder.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+/* nsholder - maintain a namespace to be entered by other processes
+ *
+ * Copyright Red Hat
+ * Author: David Gibson <david(a)gibson.dropbear.id.au>
+ *
+ * Can run in 3 modes:
+ *
+ * nsholder <path> hold
+ * Designed to be run inside a namespace, opens a Unix domain
+ * control socket at <path> and waits until instructed to stop
+ * with "nsholder <path> stop"
+ * nsholder <path> pid
+ * Prints the PID of the nsholder hold process with control
+ * socket <path>. This is given in the PID namespace where
+ * nsholder pid is executed, not the one where nsholder hold is
+ * running
+ * nsholder <path> stop
+ * Instruct the nsholder hold with control socket at <path> to exit.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#define die(...) \
+ do { \
+ fprintf(stderr, __VA_ARGS__); \
+ exit(1); \
+ } while (0)
+
+static void usage(void)
+{
+ die("Usage: holder <socket path> hold|pid\n");
+}
+
+static void hold(int fd, const struct sockaddr_un *addr)
+{
+ int rc;
+
+ rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (rc < 0)
+ die("bind(): %s\n", strerror(errno));
+
+ rc = listen(fd, 0);
+ if (rc < 0)
+ die("listen(): %s\n", strerror(errno));
+
+ printf("nsholder: local PID=%d local UID=%d local GID=%d\n",
+ getpid(), getuid(), getgid());
+ do {
+ int afd = accept(fd, NULL, NULL);
+ char buf;
+
+ if (afd < 0)
+ die("accept(): %s\n", strerror(errno));
+
+ rc = read(afd, &buf, sizeof(buf));
+ if (rc < 0)
+ die("read(): %s\n", strerror(errno));
+ } while (rc == 0);
+
+ unlink(addr->sun_path);
+}
+
+static void pid(int fd, const struct sockaddr_un *addr)
+{
+ int rc;
+ struct ucred peercred;
+ socklen_t optlen = sizeof(peercred);
+
+ do {
+ rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (rc < 0 && errno != ENOENT && errno != ECONNREFUSED)
+ die("connect(): %s\n", strerror(errno));
+ } while (rc < 0);
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+ &peercred, &optlen);
+ if (rc < 0)
+ die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
+
+ close(fd);
+
+ printf("%d\n", peercred.pid);
+}
+
+static void stop(int fd, const struct sockaddr_un *addr)
+{
+ int rc;
+ char buf = 'Q';
+
+ rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (rc < 0)
+ die("connect(): %s\n", strerror(errno));
+
+ rc = write(fd, &buf, sizeof(buf));
+ if (rc < 0)
+ die("write(): %s\n", strerror(errno));
+
+ close(fd);
+}
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ const char *sockname;
+ struct sockaddr_un sockaddr = {
+ .sun_family = AF_UNIX,
+ };
+
+ if (argc != 3)
+ usage();
+
+ sockname = argv[1];
+ strncpy(sockaddr.sun_path, sockname, UNIX_PATH_MAX);
+
+ fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ if (fd < 0)
+ die("socket(): %s\n", strerror(errno));
+
+ if (strcmp(argv[2], "hold") == 0)
+ hold(fd, &sockaddr);
+ else if (strcmp(argv[2], "pid") == 0)
+ pid(fd, &sockaddr);
+ else if (strcmp(argv[2], "stop") == 0)
+ stop(fd, &sockaddr);
+ else
+ usage();
+
+ exit(0);
+}
--
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+/* nsholder - maintain a namespace to be entered by other processes
+ *
+ * Copyright Red Hat
+ * Author: David Gibson <david(a)gibson.dropbear.id.au>
+ *
+ * Can run in 3 modes:
+ *
+ * nsholder <path> hold
+ * Designed to be run inside a namespace, opens a Unix domain
+ * control socket at <path> and waits until instructed to stop
+ * with "nsholder <path> stop"
+ * nsholder <path> pid
+ * Prints the PID of the nsholder hold process with control
+ * socket <path>. This is given in the PID namespace where
+ * nsholder pid is executed, not the one where nsholder hold is
+ * running
+ * nsholder <path> stop
+ * Instruct the nsholder hold with control socket at <path> to exit.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#define die(...) \
+ do { \
+ fprintf(stderr, __VA_ARGS__); \
+ exit(1); \
+ } while (0)
+
+static void usage(void)
+{
+ die("Usage: holder <socket path> hold|pid\n");
+}
+
+static void hold(int fd, const struct sockaddr_un *addr)
+{
+ int rc;
+
+ rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (rc < 0)
+ die("bind(): %s\n", strerror(errno));
+
+ rc = listen(fd, 0);
+ if (rc < 0)
+ die("listen(): %s\n", strerror(errno));
+
+ printf("nsholder: local PID=%d local UID=%d local GID=%d\n",
+ getpid(), getuid(), getgid());
+ do {
+ int afd = accept(fd, NULL, NULL);
+ char buf;
+
+ if (afd < 0)
+ die("accept(): %s\n", strerror(errno));
+
+ rc = read(afd, &buf, sizeof(buf));
+ if (rc < 0)
+ die("read(): %s\n", strerror(errno));
+ } while (rc == 0);
+
+ unlink(addr->sun_path);
+}
+
+static void pid(int fd, const struct sockaddr_un *addr)
+{
+ int rc;
+ struct ucred peercred;
+ socklen_t optlen = sizeof(peercred);
+
+ do {
+ rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (rc < 0 && errno != ENOENT && errno != ECONNREFUSED)
+ die("connect(): %s\n", strerror(errno));
+ } while (rc < 0);
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+ &peercred, &optlen);
+ if (rc < 0)
+ die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
+
+ close(fd);
+
+ printf("%d\n", peercred.pid);
+}
+
+static void stop(int fd, const struct sockaddr_un *addr)
+{
+ int rc;
+ char buf = 'Q';
+
+ rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (rc < 0)
+ die("connect(): %s\n", strerror(errno));
+
+ rc = write(fd, &buf, sizeof(buf));
+ if (rc < 0)
+ die("write(): %s\n", strerror(errno));
+
+ close(fd);
+}
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ const char *sockname;
+ struct sockaddr_un sockaddr = {
+ .sun_family = AF_UNIX,
+ };
+
+ if (argc != 3)
+ usage();
+
+ sockname = argv[1];
+ strncpy(sockaddr.sun_path, sockname, UNIX_PATH_MAX);
+
+ fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ if (fd < 0)
+ die("socket(): %s\n", strerror(errno));
+
+ if (strcmp(argv[2], "hold") == 0)
+ hold(fd, &sockaddr);
+ else if (strcmp(argv[2], "pid") == 0)
+ pid(fd, &sockaddr);
+ else if (strcmp(argv[2], "stop") == 0)
+ stop(fd, &sockaddr);
+ else
+ usage();
+
+ exit(0);
+}
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 08/11] test: Extend context system to run commands in namespace for pasta tests
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (6 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 07/11] test: Add nsholder utility David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 09/11] test: Use context system for guest commands David Gibson
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 3762 bytes --]
Extend the context system to allow commands to be run in a namespace
created with unshare, and use it for the namespace used in the pasta tests.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/context | 21 ++++++++++++++++++++-
test/lib/layout | 4 +---
test/lib/setup | 17 ++++++++---------
3 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/test/lib/context b/test/lib/context
index babf59a..0d92d8f 100644
--- a/test/lib/context
+++ b/test/lib/context
@@ -13,13 +13,32 @@
# Copyright Red Hat
# Author: David Gibson <david(a)gibson.dropbear.id.au>
+# context_setup_common() - Create outline of a new context
+# $1: Context name
+context_setup_common() {
+ __name="$1"
+ __prefix="${LOGDIR}/context_${__name}"
+ echo -n "${__name}$ " > "${__prefix}.log"
+}
+
# context_setup_host() - Create a new context for running commands on the host
# $1: Context name
context_setup_host() {
__name="$1"
__prefix="${LOGDIR}/context_${__name}"
+ context_setup_common "${__name}"
echo sh -c > "${__prefix}.enter"
- echo -n "${__name}$ " > "${__prefix}.log"
+}
+
+# context_setup_nsenter() - Create a new context for running commands in a namespace
+# $1: Context name
+# $2: Namespace PID
+context_setup_nsenter() {
+ __name="$1"
+ shift
+ __prefix="${LOGDIR}/context_${__name}"
+ context_setup_common "${__name}"
+ echo "nsenter $@ sh -c" > "${__prefix}.enter"
}
# context_teardown() - Remove a context (leave log files intact)
diff --git a/test/lib/layout b/test/lib/layout
index 95bd035..1401955 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -61,15 +61,13 @@ layout_pasta() {
get_info_cols
- tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
- tmux select-pane -t ${PANE_NS} -T "namespace"
-
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
pane_watch_contexts ${PANE_HOST} host host
pane_watch_contexts ${PANE_PASST} pasta passt
+ pane_watch_contexts ${PANE_NS} "namespace" unshare ns
info_layout "single pasta instance with namespace"
diff --git a/test/lib/setup b/test/lib/setup
index 6598422..a87bce9 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -17,6 +17,7 @@ INITRAMFS="${BASEPATH}/mbuto.img"
VCPUS="$( [ $(nproc) -ge 8 ] && echo 6 || echo $(( $(nproc) / 2 + 1 )) )"
__mem_kib="$(sed -n 's/MemTotal:[ ]*\([0-9]*\) kB/\1/p' /proc/meminfo)"
VMEM="$((${__mem_kib} / 1024 / 4))"
+NSHOLDER="${BASEPATH}/nsholder"
# setup_build() - Set up pane layout for build tests
setup_build() {
@@ -72,17 +73,14 @@ setup_passt() {
setup_pasta() {
context_setup_host host
context_setup_host passt
+ context_setup_host unshare
layout_pasta
- pane_run NS 'echo $$'
- pane_wait NS
- __tty_pid="$(pane_parse NS)"
-
- pane_run NS "unshare -rUnpf /bin/sh"
- pane_status NS
+ context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ns.hold hold"
+ __target_pid=$(${NSHOLDER} ns.hold pid)
- __target_pid=$(pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p')
+ context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
# Ports:
#
@@ -318,11 +316,12 @@ teardown_passt() {
# teardown_passt() - Exit namespace, kill pasta process
teardown_pasta() {
- tmux send-keys -t ${PANE_NS} "C-d"
- pane_wait NS
+ ${NSHOLDER} ns.hold stop
+ context_wait unshare
teardown_context_watch ${PANE_HOST} host
teardown_context_watch ${PANE_PASST} passt
+ teardown_context_watch ${PANE_NS} unshare ns
}
# teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
--
@@ -17,6 +17,7 @@ INITRAMFS="${BASEPATH}/mbuto.img"
VCPUS="$( [ $(nproc) -ge 8 ] && echo 6 || echo $(( $(nproc) / 2 + 1 )) )"
__mem_kib="$(sed -n 's/MemTotal:[ ]*\([0-9]*\) kB/\1/p' /proc/meminfo)"
VMEM="$((${__mem_kib} / 1024 / 4))"
+NSHOLDER="${BASEPATH}/nsholder"
# setup_build() - Set up pane layout for build tests
setup_build() {
@@ -72,17 +73,14 @@ setup_passt() {
setup_pasta() {
context_setup_host host
context_setup_host passt
+ context_setup_host unshare
layout_pasta
- pane_run NS 'echo $$'
- pane_wait NS
- __tty_pid="$(pane_parse NS)"
-
- pane_run NS "unshare -rUnpf /bin/sh"
- pane_status NS
+ context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ns.hold hold"
+ __target_pid=$(${NSHOLDER} ns.hold pid)
- __target_pid=$(pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p')
+ context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
# Ports:
#
@@ -318,11 +316,12 @@ teardown_passt() {
# teardown_passt() - Exit namespace, kill pasta process
teardown_pasta() {
- tmux send-keys -t ${PANE_NS} "C-d"
- pane_wait NS
+ ${NSHOLDER} ns.hold stop
+ context_wait unshare
teardown_context_watch ${PANE_HOST} host
teardown_context_watch ${PANE_PASST} passt
+ teardown_context_watch ${PANE_NS} unshare ns
}
# teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 09/11] test: Use context system for guest commands
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (7 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 08/11] test: Extend context system to run commands in namespace for pasta tests David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 10/11] test: Use context system for two_guests tests David Gibson
2022-09-12 10:56 ` [PATCH v3 11/11] test: Use new-style command issue for passt_in_ns tests David Gibson
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 12809 bytes --]
Extends the context system in the test scripts to allow executing commands
within a guest. Do this without requiring an existing network in the guest
by using socat to run ssh via a vsock connection.
We do need some additional "sleep"s in the tests, because the new
faster dispatch means that sometimes we attempt to connect before
socat has managed to listen.
For now, only use this for the plain "passt" tests. The "passt_in_ns" and
other tests have additional complications we still need to deal with.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/.gitignore | 2 ++
test/Makefile | 7 +++++--
test/lib/context | 28 +++++++++++++++++++++++++++-
test/lib/layout | 4 +---
test/lib/setup | 13 +++++++++----
test/lib/term | 9 ++++++---
test/passt.mbuto | 32 +++++++++++++++++++++++++++++---
test/tcp/passt | 2 ++
test/tcp/passt_in_ns | 8 ++++++++
test/udp/passt | 1 +
10 files changed, 90 insertions(+), 16 deletions(-)
diff --git a/test/.gitignore b/test/.gitignore
index d477a42..0f91c7d 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -11,3 +11,5 @@ QEMU_EFI.fd
*.stop
*.js
nsholder
+guest-key
+guest-key.pub
diff --git a/test/Makefile b/test/Makefile
index e0dc7ac..cc1a818 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -57,7 +57,7 @@ DOWNLOAD_ASSETS = mbuto \
LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \
$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
$(UBUNTU_NEW_IMGS:%=prepared-%) \
- nsholder
+ nsholder guest-key guest-key.pub
ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS)
@@ -68,7 +68,10 @@ assets: $(ASSETS)
mbuto:
git clone git://mbuto.sh/mbuto
-mbuto.img: passt.mbuto mbuto
+guest-key guest-key.pub:
+ ssh-keygen -f guest-key -N ''
+
+mbuto.img: passt.mbuto mbuto guest-key.pub
./mbuto/mbuto -p ./$< -c lz4 -f $@
nsholder: nsholder.c
diff --git a/test/lib/context b/test/lib/context
index 0d92d8f..ccb0004 100644
--- a/test/lib/context
+++ b/test/lib/context
@@ -41,12 +41,38 @@ context_setup_nsenter() {
echo "nsenter $@ sh -c" > "${__prefix}.enter"
}
+# context_setup_guest() - Create a new context for running commands in a guest
+# $1: Context name
+# $2: CID to use for vsock
+context_setup_guest() {
+ __name="$1"
+ __cid="$2"
+ __prefix="${LOGDIR}/context_${__name}"
+ context_setup_common "${__name}"
+
+ cat > "${__prefix}.ssh" <<EOF
+Host ${__name}
+ User root
+ UserKnownHostsFile ${__prefix}.hosts
+ StrictHostKeyChecking no
+ IdentityFile ${BASEPATH}/guest-key
+ IdentityAgent none
+ ProxyCommand socat - VSOCK-CONNECT:${__cid}:22
+EOF
+ echo "ssh -F ${__prefix}.ssh ${__name}" > "${__prefix}.enter"
+
+ # Wait for the guest to be booted and accepting connections
+ while ! ssh -F "${__prefix}.ssh" "${__name}" :; do
+ sleep 0.1
+ done
+}
+
# context_teardown() - Remove a context (leave log files intact)
# $1: Context name
context_teardown() {
__name="$1"
__prefix="${LOGDIR}/context_${__name}"
- rm -f "${__prefix}.enter"
+ rm -f "${__prefix}.enter" "${__prefix}.ssh" "${__prefix}.hosts"
}
# context_exists() - Test if a context currently exists
diff --git a/test/lib/layout b/test/lib/layout
index 1401955..985d31b 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -92,15 +92,13 @@ layout_passt() {
get_info_cols
- tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
- tmux select-pane -t ${PANE_GUEST} -T "guest"
-
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
pane_watch_contexts ${PANE_HOST} host host
pane_watch_contexts ${PANE_PASST} passt passt
+ pane_watch_contexts ${PANE_GUEST} guest qemu guest
info_layout "single passt instance with guest"
diff --git a/test/lib/setup b/test/lib/setup
index a87bce9..5e9072c 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -35,6 +35,7 @@ setup_distro() {
setup_passt() {
context_setup_host host
context_setup_host passt
+ context_setup_host qemu
layout_passt
@@ -55,7 +56,8 @@ setup_passt() {
context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
sleep 5
- pane_run GUEST './qrap 5 qemu-system-$(uname -m)' \
+ GUEST_CID=94557
+ context_run_bg qemu './qrap 5 qemu-system-$(uname -m)' \
' -machine accel=kvm' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \
@@ -65,8 +67,10 @@ setup_passt() {
'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \
" -netdev socket,fd=5,id=hostnet0" \
- ' -pidfile passt_qemu.pid'
- pane_status GUEST
+ " -pidfile passt_qemu.pid" \
+ " -device vhost-vsock-pci,guest-cid=$GUEST_CID"
+
+ context_setup_guest guest $GUEST_CID
}
# setup_pasta() - Create a network and user namespace, connect pasta to it
@@ -307,11 +311,12 @@ teardown_distro() {
# teardown_passt() - Kill qemu, remove passt PID file
teardown_passt() {
kill $(cat passt_qemu.pid)
- pane_wait GUEST
+
rm passt.pid
teardown_context_watch ${PANE_HOST} host
teardown_context_watch ${PANE_PASST} passt
+ teardown_context_watch ${PANE_GUEST} qemu guest
}
# teardown_passt() - Exit namespace, kill pasta process
diff --git a/test/lib/term b/test/lib/term
index fc229f1..2355e64 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -266,7 +266,8 @@ pane_or_context_run() {
__name="${1}"
shift
if context_exists "${__name}"; then
- context_run "${__name}" "$@" >/dev/null 2>&1
+ # Redirect stdin to stop ssh from eating the test instructions file we have on stdin
+ context_run "${__name}" "$@" >/dev/null 2>&1 < /dev/null
else
__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
pane_run "${__uc}" "$@"
@@ -281,7 +282,8 @@ pane_or_context_run_bg() {
__name="${1}"
shift
if context_exists "${__name}"; then
- context_run_bg "${__name}" "$@" >/dev/null 2>&1
+ # Redirect stdin to stop ssh from eating the test instructions file we have on stdin
+ context_run_bg "${__name}" "$@" >/dev/null 2>&1 < /dev/null
else
__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
pane_run "${__uc}" "$@"
@@ -295,7 +297,8 @@ pane_or_context_output() {
__name="${1}"
shift
if context_exists "${__name}"; then
- __output=$(context_run "${__name}" "$@" 2>/dev/null)
+ # Redirect stdin to stop ssh from eating the test instructions file we have on stdin
+ __output=$(context_run "${__name}" "$@" 2>/dev/null </dev/null)
if [ -z "${__output}" ]; then
echo "@EMPTY@"
else
diff --git a/test/passt.mbuto b/test/passt.mbuto
index 8b41674..d29f456 100755
--- a/test/passt.mbuto
+++ b/test/passt.mbuto
@@ -13,15 +13,15 @@
PROGS="${PROGS:-ash,dash,bash ip mount ls insmod mkdir ln cat chmod lsmod
modprobe find grep mknod mv rm umount jq iperf3 dhclient hostname
sed tr chown sipcalc cut md5sum socat dd strace ping tail killall sleep
- sysctl nproc tcp_rr tcp_crr udp_rr which tee seq bc}"
+ sysctl nproc tcp_rr tcp_crr udp_rr which tee seq bc sshd ssh-keygen}"
-KMODS="${KMODS:- virtio_net virtio_pci}"
+KMODS="${KMODS:- virtio_net virtio_pci vmw_vsock_virtio_transport}"
LINKS="${LINKS:-
ash,dash,bash /init
ash,dash,bash /bin/sh}"
-DIRS="${DIRS} /tmp /sbin /var/log /var/run /var/lib"
+DIRS="${DIRS} /tmp /sbin /usr/share /var/log /var/lib /etc/ssh /run/sshd /root/.ssh"
FIXUP="${FIXUP}"'
cat > /sbin/dhclient-script << EOF
@@ -46,7 +46,33 @@ exit 0
EOF
chmod 755 /sbin/dhclient-script
ln -s /sbin /usr/sbin
+ ln -s /bin /usr/bin
+ ln -s /run /var/run
:> /etc/fstab
+
+ # sshd(dropbear) via vsock
+ cat > /etc/passwd << EOF
+root:x:0:0:root:/root:/bin/sh
+sshd:x:100:100:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
+EOF
+ cat > /etc/shadow << EOF
+root:::0:99999:7:::
+EOF
+ chmod 000 /etc/shadow
+
+ :> /etc/ssh/sshd_config
+ ssh-keygen -A
+ chmod 700 /root/.ssh
+ chmod 700 /run/sshd
+ # Alternative location for the priv separation dir
+ ln -s /run/sshd /usr/share/empty.sshd
+
+ cat > /root/.ssh/authorized_keys <<EOF
+'"$(cat guest-key.pub)"'
+EOF
+ chmod 600 /root/.ssh/authorized_keys
+ chmod 700 /root
+ socat VSOCK-LISTEN:22,fork EXEC:"sshd -i -e" 2> /var/log/vsock-ssh.log &
sh +m
'
diff --git a/test/tcp/passt b/test/tcp/passt
index 6e65137..265f270 100644
--- a/test/tcp/passt
+++ b/test/tcp/passt
@@ -17,6 +17,7 @@ htools dd socat ip jq md5sum cut
test TCP/IPv4: host to guest: big transfer
temp TEMP_BIG
guestb socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_big.bin,create,trunc
+sleep 1
host dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
host socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001
guestw
@@ -35,6 +36,7 @@ check [ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
test TCP/IPv4: host to guest: small transfer
temp TEMP_SMALL
guestb socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_small.bin,create,trunc
+sleep 1
host dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
host socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001
guestw
diff --git a/test/tcp/passt_in_ns b/test/tcp/passt_in_ns
index 976e4e9..cb01781 100644
--- a/test/tcp/passt_in_ns
+++ b/test/tcp/passt_in_ns
@@ -18,6 +18,7 @@ nstools socat ip jq md5sum cut
test TCP/IPv4: host to guest: big transfer
temp TEMP_BIG
guestb socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep 1
host dd if=/dev/urandom bs=1M count=10 of=__TEMP_BIG__
host socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001
guestw
@@ -82,6 +83,7 @@ check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: host to guest: small transfer
temp TEMP_SMALL
guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep 1
host dd if=/dev/urandom bs=2k count=100 of=__TEMP_SMALL__
host socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001
guestw
@@ -129,6 +131,7 @@ check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to guest (using loopback address): small transfer
guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep 1
ns socat -u OPEN:__TEMP_NS_SMALL__ TCP4:127.0.0.1:10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@@ -136,6 +139,7 @@ check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to guest (using namespace address): small transfer
guestb socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep 1
ns socat -u OPEN:__TEMP_NS_SMALL__ TCP4:__ADDR__:10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@@ -143,6 +147,7 @@ check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: host to guest: big transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep 1
host socat -u OPEN:__TEMP_BIG__ TCP6:[::1]:10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
@@ -188,6 +193,7 @@ check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to guest (using loopback address): big transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep 1
ns socat -u OPEN:__TEMP_NS_BIG__ TCP6:[::1]:10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
@@ -203,6 +209,7 @@ check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: host to guest: small transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep 1
host socat -u OPEN:__TEMP_SMALL__ TCP6:[::1]:10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@@ -248,6 +255,7 @@ check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to guest (using loopback address): small transfer
guestb socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep 1
ns socat -u OPEN:__TEMP_NS_SMALL__ TCP6:[::1]:10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
diff --git a/test/udp/passt b/test/udp/passt
index 7c58648..a14e6d2 100644
--- a/test/udp/passt
+++ b/test/udp/passt
@@ -18,6 +18,7 @@ test UDP/IPv4: host to guest
temp TEMP
temp SC_PID
guestb (socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
+sleep 1
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
guestw
--
@@ -18,6 +18,7 @@ test UDP/IPv4: host to guest
temp TEMP
temp SC_PID
guestb (socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
+sleep 1
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
guestw
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 10/11] test: Use context system for two_guests tests
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (8 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 09/11] test: Use context system for guest commands David Gibson
@ 2022-09-12 10:56 ` David Gibson
2022-09-12 10:56 ` [PATCH v3 11/11] test: Use new-style command issue for passt_in_ns tests David Gibson
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 9175 bytes --]
Now that we have all the pieces we need for issuing commands both into
namespaces and into guests, we can use those to convert the two_guests to
using only the new style context command issue.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/layout | 15 ++-----
test/lib/setup | 115 ++++++++++++++++++++++--------------------------
2 files changed, 57 insertions(+), 73 deletions(-)
diff --git a/test/lib/layout b/test/lib/layout
index 985d31b..b9d30e9 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -172,23 +172,16 @@ layout_two_guests() {
get_info_cols
- tmux pipe-pane -O -t ${PANE_GUEST_1} "cat >> ${LOGDIR}/pane_guest_1.log"
- tmux select-pane -t ${PANE_GUEST_1} -T "guest #1 in namespace #1"
-
- tmux pipe-pane -O -t ${PANE_GUEST_2} "cat >> ${LOGDIR}/pane_guest_2.log"
- tmux select-pane -t ${PANE_GUEST_2} -T "guest #2 in namespace #2"
+ pane_watch_contexts ${PANE_GUEST_1} "guest #1 in namespace #1" qemu_1 guest_1
+ pane_watch_contexts ${PANE_GUEST_2} "guest #2 in namespace #2" qemu_2 guest_2
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
pane_watch_contexts ${PANE_HOST} host host
-
- tmux pipe-pane -O -t ${PANE_PASST_1} "cat >> ${LOGDIR}/pane_passt_1.log"
- tmux select-pane -t ${PANE_PASST_1} -T "passt #1 in namespace #1"
-
- tmux pipe-pane -O -t ${PANE_PASST_2} "cat >> ${LOGDIR}/pane_passt_2.log"
- tmux select-pane -t ${PANE_PASST_2} -T "passt #2 in namespace #2"
+ pane_watch_contexts ${PANE_PASST_1} "passt #1 in namespace #1" pasta_1 passt_1
+ pane_watch_contexts ${PANE_PASST_2} "passt #2 in namespace #2" pasta_2 passt_2
info_layout "two guests, two passt instances, in namespaces"
diff --git a/test/lib/setup b/test/lib/setup
index 5e9072c..467211a 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -188,6 +188,8 @@ setup_passt_in_ns() {
# setup_two_guests() - Set up two namespace, run qemu and passt in both of them
setup_two_guests() {
context_setup_host host
+ context_setup_host pasta_1
+ context_setup_host pasta_2
layout_two_guests
@@ -201,66 +203,49 @@ setup_two_guests() {
# 10004 | as server | to init | to guest | to ns #2
# 10005 | | | as server | to ns #2
- __pid1_file="$(mktemp)"
- __pid2_file="$(mktemp)"
-
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_1 "./pasta ${__opts} -P ${__pid1_file} -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004"
+ context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
+ __ns1_pid=$(${NSHOLDER} ns1.hold pid)
+ context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_2 "./pasta ${__opts} -P ${__pid2_file} -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001"
+ context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
+ __ns2_pid=$(${NSHOLDER} ns2.hold pid)
+ context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
- sleep 1
- pane_run PASST_1 ''
- pane_run PASST_2 ''
-
- pane_status PASST_1
- pane_status PASST_2
- __pasta1_pid="$(cat "${__pid1_file}")"
- __ns1_pid="$(cat /proc/${__pasta1_pid}/task/${__pasta1_pid}/children | cut -f1 -d' ')"
- rm "${__pid1_file}"
- __pasta2_pid="$(cat "${__pid2_file}")"
- __ns2_pid="$(cat /proc/${__pasta2_pid}/task/${__pasta2_pid}/children | cut -f1 -d' ')"
- rm "${__pid2_file}"
-
- pane_run GUEST_1 "nsenter -t ${__ns1_pid} -U -n --preserve-credentials"
- pane_run GUEST_2 "nsenter -t ${__ns2_pid} -U -n --preserve-credentials"
-
- pane_run PASST_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
- pane_wait PASST_1
- __ifname="$(pane_parse PASST_1)"
-
- pane_run GUEST_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
- pane_run GUEST_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
- pane_status GUEST_1
- pane_status GUEST_2
- sleep 2
- pane_run GUEST_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
- pane_run GUEST_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
- pane_status GUEST_1
- pane_status GUEST_2
+ context_setup_nsenter qemu_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
+ context_setup_nsenter qemu_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
+
+ __ifname="$(context_run qemu_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")"
+
+ context_run qemu_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
+ context_run qemu_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
+ context_run qemu_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
+ context_run qemu_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_1 "./passt -f ${__opts} -t 10001 -u 10001"
+ context_run_bg passt_1 "./passt -P passt_1.pid -f ${__opts} -t 10001 -u 10001"
sleep 1
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_2 "./passt -f ${__opts} -t 10004 -u 10004"
- pane_run GUEST_1 './qrap 5 qemu-system-$(uname -m)' \
+ context_run_bg passt_2 "./passt -P passt_2.pid -f ${__opts} -t 10004 -u 10004"
+
+ GUEST_1_CID=94557
+ context_run_bg qemu_1 './qrap 5 qemu-system-$(uname -m)' \
' -M accel=kvm:tcg' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \
@@ -270,8 +255,11 @@ setup_two_guests() {
'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \
" -netdev socket,fd=5,id=hostnet0" \
- ' -pidfile two_guests_qemu_1.pid'
- pane_run GUEST_2 './qrap 5 qemu-system-$(uname -m)' \
+ ' -pidfile two_guests_qemu_1.pid' \
+ " -device vhost-vsock-pci,guest-cid=$GUEST_1_CID"
+
+ GUEST_2_CID=94558
+ context_run_bg qemu_2 './qrap 5 qemu-system-$(uname -m)' \
' -M accel=kvm:tcg' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \
@@ -281,9 +269,11 @@ setup_two_guests() {
'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \
" -netdev socket,fd=5,id=hostnet0" \
- ' -pidfile two_guests_qemu_2.pid'
- pane_status GUEST_1
- pane_status GUEST_2
+ ' -pidfile two_guests_qemu_2.pid' \
+ " -device vhost-vsock-pci,guest-cid=$GUEST_2_CID"
+
+ context_setup_guest guest_1 ${GUEST_1_CID}
+ context_setup_guest guest_2 ${GUEST_2_CID}
}
# teardown_context_watch() - Remove contexts and stop panes watching them
@@ -348,28 +338,29 @@ teardown_passt_in_ns() {
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
- kill $(cat two_guests_qemu_1.pid)
- pane_wait GUEST_1
- tmux send-keys -t ${PANE_GUEST_1} "C-d"
-
- kill $(cat two_guests_qemu_2.pid)
- pane_wait GUEST_2
- tmux send-keys -t ${PANE_GUEST_2} "C-d"
-
- tmux send-keys -t ${PANE_PASST_1} "C-c"
- pane_wait PASST_1
- tmux send-keys -t ${PANE_PASST_1} "C-d"
-
- tmux send-keys -t ${PANE_PASST_2} "C-c"
- pane_wait PASST_2
- tmux send-keys -t ${PANE_PASST_2} "C-d"
-
- pane_wait GUEST_1
- pane_wait GUEST_2
- pane_wait PASST_1
- pane_wait PASST_2
+ __ns1_pid=$(${NSHOLDER} ns1.hold pid)
+ __ns2_pid=$(${NSHOLDER} ns2.hold pid)
+ nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat two_guests_qemu_1.pid)
+ nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat two_guests_qemu_2.pid)
+ context_wait qemu_1
+ context_wait qemu_2
+
+ nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat passt_1.pid)
+ nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat passt_2.pid)
+ context_wait passt_1
+ context_wait passt_2
+ ${NSHOLDER} ns1.hold stop
+ ${NSHOLDER} ns2.hold stop
+ context_wait pasta_1
+ context_wait pasta_2
+
+ rm -f passt_[12].pid pasta_[12].pid
teardown_context_watch ${PANE_HOST} host
+ teardown_context_watch ${PANE_GUEST_1} qemu_1 guest_1
+ teardown_context_watch ${PANE_GUEST_2} qemu_2 guest_2
+ teardown_context_watch ${PANE_PASST_1} pasta_1 passt_1
+ teardown_context_watch ${PANE_PASST_2} pasta_2 passt_2
}
# teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
--
@@ -188,6 +188,8 @@ setup_passt_in_ns() {
# setup_two_guests() - Set up two namespace, run qemu and passt in both of them
setup_two_guests() {
context_setup_host host
+ context_setup_host pasta_1
+ context_setup_host pasta_2
layout_two_guests
@@ -201,66 +203,49 @@ setup_two_guests() {
# 10004 | as server | to init | to guest | to ns #2
# 10005 | | | as server | to ns #2
- __pid1_file="$(mktemp)"
- __pid2_file="$(mktemp)"
-
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_1 "./pasta ${__opts} -P ${__pid1_file} -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004"
+ context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
+ __ns1_pid=$(${NSHOLDER} ns1.hold pid)
+ context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_2 "./pasta ${__opts} -P ${__pid2_file} -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001"
+ context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
+ __ns2_pid=$(${NSHOLDER} ns2.hold pid)
+ context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
- sleep 1
- pane_run PASST_1 ''
- pane_run PASST_2 ''
-
- pane_status PASST_1
- pane_status PASST_2
- __pasta1_pid="$(cat "${__pid1_file}")"
- __ns1_pid="$(cat /proc/${__pasta1_pid}/task/${__pasta1_pid}/children | cut -f1 -d' ')"
- rm "${__pid1_file}"
- __pasta2_pid="$(cat "${__pid2_file}")"
- __ns2_pid="$(cat /proc/${__pasta2_pid}/task/${__pasta2_pid}/children | cut -f1 -d' ')"
- rm "${__pid2_file}"
-
- pane_run GUEST_1 "nsenter -t ${__ns1_pid} -U -n --preserve-credentials"
- pane_run GUEST_2 "nsenter -t ${__ns2_pid} -U -n --preserve-credentials"
-
- pane_run PASST_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
- pane_wait PASST_1
- __ifname="$(pane_parse PASST_1)"
-
- pane_run GUEST_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
- pane_run GUEST_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
- pane_status GUEST_1
- pane_status GUEST_2
- sleep 2
- pane_run GUEST_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
- pane_run GUEST_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
- pane_status GUEST_1
- pane_status GUEST_2
+ context_setup_nsenter qemu_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
+ context_setup_nsenter qemu_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
+
+ __ifname="$(context_run qemu_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")"
+
+ context_run qemu_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
+ context_run qemu_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
+ context_run qemu_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
+ context_run qemu_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_1 "./passt -f ${__opts} -t 10001 -u 10001"
+ context_run_bg passt_1 "./passt -P passt_1.pid -f ${__opts} -t 10001 -u 10001"
sleep 1
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- pane_run PASST_2 "./passt -f ${__opts} -t 10004 -u 10004"
- pane_run GUEST_1 './qrap 5 qemu-system-$(uname -m)' \
+ context_run_bg passt_2 "./passt -P passt_2.pid -f ${__opts} -t 10004 -u 10004"
+
+ GUEST_1_CID=94557
+ context_run_bg qemu_1 './qrap 5 qemu-system-$(uname -m)' \
' -M accel=kvm:tcg' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \
@@ -270,8 +255,11 @@ setup_two_guests() {
'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \
" -netdev socket,fd=5,id=hostnet0" \
- ' -pidfile two_guests_qemu_1.pid'
- pane_run GUEST_2 './qrap 5 qemu-system-$(uname -m)' \
+ ' -pidfile two_guests_qemu_1.pid' \
+ " -device vhost-vsock-pci,guest-cid=$GUEST_1_CID"
+
+ GUEST_2_CID=94558
+ context_run_bg qemu_2 './qrap 5 qemu-system-$(uname -m)' \
' -M accel=kvm:tcg' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \
@@ -281,9 +269,11 @@ setup_two_guests() {
'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384" \
" -netdev socket,fd=5,id=hostnet0" \
- ' -pidfile two_guests_qemu_2.pid'
- pane_status GUEST_1
- pane_status GUEST_2
+ ' -pidfile two_guests_qemu_2.pid' \
+ " -device vhost-vsock-pci,guest-cid=$GUEST_2_CID"
+
+ context_setup_guest guest_1 ${GUEST_1_CID}
+ context_setup_guest guest_2 ${GUEST_2_CID}
}
# teardown_context_watch() - Remove contexts and stop panes watching them
@@ -348,28 +338,29 @@ teardown_passt_in_ns() {
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
- kill $(cat two_guests_qemu_1.pid)
- pane_wait GUEST_1
- tmux send-keys -t ${PANE_GUEST_1} "C-d"
-
- kill $(cat two_guests_qemu_2.pid)
- pane_wait GUEST_2
- tmux send-keys -t ${PANE_GUEST_2} "C-d"
-
- tmux send-keys -t ${PANE_PASST_1} "C-c"
- pane_wait PASST_1
- tmux send-keys -t ${PANE_PASST_1} "C-d"
-
- tmux send-keys -t ${PANE_PASST_2} "C-c"
- pane_wait PASST_2
- tmux send-keys -t ${PANE_PASST_2} "C-d"
-
- pane_wait GUEST_1
- pane_wait GUEST_2
- pane_wait PASST_1
- pane_wait PASST_2
+ __ns1_pid=$(${NSHOLDER} ns1.hold pid)
+ __ns2_pid=$(${NSHOLDER} ns2.hold pid)
+ nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat two_guests_qemu_1.pid)
+ nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat two_guests_qemu_2.pid)
+ context_wait qemu_1
+ context_wait qemu_2
+
+ nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat passt_1.pid)
+ nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat passt_2.pid)
+ context_wait passt_1
+ context_wait passt_2
+ ${NSHOLDER} ns1.hold stop
+ ${NSHOLDER} ns2.hold stop
+ context_wait pasta_1
+ context_wait pasta_2
+
+ rm -f passt_[12].pid pasta_[12].pid
teardown_context_watch ${PANE_HOST} host
+ teardown_context_watch ${PANE_GUEST_1} qemu_1 guest_1
+ teardown_context_watch ${PANE_GUEST_2} qemu_2 guest_2
+ teardown_context_watch ${PANE_PASST_1} pasta_1 passt_1
+ teardown_context_watch ${PANE_PASST_2} pasta_2 passt_2
}
# teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 11/11] test: Use new-style command issue for passt_in_ns tests
2022-09-12 10:56 [PATCH v3 00/11] Improve command dispatch in test scripts David Gibson
` (9 preceding siblings ...)
2022-09-12 10:56 ` [PATCH v3 10/11] test: Use context system for two_guests tests David Gibson
@ 2022-09-12 10:56 ` David Gibson
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2022-09-12 10:56 UTC (permalink / raw)
To: passt-dev
[-- Attachment #1: Type: text/plain, Size: 7808 bytes --]
Put the pieces together to use the new style context based dispatch for
the passt_in_pasta tests.
Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
test/lib/layout | 10 ++----
test/lib/setup | 73 +++++++++++++++++----------------------
test/shutdown/passt_in_ns | 4 +--
test/tcp/passt_in_ns | 1 +
test/udp/passt_in_ns | 1 +
5 files changed, 37 insertions(+), 52 deletions(-)
diff --git a/test/lib/layout b/test/lib/layout
index b9d30e9..cc7c688 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -125,11 +125,8 @@ layout_passt_in_pasta() {
get_info_cols
- tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
- tmux select-pane -t ${PANE_GUEST} -T "guest"
-
- tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
- tmux select-pane -t ${PANE_NS} -T "namespace"
+ pane_watch_contexts ${PANE_GUEST} "guest" qemu guest
+ pane_watch_contexts ${PANE_NS} "namespace" ns
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
@@ -137,8 +134,7 @@ layout_passt_in_pasta() {
pane_watch_contexts ${PANE_HOST} host host
- tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
- tmux select-pane -t ${PANE_PASST} -T "passt in pasta (namespace)"
+ pane_watch_contexts ${PANE_PASST} "passt in pasta (namespace)" pasta passt
info_layout "passt and guest in namespace, connected by pasta"
diff --git a/test/lib/setup b/test/lib/setup
index 467211a..f1e429c 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -105,6 +105,7 @@ setup_pasta() {
# setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
setup_passt_in_ns() {
context_setup_host host
+ context_setup_host pasta
layout_passt_in_pasta
@@ -127,28 +128,18 @@ setup_passt_in_ns() {
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
- __pid_file="$(mktemp)"
- pane_run PASST "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013 -P ${__pid_file}"
+ context_run_bg pasta "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013 -P pasta.pid ${NSHOLDER} ns.hold hold"
sleep 1
- pane_run PASST ''
- pane_status PASST
- __pasta_pid="$(cat "${__pid_file}")"
- __ns_pid="$(cat /proc/${__pasta_pid}/task/${__pasta_pid}/children | cut -f1 -d' ')"
- rm "${__pid_file}"
-
- pane_run GUEST "nsenter -t ${__ns_pid} -U -n --preserve-credentials"
- pane_run NS "nsenter -t ${__ns_pid} -U -n -p --preserve-credentials"
- pane_status GUEST
- pane_status NS
-
- pane_run NS "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
- pane_wait NS
- __ifname="$(pane_parse NS)"
- pane_run NS "/sbin/dhclient -4 --no-pid ${__ifname}"
- pane_status NS
+ __ns_pid=$(${NSHOLDER} ns.hold pid)
+
+ context_setup_nsenter qemu "-t ${__ns_pid} -U -n -p --preserve-credentials"
+ context_setup_nsenter ns "-t ${__ns_pid} -U -n -p --preserve-credentials"
+ context_setup_nsenter passt "-t ${__ns_pid} -U -n -p --preserve-credentials"
+
+ __ifname=$(context_run ns "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")
+ context_run ns "/sbin/dhclient -4 --no-pid ${__ifname}"
sleep 2
- pane_run NS "/sbin/dhclient -6 --no-pid ${__ifname}"
- pane_status NS
+ context_run ns "/sbin/dhclient -6 --no-pid ${__ifname}"
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_in_pasta.pcap"
@@ -156,21 +147,18 @@ setup_passt_in_ns() {
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
if [ ${VALGRIND} -eq 1 ]; then
- pane_run PASST "make clean"
- pane_status PASST
- pane_run PASST "make valgrind"
- pane_status PASST
- pane_run PASST "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
+ context_run passt "make clean"
+ context_run passt "make valgrind"
+ context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
else
- pane_run PASST "make clean"
- pane_status PASST
- pane_run PASST "make"
- pane_status PASST
- pane_run PASST "./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
+ context_run passt "make clean"
+ context_run passt "make"
+ context_run_bg passt "./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
fi
sleep 5
- pane_run GUEST './qrap 5 qemu-system-$(uname -m)' \
+ GUEST_CID=94557
+ context_run_bg qemu './qrap 5 qemu-system-$(uname -m)' \
' -machine accel=kvm' \
' -M accel=kvm:tcg' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
@@ -181,8 +169,10 @@ setup_passt_in_ns() {
'virtio-net.napi_tx=1"' \
" -device virtio-net-pci,netdev=hostnet0,x-txburst=524288" \
" -netdev socket,fd=5,id=hostnet0" \
- ' -pidfile passt_in_ns_qemu.pid'
- pane_status GUEST
+ ' -pidfile passt_in_ns_qemu.pid' \
+ " -device vhost-vsock-pci,guest-cid=$GUEST_CID"
+
+ context_setup_guest guest $GUEST_CID
}
# setup_two_guests() - Set up two namespace, run qemu and passt in both of them
@@ -321,19 +311,18 @@ teardown_pasta() {
# teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
teardown_passt_in_ns() {
- kill $(cat passt_in_ns_qemu.pid)
- pane_wait GUEST
- tmux send-keys -t ${PANE_GUEST} "C-d"
-
- tmux send-keys -t ${PANE_PASST} "C-d"
+ context_run ns kill $(cat passt_in_ns_qemu.pid)
+ context_wait qemu
- pane_wait GUEST
- pane_wait NS
- pane_wait PASST
+ ${NSHOLDER} ns.hold stop
+ context_wait pasta
- rm passt.pid
+ rm passt.pid pasta.pid
teardown_context_watch ${PANE_HOST} host
+ teardown_context_watch ${PANE_PASST} pasta passt
+ teardown_context_watch ${PANE_NS} ns
+ teardown_context_watch ${PANE_GUEST} qemu guest
}
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
diff --git a/test/shutdown/passt_in_ns b/test/shutdown/passt_in_ns
index a427bf4..3808adb 100644
--- a/test/shutdown/passt_in_ns
+++ b/test/shutdown/passt_in_ns
@@ -17,6 +17,4 @@ test shutdown: exit code
nsout PASST_PID cat passt.pid
ns kill __PASST_PID__
sleep 1
-
-pout EXIT echo $?
-check [ "__EXIT__" = "0" ]
+passtw
diff --git a/test/tcp/passt_in_ns b/test/tcp/passt_in_ns
index cb01781..a248f00 100644
--- a/test/tcp/passt_in_ns
+++ b/test/tcp/passt_in_ns
@@ -66,6 +66,7 @@ check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to guest (using loopback address): big transfer
guestb socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep 1
ns socat -u OPEN:__TEMP_NS_BIG__ TCP4:127.0.0.1:10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
diff --git a/test/udp/passt_in_ns b/test/udp/passt_in_ns
index f5ea402..d5f08fe 100644
--- a/test/udp/passt_in_ns
+++ b/test/udp/passt_in_ns
@@ -19,6 +19,7 @@ test UDP/IPv4: host to guest
temp TEMP
temp SC_PID
guestb (socat -u UDP4-LISTEN:10001 STDOUT & echo $! > sc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat sc.pid))
+sleep 1
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
guestw
--
@@ -19,6 +19,7 @@ test UDP/IPv4: host to guest
temp TEMP
temp SC_PID
guestb (socat -u UDP4-LISTEN:10001 STDOUT & echo $! > sc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat sc.pid))
+sleep 1
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
guestw
--
2.37.3
^ permalink raw reply related [flat|nested] 12+ messages in thread