numam-spdk/test/nvmf/common.sh
yidong0635 decdfa0b22 test/common: Add bdev_nvme_set_options before "bdev_nvme_attach_controller".
This patch is base on the patch about adding item "keep_alive_timeout_ms".
exposing bdev_nvme_set_options this method that existed but not used.

If we meet the keep alive timeout issue or some intermittent failure, we can
change the keep alive timer from host side. This is also an example to
demonstrate some special items that we can finetune.

Our host app is using json config, which gets config from the target side and
overwrite it .
Exposing this bdev_nvme_set_options that users can quickly change the setting
to fit the real testing environment. Strictly it's not a bug of target, just
make it more compatible.

Signed-off-by: yidong0635 <dongx.yi@intel.com>
Change-Id: Ic1e8a2757dd5ed359500e1692f16e448fab0d4fb
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5333
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
2020-12-09 08:27:06 +00:00

409 lines
10 KiB
Bash

NVMF_PORT=4420
NVMF_SECOND_PORT=4421
NVMF_THIRD_PORT=4422
NVMF_IP_PREFIX="192.168.100"
NVMF_IP_LEAST_ADDR=8
NVMF_TCP_IP_ADDRESS="127.0.0.1"
NVMF_TRANSPORT_OPTS=""
NVMF_SERIAL=SPDK00000000000001
function build_nvmf_app_args() {
if [ $SPDK_RUN_NON_ROOT -eq 1 ]; then
NVMF_APP=(sudo -u "$USER" "${NVMF_APP[@]}")
NVMF_APP+=(-i "$NVMF_APP_SHM_ID" -e 0xFFFF)
else
NVMF_APP+=(-i "$NVMF_APP_SHM_ID" -e 0xFFFF)
fi
}
: ${NVMF_APP_SHM_ID="0"}
export NVMF_APP_SHM_ID
build_nvmf_app_args
have_pci_nics=0
function rxe_cfg() {
"$rootdir/scripts/rxe_cfg_small.sh" "$@"
}
function load_ib_rdma_modules() {
if [ $(uname) != Linux ]; then
return 0
fi
modprobe ib_cm
modprobe ib_core
# Newer kernels do not have the ib_ucm module
modprobe ib_ucm || true
modprobe ib_umad
modprobe ib_uverbs
modprobe iw_cm
modprobe rdma_cm
modprobe rdma_ucm
}
function detect_soft_roce_nics() {
rxe_cfg stop # make sure we run tests with a clean slate
rxe_cfg start
}
# args 1 and 2 represent the grep filters for finding our NICS.
# subsequent args are all drivers that should be loaded if we find these NICs.
# Those drivers should be supplied in the correct order.
function detect_nics_and_probe_drivers() {
NIC_VENDOR="$1"
NIC_CLASS="$2"
nvmf_nic_bdfs=$(lspci | grep Ethernet | grep "$NIC_VENDOR" | grep "$NIC_CLASS" | awk -F ' ' '{print "0000:"$1}')
if [ -z "$nvmf_nic_bdfs" ]; then
return 0
fi
have_pci_nics=1
if [ $# -ge 2 ]; then
# shift out the first two positional arguments.
shift 2
# Iterate through the remaining arguments.
for i; do
modprobe "$i"
done
fi
}
function detect_pci_nics() {
if ! hash lspci; then
return 0
fi
detect_nics_and_probe_drivers "Mellanox" "ConnectX-4" "mlx4_core" "mlx4_ib" "mlx4_en"
detect_nics_and_probe_drivers "Mellanox" "ConnectX-5" "mlx5_core" "mlx5_ib"
detect_nics_and_probe_drivers "Intel" "X722" "i40e" "i40iw"
detect_nics_and_probe_drivers "Chelsio" "Unified Wire" "cxgb4" "iw_cxgb4"
if [ "$have_pci_nics" -eq "0" ]; then
return 0
fi
# Provide time for drivers to properly load.
sleep 5
}
function detect_rdma_nics() {
detect_pci_nics
if [ "$have_pci_nics" -eq "0" ]; then
detect_soft_roce_nics
fi
}
function allocate_nic_ips() {
((count = NVMF_IP_LEAST_ADDR))
for nic_name in $(get_rdma_if_list); do
ip="$(get_ip_address $nic_name)"
if [[ -z $ip ]]; then
ip addr add $NVMF_IP_PREFIX.$count/24 dev $nic_name
ip link set $nic_name up
((count = count + 1))
fi
# dump configuration for debug log
ip addr show $nic_name
done
}
function get_available_rdma_ips() {
for nic_name in $(get_rdma_if_list); do
get_ip_address $nic_name
done
}
function get_rdma_if_list() {
for nic_type in /sys/class/infiniband/*; do
[[ -e "$nic_type" ]] || break
for nic_name in /sys/class/infiniband/"$(basename ${nic_type})"/device/net/*; do
[[ -e "$nic_name" ]] || break
basename "$nic_name"
done
done
}
function get_ip_address() {
interface=$1
ip -o -4 addr show $interface | awk '{print $4}' | cut -d"/" -f1
}
function nvmfcleanup() {
sync
set +e
for i in {1..20}; do
modprobe -v -r nvme-$TEST_TRANSPORT
if modprobe -v -r nvme-fabrics; then
set -e
return 0
fi
sleep 1
done
set -e
# So far unable to remove the kernel modules. Try
# one more time and let it fail.
# Allow the transport module to fail for now. See Jim's comment
# about the nvme-tcp module below.
modprobe -v -r nvme-$TEST_TRANSPORT || true
modprobe -v -r nvme-fabrics
}
function nvmf_veth_init() {
NVMF_INITIATOR_IP=10.0.0.1
NVMF_FIRST_TARGET_IP=10.0.0.2
NVMF_SECOND_TARGET_IP=10.0.0.3
NVMF_BRIDGE="nvmf_br"
NVMF_INITIATOR_INTERFACE="nvmf_init_if"
NVMF_INITIATOR_BRIDGE="nvmf_init_br"
NVMF_TARGET_NAMESPACE="nvmf_tgt_ns"
NVMF_TARGET_NS_CMD=(ip netns exec "$NVMF_TARGET_NAMESPACE")
NVMF_TARGET_INTERFACE="nvmf_tgt_if"
NVMF_TARGET_INTERFACE2="nvmf_tgt_if2"
NVMF_TARGET_BRIDGE="nvmf_tgt_br"
NVMF_TARGET_BRIDGE2="nvmf_tgt_br2"
ip link set $NVMF_INITIATOR_BRIDGE nomaster || true
ip link set $NVMF_TARGET_BRIDGE nomaster || true
ip link set $NVMF_TARGET_BRIDGE2 nomaster || true
ip link set $NVMF_INITIATOR_BRIDGE down || true
ip link set $NVMF_TARGET_BRIDGE down || true
ip link set $NVMF_TARGET_BRIDGE2 down || true
ip link delete $NVMF_BRIDGE type bridge || true
ip link delete $NVMF_INITIATOR_INTERFACE || true
"${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE || true
"${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE2 || true
ip netns del $NVMF_TARGET_NAMESPACE || true
trap 'nvmf_veth_fini; exit 1' SIGINT SIGTERM EXIT
# Create network namespace
ip netns add $NVMF_TARGET_NAMESPACE
# Create veth (Virtual ethernet) interface pairs
ip link add $NVMF_INITIATOR_INTERFACE type veth peer name $NVMF_INITIATOR_BRIDGE
ip link add $NVMF_TARGET_INTERFACE type veth peer name $NVMF_TARGET_BRIDGE
ip link add $NVMF_TARGET_INTERFACE2 type veth peer name $NVMF_TARGET_BRIDGE2
# Associate veth interface pairs with network namespace
ip link set $NVMF_TARGET_INTERFACE netns $NVMF_TARGET_NAMESPACE
ip link set $NVMF_TARGET_INTERFACE2 netns $NVMF_TARGET_NAMESPACE
# Allocate IP addresses
ip addr add $NVMF_INITIATOR_IP/24 dev $NVMF_INITIATOR_INTERFACE
"${NVMF_TARGET_NS_CMD[@]}" ip addr add $NVMF_FIRST_TARGET_IP/24 dev $NVMF_TARGET_INTERFACE
"${NVMF_TARGET_NS_CMD[@]}" ip addr add $NVMF_SECOND_TARGET_IP/24 dev $NVMF_TARGET_INTERFACE2
# Link up veth interfaces
ip link set $NVMF_INITIATOR_INTERFACE up
ip link set $NVMF_INITIATOR_BRIDGE up
ip link set $NVMF_TARGET_BRIDGE up
ip link set $NVMF_TARGET_BRIDGE2 up
"${NVMF_TARGET_NS_CMD[@]}" ip link set $NVMF_TARGET_INTERFACE up
"${NVMF_TARGET_NS_CMD[@]}" ip link set $NVMF_TARGET_INTERFACE2 up
"${NVMF_TARGET_NS_CMD[@]}" ip link set lo up
# Create a bridge
ip link add $NVMF_BRIDGE type bridge
ip link set $NVMF_BRIDGE up
# Add veth interfaces to the bridge
ip link set $NVMF_INITIATOR_BRIDGE master $NVMF_BRIDGE
ip link set $NVMF_TARGET_BRIDGE master $NVMF_BRIDGE
ip link set $NVMF_TARGET_BRIDGE2 master $NVMF_BRIDGE
# Accept connections from veth interface
iptables -I INPUT 1 -i $NVMF_INITIATOR_INTERFACE -p tcp --dport $NVMF_PORT -j ACCEPT
# Verify connectivity
ping -c 1 $NVMF_FIRST_TARGET_IP
ping -c 1 $NVMF_SECOND_TARGET_IP
"${NVMF_TARGET_NS_CMD[@]}" ping -c 1 $NVMF_INITIATOR_IP
NVMF_APP=("${NVMF_TARGET_NS_CMD[@]}" "${NVMF_APP[@]}")
}
function nvmf_veth_fini() {
# Cleanup bridge, veth interfaces, and network namespace
# Note: removing one veth removes the pair
ip link set $NVMF_INITIATOR_BRIDGE nomaster
ip link set $NVMF_TARGET_BRIDGE nomaster
ip link set $NVMF_TARGET_BRIDGE2 nomaster
ip link set $NVMF_INITIATOR_BRIDGE down
ip link set $NVMF_TARGET_BRIDGE down
ip link set $NVMF_TARGET_BRIDGE2 down
ip link delete $NVMF_BRIDGE type bridge
ip link delete $NVMF_INITIATOR_INTERFACE
"${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE
"${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE2
ip netns del $NVMF_TARGET_NAMESPACE
}
function nvmftestinit() {
if [ -z $TEST_TRANSPORT ]; then
echo "transport not specified - use --transport= to specify"
return 1
fi
if [ "$TEST_MODE" == "iso" ]; then
$rootdir/scripts/setup.sh
if [ "$TEST_TRANSPORT" == "rdma" ]; then
rdma_device_init
fi
fi
NVMF_TRANSPORT_OPTS="-t $TEST_TRANSPORT"
if [ "$TEST_TRANSPORT" == "rdma" ]; then
RDMA_IP_LIST=$(get_available_rdma_ips)
NVMF_FIRST_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1)
NVMF_SECOND_TARGET_IP=$(echo "$RDMA_IP_LIST" | tail -n +2 | head -n 1)
if [ -z $NVMF_FIRST_TARGET_IP ]; then
echo "no NIC for nvmf test"
exit 0
fi
elif [ "$TEST_TRANSPORT" == "tcp" ]; then
nvmf_veth_init
NVMF_TRANSPORT_OPTS="$NVMF_TRANSPORT_OPTS -o"
fi
# currently we run the host/perf test for TCP even on systems without kernel nvme-tcp
# support; that's fine since the host/perf test uses the SPDK initiator
# maybe later we will enforce modprobe to succeed once we have systems in the test pool
# with nvme-tcp kernel support - but until then let this pass so we can still run the
# host/perf test with the tcp transport
modprobe nvme-$TEST_TRANSPORT || true
}
function nvmfappstart() {
timing_enter start_nvmf_tgt
"${NVMF_APP[@]}" "$@" &
nvmfpid=$!
trap 'process_shm --id $NVMF_APP_SHM_ID; nvmftestfini; exit 1' SIGINT SIGTERM EXIT
waitforlisten $nvmfpid
timing_exit start_nvmf_tgt
}
function nvmftestfini() {
nvmfcleanup || :
if [ -n "$nvmfpid" ]; then
killprocess $nvmfpid
fi
if [ "$TEST_MODE" == "iso" ]; then
$rootdir/scripts/setup.sh reset
if [ "$TEST_TRANSPORT" == "rdma" ]; then
rdma_device_init
elif [ "$TEST_TRANSPORT" == "tcp" ]; then
nvmf_veth_fini
fi
fi
}
function rdma_device_init() {
load_ib_rdma_modules
detect_rdma_nics
allocate_nic_ips
}
function revert_soft_roce() {
rxe_cfg stop
}
function check_ip_is_soft_roce() {
if [ "$TEST_TRANSPORT" != "rdma" ]; then
return 0
fi
rxe_cfg status rxe | grep -wq "$1"
}
function nvme_connect() {
local init_count
init_count=$(nvme list | wc -l)
if ! nvme connect "$@"; then return $?; fi
for i in $(seq 1 10); do
if [ $(nvme list | wc -l) -gt $init_count ]; then
return 0
else
sleep 1s
fi
done
return 1
}
function get_nvme_devs() {
local dev rest
nvmes=()
while read -r dev rest; do
if [[ $dev == /dev/nvme* ]]; then
nvmes+=("$dev")
fi
if [[ $1 == print ]]; then
echo "$dev $rest"
fi
done < <(nvme list)
((${#nvmes[@]})) || return 1
echo "${#nvmes[@]}" >&2
}
function gen_nvmf_target_json() {
local subsystem config=()
for subsystem in "${@:-1}"; do
config+=(
"$(
cat <<- EOF
{
"params": {
"name": "Nvme$subsystem",
"trtype": "$TEST_TRANSPORT",
"traddr": "$NVMF_FIRST_TARGET_IP",
"adrfam": "ipv4",
"trsvcid": "$NVMF_PORT",
"subnqn": "nqn.2016-06.io.spdk:cnode$subsystem",
"hostnqn": "nqn.2016-06.io.spdk:host$subsystem"
},
"method": "bdev_nvme_attach_controller"
}
EOF
)"
)
done
jq . <<- JSON
{
"subsystems": [
{
"subsystem": "bdev",
"config": [
{
"method": "bdev_nvme_set_options",
"params": {
"action_on_timeout": "none",
"timeout_us": 0,
"retry_count": 4,
"arbitration_burst": 0,
"low_priority_weight": 0,
"medium_priority_weight": 0,
"high_priority_weight": 0,
"nvme_adminq_poll_period_us": 10000,
"keep_alive_timeout_ms" : 10000,
"nvme_ioq_poll_period_us": 0,
"io_queue_requests": 0,
"delay_cmd_submit": true
}
},
$(
IFS=","
printf '%s\n' "${config[*]}"
)
]
}
]
}
JSON
}