結論としてはRealtek RTL8111Hのr8168ドライバを最新版ビルドして入れれば良い
前提; システム構成
- Host OS: Proxmox VE 8.3.2
- Kernel: 6.8.12-4-pve
- マザーボード: ASRock B550M Pro4
- NIC: Realtek RTL8111Hチップ
# pveversion
pve-manager/8.3.2/3e76eec21c4a14a7 (running kernel: 6.8.12-5-pve)
発生再現
ゲストOS側でUSBパススルーをしたいが、リソースマッピングを簡単にするため単独でIFが欲しく、USB3.0インタフェースPCIeカードをAmazonで適当に買ったので、刺して追加して起動すると、何故かProxmox veが立ち上がると同じタイミングでNICのLINK UPが消失し、LEDすら光らない。
この状態では、管理画面すら入れないので、なにもできなくなる。まず追加USBインターフェースカードを取るとNICはLINK UPしたままの状態が維持される(消失されない)、カードの指すPCIeスロットを変えても挙動に変化なし。
ちなみにProxmox veじゃなくてDebianとかUbuntuでも起こるんじゃないかな。
問題点
そもそもカニさんチップ乗ってるマザーボード使ってる方が悪い。
…とはいえ内蔵NICがこれなんだから仕方ない。なんかどうもaptで勝手に入るデフォルトのr8169
ドライバくんは最新カーネルちゃんと対応できてないらしい。なんじゃそら、NICごときにドライバを手動ビルドとは20年前のdebian woodyでもいじってる気分だ。
-
ip a
でNICが認識されるものの、リンクが確立せず通信不可。 -
dmesg
にr8169
に関連するエラーやリンク確立失敗のログ。
これらがあったらそうかもね. lspci
では以下のように認識されている(この文字列はProxmox ve管理画面のリソースマッピングからも確認できると思う)
# lspci |grep Realtek
07:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 15)
ちゃんとデバイスとしては動いているが以下のように
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp7s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 9c:6b:00:36:e9:27 brd ff:ff:ff:ff:ff:ff
意味不明にDOWNのまま何しても立ち上がらない
# lsmod | grep r816
r8169 110592 0
ドライバは当たってそうな感じを醸し出す(しかしこれはでまかせだ)
マザーボードの設定での回避策
UEFI(BIOS)で, PCIe リソースの自動割り当てを設定したり、Above 4G Decoding
をEnableにする(自動的に伝統的制御を排除するが、そもそもIOMMUによるパススルーを仮想環境上で行うならEnableであるべき、詳しくは↓こちらの記事を参照されたい)
管理画面への迂回ルートを作っとけ
べつにProxmox ve的にはNICを消失しているだけで、起動はちゃんとできている(が管理画面に行けないので困っている)これを回避するため、なんでもいいからUSB-NICをつけておき、NICとして認識させておくと良い。
もちろん物理的にモニタやキーボードをつなげとくのも良いが、ゲストOS側でPCIeパススルーを使ってGPUなどをゲストOS側で占有する場合、ホストOS側の情報は途中で出なくなるし、起動後に乗っ取ることもできないので注意されたい
0. apt update && apt full-upgrade
してもいいかもね
これだけで解決する場合もあるらしい??
1. 既存のr8169ドライバを無効化
r8169ドライバを無効化するため、モジュールをブラックリストに登録
# echo "blacklist r8169" >> /etc/modprobe.d/blacklist.conf
# update-initramfs -u
2. debian標準r8168ドライバを削除
aptではいるr8168-dkms
をremoved.
# apt remove r8168-dkms
# reboot
念の為、再起動後にlsmod
して確認したほうがいいかも。
# lsmod |grep r8168
これ打って何も出なければいいが, 出てくるようなら以下でdkms全消しできる
# dkms remove -m r8168 --all
3. 最新のr8168ドライバをget
ここから先は以下の記事を参考にした
そんでドライバソースだが、公式からダウンロードしてもいいけど、github上でパッケージ配布しているところがあるので、そこのリリースからいま現段階で最新の8.054.00をチョイス。
# wget https://github.com/sbwml/package_kernel_r8168/releases/download/8.054.00/r8168-8.054.00.tar.bz2
# tar -xvf r8168-*.tar.bz2
# cd r8168-8.054.00/
4. /usr/src/へcpしてdkms.confつくる
# mkdir /usr/src/r8168-8.054.00
# cp -v * /usr/src/r8168-8.054.00/
# vi /usr/src/r8168-8.054.00/dkms.conf
当たり前だけどディレクトリ名のバージョン数に注意な
PACKAGE_NAME="r8168"
PACKAGE_VERSION="8.053.00"
BUILT_MODULE_NAME[0]="$PACKAGE_NAME"
DEST_MODULE_LOCATION[0]="/updates/dkms"
AUTOINSTALL="YES"
REMAKE_INITRD="YES"
なんかREMAKE_INITRD
構文が非推奨化したなどNoticeがどっかで出るけど、dkms.confはこのままで問題ない
5. dkms addしてbuildしてinstallしてmodprobe
# dkms add -m r8168 -v 8.054.00
# dkms build -m r8168 -v 8.054.00 -k $(uname -r)
# dkms install -m r8168 -v 8.054.00 -k $(uname -r)
# modprobe r8168
# update-initramfs -u
dkms install
したらmodprobe
相当な動作してると思うけど、あんま信用してないからやっといた。この段階でlsmod
すると
# lsmod |grep r8168
r8168 667648 0
まあなんか入ってるはず。dkms status
でも確認できる;
# dkms status
Deprecated feature: REMAKE_INITRD (/var/lib/dkms/r8168/8.054.00/source/dkms.conf)
r8168/8.054.00, 6.8.12-5-pve, x86_64: installed
ちなみにbuild失敗したとき
# apt install pve-headers-$(uname -r)
なんかこの辺をちゃんといれることで解決するかも
6. 再起動してip a
でインタフェース名を確認する
別に再起動せずとも, ↓これでも良い
# systemctl restart networking
インタフェース名が変わってるかもね。/etc/network/interfaces
あたりを調整して、vmbr0
の物理NIC指定先をちゃんと改めないと行けないはずだぞ。
うちの環境では/etc/network/internfaces
は最終的に、以下のようになった;
auto lo
iface lo inet loopback
# Main NIC: enp7s0 (bridged to vmbr0)
auto enp7s0
iface enp7s0 inet manual
auto vmbr0
iface vmbr0 inet static
address 192.168.100.50/24
gateway 192.168.100.1
bridge-ports enp7s0
bridge-stp off
bridge-fd 0
# Backup USB-NIC: enx5c857e3dddc6 (static IP)
auto enx5c857e3dddc6
iface enx5c857e3dddc6 inet static
address 192.168.100.51/24
source /etc/network/interfaces.d/*
あ、なんか名前引けないとかトラブルでたら、/etc/resolve.conf
に適当に引き先書けばいいよ
# cat /etc/resolv.conf
nameserver 8.8.8.8