1NVMF_PORT=4420 2NVMF_SECOND_PORT=4421 3NVMF_THIRD_PORT=4422 4NVMF_IP_PREFIX="192.168.100" 5NVMF_IP_LEAST_ADDR=8 6NVMF_TCP_IP_ADDRESS="127.0.0.1" 7NVMF_TRANSPORT_OPTS="" 8NVMF_SERIAL=SPDK00000000000001 9 10function build_nvmf_app_args() { 11 if [ $SPDK_RUN_NON_ROOT -eq 1 ]; then 12 # We assume that test script is started from sudo 13 NVMF_APP=(sudo -E -u $SUDO_USER "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" "${NVMF_APP[@]}") 14 fi 15 NVMF_APP+=(-i "$NVMF_APP_SHM_ID" -e 0xFFFF) 16 17 if [ -n "$SPDK_HUGE_DIR" ]; then 18 NVMF_APP+=(--huge-dir "$SPDK_HUGE_DIR") 19 elif [ $SPDK_RUN_NON_ROOT -eq 1 ]; then 20 echo "In non-root test mode you have to set SPDK_HUGE_DIR variable." >&2 21 echo "For example:" >&2 22 echo "sudo mkdir /mnt/spdk_hugetlbfs" >&2 23 echo "sudo chown ${SUDO_USER}: /mnt/spdk_hugetlbfs" >&2 24 echo "export SPDK_HUGE_DIR=/mnt/spdk_hugetlbfs" >&2 25 return 1 26 fi 27} 28 29: ${NVMF_APP_SHM_ID="0"} 30export NVMF_APP_SHM_ID 31build_nvmf_app_args 32 33have_pci_nics=0 34 35function rxe_cfg() { 36 "$rootdir/scripts/rxe_cfg_small.sh" "$@" 37} 38 39function load_ib_rdma_modules() { 40 if [ $(uname) != Linux ]; then 41 return 0 42 fi 43 44 modprobe ib_cm 45 modprobe ib_core 46 # Newer kernels do not have the ib_ucm module 47 modprobe ib_ucm || true 48 modprobe ib_umad 49 modprobe ib_uverbs 50 modprobe iw_cm 51 modprobe rdma_cm 52 modprobe rdma_ucm 53} 54 55function detect_soft_roce_nics() { 56 rxe_cfg stop # make sure we run tests with a clean slate 57 rxe_cfg start 58} 59 60# args 1 and 2 represent the grep filters for finding our NICS. 61# subsequent args are all drivers that should be loaded if we find these NICs. 62# Those drivers should be supplied in the correct order. 63function detect_nics_and_probe_drivers() { 64 NIC_VENDOR="$1" 65 NIC_CLASS="$2" 66 67 nvmf_nic_bdfs=$(lspci | grep Ethernet | grep "$NIC_VENDOR" | grep "$NIC_CLASS" | awk -F ' ' '{print "0000:"$1}') 68 69 if [ -z "$nvmf_nic_bdfs" ]; then 70 return 0 71 fi 72 73 have_pci_nics=1 74 if [ $# -ge 2 ]; then 75 # shift out the first two positional arguments. 76 shift 2 77 # Iterate through the remaining arguments. 78 for i; do 79 if [[ $i == irdma ]]; then 80 # Our tests don't play well with iWARP protocol. Make sure we use RoCEv2 instead. 81 if [[ -e /sys/module/irdma/parameters/roce_ena ]]; then 82 # reload the module to re-init the rdma devices 83 (($(< /sys/module/irdma/parameters/roce_ena) != 1)) && modprobe -r irdma 84 fi 85 modprobe "$i" roce_ena=1 86 else 87 modprobe "$i" 88 fi 89 done 90 fi 91} 92 93function pci_rdma_switch() { 94 local driver=$1 95 96 local -a driver_args=() 97 driver_args+=("Mellanox ConnectX-4 mlx5_core mlx5_ib") 98 driver_args+=("Mellanox ConnectX-5 mlx5_core mlx5_ib") 99 driver_args+=("Intel E810 ice irdma") 100 driver_args+=("Intel X722 i40e i40iw") 101 driver_args+=("Chelsio \"Unified Wire\" cxgb4 iw_cxgb4") 102 103 case $driver in 104 mlx5_ib) 105 detect_nics_and_probe_drivers ${driver_args[0]} 106 detect_nics_and_probe_drivers ${driver_args[1]} 107 ;; 108 irdma) 109 detect_nics_and_probe_drivers ${driver_args[2]} 110 ;; 111 i40iw) 112 detect_nics_and_probe_drivers ${driver_args[3]} 113 ;; 114 iw_cxgb4) 115 detect_nics_and_probe_drivers ${driver_args[4]} 116 ;; 117 *) 118 for d in "${driver_args[@]}"; do 119 detect_nics_and_probe_drivers $d 120 done 121 ;; 122 esac 123} 124 125function pci_tcp_switch() { 126 local driver=$1 127 128 local -a driver_args=() 129 driver_args+=("Intel E810 ice") 130 131 case $driver in 132 ice) 133 detect_nics_and_probe_drivers ${driver_args[0]} 134 ;; 135 *) 136 for d in "${driver_args[@]}"; do 137 detect_nics_and_probe_drivers $d 138 done 139 ;; 140 esac 141} 142 143function detect_pci_nics() { 144 145 if ! hash lspci; then 146 return 0 147 fi 148 149 local nic_drivers 150 local found_drivers 151 152 if [[ -z "$TEST_TRANSPORT" ]]; then 153 TEST_TRANSPORT=$SPDK_TEST_NVMF_TRANSPORT 154 fi 155 156 if [[ "$TEST_TRANSPORT" == "rdma" ]]; then 157 nic_drivers="mlx5_ib|irdma|i40iw|iw_cxgb4" 158 159 # Try to find RDMA drivers which are already loded and try to 160 # use only it's associated NICs, without probing all drivers. 161 found_drivers=$(lsmod | grep -Eo $nic_drivers | sort -u) 162 for d in $found_drivers; do 163 pci_rdma_switch $d 164 done 165 166 # In case lsmod reported driver, but lspci does not report 167 # physical NICs - fall back to old approach any try to 168 # probe all compatible NICs. 169 ((have_pci_nics == 0)) && pci_rdma_switch "default" 170 171 elif [[ "$TEST_TRANSPORT" == "tcp" ]]; then 172 nic_drivers="ice" 173 found_drivers=$(lsmod | grep -Eo $nic_drivers | sort -u) 174 for d in $found_drivers; do 175 pci_tcp_switch $d 176 done 177 ((have_pci_nics == 0)) && pci_tcp_switch "default" 178 fi 179 180 # Use softroce if everything else failed. 181 ((have_pci_nics == 0)) && return 0 182 183 # Provide time for drivers to properly load. 184 sleep 5 185} 186 187function detect_transport_nics() { 188 detect_pci_nics 189 if [ "$have_pci_nics" -eq "0" ]; then 190 detect_soft_roce_nics 191 fi 192} 193 194function allocate_nic_ips() { 195 ((count = NVMF_IP_LEAST_ADDR)) 196 for nic_name in $(get_rdma_if_list); do 197 ip="$(get_ip_address $nic_name)" 198 if [[ -z $ip ]]; then 199 ip addr add $NVMF_IP_PREFIX.$count/24 dev $nic_name 200 ip link set $nic_name up 201 ((count = count + 1)) 202 fi 203 # dump configuration for debug log 204 ip addr show $nic_name 205 done 206} 207 208function get_available_rdma_ips() { 209 for nic_name in $(get_rdma_if_list); do 210 get_ip_address $nic_name 211 done 212} 213 214function get_rdma_if_list() { 215 rxe_cfg rxe-net 216} 217 218function get_tcp_if_list_by_driver() { 219 local driver 220 driver=${1:-ice} 221 222 shopt -s nullglob 223 tcp_if_list=(/sys/bus/pci/drivers/$driver/0000*/net/*) 224 shopt -u nullglob 225 printf '%s\n' "${tcp_if_list[@]##*/}" 226} 227 228function get_ip_address() { 229 interface=$1 230 ip -o -4 addr show $interface | awk '{print $4}' | cut -d"/" -f1 231} 232 233function nvmfcleanup() { 234 sync 235 236 if [ "$TEST_TRANSPORT" == "tcp" ] || [ "$TEST_TRANSPORT" == "rdma" ]; then 237 set +e 238 for i in {1..20}; do 239 modprobe -v -r nvme-$TEST_TRANSPORT 240 if modprobe -v -r nvme-fabrics; then 241 set -e 242 return 0 243 fi 244 sleep 1 245 done 246 set -e 247 248 # So far unable to remove the kernel modules. Try 249 # one more time and let it fail. 250 # Allow the transport module to fail for now. See Jim's comment 251 # about the nvme-tcp module below. 252 modprobe -v -r nvme-$TEST_TRANSPORT || true 253 modprobe -v -r nvme-fabrics 254 fi 255} 256 257function nvmf_veth_init() { 258 NVMF_INITIATOR_IP=10.0.0.1 259 NVMF_FIRST_TARGET_IP=10.0.0.2 260 NVMF_SECOND_TARGET_IP=10.0.0.3 261 NVMF_BRIDGE="nvmf_br" 262 NVMF_INITIATOR_INTERFACE="nvmf_init_if" 263 NVMF_INITIATOR_BRIDGE="nvmf_init_br" 264 NVMF_TARGET_NAMESPACE="nvmf_tgt_ns" 265 NVMF_TARGET_NS_CMD=(ip netns exec "$NVMF_TARGET_NAMESPACE") 266 NVMF_TARGET_INTERFACE="nvmf_tgt_if" 267 NVMF_TARGET_INTERFACE2="nvmf_tgt_if2" 268 NVMF_TARGET_BRIDGE="nvmf_tgt_br" 269 NVMF_TARGET_BRIDGE2="nvmf_tgt_br2" 270 271 ip link set $NVMF_INITIATOR_BRIDGE nomaster || true 272 ip link set $NVMF_TARGET_BRIDGE nomaster || true 273 ip link set $NVMF_TARGET_BRIDGE2 nomaster || true 274 ip link set $NVMF_INITIATOR_BRIDGE down || true 275 ip link set $NVMF_TARGET_BRIDGE down || true 276 ip link set $NVMF_TARGET_BRIDGE2 down || true 277 ip link delete $NVMF_BRIDGE type bridge || true 278 ip link delete $NVMF_INITIATOR_INTERFACE || true 279 "${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE || true 280 "${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE2 || true 281 ip netns del $NVMF_TARGET_NAMESPACE || true 282 283 # Create network namespace 284 ip netns add $NVMF_TARGET_NAMESPACE 285 286 # Create veth (Virtual ethernet) interface pairs 287 ip link add $NVMF_INITIATOR_INTERFACE type veth peer name $NVMF_INITIATOR_BRIDGE 288 ip link add $NVMF_TARGET_INTERFACE type veth peer name $NVMF_TARGET_BRIDGE 289 ip link add $NVMF_TARGET_INTERFACE2 type veth peer name $NVMF_TARGET_BRIDGE2 290 291 # Associate veth interface pairs with network namespace 292 ip link set $NVMF_TARGET_INTERFACE netns $NVMF_TARGET_NAMESPACE 293 ip link set $NVMF_TARGET_INTERFACE2 netns $NVMF_TARGET_NAMESPACE 294 295 # Allocate IP addresses 296 ip addr add $NVMF_INITIATOR_IP/24 dev $NVMF_INITIATOR_INTERFACE 297 "${NVMF_TARGET_NS_CMD[@]}" ip addr add $NVMF_FIRST_TARGET_IP/24 dev $NVMF_TARGET_INTERFACE 298 "${NVMF_TARGET_NS_CMD[@]}" ip addr add $NVMF_SECOND_TARGET_IP/24 dev $NVMF_TARGET_INTERFACE2 299 300 # Link up veth interfaces 301 ip link set $NVMF_INITIATOR_INTERFACE up 302 ip link set $NVMF_INITIATOR_BRIDGE up 303 ip link set $NVMF_TARGET_BRIDGE up 304 ip link set $NVMF_TARGET_BRIDGE2 up 305 "${NVMF_TARGET_NS_CMD[@]}" ip link set $NVMF_TARGET_INTERFACE up 306 "${NVMF_TARGET_NS_CMD[@]}" ip link set $NVMF_TARGET_INTERFACE2 up 307 "${NVMF_TARGET_NS_CMD[@]}" ip link set lo up 308 309 # Create a bridge 310 ip link add $NVMF_BRIDGE type bridge 311 ip link set $NVMF_BRIDGE up 312 313 # Add veth interfaces to the bridge 314 ip link set $NVMF_INITIATOR_BRIDGE master $NVMF_BRIDGE 315 ip link set $NVMF_TARGET_BRIDGE master $NVMF_BRIDGE 316 ip link set $NVMF_TARGET_BRIDGE2 master $NVMF_BRIDGE 317 318 # Accept connections from veth interface 319 iptables -I INPUT 1 -i $NVMF_INITIATOR_INTERFACE -p tcp --dport $NVMF_PORT -j ACCEPT 320 321 # Verify connectivity 322 ping -c 1 $NVMF_FIRST_TARGET_IP 323 ping -c 1 $NVMF_SECOND_TARGET_IP 324 "${NVMF_TARGET_NS_CMD[@]}" ping -c 1 $NVMF_INITIATOR_IP 325 326 NVMF_APP=("${NVMF_TARGET_NS_CMD[@]}" "${NVMF_APP[@]}") 327} 328 329function nvmf_veth_fini() { 330 # Cleanup bridge, veth interfaces, and network namespace 331 # Note: removing one veth removes the pair 332 ip link set $NVMF_INITIATOR_BRIDGE nomaster 333 ip link set $NVMF_TARGET_BRIDGE nomaster 334 ip link set $NVMF_TARGET_BRIDGE2 nomaster 335 ip link set $NVMF_INITIATOR_BRIDGE down 336 ip link set $NVMF_TARGET_BRIDGE down 337 ip link set $NVMF_TARGET_BRIDGE2 down 338 ip link delete $NVMF_BRIDGE type bridge 339 ip link delete $NVMF_INITIATOR_INTERFACE 340 "${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE 341 "${NVMF_TARGET_NS_CMD[@]}" ip link delete $NVMF_TARGET_INTERFACE2 342 ip netns del $NVMF_TARGET_NAMESPACE 343} 344 345function nvmf_tcp_init() { 346 NVMF_INITIATOR_IP=10.0.0.1 347 NVMF_FIRST_TARGET_IP=10.0.0.2 348 TCP_INTERFACE_LIST=($(get_tcp_if_list_by_driver)) 349 if ((${#TCP_INTERFACE_LIST[@]} == 0)); then 350 nvmf_veth_init 351 return 0 352 fi 353 354 # We need two net devs at minimum 355 ((${#TCP_INTERFACE_LIST[@]} > 1)) 356 357 NVMF_TARGET_INTERFACE=${TCP_INTERFACE_LIST[0]} 358 NVMF_INITIATOR_INTERFACE=${TCP_INTERFACE_LIST[1]} 359 360 # Skip case nvmf_multipath in nvmf_tcp_init(), it will be covered by nvmf_veth_init(). 361 NVMF_SECOND_TARGET_IP="" 362 363 NVMF_TARGET_NAMESPACE=$NVMF_TARGET_INTERFACE"_ns" 364 NVMF_TARGET_NS_CMD=(ip netns exec "$NVMF_TARGET_NAMESPACE") 365 ip netns del $NVMF_TARGET_NAMESPACE || true 366 ip -4 addr flush $NVMF_TARGET_INTERFACE || true 367 ip -4 addr flush $NVMF_INITIATOR_INTERFACE || true 368 369 # Create network namespace 370 ip netns add $NVMF_TARGET_NAMESPACE 371 372 # Associate phy interface pairs with network namespace 373 ip link set $NVMF_TARGET_INTERFACE netns $NVMF_TARGET_NAMESPACE 374 375 # Allocate IP addresses 376 ip addr add $NVMF_INITIATOR_IP/24 dev $NVMF_INITIATOR_INTERFACE 377 "${NVMF_TARGET_NS_CMD[@]}" ip addr add $NVMF_FIRST_TARGET_IP/24 dev $NVMF_TARGET_INTERFACE 378 379 # Link up phy interfaces 380 ip link set $NVMF_INITIATOR_INTERFACE up 381 382 "${NVMF_TARGET_NS_CMD[@]}" ip link set $NVMF_TARGET_INTERFACE up 383 "${NVMF_TARGET_NS_CMD[@]}" ip link set lo up 384 385 # Accept connections from phy interface 386 iptables -I INPUT 1 -i $NVMF_INITIATOR_INTERFACE -p tcp --dport $NVMF_PORT -j ACCEPT 387 388 # Verify connectivity 389 ping -c 1 $NVMF_FIRST_TARGET_IP 390 "${NVMF_TARGET_NS_CMD[@]}" ping -c 1 $NVMF_INITIATOR_IP 391 392 NVMF_APP=("${NVMF_TARGET_NS_CMD[@]}" "${NVMF_APP[@]}") 393} 394 395function nvmf_tcp_fini() { 396 if [[ "$NVMF_TARGET_NAMESPACE" == "nvmf_tgt_ns" ]]; then 397 nvmf_veth_fini 398 return 0 399 fi 400 if [[ -n $NVMF_TARGET_NAMESPACE && -e /var/run/netns/$NVMF_TARGET_NAMESPACE ]]; then 401 ip netns del $NVMF_TARGET_NAMESPACE 402 fi 403 ip -4 addr flush $NVMF_INITIATOR_INTERFACE || : 404} 405 406function nvmftestinit() { 407 if [ -z $TEST_TRANSPORT ]; then 408 echo "transport not specified - use --transport= to specify" 409 return 1 410 fi 411 412 trap 'process_shm --id $NVMF_APP_SHM_ID || :; nvmftestfini' SIGINT SIGTERM EXIT 413 414 if [ "$TEST_MODE" == "iso" ]; then 415 $rootdir/scripts/setup.sh 416 if [[ "$TEST_TRANSPORT" == "rdma" ]]; then 417 rdma_device_init 418 fi 419 if [[ "$TEST_TRANSPORT" == "tcp" ]]; then 420 tcp_device_init 421 fi 422 fi 423 424 NVMF_TRANSPORT_OPTS="-t $TEST_TRANSPORT" 425 if [[ "$TEST_TRANSPORT" == "rdma" ]]; then 426 RDMA_IP_LIST=$(get_available_rdma_ips) 427 NVMF_FIRST_TARGET_IP=$(echo "$RDMA_IP_LIST" | head -n 1) 428 NVMF_SECOND_TARGET_IP=$(echo "$RDMA_IP_LIST" | tail -n +2 | head -n 1) 429 if [ -z $NVMF_FIRST_TARGET_IP ]; then 430 echo "no RDMA NIC for nvmf test" 431 exit 0 432 fi 433 elif [[ "$TEST_TRANSPORT" == "tcp" ]]; then 434 nvmf_tcp_init 435 NVMF_TRANSPORT_OPTS="$NVMF_TRANSPORT_OPTS -o" 436 fi 437 438 if [ "$TEST_TRANSPORT" == "tcp" ] || [ "$TEST_TRANSPORT" == "rdma" ]; then 439 # currently we run the host/perf test for TCP even on systems without kernel nvme-tcp 440 # support; that's fine since the host/perf test uses the SPDK initiator 441 # maybe later we will enforce modprobe to succeed once we have systems in the test pool 442 # with nvme-tcp kernel support - but until then let this pass so we can still run the 443 # host/perf test with the tcp transport 444 modprobe nvme-$TEST_TRANSPORT || true 445 fi 446} 447 448function nvmfappstart() { 449 timing_enter start_nvmf_tgt 450 "${NVMF_APP[@]}" "$@" & 451 nvmfpid=$! 452 waitforlisten $nvmfpid 453 timing_exit start_nvmf_tgt 454} 455 456function nvmftestfini() { 457 nvmfcleanup || : 458 if [ -n "$nvmfpid" ]; then 459 killprocess $nvmfpid 460 fi 461 if [ "$TEST_MODE" == "iso" ]; then 462 $rootdir/scripts/setup.sh reset 463 if [[ "$TEST_TRANSPORT" == "rdma" ]]; then 464 rdma_device_init 465 fi 466 fi 467 if [[ "$TEST_TRANSPORT" == "tcp" ]]; then 468 nvmf_tcp_fini 469 fi 470} 471 472function rdma_device_init() { 473 load_ib_rdma_modules 474 detect_transport_nics 475 allocate_nic_ips 476} 477 478function tcp_device_init() { 479 detect_transport_nics 480} 481 482function revert_soft_roce() { 483 rxe_cfg stop 484} 485 486function check_ip_is_soft_roce() { 487 if [ "$TEST_TRANSPORT" != "rdma" ]; then 488 return 0 489 fi 490 rxe_cfg status rxe | grep -wq "$1" 491} 492 493function nvme_connect() { 494 local init_count 495 init_count=$(nvme list | wc -l) 496 497 if ! nvme connect "$@"; then return $?; fi 498 499 for i in $(seq 1 10); do 500 if [ $(nvme list | wc -l) -gt $init_count ]; then 501 return 0 502 else 503 sleep 1s 504 fi 505 done 506 return 1 507} 508 509function get_nvme_devs() { 510 local dev _ 511 512 while read -r dev _; do 513 if [[ $dev == /dev/nvme* ]]; then 514 echo "$dev" 515 fi 516 done < <(nvme list) 517} 518 519function gen_nvmf_target_json() { 520 local subsystem config=() 521 522 for subsystem in "${@:-1}"; do 523 config+=( 524 "$( 525 cat <<- EOF 526 { 527 "params": { 528 "name": "Nvme$subsystem", 529 "trtype": "$TEST_TRANSPORT", 530 "traddr": "$NVMF_FIRST_TARGET_IP", 531 "adrfam": "ipv4", 532 "trsvcid": "$NVMF_PORT", 533 "subnqn": "nqn.2016-06.io.spdk:cnode$subsystem", 534 "hostnqn": "nqn.2016-06.io.spdk:host$subsystem", 535 "hdgst": ${hdgst:-false}, 536 "ddgst": ${ddgst:-false} 537 }, 538 "method": "bdev_nvme_attach_controller" 539 } 540 EOF 541 )" 542 ) 543 done 544 jq . <<- JSON 545 { 546 "subsystems": [ 547 { 548 "subsystem": "bdev", 549 "config": [ 550 { 551 "method": "bdev_nvme_set_options", 552 "params": { 553 "action_on_timeout": "none", 554 "timeout_us": 0, 555 "retry_count": 4, 556 "arbitration_burst": 0, 557 "low_priority_weight": 0, 558 "medium_priority_weight": 0, 559 "high_priority_weight": 0, 560 "nvme_adminq_poll_period_us": 10000, 561 "keep_alive_timeout_ms" : 10000, 562 "nvme_ioq_poll_period_us": 0, 563 "io_queue_requests": 0, 564 "delay_cmd_submit": true 565 } 566 }, 567 $( 568 IFS="," 569 printf '%s\n' "${config[*]}" 570 ), 571 { 572 "method": "bdev_wait_for_examine" 573 } 574 ] 575 } 576 ] 577 } 578 JSON 579} 580