🏗️

WSL2にOpen vSwitchをインストール(カーネル再構築)

2022/07/11に公開

はじめに

WSL2(Ubuntu22.04)にOpen vSwitchをインストールしたときの備忘録です。

aptでOpen vSwitchパッケージインストール

Open vSwitchは普通のUbuntu22.04であればaptコマンドでインストールできます。
WSL2のUbuntu22.04でもパッケージのインストール自体は行えます。
Open vSwitchの基本機能であるL2スイッチ機能を使うには(若干冗長な名前の気もしますが)openvswitch-switchという名前のパッケージをインストールします。

apt install -y openvswitch-switch
詳細なコンソールログはこちら
# apt install openvswitch-switch
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following package was automatically installed and is no longer required:
  libffi7
Use 'apt autoremove' to remove it.
The following additional packages will be installed:
  libevent-2.1-7 libunbound8 openvswitch-common python3-openvswitch python3-sortedcontainers
Suggested packages:
  openvswitch-doc python-sortedcontainers-doc
The following NEW packages will be installed:
  libevent-2.1-7 libunbound8 openvswitch-common openvswitch-switch python3-openvswitch python3-sortedcontainers
0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
Need to get 3135 kB of archives.
After this operation, 9856 kB of additional disk space will be used.
Do you want to continue? [Y/n]
Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 libevent-2.1-7 amd64 2.1.12-stable-1build3 [148 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/main amd64 libunbound8 amd64 1.13.1-1ubuntu5 [394 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy/main amd64 python3-sortedcontainers all 2.1.0-2 [27.3 kB]
Get:4 http://archive.ubuntu.com/ubuntu jammy/main amd64 openvswitch-common amd64 2.17.0-0ubuntu1 [930 kB]
Get:5 http://archive.ubuntu.com/ubuntu jammy/main amd64 python3-openvswitch all 2.17.0-0ubuntu1 [99.8 kB]
Get:6 http://archive.ubuntu.com/ubuntu jammy/main amd64 openvswitch-switch amd64 2.17.0-0ubuntu1 [1535 kB]
Fetched 3135 kB in 2s (1530 kB/s)
Selecting previously unselected package libevent-2.1-7:amd64.
(Reading database ... 34681 files and directories currently installed.)
Preparing to unpack .../0-libevent-2.1-7_2.1.12-stable-1build3_amd64.deb ...
Unpacking libevent-2.1-7:amd64 (2.1.12-stable-1build3) ...
Selecting previously unselected package libunbound8:amd64.
Preparing to unpack .../1-libunbound8_1.13.1-1ubuntu5_amd64.deb ...
Unpacking libunbound8:amd64 (1.13.1-1ubuntu5) ...
Selecting previously unselected package python3-sortedcontainers.
Preparing to unpack .../2-python3-sortedcontainers_2.1.0-2_all.deb ...
Unpacking python3-sortedcontainers (2.1.0-2) ...
Selecting previously unselected package openvswitch-common.
Preparing to unpack .../3-openvswitch-common_2.17.0-0ubuntu1_amd64.deb ...
Unpacking openvswitch-common (2.17.0-0ubuntu1) ...
Selecting previously unselected package python3-openvswitch.
Preparing to unpack .../4-python3-openvswitch_2.17.0-0ubuntu1_all.deb ...
Unpacking python3-openvswitch (2.17.0-0ubuntu1) ...
Selecting previously unselected package openvswitch-switch.
Preparing to unpack .../5-openvswitch-switch_2.17.0-0ubuntu1_amd64.deb ...
Unpacking openvswitch-switch (2.17.0-0ubuntu1) ...
Setting up python3-sortedcontainers (2.1.0-2) ...
Setting up python3-openvswitch (2.17.0-0ubuntu1) ...
Setting up libevent-2.1-7:amd64 (2.1.12-stable-1build3) ...
Setting up libunbound8:amd64 (1.13.1-1ubuntu5) ...
Setting up openvswitch-common (2.17.0-0ubuntu1) ...
Setting up openvswitch-switch (2.17.0-0ubuntu1) ...
update-alternatives: using /usr/lib/openvswitch-switch/ovs-vswitchd to provide /usr/sbin/ovs-vswitchd (ovs-vswitchd) in auto mode
Created symlink /etc/systemd/system/multi-user.target.wants/openvswitch-switch.service → /lib/systemd/system/openvswitch-switch.service.
Created symlink /etc/systemd/system/openvswitch-switch.service.requires/ovs-record-hostname.service → /lib/systemd/system/ovs-record-hostname.service.
invoke-rc.d: could not determine current runlevel
Processing triggers for man-db (2.10.2-1) ...
Processing triggers for libc-bin (2.35-0ubuntu3) ...
Scanning processes...
Scanning processor microcode...
Scanning linux images...

Failed to retrieve available kernel versions.

Failed to check for processor microcode upgrades.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

状態確認

ovs-vsctlコマンド確認

Open vSwitchで管理されているBridge(L2スイッチ)の一覧を取得するにはovs-vsctl showコマンドを打ちます。まだBridgeは何も作っていないのですが、「Bridgeがない」ことは分かるはずなのでコマンドを打ってみます。

# ovs-vsctl show
ovs-vsctl: unix:/var/run/openvswitch/db.sock: database connection failed (No such file or directory)

データベースに接続できないというエラーが出ています。「Bridgeがない」かどうかも分からない状態です。

Open vSwitchが正常に動作しているときはovs-vswitchdとovsdb-serverというプロセスが立ち上がっています。ovs-vswitchdはBridge(仮想L2スイッチ)自体を提供するデーモンで、ovsdb-serverはovs-vswitchdに必要なデータ(ブリッジ、ポートの情報)を提供するデーモンです。

プロセス起動確認

これらのプロセスが起動している確認します。

# ps -e | grep ovs
#

起動していません。
ovs-vswitchdとovsdb-serverの状態を確認しようとsystemctlを使ったところ、別のエラーが出ました。
普通のUbuntuではsystemdがovs-vswitchd、ovsdb-serverを含む多くのデーモンを起動、制御するのですが、WSLではsystemdが有効になっていません。

# systemctl status ovs-vswitchd
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
# systemctl status ovsdb-server
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

systemdの有効化とプロセス起動

Ubuntu22.04からsystemdの試験的なサポートが始まっています。
Ubuntuのターミナルで/etc/wsl.confに起動にsystemdを起動する設定を追加します。

echo -e '[boot]\ncommand=/usr/libexec/wsl-systemd' | tee -a /etc/wsl.conf
# cat /etc/wsl.conf
[user]
default=root
[boot]
command=/usr/libexec/wsl-systemd

コマンドプロンプトでUbuntu(WSL)を終了してから、スタートメニューでUbuntuを再び起動します。

C:\Users\user01>wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2

C:\Users\user01>wsl -t Ubuntu

C:\Users\user01>wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Stopped         2

C:\Users\user01>

systemdはLinuxシステムが起動するときに一番最初にProcess ID 1で起動することを前提にしているのですが、WSLではProcess ID 1はsystemdではなくて、initプロセスです。
そこでwsl-systemdはPID namespaceという機能を使い、デフォルトのPID namespaceとは別のPID namespaceを作り出してsystemdを起動することで、その中ではsystemdがProcess ID 1であるかのように見せています。

以下が本来の(デフォルトの)PID namespaceでのpsコマンド
PID=1はinit
PID=17がsystemd

# ps -e
    PID TTY          TIME CMD
      1 ?        00:00:00 init
     11 ?        00:00:00 init
     13 ?        00:00:00 init
     15 ?        00:00:00 unshare
     16 pts/0    00:00:00 bash
     17 ?        00:00:01 systemd
     72 ?        00:00:00 systemd-journal
    107 ?        00:00:00 systemd-udevd
    142 ?        00:00:00 systemd-network
    146 ?        00:00:02 dbus-daemon
    148 ?        00:00:00 networkd-dispat
    150 ?        00:00:01 polkitd
    151 ?        00:00:00 rsyslogd
    156 ?        00:00:00 systemd-logind
    189 ?        00:00:00 ModemManager
    247 ?        00:00:00 systemd-resolve
    307 ?        00:00:01 ovsdb-server
    462 ?        00:00:00 cron
    465 ?        00:00:00 unattended-upgr
    469 tty1     00:00:00 agetty
    472 ?        00:00:00 agetty
    480 ?        00:00:00 sshd
    724 ?        00:00:00 snapfuse
    847 ?        00:00:02 snapd
    941 ?        00:00:00 snapfuse
   1008 ?        00:00:00 snapfuse
   1587 ?        00:00:00 init
   1588 ?        00:00:00 init
   1591 pts/1    00:00:00 bash
   1728 pts/0    00:00:00 nslogin
   1729 pts/0    00:00:00 bash
   5427 ?        00:00:00 init
   5428 ?        00:00:00 init
   5430 pts/2    00:00:00 bash
   5487 pts/2    00:00:00 ps

PID=17のプロセスと同じ名前空間に入ってコマンドを打つことができます。
この名前空間に入って中から見るとPID=1のプロセスはsystemdであるように見えます。

# nsenter --target 17 -p -m ps -e
    PID TTY          TIME CMD
      1 ?        00:00:01 systemd
     42 ?        00:00:00 systemd-journal
     77 ?        00:00:00 systemd-udevd
    112 ?        00:00:00 systemd-network
    116 ?        00:00:02 dbus-daemon
    118 ?        00:00:00 networkd-dispat
    120 ?        00:00:01 polkitd
    121 ?        00:00:00 rsyslogd
    126 ?        00:00:00 systemd-logind
    159 ?        00:00:00 ModemManager
    217 ?        00:00:00 systemd-resolve
    277 ?        00:00:01 ovsdb-server
    432 ?        00:00:00 cron
    435 ?        00:00:00 unattended-upgr
    439 tty1     00:00:00 agetty
    442 ?        00:00:00 agetty
    450 ?        00:00:00 sshd
    694 ?        00:00:00 snapfuse
    817 ?        00:00:02 snapd
    911 ?        00:00:00 snapfuse
    978 ?        00:00:00 snapfuse
   1496 pts/0    00:00:00 bash
   5169 pts/2    00:00:00 ps

wsl-setupパッケージに入っている/usr/libexec/nsloginが(たぶん)上記と同じようなことをしています。
/usr/libexec/nsloginと引数なしで打つとBashを起動してsystemdと同じ名前空間に入るので、そのBashでsystemctlを打ってもよいですし、/usr/libexec/nslogin systemctl status ovs-vswitchdと引数付きで打ってもよいです。

# /usr/libexec/nslogin
# systemctl status ovs-vswitchd
× ovs-vswitchd.service - Open vSwitch Forwarding Unit
     Loaded: loaded (/lib/systemd/system/ovs-vswitchd.service; static)
     Active: failed (Result: exit-code) since Sun 2022-07-10 14:37:50 JST; 6h ago

Jul 10 14:37:50 DESKTOP-QUCRLP5 systemd[1]: ovs-vswitchd.service: Scheduled restart job, restart counter is at 5.
Jul 10 14:37:50 DESKTOP-QUCRLP5 systemd[1]: Stopped Open vSwitch Forwarding Unit.
Jul 10 14:37:50 DESKTOP-QUCRLP5 systemd[1]: ovs-vswitchd.service: Start request repeated too quickly.
Jul 10 14:37:50 DESKTOP-QUCRLP5 systemd[1]: ovs-vswitchd.service: Failed with result 'exit-code'.
Jul 10 14:37:50 DESKTOP-QUCRLP5 systemd[1]: Failed to start Open vSwitch Forwarding Unit.
# systemctl status ovsdb-server
● ovsdb-server.service - Open vSwitch Database Unit
     Loaded: loaded (/lib/systemd/system/ovsdb-server.service; static)
     Active: active (running) since Sun 2022-07-10 14:37:49 JST; 6h ago
   Main PID: 277 (ovsdb-server)
      Tasks: 1 (limit: 2295)
     Memory: 12.1M
     CGroup: /system.slice/ovsdb-server.service
             └─277 ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/ru>

Jul 10 14:37:48 DESKTOP-QUCRLP5 systemd[1]: Starting Open vSwitch Database Unit...
Jul 10 14:37:48 DESKTOP-QUCRLP5 ovs-ctl[81]:  * /etc/openvswitch/conf.db does not exist
Jul 10 14:37:49 DESKTOP-QUCRLP5 ovs-ctl[81]:  * Creating empty database /etc/openvswitch/conf.db
Jul 10 14:37:49 DESKTOP-QUCRLP5 ovs-ctl[81]:  * Starting ovsdb-server
Jul 10 14:37:49 DESKTOP-QUCRLP5 ovs-vsctl[278]: ovs|00001|vsctl|INFO|Called as ovs-vsctl --no-wait -- init -- set Open_>
Jul 10 14:37:49 DESKTOP-QUCRLP5 ovs-vsctl[285]: ovs|00001|vsctl|INFO|Called as ovs-vsctl --no-wait set Open_vSwitch . o>
Jul 10 14:37:49 DESKTOP-QUCRLP5 ovs-ctl[81]:  * Configuring Open vSwitch system IDs
Jul 10 14:37:49 DESKTOP-QUCRLP5 ovs-ctl[81]:  * Enabling remote OVSDB managers
Jul 10 14:37:49 DESKTOP-QUCRLP5 systemd[1]: Started Open vSwitch Database Unit.

ovs-vswitchdはActive: failed (Result: exit-code)となっていて起動に失敗しています。
ovsdb-serverはActive: active (running)になっているので起動はしてますね。

ovs-vswitchd起動エラー原因の調査

# journalctl -u ovs-vswitchd
Jul 10 14:37:49 systemd[1]: Starting Open vSwitch Forwarding Unit...
Jul 10 14:37:49 ovs-ctl[339]: modprobe: FATAL: Module openvswitch not found in d
irectory /lib/modules/5.10.16.3-microsoft-standard-WSL2
Jul 10 14:37:49 ovs-ctl[324]:  * Inserting openvswitch module
Jul 10 14:37:49 ovs-ctl[344]: rmmod: ERROR: ../libkmod/libkmod-module.c:1941 kmo
d_module_get_holders() could not open '/sys/module/bridge/holders': No such file
 or directory
Jul 10 14:37:49 ovs-ctl[344]: rmmod: ERROR: Module unloading is not supported
Jul 10 14:37:49 ovs-ctl[324]:  * removing bridge module
Jul 10 14:37:49 systemd[1]: ovs-vswitchd.service: Control process exited, code=e
xited, status=1/FAILURE
Jul 10 14:37:49 systemd[1]: ovs-vswitchd.service: Failed with result 'exit-code'
.
Jul 10 14:37:49 systemd[1]: Failed to start Open vSwitch Forwarding Unit.
Jul 10 14:37:49 systemd[1]: ovs-vswitchd.service: Scheduled restart job, restart
 counter is at 1.
Jul 10 14:37:49 systemd[1]: Stopped Open vSwitch Forwarding Unit.

modprobeでopenvswitchモジュールのロードに失敗しているのと、rmmodでbridgeモジュールのアンロードに失敗しています。
linuxでは一般的に「/lib/modules/カーネルバージョン」ディレクトリにカーネルモジュールが入って言います。ところがこのフォルダをみても空っぽです。

# ls /lib/modules/`uname -r`
ls: cannot access '/lib/modules/5.10.16.3-microsoft-standard-WSL2': No such file or directory
# ls /lib/modules/
# 

どうやらWSLはカーネルの各機能をモジュール化せずにビルトインでもっているみたい。
そしてカーネル本体にOpen vSwitch機能をビルトインしていないためにOpen vSwitchが利用できないようになっています。

そのため、WSLのカーネル再構築を行ってopenvswitchモジュールを有効にします。

カーネル再構築

再構築に必要なツールのインストール

apt update
apt install -y build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool

MicrosoftのWSLカーネルソースをダウンロード

cd /usr/src/
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git

現在のカーネルバージョンの確認

使用中のWSLのカーネルバージョンを確認します。
以下だと「5.10.16.3」であると分かります。

# uname -r
5.10.16.3-microsoft-standard-WSL2

ダウンロードしたWSLカーネルソースのバージョンを使用中のバージョンに合わせる。

以下のサイトに行って、使用中のバージョンに一番近いタグを探します。

https://github.com/microsoft/WSL2-Linux-Kernel

もしくはダウンロードしたソースコードのtag一覧から検索することもできます。「linux-msft-wsl-5.10.16.3」がおそらく使用中のカーネルの元になったものでしょう。

# cd /usr/src/WSL2-Linux-Kernel/
# git tag | grep 5.10
linux-msft-wsl-5.10.102.1
linux-msft-wsl-5.10.16.3
linux-msft-wsl-5.10.43.3
linux-msft-wsl-5.10.60.1
linux-msft-wsl-5.10.74.3
linux-msft-wsl-5.10.81.1
linux-msft-wsl-5.10.93.2
v2.6.25.10
v2.6.35.10
v3.15.10
v4.15.10

git checkout refs/tags/タグ名でソースコードバージョンを切り替えます。

git checkout refs/tags/linux-msft-wsl-5.10.16.3

ベース設定コンフィグ

カーネル再構築の設定ファイルの元ネタを持ってきます。
以下のどちらかを使います。

  • 使用中カーネルの設定ファイル
  • Gitレポジトリの設定ファイル

まずはファイルを比較してみます。同一ファイルであれば特に悩む必要はないのでどちらかを.configファイルにコピーすれば大丈夫です。違っている場合は何が違うのか調べながら悩んでください。

# md5sum Microsoft/config-wsl <(zcat /proc/config.gz)
c9a89fbd968ffbc564438fdfde909434  Microsoft/config-wsl
c9a89fbd968ffbc564438fdfde909434  /dev/fd/63
# diff Microsoft/config-wsl <(zcat /proc/config.gz)
#

使用中カーネルの設定ファイルを元にする場合

zcat /proc/config.gz > .config

Gitレポジトリの設定ファイルを元にする場合

cp Microsoft/config-wsl .config

カーネル設定

CUIの設定画面を立ち上げます。

make menuconfig

Networking supportを選択

Networking optionsを選択

Open vSwitchが「 」(exclude)で無効化されているので、キーボードの「m」を押して「M」(module)にします。

以上が必須の設定。
以下は必要に応じて。

Exitを2回押して、トップに戻ってから「General setup」

Local versionに「-microsoft-standard-WSL2」という設定値が入っています。

これを書き換えることでuname -rで出力されるカーネルリリース名を変えることができます。

トップでExitすると設定を保存するか確認されるので、Yesを押します。設定値は.configファイルに書き込まれます。

ちなみに古いOpen vSwitchのドキュメントには、Open vSwitchを使う間はBridgeをアンロードして無効にするために、(ビルトインではなくて)モジュールにする必要があると書いてあります。

The Open vSwitch datapath requires bridging support (CONFIG_BRIDGE) to be built as a kernel module. (This is common in kernels provided by Linux distributions.) The bridge module must not be loaded or in use. If the bridge module is running (check with "lsmod | grep bridge"), you must remove it ("rmmod bridge") before starting the datapath.

新しいドキュメントではこの記述が消えているのでBridgeはビルトインのままにしました。(モジュールにしても問題ないと思う)
ちなみに、このBridge機能はmenuconfigでは「802.1d Ethernet Bridging」という名前です。モジュール化する際のご参考まで。

一応設定ファイル差分にざっと目を通しておきます。

# diff -u Microsoft/config-wsl .config
--- Microsoft/config-wsl        2022-07-11 00:51:07.601296700 +0900
+++ .config     2022-07-11 00:53:59.391296700 +0900
@@ -2,13 +2,16 @@
 # Automatically generated file; DO NOT EDIT.
 # Linux/x86 5.10.16.3 Kernel Configuration
 #
-CONFIG_CC_VERSION_TEXT="x86_64-msft-linux-gcc (GCC) 9.3.0"
+CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 11.2.0-19ubuntu1) 11.2.0"
 CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=90300
-CONFIG_LD_VERSION=234000000
+CONFIG_GCC_VERSION=110200
+CONFIG_LD_VERSION=238000000
 CONFIG_CLANG_VERSION=0
 CONFIG_LLD_VERSION=0
+CONFIG_CC_CAN_LINK=y
+CONFIG_CC_CAN_LINK_STATIC=y
 CONFIG_CC_HAS_ASM_GOTO=y
+CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
 CONFIG_CC_HAS_ASM_INLINE=y
 CONFIG_IRQ_WORK=y
 CONFIG_BUILDTIME_TABLE_SORT=y
@@ -19,7 +22,7 @@
 #
 CONFIG_INIT_ENV_ARG_LIMIT=32
 # CONFIG_COMPILE_TEST is not set
-CONFIG_LOCALVERSION="-microsoft-standard-WSL2"
+CONFIG_LOCALVERSION="-microsoft-standard-WSL2-ovs"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_BUILD_SALT=""
 CONFIG_HAVE_KERNEL_GZIP=y
@@ -1406,15 +1409,19 @@
 # CONFIG_DCB is not set
 CONFIG_DNS_RESOLVER=y
 # CONFIG_BATMAN_ADV is not set
-# CONFIG_OPENVSWITCH is not set
+CONFIG_OPENVSWITCH=m
+CONFIG_OPENVSWITCH_VXLAN=m
+CONFIG_OPENVSWITCH_GENEVE=m
 CONFIG_VSOCKETS=y
 CONFIG_VSOCKETS_DIAG=y
 # CONFIG_VSOCKETS_LOOPBACK is not set
 # CONFIG_VIRTIO_VSOCKETS is not set
 CONFIG_HYPERV_VSOCKETS=y
 CONFIG_NETLINK_DIAG=y
-# CONFIG_MPLS is not set
-# CONFIG_NET_NSH is not set
+CONFIG_MPLS=y
+CONFIG_NET_MPLS_GSO=m
+# CONFIG_MPLS_ROUTING is not set
+CONFIG_NET_NSH=m
 # CONFIG_HSR is not set
 CONFIG_NET_SWITCHDEV=y
 CONFIG_NET_L3_MASTER_DEV=y
@@ -3245,6 +3252,8 @@
 CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
 # CONFIG_UBSAN is not set
 CONFIG_HAVE_ARCH_KCSAN=y
+CONFIG_HAVE_KCSAN_COMPILER=y
+# CONFIG_KCSAN is not set
 # end of Generic Kernel Debugging Instruments

 CONFIG_DEBUG_KERNEL=y

コンパイル

いよいよコンパイルです。
並列度を(CPUコア数+1)にしてコンパイルし、出来上がったモジュールのインストールを行います。
コンパイルはそれなりに時間かかります。Core i7-12700(12コア)のうち仮想2コアを使用して13分かかりました。
make modules_installはすぐ終わります。その後、カーネル再構築では一般的にはmake installでカーネルを/boot/にインストールしますが、WSLでは必要ないです。

jobs=$(($(cat /proc/cpuinfo | grep processor | wc -l)+1))
time make -j $jobs
make modules_install

結果の確認

モジュールのインストール先の確認

# find /lib/modules
/lib/modules
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.builtin.modinfo
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.symbols.bin
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.devname
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.order
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.alias.bin
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/source
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.builtin.alias.bin
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.dep.bin
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.softdep
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.builtin
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.builtin.bin
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.dep
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/build
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.alias
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/openvswitch
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/openvswitch/openvswitch.ko
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/openvswitch/vport-vxlan.ko
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/openvswitch/vport-geneve.ko
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/mpls
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/mpls/mpls_gso.ko
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/nsh
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/kernel/net/nsh/nsh.ko
/lib/modules/5.10.16.3-microsoft-standard-WSL2-ovs+/modules.symbols

WSL側の設定

vmlinuxをWindows側のファイルシステムに置きます。
C:\Users\ユーザ名\.wslconfigファイルを作成して、上記vmlinuxを使うように設定します。(この設定はWSLグローバルなので、複数のWSL環境を使っている場合はすべての環境に影響します)

winuser=$(cmd.exe /c "echo %USERNAME%" 2> /dev/null | tr -d '\012\015')
echo $winuser
mkdir /mnt/c/Users/$winuser/wsl2/
cp vmlinux /mnt/c/Users/$winuser/wsl2/
echo  -e '[wsl2]\nkernel = C:\\\\Users\\\\'$winuser'\\\\wsl2\\\\vmlinux' | tee /mnt/c/Users/$winuser/.wslconfig

設定ファイルの内容

[wsl2]
kernel = C:\\Users\\ユーザ名\\wsl2\\vmlinux

WSL再起動

WSLを再起動する前に現在使用中のカーネルリリース名とカーネルがコンパイルされた日時を確認しておきましょう。

# uname -rv
5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021

コマンドプロンプトでUbuntu(WSL)を終了してから、スタートメニューでUbuntuを再び起動します。
systemdを終了したときはwsl -t Ubuntuで「Ubuntu」WSL環境だけ停止したのですが、wsl --shutdownで全WSL環境を終了させる必要があるみたいです。

C:\Users\user01>wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2

C:\Users\user01>wsl --shutdown

C:\Users\user01>wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Stopped         2

uname -rvでカーネルリリース名が自分で設定したLocal versionになっていること、「+」がついていること、カーネルがコンパイルされた日時が自分がコンパイルした時間になっていることを確認します。

# uname -rv
5.10.16.3-microsoft-standard-WSL2-ovs+ #1 SMP Mon Jul 11 00:54:44 JST 2022

状態確認(再構築後)

プロセス起動確認(再構築後)

ovs-vswitchdとovsdb-serverのプロセスが起動しているかを確認します。
どちらもActive: active (running)となっているのでOKです。先ほど起動に失敗していたovs-vswitchdが起動できています。

# /usr/libexec/nslogin
# systemctl status ovs-vswitchd
● ovs-vswitchd.service - Open vSwitch Forwarding Unit
     Loaded: loaded (/lib/systemd/system/ovs-vswitchd.service; static)
     Active: active (running) since Sun 2022-07-10 23:59:36 JST; 1min 4s ago
    Process: 245 ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-ovsdb-server --no-monitor --system-id=random --n>
   Main PID: 319 (ovs-vswitchd)
      Tasks: 1 (limit: 2295)
     Memory: 4.3M
     CGroup: /system.slice/ovs-vswitchd.service
             └─319 ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall -->

Jul 10 23:59:36 DESKTOP-QUCRLP5 systemd[1]: Starting Open vSwitch Forwarding Unit...
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-ctl[294]:  * Inserting openvswitch module
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-ctl[245]:  * Starting ovs-vswitchd
Jul 10 23:59:36 DESKTOP-QUCRLP5 systemd[1]: Started Open vSwitch Forwarding Unit.
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-ctl[245]:  * Enabling remote OVSDB managers
# systemctl status ovsdb-server
● ovsdb-server.service - Open vSwitch Database Unit
     Loaded: loaded (/lib/systemd/system/ovsdb-server.service; static)
     Active: active (running) since Sun 2022-07-10 23:59:36 JST; 1min 10s ago
    Process: 103 ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-ovs-vswitchd --no-monitor --system-id=random --n>
   Main PID: 171 (ovsdb-server)
      Tasks: 1 (limit: 2295)
     Memory: 13.0M
     CGroup: /system.slice/ovsdb-server.service
             └─171 ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/ru>

Jul 10 23:59:36 DESKTOP-QUCRLP5 systemd[1]: Starting Open vSwitch Database Unit...
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-ctl[103]:  * Starting ovsdb-server
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-vsctl[201]: ovs|00001|vsctl|INFO|Called as ovs-vsctl --no-wait -- init -- set Open_>
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-vsctl[232]: ovs|00001|vsctl|INFO|Called as ovs-vsctl --no-wait set Open_vSwitch . o>
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-ctl[103]:  * Configuring Open vSwitch system IDs
Jul 10 23:59:36 DESKTOP-QUCRLP5 ovs-ctl[103]:  * Enabling remote OVSDB managers
Jul 10 23:59:36 DESKTOP-QUCRLP5 systemd[1]: Started Open vSwitch Database Unit.

プロセスログ確認(再構築後)

ovs-vswitchdのログも見てみます。先ほどはopenvswitchのロードとbridgeのアンロードに失敗していました。
今回は特にエラーは出ていないです。

# journalctl -u ovs-vswitchd
  (省略)
Jul 10 23:59:36 systemd[1]: Starting Open vSwitch Forwarding Unit...
Jul 10 23:59:36 ovs-ctl[294]:  * Inserting openvswitch module
Jul 10 23:59:36 ovs-ctl[245]:  * Starting ovs-vswitchd
Jul 10 23:59:36 systemd[1]: Started Open vSwitch Forwarding Unit.
Jul 10 23:59:36 ovs-ctl[245]:  * Enabling remote OVSDB managers

カーネルにロードされているモジュール一覧を確認します。openvswitchが存在して、bridgeが存在しないのでOKです。

# lsmod
Module                  Size  Used by
openvswitch           151552  0
nsh                    16384  1 openvswitch

ovs-vsctlコマンド確認(再構築後)

ovs-vsctl showでBride一覧を出力します。何かのIDとバージョンが表示され、エラーなしでコマンド終了しました。問題ないでしょう。

# ovs-vsctl show
a610d88a-094d-4266-bcfe-5643b1a5cf9f
    ovs_version: "2.17.0"
# echo $?
0

動作確認

Bridge(仮想L2スイッチ)に2台のPCが接続されている構成を作ってみます。

まずはpc1, pc2とvethを作ります。Bridgeがないのでまだ通信はできないです。

ip netns add pc1
ip netns add pc2
ip link add p1 type veth peer name eth0 netns pc1
ip link add p2 type veth peer name eth0 netns pc2
ip -n pc1 addr add 10.0.0.1/24 dev eth0
ip -n pc2 addr add 10.0.0.2/24 dev eth0
ip -n pc1 link set eth0 up
ip -n pc2 link set eth0 up

「br1」という名前のBrideを作成します。
ovs-vsctl showでは作成したBridgeの情報が出てきました。

# ovs-vsctl add-br br1
# ovs-vsctl show
7f9d9250-719a-44a9-b775-439d1eb98529
    Bridge br1
        Port br1
            Interface br1
                type: internal
    ovs_version: "2.17.0"ovs-vsctl add-port br1 p1

作成したbr1にpc1, pc2につながるケーブルp1, p2を接続します。まだリンクアップさせていないので通信できないです。
ovs-vsctl showでPort情報が出てくるようになりました。

# ovs-vsctl add-port br1 p1
# ovs-vsctl add-port br1 p2
# ovs-vsctl show
7f9d9250-719a-44a9-b775-439d1eb98529
    Bridge br1
        Port p2
            Interface p2
        Port p1
            Interface p1
        Port br1
            Interface br1
                type: internal
    ovs_version: "2.17.0"

まずはpc1に繋がるbr1のp1ポートのみリンクアップさせます。
pingを実施してみて、この時点では通信できないことを確認します。

# ip link set p1 up
# ip netns exec pc1 ping -c 3 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.

--- 10.0.0.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2099ms

最後にpc2に繋がるbr1のp2ポートをリンクアップさせます。
pingが成功するようになりました。Open vSwitchで作成したBridgeを使った通信ができることが確認できました。

# ip link set p2 up
# ip netns exec pc1 ping -c 3 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.293 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.027 ms

動作確認が終わったら不要になったオブジェクトは消しておきます。

ovs-vsctl del-port p1
ovs-vsctl del-port p2
ovs-vsctl del-br br1
ip link del dev p1
ip link del dev p2
ip netns del pc1
ip netns del pc2

参考文献

https://k-hyoda.hatenablog.com/entry/2020/09/22/120120
https://note.com/decoponia/n/nb0275811cb6b
https://github.com/ubuntu/wsl-setup/tree/main/systemd
https://blog.mono0x.net/2014/04/26/linux-kernel-version/

Discussion