Я все еще играю с сокетом AF_XDP, и моя программа по-прежнему в значительной степени основана на: https://github.com/xdp-project/xdp-tutorial/tree/master/advanced03-AF_XDP
Теперь я хочу получить несколько многоадресных потоков (что отлично работает, как я зарегистрируйте многоадресные IP-адреса, потому что я проверил их с сокетом по умолчанию Linux, поэтому я не делюсь кодом, если вы, ребята, не скажете, что это необходимо для решения проблемы).
потому что я не хочу менять моя программа для работы с несколькими RX-очередями NI C только сейчас (go шаг за шагом, но в конечном итоге мне нужно сделать это для увеличения пропускной способности). Я направил трафик c в одну 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).
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