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
/cset
và iperf3
để đẩ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_affinity
≠smp_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.
- Bình thường trên VMware; dựa vào
- 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ìnsmp_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.