Кольцевые буферы EBPF не печатают событие на stdout, evt struct заполняется и печатается при печати на Trace_pipeLinux

Ответить
Anonymous
 Кольцевые буферы EBPF не печатают событие на stdout, evt struct заполняется и печатается при печати на Trace_pipe

Сообщение Anonymous »

У меня есть следующая структура программы:
src/main.bpf.c:

Код: Выделить всё

#include "../vmlinux.h"
#include 
#include 
#include 
#include 
#include "../include/omega.h"

#define ETH_P_IP 0x0800

/*
* NOTES:
*  __builtin_memcpy HAS TO BE USED BEFORE bpf_ringbuf_submit otherwise it will generate an error!
*/

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

SEC("xdp")
int xdp_packet_filter(struct xdp_md *ctx) {
struct packet_evt *evt = {0};

evt = bpf_ringbuf_reserve(&rb, sizeof(*evt), 0);
if (!evt) {
return XDP_PASS;
}

void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;

struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) {
goto failure;
}

if (eth->h_proto != bpf_htons(ETH_P_IP)) {
goto failure;
}

struct iphdr *ip = data + sizeof(struct ethhdr);
if ((void *)(ip + 1) > data_end) {
goto failure;
}

if (ip->protocol == IPPROTO_UDP) {
struct udphdr *udp = (void *)ip + sizeof(struct iphdr);
if ((void *)(udp + 1) > data_end) {
goto failure;
}

__u16 src_port = bpf_ntohs(udp->source);
__u16 dest_port = bpf_ntohs(udp->dest);

if (evt) {
evt->src_ip = ip->saddr;
evt->dst_ip = ip->daddr;
evt->src_port = src_port;
evt->dst_port = dest_port;

bpf_printk("Submitting Event: SRC IP: %x DST IP: %x SRC PORT: %d DST PORT: %d\n",
evt->src_ip, evt->dst_ip, evt->src_port, evt->dst_port);
//bpf_printk("TCP packet from %x:%d to %x:%d\n",
//ip->saddr, src_port, ip->daddr, dest_port);
} else {
bpf_printk("Ring buffer reservation failed\n");
goto failure;
}

//PACKET FROM TO
//bpf_printk("UDP|%x:%d|%x:%d\n",
//    ip->saddr, src_port, ip->daddr, dest_port);
} else if (ip->protocol == IPPROTO_TCP) {
struct tcphdr *tcp = (void *)ip + sizeof(struct iphdr);
if ((void *)(tcp + 1) >  data_end) {
goto failure;
}

__u16 src_port = bpf_ntohs(tcp->source);
__u16 dest_port = bpf_ntohs(tcp->dest);

if (evt) {
evt->src_ip = ip->saddr;
evt->dst_ip = ip->daddr;
evt->src_port = src_port;
evt->dst_port = dest_port;

bpf_printk("Submitting Event: SRC IP: %x DST IP: %x SRC PORT: %d DST PORT: %d\n",
evt->src_ip, evt->dst_ip, evt->src_port, evt->dst_port);
//bpf_printk("TCP packet from %x:%d to %x:%d\n",
//ip->saddr, src_port, ip->daddr, dest_port);
} else {
bpf_printk("Ring buffer reservation failed\n");
goto failure;
}

// PACKET FROM TO
// bpf_printk("TCP|%x:%d|%x:%d\n",
//     ip->saddr, src_port, ip->daddr, dest_port);
}

bpf_ringbuf_submit(evt, 0);
bpf_printk("Evt submit done!\n");
return XDP_PASS;

failure:
bpf_printk("Failure!\n");
bpf_ringbuf_discard(evt, 0);
return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";
include/omega.h:

Код: Выделить всё

#ifndef __OMEGA_H__
#define __OMEGA_H__

#define MAX_EVENT_LEN 24

struct packet_evt {
__u32 src_ip;
__u32 dst_ip;
__u16 src_port;
__u16 dst_port;
};

#endif // __OMEGA_H__
src/loader.c

Код: Выделить всё

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "../omega.skel.h"
#include "../include/omega.h"

static volatile int stop = 0;

static void bump_memlock_rlimit(void) {
struct rlimit rlim_new = {
.rlim_cur   = RLIM_INFINITY,
.rlim_max   = RLIM_INFINITY,
};

if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}

void handle_signal(int sig) {
stop = 1;
}

static int handle_evt(void *ctx, void *data, size_t sz) {
const struct packet_evt *evt = data;

fprintf(stdout, "Received Event: SRC IP: %u DST IP: %u SRC PORT: %u DST PORT: %u\n",
evt->src_ip, evt->dst_ip, evt->src_port, evt->dst_port);
fflush(stdout);

return 0;
}

int main(void) {
struct omega *skel = NULL;
struct ring_buffer *rb = NULL;

signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal);

// Increase rlimit for BPF memory lock
bump_memlock_rlimit();

skel = omega__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeleton\n");
return 1;
}

if (omega__load(skel)) {
fprintf(stderr, "Failed to load BPF skeleton\n");
omega__destroy(skel);
return 1;
}

if (omega__attach(skel)) {
fprintf(stderr, "Failed to attach BPF skeleton\n");
omega__destroy(skel);
return 1;
}

// Set up ring buffer
int rb_fd = bpf_map__fd(skel->maps.rb);
if (rb_fd < 0) {
fprintf(stderr, "Failed to get ring buffer FD\n");
omega__destroy(skel);
return 1;
}

rb = ring_buffer__new(rb_fd, handle_evt, NULL, NULL);
if (!rb) {
fprintf(stderr, "Failed to create ring buffer\n");
omega__destroy(skel);
return 1;
}

printf("Ring buffer successfully created. Waiting for events...\n");

while (!stop) {
int err = ring_buffer__poll(rb, 1000);
if (err < 0) {
fprintf(stderr, "Error polling ring buffer: %d\n", err);
break;
}
}

printf("Cleaning up...\n");
ring_buffer__free(rb);
omega__destroy(skel);

return 0;
}

Когда я кошка/sys/kernel/debug/tracing/trace_pipe
bpf_trace_printk: Событие отправки: SRC IP: 108CA203 DST IP: 6D00A8C0 SRC Port: 443 DST Port: 55938 < /p>
Также, когда я запускаю погрузчик, я получаю.
Ring Buffer успешно создан. В ожидании событий ... < /p>
Также он печатает EVT отправить! Таким образом, код наверняка приходит в Rinbuf_submit. < /p>
Я не уверен, что может быть потенциальным исправлением или следующими шагами отладки. Я предполагаю, что harder_evt не может быть вызван, но опять же, очень сомневаюсь в этом. есть.

Подробнее здесь: https://stackoverflow.com/questions/794 ... -populated
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Linux»