diff --git a/.github/workflows/integration-tdx.yml b/.github/workflows/integration-tdx.yml index 1bb9645b..73a6a566 100644 --- a/.github/workflows/integration-tdx.yml +++ b/.github/workflows/integration-tdx.yml @@ -47,13 +47,19 @@ jobs: - name: Build Migration TD binary run: cargo image --policy config/policy_pre_production_fmspc.json --root-ca config/Intel_SGX_Provisioning_Certification_RootCA_preproduction.cer - + - name: Run Tests - Test Migration TD 20 Cycles run: | pushd sh_script/test sudo pytest -k "cycle" popd + - name: Run Tests - Test pre-binding + run: | + pushd sh_script/test + sudo pytest -k "pre_binding" --servtd_hash $(cargo hash --image $GITHUB_WORKSPACE/target/release/migtd.bin) + popd + - name: Build all test binaries run: bash sh_script/build_final.sh -t test -c -a on @@ -82,13 +88,19 @@ jobs: - name: Build Migration TD binary run: cargo image --no-default-features --features remote-attestation,stack-guard,virtio-serial --policy config/policy_pre_production_fmspc.json --root-ca config/Intel_SGX_Provisioning_Certification_RootCA_preproduction.cer - + - name: Run Tests - Test Migration TD 20 Cycles run: | pushd sh_script/test sudo pytest -k "cycle" --device_type serial popd + - name: Run Tests - Test pre-binding + run: | + pushd sh_script/test + sudo pytest -k "pre_binding" --device_type serial --servtd_hash $(cargo hash --image $GITHUB_WORKSPACE/target/release/migtd.bin) + popd + - name: Build all test binaries run: bash sh_script/build_final.sh -t test -c -a on -d serial diff --git a/sh_script/build_final.sh b/sh_script/build_final.sh index c5ebc84c..65753af0 100644 --- a/sh_script/build_final.sh +++ b/sh_script/build_final.sh @@ -217,20 +217,20 @@ function final_test_migtd() { build_migtd build_tdshim strip_info - link "migtd" "migtd.bin" - enroll "migtd.bin" "policy_no.json" "migtd_no.bin" + link "migtd" "migtd_test.bin" + enroll "migtd_test.bin" "policy_no.json" "migtd_no.bin" echo "-- Build final binary for test case 007 of migration TD" # Different policy file and check "Digest.MigTdPolicy" - enroll "migtd.bin" "policy_003.json" "migtd_007.bin" + enroll "migtd_test.bin" "policy_003.json" "migtd_007.bin" echo "-- Build final binary for test case 008 of migration TD" # Invalid json - enroll "migtd.bin" "policy_005.json" "migtd_008.bin" + enroll "migtd_test.bin" "policy_005.json" "migtd_008.bin" echo "-- Build final binary for test case 009 of migration TD" # Test without vsock deveice init - enroll "migtd.bin" "policy_no.json" "migtd_009.bin" + enroll "migtd_test.bin" "policy_no.json" "migtd_009.bin" } function final_migtd() { diff --git a/sh_script/test/conftest.py b/sh_script/test/conftest.py index ba4c459b..b01cc4f8 100644 --- a/sh_script/test/conftest.py +++ b/sh_script/test/conftest.py @@ -18,11 +18,16 @@ def pytest_addoption(parser): parser.addoption("--device_type", action="store", default="vsock", help="Device type vsock/serial") + parser.addoption("--servtd_hash", action="store", default="", help="SERVTD_INFO_HASH of MigTD image") @pytest.fixture() def device_type(request): return request.config.getoption("--device_type") +@pytest.fixture() +def servtd_hash(request): + return request.config.getoption("--servtd_hash") + @contextmanager def migtd_context(): """ @@ -43,6 +48,7 @@ class MigtdTest: def __init__(self): # variable from the config file self.qemu: str = None + self.migtd_hash_script: str = None self.mig_td_script: str = None self.user_td_script: str = None self.connect_script: str = None @@ -150,14 +156,16 @@ def start_mig_td(self, bios_img=None, type=None, no_device=False, device=None): time.sleep(1) # type has src dst - def start_user_td(self, type=None): + def start_user_td(self, is_pre_binding=False, type=None, hash=None): + command = f"sudo bash {self.user_td_script} -q {self.qemu} -i {self.guest_img} -k {self.kernel_img} -o {self.user_td_bios_img} -t {type}" + if is_pre_binding: + command += f" -g true -m {hash}" """ Start user td """ thread_usertd = threading.Thread( target=self._exec_shell_cmd, - args=(f"sudo bash {self.user_td_script} -q {self.qemu} -i {self.guest_img} -k {self.kernel_img} -o {self.user_td_bios_img} -t {type}", - f"user_td_{type}") + args=(command, f"user_td_{type}") ) LOG.debug(f"Starting {type} user td") @@ -180,12 +188,15 @@ def connect(self): self._threads["connect"] = thread_connect time.sleep(5) - def pre_migration(self): + def pre_migration(self, is_pre_binding=False): """ Execute pre migration """ LOG.debug(f"Start pre migration") - self._exec_shell_cmd(f"sudo bash {self.pre_mig_script}") + command = f"sudo bash {self.pre_mig_script}" + if is_pre_binding: + command += " -p true" + self._exec_shell_cmd(command) def check_migration_result(self, negative=False, wait_time=2): """ diff --git a/sh_script/test/integration_test.py b/sh_script/test/integration_test.py index c0b0d203..24b7611c 100644 --- a/sh_script/test/integration_test.py +++ b/sh_script/test/integration_test.py @@ -393,6 +393,25 @@ def test_function_000(device_type): ctx.start_test_payload(bios_img=test_bin, type="src", device=device_type) ctx.terminate_all_tds() +def test_pre_binding(device_type, servtd_hash): + migtd_src = "../../target/release/migtd.bin" + migtd_dst = "../../target/release/migtd.bin" + + with migtd_context() as ctx: + ctx.start_user_td(type="src", is_pre_binding=True, hash=servtd_hash) + ctx.start_user_td(type="dst", is_pre_binding=True, hash=servtd_hash) + ctx.start_mig_td(bios_img=migtd_src, type="src", device=device_type) + ctx.start_mig_td(bios_img=migtd_dst, type="dst", device=device_type) + ctx.connect() + + ctx.pre_migration(is_pre_binding=True) + ctx.check_migration_result() + ctx.terminate_user_td(type="src") + ctx.terminate_user_td(type="dst") + + ctx.terminate_mig_td() + ctx.terminate_socat() + def test_cycle(device_type): migtd_src = "../../target/release/migtd.bin" migtd_dst = "../../target/release/migtd.bin" diff --git a/sh_script/test/pre-mig.sh b/sh_script/test/pre-mig.sh index be64d6fd..3ab902f9 100644 --- a/sh_script/test/pre-mig.sh +++ b/sh_script/test/pre-mig.sh @@ -8,21 +8,24 @@ set -e TYPE="local" DEST_IP="" +PRE_BINDING="false" usage() { cat << EOM Usage: $(basename "$0") [OPTION]... -i Destination platform ip address -t Use single or cross host live migration + -p [true|false] Use pre-binding or not, default value is false -h Show this help EOM } process_args() { - while getopts "i:t:h" option; do + while getopts "i:t:p:h" option; do case "${option}" in i) DEST_IP=$OPTARG;; t) TYPE=$OPTARG;; + p) PRE_BINDING=$OPTARG;; h) usage exit 0 ;; @@ -53,15 +56,23 @@ error() { } pre_mig(){ + DST_COMMAND="echo qom-set /objects/tdx0/ vsockport 1235 | nc -U /tmp/qmp-sock-dst" + SRC_COMMAND="echo qom-set /objects/tdx0/ vsockport 1234 | nc -U /tmp/qmp-sock-src" + + if [[ ${PRE_BINDING} == "true" ]]; then + DST_COMMAND="echo qom-set /objects/tdx0/ migtd-pid $(pgrep migtd-dst) | nc -U /tmp/qmp-sock-dst && "${DST_COMMAND} + SRC_COMMAND="echo qom-set /objects/tdx0/ migtd-pid $(pgrep migtd-src) | nc -U /tmp/qmp-sock-src && "${SRC_COMMAND} + fi + # Asking migtd-dst to connect to the dst socat if [[ ${TYPE} == "local" ]]; then - echo "qom-set /objects/tdx0/ vsockport 1235" | nc -U /tmp/qmp-sock-dst + eval ${DST_COMMAND} else - ssh root@"${DEST_IP}" -o ConnectTimeout=30 "echo qom-set /objects/tdx0/ vsockport 1235 | nc -U /tmp/qmp-sock-dst" + ssh root@"${DEST_IP}" -o ConnectTimeout=30 "${DST_COMMAND}" fi # Asking migtd-dst to connect to the src socat - echo "qom-set /objects/tdx0/ vsockport 1234" | nc -U /tmp/qmp-sock-src + eval ${SRC_COMMAND} } process_args "$@" diff --git a/sh_script/test/user-td.sh b/sh_script/test/user-td.sh index 99fe3e99..fb142f0d 100644 --- a/sh_script/test/user-td.sh +++ b/sh_script/test/user-td.sh @@ -18,6 +18,8 @@ QUOTE_TYPE="" GUEST_CID=3 TELNET_PORT=9088 INCOMING_PORT=6666 +PRE_BINDING="false" +SERVTD_HASH="" usage() { @@ -32,12 +34,14 @@ Usage: $(basename "$0") [OPTION]... -q [tdvmcall|vsock] Support for TD quote using tdvmcall or vsock -r root partition for direct boot, default is /dev/vda1 -t Must set userTD type, src or dst + -g [true|false] Use pre-binding or not, default is "false" + -m [MigTD hash] Hash of MigTD SERVTD_INFO_HASH, shall be provided if "-g" is true -h Show this help EOM } process_args() { - while getopts "i:k:b:o:p:q:r:t:h" option; do + while getopts "i:k:b:o:p:q:r:t:g:m:h" option; do case "${option}" in i) GUEST_IMG=$OPTARG;; k) KERNEL=$OPTARG;; @@ -48,6 +52,8 @@ process_args() { a) QUOTE_TYPE=$OPTARG;; r) ROOT_PARTITION=$OPTARG;; t) TD_TYPE=$OPTARG;; + g) PRE_BINDING=$OPTARG;; + m) SERVTD_HASH=$OPTARG;; h) usage exit 0 ;; @@ -68,12 +74,16 @@ process_args() { "src") GUEST_CID=3 TELNET_PORT=9088 - TARGET_PID=$(pgrep migtd-src) + if [[ ${PRE_BINDING} != "true" ]]; then + TARGET_PID=$(pgrep migtd-src) + fi ;; "dst") GUEST_CID=4 TELNET_PORT=9089 - TARGET_PID=$(pgrep migtd-dst) + if [[ ${PRE_BINDING} != "true" ]]; then + TARGET_PID=$(pgrep migtd-dst) + fi ;; *) error "Invalid ${TD_TYPE}, must be [src|dst]" @@ -142,16 +152,24 @@ QEMU_CMD="${QEMU_EXEC} \ -monitor telnet:127.0.0.1:${TELNET_PORT},server,nowait \ -device virtio-serial,romfile= \ -device virtconsole,chardev=mux -serial chardev:mux -monitor chardev:mux" +OBJ_SUBCOMMAND=" -object tdx-guest,id=tdx0,sept-ve-disable=on,debug=off" + + if [[ ${PRE_BINDING} == "true" ]]; then + OBJ_SUBCOMMAND+=",migtd-hash=${SERVTD_HASH},migtd-attr=0x0000000000000001" + else + OBJ_SUBCOMMAND+=",migtd-pid=${TARGET_PID}" + fi if [[ -n ${QUOTE_TYPE} ]]; then if [[ ${QUOTE_TYPE} == "tdvmcall" ]]; then - QEMU_CMD+=" -object tdx-guest,id=tdx0,sept-ve-disable=on,debug=off,migtd-pid=${TARGET_PID},quote-generation-service=vsock:2:4050" + OBJ_SUBCOMMAND+=",quote-generation-service=vsock:2:4050" + QEMU_CMD+=${OBJ_SUBCOMMAND} else - QEMU_CMD+=" -object tdx-guest,id=tdx0,sept-ve-disable=on,debug=off,migtd-pid=${TARGET_PID}" + QEMU_CMD+=${OBJ_SUBCOMMAND} QEMU_CMD+=" -device vhost-vsock-pci,guest-cid=${GUEST_CID}" fi else - QEMU_CMD+=" -object tdx-guest,id=tdx0,sept-ve-disable=on,debug=off,migtd-pid=${TARGET_PID}" + QEMU_CMD+=${OBJ_SUBCOMMAND} fi if [[ ${BOOT_TYPE} == "direct" ]]; then