xref: /spdk/test/nvmf/target/multipath.sh (revision dde1b14986139d67f655f9a062c2dab6dfa9b076)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2020 Intel Corporation
4#  All rights reserved.
5#
6testdir=$(readlink -f $(dirname $0))
7rootdir=$(readlink -f $testdir/../../..)
8source $rootdir/test/common/autotest_common.sh
9source $rootdir/test/nvmf/common.sh
10
11MALLOC_BDEV_SIZE=64
12MALLOC_BLOCK_SIZE=512
13nqn=nqn.2016-06.io.spdk:cnode1
14
15rpc_py="$rootdir/scripts/rpc.py"
16
17function check_ana_state() {
18	local path=$1 ana_state=$2
19	# Very rarely a connection is lost and Linux NVMe host tries reconnecting
20	# after 10 seconds delay. For this case, set a sufficiently long timeout.
21	# Linux NVMe host usually recognizes the new ANA state within 2 seconds.
22	local timeout=20
23	local ana_state_f=/sys/block/$path/ana_state
24
25	while [[ ! -e $ana_state_f || $(< "$ana_state_f") != "$ana_state" ]] && sleep 1s; do
26		if ((timeout-- == 0)); then
27			echo "timeout before ANA state ($path) becomes $ana_state"
28			return 1
29		fi
30	done
31}
32
33get_subsystem() {
34	local nqn=$1 serial=$2 s
35
36	for s in /sys/class/nvme-subsystem/*; do
37		[[ $nqn == "$(< "$s/subsysnqn")" && "$serial" == "$(< "$s/serial")" ]] || continue
38		echo "${s##*/}" && return 0
39	done
40	return 1
41}
42
43nvmftestinit
44
45if [ -z $NVMF_SECOND_TARGET_IP ]; then
46	echo "only one NIC for nvmf test"
47	nvmftestfini
48	exit 0
49fi
50
51if [ "$TEST_TRANSPORT" != "tcp" ]; then
52	echo "run this test only with TCP transport for now"
53	nvmftestfini
54	exit 0
55fi
56
57nvmfappstart -m 0xF
58
59$rpc_py nvmf_create_transport $NVMF_TRANSPORT_OPTS -u 8192
60
61$rpc_py bdev_malloc_create $MALLOC_BDEV_SIZE $MALLOC_BLOCK_SIZE -b Malloc0
62$rpc_py nvmf_create_subsystem "$nqn" -a -s "$NVMF_SERIAL" -r
63$rpc_py nvmf_subsystem_add_ns "$nqn" Malloc0
64$rpc_py nvmf_subsystem_add_listener "$nqn" -t $TEST_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
65$rpc_py nvmf_subsystem_add_listener "$nqn" -t $TEST_TRANSPORT -a $NVMF_SECOND_TARGET_IP -s $NVMF_PORT
66
67$NVME_CONNECT "${NVME_HOST[@]}" -t $TEST_TRANSPORT -n "$nqn" -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT" -g -G
68$NVME_CONNECT "${NVME_HOST[@]}" -t $TEST_TRANSPORT -n "$nqn" -a "$NVMF_SECOND_TARGET_IP" -s "$NVMF_PORT" -g -G
69waitforserial "$NVMF_SERIAL"
70
71# Make sure we work with proper subsystem
72subsystem=$(get_subsystem "$nqn" "$NVMF_SERIAL")
73paths=(/sys/class/nvme-subsystem/$subsystem/nvme*/nvme*c*)
74paths=("${paths[@]##*/}")
75
76((${#paths[@]} == 2))
77
78p0=${paths[0]}
79p1=${paths[1]}
80
81check_ana_state "$p0" "optimized"
82check_ana_state "$p1" "optimized"
83
84# Set IO policy to numa
85echo numa > "/sys/class/nvme-subsystem/$subsystem/iopolicy"
86
87$rootdir/scripts/fio-wrapper -p nvmf -i 4096 -d 128 -t randrw -r 6 -v &
88fio_pid=$!
89
90sleep 1
91
92$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT" -n inaccessible
93$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_SECOND_TARGET_IP" -s "$NVMF_PORT" -n non_optimized
94
95check_ana_state "$p0" "inaccessible"
96check_ana_state "$p1" "non-optimized"
97
98$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT" -n non_optimized
99$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_SECOND_TARGET_IP" -s "$NVMF_PORT" -n inaccessible
100
101check_ana_state "$p0" "non-optimized"
102check_ana_state "$p1" "inaccessible"
103
104wait $fio_pid
105
106$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT" -n optimized
107$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_SECOND_TARGET_IP" -s "$NVMF_PORT" -n optimized
108
109check_ana_state "$p0" "optimized"
110check_ana_state "$p1" "optimized"
111
112# Set IO policy to round-robin
113echo round-robin > "/sys/class/nvme-subsystem/$subsystem/iopolicy"
114
115$rootdir/scripts/fio-wrapper -p nvmf -i 4096 -d 128 -t randrw -r 6 -v &
116fio_pid=$!
117
118sleep 1
119
120$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT" -n inaccessible
121$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_SECOND_TARGET_IP" -s "$NVMF_PORT" -n non_optimized
122
123check_ana_state "$p0" "inaccessible"
124check_ana_state "$p1" "non-optimized"
125
126$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT" -n non_optimized
127$rpc_py nvmf_subsystem_listener_set_ana_state "$nqn" -t $TEST_TRANSPORT -a "$NVMF_SECOND_TARGET_IP" -s "$NVMF_PORT" -n inaccessible
128
129check_ana_state "$p0" "non-optimized"
130check_ana_state "$p1" "inaccessible"
131
132wait $fio_pid
133
134nvme disconnect -n "$nqn"
135waitforserial_disconnect "$NVMF_SERIAL"
136
137$rpc_py nvmf_delete_subsystem "$nqn"
138
139rm -f ./local-job0-0-verify.state
140rm -f ./local-job1-1-verify.state
141
142trap - SIGINT SIGTERM EXIT
143
144nvmftestfini
145