跳轉到

IRQ Affinity

GRUB 章節設定的 isolcpus=managed_irq 已確保 kernel 在分配硬體中斷時自動排除 CPU 3(NetThread 專用核心)。本章補充設定 irqbalance,避免一般 IRQ 被排程至隔離核心。

irqbalance 設定

編輯 /etc/sysconfig/irqbalance,加入:

IRQBALANCE_BANNED_CPULIST=3

套用:

sudo systemctl enable --now irqbalance
sudo systemctl restart irqbalance

改 ban list 不會搬走「已存在」的 IRQ

IRQBALANCE_BANNED_CPULIST=3 只防止 irqbalance 將來把 IRQ 排到 CPU 3,不會主動把目前已綁在 CPU 3 上的 IRQ 搬走;driver 啟動時的 affinity_hint 預設值含 CPU 3(NIC RX queue 通常是 ½/4/8),裝完 irqbalance 不重啟則 hint 會延續。

若部署過程中曾經把 IRQ 卡在 CPU 3,或這台機器先前 ban list 寫錯(例如 =6 但只有 4 顆 CPU),手動把 effective_affinity 推離 CPU 3 一次:

for irq in /proc/irq/[0-9]*; do
  eff=$(cat "$irq/effective_affinity_list" 2>/dev/null)
  case "$eff" in *3*) echo 7 | sudo tee "$irq/smp_affinity" >/dev/null ;;
  esac
done

7 = mask 0b0111 = CPU 0,1,2。Managed IRQ(kernel 內部 queue-per-CPU)會回 Input/output error 拒絕;正常情形這些 IRQ 流量極低(幾筆/小時),可忽略。

驗證

# 1. ban list 對齊 isolated CPU
grep ^IRQBALANCE_BANNED_CPULIST /etc/sysconfig/irqbalance
# → IRQBALANCE_BANNED_CPULIST=3

# 2. 沒有 IRQ 的 effective_affinity 還含 CPU 3(managed IRQ 例外,會在輸出中列出)
for irq in /proc/irq/[0-9]*; do
  num=$(basename "$irq")
  eff=$(cat "$irq/effective_affinity_list" 2>/dev/null)
  case "$eff" in *3*)
    name=$(awk -v i="$num:" '$1==i{print $NF}' /proc/interrupts)
    printf "  irq=%s eff=%s name=%s\n" "$num" "$eff" "$name"
    ;;
  esac
done
# 出現的應該都是少量 managed IRQ(mlx5_async / TX completion 等)

# 3. 5 秒間隔 sample,CPU 3 IRQ rate 應接近 0
b=$(awk '/^\s*[0-9]+:/{s+=$5} END{print s}' /proc/interrupts); sleep 5
a=$(awk '/^\s*[0-9]+:/{s+=$5} END{print s}' /proc/interrupts)
echo "CPU3 IRQ rate = $(((a-b)/5))/sec"
# 預期 ≈ 0;> 10 表示還有源頭沒處理乾淨

盤前自動驗

tapioctl check tuning 會把以上三項 + GRUB cmdline 對齊一次跑完。日常巡檢用 tapioctl check all 即可,不用人工敲。