AF_XDP: `BPF_MAP_TYPE_XSKMAP` содержит только записи с« Операция не поддерживается » - PullRequest
2 голосов
/ 02 марта 2020

Это весь мой код ядра XDP / BPF:

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 */
};

struct bpf_map_def SEC("maps") rx_queue_pckt_counter_map = {
    .type = BPF_MAP_TYPE_ARRAY,
    .key_size = sizeof(int),
    .value_size = sizeof(unsigned long),
    .max_entries = 48,
};

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) {

                            void *rec = bpf_map_lookup_elem(&rx_queue_pckt_counter_map, &index);
                            if(rec) {
                                long *pckt_counter_val = (long*)(rec);
                                *pckt_counter_val += 1;
                            } else {
                                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;
                            }
                        }
                    }
                }
            }
        }
    }

    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";

Я пытаюсь отфильтровать все пакеты IP-UDP и отправить их в пространство пользователя. Я также подсчитываю количество пакетов, поступающих для каждой RX-очереди (указано ctx->rx_queue_index).

Моя программа компилируется нормально, но по какой-то причине я не получаю никаких пакетов в своей программе пользовательского пространства. Я уже говорил об этом в другом своем посте: AF_XDP: нет пакетов от многоадресной рассылки, хотя он направлен на RX-очередь 0

Я заранее выполнил sudo ethtool -N eth20 flow-type udp4 action 0, чтобы направить все пакеты на RX-очередь 0.

Я вижу все карты bpf, которые в настоящее время активны, через

$ sudo bpftool map list       
32: lpm_trie  flags 0x1
        key 8B  value 8B  max_entries 1  memlock 4096B
33: lpm_trie  flags 0x1
        key 20B  value 8B  max_entries 1  memlock 4096B
34: lpm_trie  flags 0x1
        key 8B  value 8B  max_entries 1  memlock 4096B
35: lpm_trie  flags 0x1
        key 20B  value 8B  max_entries 1  memlock 4096B
36: lpm_trie  flags 0x1
        key 8B  value 8B  max_entries 1  memlock 4096B
37: lpm_trie  flags 0x1
        key 20B  value 8B  max_entries 1  memlock 4096B
125: array  name rx_queue_pckt_c  flags 0x0
        key 4B  value 8B  max_entries 48  memlock 4096B
126: xskmap  name xsks_map  flags 0x0
        key 4B  value 4B  max_entries 64  memlock 4096B

Но я думаю, что только 125 и 126 связаны с моей программой.

Управление очередью работает, потому что с sudo bpftool map dump id 125 я получаю:

key: 00 00 00 00  value: 99 1a cc 04 00 00 00 00
key: 01 00 00 00  value: 00 00 00 00 00 00 00 00
key: 02 00 00 00  value: 00 00 00 00 00 00 00 00
key: 03 00 00 00  value: 00 00 00 00 00 00 00 00
key: 04 00 00 00  value: 00 00 00 00 00 00 00 00
key: 05 00 00 00  value: 00 00 00 00 00 00 00 00
key: 06 00 00 00  value: 00 00 00 00 00 00 00 00
key: 07 00 00 00  value: 00 00 00 00 00 00 00 00
key: 08 00 00 00  value: 00 00 00 00 00 00 00 00
key: 09 00 00 00  value: 00 00 00 00 00 00 00 00
key: 0a 00 00 00  value: 00 00 00 00 00 00 00 00
key: 0b 00 00 00  value: 00 00 00 00 00 00 00 00
key: 0c 00 00 00  value: 00 00 00 00 00 00 00 00
key: 0d 00 00 00  value: 00 00 00 00 00 00 00 00
key: 0e 00 00 00  value: 00 00 00 00 00 00 00 00
key: 0f 00 00 00  value: 00 00 00 00 00 00 00 00
key: 10 00 00 00  value: 00 00 00 00 00 00 00 00
key: 11 00 00 00  value: 00 00 00 00 00 00 00 00
key: 12 00 00 00  value: 00 00 00 00 00 00 00 00
key: 13 00 00 00  value: 00 00 00 00 00 00 00 00
key: 14 00 00 00  value: 00 00 00 00 00 00 00 00
key: 15 00 00 00  value: 00 00 00 00 00 00 00 00
key: 16 00 00 00  value: 00 00 00 00 00 00 00 00
key: 17 00 00 00  value: 00 00 00 00 00 00 00 00
key: 18 00 00 00  value: 00 00 00 00 00 00 00 00
key: 19 00 00 00  value: 00 00 00 00 00 00 00 00
key: 1a 00 00 00  value: 00 00 00 00 00 00 00 00
key: 1b 00 00 00  value: 00 00 00 00 00 00 00 00
key: 1c 00 00 00  value: 00 00 00 00 00 00 00 00
key: 1d 00 00 00  value: 00 00 00 00 00 00 00 00
key: 1e 00 00 00  value: 00 00 00 00 00 00 00 00
key: 1f 00 00 00  value: 00 00 00 00 00 00 00 00
key: 20 00 00 00  value: 00 00 00 00 00 00 00 00
key: 21 00 00 00  value: 00 00 00 00 00 00 00 00
key: 22 00 00 00  value: 00 00 00 00 00 00 00 00
key: 23 00 00 00  value: 00 00 00 00 00 00 00 00
key: 24 00 00 00  value: 00 00 00 00 00 00 00 00
key: 25 00 00 00  value: 00 00 00 00 00 00 00 00
key: 26 00 00 00  value: 00 00 00 00 00 00 00 00
key: 27 00 00 00  value: 00 00 00 00 00 00 00 00
key: 28 00 00 00  value: 00 00 00 00 00 00 00 00
key: 29 00 00 00  value: 00 00 00 00 00 00 00 00
key: 2a 00 00 00  value: 00 00 00 00 00 00 00 00
key: 2b 00 00 00  value: 00 00 00 00 00 00 00 00
key: 2c 00 00 00  value: 00 00 00 00 00 00 00 00
key: 2d 00 00 00  value: 00 00 00 00 00 00 00 00
key: 2e 00 00 00  value: 00 00 00 00 00 00 00 00
key: 2f 00 00 00  value: 00 00 00 00 00 00 00 00
Found 48 elements

Как видите, только счетчик для RX-очереди 0 больше 0.

Но, если Я смотрю на BPF_MAP_TYPE_XSKMAP (который используется для передачи пакетов в пространство пользователя), я получаю:

$ sudo bpftool map dump id 126
key:
00 00 00 00
value:
Operation not supported
key:
01 00 00 00
value:
Operation not supported
key:
02 00 00 00
value:
Operation not supported
key:
03 00 00 00
value:
Operation not supported
key:
04 00 00 00
value:
Operation not supported
...
key:
3e 00 00 00
value:
Operation not supported
key:
3f 00 00 00
value:
Operation not supported
Found 0 elements

Является ли сообщение Operation not supported индикатором, почему я не получаю никаких пакетов в моей программе пространства пользователя? Или это просто невозможно получить значение во время выполнения? Мне также странно видеть Found 0 elements.

Есть идеи, что тут не так?

1 Ответ

2 голосов
/ 02 марта 2020

Это просто потому, что карты типа BPF_MAP_TYPE_XSKMAP не поддерживают поиск из пространства пользователя (вы получите адреса из пространства ядра, что не имеет смысла с точки зрения пространства пользователя и может быть проблемой безопасности).

Так как попытка поиска возвращает -EOPNOTSUPP, bpftool не может показать значения. Он мог выдавать ошибку и ничего не печатать, но вместо этого мы сделали печать ключей, которые он нашел, и распечатали сообщения об ошибках, которые мы получили для значений .

Что касается Found 0 elements, count для элементов, которые bpftool мог извлечь безо всякой ошибки, поэтому логично, что в этом случае он остается равным нулю.

Так что в вашем случае нет ничего плохого, я не верю, что этот вывод связан с вашим проблема с отсутствующими пакетами.

...