From 5bafc240e5ae9c78416663301aa2f14db245f3df Mon Sep 17 00:00:00 2001 From: Tomasz Zawadzki Date: Wed, 25 Apr 2018 12:16:08 -0400 Subject: [PATCH] test/iscsi: utilize network namespaces in iSCSI tests Network namespaces are used to assure that kernel is not routing packets within host stack, but they go through veth interfaces. This patch serves as a base for future VPP test changes, where namespaces are used as well. Change-Id: Ic7b82b0a0837bca2e16774fde244348a691fe056 Signed-off-by: Tomasz Zawadzki Reviewed-on: https://review.gerrithub.io/405641 Reviewed-by: Jim Harris Reviewed-by: Daniel Verkamp Tested-by: SPDK Automated Test System --- test/common/autotest_common.sh | 27 ++++++++++++++----- test/iscsi_tgt/common.sh | 19 +++++++++---- test/iscsi_tgt/initiator/initiator.sh | 2 +- test/iscsi_tgt/ip_migration/ip_migration.sh | 3 +++ .../multiconnection/multiconnection.sh | 2 +- test/iscsi_tgt/nvme_remote/fio_remote_nvme.sh | 11 ++++++-- test/iscsi_tgt/rbd/rbd.sh | 2 +- test/iscsi_tgt/rpc_config/rpc_config.py | 17 ++++++------ test/iscsi_tgt/rpc_config/rpc_config.sh | 2 +- 9 files changed, 60 insertions(+), 25 deletions(-) diff --git a/test/common/autotest_common.sh b/test/common/autotest_common.sh index 106beb556..f8d98f68d 100755 --- a/test/common/autotest_common.sh +++ b/test/common/autotest_common.sh @@ -236,13 +236,19 @@ function waitforlisten() { if ! kill -s 0 $1; then exit 1 fi + + namespace=$(ip netns identify $1) + if [ -n "$namespace" ]; then + ns_cmd="ip netns exec $namespace" + fi + if hash ss; then - if ss -lx | grep -q $rpc_addr; then + if $ns_cmd ss -lx | grep -q $rpc_addr; then ret=0 fi else # if system doesn't have ss, just assume it has netstat - if netstat -an -x | grep -iw LISTENING | grep -q $rpc_addr; then + if $ns_cmd netstat -an -x | grep -iw LISTENING | grep -q $rpc_addr; then ret=0 fi fi @@ -315,20 +321,29 @@ function start_iscsi_service() { function rbd_setup() { # $1 = monitor ip address + # $2 = name of the namespace if [ -z "$1" ]; then echo "No monitor IP address provided for ceph" exit 1 fi + if [ -n "$2" ]; then + if ip netns list | grep "$2"; then + NS_CMD="ip netns exec $2" + else + echo "No namespace $2 exists" + exit 1 + fi + fi if hash ceph; then export PG_NUM=128 export RBD_POOL=rbd export RBD_NAME=foo - $rootdir/scripts/ceph/start.sh $1 + $NS_CMD $rootdir/scripts/ceph/start.sh $1 - ceph osd pool create $RBD_POOL $PG_NUM || true - rbd pool init $RBD_POOL || true - rbd create $RBD_NAME --size 1000 + $NS_CMD ceph osd pool create $RBD_POOL $PG_NUM || true + $NS_CMD rbd pool init $RBD_POOL || true + $NS_CMD rbd create $RBD_NAME --size 1000 fi } diff --git a/test/iscsi_tgt/common.sh b/test/iscsi_tgt/common.sh index fcf10d4d8..30fbb3ee7 100644 --- a/test/iscsi_tgt/common.sh +++ b/test/iscsi_tgt/common.sh @@ -1,19 +1,22 @@ # Network configuration TARGET_INTERFACE="spdk_tgt_int" INITIATOR_INTERFACE="spdk_init_int" +TARGET_NAMESPACE="spdk_iscsi_ns" +TARGET_NS_CMD="ip netns exec $TARGET_NAMESPACE" # iSCSI target configuration TARGET_IP=10.0.0.1 INITIATOR_IP=10.0.0.2 ISCSI_PORT=3260 -NETMASK=$INITIATOR_IP/30 +NETMASK=$INITIATOR_IP/32 INITIATOR_TAG=2 INITIATOR_NAME=ANY PORTAL_TAG=1 -ISCSI_APP="./app/iscsi_tgt/iscsi_tgt -i 0" +ISCSI_APP="$TARGET_NS_CMD ./app/iscsi_tgt/iscsi_tgt -i 0" ISCSI_TEST_CORE_MASK=0xFF function create_veth_interfaces() { + ip netns del $TARGET_NAMESPACE || true ip link delete $INITIATOR_INTERFACE || true # Create veth (Virtual ethernet) interface pair @@ -21,14 +24,20 @@ function create_veth_interfaces() { ip addr add $INITIATOR_IP/24 dev $INITIATOR_INTERFACE ip link set $INITIATOR_INTERFACE up - ip addr add $TARGET_IP/24 dev $TARGET_INTERFACE - ip link set $TARGET_INTERFACE up + # Create and add interface for target to network namespace + ip netns add $TARGET_NAMESPACE + ip link set $TARGET_INTERFACE netns $TARGET_NAMESPACE + + $TARGET_NS_CMD ip link set lo up + $TARGET_NS_CMD ip addr add $TARGET_IP/24 dev $TARGET_INTERFACE + $TARGET_NS_CMD ip link set $TARGET_INTERFACE up trap "cleanup_veth_interfaces; exit 1" SIGINT SIGTERM EXIT } function cleanup_veth_interfaces() { - # Cleanup veth interfaces + # Cleanup veth interfaces and network namespace # Note: removing one veth, removes the pair ip link delete $INITIATOR_INTERFACE + ip netns del $TARGET_NAMESPACE } diff --git a/test/iscsi_tgt/initiator/initiator.sh b/test/iscsi_tgt/initiator/initiator.sh index 040626b30..dbdfde05b 100755 --- a/test/iscsi_tgt/initiator/initiator.sh +++ b/test/iscsi_tgt/initiator/initiator.sh @@ -16,7 +16,7 @@ timing_enter start_iscsi_tgt # Start the iSCSI target without using stub # Reason: Two SPDK processes will be started -$rootdir/app/iscsi_tgt/iscsi_tgt -c $testdir/iscsi.conf -m 0x2 -p 1 -s 512 & +$ISCSI_APP -c $testdir/iscsi.conf -m 0x2 -p 1 -s 512 & pid=$! echo "iSCSI target launched. pid: $pid" trap "killprocess $pid;exit 1" SIGINT SIGTERM EXIT diff --git a/test/iscsi_tgt/ip_migration/ip_migration.sh b/test/iscsi_tgt/ip_migration/ip_migration.sh index 341a26f1c..e9b528214 100755 --- a/test/iscsi_tgt/ip_migration/ip_migration.sh +++ b/test/iscsi_tgt/ip_migration/ip_migration.sh @@ -8,6 +8,9 @@ source $rootdir/test/iscsi_tgt/common.sh rpc_py="python $rootdir/scripts/rpc.py" fio_py="python $rootdir/scripts/fio.py" +# Namespaces are NOT used here on purpose. This test requires changes to detect +# ifc_index for interface that was put into namespace. Needed for add_ip_address. +ISCSI_APP="$rootdir/app/iscsi_tgt/iscsi_tgt" NETMASK=127.0.0.0/24 MIGRATION_ADDRESS=127.0.0.2 diff --git a/test/iscsi_tgt/multiconnection/multiconnection.sh b/test/iscsi_tgt/multiconnection/multiconnection.sh index ab7098ebf..464973039 100755 --- a/test/iscsi_tgt/multiconnection/multiconnection.sh +++ b/test/iscsi_tgt/multiconnection/multiconnection.sh @@ -48,7 +48,7 @@ $rootdir/scripts/gen_nvme.sh >> $testdir/iscsi.conf timing_enter start_iscsi_tgt # Start the iSCSI target without using stub. -$rootdir/app/iscsi_tgt/iscsi_tgt -c $testdir/iscsi.conf & +$ISCSI_APP -c $testdir/iscsi.conf & iscsipid=$! echo "iSCSI target launched. pid: $iscsipid" trap "remove_backends; iscsicleanup; killprocess $iscsipid; exit 1" SIGINT SIGTERM EXIT diff --git a/test/iscsi_tgt/nvme_remote/fio_remote_nvme.sh b/test/iscsi_tgt/nvme_remote/fio_remote_nvme.sh index dcd224de8..1d1e4d0d7 100755 --- a/test/iscsi_tgt/nvme_remote/fio_remote_nvme.sh +++ b/test/iscsi_tgt/nvme_remote/fio_remote_nvme.sh @@ -20,6 +20,11 @@ fio_py="python $rootdir/scripts/fio.py" NVMF_PORT=4420 +# Namespaces are NOT used here on purpose. Rxe_cfg utilility used for NVMf tests do not support namespaces. +TARGET_IP=127.0.0.1 +INITIATOR_IP=127.0.0.1 +NETMASK=$INITIATOR_IP/32 + function run_nvme_remote() { echo "now use $1 method to run iscsi tgt." cp $testdir/iscsi.conf $testdir/iscsi.conf.tmp @@ -30,7 +35,8 @@ function run_nvme_remote() { fi # Start the iSCSI target without using stub iscsi_rpc_addr="/var/tmp/spdk-iscsi.sock" - $rootdir/app/iscsi_tgt/iscsi_tgt -r "$iscsi_rpc_addr" -c $testdir/iscsi.conf.tmp -m 0x1 -p 0 -s 512 & + ISCSI_APP="$rootdir/app/iscsi_tgt/iscsi_tgt" + $ISCSI_APP -r "$iscsi_rpc_addr" -c $testdir/iscsi.conf.tmp -m 0x1 -p 0 -s 512 & iscsipid=$! echo "iSCSI target launched. pid: $iscsipid" trap "killprocess $iscsipid; killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT @@ -56,7 +62,8 @@ function run_nvme_remote() { timing_enter nvme_remote # Start the NVMf target -$rootdir/app/nvmf_tgt/nvmf_tgt -c $rootdir/test/nvmf/nvmf.conf -m 0x2 -p 1 -s 512 & +NVMF_APP="$rootdir/app/nvmf_tgt/nvmf_tgt" +$NVMF_APP -c $rootdir/test/nvmf/nvmf.conf -m 0x2 -p 1 -s 512 & nvmfpid=$! echo "NVMf target launched. pid: $nvmfpid" trap "killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT diff --git a/test/iscsi_tgt/rbd/rbd.sh b/test/iscsi_tgt/rbd/rbd.sh index 1a38f3b40..4abb73e76 100755 --- a/test/iscsi_tgt/rbd/rbd.sh +++ b/test/iscsi_tgt/rbd/rbd.sh @@ -11,7 +11,7 @@ if ! hash ceph; then fi timing_enter rbd_setup -rbd_setup $TARGET_IP +rbd_setup $TARGET_IP $TARGET_NAMESPACE trap "rbd_cleanup; exit 1" SIGINT SIGTERM EXIT timing_exit rbd_setup diff --git a/test/iscsi_tgt/rpc_config/rpc_config.py b/test/iscsi_tgt/rpc_config/rpc_config.py index 41865bed2..404c25b3e 100755 --- a/test/iscsi_tgt/rpc_config/rpc_config.py +++ b/test/iscsi_tgt/rpc_config/rpc_config.py @@ -10,12 +10,14 @@ import json import random from subprocess import check_call, call, check_output, Popen, PIPE, CalledProcessError -if (len(sys.argv) == 6): +if (len(sys.argv) == 7): target_ip = sys.argv[2] initiator_ip = sys.argv[3] port = sys.argv[4] netmask = sys.argv[5] + namespace = sys.argv[6] +ns_cmd = 'ip netns exec ' + namespace other_ip = '127.0.0.6' initiator_name = 'ANY' portal_tag = '1' @@ -402,7 +404,8 @@ def verify_get_interfaces(rpc_py): nics = json.loads(rpc.get_interfaces()) nics_names = set(x["name"].encode('ascii', 'ignore') for x in nics) # parse ip link show to verify the get_interfaces result - ifcfg_nics = set(re.findall("\S+:\s(\S+?)(?:@\S+){0,1}:\s<.*", check_output(["ip", "link", "show"]))) + ip_show = ns_cmd + " ip link show" + ifcfg_nics = set(re.findall("\S+:\s(\S+?)(?:@\S+){0,1}:\s<.*", check_output(ip_show.split()))) verify(nics_names == ifcfg_nics, 1, "get_interfaces returned {}".format(nics)) print "verify_get_interfaces passed." @@ -422,11 +425,12 @@ def verify_add_delete_ip_address(rpc_py): # add ip on up to first 2 nics for x in nics[:2]: faked_ip = "123.123.{}.{}".format(random.randint(1, 254), random.randint(1, 254)) + ping_cmd = ns_cmd + " ping -c 1 -W 1 " + faked_ip rpc.add_ip_address(x["ifc_index"], faked_ip) verify(faked_ip in help_get_interface_ip_list(rpc_py, x["name"]), 1, "add ip {} to nic {} failed.".format(faked_ip, x["name"])) try: - check_call(["ping", "-c", "1", "-W", "1", faked_ip]) + check_call(ping_cmd.split()) except: verify(False, 1, "ping ip {} for {} was failed(adding was successful)".format @@ -437,7 +441,7 @@ def verify_add_delete_ip_address(rpc_py): (faked_ip, x["name"])) # ping should be failed and throw an CalledProcessError exception try: - check_call(["ping", "-c", "1", "-W", "1", faked_ip]) + check_call(ping_cmd.split()) except CalledProcessError as _: pass except Exception as e: @@ -486,10 +490,7 @@ if __name__ == "__main__": verify_initiator_groups_rpc_methods(rpc_py, rpc_param) verify_target_nodes_rpc_methods(rpc_py, rpc_param) verify_scsi_devices_rpc_methods(rpc_py) - # This test is removed due to kernel routing packets in host stack - # when handling connection between interfaces on same host. - # It is enabled back in next patch in series adding namespaces. - # verify_iscsi_connection_rpc_methods(rpc_py) + verify_iscsi_connection_rpc_methods(rpc_py) verify_add_nvme_bdev_rpc_methods(rpc_py) except RpcException as e: print "{}. Exiting with status {}".format(e.message, e.retval) diff --git a/test/iscsi_tgt/rpc_config/rpc_config.sh b/test/iscsi_tgt/rpc_config/rpc_config.sh index 353dce935..0e7048c14 100755 --- a/test/iscsi_tgt/rpc_config/rpc_config.sh +++ b/test/iscsi_tgt/rpc_config/rpc_config.sh @@ -26,7 +26,7 @@ echo "iscsi_tgt is listening. Running tests..." timing_exit start_iscsi_tgt -$rpc_config_py $rpc_py $TARGET_IP $INITIATOR_IP $ISCSI_PORT $NETMASK +$rpc_config_py $rpc_py $TARGET_IP $INITIATOR_IP $ISCSI_PORT $NETMASK $TARGET_NAMESPACE $rpc_py get_bdevs