0

我仍在使用 AF_XDP 套接字,我的程序仍然主要基于:https ://github.com/xdp-project/xdp-tutorial/tree/master/advanced03-AF_XDP

我现在想要接收多个多播流(这在我注册多播 IP 的方式上工作得很好,因为我已经使用默认的 Linux 套接字对其进行了测试,因此我不会共享代码,除非你们说有必要解决这个问题)。

因为我还不想更改我的程序以在 NIC 的多个 RX-Queue 上工作(逐步进行,但最终我必须这样做以增加吞吐量)我将流量引导到单个 RX-Queue这个命令:

sudo ethtool -N eth20 flow-type udp4 action 0

过滤器似乎处于活动状态:

$ sudo ethtool -n eth20
48 RX rings available
Total 1 rules

Filter: 1023
        Rule Type: UDP over IPv4
        Src IP addr: 0.0.0.0 mask: 255.255.255.255
        Dest IP addr: 0.0.0.0 mask: 255.255.255.255
        TOS: 0x0 mask: 0xff
        Src port: 0 mask: 0xffff
        Dest port: 0 mask: 0xffff
        Action: Direct to queue 0

但无论出于何种原因,我都收到了确切的0数据包。这是我正在使用的内核程序:

struct bpf_map_def SEC("maps") xsks_map = {
    .type = BPF_MAP_TYPE_XSKMAP,
    .key_size = sizeof(int),
    .value_size = sizeof(int),
    .max_entries = 64,  /* Assume netdev has no more than 64 queues */
};

SEC("xdp_sock")
int xdp_sock_prog(struct xdp_md *ctx) {

    int index = ctx->rx_queue_index;

    void *data_end = (void *)(long)ctx->data_end;
    void *data = (void *)(long)ctx->data;

    void *pos = data;
    struct ethhdr *eth = (struct ethhdr*)(pos);

    if(eth + sizeof(struct ethhdr) <= data_end) {

        if(bpf_ntohs(eth->h_proto) == ETH_P_IP) {
            struct iphdr *iph = (struct iphdr*)(pos + sizeof(struct ethhdr));

            if(iph + sizeof(struct iphdr) <= data_end) {

                if(iph->protocol == IPPROTO_UDP) {
                    const __u16 iph_sz_in_bytes = iph->ihl * 4;

                    if(iph + iph_sz_in_bytes <= data_end) {
                        struct udphdr *udh = (struct udphdr*)(pos + sizeof(struct ethhdr) + iph_sz_in_bytes);

                        if(udh + sizeof(struct udphdr) <= data_end) {

                            if (bpf_map_lookup_elem(&xsks_map, &index)) {
                                return bpf_redirect_map(&xsks_map, index, 0);
                            }
                        }
                    }
                }
            }
        }
    }

    return XDP_PASS;
}

任何想法为什么?

编辑:

我变了:

                    if (bpf_map_lookup_elem(&xsks_map, &index)) {
                        const int ret_val = bpf_redirect_map(&xsks_map, index, 0);
                        bpf_printk("RET-VAL: %d\n", ret_val);
                        return ret_val;
                    }

并且做了

sudo cat /sys/kernel/debug/tracing/trace_pipe

返回:

ksoftirqd/17-98 [017] ..s. 277979.654041: 0: RET-VAL: 4

根据描述bpf_redirect_map

  • 成功时返回 * XDP_REDIRECT,或者错误时返回 **flags* 参数的两个低位 * 的值。

因为XDP_REDIRECT = 4我认为这按预期工作。

main()此外,在解析命令行参数后,我在用户空间代码中添加了这个输出:

printf("RX-Queue: %d\n", cfg.xsk_if_queue);

确实返回0(因此选择了正确的 RX-Queue)。

Edit_2:奇怪的是,我之前能够接收到一个多播流(它以某种方式意外地在 RX-Queue 0 上结束)但是在执行ethtool上面的 -command 之后我什么都没有收到。听起来很奇怪,但这就是我观察它的方式。

Edit_3:sudo ethtool -S eth20返回:http: //ix.io/2cSC

$ sudo bpftool prog show
39: cgroup_skb  tag 7be49e3934a125ba  gpl
        loaded_at 2020-02-28T08:00:06+0000  uid 0
        xlated 296B  not jited  memlock 4096B  map_ids 38,39
40: cgroup_skb  tag 2a142ef67aaad174  gpl
        loaded_at 2020-02-28T08:00:06+0000  uid 0
        xlated 296B  not jited  memlock 4096B  map_ids 38,39
41: cgroup_skb  tag 7be49e3934a125ba  gpl
        loaded_at 2020-02-28T08:00:06+0000  uid 0
        xlated 296B  not jited  memlock 4096B  map_ids 40,41
42: cgroup_skb  tag 2a142ef67aaad174  gpl
        loaded_at 2020-02-28T08:00:06+0000  uid 0
        xlated 296B  not jited  memlock 4096B  map_ids 40,41
43: cgroup_skb  tag 7be49e3934a125ba  gpl
        loaded_at 2020-02-28T08:00:06+0000  uid 0
        xlated 296B  not jited  memlock 4096B  map_ids 42,43
44: cgroup_skb  tag 2a142ef67aaad174  gpl
        loaded_at 2020-02-28T08:00:06+0000  uid 0
        xlated 296B  not jited  memlock 4096B  map_ids 42,43
4

1 回答 1

0

我的用户空间代码确实存在问题。即使我禁用了轮询,我也轮询了套接字的文件描述符。正因为如此,它再也没有回来。

于 2020-03-03T13:08:33.570 回答