分12第584回ではカーネルデバッグツールのひとつ「SystemTap」を紹介しました。今回はより実践的な例として,Ethernetフレームがドロップした際のMACアドレスを出力してみましょう。droppedになったフレームのMACアドレスを調べるLinuxは予期しないEthernetフレームを受け取ったとき,その内容によっては意図的に破棄し,ネットワークインターフェースのdroppedカウンターをインクリメントします。通常のネットワーク環境だとほぼ0なのですが,特定の機器や構成によっては恒常的にdroppedカウンターが増えることもあります。そこでこのdroppedカウンターが上昇した理由を調べるために,droppedカウンター増加時のEthernetフレームの送信元・送信先のMACアドレスを,今回はSystemTapを用いて確認してみましょう。予期しないEthernetフレームを送る仕組みを作るまずはテスト用に予期しないEthernetフレームを送る仕組みを作ります。今回はテスト用なのでloインターフェースを対象にします。show」コマンドで確認できます。ローカルのループバックインターフェースは次のとおりです。0上記の「dorpped」の部分ですね。今回の例では受信フレームのみを扱いますので,「⁠RX:」で始まっているほうを確認してください。「予期しないEthernetフレーム」にはいろいろありますが,代表的なのはEtherTypeフィールドが「サポートしていないEtherType」だった場合です。カーネル側が届いたフレームのEtherTypeをどう扱うか不明な場合にdroppedとなります。IPv6のフレームならEtherTypeには0x86DDが入ります。このEtherTypeが使用しているカーネルでサポートしていない値(たとえば0x4321など)になっているフレームを受信するとdroppedが増えるというわけです(※1⁠)⁠。※1たとえばBuffaloのスイッチはループ防止機能として2秒に1回検出用フレームをブロードキャストする機能が存在します。Protocol)用の「0x8899」なEtherTypeをなぜか設定するようです。dropped」カウンターが増えていくことになります。ユーザーランド側で「SOCK_RAW/ETH_P_ALLなsocket()」を作成した場合,すべてのEtherTypeが一度ユーザーランドにあがる(=カーネル側から見るとサポートしていないEtherTypeが存在しない)ため,droppedなフレームとしては表示されません。任意のバイト列のEthernetフレームを送信する方法はいろいろ存在しますが,今回は次のようなPythonスクリプト(errframe.py)を作成し,利用することにします。payload)コード自体は特に難しいものではないと思います。送信元のMACアドレス(src)としてRFC7042に記載のある文書用のMACアドレスを指定しているのは,特に大きな理由はありません。今回は送信元も送信先もローカルループバックなので,送信先MACアドレスであるdstも送信元インターフェースであるinterfaceもそれに合わせています。payloadには最小フレームサイズを満たすよう0で埋めたバイト列を作っているだけです。後半はSOCK_RAWなsocket()を作成して,インターフェースにbind()し,send()で生のEthernetフレームを送っています。送信元と送信先が一緒になっているため多少わかりにくいかもしれません。実際にdrooppedが起きるのは実デバイスに紐付いたインターフェースのはずなので,srcやdst,interfaceはそれらに合わせて適宜変更してください。実際にこのコードを実行してから,再度loの情報を表示してみましょう。0無事にdroppedが1増えました。droppedカウンターが更新されたことを表示するこの受信用のdroppedカウンターはいくつかの箇所で更新されうるのですが,今回はそのあたりの話をすっとばして,具体的なコードの場所に移動します。net/core/dev.cの__netif_receive_skb_core()では,いくつかの条件において関数内のdropラベルにジャンプし,ネットワークインターフェースのrx_droppedを更新します。NET_RX_DROP;atomic_long_inc(&skb->dev->rx_dropped)がまさにその場所です。コードを見るとわかるように,条件によってはrx_droppedではなくrx_nohandlerが上がることもあるようです。いうわけでこのラベルにジャンプするかどうかを確認してみましょう。SystemTapには「.label("FOO")」というフィルタリングルールがあるため,簡単にプローブポイントを指定できます。dropped\n");}早速,このSTPスクリプトを実行しつつ,先ほどのPythonスクリプトを動かしてください。ちなみにこれ以降,STPスクリプトのファイル名は「drop.stp」であるとします。dropped裏でerrframe.pyを実行するたびに,上記が表示されるはずです。Ctrl-Cを入力してstapコマンドを終了しておきましょう。