NVMe-TCP on Oracle Linux - Quick Start Guide

Linux

Audience
Public
Product
FlashBlade
FlashArray
Technology Integrations
Linux
Source Type
Documentation
Important:

Vendor Documentation Priority: This guide is for reference only. Always consult official vendor documentation for your distribution. Test thoroughly in a lab environment before production use.

Note:

For detailed explanations, alternative configurations, and troubleshooting: See NVMe-TCP Best Practices

Prerequisites:

  • Oracle Linux 8.x or 9.x with UEK R7 (5.15+) recommended

  • FlashArray configured with NVMe-TCP with portal IPs and subsystem NQN

  • Dedicated storage network interfaces

  • Root or sudo access

Note:

New to NVMe-TCP? See the Storage Terminology Glossary.

Warning:

If both interfaces are on the same subnet, configure ARP settings. See ARP Configuration.

  1. Install Packages:
    sudo dnf install -y nvme-cli
    sudo modprobe nvme-tcp
    echo "nvme-tcp" | sudo tee /etc/modules-load.d/nvme-tcp.conf
  2. Configure Network Interfaces:
    # First storage interface
    sudo nmcli connection add type ethernet \
        con-name storage-1 \
        ifname <INTERFACE_NAME_1> \
        ipv4.method manual \
        ipv4.addresses <HOST_IP_1>/<CIDR> \
        ipv4.never-default yes \
        802-3-ethernet.mtu 9000 \
        connection.autoconnect yes
    
    # Second storage interface
    sudo nmcli connection add type ethernet \
        con-name storage-2 \
        ifname <INTERFACE_NAME_2> \
        ipv4.method manual \
        ipv4.addresses <HOST_IP_2>/<CIDR> \
        ipv4.never-default yes \
        802-3-ethernet.mtu 9000 \
        connection.autoconnect yes
    
    # Activate
    sudo nmcli connection up storage-1
    sudo nmcli connection up storage-2
  3. Configure Firewall:

    Add storage interfaces to trusted zone (recommended for dedicated storage networks):

    # Check if firewalld is running (skip if not installed, e.g., minimal/cloud images)
    if systemctl is-active --quiet firewalld; then
        sudo firewall-cmd --permanent --zone=trusted --add-interface=<INTERFACE_NAME_1>
        sudo firewall-cmd --permanent --zone=trusted --add-interface=<INTERFACE_NAME_2>
        sudo firewall-cmd --reload
    else
        echo "firewalld not running - skipping firewall configuration"
    fi
    Note:

    Alternative: For port filtering options, see Best Practices - Firewall Configuration.

  4. Generate Host NQN:
    sudo mkdir -p /etc/nvme
    sudo nvme gen-hostnqn | sudo tee /etc/nvme/hostnqn
    cat /etc/nvme/hostnqn

    Register this NQN with your FlashArray.

  5. Connect to NVMe Subsystems:

    Option A: Connect-all (simplest method)

    Discovers and connects to all available subsystems from a single portal:

    # Replace <PORTAL_IP_1> with any storage portal IP
    sudo nvme connect-all -t tcp -a <PORTAL_IP_1> -s 4420
    
    # Verify connections
    sudo nvme list-subsys

    Option B: Individual connections (for specific interface binding)

    Use when you need to bind connections to specific host interfaces:

    # Replace values: <PORTAL_IP_X>, <SUBSYSTEM_NQN>, <INTERFACE_NAME_X>, <HOST_IP_X>
    sudo nvme connect -t tcp -a <PORTAL_IP_1> -s 4420 -n <SUBSYSTEM_NQN> \
        --host-iface=<INTERFACE_NAME_1> --host-traddr=<HOST_IP_1> \
        --ctrl-loss-tmo=1800 --reconnect-delay=10
    
    sudo nvme connect -t tcp -a <PORTAL_IP_2> -s 4420 -n <SUBSYSTEM_NQN> \
        --host-iface=<INTERFACE_NAME_1> --host-traddr=<HOST_IP_1> \
        --ctrl-loss-tmo=1800 --reconnect-delay=10
    
    # Repeat for all portal/interface combinations to create full mesh
    
    # Verify connections
    sudo nvme list-subsys
  6. Configure IO Policy:
    # Create udev rule for queue-depth IO policy
    sudo tee /etc/udev/rules.d/99-nvme-iopolicy.rules > /dev/null <<'EOF'
    ACTION=="add|change", SUBSYSTEM=="nvme-subsystem", ATTR{iopolicy}="queue-depth"
    EOF
    
    sudo udevadm control --reload-rules
    sudo udevadm trigger
  7. Configure Persistent Connections:
    # Create discovery configuration
    sudo tee /etc/nvme/discovery.conf > /dev/null <<EOF
    -t tcp -a <PORTAL_IP_1> -s 4420
    -t tcp -a <PORTAL_IP_2> -s 4420
    -t tcp -a <PORTAL_IP_3> -s 4420
    -t tcp -a <PORTAL_IP_4> -s 4420
    EOF
    
    # Enable autoconnect service
    sudo systemctl enable --now nvmf-autoconnect.service
  8. Create LVM Storage:
    # Find NVMe device
    sudo nvme list
    # Example: /dev/nvme0n1
    
    # Create LVM
    sudo pvcreate /dev/nvme0n1
    sudo vgcreate nvme-storage /dev/nvme0n1
    sudo lvcreate -L 500G -n data nvme-storage
    # Format and mount (Oracle Linux: XFS recommended)
    sudo mkfs.xfs /dev/nvme-storage/data
    sudo mkdir -p /mnt/nvme-storage
    sudo mount /dev/nvme-storage/data /mnt/nvme-storage
    
    # Add to fstab
    echo '/dev/nvme-storage/data /mnt/nvme-storage xfs defaults,_netdev 0 0' | sudo tee -a /etc/fstab
  9. Verify Configuration:
    # Check multipath is enabled
    cat /sys/module/nvme_core/parameters/multipath  # Should show: Y
    
    # Check all paths are live
    sudo nvme list-subsys
    
    # Check IO policy
    cat /sys/class/nvme-subsystem/nvme-subsys*/iopolicy  # Should show: queue-depth
    
    # Verify block devices are visible
    lsblk | grep nvme
    
    # Verify storage (after LVM/filesystem creation)
    df -h | grep nvme

    Verify Persistent Connections (recommended):

    # Reboot to confirm connections re-establish automatically
    sudo reboot
    
    # After reboot, verify all paths reconnected
    sudo nvme list-subsys  # All paths should show "live"
    Note:

    Quick Reference

    Command Description
    sudo nvme list-subsys Show all paths and subsystems
    sudo nvme list List NVMe devices
    sudo nvme connect -t tcp -a <IP> -s 4420 -n <NQN> Connect to subsystem
    sudo nvme disconnect -n <NQN> Disconnect from subsystem

For production deployments, see NVMe-TCP Best Practices for:

  • Network design and VLAN configuration

  • Performance tuning

  • Security best practices (SELinux, firewall options)

  • Monitoring and troubleshooting

  • High availability considerations

  • UEK vs RHCK kernel selection

  • Ksplice zero-downtime updates

Additional Resources: