Bagi para network engineer yang membangun high-performance router menggunakan Vector Packet Processing (VPP) bersama kartu jaringan Intel X710, galat Error 11 saat proses booting mungkin sudah tidak asing lagi. Masalah ini sering kali muncul secara acak dan membuat salah satu port kartu X710 “hilang” dari VPP.
Artikel ini merangkum investigasi mendalam mengenai akar permasalahan tersebut secara definitif, membongkar mitos penyebabnya, serta menyajikan solusi bersih tanpa harus melakukan flashing firmware yang berisiko bricked.
1. Gejala dan Dampak
Saat layanan VPP dimulai (start), galat ini muncul di log dengan karakteristik sebagai berikut:
dpdk: PCI_BUS: Unable to reset device! Error: 11 (Resource temporarily unavailable)
dpdk: PCI_BUS: 0000:01:00.0 setup device failed
dpdk: PCI_BUS: Requested device 0000:01:00.0 cannot be used
Frekuensi: Muncul secara acak pada sekitar 10–25% percobaan restart VPP.
Target: Hampir selalu terjadi pada port pertama (0000:01:00.0).
Dampak: VPP tetap berjalan normal, tetapi salah satu antarmuka fisik X710 gagal diinisialisasi oleh DPDK dan tidak muncul di konsol VPP.
2. Akar Masalah Definitif (Terbukti secara Low-Level)
Berdasarkan penelusuran menggunakan kprobe pada kernel Linux, rantai kejadian yang memicu galat ini adalah sebagai berikut:
- Saat VPP melakukan start, DPDK menginisialisasi perangkat dan memanggil fungsi
ioctl(VFIO_DEVICE_RESET). - Di sisi kernel, panggilan ini diteruskan ke
vfio_pci_ioctl_reset()$\rightarrow$pci_try_reset_function()$\rightarrow$pci_dev_trylock(). - Fungsi
pci_dev_trylock()bersifat non-blocking (mengambildevice_trylockdanpci_cfg_access_trylock). Jikadev->mutexsedang dipegang oleh proses lain, fungsi ini langsung gagal dan mengembalikan kode-EAGAIN(Error 11). - DPDK menganggap galat selain
EINVALsebagai kondisi fatal, sehingga perangkat dibatalkan dan port pun hilang.
Siapa Pemegang Mutex Tersebut?
Pelaku di balik layar adalah systemd-journald.
Setiap kali journald memproses pesan kernel dari /dev/kmsg, ia melakukan resolve pada perangkat terkait dan membaca /sys/bus/pci/devices/<bdf>/uevent. Proses pembacaan ini mengambil device_lock() (dev->mutex) yang sama persis dengan yang dibutuhkan oleh proses reset VFIO.
Karena murni masalah timing (irisan waktu dalam orde mikrodetik) dan DPDK selalu memproses fungsi pertama (.0) terlebih dahulu, tabrakan mutex ini hampir selalu terjadi di port pertama.
3. Solusi Utama: Menonaktifkan Pembacaan KMsg pada Journald
Karena akar masalahnya adalah perebutan akses mutex antara pembacaan /dev/kmsg oleh systemd-journald dan perintah reset VFIO oleh DPDK, solusi paling elegan adalah menghentikan pembacaan /dev/kmsg tanpa harus mematikan fungsi Function Level Reset (FLR) perangkat keras.
Cukup buat satu file konfigurasi drop-in untuk journald di /etc/systemd/journald.conf.d/99-vpp-no-kmsg.conf:
[Journal]
ReadKMsg=no
Cara Pemasangan:
mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-vpp-no-kmsg.conf <<'EOF'
[Journal]
ReadKMsg=no
EOF
systemctl daemon-reload
systemctl restart systemd-journald
systemctl restart vpp
Verifikasi:
systemd-analyze cat-config systemd/journald.conf | grep -i ReadKMsg # Pastikan bernilai ReadKMsg=no
vppctl show interface | grep -c TenGigabitEthernet # Pastikan port bernilai 2
journalctl -u vpp --since "-10 min" | grep -c "Unable to reset device" # Harus bernilai 0
Catatan Dampak: Pesan log kernel tidak lagi disimpan secara otomatis ke dalam basis data journal systemd, namun tetap tersedia secara real-time melalui perintah dmesg. Log layanan aplikasi lain (seperti VPP, SSH, dan FRR) tetap tercatat normal di journal.
4. Alternatif Pendekatan (Opsional)
Jika Anda memerlukan log kernel tetap masuk ke journal, terdapat dua alternatif metode lain (pilih salah satu, jangan digabungkan):
Alternatif A: Mematikan Reset VFIO saat Setup (reset_method)
Mengosongkan metode reset membuat ioctl mengembalikan -EINVAL, yang ditoleransi oleh DPDK sehingga tidak memicu galat fatal.
- Konfigurasi Drop-in (
/etc/systemd/system/vpp.service.d/50-no-reset.conf):
[Service]
ExecStartPre=/bin/sh -c 'for f in /sys/bus/pci/devices/0000:01:00.0/reset_method /sys/bus/pci/devices/0000:01:00.1/reset_method; do echo "" > $f; done'
- Trade-off: Perangkat tidak di-FLR sama sekali saat start maupun stop.
Alternatif B: Skrip Guard & Auto-Retry
Memasang skrip pengawas (ExecStartPost) yang mendeteksi jika port X710 belum lengkap, lalu memerintahkan systemd untuk melakukan restart otomatis hingga port siap.
Skrip Pengawas: /usr/local/sbin/vpp-x710-guard.sh
Buat dan simpan file tersebut dengan isi lengkap berikut:
#!/bin/bash
# vpp-x710-guard.sh
#
# Tujuan: mendeteksi kasus "satu port X710 hilang" yang terjadi karena race di
# kernel saat VPP start. Di log VPP muncul:
# dpdk: PCI_BUS: Unable to reset device! Error: 11 (Resource temporarily unavailable)
# dpdk: PCI_BUS: 0000:01:00.0 setup device failed
# dpdk: PCI_BUS: Requested device 0000:01:00.0 cannot be used
#
# Sebabnya: DPDK memanggil VFIO_DEVICE_RESET; di kernel jalur ini memakai
# pci_try_reset_function() yang mengembalikan -EAGAIN bila lock device PCI
# sedang dipegang konteks kernel lain (race, ~20-30% kejadian, hanya bila
# kedua fungsi X710 dipakai). DPDK menganggap ini fatal dan melewati device
# itu, sehingga port hilang.
#
# Skrip ini dipasang sebagai ExecStartPost. Ia menunggu sampai jumlah port X710
# yang diharapkan muncul. Jika sampai timeout belum lengkap, skrip keluar
# non-zero -> systemd (Restart=always) mengulang start VPP sampai port lengkap.
#
# Logika:
# - Selama VPP belum menyajikan interface sama sekali, tunggu sampai WAIT detik
# (menangani VPP yang masih start).
# - Begitu sudah ada >=1 interface, beri GRACE detik agar port lain menyusul.
# Bila setelah GRACE jumlah belum lengkap, anggap race -> gagal cepat.
# Ini membuat deteksi gagal cepat (~GRACE detik) tanpa salah nilai saat VPP
# masih membuat interface satu per satu.
set -u
SOCK=/run/vpp/cli.sock
VPPCTL=/usr/bin/vppctl
WANT=${VPP_X710_GUARD_WANT:-2} # jumlah port X710 yang diharapkan
WAIT=${VPP_X710_GUARD_WAIT:-60} # detik maksimum menunggu VPP muncul
GRACE=${VPP_X710_GUARD_GRACE:-6} # detik tunggu ekstra setelah port pertama muncul
have=0
grace=0
i=0
while [ "$i" -lt "$WAIT" ]; do
have=$("$VPPCTL" -s "$SOCK" show interface 2>/dev/null \
| grep -c 'TenGigabitEthernet')
if [ "$have" -ge "$WANT" ]; then
exit 0
fi
if [ "$have" -ge 1 ]; then
grace=$(( grace + 1 ))
[ "$grace" -ge "$GRACE" ] && break
fi
i=$(( i + 1 ))
sleep 1
done
echo "vpp-x710-guard: port X710 terdeteksi $have, diharapkan $WANT -> minta restart VPP" >&2
exit 1
Buat file systemd override /etc/systemd/system/vpp.service.d/override.conf
Isi:
[Service]
ExecStartPost=/usr/local/sbin/vpp-x710-guard.sh
RestartSec=5
TimeoutStartSec=180
Uji beban (opsional, cepat):
for i in $(seq 1 50); do
systemctl reset-failed vpp >/dev/null 2>&1
systemctl restart vpp >/dev/null 2>&1
for j in $(seq 1 100); do
[ "$(timeout 3 vppctl show interface 2>/dev/null | grep -c TenGigabitEthernet)" -ge 2 ] && break
sleep 0.2
done
printf '.'
done; echo
journalctl -u vpp --since "-5 min" | grep -c "Unable to reset device" # -> 0
Kesimpulan
Galat Error 11 pada inisialisasi DPDK dan X710 bukanlah kerusakan perangkat keras (hardware failure) ataupun cacat fatal pada firmware, melainkan bentrok timing akses mutex kernel akibat aktivitas systemd-journald. Dengan menyetel ReadKMsg=no, sistem operasi terbebas dari race condition, performa dataplane VPP tetap terjaga, dan stabilitas server kembali normal seratus persen.