ラベル BPF の投稿を表示しています。 すべての投稿を表示
ラベル BPF の投稿を表示しています。 すべての投稿を表示

2023-12-10

MOPDの実装:select()かpoll()か

DEC製ワークステーションをネットワークから起動するために必要となるMOPDの実装を調べています。調査をすすめているうちに、横道にそれるという言うか、派生する技術についても把握しておく必要に迫られます。しかも空き時間を見つけながら調査しているので、なかなか先に進みません。


ともかく、MOPDをデーモンとして動作させるための中心部分とおもわれる「Loop()」(mopd-2.5.3/common/loo-bsd.c)を調べてみました。そこではシステムコール「select()」 が使われているのですが、NetBSD版ではシステムコール「poll()」に置き換わっています。他の実装、OpenBSD版、Linux版、FreeBSD版では、select()のままです。


システムコール「select()」と「poll()」は歴史的に見れば成り立ちが異なるようですが、それは2000年以前のUNIX乱立時代の頃の話であって、21世紀に入って20年以上も過ぎた今日では、両システムコールが実装されていないOSの存在を気にする必要はない気がします。


そうであるならば、システムコール「select()」と「poll()」の何れを用いるのが望ましいのでしょうか。select()の方が制限が厳しいようで、よりましなpoll()を使っておく方が良いとも考えられます。しかしMOPDにおいて、その制限が問題になるようなネットワーク的な同時接続数があるのかと言うと、そんな事はないと思います。程度問題なのかもしれませんが、机上の空論のような究極の状況を考慮してロジックを組むのも、やりすぎではないかとも思います。

 

NetBSD版MOPDのようにシステムコール「poll()」に置き換えるのが悪いとは思いませんが、圧倒的なメリットがある訳でもなさそうです。ならば他の実装のようにシステムコール「select()」のままにしておくのも、ひとつの判断でしょう。どちらのシステムコールを採用するのか、判断の決め手のようなものが何かあれば良いのですが。

2023-11-16

「The BSD Packet Filer: A New Architecture for User-level Packet Capture」を読んでみました

MOPDを調べようとしたら、BPFが使われているので、横道にそれてしまうようですが、BPFを理解するのを先に済ませることにしました。マニュアル「BPF(4)」を読むことも必要かと思いますが、そもそもBPFって結局何なのかを知るには大元となる論文を読むのがよさそうです。それは、1993年のWinter USENIXにおける「The BSD Packet Filter: A New Architecture for User-level Packet Capture」(Steven McCanne and Van Jacobson)との事なので、読んでみました。

 

論文の中に次のような記述がありました。

 A packet filter is simply a boolean valued function on a packet. If the value of the function is true he kernel copies the packet for the application: if it is false the packet is ignored.


これを読んで、成程そういう事かと思いました。BPFについて調べはじめた当初、Webを検索すると、何かというと「仮想マシン」の話が出てきました。何故BPFと仮想マシンが結びつくのだろうと思いましたが、論文を読んで納得しました。

 

BPFについて何を理解したら「わかった」という事になるのかという点では、いろいろと意見が別れるところだと思います。しかしMOPDを理解するためのBPFという意味では、「わかった」という事にしても構わないと思います。

2023-11-14

「BPF(BSD packet Filter)」は「パケットをフィルタリングする」だけが目的ではないような気がする

MOPDを調査するために、BPFを調べる必要を感じたので、先にそちらを見ています。ウィキペディアの「Berkeley Packet Filter」には、概要として最初に以下のような事が書かれています。

 BPFはデータリンク層へのrawインターフェイスを提供し、生のリンク層パケットの送信と受信を可能にする。

 

BPFの「PF」は「Packet Filter」なんですから、上記した記述はもっともだと思います。しかしBPFの目的はそれだけではないような気がします。ウィキペディアの概要を読み進めると、次のような記述が現れます。

この機能を利用することで、オペレーティングシステムのカーネルからプロセスへの不要なパケットのコピーが回避され、パフォーマンスが大幅に向上する。


ネットワークのパケットを送受するのはカーネル内部ですが、それをユーザプログラム側が操作しようとすると、カーネルとユーザ側の遷移が数多く発生します。そのままでは性能に悪影響を及ぼしてしまうため、特別な仕組みが用意され、それが「BPF」なのでしょう。当初の目的がネットワークのパケットをフィルタリングして、必要なものだけをユーザプログラム側で操作したかったという事なのではないかと思いますが、その為の仕組みの有用性に注目が集まっているという事のように思います。


Linuxでは「eBPF」という拡張がなされており、ウィキペディアでは「eBPFプログラムをさまざまなTracepointにアタッチする用途など、ネットワーク以外の目的でも使用できる」と書かれているように、もはやネットワークに限った技術ではなくなっているようです。しかも旧来の「BPF」との互換性はないようなので、だったら名前を「eBPF」としないで、別の名前にしたら良かったのではないかと思いますが、そうもいかなかったのかもしれません。


2023-11-13

The Icon Programming Language

MOPDの構造を調べるには、BPFを知る必要があるようです。その原理は「The BSD Packet Filter: A New Architecture for User-level Packet Capture 」という1993年に発表された論文に遡るようなので、入手しました。その論文の最後にある参照文献には、次のような記述がありました。

 [3] GRISWOLD, R. E., AND GRISWOLD, M. T. The Icon Programming Language. Prentice Hall, Inc., Englewood Cliffs, NJ, 1983.

 

Iconという言語は、あまり知られていないかと思います。今日ではテキスト処理と言ったら、PythonやPerlなどが使われると思いますが、まだAWKくらいしか選択肢が無かった頃に、SNOBOLやIconという言語を耳にすることがありました(それでもメジャーとは言い難かったと思いますが)。

 

公式サイトはありますが、今でも活動が続いているのか否かはわかりません。『The Icon Programming Language Third Edition』という書籍があり、ずいぶん前に購入しました。今でも捨てずに持っています。寄附金を募っていたようなので、ほんの僅かな金額ですが送りました。そうしたら礼状が返ってきて、感激した記憶があります。


BPFがIconをどう使っているのか詳細は不明ですが、論文には以下のような記述がありました。

 A very different application of BPF has been its incorporation into a variant of the Icon Programming Language [3].

 

Iconの公式サイトにはFreeBSDやLinux用のバイナリも置いてあります。Pythonが大流行している今日において、Iconを使う必要性があるのか何とも言えませんが、ちょっと勉強してみるのも悪くないかなと考えています。

2023-11-09

mopdの実装を調査するためにmopd/mopd.cを読んでみました。オリジナルのmopd-2.5.3が各OSの実装で変更されており、似たような変更を加えていますが、統一化が図られている訳ではないようです。 

  • mopd.cを見ると、MOPD(8)では説明されていないオプションが実装されています。ただしOpenBSD版のMOPD(8)では、そのオプションの説明が加えられています。またNetBSD版では、-sという新しいオプションが追加されています。
  • オリジナル版では、大域変数Programを用いて、argv[0]からプログラム名を得ています。ところが他の実装では、関数getprogname()や変数__prognameを利用するように変更が加えられています。
  • デーモンとして動作させるため、オリジナル版ではfork()を呼び出したりしていますが、他の実装ではdaemon()を利用するように変更が加えられています。

 

オリジナル版も他の実装にも、以下のような処理があります。このロジックならば、ForegroundFlagが指定されておらず、DebugFlagが指定されている場合に、このメッセージが出力されるという事です。しかしメッセージの「not running as daemon」と、ForegroudFlagが指定されていないという状態とが、整合していない気がします。

if ((!ForegroundFlag) && DebugFlag) {
    fprintf(stdout, "%s: not running as daemon, -d given.\n", Program);
}


MOPD(8)では、SEE ALSOにbpf(4)が記載されています。BPFというのはBerkeley Packet Filterの事だという事しか知らないので、勉強しておこうと思います。