NVMe over Fabrics (NVMe-oF)
3 min read
Protocol extension that allows NVMe commands to be transported over a network fabric. NVMe/TCP is the standard choice for most deployments — it runs over standard Ethernet without special hardware, offers lower latency than iSCSI due to the leaner NVMe command set, and is well-supported since Linux 5.0.
Other transports (RDMA/RoCE, Fibre Channel) exist but require specialized NICs/switches and are not covered here.
NVMe/TCP
Exposes a local block device as an NVMe namespace accessible to remote hosts over TCP/IP.
NQN Naming
NVMe Qualified Names follow the format:
nqn.YYYY-MM.reverse-domain:identifier
Example: nqn.2024-01.com.example:storage-pool-1
Every host also has its own NQN (used for access control):
sh
cat /etc/nvme/hostnqn # view
nvme gen-hostnqn # generate if missing
Basic Setup (Linux)
Target (server):
sh
modprobe nvmet
modprobe nvmet-tcp
NQN="nqn.2024-01.com.example:storage-pool-1"
# Subsystem + namespace
mkdir /sys/kernel/config/nvmet/subsystems/$NQN
mkdir /sys/kernel/config/nvmet/subsystems/$NQN/namespaces/1
echo /dev/nvme0n1 > /sys/kernel/config/nvmet/subsystems/$NQN/namespaces/1/device_path
echo 1 > /sys/kernel/config/nvmet/subsystems/$NQN/namespaces/1/enable
# Port
mkdir /sys/kernel/config/nvmet/ports/1
echo 0.0.0.0 > /sys/kernel/config/nvmet/ports/1/addr_traddr
echo ipv4 > /sys/kernel/config/nvmet/ports/1/addr_adrfam
echo tcp > /sys/kernel/config/nvmet/ports/1/addr_trtype
echo 4420 > /sys/kernel/config/nvmet/ports/1/addr_trsvcid
ln -s /sys/kernel/config/nvmet/subsystems/$NQN \
/sys/kernel/config/nvmet/ports/1/subsystems/$NQN
Initiator (client):
sh
modprobe nvme-tcp
nvme discover -t tcp -a <server-ip> -s 4420
nvme connect -t tcp -a <server-ip> -s 4420 -n nqn.2024-01.com.example:storage-pool-1
nvme list # shows the connected device, e.g. /dev/nvme1n1
Disconnect:
sh
nvme disconnect -n nqn.2024-01.com.example:storage-pool-1
nvme disconnect-all # disconnects everything
Production
Host Access Control
Never use attr_allow_any_host 1 in production. Instead, explicitly allow each initiator by its host NQN:
sh
INITIATOR_NQN="nqn.2024-01.com.example:host-node1"
mkdir /sys/kernel/config/nvmet/subsystems/$NQN/allowed_hosts/$INITIATOR_NQN
Persistence
The configfs tree is lost on reboot. Use nvmetcli (Python tool) to save and restore it:
sh
nvmetcli save /etc/nvmet.json # snapshot current config
nvmetcli restore /etc/nvmet.json # restore it
nvmetcli clear # wipe all config
Systemd service to restore on boot (/etc/systemd/system/nvmet.service):
ini
[Unit]
Description=NVMe-oF Target
After=network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=nvmetcli restore /etc/nvmet.json
ExecStop=nvmetcli clear
[Install]
WantedBy=multi-user.target
Multipath
NVMe native multipath merges multiple paths to the same subsystem into a single block device. Connect the same NQN over multiple IPs:
sh
nvme connect -t tcp -a <ip1> -s 4420 -n <nqn>
nvme connect -t tcp -a <ip2> -s 4420 -n <nqn>
# kernel presents a single /dev/nvmeXnY
Enable multipath in the kernel module config:
sh
# /etc/modprobe.d/nvme.conf
options nvme_core multipath=1
Check path status:
sh
nvme list-subsys
Backing Store
The namespace device_path accepts:
| Type | Example |
|---|---|
| Physical NVMe / block device | /dev/nvme0n1, /dev/sdb |
| LVM logical volume | /dev/vg0/lv_storage |
| Regular file (kernel 5.x+) | /mnt/pool/disk.img |
Network Recommendations
• Dedicated storage VLAN — isolates storage traffic and simplifies access control.
• Jumbo frames (MTU 9000) — reduces CPU overhead for large sequential I/O; must be set on both ends and all switches in the path.
• Bind target to a specific IP — use the actual storage interface IP in addr_traddr instead of 0.0.0.0.
• IRQ affinity — spread NVMe queue interrupts across cores for high-throughput workloads (irqbalance or manual smp_affinity).
Security
By default NVMe/TCP has no encryption. Options:
• Network isolation — storage VLAN + firewall rules; simplest for trusted environments.
• TLS (kernel 6.3+) — native in-kernel TLS for NVMe/TCP 1.1; requires nvme connect --tls and pre-shared keys or certificates.