Sysctl Tuning
Create sysctl configuration:
sudo tee /etc/sysctl.d/90-nvme-tcp-storage.conf > /dev/null <<'EOF'
# Network buffer sizes
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
# Network performance
net.core.netdev_max_backlog = 30000
net.core.somaxconn = 4096
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_sack = 1
# VM tuning
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.swappiness = 10
# ARP cache
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
# ARP settings for same-subnet multipath (CRITICAL)
# Prevents ARP responses on wrong interface when multiple NICs share same subnet
# See: Network Concepts documentation for detailed explanation
net.ipv4.conf.all.arp_ignore = 2
net.ipv4.conf.default.arp_ignore = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
# Interface-specific (adjust interface names as needed)
net.ipv4.conf.ens1f0.arp_ignore = 2
net.ipv4.conf.ens1f1.arp_ignore = 2
net.ipv4.conf.ens1f0.arp_announce = 2
net.ipv4.conf.ens1f1.arp_announce = 2
EOF
# Apply settings
sudo sysctl -p /etc/sysctl.d/90-nvme-tcp-storage.conf
NIC Tuning with Wicked
Integrated in wicked configuration:
# Edit interface configuration
sudo nano /etc/sysconfig/network/ifcfg-ens1f0
# Add ETHTOOL_OPTIONS
ETHTOOL_OPTIONS='-G ${INTERFACE} rx 4096 tx 4096; -C ${INTERFACE} rx-usecs 50 tx-usecs 50; -K ${INTERFACE} tso on gso on gro on'
# Reload
sudo wicked ifreload ens1f0
Or create systemd service:
sudo tee /etc/systemd/system/tune-storage-nics.service > /dev/null <<'EOF'
[Unit]
Description=Tune storage network interfaces
After=network-online.target wicked.service
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/tune-storage-nics.sh
[Install]
WantedBy=multi-user.target
EOF
# Create tuning script
sudo tee /usr/local/bin/tune-storage-nics.sh > /dev/null <<'EOF'
#!/bin/bash
INTERFACES="ens1f0 ens1f1"
for iface in $INTERFACES; do
if [ -d "/sys/class/net/$iface" ]; then
echo "Tuning $iface..."
ethtool -G $iface rx 4096 tx 4096 2>/dev/null || true
ethtool -C $iface rx-usecs 50 tx-usecs 50 2>/dev/null || true
ethtool -K $iface tso on gso on gro on 2>/dev/null || true
ethtool -A $iface rx on tx on 2>/dev/null || true
echo "$iface tuned successfully"
fi
done
EOF
sudo chmod +x /usr/local/bin/tune-storage-nics.sh
sudo systemctl enable --now tune-storage-nics.service
CPU Governor
Set performance governor:
# Install cpupower
sudo zypper install -y cpupower
# Set to performance
sudo cpupower frequency-set -g performance
# Make persistent
echo 'CPUPOWER_START_OPTS="frequency-set -g performance"' | \
sudo tee /etc/sysconfig/cpupower
# Enable service
sudo systemctl enable --now cpupower
IRQ Affinity
Install irqbalance:
sudo zypper install -y irqbalance
# Configure
sudo tee /etc/sysconfig/irqbalance > /dev/null <<EOF
IRQBALANCE_BANNED_CPUS=00000001
EOF
# Enable and start
sudo systemctl enable --now irqbalance
I/O Scheduler
Set I/O scheduler for NVMe:
# Set to 'none' for NVMe
echo none | sudo tee /sys/block/nvme*/queue/scheduler
# Make persistent with udev
sudo tee /etc/udev/rules.d/60-nvme-scheduler.rules > /dev/null <<'EOF'
ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"
EOF
# Reload udev
sudo udevadm control --reload-rules
sudo udevadm trigger
Kernel Boot Parameters
Edit GRUB configuration:
# Edit /etc/default/grub
sudo nano /etc/default/grub
# Add to GRUB_CMDLINE_LINUX:
# isolcpus=2,3,10,11 nohz_full=2,3,10,11 rcu_nocbs=2,3,10,11 intel_iommu=on iommu=pt
# Update GRUB
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# Reboot
sudo reboot
Parameter explanations:
-
isolcpus- Isolate CPUs from scheduler (dedicate to storage I/O) -
nohz_full- Disable timer ticks on isolated CPUs -
rcu_nocbs- Offload RCU callbacks from isolated CPUs -
intel_iommu=on iommu=pt- Enable IOMMU passthrough
These are general CPU and NUMA optimizations that improve overall system performance for I/O-intensive workloads. They do not directly affect NVMe-TCP protocol behavior. Measure baseline performance before and after changes to validate impact in your environment. The nvme_core.multipath=Y parameter (if not already set) directly affects NVMe multipath behavior.