Linux (2.6.38.8) で実行されるアプリケーションがあり、libpcap (>1.0) を使用して、イーサネット経由でストリーミングされたパケットをキャプチャします。私のアプリケーションはほぼ 100% の CPU を使用しており、libpcap を可能な限り効率的に使用しているかどうか確信が持てません。
pcap チューナブルとパフォーマンスの間の相関関係を見つけるために戦っています。
これが私の簡略化されたコードです(エラーチェックなどは省略されています):
// init libpcap
pcap_t *p = pcap_create("eth0", my_errbuf);
pcap_set_snaplen(p, 65535);
pcap_set_promisc(p, 0);
pcap_set_timeout(p, 1000);
pcap_set_buffer_size(p, 16<<20); // 16MB
pcap_activate(p);
// filter
struct bpf_program filter;
pcap_compile(p, &filter, "ether dst 00:11:22:33:44:55", 0, 0);
pcap_setfilter(p, &filter);
// do work
while (1) {
int ret = pcap_dispatch(p, -1, my_callback, (unsigned char *) my_args);
if (ret <= 0) {
if (ret == -1) {
printf("pcap_dispatch error: %s\n", pcap_geterr(p));
} else if (ret == -2) {
printf("pcap_dispatch broken loop\n");
} else if (ret == 0) {
printf("pcap_dispatch zero packets read\n");
} else {
printf("pcap_dispatch returned unexpectedly");
}
} else if (ret > 1) {
printf("processed %d packets\n", ret);
}
}
1000 ミリ秒のタイムアウトと 2M、4M、および 16M のバッファ サイズを使用した場合の結果は、高いデータ レート (~200 1kB パケット/秒) で同じです: pcap_dispatch は一貫して 2 を返します。 pcap_dispatch は、バッファがいっぱいになるかタイムアウトになったときに戻ります。しかし、戻り値が 2 の場合、2kB のデータしか読み取られておらず、2/200 秒しか経過していないため、これらの条件はいずれも満たされません。
データレートを遅くすると (1kB パケットが 100 個/秒)、pcap_dispatch は 2 から 7 の間を返すため、データレートを半分にすると、pcap_dispatch ごとに処理されるパケット数に影響します。(パケットが多いほど良いと思います。これは、OS とユーザー空間の間のコンテキストの切り替えが少なくなることを意味します。これは本当ですか?)
タイムアウト値も違いはないようです。
いずれの場合も、CPU 使用率はほぼ 100% です。
libpcap の PF_RING バージョンを試してみるべきかどうか疑問に思い始めていますが、SO と libpcap のメーリング リストで読んだことによると、libpcap > 1.0 はいずれにせよゼロ コピー機能を実行するため、おそらく意味がありません。
どんなアイデア、ポインタも大歓迎です! G