【问题标题】:What is the analogue of an NDIS filter in linux?linux中NDIS过滤器的类似物是什么?
【发布时间】:2012-10-01 12:04:33
【问题描述】:

我正在尽可能在 linux 中使用as close to real-time 系统,并且需要在收到特定数据包后立即在 TCP 数据包中发送大约 600-800 字节。

为了尽可能缩短延迟,我希望这个数据包直接从内核发送,而不是接收到的数据包一直到达用户空间和应用程序,然后再返回。

如果我在 Windows 上,我会编写一个 NDIS 过滤器,我会缓存要发送的数据包和匹配的参数,以便它检查接收到的数据包,并在匹配时将预缓存的数据包触发到无需将接收到的数据包传递给更高层。

所以我的问题是 linux 上最接近 NDIS 过滤器的类似物是什么?

我已经阅读了有关 netfilter 的内容,也许我会使用它,但我不知道这是否是最好的方法。

我还能做些什么来实现尽可能低的延迟?

我当前的纯用户空间代码在 Intel Xeon 3.7 GHz 处理器上运行 2.6.3x 内核上的 Ubuntu 10.04 为我提供了大约 80-100 微秒。

【问题讨论】:

    标签: linux kernel hpc netfilter ndis


    【解决方案1】:

    Linux 内核中有类似的机制称为 BPF(伯克利包过滤器)。 从您的应用程序中将 BPF 过滤器注册到内核中。匹配过滤器的数据包将被捕获并转发到注册的钩子函数。

    以下是我在互联网上找到的示例代码。 (https://gist.github.com/939154) 基本上你必须创建一个开放的,将它与一个 BPF 过滤器绑定,然后选择这个 FD 来接收数据包: ; set_filter(int fd) { 结构 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 },
    

    【讨论】:

    • 请注意,这仍然会跳转到用户空间并返回,因为您必须读取 bpf 设备并将数据包写回它。但是,在此之前关闭基准测试。 Linux 系统调用通常比 Windows 系统调用更快。
    【解决方案2】:

    您可以使用iptables 目标NFLOG 将数据包复制到用户空间或NFQUEUE 以允许用户空间破坏它们。这种交互发生在netlink 上,但您可以使用诸如libnetfilter_loglibnetfilter_queue 之类的库来环绕它。

    【讨论】:

      猜你喜欢
      • 2017-04-14
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 2019-10-16
      • 2021-11-20
      • 1970-01-01
      • 2017-08-07
      • 2021-12-19
      相关资源
      最近更新 更多