eBPF: Как использовать `bpf_map_update_elem` для отправки данных из пространства ядра?

#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 для этого.