Я все еще играю с сокетом 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
return XDP_PASS
пропускает все пакеты, аreturn XDP_DROP
все отбрасывает? Что ваша карта сокетов заполнена? Чтоctx->rx_queue_index
фактически равно 0 (можно использоватьbpf_trace_printk()
для проверки)? Какое значение возвращаетbpf_redirect_map()
? - person Qeole   schedule 27.02.2020XDP_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.2020ethtool -n eth20
возвращает ожидаемый фильтр? Я не помню, нельзя ли получить статистику по очереди с помощьюethtool -S
? Возможно, стоит проверить, что там написано. Также проверьте количество запусков для вашей программы, чтобы убедиться, что она действительно работает (но тогда вы увидите вtrace_pipe
, так что он, вероятно, запускается в какой-то момент)? - person Qeole   schedule 27.02.2020ethtool -S
, а затем запустил программу на 6 секунд. Я прикрепил вывод к исходному сообщению. Я сейчас не знаю, как мне получитьbpftool
в Debian - person binaryBigInt   schedule 28.02.2020bpftool prog show
. Кстати, действительно интересная страница в Твиттере - person binaryBigInt   schedule 28.02.2020rx0_xdp_drop: 11250292
,rx0_xdp_redirect: 2048
). Как вы пытаетесь увидеть их на своем сокете? Может ли быть, что ошибка находится в программе пользовательского пространства? Такжеbpftool prog show
не показывает ваши программы, возможно, они не были подключены, когда вы запускали команду (программыcgroup_skb
, которые мы видим, были созданы от systemd). - person Qeole   schedule 28.02.2020bpftool 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.2020I receive exactly 0 packets
? Как вы говорите? - person Qeole   schedule 28.02.2020poll()
. com/xdp-project/xdp-tutorial/blob/master/, который никогда не возвращается - person binaryBigInt   schedule 28.02.2020