AF_XDP: нет пакетов от многоадресной рассылки, хотя они направляются в RX-Queue 0

Я все еще играю с сокетом AF_XDP, и моя программа по-прежнему в значительной степени основана на: https://github.com/xdp-project/xdp-tutorial/tree/master/advanced03-AF_XDP

Теперь я хочу получать несколько многоадресных потоков (что отлично работает, поскольку я регистрирую многоадресные IP-адреса, потому что я протестировал его с сокетом Linux по умолчанию, поэтому я не делюсь кодом, если вы, ребята, не скажете, что это необходимо для решения проблемы).

Поскольку я пока не хочу менять свою программу для работы с несколькими очередями RX сетевой карты (действуйте шаг за шагом, но в конечном итоге мне придется сделать это для увеличения пропускной способности), я направил трафик на одну очередь RX с помощью эта команда:

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 выше я вообще ничего не получаю. Звучит странно, но именно так я это и наблюдал.

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

person binaryBigInt    schedule 27.02.2020    source источник
comment
Хм, я не вижу никаких красных флажков в вашей программе. Контрольный список, чтобы попытаться закрепить... Итак, вы проверили, что ваша программа правильно загружена и подключена? Что простая программа return XDP_PASS пропускает все пакеты, а return XDP_DROP все отбрасывает? Что ваша карта сокетов заполнена? Что ctx->rx_queue_index фактически равно 0 (можно использовать bpf_trace_printk() для проверки)? Какое значение возвращает bpf_redirect_map()?   -  person Qeole    schedule 27.02.2020
comment
@Qeole Я обновил свою исходную публикацию. К сожалению, я не могу просто использовать XDP_PASS или XDP_DROP в качестве тестовой программы, потому что libbpf не загрузит сокет AF-XDP, который не имеет доступа к какой-либо карте (взгляните на строку 506 в xsk.c в libbpf: github.com/libbpf/libbpf/blob/master/src/xsk.c ). Но поскольку bpf_redirect_map() возвращает успех, я предполагаю, что это работает так, как ожидалось.   -  person binaryBigInt    schedule 27.02.2020
comment
Хорошо, да, я пока мало работал с sockmaps. Хм. Что касается вашего редактирования № 2, означает ли это, что вы вообще не получаете пакет, даже если прога BPF отсутствует? Также ethtool -n eth20 возвращает ожидаемый фильтр? Я не помню, нельзя ли получить статистику по очереди с помощью ethtool -S? Возможно, стоит проверить, что там написано. Также проверьте количество запусков для вашей программы, чтобы убедиться, что она действительно работает (но тогда вы увидите в trace_pipe, так что он, вероятно, запускается в какой-то момент)?   -  person Qeole    schedule 27.02.2020
comment
@Qeole Я только что перезагрузил систему, чтобы очистить статистику, предоставленную ethtool -S, а затем запустил программу на 6 секунд. Я прикрепил вывод к исходному сообщению. Я сейчас не знаю, как мне получить bpftool в Debian   -  person binaryBigInt    schedule 28.02.2020
comment
@Qeole Я также добавил вывод для bpftool prog show. Кстати, действительно интересная страница в Твиттере   -  person binaryBigInt    schedule 28.02.2020
comment
Спасибо! Да, пока нет пакета для Debian, вы бы для сборки из исходников. Хм, очевидно, у вас есть несколько пакетов, отброшенных или перенаправленных с помощью XDP (rx0_xdp_drop: 11250292, rx0_xdp_redirect: 2048). Как вы пытаетесь увидеть их на своем сокете? Может ли быть, что ошибка находится в программе пользовательского пространства? Также bpftool prog show не показывает ваши программы, возможно, они не были подключены, когда вы запускали команду (программы cgroup_skb, которые мы видим, были созданы от systemd).   -  person Qeole    schedule 28.02.2020
comment
@Qeole О, я только что начал удалять ключи с карт, показанных bpftool prog show, потому что думал, что они остались от предыдущих программ, которые я запускал, и поэтому могут мешать друг другу. Что вы имеете в виду под How are you trying to see them on your socket?. Конечно, может быть ошибка в пользовательском пространстве, но я не сильно изменился. Только добавлен общий сокет Linux, который отправляет многоадресные сообщения IGMP. Я получил пакет bpftool отсюда: github .com/xdp-project/xdp-tutorial/blob/master/   -  person binaryBigInt    schedule 28.02.2020
comment
Ха-ха, я создал этот пакет .deb :). Я имел в виду, что вы подразумеваете под I receive exactly 0 packets? Как вы говорите?   -  person Qeole    schedule 28.02.2020
comment
@Qeole В github есть вызов poll(). com/xdp-project/xdp-tutorial/blob/master/, который никогда не возвращается   -  person binaryBigInt    schedule 28.02.2020
comment
Хорошо, хм, у меня действительно больше нет идей, если вы не получите ответа здесь, вы можете попробовать другие каналы (#xdp на Freenode в IRC, репозиторий GitHub для руководства, список рассылки xdp-newbies.. .)   -  person Qeole    schedule 28.02.2020
comment
@Qeole Большое спасибо за вашу помощь. Спрошу на freenode!   -  person binaryBigInt    schedule 28.02.2020


Ответы (1)


В моем пользовательском коде действительно была проблема. Я опросил файловый дескриптор сокета, хотя я отключил опрос. Из-за этого он так и не вернулся.

person binaryBigInt    schedule 03.03.2020