2

Linux で可能な限りシステムに取り組んでおりas close to real-time、特定のパケットを受信したらすぐに TCP パケットで約 600 ~ 800 バイトを送信する必要があります。

可能な限り最高のレイテンシーを得るには、受信したパケットがユーザー空間とアプリケーションに到達してから戻るのではなく、このパケットをカーネルから直接送信する必要があります。

私がWindowsを使用していた場合、送信するパケットと一致するパラメーターをキャッシュするNDISフィルターを作成して、受信したパケットをチェックし、一致すると、事前にキャッシュされたパケットを通過せずにネットワークに送信します上位層までの受信パケット。

私の質問は、Linux の NDIS フィルターに最も近いものは何ですか?

私は netfilter について読んだことがあり、おそらくそれを使用するでしょうが、それが可能な限り最良の方法であるかどうかはわかりません.

可能な限り低いレイテンシを達成するために他に何ができますか?

私の現在の純粋なユーザー空間コードは、2.6.3x カーネルで Ubuntu 10.04 を実行している Intel Xeon 3.7 GHz プロセッサで約 80 ~ 100 マイクロ秒を提供します。

4

2 に答える 2

2

iptablesターゲットを使用して、NFLOGパケットをユーザー空間にコピーしたり、ユーザー空間でパケットを破壊したりNFQUEUEできます。このやり取りはnetlinkを介して行われますが、これをラップするlibnetfilter_loglibnetfilter_queueなどのライブラリを使用できます。

于 2012-10-12T04:29:53.863 に答える
1

Linux カーネルには、BPF (バークレー パケット フィルター) と呼ばれる同様のメカニズムがあります。アプリケーションから BPF フィルターをカーネルに登録します。フィルタに一致するパケットがキャプチャされ、登録されたフック関数に転送されます。

以下は、インターネットで見つけた例のコードです。( https://gist.github.com/939154 ) 基本的に、オープンを作成し、それを BPF フィルターにバインドしてから、パケットを受信するためにこの FD を選択する必要がありました。set_filter(int fd) { struct bpf_program fcode = {0};

/* dump ssh packets only */
struct bpf_insn insns[] = {
    BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
    BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 10),
    BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
    BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 8),
    BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
    BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 6, 0),
    BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
    BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),
    BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 22, 2, 0),
    BPF_STMT(BPF_LD+BPF_H+BPF_IND, 16),
    BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 22, 0, 1),
    BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
    BPF_STMT(BPF_RET+BPF_K, 0),
};


/* Set the filter */
fcode.bf_len = sizeof(insns) / sizeof(struct bpf_insn);
fcode.bf_insns = &insns[0];

if(ioctl(fd, BIOCSETF, &fcode) < 0)
    return -1;

return 0;

}

bpf_inst は奇妙に見えます。ただし、手動で記述する必要はありません。tcp-dump を使用して、これらのスクリプトを自動生成できます。

例えば:

sudo tcpdump 'tcp[13]=18'  -i eth0 -dd
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 8, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 6, 0x00000006 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 4, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x50, 0, 0, 0x0000001b },
{ 0x15, 0, 1, 0x00000012 },
{ 0x6, 0, 0, 0x00000060 },
{ 0x6, 0, 0, 0x00000000 },
于 2012-10-12T03:22:56.853 に答える