Windows」カテゴリーアーカイブ

Hyper-V 上の Linux から GPU を利用する話

どうも、みむらです。

最近は在宅時は NACK5 さんを聞きながら仕事をしていることが増えているのですが、
特に「日常野郎 鬼ガイバー!」と「あまがみ神社」に特にウキウキする今日この頃です。

さてさて。

Hyper-V 上の Linux 上で GPU を使うというのがあります。
主に GPU で機械学習をしたり動画処理したり、私ですと職業柄 hashcat を回してみたり。

色々な記事はあったのですが Linux カーネルを新しめ (執筆時点では 6.8) のもので組むのには、少し手間が掛かってしまったのでここにまとめてみようかと。

なおこの記事は「GPU パーティション分割」機能を用いた構築例となります。
GPU を直接触るものではないため、使い勝手は少し異なりますが、ホスト側と共存して使えるようになるため、個人的にはオススメです。

詳細についてはこのあたりを参照ください:
https://learn.microsoft.com/ja-jp/windows-server/virtualization/hyper-v/gpu-partitioning

今回は、諸事情で Kali Linux (Debian) での紹介となりますが、素のDebian や Ubuntu はもちろん、他のディストリビューションでも転用出来ると思います。


1. ゲスト側の Linux で必要なファイルを WSL2 環境から取り出す

WSL のシステムディストリビューションを起動し、中から必要なファイルを取り出します。

WSL2 はユーザがインストールしたディストリビューション(ユーザディストリビューション)をコンテナとして動かす仕組みになっています。
システムディストリビューションは、それらのコンテナにむけて機能を提供するホストとなっており、WSL が提供する機能のドライバ類はここに入っています。

余談ですが、とくに手を入れていなければ CBL-Mariner が走っています。
https://github.com/microsoft/azurelinux
Azure に馴染みのある方であれば、 “Azure Linux” と呼ばれている軽量な Linux システムとして見たことがあるかたもいらっしゃると思います。

今回ここから取り出すのは、/usr/lib/wsl/lib 以下にあるファイル群になります。


Windows 環境側に作業用フォルダを作り、必要なファイルをコピーして tar を作ります。

なお下記のコマンド例では、作業用フォルダのパスは「 C:\Users\mimura1133\Desktop\work_wsl 」にあるものとします。

方法1:ディスク容量を気にしない場合

この場合はシンプルに
/usr/lib/wsl 以下を tar 固めなどして Windows 環境側に持ち出せばOKです。

ただし、不要なドライバが大量に含まれるため、かなり大きくなります。
(私の環境では 3GB ほどありました)

cd /usr/lib/wsl
cp -R /mnt/(Windows 側作業フォルダまでのパス)/lib.tar.gz lib
cp -R /mnt/(Windows 側作業フォルダまでのパス)/drivers.tar.gz drivers

# コマンド実行例:
# cd /usr/lib/wsl
# bsdtar /mnt/c/Users/mimura1133/Desktop/lib.tar.gz lib
# bsdtar /mnt/c/Users/mimura1133/Desktop/drivers.tar.gz drivers

以上の手順で作成された lib.tar.gz と drivers.tar.gz が後ほど必要になります。

方法2:必要最小限のデータのみを取り出す場合

下記の手順では必要最小限のデータのみを取り出します。
(この方式では、当方環境ですと 1GB 未満になりました)

1. /usr/lib/wsl/lib ディレクトリ以下を取り出す

cd /usr/lib/wsl
cp -R /mnt/(Windows 側作業フォルダまでのパス)/lib.tar.gz lib

# コマンド実行例:
# cd /usr/lib/wsl
# bsdtar zcvf /mnt/c/Users/mimura1133/Desktop/work_wsl/lib.tar.gz lib

2. 現在使用しているグラフィックドライバをコピーする

Windows 側の PowerShell で下記のコマンドを実行して、ドライバを特定します。

Get-CimInstance -ClassName Win32_VideoController -Property * | Format-Table InstalledDisplayDrivers -AutoSize -Wrap

実行例:

上記の例の場合は、 C:\Windows\System32\DriverStore\FileRepository\nv_dispsig.inf_amd64_e6cac7f31a92d62e 以下に必要なファイル群があることが分かります。

上記の結果を用いて、必要なドライバをフォルダごと作業フォルダの “drivers” 以下にコピーします。

# カレントディレクトリ移動
cd C:\Windows\System32\DriverStore\FileRepository
# ドライバをフォルダごとコピー
robocopy /mir (必要なドライバのフォルダ名) (作業フォルダまでのパス)\drivers\(必要なドライバのフォルダ名)
# ini ファイルをコピー
copy (必要なドライバのフォルダ名).ini (作業フォルダまでのパス)\drivers

# コマンド実行例:
# cd C:\Windows\System32\DriverStore\FileRepository
# robocopy /mir nv_dispsig.inf_amd64_e6cac7f31a92d62e C:\Users\mimura1133\Desktop\work_wsl\drivers\nv_dispsig.inf_amd64_e6cac7f31a92d62e
# copy nv_dispsig.inf_amd64_e6cac7f31a92d62e C:\Users\mimura1133\Desktop\work_wsl\drivers

3.ドライバを tar で固める

WSL2 が動く Windows であれば、最初から tar が使えるようになっています。
コマンドプロンプトを用いて下記のコマンドを実行します。

cd (作業フォルダまでのパス)
tar zcvf drivers.tar.gz drivers

実行例:

以上で drivers.tar.gz と lib.tar.gz が出来ました。以降でこれらのファイルが必要になります。


2. Kali Linux をインストールする

通常通りのインストールを実施します。

公式サイトからの VM イメージのダウンロード、iso を用いたインストール、Hyper-V のクイック作成等方法は問いません。

なお、iso からインストールを行う場合は「第2世代」で作成を行ってください。


3. 仮想マシン (VM) の設定を変更する

VMの設定を行います。

既にVM が起動している場合はシャットダウンをおこなった上で
VMの設定画面を開き、いくつか確認を行っていきます。

・セキュアブートが無効になっているか
 ON の場合、後段の dkms 周りで不具合が出る場合があります。

・動的メモリは無効になっているか
 仕組み上動的メモリを有効にすることは出来ないようです。

チェックポイント(スナップショット)は無効になっているか
 これも、本機能有効時には使えないようです。


上記までの設定が終わったら “OK” を押して画面を閉じます。

続けて Powershell を管理者権限で起動し、下記の設定を順に行います。

# VM の情報を取得
$vm = Get-VM -Name "<VM名, ワイルドカードも使えます>"

# GPU の追加
$vm | Add-VMGpuPartitionAdapter

# Memory Mapped I/O 領域の設定
$vm | Set-VM -GuestControlledCacheTypes $true -LowMemoryMappedIoSpace 1GB -HighMemoryMappedIoSpace 32GB

4. VM 内に必要なデータをコピーする

VM を起動し、1つめのステップで作成した lib.tar.gz と drivers.tar.gz を Linux VM 内にコピーします。

※ 2024.06.17 現在、Kali Linux ではこの段階では GUI (Xorg) の起動に失敗します。
後段でGUI 起動が出来るようになりますのでご安心ください。

ファイルのコピーには SCP や curl 等を用いることもできますが、
一番やりやすい方法としては “Copy-VMFile” を用いるのが一番やりやすいかと思います。

管理者権限で起動した PowerShell を用いて下記のように入力します。

# VM の情報を取得。
# (Step 3 で行っている場合は下記コマンドは不要)
$vm = Get-VM -Name "<VM名, ワイルドカードも使えます>"

# ファイルコピー
$vm | Copy-VMFile -FileSource Host -SourcePath .\lib.tar.gz -DestinationPath /
$vm | Copy-VMFile -FileSource Host -SourcePath .\drivers.tar.gz -DestinationPath /

上記手順が完了次第、Linux VM にログインし、
ルート直下に lib.tar.gz と drivers.tar.gz があることを確認します。

(Ctrl + Alt + F1 を押下してログイン画面を表示し、ログインします。)

実行例:


5. コピーした tar.gz ファイルを展開する

コピーしたファイルを VM 内の /usr/lib/wsl 以下に展開します。

# ディレクトリを作成
sudo mkdir /usr/lib/wsl

# lib を展開
sudo tar zxvf lib.tar.gz -C /usr/lib/wsl

# drivers を展開
sudo tar zxvf drivers.tar.gz -C /usr/lib/wsl

# 権限を設定
sudo chmod -R 0555 .

コピー後、下記のようなディレクトリ構造になっていることを確認出来れば OK です。
( nv_dispsig.inf およびそれ以下の部分は、コピーした内容や環境の違いで変わります )


6. コピーしたファイルにパスを通す

下記コマンドを実行しパスを通します。

echo "/usr/lib/wsl/lib" | sudo tee /etc/ld.so.conf.d/ld.wsl.conf
sudo ldconfig

# libcuda.so.1 に関するエラーが出ますが、無視してOKです。

7. カーネルドライバをインストールする

WSL2 に組み込まれているカーネルモードドライバを組み込みます。

この部分のコードは WSL2 のカーネルのソースコードにしかなく、通常、最新のカーネルコードを用いる場合Microsoft 社が公開しているコードでは手入れが必要です。

とても親切なかたがインターネット上にはいらっしゃって、
最新のカーネルで上手く動くようにカスタムして公開してくれています。
https://github.com/Nevuly/WSL2-Linux-Kernel-Rolling

今回はここのコードを用いて、今走っているカーネル向けのドライバを作って入れ込む戦略を採ります。入れ込む部分のコードについても、下記に公開されているものをお借りして進めます。

https://gist.github.com/krzys-h/e2def49966aa42bbd3316dfb794f4d6a


・必要なプログラム・ファイルのインストール

sudo apt install linux-headers-amd64 dkms git

・カーネルモードドライバの作成・インストール

先ほどのサイトからお借りして少し編集したものを下記に示します。
こちらを実行すれば必要なドライバがビルドされてインストールされます。

#!/bin/bash -e

#
# The original version is https://gist.github.com/krzys-h/e2def49966aa42bbd3316dfb794f4d6a
#

if [ "$EUID" -ne 0 ]; then
    echo "Swithing to root..."
    exec sudo $0 "$@"
fi

git clone --depth=1 https://github.com/Nevuly/WSL2-Linux-Kernel-Rolling
cd WSL2-Linux-Kernel-Rolling
VERSION=$(git rev-parse --short HEAD)

cp -r drivers/hv/dxgkrnl /usr/src/dxgkrnl-$VERSION
mkdir -p /usr/src/dxgkrnl-$VERSION/inc/{uapi/misc,linux}
cp include/uapi/misc/d3dkmthk.h /usr/src/dxgkrnl-$VERSION/inc/uapi/misc/d3dkmthk.h
cp include/linux/hyperv.h /usr/src/dxgkrnl-$VERSION/inc/linux/hyperv_dxgkrnl.h
sed -i 's/\$(CONFIG_DXGKRNL)/m/' /usr/src/dxgkrnl-$VERSION/Makefile
sed -i 's#linux/hyperv.h#linux/hyperv_dxgkrnl.h#' /usr/src/dxgkrnl-$VERSION/dxgmodule.c
echo "EXTRA_CFLAGS=-I\$(PWD)/inc" >> /usr/src/dxgkrnl-$VERSION/Makefile

cat > /usr/src/dxgkrnl-$VERSION/dkms.conf <<EOF
PACKAGE_NAME="dxgkrnl"
PACKAGE_VERSION="$VERSION"
BUILT_MODULE_NAME="dxgkrnl"
DEST_MODULE_LOCATION="/kernel/drivers/hv/dxgkrnl/"
AUTOINSTALL="yes"
EOF

dkms add dxgkrnl/$VERSION
dkms build dxgkrnl/$VERSION
dkms install dxgkrnl/$VERSION

また、下記の gist にもアップロードしました。
端末に入れ込む際にダウンロード先として利用頂けたらと思います。

https://gist.github.com/mimura1133/895b2f5f79ca1de1fbd7b0acf10358d6


8. CUDA の環境をインストールする

nvidia-cuda-toolkit のインストールと、ライブラリのリンクの張り替えを行います。

# cuda toolkit のインストール
sudo apt install nvidia-cuda-toolkit

# 不要な追加パッケージの削除
sudo apt remove nvidia-kernel-dkms nvidia-modprobe nvidia-kernel-common

# libcuda.so が cuda toolkit のモノになっているので張り替える。
sudo rm /usr/lib/x86_64-linux-gnu/libcuda.so
sudo rm /usr/lib/x86_64-linux-gnu/libcuda.so.1
sudo ln -s /usr/lib/wsl/lib/libcuda.so /usr/lib/x86_64-linux-gnu/libcuda.so
sudo ln -s /usr/lib/wsl/lib/libcuda.so.1 /usr/lib/x86_64-linux-gnu/libcuda.so.1

ここまで来たら一度再起動を行います。


再起動完了後、nvidia-smi を実行すると下記のような表示となり、
GPU (CUDA) が利用可能な状態になります。

また CUDA を用いるアプリケーションにおいても正常に認識され、 Windows 側のタスクマネージャからも GPU が動作していることが分かります。

CUI で計算を行う範囲で十分であれば、ここで設定は完了となります。
以降は GUI を有効にする場合の手順となります。


(追加) 9. GUI を有効にする

GUI が立ち上がるように設定を入れ込みます。

modesetting ドライバで上手く処理が出来なくなっているのが原因であるため、
BusID とドライバの設定を行い動作するようにします。

内部に露出している PCI の BusID を調べる

一度 xorg を起動して失敗させ、その中のログから調べるのが手っ取り早いです。

# Xorg の起動を試みる。(失敗してエラーが表示されます)
sudo startx

# ログの中から PCI Bus の ID を見つける
grep "PCI" /var/log/Xorg.0.log

# --
# 実行例
# --
grep "PCI" /var/log/Xorg.0.log
[   3.668] (--) PCI:*(0@41715:0:0) 1414:008e:0000:0000 rev 0

上記の実行例の場合、必要になるのはアットマーク以降の “41715:0:0” になります。

調べた BusID を設定に入れる

下記の内容を /etc/X11/xorg.conf.d/hv-fbdev.conf として保存します。

Section "Device"
         Identifier "Card0"
         Driver     "fbdev"
         BusID      "PCI:(上記で見つけた ID)"
EndSection

記入例としては下記のような形になります:

#
# 設定・記入例
#

# sudo vim /etc/X11/xorg.conf.d/hv-fbdev.conf

Section "Device"
         Identifier "Card0"
         Driver     "fbdev"
         BusID      "PCI:41715:0:0"
EndSection

その後、再起動すると GUI が立ち上がってきます。


(追加)10. Kali Linux の Enhanced Mode を有効にする

Enhanced Mode を有効にすることで、クリップボードの共有やスムーズな描画を使えるようにします。

下記ページに従って設定を行った後、追加の設定を行います。
https://www.kali.org/docs/virtualization/install-hyper-v-guest-enhanced-session-mode


kali-tweaks を実行して、初期設定を行う

下記の順番で遷移して設定を行います。
Virtualization → Configure

設定後下記コマンドを入力し、xorg を xrdp を出力先として起動するように設定します。
(先述の 9 で設定した内容と排他になり、Enhanced Mode でのみ GUI が表示されるようになります。)

# Step 9 を実行している場合は、その設定を消去する
sudo rm /etc/X11/xorg.conf.d/hv-fbdev.conf

# xrdp を出力先として起動するように設定する
sudo cp /etc/X11/xrdp/xorg.conf /etc/X11/xorg.conf.d/

設定後 VM をシャットダウンします。

Enhanced Session の接続方式を HVSocket に切替える

管理者権限で起動した PowerShell を用いて、下記のコマンドを実行します。

# VM の情報を取得。
# (Step 3 や 4 で既に実行済みであれば実行不要)
$vm = Get-VM -Name "<VM名, ワイルドカードも使えます>"

$vm | Set-VM -EnhancedSessionTransportType HVSocket

上記が完了したら VM の電源を投入します。

上手く行けば、起動時に下記のようなダイアログが表示されます。

接続を行い、IDとパスワードを入力後、デスクトップが出てくれば完成です。


注意・留意事項等

・マイクロソフト社やその他関連する会社様などから記事の削除・非表示化の指示を受けた場合は予告なく記事を非表示にすることがあります。

・本手法については公式のものではありません。内容に関する質問についてマイクロソフト社やその他の窓口に問い合わせすることはおやめください。また予告なく動作しなくなる場合も考えられます。

・ホスト側のグラフィックドライバの更新などのVM 内のドライバも入れ替える必要がある可能性がある、とのことです(当方環境ではまだ未確認)

執筆に際して参考にした記事など

Hyper-VでGPU(GPU-PV)を利用する方法 (Ubuntu編)
https://qiita.com/Hyper-W/items/5ddfc93891f7b620da8a

Ubuntu 21.04 VM with GPU acceleration under Hyper-V…?
https://gist.github.com/krzys-h/e2def49966aa42bbd3316dfb794f4d6a

GitHub – Nevuly/WSL2-Linux-Kernel-Rolling: Rolling Release Stable Kernel for Windows Subsystem for Linux2 (WSL2)
https://github.com/Nevuly/WSL2-Linux-Kernel-Rolling


検証しながら書いていたら、日が沈んで夜になり、また新たな朝日が昇ってきてしまいました。でもとっても楽しかったのでヨシとします・・!

それではよき GPGPU ライフを VM 内でもお過ごしください!

Jumbo Frame + WinServer 2019 の Hyper-V の通信は妙に遅い。

どうもみむらです。
最近梅雨に入ったのか夏に入ったのか、色々パッとしなくて困る日々が続いております。

先日 Windows Server 2019 (もしくは Hyper-V Server 2019) を Jumbo Frame 環境下で用いると、通信が遅くなるということが分かりましたのでメモがてら。
同じような問題に遭遇した方の一助のとなればありがたいです。


事象:

Windows Server 2019 上の Hyper-V に展開された VM において
RSC (Receive Side Coalescing, Linux では Large Receive Offload で知られている) が有効
かつ VM が Jumbo Frame の環境において、VMから見て受信方向の通信が遅くなる。

注1:Windows Server 2019 では RSC は既定で有効になっています。
注2:MTU が 2850 bytes を上回る ( >2850 ) 場合に速度低下が発生するようです。

原因:

VMSwitch において Reassemble されたパケットが VMに届かなくなる。

回避方法:

RSC を無効にするか MTU を 1500 にする

方法1:ゲスト VM の MTU を 1500 にする。
 例) ip l set mtu 1500 dev eth0

方法2:ホスト側でRSC 機能を VMSwitch 単位で無効にする
 例)Set-VMSwitch (Switch名) -EnableSoftwareRsc $false

方法3:ゲストVM において ethtool 等を用いて “large-receive-offload” を off にする
 Linux) ethtool -K eth0 large-receive-offload off
 Windows) Set-NetAdapterAdvancedProperty “*” -DisplayName “Recv Segment Coalescing” -RegistryValue 0


パケットの気持ちになってみる

最近パケットの気持ちになる、が一部界隈で有名ですので「なってみよう」と思います。

ざっくりと構成は下記の通り。
Hyper-V サーバ内に立てられた VM-01 との通信について Hyper-V サーバの前段のミラー (CAP-01) と VMSwitch のミラー (CAP-02) で通信をキャプチャして挙動を確認しよう、という構成になっています。

なお、各キャプチャは同タイミングでのものではありません。ご了承ください


VM-01 での curl での速度比較

事象を確認するためにまずは curl で適当な通信を発生させて速度を見てみます。

MTU 1500 の場合は Average Speed が 10.7M となっているのに対し
MTU 9000 の場合は Average Speed が 44024 となっています。


MTU 9000 の時の VM-01 のキャプチャ

上記のようになります。

No. 12 において Seq=141, Ack=1409 をサーバに対して返答していますが
その次にやってきたパケット (No.13) は Seq=16897 になっています。
(通常は直前の Ack と同じ番号の Seq が返ってきます)

そのため No.14 において Ack=1409 を再度送信され、
サーバ側からは No.16 において Seq=1409 の返答(再送)が起きてしまっています。


MTU9000 の時の CAP-02 のキャプチャ

上記のようになります。
No. 13 までは先ほどの VM-01 と同じような流れになっています。

ですが No.14 付近から 1474 bytes ではないパケットが流れはじめます。
またそれを境にして、 Ack と Seq の関係が壊れはじめるのも確認が出来ます。

たとえば No.14 は Seq=1409 として 2882 bytes の通信が行われていますが
その後の ACK (No.16) では Ack=1409 として返答が行われていることが分かり、
通信が正常に行われていないことがここから読み取れます。

またこの 1475 bytes でないパケットについては先述の VM-01 のキャプチャにおいては確認出来ず、その後発生した No.25 の Ack に対する No.26 の 1474 bytes の通信が行われて初めて VM-01 側にパケットが到達しているように見受けられます。


MTU9000 の時の CAP-01 のキャプチャ

上記のようになります。

インターネットを介して No.10 ~ No.19 に掛けて勢いよく通信が行われていますが
その後 No.20 において Ack=1 が返され、No.23 において再送が行われています。

この間 Seq は 12673 まで増えており、この No.19 に当該するパケットは先述の CAP-02 においても No.21 として観測できているように見受けられます。


以上の事象、また CAP-02 においてパケットをとり続けると、 reassemble されたパケットが送信された後に再送要求が発生していること、そして RSC を Disable にするとこれらの事象が解決することから RSC (LRO) が原因と判断しました。

また繰り返しではありますが、
Windows Server 2022 (Preview) や Windows 10 (21H1) では発生しないことを確認していますので Windows Server 2019 特有の問題 ( 1809 ベースの Hyper-V 特有? ) と判断しています。


番外:ドライバベースで治せないかやってみる

Linux のドライバは自由に修正したりして実験できますので、
これで何か出来ないかやってみます。

1.そもそも機能を切る:

netvsc の 603 行目に下記のような記述があります
https://github.com/torvalds/linux/blob/master/drivers/net/hyperv/netvsc.c#L603

/* Negotiate NVSP protocol version */
static int negotiate_nvsp_ver(struct hv_device *device,
			      struct netvsc_device *net_device,
			      struct nvsp_message *init_packet,
			      u32 nvsp_ver)
{

/// 省略 ///

	if (nvsp_ver >= NVSP_PROTOCOL_VERSION_61)
		init_packet->msg.v2_msg.send_ndis_config.capability.rsc = 1;

/// 省略 ///

	return ret;
}

この nvsp_ver で Windows Server 2019 とそれ以降の区別を試みましたが
共に NVSP_PROTOCOL_VERSION_61 (0x60001) が返るため、区別は出来ませんでした。

もちろんですが、”init_packet->msg.v2_msg.send_ndis_config.capability.rsc = 0;” とすると RSC の機能が恒久的に無効になります。


2.別パラメータから値を推測する等で値を修正する:

こちらですが、そもそも VMBus 経由での VMQ の割込が来ないため
修正は難しいという形になりました。

Hyper-V のネットワーク通信は下記のようなアーキテクチャになっています。

vmq コンポーネント

引用元 : https://docs.microsoft.com/ja-jp/windows-hardware/drivers/network/vmq-components

親(ホスト)が持つ NetVSP (VMSwitch) に対して VMBus 経由で接続するアーキテクチャになっており、Linux の netvsc ドライバにおいても 1665 行目付近でその接続が行われていることが伺えます。

struct netvsc_device *netvsc_device_add(struct hv_device *device,
				const struct netvsc_device_info *device_info)
{

/// 省略 ///

	/* Enable NAPI handler before init callbacks */
	netif_napi_add(ndev, &net_device->chan_table[0].napi,
		       netvsc_poll, NAPI_POLL_WEIGHT);

	/* Open the channel */
	device->channel->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes);
	ret = vmbus_open(device->channel, netvsc_ring_bytes,
			 netvsc_ring_bytes,  NULL, 0,
			 netvsc_channel_cb, net_device->chan_table);

	if (ret != 0) {
		netdev_err(ndev, "unable to open channel: %d\n", ret);
		goto cleanup;
	}

	/* Channel is opened */
	netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");

	napi_enable(&net_device->chan_table[0].napi);

	/* Connect with the NetVsp */
	ret = netvsc_connect_vsp(device, net_device, device_info);
	if (ret != 0) {
		netdev_err(ndev,
			"unable to connect to NetVSP - %d\n", ret);
		goto close;
	}

/// 省略 ///

}

https://github.com/torvalds/linux/blob/9d31d2338950293ec19d9b095fbaa9030899dcb4/drivers/net/hyperv/netvsc.c#L1648


試しに netvsc_receive 関数を下記のように編集してみると下記のような出力が得られました。

static int netvsc_receive(struct net_device *ndev,
			  struct netvsc_device *net_device,
			  struct netvsc_channel *nvchan,
			  const struct vmpacket_descriptor *desc)
{
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct vmbus_channel *channel = nvchan->channel;
	const struct vmtransfer_page_packet_header *vmxferpage_packet
		= container_of(desc, const struct vmtransfer_page_packet_header, d);
	const struct nvsp_message *nvsp = hv_pkt_data(desc);
	u32 msglen = hv_pkt_datalen(desc);
	u16 q_idx = channel->offermsg.offer.sub_channel_index;
	char *recv_buf = net_device->recv_buf;
	u32 status = NVSP_STAT_SUCCESS;
	int i;
	int count = 0;

  // 下記行を追記
	netif_info(netdevice_ctx, rx_err, ndev, "BUF-SIZE : %u, SEC-SIZE : %u, RSC-PKTLEN %u\n",
    net_device->recv_buf_size, net_device->recv_section_size,
    nvchan->rsc.pktlen);

	/* Ensure packet is big enough to read header fields */
	if (msglen < sizeof(struct nvsp_message_header)) {
		netif_err(net_device_ctx, rx_err, ndev,
			  "invalid nvsp header, length too small: %u\n",
			  msglen);
		return 0;
	}

/// 以下省略 ///

BUF-SIZE が Window Size にちょっと足したもの、SEC-SIZE が MTU にちょっと足したものの値になり、 RSC-PKTLEN がフレームサイズと同じ値を指し示すようです。

RSC-PKTLEN の値は 1474 を示しており、冒頭のパケットキャプチャと同じような感じになっていることが読み取れます。

なお、同じ VM を同じ設定で Windows 10 の上に構築した場合は下記のようになります。

RSC-PKTLEN が十分に大きな値になっており、 RSC にて reassemble されたパケットが受信出来ていることが分かります。

ドライバを追いかけてみたのですが、正しい値が別パラメータに入っていることなどはなく、また NetVSP の割込が来ないため修正は難しいと考えられました。


まとめ

Windows Server 2019 の Hyper-V を使用して VM を作成する場合は

・MTU を 1500 以下に設定して RSO が正常に機能するようにして使う
・Jumbo Frame を有効にしたい場合は RSO を Disable にする

のどちらかで利用しないと、落とし穴があるという話です。

執筆時点の最新版である “10.0.17763.1999” でもこの事象は発生していますので、
お気をつけくださいませ。


P.S.

割と海外のフォーラムだと “RSO を無効にしたら良くなった!” 的なのはちらほら報告されているみたいですね。。修正されたらいいなとぼんやり思ってます。。

https://social.technet.microsoft.com/Forums/en-US/8aa6a88c-ffc8-4ede-abfc-42e746ff5996/windows-server-2019-hyperv-guest-on-windows-server-2019-hyperv-host?forum=winserverhyperv

https://www.doitfixit.com/blog/2020/01/15/slow-network-speed-with-hyper-v-virtual-machines-on-windows-server-server-2019/

コンソールで Optane Memory を有効にする

あけましておめでとうございます。
今年も宜しくお願い致します。

自宅内で Windows Server 2019 が走っているのですが、
大きなデータを保存しておく場所として HDD が搭載されており
これの高速化として “Optane Memory” を使おうとしてみました。

入れてみて、さて有効にしようと画面を開こうとしたところ・・

The Intel Optane memory application ran into a problem と表示される

ということで、起動が出来ません。でも Optane Memory での高速化はしたい。

ただコンソールで Optane Memory の有効化操作を行ったところ
上手く有効になりましたので、今後のメモとしてここに記録します。


記事にあたり:

インテル公式としては、 Windows Server での Optane Memory の動作は保証していないようです。
本番環境に導入するなどして障害が起きてもこちらではカバー出来ませんので、あくまでも実験用やデータが飛んでも問題ない環境でお試しください。

インテル® Optane™メモリー: 購入する前に、主な要件https://www.intel.co.jp/content/www/jp/ja/support/articles/000023994/memory-and-storage/intel-optane-memory.html


1.ドライバを入れる

セットアッププログラムを使用したり、
pnputil コマンド ( 例 : pnputil /add-driver iaStorAC.inf /install ) などでドライバをインストールします。

18.x 系のドライバが必要なため、マザーボードベンダなどで提供されているドライバが古い場合は最新版のドライバを入れておけば大丈夫だと思います。

インテル® Optane™・メモリーを備えたインテル®ラピッド・ストレージ・テクノロジードライバー・インストール・ソフトウェア
https://downloadcenter.intel.com/ja/download/29978

また、ドライバが上手く当たらない場合 (古いバージョンのまま、等) は
devcon.exe を Windows Driver Kit (WDK) から持ってきて更新することも可能です。

DevCon Update – Windows drivers | Microsoft Docs
https://docs.microsoft.com/ja-jp/windows-hardware/drivers/devtest/devcon-update


2. RSTCliPro を用意する

下記のサイトから RSTCliPro.exe をダウンロードし、
当該端末 (今回の私の場合は Windows Server 2019) にコピーしておきます。

インテル® Optane™メモリー向けインテル® RSTCLI Pro
https://downloadcenter.intel.com/ja/download/29986/-Optane-RSTCLI-Pro


3. Optane Memory と 高速化したい HDD の ID を確認する

下記のコマンドを実行します

RstCliPro.exe -I

実行すると下記のようにデバイス一覧が出てきます

そのうち、高速化したいデバイスの ID と Optane Memory の ID を探して控えます。
今回の場合は “0-0-5-0” が高速化したいデバイスで、 “0-1-0-0” が Optane Memory の ID になります。


4. Optane Memory を有効化する

先ほどメモをした ID を元に次のようなコマンドを実行します。

RstCliPro --OptaneMemory --enable --fast-drive <Optane MemoryのID> --drive-to-accel <高速化したいドライブ>

私の場合は、
“RstCliPro.exe –OptaneMemory –enable –fast-drive 0-1-0-0 –drive-to-accel 0-0-5-0”
というコマンドになります。

実行して “Enable completed” と出れば OK です。


以上で設定は完了です。

上記が完了した後 “RstCliPro.exe –OptaneMemory –info” を実行することで設定内容を確認することも可能です。

というわけで、素敵な Optane Memory ライフを!

PrimoCache を使って Intel の最新チップセットでも HDD を SSD を使って高速化する

どうもみむらです。
先日 PC が故障しまして第9世代の Intel CPU (i7-9700) を用いて組み直していました。

故障する数日前からビープ音(長音)の連続で起動に失敗したりしていたので
なんか気持ち悪いなとは思っていたのですが。。

テレワークが推奨されており、お仕事に甚大な影響が出ることもありましたので
ツクモ電機さんのレジの横にあるリーダーにクレジットカードをシャコシャコッと何度も差し入れしてきました。。来月の引き落としに今から震えています。

ただ今回買い換えを行ってみて
Intel Smart Response Technology (iSRT, HDD を SSD キャッシュで高速化するやつ) が
Intel Optane Memory との組み合わせ専用かつ、RAID 不可に変更
されており
iSRT を使って RAID-5 を高速化していた身としてはかなりショックでした。。

では iSRT の代替としていいものは無いのかと探していたところ
PrimoCacheという良さそうなものを見つけたので試してみました。


PrimoCacheとは

HDD を SSD でキャッシュして高速化するソフトです。
まさしく Intel の Smart Response Technology で実現していたものを実現してくれます。

ほかにも FuzeDrive (AMD 環境では StoreMI という名前で提供されています) というソフトなどもありますが、いくつか試してみたところ PrimoCache がよさそうな感じでした。

PrimoCache は Romex Software 社の製品で、1つ当たり $29.95 の製品になっています。
https://www.romexsoftware.com/en-us/primo-cache/

なお私自身はメーカーさんから
今回の記事に関して何か支援を受けてはいませんのであしからず。。

PrimoCache の設定をする

左上のボタンを押してドライブを追加します。

図3 : ドライブの追加ボタン

次の画面で「高速化したいドライブ」を選択します。

図4: 高速化したいドライブを設定。今回は Intel RAID 1 ドライブ。

次にキャッシュの方法についての設定です。
Level-1 Cache が “DRAM 上” のキャッシュ、 Level-2 Cache がストレージとなります。

またキャッシュについては文字通り Level1, Level2 の階層構造になっています。

今回の場合は SSD キャッシュのみを有効にするため、
Level-1 Cache は 0MB に設定します。

図5: Level-1 Cache を 0MBに設定する

次に Level-2 Cache を設定するために、画面中央の小さなボタンを押下します。

図6: Level-2 Cache の設定ボタン

ボタンを押下すると次のような画面が表示され
キャッシュ用のドライブを選択する画面になります。

今回は Intel Optane Memory を使うため
INTEL MEMPEK.. で始まるドライブを選択します。

注:もちろん Intel Optane Memory を使わずに通常の SSD でも利用可能です。
注2:認識されている容量が小さい場合は何らかのパーティションを作ってから再試行してみてください。

図7: キャッシュ用ドライブを設定している図¥

設定後、 “Size” を “MAX” に変更し、その横にあるボタンを押下します。

図8: キャッシュ設定を行う

特に何もなければ
“Individual Read/Write Cache Space” のチェックを無効にします。

これが ON の時はそれぞれのキャッシュが設定した割合で行われますが
無効の場合は割合を気にせずに Read / Write キャッシュを行うようになります。

図9: Read/Write Cache の割振設定を無効にする。

最後にお好みで Defer-Write (遅延書き込み) の設定を行います。

遅延書き込みを有効にすると応答速度が速くなりますが、
ディスクへの書き込み(キャッシュ内容の反映)が遅くなります。

図10: 設定がほぼ完了した図

設定が完了したら “Start” を押下します。

画面UI について

稼働を始めると下記のようにキャッシュ率などが表示されます。

図11: 稼働が開始した画面

ある程度動きはじめたら、画面を閉じて仕事に戻りましょう。


冒頭のとおり PC の故障で買い替えたところ
Intel RAID 構成に対する SSD キャッシュが使えなくなって呆然としていたところ
こういうソフトを見つけることができてよかったです。。!

また前回の構成では Intel RAID の RAID-5 だったのですが
iSRT が有効な環境だと最新のマザーボードや mdadm ではマウントできず焦りましたが
dmraid を使うことでマウントができました。

PrimoCache の場合は Intel RAID と SSD Cache が別の機構なため
同じようにマウントできなくなることは(きっと)ないと思いますし安心です・・!

ではでは、素敵なテレワークライフを!

Ubuntu 19.10 で Hyper-V の Enhanced Mode を有効にする (Enable the Enhanced Mode with Ubuntu 19.10)

どうもみむらです。

Ubuntu を Hyper-V で使用していると、
起動時に高確率で GUI 起動待ちになって何も操作できなくなったり
( Ctrl + Alt + Function Key での切り替えしてもログイン画面が出てこない )
そもそも Enhanced Mode が使えなくて色々と不便でしたので、
有効にするスクリプトを作成しました。


Hi I’m Mimura.

I make a script to enable the “Enhanced Mode” on Hyper-V with “Ubuntu 19.10”.
Also, it fix an issue that to fail to start X.


Script:

下記からダウンロードできます。 / you can download from this link:
https://gist.github.com/mimura1133/a6aebf4945b6688d1a5aedffdfa9368c


How does it works / どういう仕組みか:

このスクリプトは、
Microsoft が提供している Enhanced Mode を有効にするスクリプトを元に
作成されています。

https://github.com/microsoft/linux-vm-tools/tree/master/ubuntu/18.04

最近の Ubuntu では Wayland を最初に使用しようと試みます。

上記のスクリプトでは、 Xorg を使うようにできているため、
Wayland を利用しないようにする処理を追加し、
Enhanced Mode を Xorg 経由で使えるようにしました。

# Stop to use wayland.
sed -i_orig -e 's/#WaylandEnable=false/WaylandEnable=false/g' /etc/gdm3/custom.conf

また、どうやら Ubuntu に入っている Wayland と Hyper-V が相性が悪いらしく
時々起動に失敗する(コンソール経由のログインも受け付けない状態になる)のですが
Wayland を無効にすることで、確実に起動できるようにもなります。

(Arch Linux に入れたときには上手く動いていたので、 Ubuntu の問題だと個人的には思ってます..)


this script based on Microsoft’s.
https://github.com/microsoft/linux-vm-tools/tree/master/ubuntu/18.04

Recent versions of ubuntu are try to use a Wayland before using Xorg.
So, I added a code to disable to use Wayland.

# Stop to use wayland.
sed -i_orig -e 's/#WaylandEnable=false/WaylandEnable=false/g' /etc/gdm3/custom.conf

In addition, the Wayland and Hyper-V seem to be incompatible, sometimes fail to boot,
but the issue is fixed at the same time by disabling wayland.


Ubuntu の最新版が Enhanced Mode でサクサク動いて、コピペも出来るようになりますし、
同じように Kal Linux でも Enhanced Mode が使えるようにするものも公開していますので
Linux を Hyper-V で使っている方は、是非お試しくださいませー。

I have also released another versions for Kali Linux.
Please feel free to use the script if you’re using Linux on Hyper-V.

Git Repository (Forked from Microsoft):
https://github.com/mimura1133/linux-vm-tools