1e745bb65STheo Jepsen# NVMe-oF Multipath HOWTO {#nvmf_multipath_howto} 2e745bb65STheo Jepsen 3e745bb65STheo JepsenThis HOWTO provides step-by-step instructions for setting-up a simple SPDK deployment and testing multipath. 4e745bb65STheo JepsenIt demonstrates configuring path preferences with Asymmetric Namespace Access (ANA), as well as round-robin 5e745bb65STheo Jepsenpath load balancing. 6e745bb65STheo Jepsen 7e745bb65STheo Jepsen## Build SPDK on both the initiator and target servers 8e745bb65STheo Jepsen 9e745bb65STheo JepsenClone the repo: 10e745bb65STheo Jepsen~~~{.sh} 1101a88849Spaul lusegit clone https://github.com/spdk/spdk --recursive 12e745bb65STheo Jepsen~~~ 13e745bb65STheo Jepsen 14e745bb65STheo JepsenConfigure and build SPDK: 15e745bb65STheo Jepsen~~~{.sh} 16e745bb65STheo Jepsencd spdk/ 17e745bb65STheo Jepsen./configure 18e745bb65STheo Jepsenmake -j16 19e745bb65STheo Jepsen~~~ 20e745bb65STheo Jepsen 21e745bb65STheo Jepsen## Setup hugepages 22e745bb65STheo Jepsen 23e745bb65STheo JepsenThis should be run once on each server (and after reboots): 24e745bb65STheo Jepsen~~~{.sh} 25e745bb65STheo Jepsencd spdk/ 26e745bb65STheo Jepsen./scripts/setup.sh 27e745bb65STheo Jepsen~~~ 28e745bb65STheo Jepsen 29e745bb65STheo Jepsen## On target: start and configure SPDK 30e745bb65STheo Jepsen 31e745bb65STheo JepsenStart the target in the background and configure it: 32e745bb65STheo Jepsen~~~{.sh} 33e745bb65STheo Jepsencd spdk/ 34e745bb65STheo Jepsen./build/bin/nvmf_tgt -m 0x3 & 35e745bb65STheo Jepsen./scripts/rpc.py nvmf_create_transport -t tcp -o -u 8192 36e745bb65STheo Jepsen~~~ 37e745bb65STheo Jepsen 38e745bb65STheo JepsenCreate a subsystem, with `-r` to enable ANA reporting feature: 39e745bb65STheo Jepsen~~~{.sh} 40e745bb65STheo Jepsen./scripts/rpc.py nvmf_create_subsystem nqn.2022-02.io.spdk:cnode0 -a -s SPDK00000000000001 -r 41e745bb65STheo Jepsen~~~ 42e745bb65STheo Jepsen 43e745bb65STheo JepsenCreate and add a malloc block device: 44e745bb65STheo Jepsen~~~{.sh} 45e745bb65STheo Jepsen./scripts/rpc.py bdev_malloc_create 64 512 -b Malloc0 46e745bb65STheo Jepsen./scripts/rpc.py nvmf_subsystem_add_ns nqn.2022-02.io.spdk:cnode0 Malloc0 47e745bb65STheo Jepsen~~~ 48e745bb65STheo Jepsen 49e745bb65STheo JepsenAdd two listeners, each with a different `IP:port` pair: 50e745bb65STheo Jepsen~~~{.sh} 51e745bb65STheo Jepsen./scripts/rpc.py nvmf_subsystem_add_listener -t tcp -a 172.17.1.13 -s 4420 nqn.2022-02.io.spdk:cnode0 52e745bb65STheo Jepsen./scripts/rpc.py nvmf_subsystem_add_listener -t tcp -a 172.18.1.13 -s 5520 nqn.2022-02.io.spdk:cnode0 53e745bb65STheo Jepsen~~~ 54e745bb65STheo Jepsen 55e745bb65STheo Jepsen## On initiator: start and configure bdevperf 56e745bb65STheo Jepsen 57e745bb65STheo JepsenLaunch the bdevperf process in the background: 58e745bb65STheo Jepsen~~~{.sh} 59e745bb65STheo Jepsencd spdk/ 60*29784f35SKrzysztof Karas./build/examples/bdevperf -m 0x4 -z -r /tmp/bdevperf.sock -q 128 -o 4096 -w verify -t 90 &> bdevperf.log & 61e745bb65STheo Jepsen~~~ 62e745bb65STheo Jepsen 63e745bb65STheo JepsenConfigure bdevperf and add two paths: 64e745bb65STheo Jepsen~~~{.sh} 65e745bb65STheo Jepsen./scripts/rpc.py -s /tmp/bdevperf.sock bdev_nvme_set_options -r -1 66e745bb65STheo Jepsen./scripts/rpc.py -s /tmp/bdevperf.sock bdev_nvme_attach_controller -b Nvme0 -t tcp -a 172.17.1.13 -s 4420 -f ipv4 -n nqn.2022-02.io.spdk:cnode0 -l -1 -o 10 67e745bb65STheo Jepsen./scripts/rpc.py -s /tmp/bdevperf.sock bdev_nvme_attach_controller -b Nvme0 -t tcp -a 172.18.1.13 -s 5520 -f ipv4 -n nqn.2022-02.io.spdk:cnode0 -x multipath -l -1 -o 10 68e745bb65STheo Jepsen~~~ 69e745bb65STheo Jepsen 70e745bb65STheo Jepsen## Launch a bdevperf test 71e745bb65STheo Jepsen 72e745bb65STheo JepsenConnect to the RPC socket of the bdevperf process and start the test: 73e745bb65STheo Jepsen~~~{.sh} 74*29784f35SKrzysztof KarasPYTHONPATH=$PYTHONPATH:/root/src/spdk/python ./examples/bdev/bdevperf/bdevperf.py -t 1 -s /tmp/bdevperf.sock perform_tests 75e745bb65STheo Jepsen~~~ 76e745bb65STheo Jepsen 77e745bb65STheo JepsenThe RPC command will return, leaving the test to run for 90 seconds in the background. On the target server, 78e745bb65STheo Jepsenobserve that only the first path (port) is receiving packets by checking the queues with `ss -t`. 79e745bb65STheo Jepsen 80e745bb65STheo JepsenYou can view the paths available to the initiator with: 81e745bb65STheo Jepsen~~~{.sh} 82e745bb65STheo Jepsen./scripts/rpc.py -s /tmp/bdevperf.sock bdev_nvme_get_io_paths -n Nvme0n1 83e745bb65STheo Jepsen~~~ 84e745bb65STheo Jepsen 85e745bb65STheo Jepsen## Switching paths 86e745bb65STheo Jepsen 87e745bb65STheo JepsenThis can be done on the target server by setting the first path's ANA to `non_optimized`: 88e745bb65STheo Jepsen~~~{.sh} 89e745bb65STheo Jepsen./scripts/rpc.py nvmf_subsystem_listener_set_ana_state nqn.2022-02.io.spdk:cnode0 -t tcp -a 172.17.1.13 -s 4420 -n non_optimized 90e745bb65STheo Jepsen~~~ 91e745bb65STheo Jepsen 92e745bb65STheo JepsenUse `ss -t` to verify that the traffic has switched to the second path. 93e745bb65STheo Jepsen 94e745bb65STheo Jepsen## Use round-robin (active_active) path load balancing 95e745bb65STheo Jepsen 96e745bb65STheo JepsenFirst, ensure the ANA for both paths is configured as `optimized` on the target. Then, change the 97e745bb65STheo Jepsenmultipath policy on the initiator to `active_active` (multipath policy is per bdev, so 98e745bb65STheo Jepsen`bdev_nvme_set_multipath_policy` must be called after `bdev_nvme_attach_controller`): 99e745bb65STheo Jepsen~~~{.sh} 100e745bb65STheo Jepsen./scripts/rpc.py -s /tmp/bdevperf.sock bdev_nvme_set_multipath_policy -b Nvme0n1 -p active_active 101e745bb65STheo Jepsen~~~ 102e745bb65STheo Jepsen 103e745bb65STheo JepsenObserve with `ss -t` that both connections are receiving traffic (queues build up). 104