Я хочу создать простую демонстрационную версию 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
Я пытался установить для 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
Мобильная версия