Kernel/VM/探検隊online part1 (自分のツィートのみ) #kernelvm_tw

0
Yoshikazu GOTO @goto_ipv6

Linux のネットワーク機能のデバッグツールを作ったのでその話を今日は。 #kernelvm #kernelvm_tw

2020-06-06 14:00:00
Yoshikazu GOTO @goto_ipv6

ipftrace: ・Linuxのネットワーク機能に特化した関数コールトレーサー ・カーネルの中で、あるパケットがどの関数を通ったのかのトレースが取れる #kernelvm #kernelvm_tw

2020-06-06 14:00:33
Yoshikazu GOTO @goto_ipv6

モチベーション: ・仕事柄、Linux のネットワーク機能をヘビーに使う ・でもパケットは往々にしてどこかに行っちゃう →Drop、意図した方向にルーティングされないなど #kernelvm #kernelvm_tw

2020-06-06 14:02:41
Yoshikazu GOTO @goto_ipv6

・どうしても原因がわからない場合はソースを見るしか無い →ソースを読んだだけではわかることは少ない →実行して挙動を確認したい #kernelvm #kernelvm_tw

2020-06-06 14:02:42
Yoshikazu GOTO @goto_ipv6

System Tap, bpftrace: ・C と awk をあわせたような DSL を使ってトレースが書ける ・関数の呼び出しなどをフックして引数の値などを出力 ・トレースする対象はユーザーが指定 →何も手がかりがないと使いづらい #kernelvm #kernelvm_tw

2020-06-06 14:03:42
Yoshikazu GOTO @goto_ipv6

ftrace: ・カーネル全体の関数呼び出しのトレースが取れる ・何も手がかりがない状態でも使いやすいが、スクリプティングの機能はない ・出力がファジーになりがち →ネットワーク以外も混ざるので #kernelvm #kernelvm_tw

2020-06-06 14:04:29
Yoshikazu GOTO @goto_ipv6

Network domain specific requirement: ・特定のパケットの処理だけを見ることができない問題 ・関数呼び出しのトレースだけではどのパケットを処理しているかわからない #kernelvm #kernelvm_tw

2020-06-06 14:05:41
Yoshikazu GOTO @goto_ipv6

Requirement: ・こんなトレーサーがほしい →何も手がかりがない状態で使いやすい→関数コールトレーサー →パケットを処理する関数以外にはそんなに興味がない →パケット単位でトレースしたい #kernelvm #kernelvm_tw

2020-06-06 14:06:39
Yoshikazu GOTO @goto_ipv6

→SsytemTapやbpftrace みたいなスクリプティングの機能もほしい #kernelvm #kernelvm_tw

2020-06-06 14:06:40
Yoshikazu GOTO @goto_ipv6

ipftrace の動作: ・Linux のネットワーク処理は、パケット (struct sk_buff *) を引数に取る関数に、パケットを通していくような形をしている #kernelvm #kernelvm_tw

2020-06-06 14:07:49
Yoshikazu GOTO @goto_ipv6

(このあたりのソースコードは読んだなぁ、昔) #kernelvm #kernelvm_tw

2020-06-06 14:07:59
Yoshikazu GOTO @goto_ipv6

・skb を引数に取る関数だけを全部フックして skb のポインタ値ごとでトレースログを取れば、パケットが通った関数のリストが得られる #kernelvm #kernelvm_tw

2020-06-06 14:08:30
Yoshikazu GOTO @goto_ipv6

(なるほど、そういうアイデアはなかった。確かに引数) #kernelvm #kernelvm_tw

2020-06-06 14:08:54
Yoshikazu GOTO @goto_ipv6

・skb に "mark" をつけてそれを見ることによって特定のパケットだけをトレースできる #kernelvm #kernelvm_tw

2020-06-06 14:09:37
Yoshikazu GOTO @goto_ipv6

・skb を引数に取る関数を全部取得する →カーネルにこのような機能はない →→C の話なので →デバッグ情報から取ってくる必要がある →→DWARF か BTF を使って #kernelvm #kernelvm_tw

2020-06-06 14:10:38
Yoshikazu GOTO @goto_ipv6

・skb を引数に取る関数を全部フックしてトレースログを出す →kprobe + eBPF + perf_event #kernelvm #kernelvm_tw

2020-06-06 14:11:56
Yoshikazu GOTO @goto_ipv6

・skb に mark をつける →skb-mark という自由に使える 32bit のフィールドがある →iptables (netfilter) や tc, setsockopt(SO_MARK) などで書き込みができる #kernelvm #kernelvm_tw

2020-06-06 14:12:41
Yoshikazu GOTO @goto_ipv6

→これらで記述できる任意の条件でパケットにマークを付けられる →netns をまたぐと消える→コンテナのトレーシングに便利 #kernelvm #kernelvm_tw

2020-06-06 14:13:23
Yoshikazu GOTO @goto_ipv6

Scripting: ・関数が呼び出されたときの skb についているデータもちょっと見たい →例えば、データがどこでおかしくなったのかを追いたいときに ・ちょっとしたプログラマビリティがほしい ・Lua で拡張できるように #kernelvm #kernelvm_tw

2020-06-06 14:15:01
Yoshikazu GOTO @goto_ipv6

・Lua で emit, dump の 2つを書くと出力をカスタマイズできる ・emit: 追加のデータを集める eBPF のバイトコードを吐く ・dump: emit で集めたデータを整形した文字列を吐く #kernelvm #kernelvm_tw

2020-06-06 14:15:59
Yoshikazu GOTO @goto_ipv6

Linux version & architecuture dependency issue: ・Linuxのバージョンが変わると構造体のフォーマットが変わる #kernelvm #kernelvm_tw

2020-06-06 14:16:39
Yoshikazu GOTO @goto_ipv6

・デバッグ情報を使って構造体メンバーのオフセットやデータ型のサイズを実行時に解決 ・Lua からは iptf.offsetof/sizeof/typeof を使ってデバッグ情報をクエリできるように #kernelvm #kernelvm_tw

2020-06-06 14:17:22
Yoshikazu GOTO @goto_ipv6

仕事で役に立ったことが: ・Linux の SRv6 の TSO/GSO 処理にバグが有り、特定の設定で性能が悪くなる ・ipftrace を使用して原因を特定 ・修正パッチを upstream #kernelvm #kernelvm_tw

2020-06-06 14:18:21
Yoshikazu GOTO @goto_ipv6

(昔、こんなツールがあったら……) #kernelvm #kernelvm_tw

2020-06-06 14:18:47
Yoshikazu GOTO @goto_ipv6

・Linux はキャッシュのヒット率を上げるために同じ skb のメモリを使い回す ・ipftrace は skb のアドレスを使ってパケットを区別する ・機械で処理をするのは難しい →人間が見るとわかるのだが #kernelvm #kernelvm_tw

2020-06-06 14:22:24