简体   繁体   中英

How to properly utilize masks to send index information to perf event output?

According to the documentation for bpf_perf_event_output found here: http://man7.org/linux/man-pages/man7/bpf-helpers.7.html

"The flags are used to indicate the index in map for which the value must be put, masked with BPF_F_INDEX_MASK."

In the following code:

SEC("xdp_sniffer")
int xdp_sniffer_prog(struct xdp_md *ctx)
{

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

    if (data < data_end) {
        /* If we have reached here, that means this
        * is a useful packet for us. Pass on-the-wire
        * size and our cookie via metadata.
        */
        /* If we have reached here, that means this
        * is a useful packet for us. Pass on-the-wire
        * size and our cookie via metadata.
        */
        __u64 flags = BPF_F_INDEX_MASK;
        __u16 sample_size;
        int ret;
        struct S metadata;

        metadata.cookie = 0xdead;
        metadata.pkt_len = (__u16)(data_end - data);

        /* To minimize writes to disk, only
        * pass necessary information to userspace;
        * that is just the header info.
        */
        sample_size = min(metadata.pkt_len, SAMPLE_SIZE);
        flags |= (__u64)sample_size << 32;

        ret = bpf_perf_event_output(ctx, &my_map, flags,
                        &metadata, sizeof(metadata));
        if (ret)
            bpf_printk("perf_event_output failed: %d\n", ret);
    }
    return XDP_PASS;
}

It works as you would expect and stores the information for the given CPU number. However, suppose I want all packets to be sent to index 1.

I swap

__u64 flags = BPF_F_INDEX_MASK;

for

__u64 flags = 0x1ULL;

The code compiles correctly and throws no errors, however no packets get saved at all anymore. What am I doing wrong if I want all of the packets to be sent to index 1?

Partial answer: I see no reason why the packets would not be sent to the perf buffer, but I suspect the error is on the user space code (not provided). It could be that you do not “open” the perf event for all CPUs when trying to read from the buffer. Have a look at the man page for perf_event_open(2) : check that the combination of values for pid and cpu allows you to read data written for CPU 1.

As a side note, this:

__u64 flags = BPF_F_INDEX_MASK;

is misleading. The mask should be used to mask the index, not to set its value. BPF_F_CURRENT_CPU should be used instead, the former only happens to work because the two enum attributes have the same value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM