#c #bpf #ebpf #xdp-bpf
Вопрос:
Я пытаюсь отправить данные (IP — адрес) из пространства ядра в пространство пользователя, запустив следующую процедуру BPF:
struct bpf_map_def EVENTS = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(__u32), .value_size = sizeof(__u32), .max_entries = 1, }; SEC("xdp") int _xdp_ip_filter(struct xdp_md *ctx) { bpf_printk("got a packetn"); void *data_end = (void *)(long)ctx-gt;data_end; void *data = (void *)(long)ctx-gt;data; struct ethhdr *eth = data; // check packet size if (eth 1 gt; data_end) { return XDP_PASS; } // get the source address of the packet struct iphdr *iph = data sizeof(struct ethhdr); if (iph 1 gt; data_end) { return XDP_PASS; } __u32 ip_src = iph-gt;saddr; bpf_printk("source ip address is %un", ip_src); // key of the maps __u32 key = 0; bpf_printk("starting xdp ip filtern"); // send the ip to the userspace program. bpf_map_update_elem(amp;EVENTS, amp;key, amp;ip_src, BPF_ANY); return XDP_PASS; }
Сделать файл:
CLANG ?= clang LLC ?= llc OPT ?= opt DIS ?= llvm-dis ARCH ?= $(shell uname -m | sed -e 's/aarch64/arm64/' -e 's/x86_64/x86/') KERNEL ?= /usr/src/linux CFLAGS = -O2 -g -emit-llvm -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign -Wno-compare-distinct-pointer-types -Wno-address-of-packed-member -Wno-tautological-compare -Wno-unknown-warning-option -Wno-gnu-variable-sized-type-not-at-end -fno-asynchronous-unwind-tables bytecode.$(ARCH).o: bytecode.c $(CLANG) $(CFLAGS) -c $lt; -o - | $(OPT) -O2 -mtriple=bpf-pc-linux | $(DIS) | $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@
Однако я продолжаю получать следующую ошибку:
58: (85) call bpf_map_update_elem#2 R1 type=map_value expected=map_ptr verification time 272 usec
Кто-нибудь может помочь мне понять эту ошибку? Кроме того, где я могу просмотреть bpf_printk
сообщения?
Я подозреваю, что файл, созданный make, не включает EVENTS
карту.. Но я не уверен, как это исправить — если я добавлю SEC("maps")
над картой, верификатор ядра вообще не сможет найти раздел..
Ответ №1:
Ты пропал без вести:
SEC("maps")
в объявлении карты (как вы уже догадались).- Декларация о лицензии.
#include lt;linux/bpf.hgt; #include lt;linux/if_ether.hgt; #include lt;linux/ip.hgt; #include lt;bpf/bpf_helpers.hgt; struct bpf_map_def SEC("maps") EVENTS = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(__u32), .value_size = sizeof(__u32), .max_entries = 1, }; SEC("xdp") int _xdp_ip_filter(struct xdp_md *ctx) { bpf_printk("got a packetn"); void *data_end = (void *)(long)ctx-gt;data_end; void *data = (void *)(long)ctx-gt;data; struct ethhdr *eth = data; // check packet size if (eth 1 gt; data_end) { return XDP_PASS; } // get the source address of the packet struct iphdr *iph = data sizeof(struct ethhdr); if (iph 1 gt; data_end) { return XDP_PASS; } __u32 ip_src = iph-gt;saddr; bpf_printk("source ip address is %un", ip_src); // key of the maps __u32 key = 0; bpf_printk("starting xdp ip filtern"); // send the ip to the userspace program. bpf_map_update_elem(amp;EVENTS, amp;key, amp;ip_src, BPF_ANY); return XDP_PASS; } char _license[] SEC("license") = "GPL";
Я смог загрузить и прикрепить с:
make sudo ip link set dev wlp59s0 xdp obj ./bytecode.o sec xdp
Комментарии:
1. Спасибо! Где я могу видеть
printk
звонки?2. Вы можете использовать
bpftool prog tracelog
для этого.