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 <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/405641
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
Tomasz Zawadzki 2018-04-25 12:16:08 -04:00 committed by Daniel Verkamp
parent adfa9f6dc7
commit 5bafc240e5
9 changed files with 60 additions and 25 deletions

View File

@ -236,13 +236,19 @@ function waitforlisten() {
if ! kill -s 0 $1; then if ! kill -s 0 $1; then
exit 1 exit 1
fi fi
namespace=$(ip netns identify $1)
if [ -n "$namespace" ]; then
ns_cmd="ip netns exec $namespace"
fi
if hash ss; then if hash ss; then
if ss -lx | grep -q $rpc_addr; then if $ns_cmd ss -lx | grep -q $rpc_addr; then
ret=0 ret=0
fi fi
else else
# if system doesn't have ss, just assume it has netstat # 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 ret=0
fi fi
fi fi
@ -315,20 +321,29 @@ function start_iscsi_service() {
function rbd_setup() { function rbd_setup() {
# $1 = monitor ip address # $1 = monitor ip address
# $2 = name of the namespace
if [ -z "$1" ]; then if [ -z "$1" ]; then
echo "No monitor IP address provided for ceph" echo "No monitor IP address provided for ceph"
exit 1 exit 1
fi 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 if hash ceph; then
export PG_NUM=128 export PG_NUM=128
export RBD_POOL=rbd export RBD_POOL=rbd
export RBD_NAME=foo 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 $NS_CMD ceph osd pool create $RBD_POOL $PG_NUM || true
rbd pool init $RBD_POOL || true $NS_CMD rbd pool init $RBD_POOL || true
rbd create $RBD_NAME --size 1000 $NS_CMD rbd create $RBD_NAME --size 1000
fi fi
} }

View File

@ -1,19 +1,22 @@
# Network configuration # Network configuration
TARGET_INTERFACE="spdk_tgt_int" TARGET_INTERFACE="spdk_tgt_int"
INITIATOR_INTERFACE="spdk_init_int" INITIATOR_INTERFACE="spdk_init_int"
TARGET_NAMESPACE="spdk_iscsi_ns"
TARGET_NS_CMD="ip netns exec $TARGET_NAMESPACE"
# iSCSI target configuration # iSCSI target configuration
TARGET_IP=10.0.0.1 TARGET_IP=10.0.0.1
INITIATOR_IP=10.0.0.2 INITIATOR_IP=10.0.0.2
ISCSI_PORT=3260 ISCSI_PORT=3260
NETMASK=$INITIATOR_IP/30 NETMASK=$INITIATOR_IP/32
INITIATOR_TAG=2 INITIATOR_TAG=2
INITIATOR_NAME=ANY INITIATOR_NAME=ANY
PORTAL_TAG=1 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 ISCSI_TEST_CORE_MASK=0xFF
function create_veth_interfaces() { function create_veth_interfaces() {
ip netns del $TARGET_NAMESPACE || true
ip link delete $INITIATOR_INTERFACE || true ip link delete $INITIATOR_INTERFACE || true
# Create veth (Virtual ethernet) interface pair # Create veth (Virtual ethernet) interface pair
@ -21,14 +24,20 @@ function create_veth_interfaces() {
ip addr add $INITIATOR_IP/24 dev $INITIATOR_INTERFACE ip addr add $INITIATOR_IP/24 dev $INITIATOR_INTERFACE
ip link set $INITIATOR_INTERFACE up ip link set $INITIATOR_INTERFACE up
ip addr add $TARGET_IP/24 dev $TARGET_INTERFACE # Create and add interface for target to network namespace
ip link set $TARGET_INTERFACE up 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 trap "cleanup_veth_interfaces; exit 1" SIGINT SIGTERM EXIT
} }
function cleanup_veth_interfaces() { function cleanup_veth_interfaces() {
# Cleanup veth interfaces # Cleanup veth interfaces and network namespace
# Note: removing one veth, removes the pair # Note: removing one veth, removes the pair
ip link delete $INITIATOR_INTERFACE ip link delete $INITIATOR_INTERFACE
ip netns del $TARGET_NAMESPACE
} }

View File

@ -16,7 +16,7 @@ timing_enter start_iscsi_tgt
# Start the iSCSI target without using stub # Start the iSCSI target without using stub
# Reason: Two SPDK processes will be started # 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=$! pid=$!
echo "iSCSI target launched. pid: $pid" echo "iSCSI target launched. pid: $pid"
trap "killprocess $pid;exit 1" SIGINT SIGTERM EXIT trap "killprocess $pid;exit 1" SIGINT SIGTERM EXIT

View File

@ -8,6 +8,9 @@ source $rootdir/test/iscsi_tgt/common.sh
rpc_py="python $rootdir/scripts/rpc.py" rpc_py="python $rootdir/scripts/rpc.py"
fio_py="python $rootdir/scripts/fio.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 NETMASK=127.0.0.0/24
MIGRATION_ADDRESS=127.0.0.2 MIGRATION_ADDRESS=127.0.0.2

View File

@ -48,7 +48,7 @@ $rootdir/scripts/gen_nvme.sh >> $testdir/iscsi.conf
timing_enter start_iscsi_tgt timing_enter start_iscsi_tgt
# Start the iSCSI target without using stub. # Start the iSCSI target without using stub.
$rootdir/app/iscsi_tgt/iscsi_tgt -c $testdir/iscsi.conf & $ISCSI_APP -c $testdir/iscsi.conf &
iscsipid=$! iscsipid=$!
echo "iSCSI target launched. pid: $iscsipid" echo "iSCSI target launched. pid: $iscsipid"
trap "remove_backends; iscsicleanup; killprocess $iscsipid; exit 1" SIGINT SIGTERM EXIT trap "remove_backends; iscsicleanup; killprocess $iscsipid; exit 1" SIGINT SIGTERM EXIT

View File

@ -20,6 +20,11 @@ fio_py="python $rootdir/scripts/fio.py"
NVMF_PORT=4420 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() { function run_nvme_remote() {
echo "now use $1 method to run iscsi tgt." echo "now use $1 method to run iscsi tgt."
cp $testdir/iscsi.conf $testdir/iscsi.conf.tmp cp $testdir/iscsi.conf $testdir/iscsi.conf.tmp
@ -30,7 +35,8 @@ function run_nvme_remote() {
fi fi
# Start the iSCSI target without using stub # Start the iSCSI target without using stub
iscsi_rpc_addr="/var/tmp/spdk-iscsi.sock" 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=$! iscsipid=$!
echo "iSCSI target launched. pid: $iscsipid" echo "iSCSI target launched. pid: $iscsipid"
trap "killprocess $iscsipid; killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT trap "killprocess $iscsipid; killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT
@ -56,7 +62,8 @@ function run_nvme_remote() {
timing_enter nvme_remote timing_enter nvme_remote
# Start the NVMf target # 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=$! nvmfpid=$!
echo "NVMf target launched. pid: $nvmfpid" echo "NVMf target launched. pid: $nvmfpid"
trap "killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT trap "killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT

View File

@ -11,7 +11,7 @@ if ! hash ceph; then
fi fi
timing_enter rbd_setup timing_enter rbd_setup
rbd_setup $TARGET_IP rbd_setup $TARGET_IP $TARGET_NAMESPACE
trap "rbd_cleanup; exit 1" SIGINT SIGTERM EXIT trap "rbd_cleanup; exit 1" SIGINT SIGTERM EXIT
timing_exit rbd_setup timing_exit rbd_setup

View File

@ -10,12 +10,14 @@ import json
import random import random
from subprocess import check_call, call, check_output, Popen, PIPE, CalledProcessError 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] target_ip = sys.argv[2]
initiator_ip = sys.argv[3] initiator_ip = sys.argv[3]
port = sys.argv[4] port = sys.argv[4]
netmask = sys.argv[5] netmask = sys.argv[5]
namespace = sys.argv[6]
ns_cmd = 'ip netns exec ' + namespace
other_ip = '127.0.0.6' other_ip = '127.0.0.6'
initiator_name = 'ANY' initiator_name = 'ANY'
portal_tag = '1' portal_tag = '1'
@ -402,7 +404,8 @@ def verify_get_interfaces(rpc_py):
nics = json.loads(rpc.get_interfaces()) nics = json.loads(rpc.get_interfaces())
nics_names = set(x["name"].encode('ascii', 'ignore') for x in nics) nics_names = set(x["name"].encode('ascii', 'ignore') for x in nics)
# parse ip link show to verify the get_interfaces result # 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)) verify(nics_names == ifcfg_nics, 1, "get_interfaces returned {}".format(nics))
print "verify_get_interfaces passed." 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 # add ip on up to first 2 nics
for x in nics[:2]: for x in nics[:2]:
faked_ip = "123.123.{}.{}".format(random.randint(1, 254), random.randint(1, 254)) 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) rpc.add_ip_address(x["ifc_index"], faked_ip)
verify(faked_ip in help_get_interface_ip_list(rpc_py, x["name"]), 1, verify(faked_ip in help_get_interface_ip_list(rpc_py, x["name"]), 1,
"add ip {} to nic {} failed.".format(faked_ip, x["name"])) "add ip {} to nic {} failed.".format(faked_ip, x["name"]))
try: try:
check_call(["ping", "-c", "1", "-W", "1", faked_ip]) check_call(ping_cmd.split())
except: except:
verify(False, 1, verify(False, 1,
"ping ip {} for {} was failed(adding was successful)".format "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"])) (faked_ip, x["name"]))
# ping should be failed and throw an CalledProcessError exception # ping should be failed and throw an CalledProcessError exception
try: try:
check_call(["ping", "-c", "1", "-W", "1", faked_ip]) check_call(ping_cmd.split())
except CalledProcessError as _: except CalledProcessError as _:
pass pass
except Exception as e: except Exception as e:
@ -486,10 +490,7 @@ if __name__ == "__main__":
verify_initiator_groups_rpc_methods(rpc_py, rpc_param) verify_initiator_groups_rpc_methods(rpc_py, rpc_param)
verify_target_nodes_rpc_methods(rpc_py, rpc_param) verify_target_nodes_rpc_methods(rpc_py, rpc_param)
verify_scsi_devices_rpc_methods(rpc_py) verify_scsi_devices_rpc_methods(rpc_py)
# This test is removed due to kernel routing packets in host stack verify_iscsi_connection_rpc_methods(rpc_py)
# 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_add_nvme_bdev_rpc_methods(rpc_py) verify_add_nvme_bdev_rpc_methods(rpc_py)
except RpcException as e: except RpcException as e:
print "{}. Exiting with status {}".format(e.message, e.retval) print "{}. Exiting with status {}".format(e.message, e.retval)

View File

@ -26,7 +26,7 @@ echo "iscsi_tgt is listening. Running tests..."
timing_exit start_iscsi_tgt 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 $rpc_py get_bdevs