お腹.ヘッタ。

関数型とかセキュリティとか勉強したい。進捗つらぽよ

Linuxカーネルへのパッチの出し方メモ

これは三ヶ月放っておいたら出し方忘れてしまって、えらく叱られてしまったのでそのためにメモしなおしたものです。とてもつらかった。。。。困ったらChatGPTを使いましょう。破茶滅茶な英文が幾分マシになります。なんか僕が失敗するたびにこのページは勝手に増えます。

最初に読むべきモノたち

チートシート

カーネルの修正

基本的には頑張ってコードを読む以外はなさそう。あたりを付けて書き換えるとかビルドするとか。 とりあえずbuildの仕方とかは載せておこうじゃないか。 基本的にはfullbuildは初回とか、rebaseしたりした時にいる感じ。

git clone git@github.com:takehaya/linux.git
cd linux
git checkout support_rss_gtp
# ubuntu case
sudo apt install linux-image-6.1.0-1008-oem linux-headers-6.1.0-1008-oem linux-modules-6.1.0-1008-oem
sudo sed -i 's/# deb-src/deb-src/' /etc/apt/sources.list
sudo apt update
sudo apt build-dep -y linux
sudo apt install libncurses-dev
mkdir ../build
make olddefconfig O=../build
cd ../build
make localmodconfig
make menuconfig

# build
# CONFIG_SYSTEM_REVOCATION_KEYS のキー情報を消し飛ばしておく
# ICEのコンフィグを有効にして行おう
# cf. https://qiita.com/MNT_QU/items/4b86e56731320f033c3e#config%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6
make -j64 LOCALVERSION=-rss-custom-01
make modules -j64 LOCALVERSION=-rss-custom-01

# package
make bindeb-pkg -j64 LOCALVERSION=-rss-custom-01

# local install
# sudo make modules_install
# sudo make install
sudo apt install ../*.deb

debugのためにビルドして再度適用するときはこちら

make modules -j64 LOCALVERSION=-rss-custom-01
sudo cp drivers/net/ethernet/intel/ice/ice.ko /lib/modules/6.3.0-rc6-rss-custom-01/kernel/drivers/net/ethernet/intel/ice/ice.ko 

sudo modprobe -r irdma
sudo modprobe -r ice
sudo depmod -a
sudo modprobe ice

強いて言うならばこれが参考になるかもしれないですね(古いけど!) https://knqyf263.hatenablog.com/entry/2019/07/01/152643

パッチの送信方法

送るための前準備

# patchのコードスタイルが合っているかどうかを見る
# これが何も出なくなるまで頑張る。
git diff HEAD^ | scripts/checkpatch.pl

# singoff by と言うのをすることでコードに対して署名をする
git config format.signOff yes

# sendemailをするときの対象者を設定する
# (これは特定のgit管理されてるリポジトリで行う)
# に実態が置かれてる
git config sendemail.to "$(git diff HEAD^ | ./scripts/get_maintainer.pl --separator , --nokeywords --nogit --nogit-fallback --norolestats --nol)"
git config sendemail.cc "$(git diff HEAD^ | ./scripts/get_maintainer.pl --separator , --nokeywords --nogit --nogit-fallback --norolestats --nom)"
# ちなみにさらにメールを明示的に追加するならこんな感じである
# git config sendemail.cc "$(git diff HEAD^ | ./scripts/get_maintainer.pl --separator , --nokeywords --nogit --nogit-fallback --norolestats --nom) mailhol.vincent@wanadoo.fr vladimir.oltean@nxp.com"

# smtpの設定などを.gitconfigに入れておく
# 80文字で折り返すようにしておくといいが、実際には手動でぽちぽちやることになるのでなくてもいい。
~/private/linux$ vim ~/.gitconfig 
[sendemail]
       smtpserver = smtp.gmail.com
       smtpuser = hayatake396@gmail.com
       smtpencryption = tls
       smtpserverport = 587
       smtpPass = aaaaaa
       annotate = yes
[format]
        wrap = 80

実際に送りつける

# 単一のちょっとしたパッチはこれで送りつけて大丈夫
# パッチのバージョンに合わせてv6とかv7,v8...に上げていく必要がある
git send-email --annotate -v6 --subject-prefix='PATCH net-next' HEAD

# 意味が変わるようなパッチであれば二つに分割したりする必要がある。例えばuapiとそれに基づいて作られるdriveの機能とか(ethtool.hとiceドライバに関する機能)とかね
# 以下のコマンドで二つのパッチを同時に出せる
git send-email --annotate -v6 --subject-prefix='PATCH net-next' -2 HEAD

# パッチを同時に二つコマンドを実行すると以下のように出てくる。同時に二つ出すのは明示的にパッチシリーズであると言うことにするためだ。
# ここには見えてないがcommit messageとパッチの画面が出てくるのでそこでeditをしよう。
# ちなみに本当にパッチが二つになってるか知りたい場合は、以下に見える /tmp/hoge/v[0-9]-000~が2個あるかどうかで確認しよう。
~/private/linux$ git send-email --annotate -v7 --subject-prefix='PATCH net-next' -2 HEAD
/tmp/B_FPb86TTd/v7-0001-ethtool-Add-GTP-RSS-hash-options-to-ethtool.h.patch
/tmp/B_FPb86TTd/v7-0002-ice-Implement-RSS-settings-for-GTP-using-ethtool.patch
2 files to edit
(mbox) Adding cc: Takeru Hayasaka <hayatake396@gmail.com> from line 'From: Takeru Hayasaka <hayatake396@gmail.com>'
(body) Adding cc: Takeru Hayasaka <hayatake396@gmail.com> from line 'Signed-off-by: Takeru Hayasaka <hayatake396@gmail.com>'

From: Takeru Hayasaka <hayatake396@gmail.com>
To: Jesse Brandeburg <jesse.brandeburg@intel.com>,
        Tony Nguyen <anthony.l.nguyen@intel.com>,
        "David S. Miller" <davem@davemloft.net>,
        Eric Dumazet <edumazet@google.com>,
        Jakub Kicinski <kuba@kernel.org>,
        Paolo Abeni <pabeni@redhat.com>,
        Jonathan Corbet <corbet@lwn.net>
Cc: intel-wired-lan@lists.osuosl.org,
        netdev@vger.kernel.org,
        linux-doc@vger.kernel.org,
        linux-kernel@vger.kernel.org,
        mailhol.vincent@wanadoo.fr,
        vladimir.oltean@nxp.com,
        laforge@gnumonks.org,
        Takeru Hayasaka <hayatake396@gmail.com>
Subject: [PATCH net-next v7 1/2] ethtool: Add GTP RSS hash options to ethtool.h
Date: Thu,  1 Feb 2024 03:33:09 +0000
Message-Id: <20240201033310.1028154-1-hayatake396@gmail.com>
X-Mailer: git-send-email 2.34.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

    The Cc list above has been expanded by additional
    addresses found in the patch commit message. By default
    send-email prompts before sending whenever this occurs.
    This behavior is controlled by the sendemail.confirm
    configuration setting.

    For additional information, run 'git send-email --help'.
    To retain the current behavior, but squelch this message,
    run 'git config --global sendemail.confirm auto'.

Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): y

# この時、yを押すと一つずつパッチが送られる。aを押すと全部送ってくれる感じである

気をつけた方がいいこと

コミットメッセージは80文字で切る

注意点としては文章の区切りで改行を入れるのではなく、コンテキストが続くものは連続で書くべきである。 例えば以下が正しい例である

commit 739a0aac9d26ce2b51bb5ec2da46c8db91129b58 (HEAD)
Author: Takeru Hayasaka <hayatake396@gmail.com>
Date:   Thu Feb 1 03:11:04 2024 +0000

    ice: Implement RSS settings for GTP using ethtool
    
    Following the addition of new GTP RSS hash options to ethtool.h, this patch
    implements the corresponding RSS settings for GTP packets in the Intel ice
    driver. It enables users to configure RSS for GTP-U and GTP-C traffic over IPv4
    and IPv6, utilizing the newly defined hash options.
    
    The implementation covers the handling of gtpu(4|6), gtpc(4|6), gtpc(4|6)t,
    gtpu(4|6)e, gtpu(4|6)u, and gtpu(4|6)d traffic, providing enhanced load
    distribution for GTP traffic across multiple processing units.
    
    Signed-off-by: Takeru Hayasaka <hayatake396@gmail.com>

これを悪くしてみよう。例えば怒られた例だとなるべく句読点で改行したり、適当なはちゃめチヤなところで切ってるやつである。これは正しくするならば、80行ギリギリになる単語で切る。同じ文章のまとまりで初めて改行を入れるべきである。本来であれば二つの塊で問題ないのに、3つの塊にしてたり、80文字までまだまだ単語が入るのに変な位置で切っていると言うのが問題である。

commit 739a0aac9d26ce2b51bb5ec2da46c8db91129b58 (HEAD)
Author: Takeru Hayasaka <hayatake396@gmail.com>
Date:   Thu Feb 1 03:11:04 2024 +0000

    ice: Implement RSS settings for GTP using ethtool
    
Following the addition of new GTP RSS hash options to ethtool.h,
this patch implements the corresponding RSS settings for
GTP packets in the Intel ice driver. 

It enables users to configure RSS for GTP-U and GTP-C traffic 
over IPv4 and IPv6, utilizing the newly defined hash options.

The implementation covers the handling of gtpu(4|6), gtpc(4|6), 
gtpc(4|6)t, gtpu(4|6)e, gtpu(4|6)u, and gtpu(4|6)d traffic, 
providing enhanced load distribution for GTP traffic across 
multiple processing units.
    
    Signed-off-by: Takeru Hayasaka <hayatake396@gmail.com>

正しく空白行を入れる

引用形式の文を書く

レビューをしてくれた人からメールが来るだろう。 その時には相手の文章に対して返信を書くことになるはず。

> 相手の文章

自分の意見

> 相手の文章

自分の意見

と言った感じで書くことがいい ちなみにだが、gmailとかでメールを返信するときは Content-Type: text/plain; にしなくてはいけないので注意。 この辺が参考になりそうです。 https://www.kernel.org/doc/html/next/process/email-clients.html https://nekomatu.blogspot.com/2014/05/howto-send-patch-to-linux.html

パッチの revisionをするとき

こんな感じでrevisionをするときにv1,v2とかの差分をここに書いてあげると親切らしい。

Signed-off-by: Takeru Hayasaka <hayatake396@gmail.com>
---
v2->v3: Based on Harald-san's review, I added documentation and comments to
ethtool.h and ice.rst.
v3->v4: Based on Marcin-san's review, I added the missing code for GTPC and
GTPC_TEID, and revised the documentation and comments.
v4->v5: Based on Marcin-san's review, I fixed rename and wrong code regarding
GTPC
v5->v6: Based on Marcin-san's review, Undoing the addition of unnecessary
blank lines.Minor fixes.
v6->v7 Based on Jakub-san's review, Split the patch.
 include/uapi/linux/ethtool.h | 48 ++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

CIが落ちたりしたので再度叩き込む時

中身は大きく変わるわけではないが、CIが落ちたりしたので再度叩き込む時に必要だったりする。 RESENDをつけることでレビュワーの混乱を防げる。

git send-email --annotate -v7 --subject-prefix='PATCH net-next RESEND' HEAD^

自分のパッチの送付を確認するとき

https://patchwork.kernel.org/project/netdevbpf/list/?submitter=210976 とかpatchworkを見るのが良い。

https://lore.kernel.org/all/20240201033310.1028154-2-hayatake396@gmail.com/ とかでメーリングリストにタイトルを入れるのも良い。

PyCon APAC 2023で発表してきました

Why

今後もいろんなところでCfPを出していくぞ!というメモ書きとして書き残すためにこれを書きます。

What

PyCon JP 2023はPyCon APAC 2023として開催されました。APACが日本で行われるのは10年ぶりの開催だそうです。

どうせ参加するなら発表したいなーと思ってプロポーザルを出したところ、採択していただけたのでスピーカーとして参加しました。

発表内容について

今年の私のトークタイトルは 「自作パケット処理系の性能測定と可視化&改善のPDCAを回して最強のパケット処理系の作り方を学ぼう」 でした。

speakerdeck.com

実は初参加でした。PyConJP自体は存じ上げてたのですが、今まで地方に(今も?)住んでいるので参加には大変敷居が高かったというのがあり初参加・初スピーカーという感じでドキドキでした。

PyConと言いつつ少しPython感は薄い感じになりましたが転職して戻ってきて一年でちゃんと対外発表できる感じでだったのでよかったです。

CfPを練るにあたっての所感

発表内容については実は合計二本出していて、「ExaBGPにSRv6MUPを入れた話」と今回の「PGW-Uに対して負荷計測を行った話」を出していました。

前者はIETFのネームバリューとかOSSに初めて新機能入れました!みたいなセンセーショナルさで攻めてみたCfP、後者は学びや再現性がある話を売りにして攻めてみたCfPで書いました。結果としては後者に関して拾ってもらえてよかったです。

自分はこのように大きいところで話すのは初めてだったのでおすすめタイトルは何かを調べました。

speakerdeck.com

次にトラックの選び方の話とかプロポーザルの参考例を眺めてやりました。

あとはプロポーザルの選択基準が明確に出されてたのでこのように書き出して強みってなんだろー?と思いながら書き出してました。

## どういう話にするか&どういう強みがあるか
### Python 初心者にとって自らの知見を広げる内容か
~なさそう~ ネットワークの処理系に関しても使えるんだぞ!という分野自体を伝えれるかも

### Python が社会で活用されている具体的なイメージを描けるか
SDNやNFVと言われているサービスというのは自分たちの手で実装可能なことが知られているが、どのように品質を担保するかはあまり知られていない。ネットワーク製品を良くするために使われてるというイメージを持ってもらえる

### 内容に独自性・新規性はあるか
Trexでどのようにしてデータを持ってくるとか細かい実装レベルについては書いてないので、そういうのを書いてもいいかも

### トークの発表が明確にイメージできるほど構成は詳細に書かれているか
本文の詳細を見てイメージできるように書き出してみる
- 背景とモチベ
  - 弊社ではフルMVNO事業をやっており、その中のPGW-Uと呼ばれるインターネットに出るための自作パケット処理系の通信効率の性能を上げることが求められていました
  - そのためにpython製のツールとライブラリを駆使して計測し高速化をしました
- 話す内容
  - 私たちは、XDPと呼ばれるeBPFを使った高速パケット処理技術を使って実装しています
  - 性能試験を通した改善プロセスでは、負荷試験のパケット生成・テスト結果の記録・メトリックの分析など多くの場面で Python を活用しています
  - それぞれの場面での活用事例を紹介します
    - scapy で TRex のパケット生成にモバイル網で使うプロトコルのパケットを追加しました
    - 性能試験のテスト完了後、性能指標を TRex から取得し Pushgateway で記録しました
    - Jupyter Lab 上で Grafana 経由の CSV ファイルを pandas.DataFrame に加工し、可視化や評価を行いました
  - 性能試験を通じた改善例
    - 大容量のエントリを流した際にメモリ使用量が大きくなるとコケる問題を発見して修正した事例
    - パケットのcheck sumの処理で遅くなったので処理性能を向上させるためにchecksum機能をoptoutする機能を追加した事例
    - 特定のパケットに対してマルチコア対応がされていないことを発見して、IntelのNICドライバに機能を追加してマルチコア対応させた。その結果$(nproc| CPUコア数)倍の効率アップができた事例

### コミュニティの国際交流に寄与するか
わからん。。。

### Python を使う「楽しさ・熱意」をアピールできるか
ぶっちゃけscapyがすごいんだけど、pythonで好きなパケットをホイホイ投げれるのは良い

### 聴衆が具体的に持ち帰ることができる知識や技術の利用方法・工夫があるか
自社のネットワーク製品を検証できるフレームワークやコードを提供できる

その他の雑感

参加について

スピーカーは本会議前日に特別招待されたイベントに参加できました。 が、普段のネットワークの人たちは全くいないので知り合いがいなくてそれなりにぼっちで辛かったです(かなりクラスタが違うし、コミュ障には厳しい)

IETFとかみたいに始めまして参加者限定パーティーとかそういうのがあったら嬉しかったなーと思いました

発表聴講に関して色々クラスタを見てると体感3-4割ぐらいがMLっぽい人が多いなーとか思いました。 NetworkX!?ネットワークの人がいる〜!と思ってノコノコ行ったらニューラルネットワークのネットワークでorzとなりました。

ただMemrayの発表とかはなるほどーとなって面白かったです。スレッド間の話とかをしてなかったのでもうちょい深い話を聞きたかったんですが色々聞いた感じ発表内容的にはオーバービューみたいな発表が好まれるのだなーと思いました。Qiitaとかにあるチュートリアルやってみました。こんなこともできるらしいです!ぐらいの感じが一番ウケそうだなぁと思いました。

実際自分が登壇する時はクラスタ的に全然きてくれないかも・・と不安で参加前についてはTwitterで極力宣伝しまくりました。結果としては30人ちょいぐらいは来てくれてたので0人じゃなくてよかったのかなと思います。宣伝後も登壇した資料を公開してそれなりにPVしてもらうことはできました。きっとJANOGとかIWならもう少し来てくれる人が居たかもなーと思ったりしましたがこれも学びです😇

ちなみに懇親会でとあるプログラム委員と話したところ、投稿してる人が少ない分野でちゃんと描いてると通りやすいんだよねーという話を聞きました。なので今回ネットワークプログラミングに関するトラックで選択して投稿したのはよかったなと思います。

発表方法について

発表練習は個人で行い、スピーカーノートにはある程度文章でスクリプトを描きました。発表資料・言語は日本語なので緊張はしましたが話が飛んでしまうということはなかったかなと思います。

反省点として自分の発表は本当にLTみたいな早口詰め込み発表でしたので要点を絞る訓練をした方がいいと思いました。また資料に不必要な図の引用をしてたので社の先輩に指摘されてしまったというのがあり、ある程度フォーマルな場所での発表の仕方というのを身につけた方がいいなと思いました。詰め込んだことに関しては、スライドの狙いとして後から見返して嬉しくなるようにしたので仕方ないんですが果たしてここの発表でそれは適切だったのかは悩ましいです。その点で唯一良かった点は初め20-30秒QRコードを出してスライドをぜひお手元でご覧ください!という話をしたのは直前で追加した動きでしたが良かったです。

そろそろ若手社員という枠じゃ無くなりそう(今3年目😇)なので何とか身につけたいです。。。

早口なものだった話は、多少言い訳すると30分の発表で募集されてたので30分まるまる使えるものだと思っていました。

が、実際発表する時に初めて25分で残り5分は質疑と書かれており・・・この辺は登壇時に気をつけることという旨の資料上で事前アナウンスされてなかったので大変焦りました。この辺はあらかじめちゃんと確認しておくと良いなと思いました(反省)

発表後に気がついたんですが、発表に関しても pyconの運営の人たちがノウハウを出してくれてたので見ておくとよかったなーと思いました。 (全然見つけれなかったのでいろんなところでこういう資料を宣伝して欲しかったw)

tv.pycon.jp

linux kernel をbuildしてinstallしたら立ち上がらなくなった時のメモ

言ってる通り立ち上がらなくなった。 とてもつらい気持ちになったのでそれをどうやって解決しましたか?というメモです。

こういうのがネットに転がってるとマジでありがたいので感謝の意を込めて晒しておきます。

前提として

  • grubすら上がらない設定にしてしまった
  • idracとかから busybox のshellに対して書き込みができなくて終わってしまった
    • なんで idracから触れないのか... :innocent:
  • kernel build して make install したら死んだ

こんな感じの顔をして死んでた。linuxさんの色々なアヘ顔って感じです

Gave up waiting for root device. Common problems:
  — Boot args (cat /proc/cmdline)
    — Check rootdelay= (did the system wait long enough?)
    — Check root= (did the system wait for the right device?)
  — Missing modules (cat /proc/modules; ls /dev)
ALERT! /dev/mapper/ubuntu--vg-root does not exist. Dropping to a shell! 

BusyBox v.1.21.1 (Ubuntu 1:1.21.1-1ubuntu1) built-in shell (ash)   
Enter 'help' for list of built-in commands.  

(initramfs)

直し方

  • 雑にUSBライブブートをなんかでします。ubuntuとかでも良いです。
  • ライブブートからshellを触れる様にします。
  • とりあえず何も考えず ubuntu server のイメージを使いました。
# shellが触れてたら fdiskで対象のジャーナルを探す
fdisk -l 

# 雑に dev を見たら色々あるのでそれっぽいのをmountする
# sda1がefi, sda2がboot, sda3 が lvという感じ
mount /dev/ubuntu-vg/ubuntu-lv /mnt
mount /dev/sda2 /mnt/boot

# 後から chroot をするときに触りたい環境情報があるものをマウントして使える様にしておきます。これがないとFSとか触れなくて困る。
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys

# chroot いわゆるコンテナ化みたいなやつです。(雑
# これで自分の壊したSSDとかのデータにログインするみたいなことができる
chroot /mnt /bin/bash

# 起動のオプションとかインストールが失敗してるだろうからこれで入れ直し
# カーネルのバージョンは /boot/ とかに転がってるファームから分かる。
# /etc/default/grub とかに設定があるからそれを書き換えたりも出来る
grub-install /dev/sda 
update-initramfs -u -k [カーネルのバージョン]

# 後片付け
exit
umount /mnt/dev
umount /mnt/proc
umount /mnt/sys
umount /mnt/boot
umount /mnt

sudo reboot 

これで戻ってくるのを信じてもう一度トライ。 これで治らなかったらもっと頑張りましょう(完

もし無理なら /mnt が出来る時点で /home/user/ が手に入るのでそこにあるものをZIPしてどこかに投げつけるとかでレスキューしてOS入れ直しとかをすると良いと思います。

参考

VPP上の開発・デバッグ方法テクニック

ビルド方法やテストの実行テクニックに関してはVPPにSRv6 MUP Plugin APIを追加している話開発方法とパッチを出すときの Tips に書いたりしてるわけですが、もう少しフォローアップする話があってもいいかなー(書いとくと後で思い出すのに便利)と思い記事を書きました。

この記事は自分が便利だと思った物を追記してくスタイルなのでサイレントで更新されたりします。

プログラムのデバッグ方法

ここでは printf ではもう辛くなった人向けです。たとえばCに慣れてなくて初期化されてなくて困ってるとかそういう人が便利に使う想定です。

AddressSanitizer

アドレスサニタイザーってやつです。VPPはマルチスレッドな感じでvalgrindが使えない環境なので使うと便利だったというやつです。 詳しくはここを見ると良さそう。

s3-docs.fd.io

make build VPP_EXTRA_CMAKE_ARGS=-DVPP_ENABLE_SANITIZE_ADDR=ON

GDB

gdbなので使い方はググってくれ

世の中にはいい記事がいっぱいあります。 https://uguisu.skr.jp/Windows/gdb.html

make debug

Trace

コードレベルではなく、設定や構成レベルのデバッグに有用です。

# VMのNICがある部分からパケットを受け取るときはここを見る
trace add dpdk-input 10
show trace
clear trace

# VTAPなどの部分からパケットを受け取るときはここを見る
trace add virtio-input 100
show trace
clear trace

# それぞれの処理nodeへの着信カウンターを見ることでどの処理が多く動いてるかがわかる
show runtime

packet trace

https://vps3-docs.fd.io/vpp/23.06/cli-reference/clis/clicmd_src_plugins_dispatch-trace.html

# pcap をtx側のものを全て取得する
pcap trace tx on

# 取得したものを書き出し(/tmp/tx.pcapに書き込まれる。 txをrxに置き換えても成り立つ仕様)
pcap trace tx off

pluginの有効化と Linux-CPの利用法

confの中に以下のように入れることで pluginが有効化されます

plugins {
  plugin linux_cp_plugin.so { enable }
}

linux-cp設定例

tap(つまりただのL2の分岐機能です)を使うことで hostのlinuxに入れれて便利という話があったりしますが、これはそれはうまいことlinux側と協調動作するというわけではないです。

そこでlinux-cpを利用するとVPPとLinuxが協調動作します。つまりVPPを普通のlinuxっぽく利用できます。 詳しくはこの一連の記事を見るのがおすすめです。

これを利用することでLinuxでVPP+FRRを動作させてBGPを話すサーバーとして使うことができます。

ipng.ch

(ちなみに、以前はvppsbの中にrouterプラグインがあって、それは特定プロトコルだけ分離してcplaneに投げてくれるいわゆるtap-inject機能がありましたが、それはもう古いのでlinuxcpを使いましょう)

# lcp use netlink
cat << EOF > /etc/sysctl.d/81-vpp-Netlink.conf 
# Increase Netlink to 64M
net.core.rmem_default=67108864
net.core.wmem_default=67108864
net.core.rmem_max=67108864
net.core.wmem_max=67108864
EOF
sudo sysctl -p

VPP

set interface state eth1 up
set interface ip address eth1 172.0.1.2/24
set interface state eth2 up 
set interface ip address eth2 fc00:12::1/64

loopback create-interface
set interface state loop0 up
set interface ip address loop0 fc00:1::1/64

lcp lcp-sync on
lcp lcp-auto-subint on
lcp create eth1 host-if eth1
lcp create eth2 host-if eth2

linux

sudo ip link set eth1 up
sudo ip addr add 172.0.1.2/24 dev eth1
sudo ip link set eth2 up
sudo ip addr add fc00:12::1/64 dev eth2

ExaBGPにSRv6 MUPを実装をした時のメモ

Why

exaBGPに MUP-BGP を追加しました。パッチを出すのにちょくちょく困ってたのでメモを公開しておきます。

当該パッチはこちら github.com

使い方はこちらgobgpとの相互接続例をこのリンクで示してます。

追記: CML2で遊べるように cloudinitファイルを書いてみました。宜しければどうぞー

設計に関しての勘所

大きくわけて設定のためのパーサーとパケットのパーサーを書くというのが、BGPに機能を実装するということです。

具体的には前者のあたりはsrc/exabgp/configuration/を中心としたコード、後者は src/exabgp/bgp/message/update/を中心としたコードに手を加えることになります。

例えば前者のコードで announce セクションで動作するには 例えば@ParseAnnounce.register('mup', 'extend-name', 'ipv4') といったデコレーターをつけた上でパーサーコードを作り、先ほどの後者で記述されるTypeに合わせた設定を返します。

詳しくはPRにあるコードを見てください。

デバッグとtest方法

これはpythonなのでデバッグには import pdb;pdb.set_trace() を使うのが一番便利です。実質ブレークポイントなのでこれを入れて保存して実行してあげるのが良い感じです。 また、パケットの構造がミスってるかどうかを知りたい場合は受け取る方を行う方がわかりやすいです。理由としては受け取り側はstack traceが出るようになっていて尚且つ Notificationメッセージなどでわかるケースがあるからです。

他にもこのようにログとしてもヒントが出てきたりします。13:22:02 1656739 outgoing-13 >> NOTIFICATION (3,0,“invalid ipv4 mup next-hop length 16 expected 4”)

パースの方だと先ほどのような stack trace が出てこないので気をつける必要があります。

デバッグを通じて完成した場合はテストを書いてあげることもしたくなるはずです。 etc/exabgp/<confname>.conf (合わせてqa/ci/<confname>.ci<confname>.confと書いてあげる必要があります)に設定を書いてあげる必要があります。 これは実装物の設定例になる物です。

詳しくはPRを参照すると良いですが、肝は neighbor 127.0.0.1 にした上でコンフィグを設定し、exabgp -d <confname>.conf-d オプションを追加した上でログからupdateメッセージを取得して qa/ci/<confname>.msgに加筆する必要があります。

以下にgobgpの設定とexabgpの設定、先に示したようなgistに書いたネットワークを変形させたnetnsを示します。

#!/bin/bash

set -eu

if [[ $(id -u) -ne 0 ]] ; then
    echo "Please run with sudo"
    exit 1
fi

run () {
    echo "$@"
    "$@" || exit 1
}

destroy_network () {
    run ip netns del red
    run ip netns del blue
}

stop () {
    destroy_network
}

trap stop 0 1 2 3 13 14 15

# exec functions
run ip link add veth-red-blue type veth peer name veth-blue-red

run ip netns add red
run ip link set veth-red-blue netns red
run ip netns exec red ip link set up lo
run ip netns exec red ip link set up veth-red-blue 
run ip netns exec red ip addr add 10.0.0.1/24 dev veth-red-blue

status=0; $SHELL || status=$?
exit $status

gobgp.toml

[global.config]
    as = 65000
    router-id = "127.0.0.1"

[[neighbors]]
    [neighbors.config]
        peer-as = 65000
        local-as = 65000
        neighbor-address = "127.0.0.1"
    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
            afi-safi-name = "ipv4-mup"
    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
            afi-safi-name = "ipv6-mup"

exabgp.conf

neighbor 127.0.0.1 {
    router-id 10.0.0.1;
    local-address 127.0.0.1;
    local-as 65000;
    peer-as 65000;

    family {
            ipv4 mup;
            ipv6 mup;
    }
    announce {
        // gistを参考に所望のannouceを記述する
    }
}

これらの設定コンフィグを保存した後は以下のようにして実行します。

# red
sudo ip netns exec blue gobgpd -f ./gobgp.toml

# separate terminal exec
sudo ip netns exec red \
    /home/ubuntu/exabgp/sbin/exabgp \
    -d -v\
    ./exabgp.conf

以下のように update messageがログに流れるはずです。

23:19:14 1720215 rib             insert mup:t1st::100:100:2001:db8:1:1::1/128:12345:9:128:2001::1 extended-community target:10:10                                                    [733/1918]
23:19:14 1720215 rib             insert mup:t2st::100:100:12345:128:2001::1 extended-community target:10:10                                                                                    
23:19:14 1720215 outgoing-1      sending TCP payload ( 128) FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 0080 0200 0000 6940 0101 0040 0200 4005 0400 0000 64C0 1008 0002 000A 0000 000A C028 2505 0022 0001 001E 0020 010D B800 0100 0100 0000 0000 0000 0000 0048 0001 0006 4018 1000 0000 800E 2500 0155 1020 0100 0000 0000 0000 0000 0000 0000 0100 0100 010C 0000 0064 0000 0064 180A 0001
(中略)
23:19:14 1720215 outgoing-1      >> 8 UPDATE(s) 

そしたらこの outgoing-1 のバイナリ列がupdate messageになっているのでそれを取得して整形します

整形する形は以下のようにします

1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0080:02:000000694001010040020040050400000064C010080002000A0000000AC028250500220001001E0020010DB800010001000000000000000000004800010006401810000000800E250001551020010000000000000000000000000001000100010C0000006400000064180A0001

肝としては、接頭子にルールナンバーとtype,あとは取得したログの空白行を消して、初めのFの連続までをコロン、0080をコロン、02をコロンにして記述します。 ざっくり中身を説明すると

  • F~F: marker
  • 0080: lenght
  • 02: update message type

あとは以下のコマンドを実行して testが動作するかを見ます。これの作業を加えることで機能のテストが無事完了します。

./qa/bin/functional encoding

追記(2023/3/20)

もっと便利な方法があったのでメモしておく。 (ついでに引っかかりポイントも) まず引っかかりポイントとして何かしらの原因で test processが動いてるゆえにテストがゾンビ化してそちらにテスト実行時に繋がってしまい大変困るケースがある。遠慮なく pkill -f python3 とかで殺しておこう。

で、テストの時にnetnsとかはだるいと思うのでどうするかというとupdate messageを見るのではなくて、テストのunexpect エラーから取ってくると楽。具体的には以下のようなイメージ。この時の B は区別されてる列記としたラベルで以下のように list オプションで確認できる。

./qa/bin/functional encoding --list

./qa/bin/functional encoding --server B

./qa/bin/functional encoding --client B

こんな感じで出てくる。エラー自体のタイミングでクライアントの接続を切断されるので、そこではupdate messageと合わせて突き合わせれば良い。

new session:                                                                                                                                                                  
open recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0047:01:04FDE800B40A0000012A02060104000100010206010400010055020641040000FDE8020C400A80B4000101800001558002020600                 
open sent   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0047:01:04FDE800B40A0000022A02060104000100010206010400010055020641040000FDE8020C400A80B4000101800001558002020600                 
msg  recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0013:04:                                                                                                                         
msg  recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0017:02:00000000                                                                                                                 
msg  recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:001E:02:00000007900F0003000155                                                                                                   
msg  recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0030:02:00000015400101004002004003040A0001FE400504000000C8180A0001                                                               
msg  recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0080:02:000000694001010040020040050400000064C010080002000A0000000AC028250500220001001E0020010DB8000100010000000000000000000048000
10006401810000000800E250001551020010000000000000000000000000001000100010C0000006400000064180A0001                                                                             
msg  recv   FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:001B:02:0004180A00010000                                                                                                         
                                                                                                                                                                              
unexpected message:                                                                                                                                                           
received    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:001B:02:0004180A00010000      

終わりに

ドキュメントやコードは見やすいように整備されてて、迅速なレビューが素晴らしいですがciとmake fmtのルールが異なったり長い間使われてるOSSなので多少レガシーであることは事実でコードのメンテナンスは難しいなぁと思いました。

一方初めてBGPの機能実装を行いましたが比較的簡単に実装できるOSSというのは良い作品だと思ったのでぜひ今後も機会があればコントリビュートしていきたいと思いました。

EdgeRouterXが息をしてない時にやるやつ

要約

  • edgerouterx が上がってこない時は多分kernel panicを起こしてるのでリカバリーが必要。
  • USB TTL が必要になる

突然の死

なんか上がってこない

なおしかた

この記事を見て(完) yaaamaaaguuu.hatenablog.com

にならなかったので今回は書いています。

上の記事を見てもダメだった時に参考にしてください。

自分の場合はこのようなエラーが出てて、要はFSごと死んでたという話でした。この場合だと上記のような手順では復活できなくて困りました。

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

ググるとこんなのが出てきて Edgerouter X wiki points to not working .BIN and other thingies - #14 by zett - Installing and Using OpenWrt - OpenWrt Forum

どうやら公式のマニュアルがあるようです。 https://help.ui.com/hc/en-us/articles/360018189493-EdgeRouter-Manual-TFTP-Recovery#3

公式で出ているイメージ ER-e50.recovery.v2.0.6.5208541.190708.0508.16de5fdde.imgER-X-SFP / ER-X / EP-R6 / ER-10X (e50) をクリックして持ってきて記事通り焼くだけ。

同じように困ってしまった人は参考にしてください。

Go+XDPな開発を始めるときに参考になる記事/janog LT フォローアップ

これは JANOG LT のフォローアップブログです。 Go+XDPな開発何も説明できなかったことに気がついたので書きました。

SRv6,GTPv1,XDPの大まかな説明は世の中に神な資料があるので特に説明はしません。

もしebpfとはなんぞなどの疑問がある方は

などを合わせて見ていただけるといいと思います。

TL;TR

GoでXDPをやるときの選択肢と最近の利点

Goを利用する際の開発においての選択肢は以下のようにいくつかあります。

..etc

自分はもしその中であればcilium/ebpfを利用した開発をお勧めしております。

いくつかの理由がありますが、まず他が微妙というのもあります。 上記にあげたnewtools/ebpf をcloudflareの中の人が作っていて、それをciliumで利用を使うとなったことで新しく移動したのが cilium/ebpfです。なので中の人が同じであります。 また、 dropbox/goebpfもありますが直近ではあまりコントリビュートされず、そもそもdropboxの中のひともcilium/ebpfにコントリビュートしてるので恐らく方針としてはこちらはもう下火になると思われます。 iovisor/gobpfはCGoなので互換性問題を考えるときに辛いと思います(これは個人の趣味ぽいですね...)

で、なぜお勧めするかというと BTF対応が一番進んでいて ciliumのような巨大な実績のあるプロダクトを参考に開発を進めることができるからというのが一番大きいです。また大きい会社がバックでコントリビュートしてるのも大きいでしょう。

例えばBTFの対応の一番見かけるパターンの話の例としては、今の最新の ebpf map においての定義は 以下のようなxdpcapの書き換えのようにに .maps と書く必要があります。またトレーシングをやる人はCO-RE の影響を受けるのでなおさらBTFが必要になるでしょう。実際 kernelの sample/bpf を見ても全て今は .maps に書き換わっています。

// https://github.com/cloudflare/xdpcap
// old case
// struct bpf_map_def SEC("maps") xdpcap_hook = {
//     .type = BPF_MAP_TYPE_PROG_ARRAY, \
//     .key_size = sizeof(int), \
//     .value_size = sizeof(int), \
//     .max_entries = 5, \
// }

struct xdpcap_hook
{
    __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    __uint(key_size, sizeof(int));
    __uint(value_size, sizeof(int));
    __uint(max_entries, 5);
} xdpcap_hook SEC(".maps");

また、ebpfを使う弱点の一例としてはバイナリ一つに落とすことができないのがあったと思います。これではせっかくのGoの利点が台無しです。

なので今まではなんとか github.com/rakyll/statik などでシリアライズをしてバイナリをgoのコードにつめてワンバイナリで嬉しいですね?とか言ってたわけです。(しかもビルドのタイミングは自分でmakeなりに書く必要があって本当に面倒)

しかし cilium/ebpfには bpf2goが入り go:generate を使ってclangを叩いてビルドをしてコードに詰めて、それらをマップした構造体まで用意してくれるという便利機能が入りました。 bpf2goは今回のgoxdp-templateでは go:generate の例で動いてるので参考になると思います。

ちなみにですが、激推ししてるけどまだまだダメなところもあります。例えばnewtoolsではできた innermap をelfから生成したり、ebpfmapに書き込む際に構造体のアライメント周りが粗雑になってたりしてるので定義して使うときにはいくつかのワークアラウンドを必要とするケースがありますのでそこは今後に期待というところでしょうか....

もしこれを使ってDplaneを開発するぞ!となったらxdp-tutorial などを見てDplane開発を進めるのが良いでしょう。

終わりに

今回JANOG初参加だったんですが(オンラインだとこれは参加したと言えるのかという気持ちですが...😇)勢いで出したLTがギリギリ通っててよかったです。

学生生活最後だったので現地開催でいきたかったんですが、、、行けるときに行っておくのは重要だなぁと思いました。

あとどこかの機会で自作SRv6+XDP Dplane: Vinberoで使ってるワークアラウンドとかブログネタにしたいなぁと思いました。 例えば

  • 可変スタック上に乗る場合は ebpfmap を変数にして使うと便利
  • loopsizeにおいての上限値制限は and演算 をすると便利

とかどこのブログにも載ってなさそうなネタだと思うので、もしきになる人がいたらコードを読んでください。

また、l3vpn exampleとかあるのでよければ気が向いた時にでも遊んでみてください。まだまだ荒削りなのでバグが(多分)あると思うんですが優しくissueに書いてくれると助かります。

ではでは。