The BSD Packet Filter: A New Architecture for User-level Packet Capture

Steven McCanne and Van Jacobson
Lawrence Berkeley Laboratory
One Cyclotron Road
Berkeley, CA 94720
mccanne@ee.lbl.gov, van@ee.lbl.gov

December 19, 1992



Abstract

Many versions of Unix provide facilities for user-level packet capture, making possible the use of general purpose workstations for network monitoring. Because network monitors run as user-level processes, packets must be copied across the kernel/user-space protection boundary. This copying can be minimized by deploying a kernel agent called a packet filter, which discards unwanted packets as early as possible. The original Unix packet filter was designed around a stack-based filter evaluator that performs sub-optimally on current RISC CPUs. The BSD Packet Filter (BPF) uses a new, register-based filter evaluator that is up to 20 times faster than the original design. BPF also uses a straightforward buffering strategy that makes its overall performance up to 100 times faster than Sun's NIT running on the same hardware.
Unixの多くのバージョンが、 ネットワーク・モニタリングのための 一般的な目的ワークステーションの使用を可能にして、 ユーザレベルパケット捕獲に設備を供給します。 ネットワーク・モニターがユーザレベルプロセスとして走るので、 パケットは、核/ユーザスペース保護境界を横切ってコピーされるに違いありません。 この複写は、パケットフィルター(それはできるだけ早く望まれない パケットを廃棄する)と呼ばれる核代理人を展開させることにより 最小限にすることができます。 オリジナルのUnixパケットフィルターは、 現在のRISC CPU上でサブ最良に実行する スタックベースのフィルタ検討者のまわりで設計されました。 BSDパケットフィルター(BPF)は、オリジナルの設計より20倍以内速い新しく、 登録に基づいたフィルタ検討者を使用します。 BPFは、さらにその全面的な実行を同じハードウェア上で走る サンのNITより100倍以内速く行なう、 バッファーを用いた真直ぐな戦略を使用します。



1 Introduction

Unix has become synonymous with high quality networking and today's Unix users depend on having reliable, responsive network access. Unfortunately, this dependence means that network trouble can make it impossible to get useful work done and increasingly users and system administrators find that a large part of their time is spent isolating and fixing network problems. Problem solving requires appropriate diagnostic and analysis tools and, ideally, these tools should be available where the problems are-on Unix workstations. To allow such tools to be constructed, a kernel must contain some facility that gives user-level programs access to raw, unprocessed network traffic.[7] Most of today's workstation operating systems contain such a facility, e.g., NIT[10] in SunOS, the Ultrix Packet Filter[2] in DEC's Ultrix and Snoop in SGI's IRIX.
Unixは高品質ネットワーキングと同義になりました。 また、今日のUnixユーザは信頼できて反応する ネットワーク・アクセスを持っていることを当てにします。 不運にも、この依存は、ネットワーク問題が有用な仕事を行うのを 不可能にすることができることを意味します。 また、ますます、ユーザとシステム管理者は、 それらの時間の大部分が費やされた分離し 固定ネットワーク問題であることを知ります。 問題解決は適切な診断と分析ツールを要求します。 また、理想的に、その問題がUnixワークステーションであるオン場合、 これらのツールは利用可能であるべきです。 構築されるそのようなツールを許可するために、 核は、ユーザレベル・プログラムに生で加工されていない ネットワーク交通へのアクセスを与えるある 設備を含んでいなければなりません。[7] 今日のワークステーション・オペレーティング・システムのうちの ほとんどはSunOSにそのような設備(例えばNIT[10])を含んでいます、 DECのUltrixの中のUltrixパケットフィルター[2] またSGIのIRIXの中でスヌープします。

These kernel facilities derive from pioneering work done at CMU and Stanford to adapt the Xerox Alto `packet filter' to a Unix kernel[8]. When completed in 1980, the CMU/Stanford Packet Filter, CSPF, provided a much needed and widely used facility. However on today's machines its performance, and the performance of its descendents, leave much to be de- sired - a design that was entirely appropriate for a 64KB PDP-11 is simply not a good match to a 16MB Sparcstation 2. This paper describes the BSD Packet Filter, BPF, a new kernel architecture for packet capture. BPF offers substan- tial performance improvement over existing packet capture facilities-10 to 150 times faster than Sun's NIT and 1.5 to 20 times faster than CSPF on the same hardware and traffic mix. The performance increase is the result of two architectural improvements:
これらの核設備は、Unix核[8]にゼロックス・アルト「パケットフィルター」を 適応させるためにCMUとスタンフォードで終わった仕事の開拓に由来します。 1980年に完成した時、CMU/スタンフォードのパケットフィルター(CSPF)は 非常に必要とされ、広く用いられている設備を提供しました。 今日の機械上で(しかしながら)その業績およびその子孫の業績、 あるために多くを望むおく―64KB PDP-11に完全に適切だった設計は 単に16MBのSparcstation 2への良縁ではありません。 この論文はBSDパケットフィルター、 BPF(パケット捕獲用の新しい核アーキテクチャー)について記述します。 BPFは、既存のパケット上の実質的履行改良を提示します、 設備-10を捕らえる、に、サンのNITおよび1.5より150倍速く、に、 同じハードウェアおよび交通上のCSPFより20倍速く、 混合します。実行増加は2つの建築上の改良の結果です:

In this paper, we present the design of BPF, outline how it interfaces with the rest of the system, and describe the new approach to the filtering mechanism. Finally, we present performance measurements of BPF, NIT, and CSPF which show why BPF performs better than the other approaches.
この論文では、私たちが、BPFのデザインを示します、 概説する、どのように、それ、システムの残りとのインターフェース、 またろ過するメカニズムへの新しいアプローチについて記述します。 最後に、私たちは、なぜBPFが他のアプローチよりよく 実行するか示すBPF、NITおよびCSPFの性能測定を示します。


2 The Network Tap

BPF has two main components: the network tap and the packet filter. The network tap collects copies of packets from the network device drivers and delivers them to listening applications. The filter decides if a packet should be accepted and, if so, how much of it to copy to the listening application. Figure 1 illustrates BPF's interface with the rest of the system. When a packet arrives at a network interface the link level device driver normally sends it up the system protocol stack. But when BPF is listening on this interface, the driver first calls BPF. BPF feeds the packet to each participating process' filter. This user-defined filter decides whether a packet is to be accepted and how many bytes of each packet should be saved. For each filter that accepts the packet, BPF copies the requested amount of data to the buffer associated with that filter. The device driver then regains control. If the packet was not addressed to the local host, the driver returns from the interrupt. Otherwise, normal protocol processing proceeds.
BPFは2つの主要なコンポーネントを持っています: ネットワーク・タップおよびパケットフィルター。 ネットワーク・タップはネットワーク・デバイス・ドライバから 部のパケットを集めて、聞く適用にそれらを配達します。 フィルタは、パケットが受理されるべきかどうか決定します、 そして、そうならば、どのように、聞く適用にコピーするためにそれに非常に。 図1はBPFのインターフェースをシステムの残りで例証します。 パケットがネットワークインターフェイスに到着する場合、 リンク・レベル・デバイス・ドライバは 通常システム・プロトコル・スタックを上へそれを送ります。 しかし、BPFがこのインターフェース上で聞いている場合、 ドライバーは最初にBPFを呼びます。 BPFは各参加するプロセスのフィルタにパケットを与えます。 このユーザに定義されたフィルタは、 パケットが受理されることになっているかどうか 各パケットのどれだけのバイトを保存しなければならないか、決定します。 パケットを受理するフィルタごとについては、 BPFがそのフィルタに関連したバッファーに要求された量の データをコピーします。 その後、デバイス・ドライバはコントロールを回復します。 パケットが地方のホストに出されなかった場合、 ドライバーは割り込みから戻ります。 そうでなければ、正常なプロトコル処理は進みます。

Figure 1: BPF Overview

Since a process might want to look at every packet on a network and the time between packets can be only a few microseconds, it is not possible to do a read system call per packet and BPF must collect the data from several packets and return it as a unit when the monitoring application does a read. To maintain packet boundaries, BPF encapsulates the captured data from each packet with a header that includes a time stamp, length, and offsets for data alignment.
プロセスがネットワーク上のすべてのパケットを見たいかもしれないし、 パケット間の時間が数マイクロセカンドだけでありえるので、 1つのパケット当たり読み取りシステムコールを行うことは可能ではありません。 また、BPFはいくつかのパケットからデータを集めるに違いないし、 モニタリング適用が読み取りを行う場合、 1ユニットとしてそれを返すに違いありません。 パケット境界を維持するために、 BPFは、タイムスタンプ、 長さおよびデータ整列のためのオフセットを含んでいる ヘッダーを備えた各パケットからの捕らえられたデータをカプセルに入れます。


2.1 Packet Filtering

Because network monitors often want only a small subset of network traffic, a dramatic performance gain is realized by filtering out unwanted packets in interrupt context. To minimize memory traffic, the major bottleneck in most modern workstations, the packet should be filtered `in place' (e.g., where the network interface DMA engine put it) rather than copied to some other kernel buffer before filtering. Thus, if the packet is not accepted, only those bytes that were needed by the filtering process are referenced by the host.
ネットワーク・モニターがネットワーク交通の小さな部分集合だけを しばしば望むので、劇的な実行利得は、 割り込み情況中の望まれないパケットをろ過することにより実現されます。 メモリ交通(最も現代のワークステーション中の主なボトルネック)を 最小限にするために、フィルタリングの前に他のある 核バッファーにコピーされたのではなく (例えばネットワークインターフェイスDMAエンジンがそれを置いたところで)、 パケットは適所にろ過されるべきです。 したがって、パケットが受理されない場合、 参照がホストによってろ過するプロセスによって 必要だったバイトだけに付けられます。

In contrast, SunOS's STREAMS NIT [10] copies the packets before filtering and as a result suffers a performance degradation. The STREAMS packet filter module ( nit_pf(4M) ) sits on top of the packet capture module ( nit_if(4M) ). Each packet received is copied to an mbuf, and passed off to NIT, which then allocates a STREAMS message buffer and copies in the packet. The message buffer is then sent upstream to the packet filter, which may decide to discard the packet. Thus, a copy of each packet is always made, and many CPU cycles will be wasted copying unwanted packets.
対照的に、SunOSのSTREAMS NIT[10]はフィルタリングの前にパケットをコピーし、 その結果実行低下を受けます。 STREAMSパケットフィルター・モジュール( nit_pf(4M) )パケット捕獲モジュール (受け取られた各パケットがコピーされる nit_if(4M) ). 、mbuf、 またNIT (その後、それはSTREAMSメッセージ・バッファーおよび パケット中のコピーを割り付ける)に離れて通過した。 その後、メッセージ・バッファーは、 パケットフィルター (それはパケットを廃棄することを決定してもよい)へ上流に送られます。 したがって、1部の各パケットは常に作られます、 また、多くのCPUサイクルが衰弱した複写になるでしょう、 望まれないパケット)の上に座る。


2.2 Tap Performance Measurements

Before discussing the details of the packet filter, we present some measurements which compare the the relative costs of the BPF and SunOS STREAMS buffering models. This performance is independent of the packet filtering machinery.
パケットフィルターの詳細について議論する前に、 私たちは、匹敵するいくつかの測定を示します、 その(モデル)バッファーを用いたBPFとSunOSのSTREAMSの相対的なコスト。 この実行はパケットフィルタリング機械類に依存しません。

We configured both BPF and NIT into the same SunOS 4.1.1 kernel, and took our measurements on a Sparcstation 2. The measurements reflect the overhead incurred during the interrupt processing - i.e., how long it takes each system to stash the packet into a buffer. For BPF we simply measured the before and after times of the tap call, bpf_tap() , using the Sparcstation's microsecond clock. For NIT we measured the time of the tap call snit_intr() plus the additional overhead of copying promiscuous packets to mbufs. (Promiscuous pack- ets are those packets which were not addressed to the local host, and are present only because the packet filter is run- ning.) In other words, we included the performance hit that NIT takes for not filtering packets in place. To obtain accurate timings, interrupts were locked out during the instrumented code segments.
私たちは同じSunOS 4.1.1核へBPFおよびNITの両方を形成し、 Sparcstation 2の上で私たちの測定をとりました。 その測定は、割り込み処理中に招かれたオーバーヘッドを反映します。 つまり、バッファーへパケットをしまっておくことは、 どれくらいの時間各システムに必要とするか。 BPFについては、私たちが単に測定しました、 その、タップ呼び出し、bpf_tap()の回の前に、 およびtimeの後にSparcstationのマイクロセカンド時計の使用。 NITについては、私たちが、タップ呼び出しsnit_intr()の時間を測定しました。 mbufsに乱雑なパケットをコピーする補足オーバーヘッドを増してください。 (乱雑なパケットは地方のホストに出されず、 ただパケットフィルターが走っているので、存在するパケットです。) 言いかえれば、私たちは、 NITが適所にパケットをろ過しないために受ける実行打撃を含みました。 正確なタイミングを得るために、割り込みは、 機器を備えたコードセグメント中にロックされました。

The data sets were taken as a histogram of processing time versus packet length. We plotted the mean processing per packet versus packet size, for two configurations: an "accept all" filter, and a "reject all" filter.
データセットは、 時間対パケット長さを処理するヒストグラムとして得られました。 私たちは、2つの配置のために、 パケット対パケット・サイズについて中間の処理を計画しました: 1つの「すべてを受理します」フィルタ、 そして1つの「すべてを拒絶します」フィルタ。

In the first case, the STREAMS NIT buffering module ( nit_buf(4M) ) was pushed on the NIT stream with its chunk-size parameter set to the 16K bytes. Similarly, BPF was configured to use 16K buffers. The packet filtering module which usually sits between the NIT interface and NIT buffering modules was omitted to effect "accept all" semantics. In both cases, no truncation limits were specified. This data is shown in Figure 2. Both BPF and NIT show a linear growth with captured packet size reflecting the cost of packet-to-filter buffer copies. However the different slopes of the BPF and NIT lines show that BPF does its copies at memory speed (148ns/byte) while NIT runs 45% slower (216ns/byte). The y-intercept gives the fixed per-packet processing overhead: The overhead of a BPF call is about 6us while NIT is 15 times worse at 89us per packet. Much of this huge disparity appears to be due to the cost of allocating and initializing a buffer under the remarkably baroque AT&T STREAM I/O system.
第1のケース、STREAMS NITバッファーを用いたモジュール( nit_buf(4M) )にその塊サイズを備えたNIT流れに押しつけられました。 16Kバイトまでパラメーター・セット。 同様に、BPFは16Kのバッファーを使用するために形成されました。 (モジュール)バッファーを用いたNITインターフェース およびNITの間に通常座るパケットフィルタリング・モジュールは 達成するために省略されました「すべてを受理します」意味論。 両方の場合では、切断範囲が指定されませんでした。 このデータは図2の中で示されます。BPFおよびNITの両方は、 ろ過するパケットバッファー・コピーのコストを反映する、 捕らえられたパケット・サイズを備えた線形の成長を示します。 しかしながら、BPFとNITのラインの異なる傾斜は、 NITが45%遅く(216ns/バイト)なっている一方 メモリ速度(148ns/バイト)でBPFがそのコピーを?sうことを示します。 その、y-遮る、パケットごとの固定処理オーバーヘッドを与える: NITが1つのパケット当たり89usで15倍悪い間、 BPF呼び出しのオーバーヘッドは6usに関係しています。 非常に、これに、巨大な不均衡は、 著しくバロック式のAT&T STREAM I/Oシステムの下の バッファーを割り付けて初期化するコストによるように見えます。

Figure 2: NIT versus BPF: "accept all"

Figure 3 shows the results for the "reject all" configuration. Herethe STREAMS packet filter module was configured with a "reject all" filter and pushed directly on top of the NIT interface module (the NIT buffering module was not used). Since the filter discards all packets, the processing time should be constant, independent of the packet size. For BPF this is true - we see essentially the same fixed cost as last time (5s instead of 6 since rejecting avoids a call to the BPF copy routine) and no effect due to packet size. However, as explained earlier, NIT doesn't filter packets in place but instead copies packets then runs the filter over the copies. Thus the cost of running NIT increases with packet size even when the packet is discarded by the filter . For large packets, this gratuitous copy makes NIT almost two orders of magnitude more expensive than BPF (450us vs. 5s). The major lesson here is that filtering packets early and in place pays off. While a STREAMS-like design might ap- pear to be modular and elegant, the performance implications of module partitioning need to be considered in the design. We claim that even a STREAMS-based network tap should include the packet filtering and buffering functionality in its lowest layer. There is very little design advantage in factor- ing the packet filter into a separate streams module, but great performance advantage in integrating the packet filter and the tap into a single unit.
図3は結果を示します、のために、その「すべてを拒絶します」配置。 Herethe STREAMSパケットフィルター・モジュールは形成されました、 1つの「すべてを拒絶します」フィルタ、 またNITインターフェース・モジュール ((モジュール)バッファーを用いたNITは使用されませんでした) の上に直接押されました。 フィルタがパケットをすべて廃棄するので、 処理時間はパケット・サイズと無関係に一定に違いありません。 BPFについては、これが真実です―私たちは同じ固定費を本質的に見ます、 として、時に (拒絶以来の6の代わりに5sは、BPFコピー・ルーチンへの呼び出しを回避します) またパケット・サイズによる効力はない。 以前に説明されるように、(しかしながら)、 NITは、適所にしかし代わりにパケットをろ過しません、 コピー、パケット、その後、コピー上でフィルタを実行します。 したがってパケットがフィルタによって廃棄される場合にさえ パケット・サイズを備えたNIT増加を実行するコスト。 大きなパケットについては、この無料のコピーが NITをBPF(450us対5s)より高価なほとんど2つの桁にします。 主なレッスンはここで、パケットを初期に適所にろ過することが 成果をあげるということです。
STREAMSのような設計がモジュールで上品に見えているかもしれない一方、 モジュールを分割する実行含意を設計の中で 考慮する必要があります。 私たちは、その最低の層にSTREAMSに基づいた ネットワーク・タップさえがパケットフィルタリング およびバッファーを用いた機能性を含むべきであると主張します。 個別の流れモジュールへパケットフィル?^ーを 因数分解することでの設計利点だが単一のユニットへ パケットフィルターおよびタップを統合することでの 大きな実行利点はほとんどありません。

Figure 3: NIT versus BPF: "reject all"

3 The Filter Model

Assuming one uses reasonable care in the design of the buffering model, it will be the dominant cost of packets you accept while the packet filter computation will be the dominant cost of packets you reject. Most applications of a packet capture facility reject far more packets than they accept and, thus, good performance of the packet filter is critical to good over- all performance.
1つの仮定はバッファーを用いたモデルのデザインの中で合理的な注意を使用します。 それは、パケットフィルター計算が拒絶するパケットの 支配的なコストになっているかもしれない一方、 受理するパケットの支配的なコストになるでしょう。 パケット捕獲設備のほとんどの適用は それらが受理するよりはるかに多くのパケットを拒絶します。 また、したがって、パケットフィルターの よいパフォーマンスはよい全面的なパフォーマンスに重大です。

A packet filter is simply a boolean valued function on a packet. If the value of the function is true the kernel copies the packet for the application; if it is false the packet is ignored. Historically there have been two approaches to the fil- ter abstraction: a boolean expression tree (used by CSPF) and a directed acyclic control flow graph or CFG (first used by NNStat[1] and used by BPF). For example, Figure 4 illustrates the two models with a filter that recognizes either IP or ARP packets on an Ethernet. In the tree model each node represents a boolean operation while the leaves represent test predicates on packet fields. The edges represent operator-operand relationships. In the CFG model each node represents a packet field predicate while the edges represent control transfers. The righthand branch is traversed if the predicate is true, the lefthand branch if false. There are two terminating leaves which represent true and false for the entire filter.
パケットフィルターは単にパケット上のブールの価値のある機能です。 機能の値が真実の場合核は、適用用のパケットをコピーします; それが誤りの場合パケットが無視されます。 歴史上、フィルタ抽象への2つのアプローチがありました: ブールの表現木(CSPFによって使用された) および指図された非有輪のコントロール・フロー・グラフか、 CFG(最初にNNStat[1]によって使用され、BPFによって使用された)。 例えば、図4は2つのモデルをイーサネット上の IPあるいはARPのパケットのいずれかを認識するフィルタで例証します。 木モデルでは、葉がパケット競技場でテスト述語を表わしている一方、 各ノードはブールのオペレーションを表わします。 端はオペレーターオペランド関係を表わします。 CFGモデルでは、コントロールが移ると端が言っている一方、 各ノードはパケット・フィールド述語を表わします。 述語が真実の場合、右手枝は横断されます(誤りの場合左手枝)。 言う2枚の終了する葉があります、真実そして全フィルタには誤りです。

These two models of filtering are computationally equivalent. I.e., any filter that can be expressed in one can be expressed in the other. However, in implementation they are very different: The tree model maps naturally into code for a stack machine while the CFG model maps naturally into code for a register machine. Since most modern machines are register based, we will argue that the CFG approach lends itself to a more efficient implementation.
フィルタリングのこれらの2つのモデルは計算上等価です。 つまり、一つの中で表現することができるどんなフィルタは 他方の中で表現することができます。 しかしながら、インプリメンテーションでは、 それらは非常に異なります:CFGモデルが登録機械のためのコードへ 当然写像している一方、木モデルは、スタック機械のためのコードへ当然写像します。 最も現代の機械が基づいた登録であるので、 私たちはCFGアプローチがより効率的なインプリメンテーションに 向いていると主張するでしょう。


3.1 The CSPF (Tree) Model

The CSPF filter engine is based on an operand stack. In structions either push constants or packet data on the stack, or perform a binary boolean or bitwise operation on the top two elements. A filter program is a sequentially executed list of instructions. After evaluating a program, if the top of stack has a non-zero value or the stack is empty then the packet is accepted, otherwise it is rejected.
CSPFフィルタ・エンジンはオペランド・スタックに基づきます。 structionsの中で、スタック上の押し定数あるいはパケット・データ、 あるいは実行する、1つの、2進法、ブール、あるいはトップ2つの要素に対する ビット的にオペレーション。 フィルタ・プログラムは指示の連続して実行されたリストです。 スタックのトップが0でない値あるいはスタックを持っている場合、 プログラムの評価が空の後、その後、パケットはそうでなければ受理されます、 それが拒絶されます。

There are two implementation shortcomings of the expression tree approach:
表現木アプローチの2つのインプリメンテーション欠点があります:

Figure 4: Filter Function Representations.

Another problem with CSPF, recognized by the designers, is its inability to parse variable length packet headers, e.g., TCP headers encapsulated in a variable length IP header. Because the CSPF instruction set didn't include an indirection operator, only packet data at fixed offsets is accessible. Also, the CSPF model is restricted to a single sixteen bit data type which results in a doubling of the number of operations to manipulate 32 bit data such as Internet addresses or TCP sequence numbers. Finally, the design does not permit access to the last byte of an odd-length packet.
デザイナーによって認識されたCSPFに関する別の問題は 可変長さパケット・ヘッダー (例えば可変長さIPヘッダーの中でカプセルに入れられたTCPヘッダー) を解析するその無力です。 CSPF指示セットが間接オペレーターを含んでいなかったので、 固定オフセットのパケット・データだけがアクセス可能です。 さらに、CSPFモデ??aモデル、オペレーションの番号の インターネット・アドレスあるいはTCPシーケンス番号のような 32ビットのデータを操作するために2倍になることに帰着する 単一の16ビットのデータ・タイプに制限されます。 最後に、設計は、奇妙な長さのパケットの 最後のバイトへのアクセスを許しません。

While the CSPF model has shortcomings, it offers a novel generalization of packet filtering: The idea of putting a pseudo-machine language interpreter in the kernel provides a nice abstraction for describing and implementing the filtering mechanism. And, since CSPF treats a packet as a simple array of bytes, the filtering model is completely protocol indepen- dent. (The application that specifies the filter is responsible for encoding the filter appropriately for the underlying network media and protocols.)
CSPFモデルが欠点を持っている一方、 それはパケットフィルタリングの斬新な一般化を提示します: 核に偽りの機械語のインタープリターを入れる考えは、 ろ過するメカニズムについて記述しインプリメントするために よい抽象的概念を提供します。 また、CSPFがバイトの単純な配列としてパケットを扱うので、 ろ過?キるモデルは完全にプロトコルです、 独立した (フィルタが根本的なネットワーク・メディア およびプロトコル用にフィルタを適切にコード化すること原因であることを 明示する適用。)

The BPF model, described in the next section, is an attempt to maintain the strengths of CSPF while addressing its limitations and the performance shortcomings of the stack-based filter machine.
次のセクションに記述されたBPFモデルはその制限に取り組む間の CSPFの強さおよびスタックに基づいたフィルタ機械の実行欠点を維持する試みです。


3.2 The BPF Model


3.2.1 CFGs vs. Trees

BPF uses the CFG filter model since it has a significant performance advantage over the expression tree model. While the tree model may need to redundantly parse a packet many times, the CFG model allows parse information to be `built into' the flow graph. I.e., packet parse state is `remembered' in the graph since you know what paths you must have traversed to reach to a particular node and once a subexpression is evaluated it need not be recomputed since the control flow graph can always be (re-)organized so the value is only used at nodes that follow the original computation.
それが表現木モデルに関する重要な実行長所を持つので、 BPFはCFGフィルタ・モデルを使用します。 木モデルがパケットを余分に何度も解析している必要があるかもしれない一方、 CFGモデルは許可します「構築される情報を解析する」フロー・グラフ。 つまり、パケット、状態を解析する、中へ「記憶される」グラフ、 特別のノードにどのパスに達するために、 横断したに違いないかあなたが知っており、 一度、subexpressionが評価されるので、 コントロール・フロー・グラフが常にそうでありうる(re)ので、 それを再計算する必要がありません、 値がオリジナルの計算に続くノードで単に使用されるように、 組織しました。

Figure 5: CFG Filter Function for "host foo".

For example, Figure 5 shows a CFG filter function that ac- cepts all packets with an Internet address foo . We consider a scenario where the network layer protocols are IP, ARP, and Reverse ARP, all of which contain source and destination Internet addresses. The filter should catch all cases. Accord- ingly, the link layer type field is tested first. In the case of IP packets, the IP host address fields are queried, while in the case of ARP packets, the ARP address fields are used. Note that once we learn that the packet is IP, we do not need to check that it might be ARP or RARP. In the expression tree model, shown in figure 6, seven comparison predicates and six boolean operations are required to traverse the entire tree. The longest path through the CFG has five comparison operations, and the average number of comparisons is three.
例えば、図5は、インターネット・アドレスfooを備えたパケットを すべて受理するCFGフィルタ機能を示します。 .ネットワーク層プロトコルがIP、ARPおよび逆のARP (それらのすべては出所と目的地のインターネット・アドレスを含んでいる) である場合、私たちはシナリオを考慮します。 フィルタはすべてのケースをつかむべきです。 従って、リンク層タイプ・フィールドは最初にテストされます。 IPパケットの場合には、ARPのパケットの場合には、 ARPアドレス・フィールドが使用されている一方、 IPホスト・アドレス・フィールドは尋ねられます。 一旦パケットがIPであることを知れば 私たちが、それがARPまたはRARPかもしれないことを チェックする必要がないことに注意してください。 図6の中で示される表現木モデルでは、7つの比較が断定します。 また、6つのブールのオペレーションが全木を 横断するために要求されます。 CFGを通る最長のパスは5つの比較オペレーションを持っています。 また、比較の平均数は3です。

Figure 6: Tree Filter Function for "host foo".

3.2.2 Design of filter pseudo-machine

The use of a control flow graph rather than an expression tree as the theoretical underpinnings of the filter pseudo-machine is a necessary step towards an efficient implementation but it is not sufficient. Even after leveraging off the experience and pseudo-machine models of CSPF and NNStat[1], the BPF model underwent several generations (and several years) of design and test. We believe the current model offers sufficient generality with no sacrifice in performance. Its evolution was guided by the following design constraints:
フィルタの偽りの機械の理論的な土台としての表現木ではなく コントロール・フロー・グラフの使用は、 効率的なインプリメンテーションに向けての必要なステップです。 しかし、?サれは十分ではありません。 さえ、CSPFおよびNNStat[1]の経験および偽りの機械のモデルからてこ入れした後に、 BPFモデルは、設計とテストのいくつかの世代(また数年)を経験しました。 私たちは、現在のモデルが実行での犠牲のない 十分な一般法則を提示すると信じます。 その発展は次の設計制約によってガイドされました:

  1. It must be protocol independent. The kernel should not have to be modified to add new protocol support.
    それはプロトコルであるに違いありません、 独立した核を新しいプロトコル支援を加えるためには修正する必要がありません。

  2. It must be general. The instruction set should be rich enough to handle unforeseen uses.
    それは一般的であるに違いありません。 指示セットは意外な用途を扱うように十分に豊富に違いありません。


  3. Packet data references should be minimized.
    パケット・データ参照が最小限にされるべきです。


  4. Decoding an instruction should consist of a single C switch statement.
    指示の解読は単一のCスイッチ・ステートメントから成るべきです。


  5. The abstract machine registers should reside in physical registers.
    抽象的な機械登録は物理的な登録に存在するべきです。

Like CSPF, constraint 1 is adhered to simply by not mentioning any protocols in the model. Packets are viewed simply as byte arrays.
CSPFのように、 強制1は、単にモデル中のどんなプロトコルにも言及しますことにより付着します。 パケットは単にバイト配列として見られます。

Constraint 2 means that we must provide a fairly general computational model, with control flow, sufficient ALU operations, and conventional addressing modes.
コントロール・フロー、 十分なALUオペレーションおよび従来のアドレッシングモードと共に、 私たちがかなり一般的な計算上のモデルを供給しなければならない強制2手段。

Constraint3 requires that we only ever touch a given packet word once. It is common for a filter to compare a given packet fieldagainst a set of values, then compare another field against another set of values, and so on. For example, a filter might match packets addressed to a set of machines, or a set of TCP ports. Ideally, we would like to cache the packet field in a register and compare it across the set of values. If the field is encapsulated in a variable length header, we must parse the outer headers to reach the data. Furthermore, on alignment restricted machines, accessing multi-byte data can involve an expensive byte-by-byte load. Also, for packets in mbufs , a field access may involve traversing an mbuf chain. After we have done this work once, we should not do it again.
Constraint3は、 私たちが与えられたパケット単語に単に常にかつて触れることを必要とします。 フィルタが与えられたパケットfieldagainstを比較することは一般的です、 1セットの値、その後、値の別のセットに対する別のフィールドなどを比較します。 例えば、フィルタは、1セットの機械に出されたパケット、 あるいは1セットのTCPポートと一致するかもしれません。 理想的には、私たちは、登録中のパケット・フィールドを貯えて、 値のセットを横切ってそれを比較したい。 フィールドが可変長さヘッダーの中でカプセルに入れられる場合、 私たちは、データに達するために外部のヘッダーを解析しなければなりません。 更に、整列を制限された機械においては、多重バイトデータへのアクセスは、 バイトごとの高価なロードを含んでいるかもしれません。 さらに、mbufsの中のパケットのために フィールド・アクセスはmbufを横断することを含んでいるかもしれません。 チェーン。この仕事を以前行ったことがある後、 私たちはそれを再び行ってはなりません。

Constraint 4 means that we will have an efficient instruction decoding step but it precludes an orthogonal addressing mode design unless we are willing to accommodate a combinatorial explosion of switch cases. For example, while three address instructions make sense for a real processor (where much work is done in parallel) the sequential execution model of an interpreter means that each address descriptor would have to be decoded serially. A single address instruction format minimizes the decode, while maintaining sufficient generality.
強制4は、私たちが効率的な指示をデコードする ステップを行うだろうが、もし私たちが喜んで スイッチの場合の組み合わせの爆発を提供しなければ それが直角のアドレッシングモード設計を排除するということを意味します。 例えば、3つのアドレス命令がインタープリターの 連続する実行モデルが意味する、 実際のプロセッサー(多くの仕事が平行中で終わる場合)用に 各アドレス・ディスクリプタが連続的にデコードされなければ ならないだろうという意味をなしている一方、 十分な一般法則を維持している間、 単一のアドレス指示フォーマットはdecodeを最小限にします。

Finally, Constraint 5 is a straightforward performance consideration. Along with constraint 4, it enforces the notion that the pseudo-machine register set should be small.
最後に、強制5は真直ぐな実行考察です。 強制4に加えて、それは、偽りの機械の登録セットが 小さくあるべきであるという概念を強化します。

These constraints prompted the adoption of an accumulator machine model. Under this model, each node in the flowgraph computes its corresponding predicate by computing a value into the accumulator and branching based on that value. Figure 7 shows the filter function of Figure 5 using the BPF instruction set.
これらの制約は、アキュムレーター機械モデルの採用を刺激しました。 このモデルの下では、flowgraphの中の各ノードが、 その値に基づいたアキュムレーターおよび分岐へ値を計算することにより、 その対応する述語を計算します。 図7は、BPF指示セットを使用して、図5のフィルタ機能を示します。


3.3 The BPF Pseudo-Machine

The BPF machine abstraction consists of an accumulator, an index register ( x ), a scratch memory store, and an implicit program counter. The operations on these elements can be categorized into the following groups:
BPF機械抽象はアキュムレーター、 インデックス登録(x)から成ります。 雑記用のメモリ店、また暗黙のプログラム・カウンター。 これらの要素に対するオペレーションは次のグループへ分類することができます:

  1. LOAD INSTRUCTIONS copy a value into the accumulator or index register. The source can be an immediate value, packet data at a fixed offset, packet data at a variable offset, the packet length, or the scratch memory store.
    ロード指示アキュムレーターかインデックス登録に値をコピーしてください。 その出所は即時の値、固定オフセットのパケット・データ、 変数オフセットのパケット・データ、 パケット長さあるいは雑記用のメモリ店でありえます。


  2. STORE INSTRUCTIONS copy either the accumulator or index register into the scratch memory store.
    店指示雑記用のメモリ店に一方のアキュムレーターか インデックス登録をコピーしてください。


  3. ALU INSTRUCTIONS perform arithmetic or logic on the accumulator using the index register or a constant as an operand.
    ALU指示オペランドとしてインデックス登録 あるいは定数を使用して、 アキュムレーター上で算術またはロジックを実行してください。


  4. BRANCH INSTRUCTIONS alter the flow of control, based on comparison test between a constant or x register and the accumulator.
    枝指示定数かxの間の比較テストに基づいて、 コントロールのフローを変更します。 登録する、またアキュムレーター。


  5. RETURN INSTRUCTIONS terminate the filter and indicated what portion of the packet to save. The packet is discarded entirely if the filter returns 0.
    リターン指示フィルタを終了し示した、 どんな部分、 保存するべきパケットの。 完全にフィルタが0を返す場合、パケットが廃棄されます。


  6. MISCELLANEOUS INSTRUCTIONS comprise everything else - currently, register transfer instructions.
    様々な指示他のすべてを含んでください。 現在、トランスファー指示を登録してください。

The fixed-length instruction format is defined by as follows:
固定長指示フォーマットはそばに以下のように定義されます:

opcode:16 jt:8 jf:8
k:32

The opcode field indicates the instruction type and addressing modes. The jt and jf fields are used by the conditional jump instructions and are the offsets from the next instruction to the true and false targets. The k field is a generic field used for various purposes.
そのopcodeフィールドは指示タイプおよびアドレッシングモードを示します。 そのjtそしてjfフィールドは条件付きの跳躍命令によって使用され、 次の指示から真実と誤りの目標までオフセットです。 kフィールドは様々な目的のために使用された総括的なフィールドです。

Table 1 shows the entire BPF instruction set. We have adopted this "assembler syntax" as a means of illustrating BPF filters and for debugging output. The actual encodings are defined with C macros, the details of which we omit here (see [6] for full details). The column labelled addr modes lists the addressing modes allowed for each instruction listed in the opcode column. The semantics of the addressing modes are listed in Table 2.
テーブル1はBPF指示セット全体を示します。 私たちは、BPFフィルタを例証する手段として、 および出力のデバッグのためにこの「アセンブラー・シンタックス」を採用しました。 実際の符号づけは、Cマクロ (私たちがどれをここで省略するかの詳細) で定義されます(十分な詳細に関しては[6]を参照)。 カラムはaddrモードにラベルを付けました。 リストリストされた各指示のために許可されたアドレッシングモード、 そのopcodeカラム。 アドレッシングモードの意味論、 テーブル2にリストされます。

opcodes addr modes
ldb
[k] [x+k]
ldh
[k] [x+k]
ld
#k #len M[k] [k] [x+k]
ldx
#k #len M[k] 4*([k]&0xf)
st
M[k]
stx
M[k]
jmp
L
jeq
#k, Lt, Lf
jgt
#k, Lt, Lf
jge
#k, Lt, Lf
jset
#k, Lt, Lf
add
#k x
sub
#k x
mul
#k x
div
#k x
and
#k x
or
#k x
lsh
#k x
rsh
#k x
ret
#k x
tax
 
txa
 
Table 1: BPF Instruction Set


#k the literal value stored in k
#len the length of the packet
M[k] the word at offset k in the scratch memory store
[k] the byte, halfword, or word at byte offset k in the packet
[x+k] the byte, halfword, or word at offset x+k in the packet
L an offset from the current instruction to L
#k, Lt, Lf the offset to Lt if the predicate is true, otherwise the offset to Lf
x the index register
4*([k]&0xf) four times the value of the low four bits of the byte at offset k in the packet
Table 2: BPF Addressing Modes

The load instructions simply copy the indicated value into the accumulator ( ld , ldh , ldb ) or index register ( ldx ). The index register cannot use the packet addressing modes. Instead, a packet value must be loaded into the accumulator and transferred to the index register, via tax . This is not a common occurrence, as the index register is used primarily to parse the variable length IP header, which can be loaded directly via the 4*([k]&0xf) addressing mode. All values are 32 bit words, except packet data can be loaded into the accumulator as unsigned bytes ( ldb ) or unsigned halfwords ( ldh ). Similarly, the scratch memory store is addressed as an array of 32 bit words. The instruction fields are all in host byte order, and the load instructions convert packet data from network order to host order. Any reference to data beyond the end of the packet terminates the filter with a return value of zero (i.e., the packet is discarded).
ロード指示は、 単にアキュムレーター(ld、ldh、ldb)に示された値をコピーします。 あるいはインデックス登録 (インデックス登録が使用することができないldx).、 パケット・アドレッシングモード)代わりに、 パケット価値をアキュムレーターにロードし、 税によってインデックス登録に転送されるに違いありません。 インデックス登録が第1に可変長さIPヘッダー (それは4*([k]&0xf)アドレッシングモードによって直接ロードすることができる) を解析するために使用されるので、 これは共通の発生ではありません。 値はすべて、符号なしのバイト(ldb)としてアキュムレーターに パケット・データをロードすることができる以外は、 32ビットの言葉です。 あるいは符号なしのhalfwords (ldh).、同様に、雑記用のメモリ店は 多くの32ビットの言葉としてアドレスされます。 指示フィールドは、ホスト・バイトオーダーおよびロード命令の中にすべてあります、 パケット・データをネットワーク・オーダーからホスト・オーダーに変換する。 パケットの終了を越えたデータへのどんな言及も、 0(つまり、パケットは廃棄されます)の返り値を備えたフィルタを終了します)

The ALU operations ( add , sub , etc.) perform the indicated operation using the accumulator and operand, and store the result back into the accumulator. Division by zero terminates the filter.
ALUオペレーション(加える(sub))など、 アキュムレーターおよびオペランドを使用して、 示されたオペレーションを?タ行し、 アキュムレーターへ結果を後ろに格納する。 0による区分はフィルタを終了します。

The jump instructions compare the value in the accumulator with a constant ( jset performs a "bitwise and" - useful for conditional bit tests). If the result is true (or non-zero), the true branch is taken, otherwise the false branch is taken. Arbitrary comparisons, which are less common, can be done by subtracting and comparing to 0. Note that there are no jlt , jle or jne opcodes since these can be built from the codes above by reversing the branches. Since jump offsets are encoded in eight bits, the longest jump is 256 instructions. Jumps longer than this are conceivable, so a jump always opcode is provided ( jmp ) that uses the 32 bit operand field for the offset.
跳躍指示は、アキュムレーター中の値を比較します、 で、1つの、一定(jsetは実行します、 1つの「ビット的に、そして"―条件付きのビット・テストに役立つ)。 結果が真実の(あるいは0でない)場合、 真実の枝はそうでなければ得られます、 誤りの枝が得られます。 任意の比較(それらはそれほど一般的でない)は 0まで引き算をするおよび匹敵することにより行うことができます。 それにそこに注意する、jltでない。、 jleあるいはjneこれら以来のopcodesは枝を逆にすることにより コードから上に構築することができます。 跳躍オフセットが8ビットでコード化されるので、 最長の跳躍は256の指示です。これより長くジャンプする、 考えられる、したがって、跳躍、常に、opcodeは提供されます(jmp)。 それはオフセットのために32ビットのオペランド・フィールドを使用します。

The return instructions terminate the program and indicate how many bytes of the packet to accept. If that amount is 0, the packet will be rejected entirely. The actual amount accepted will be the minimum of the length of the packet and the amount indicated by the filter.
####


3.4 Examples

Wenow present some examples to illustrate how packet filters can be expressed using the BPF instruction set. (In all the examples that follow, we assume Ethernet format for the link level headers.)

This filter accepts all IP packets:


ldh	[12]
jeq	#ETHERTYPE IP, L1, L2
L1:	ret	#TRUE
L2:	ret	#0

The first instruction loads the Ethernet type field. We compare this to type IP. If the comparison fails, zero is returned and the packet is rejected. If it is successful, TRUE is returned and the packet is accepted. (TRUE is some non-zero value that represents the number of bytes to save.)

This next filter accepts all IP packets which did not originate from two particular IP networks, 128.3.112 or 128.3.254. If the Ethernet type is IP, the IP source address is loaded and the high 24 bits are masked off. This value is compared with the two network addresses:


ldh	[12]
jeq	#ETHERTYPE IP, L1, L4
L1:	ld	[26]
and	#0xffffff00
jeq	#0x80037000, L4, L2
L2:	jeq	#0x8003fe00, L4, L3
L3:	ret	#TRUE
L4:	ret	#0


3.5 Parsing Packet Headers

The previous examples assume that the data of interest lie at fixed offsets in the packet. This is not the case, for example, with TCP packets, which are encapsulated in a variable length IP header. The start of TCP header must be computed from the length given in the IP header.

The IP header length is given by the low four bits of the first byte in the IP section (byte 14 on an Ethernet). This value is a word offset, and must be scaled by four to get the corresponding byte offset. The instructions below will load this offset into the accumulator:


ldb	[14]
and	#0xf
lsh	#2

Once the IP header length is computed, data in the TCP section can be accessed using indirect loads. Note that the effective offset has three components:

For example, an Ethernet header is 14 bytes and the destination port in a TCP packet is at byte two. Thus, adding 16 to the IP header length gives the offset to the TCP destination port. The previous code segment is shown below, augmented to test the TCP destination port against some value N :


ldb	[14]
and	#0xf
lsh	#2
tax
ldh	[x+16]
jeq	#N, L1, L2
L1:	ret	#TRUE
L2:	ret	#0

Because the IP header length calculation is a common operation, the 4*([k]&0xf) addressing mode was introduced. Substituting in the ldx instruction simplifies the filter into:


ldx	4*([14]&0xf)
ldh	[x+16]
jeq	#N, L1, L2
L1:	ret	#TRUE
L2:	ret	#0

However, the above filter is valid only if the data we are looking at is really a TCP/IP header. Hence, the filter must also check that link layer type is IP, and that the IP protocol type is TCP. Also, the IP layer might fragment a TCP packet, in which case the TCP header is present only in the first fragment. Hence, any packets with a non-zero fragment offset should be rejected. The final filter is shown below:


ldh	[12]
jeq	#ETHERPROTO IP, L1, L5
L1:	ldb	[23]
jeq	#IPPROTO TCP, L2, L5
L2:	ldh	[20]
jset	#0x1fff, L5, L3
L3:	ldx	4*([14]&0xf)
ldh	[x+16]
jeq	#N, L4, L5
L4:	ret	#TRUE
L5:	ret	#0



3.6 Filter Performance Measurements

We profiled the BPF and CSPF filtering models outside the kernel using iprof [9], an instruction count profiler. To fully compare the two models, an indirection operator was added to CSPF so it could parse IP headers. The change was minor anddid not adversely affectthe original filtering performance. Tests were run on large packet trace files gathered from a busy UC Berkeley campus network. Figure 8 shows the results for four fairly typical filters.

Filter 1 is trivial. It tests whether one 16 bit word in the packet is a given value. The two models are fairly comparable, with BPF faster by about 50%.

Filter 2 looks for a particular IP host (source or destination) and shows more of a disparity-a performance gap of 240%. The larger difference here is due mostly to the fact that CSPF operates only on 16 bit words and needs two comparison operations to determine the equality of a 32 bit Internet address.

Filter 3 is an example of packet parsing (required to locate the TCP destination port field) and illustrates a yet greater performance gap. The BPF filter parses the packet once, loading the port field into the accumulator then simply does a comparison cascade of the interesting ports. The CSPF filter must re-do the parse and relocate the TCP header for each port to be tested.

Finally, filter 5 demonstrates the effect of the unnecessary computations done by CSPF for a filter similar to the one described in figures 6 and 5.


4 Applications

BPF is now about two years old and has been put to work in several applications. The most widely used is tcpdump [4], a network monitoring and data acquisition tool. Tcpdump performs three primary tasks: filter translation, packet ac- quisition, and packet display. Of interest here is the filter translation mechanism. A filter is specified with a user- friendly, high level description language. Tcpdump has a built in compiler (and optimizer) which translates the high level filters into BPF programs. Of course, this translation process is transparent to the user.

Arpwatch [5] is a passive monitoring program that tracks Ethernet to IP address mappings. It notifies the system administrator, via email, when new mappings are established or abnormal behavior is noted. A common administrative nuisance is the use of a single IP address by more than one physical host, which arpwatch dutifully detects and reports.

A very different application of BPF has been its incorporation into a variant of the Icon Programming Language [3]. Two new data types, a packet and a packet generator have been built into the Icon interpreter. Packets appear as first class record objects, allowing convenient "dot operator" access to packet headers. A packet generator can be instanti- ated directly off the network, or from a previously collected file of trace data. Icon is an interpreted, dynamically typed language with high level string scanning primitives and rich data structures. With the BPF extensions, it is well suited for the rapid prototyping of networking analysis tools.

Netload and histo are two network visualization tools which produce real time network statistics on an X dis- play. Netload graphs utilization data in real time, using tcpdump style filter specifications. Histo produces a dynamic interarrival-time histogram of timestamped multimedia net- work packets.

The Reverse ARP daemon uses the BPF interface to read and write Reverse ARP requests and replies directly to the local network. (We developed this program to allow us to entirely replace NIT by BPF in our SunOS 4 systems. Each of the Sun NIT-based applications (etherfind, traffic, and rarpd) now has a BPF analog.)

Finally, recent versions of NNStat[1] and nfswatch can be configured to run over BPF (in addition to running over NIT).


5 Conclusion

BPF has proven to be an efficient, extensible, and portable interface for network monitoring. Our comparison studies have shown that it outperforms NIT in its buffer manage- ment and CSPF in its filtering mechanism. Its programmable pseudo-machine model has demonstrated excellent general- ity and extensibility (all knowledge of particular protocols is factored out of the kernel). Finally, the system is portable and runs on most BSD and BSD-derivative systems and can interact with various data link layers.

Figure 8: BPF/CSPF Filter Performance

6 Availability

BPF is available via anonymous ftp from host ftp.ee.lbl.gov as part of the tcpdump distribution, currently in the file tcpdump-2.2.1.tar.Z . Eventually we plan to factor BPF out into its own distribution so look for bpf-*.tar.Z in the future. Arpwatch and netload are also available from this site.


7 Acknowledgements

This paper would never have been published without the encouragement of Jeffrey Mogul. Jeff ported tcpdump to Ultrix and added little-endian support, uncovering dozens of our byte-ordering bugs. He also inspired the jset instruction by forcing us to consider the arduous task of parsing DECNET packet headers. Mike Karels suggested that the filter should decide not only whether to accept a packet, but also how much of it to keep. Craig Leres was the first major user of BPF/tcpdump and is responsible for finding and fixing many bugs in both. Chris Torek helped with the packet processing performance measurements and provided insight on various BSD peculiarities. Finally, we are grateful to the many users and extenders of BPF/tcpdump across the Internet for their suggestions, bug fixes, source code, and the many questions that have, over the years, greatly broadened our view of the networking world and BPF's place in it.

Finally, we would like to thank Vern Paxson, Craig Leres, Jeff Mogul, Sugih Jamin, and the referees for their helpful comments on drafts of this paper.