SONiCでVRFを使うの続きです。
ip vrf
が使えない
SONiCは、Debian/GNU Linuxをベースにしたホワイトボックススイッチ用のOSです。現在はDebian 9.0(stretch)ベースとなっています。カーネルバージョンは4.9.189-3+deb9u2とのことです。
SONiCはホワイトボックススイッチ用のOSということで、ネットワーク関連機能の設定、参照、動作確認などを提供しています。しかし、VRF (Virtual Routing and Forwarding) の機能確認のため ip vrf
コマンドを使用することはできません。
ip vrf
コマンドを使えない理由は
- iproute2パッケージのバージョンが古く、サポートされていない
- linux kernelのバージョンが古く、サポートされていない
となります。iproute2パッケージ自体はstretch-backportsによりip vrf
をサポートするバージョンが提供されていますので、そちらをインストールすることで解決しますが、カーネルが古いままだと ip vrf exec
を実行することができません。
その1 単純にカーネルを入れ替えるだけ(失敗)
カーネルを更新できれば解決しそう、ということで、早速やってみることにしました。
新しいカーネルのインストール
sudo apt-get -t stretch-backports install linux-image-4.19.0-0.bpo.6-amd64
リブートすると、無事……元々入っていた4.9.0が起動してきます。あれ?
GRUBで新しいカーネルを指定する
んー。GRUBかな。ということで再度リブートし、GRUBのメニュー画面でe
を叩くと、たしかに4.9.0のまま。一時編集ですが4.19に書き換えて、起動させます。
動作確認
起動はしました。マネジメントポートは生きています。sshでログインしてバージョン確認。ヨシ!
ip vrf exec
も動かしてみよう、えーとIPアドレスは、show ip interfaces
で確認……
あれ、Ethernet*がひとつも見えてないぞ? ログを見てみます。show logging|less
すると、
INFO pmon#supervisord: 2020-02-21 07:59:43.276 INFO exited: syseepromd (exit status 1; not expected)
あーーー。そういえばSONiCはスイッチASICだとかSFP周りの制御のためにカーネルモジュールを用意しているので、バージョンが合わなきゃ動かないってことをすっかり忘れてました。これは標準のLinux kernelには含まれないので、ビルドするところから手を入れないとどうしようもないです。残念ですが、このやり方はここまで。
その2 新しいカーネルを含むSONiCをビルドする(失敗)
SONiCでは、Linuxカーネルを含むイメージをソースコードから作成できます。このとき、外からバイナリイメージを取得してビルド時間を短縮することもできるのですが、通常はLinuxカーネル自体もソースコードからビルドします。その部分が4.9を対象としているので、4.19など新しいバージョンに置き換えればうまくいくのでは? と思い、試してみました。
src/sonic-linux-kernel/Makefile
を変更(不十分)
sonic-linux-kernel
はsubmoduleです。この下にカーネルソースが展開されたりしていますしMakefile
もありますので、ここを変更すれば良さげです。
diff --git a/Makefile b/Makefile
index 4d3a28a..6bf651f 100644
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,10 @@
SHELL = /bin/bash
.SHELLFLAGS += -e
-KERNEL_ABI_MINOR_VERSION = 2
-KVERSION_SHORT ?= 4.9.0-11-$(KERNEL_ABI_MINOR_VERSION)
+KVERSION_SHORT ?= 4.19.0-0.bpo.6
KVERSION ?= $(KVERSION_SHORT)-amd64
-KERNEL_VERSION ?= 4.9.189
-KERNEL_SUBVERSION ?= 3+deb9u2
+KERNEL_VERSION ?= 4.19.67
+KERNEL_SUBVERSION ?= 2+deb10u2~bpo9+1
kernel_procure_method ?= build
LINUX_HEADER_COMMON = linux-headers-$(KVERSION_SHORT)-common_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_all.deb
@@ -20,11 +19,11 @@ ifneq ($(kernel_procure_method), build)
# Downloading kernel
diff --git a/Makefile b/Makefile
index 4d3a28a..6bf651f 100644
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,10 @@
SHELL = /bin/bash
.SHELLFLAGS += -e
-KERNEL_ABI_MINOR_VERSION = 2
-KVERSION_SHORT ?= 4.9.0-11-$(KERNEL_ABI_MINOR_VERSION)
+KVERSION_SHORT ?= 4.19.0-0.bpo.6
KVERSION ?= $(KVERSION_SHORT)-amd64
-KERNEL_VERSION ?= 4.9.189
-KERNEL_SUBVERSION ?= 3+deb9u2
+KERNEL_VERSION ?= 4.19.67
+KERNEL_SUBVERSION ?= 2+deb10u2~bpo9+1
kernel_procure_method ?= build
LINUX_HEADER_COMMON = linux-headers-$(KVERSION_SHORT)-common_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_all.deb
@@ -20,11 +19,11 @@ ifneq ($(kernel_procure_method), build)
# Downloading kernel
これでいいんじゃないかな。make
してみます。
"SONIC_DEBUGGING_ON" : ""
"SONIC_PROFILING_ON" : ""
"KERNEL_PROCURE_METHOD" : "build"
"BUILD_TIMESTAMP" : "20200221.131016"
"BLDENV" : "stretch"
"VS_PREPARE_MEM" : "yes"
"ENABLE_SFLOW" : "y"
[ 01 ] [ target/debs/stretch/linux-headers-4.9.0-11-2-common_4.9.189-3+deb9u2_al
あれ?
残存する4.9指定部分を変更していく
よく見ると、build_debian.sh
の下の方にパッケージ取得の記述があり、そこのURLが4.9を取りに行くよう書かれていました。追加のパッチを用意します。
diff --git a/build_debian.sh b/build_debian.sh
index 37db2bde..bb58d7ab 100755
--- a/build_debian.sh
+++ b/build_debian.sh
@@ -37,7 +37,7 @@ if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
else
DOCKER_VERSION=5:18.09.8~3-0~debian-stretch
fi
-LINUX_KERNEL_VERSION=4.9.0-11-2
+LINUX_KERNEL_VERSION=4.19.0-0.bpo.6
## Working directory to prepare the file system
FILESYSTEM_ROOT=./fsroot
@@ -139,9 +139,7 @@ sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/initramfs-tools_*.deb || \
sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/linux-image-${LINUX_KERNEL_VERSION}-*_${CONFIGURED_ARCH}.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install acl
-if [[ $CONFIGURED_ARCH == amd64 ]]; then
- sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install dmidecode hdparm
-fi
+[[ $CONFIGURED_ARCH == amd64 ]] && sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install dmidecode
## Update initramfs for booting with squashfs+overlay
cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null
他多数は s/4\\.9\\.0-11-2/4.19.0-0.bpo.6/
でだいたい大丈夫なので,perl -pi
で一気に置換します。
あとはrules/linux-kernel.mk
です。
diff --git a/rules/linux-kernel.mk b/rules/linux-kernel.mk
index e6742bdf..ec36b382 100644
--- a/rules/linux-kernel.mk
+++ b/rules/linux-kernel.mk
@@ -1,9 +1,9 @@
# linux kernel package
-KVERSION_SHORT = 4.9.0-11-2
+KVERSION_SHORT = 4.19.0-0.bpo.6
KVERSION = $(KVERSION_SHORT)-$(CONFIGURED_ARCH)
-KERNEL_VERSION = 4.9.189
-KERNEL_SUBVERSION = 3+deb9u2
+KERNEL_VERSION = 4.19.67
+KERNEL_SUBVERSION = 2+deb10u2~bpo9+1
ifeq ($(CONFIGURED_ARCH), armhf)
# Override kernel version for ARMHF as it uses arm MP (multi-platform) for short version
KVERSION = $(KVERSION_SHORT)-armmp
これで4.9を参照しに行くことはなくなったはず、ということで、再度ビルドしてみます。
Initialized empty Git repository in /sonic/src/sonic-linux-kernel/linux-signed-amd64-4.19.67+2+deb10u2~bpo9+1/.git/
error: patch failed: debian/changelog:1248
error: debian/changelog: patch does not apply
stg import: Diff does not apply cleanly
Makefile:52: recipe for target '/sonic/target/debs/stretch/linux-headers-4.19.0-0.bpo.6-common_4.19.67-2+deb10u2~bpo9+1_all.deb' failed
make[1]: *** [/sonic/target/debs/stretch/linux-headers-4.19.0-0.bpo.6-common_4.19.67-2+deb10u2~bpo9+1_all.deb] Error 2
あれ?
結論: カーネルの更新は断念
src/sonic-linux-kernel/patch
に、カーネルに当てるパッチが置かれていますが、ファイル数は105もあります。中を見ると、
- 「4.10からbackportした」(つまり当てなくてよい)
- 「5.1からbackportした」(当たるかわからないけど変更が必要)
- 「backportした」(どこから持ってきたか不明なので調査が必要)
- コメントなし(同じく調査が必要)
といったふうにどのパッチが必要なのかは個別に判断しなければいけないことがわかりました。中には「これはMellanoxのスイッチ向けだ」というのもあって、ターゲット次第では当てずに済むパッチもいくつかあるようでした。
1日1パッチ片付ければ105日で、1日10パッチ片付ければ11日で105個こなせると言えばそのとおりなのですが、パッチ整理だけにそんなに時間を使うわけにも行かないので、4.19への置き換えは断念しました。残念ですがしかたありません。
作業の残骸をgithubに置いておきますので、頑張れる方はこれを取っ掛かりにしてもいいかもしれません。
https://github.com/iMasaruOki/sonic-buildimage/tree/linux-kernel-4.19
※追加情報があります。末尾の後日談2をお読みください
最初の問題: ip vrf exec
はどうなるの?
いろいろさまよっていたところ、代替手段としてcgroupsを使ってどうにかできることがわかりました。
ごそごそとシェルスクリプトを作りました。gistに放り込んでるので、コピペしてご自由にお使いください。
https://gist.github.com/iMasaruOki/a4e4cf03f4b754cb5d5f17633276a381
動作はこんな感じです。
admin@sonic:~$ ip addr show Ethernet0
8: Ethernet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9100 qdisc pfifo_fast master Vrf1 state UP group default qlen 1000
link/ether 6c:b9:c5:16:88:cc brd ff:ff:ff:ff:ff:ff
inet 172.21.1.1/31 scope global Ethernet0
valid_lft forever preferred_lft forever
inet6 fe80::6eb9:c5ff:fe16:88cc/64 scope link
valid_lft forever preferred_lft forever
admin@sonic:~$ ping 172.21.1.0
PING 172.21.1.0 (172.21.1.0) 56(84) bytes of data.
--- 172.21.1.0 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1006ms
admin@sonic:~$ sudo ./ip-vrf-exec Vrf1 ping 172.21.1.0
PING 172.21.1.0 (172.21.1.0) 56(84) bytes of data.
64 bytes from 172.21.1.0: icmp_seq=1 ttl=64 time=0.421 ms
--- 172.21.1.0 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.421/0.421/0.421/0.000 ms
admin@sonic:~$
というわけで、どうにかできました。ヨシ!
後日談
pingでよければcgroupとかやらずに、単に ping -I Vrf1 172.21.1.0
でできるとのこと。そういえばnetdev生えてたよなあ、なるほど盲点でした。
後日談2
カーネルを入れ替えると言うかベースのDebianをbusterにする開発について、公式ページがありました。work in progressなかんじですが、こちらを参照したほうがベターと思います。