Как использовать BPF_MAP_TYPE_CPUMAP?Linux

Ответить
Anonymous
 Как использовать BPF_MAP_TYPE_CPUMAP?

Сообщение Anonymous »

Я работаю над программой BPF, в которой мне нужно обновить карту BPF новым элементом. Однако я столкнулся с ошибкой «Невозможно выделить память». Вот соответствующая часть моего кода:
Я хочу создать простую демонстрационную версию BPF_MAP_TYPE_CPUMAP и перенаправлять каждый пакет на cpu0 и печатать журнал в канал.
Для ядра:

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

// cpu_map_kernel.c
#include 
#include 
struct {
__uint(type, BPF_MAP_TYPE_CPUMAP);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(struct bpf_cpumap_val));
__uint(pinning, LIBBPF_PIN_BY_NAME);
} cpu_map SEC(".maps");

SEC("xdp")
int xdp_main(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;

struct ethhdr *eth = data;
if (eth + 1 > data_end)
return XDP_PASS;

struct iphdr *ip = data + sizeof(*eth);
if (ip + 1 > data_end)
return XDP_PASS;
if (ip->protocol != IPPROTO_UDP)
return XDP_PASS;

__u32 cpu_dest = 0;
return bpf_redirect_map(&cpu_map, cpu_dest, 0);
}

SEC("xdp")
int just_pass(struct xdp_md *ctx)
{
bpf_printk("Just pass by cpu0\n");
return XDP_PASS;
}

char _license[] SEC("license") = "GPL";
Для пользовательского пространства:

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

// cpu_map_user.c
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "cpu_map.skel.h"

static volatile int quit = 0;

void sigint_handler(int signum)
{
quit = 1;
}

int main()
{
struct cpu_map_bpf *skel;
__u32 xdp_flags = 0;
int ret;
int n_cpus = libbpf_num_possible_cpus();
printf("Current libbpf_num_possible_cpus: %d\n", n_cpus);

// By default, 8MiB of memory can be locked to RAM
struct rlimit r = { RLIM_INFINITY, RLIM_INFINITY };
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit failed");
return 1;
}

struct rlimit cur = {};
getrlimit(RLIMIT_MEMLOCK, &cur);
printf("Current Mem limit: cur %lld, max %lld\n", cur.rlim_cur, cur.rlim_max);

skel = cpu_map_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeleton\n");
goto end_destroy;
}

if (bpf_map__set_max_entries(skel->maps.cpu_map, n_cpus) < 0) {
fprintf(stderr, "Failed to set max entries for cpu_map map: %s", strerror(errno));
goto end_destroy;
}

ret = cpu_map_bpf__load(skel);
if (ret < 0) {
fprintf(stderr, "Failed to cpu_map_bpf__load: %s\n", strerror(errno));
goto end_destroy;
}

int cpu_map_fd = bpf_map__fd(skel->maps.cpu_map);
int just_pass_fd = bpf_program__fd(skel->progs.just_pass);
struct bpf_cpumap_val val = {
.qsize = 1024,
.bpf_prog.fd = just_pass_fd,
};
__u32 cpu = 0;
ret = bpf_map_update_elem(cpu_map_fd, &cpu, &val, BPF_EXIST);
if (ret < 0) {
fprintf(stderr, "Failed to update cpu_map: %s\n", strerror(errno));
goto end_destroy;
} else {
fprintf(stderr, "Successfully updated cpu_map\n");
return 0;
}

int LO_IFINDEX = 1;
int cpu_prog_fd = bpf_program__fd(skel->progs.xdp_main);
if (bpf_xdp_attach(LO_IFINDEX, cpu_prog_fd, xdp_flags, NULL) <  0) {
fprintf(stderr, "Error: bpf_set_link_xdp_fd failed for interface %d\n", LO_IFINDEX);
goto end_destroy;
} else {
printf("Main BPF program attached to XDP on interface %d\n", LO_IFINDEX);
}

printf("Successfully started!\n");
signal(SIGINT, sigint_handler);
signal(SIGINT, sigint_handler);
signal(SIGTERM, sigint_handler);
while (!quit)
usleep(100000);
printf("Exiting...\n");
goto end_destroy;

end_destroy:
cpu_map_bpf__destroy(skel);
printf("End of the program\n");
return 0;
}
Происходит сбой с ошибкой:

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

Current libbpf_num_possible_cpus: 24
Current Mem limit: cur -1, max -1
Failed to update cpu_map: Cannot allocate memory
End of the program
Что означает «Невозможно выделить память (с идентификатором ENOMEM)»? Как это исправить?
Я пытался установить для RLIMIT_MEMLOCK значение RLIM_INFINITY, но на bpf_map_update_elem(map_progs_xdp_fd, &XDP_PROG_SET_CACHE_ENTRY, &set_cache_entry_fd, 0);

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

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

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

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

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

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