Pin IRQ/SoftIRQ và tách core cho app

1. Tổng quan

Mục tiêu của bài lab là quan sát và điều khiển đường đi của IRQ và SoftIRQ trong VM, từ đó tách riêng một nhóm core chỉ xử lý cho IRQ/SoftIRQ và dành các core còn lại cho ứng dụng (user/system). Bài demo sử dụng các công cụ sẵn có của Linux: /proc/interrupts, smp_affinity/effective_affinity, RPS/XPS, taskset/csetiperf3 để đẩy traffic vào card mạng.

2. Điều kiện tiên quyết (VM)

  • Server thứ nhất là VM Linux (ví dụ Ubuntu 22.04) có ≥ 4 vCPU (tốt nhất 6–8).
  • NIC ảo hỗ trợ multiqueue (vmxnet3 trên VMware, virtio-net trên KVM…).
  • Quyền root.
  • Server thứ hai cũng là VM Linux trong cùng mạng để chạy iperf3 client.

Cài công cụ cơ bản:

apt update
apt install -y iperf3 htop sysstat util-linux ethtool

3. Nhận diện NIC và driver

ip -br a
ethtool -i ens160          # thay ens160 bằng tên NIC của bạn
lsmod | grep -E 'vmxnet3|virtio'
  • VMware: thường là vmxnet3 (ens160).
  • KVM: thường là virtio_net (ensX / ethX).

4. Kiểm tra multiqueue qua /proc/interrupts

Trên VMware, ethtool -l có thể “Operation not supported”, nhưng vẫn có nhiều queue:

grep ens160 /proc/interrupts

Bạn kỳ vọng thấy các dòng kiểu:

56: ... ens160-rxtx-0
57: ... ens160-rxtx-1
...
64: ... ens160-rxtx-7

Mỗi dòng là một IRQ ID (queue).

Sơ đồ nhanh:

ens160 (NIC ảo)
 ├─ rxtx-0 → IRQ 56
 ├─ rxtx-1 → IRQ 57
 └─ ...

5. Tắt irqbalance (tránh tự động đổi affinity)

systemctl stop irqbalance
systemctl disable irqbalance
pkill -9 irqbalance || true

6. Pin IRQ vào core dành riêng (Hard IRQ)

Ví dụ gom IRQ về CPU0–1:

6.1. Đặt smp_affinity theo mask

for irq in $(grep ens160-rxtx /proc/interrupts | awk '{print $1}' | tr -d :); do
  echo 3 > /proc/irq/$irq/smp_affinity     # 0x03 = CPU0 + CPU1
done

6.2. Xác thực bằng effective_affinity

for irq in $(grep ens160-rxtx /proc/interrupts | awk '{print $1}' | tr -d :); do
  printf "IRQ %s  smp:%s  eff:%s\n" \
    "$irq" \
    "$(cat /proc/irq/$irq/smp_affinity)" \
    "$(cat /proc/irq/$irq/effective_affinity)"
done
  • effective_affinity là mask thực tế kernel áp dụng.
  • Trên VMware/vmxnet3, IRQ có thể là managed IRQ, kernel/driver chỉ cho chạy ở một tập CPU hẹp hơn; vì vậy eff có thể ≠ smp.

Lưu ý nếu eff trả về 02 dù bạn set 03, nghĩa là driver khóa về CPU1. Đây là hành vi thường gặp với vmxnet3.

7. Kiểm soát SoftIRQ (RPS/XPS)

Mặc định, SoftIRQ (NET_RX) chạy trên cùng core nhận IRQ. Nếu RPS/XPS bật, SoftIRQ có thể bị trải sang CPU khác.

7.1. Kiểm tra trạng thái RPS/XPS

grep . /sys/class/net/ens160/queues/rx-*/rps_cpus
grep . /sys/class/net/ens160/queues/tx-*/xps_cpus
sysctl net.core.rps_sock_flow_entries

0 = tắt; ff (hay giá trị hex khác 0) = bật trên tập CPU tương ứng.

7.2. Tắt RPS/XPS (gom SoftIRQ về core của IRQ)

for f in /sys/class/net/ens160/queues/rx-*/rps_cpus; do echo 0 > "$f"; done
for f in /sys/class/net/ens160/queues/tx-*/xps_cpus; do echo 0 > "$f"; done
sysctl -w net.core.rps_sock_flow_entries=0

7.3. Bật RPS có kiểm soát (tùy mục tiêu)

Ví dụ chỉ cho RX queue 0 xử lý SoftIRQ trên CPU2–3:

echo c > /sys/class/net/ens160/queues/rx-0/rps_cpus   # 0x0c = CPU2 + CPU3

8. Tách core cho ứng dụng (user/system)

IRQ affinity không tự chặn app chạy trên core đó. Bạn cần ép app ra core khác.

8.1. Nhanh gọn với taskset

# Chạy app (ví dụ iperf3 server, Ceph OSD) trên CPU2–7
taskset -c 2-7 <command>

8.2. Cô lập bằng cset shield (khuyến nghị lab)

apt install -y cpuset
cset shield --cpu 2-7 --kthread on
cset shield --exec -- <command>

8.3. Mặc định hệ thống bằng systemd (tùy chọn)

systemctl set-property --runtime -- system.slice CPUAffinity=2-7
systemctl set-property --runtime -- user.slice   CPUAffinity=2-7

9. Đẩy traffic vào card mạng và quan sát

9.1. Đẩy traffic vào card mạng

Trên VM (server) — cho chạy ở CPU2–7:

taskset -c 2-7 iperf3 -s

Từ máy khác trong mạng:

iperf3 -c <IP_VM> -t 60 -P 8

9.2. Quan sát IRQ/SoftIRQ và CPU

watch -n1 "grep ens160-rxtx /proc/interrupts"
mpstat -P ALL 1
htop

Kỳ vọng (khi đã gom đúng):

  • Các dòng ens160-rxtx-* chỉ tăng ở cột CPU0–1.
  • %si (softirq) cao ở CPU0–1; CPU2–7 chủ yếu %us (user) do app.

10. Sơ đồ logic tách core

CPU0  CPU1  |  CPU2  CPU3  CPU4  CPU5  CPU6  CPU7
[IRQ/SoftIRQ] | [User/System: iperf, Ceph OSD, ...]

Luồng gói tin (đơn giản hoá):

NIC → Hard IRQ (CPU0/1) → SoftIRQ NET_RX (CPU0/1 hoặc theo RPS) → Socket → App (CPU2–7)

11. Khắc phục sự cố (trên VMware/vmxnet3)

  • effective_affinitysmp_affinity:
    • Managed IRQ: driver giới hạn CPU. Chấp nhận gom theo khả năng của driver (thường dính vào 1 trong 2 core đầu).
  • /proc/interrupts vẫn thấy cột CPU ngoài 0–1 tăng:
    • RPS/XPS đang bật → tắt theo Mục 7.
    • Có process lạ chạy trên 0–1 → ép app ra 2–7 theo Mục 8.
  • ethtool -l báo Operation not supported:
    • Bình thường trên VMware; dựa vào /proc/interrupts để thấy số queue.
  • Oversubscribe vCPU/pCPU trên host:
    • Kết quả đo có thể nhiễu; nếu có thể, giảm oversubscribe.

12. Ví dụ hai profile bật/tắt nhanh

12.1. Profile A — Gom IRQ về CPU0–1, tắt RPS/XPS

# stop irqbalance
systemctl stop irqbalance
pkill -9 irqbalance || true

# pin IRQ ens160-rxtx-* vào CPU0-1 (mask 0x03)
for irq in $(grep 'ens160-rxtx' /proc/interrupts | awk '{print $1}' | tr -d :); do
  echo 3 > /proc/irq/$irq/smp_affinity
done

# tắt RPS/XPS
for f in /sys/class/net/ens160/queues/rx-*/rps_cpus; do echo 0 > "$f"; done
for f in /sys/class/net/ens160/queues/tx-*/xps_cpus; do echo 0 > "$f"; done
sysctl -w net.core.rps_sock_flow_entries=0

# chạy app ở CPU2-7
taskset -c 2-7 iperf3 -s

12.2. Profile B — Rollback

# cho IRQ dùng tất cả CPU0-7
for irq in $(grep 'ens160-rxtx' /proc/interrupts | awk '{print $1}' | tr -d :); do
  echo ff > /proc/irq/$irq/smp_affinity
done

# bật lại RPS/XPS theo ý (ví dụ vẫn để 0)
for f in /sys/class/net/ens160/queues/rx-*/rps_cpus; do echo 0 > "$f"; done
for f in /sys/class/net/ens160/queues/tx-*/xps_cpus; do echo 0 > "$f"; done

# bật lại irqbalance nếu muốn
systemctl enable --now irqbalance

13. Bảng mask nhanh (8 vCPU)

  • CPU0 → 01
  • CPU1 → 02
  • CPU2 → 04
  • CPU3 → 08
  • CPU4 → 10
  • CPU5 → 20
  • CPU6 → 40
  • CPU7 → 80
  • CPU0–1 → 03
  • CPU0–3 → 0f
  • CPU2–7 → fc
  • CPU0–7 → ff

Có thể dùng dạng danh sách dễ đọc:

echo 0-1 > /proc/irq/<IRQ>/smp_affinity_list

14. Lời khuyên

  • Nếu mục tiêu kiểm soát tuyệt đối affinity và số queue: KVM + virtio-net multiqueue (hoặc SR-IOV/PCI passthrough) thường linh hoạt hơn VMware/vmxnet3.
  • Luôn xác nhận bằng effective_affinity thay vì chỉ nhìn smp_affinity.
  • Với VM đông vCPU nhưng ít queue phần cứng, cân nhắc bật RPS có kiểm soát để dàn đều SoftIRQ.
  • Đừng quên tách app khỏi core IRQ bằng taskset/cset; chỉ pin IRQ mà không tách app sẽ dễ tranh tài nguyên.

15. Kết luận

Bài lab cho thấy trong VM vẫn có thể quan sát và điều khiển đường đi của IRQ/SoftIRQ để tách core: gom IRQ/SoftIRQ về một nhóm core (ví dụ CPU0–1) và đẩy ứng dụng sang nhóm core còn lại (CPU2–7). Trên VMware/vmxnet3, cần lưu ý cơ chế managed IRQ khiến effective_affinity có thể khác smp_affinity. Kết hợp pin IRQ, điều chỉnh RPS/XPS và ép app bằng taskset/cset, bạn sẽ có một mô hình lab rõ ràng để đo lường và tối ưu hiệu năng mạng trong môi trường virtual hóa.

Bài viết gần đây

spot_img

Related Stories

Leave A Reply

Please enter your comment!
Please enter your name here

Đăng ký nhận thông tin bài viết qua email