Как установить количество ядер / потоков, используемых хуком XDP? - PullRequest
2 голосов
/ 18 января 2020

Я использую многопользовательскую реализацию для одного потребителя на стороне пользователя для обработки входящих данных из карты eBPF из ловушки XDP.

Однако для этого мне нужно ограничить число ядер, которые может использовать ловушка XDP для отправки информации в пространство пользователя по одному.

Есть ли способ, которым мы можем сделать это?

Я использую BPF_MAP_TYPE_PERF_EVENT_ARRAY, и я подключаю код ядра через bpf_prog_load_xattr и bpf_set_link_xdp_fd.

Вот функция, которая загружает ловушку.

static int do_attach(int idx, int fd, const char *name, __u32 xdp_flags)
{
    struct bpf_prog_info info = {};
    __u32 info_len = sizeof(info);
    int err;

    err = bpf_set_link_xdp_fd(idx, fd, xdp_flags);
    if (err < 0) {
        printf("ERROR: failed to attach program to %s\n", name);
        return err;
    }

    err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
    if (err) {
        printf("can't get prog info - %s\n", strerror(errno));
        return err;
    }
    prog_id = info.id;

    return err;
}

И вот где она используется.

int main(int argc, char **argv)
{
    struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
    struct bpf_prog_load_attr prog_load_attr = {
        .prog_type  = BPF_PROG_TYPE_XDP,
    };
    int prog_fd, map_fd;
    struct bpf_object *obj;
    struct bpf_map *map;
    char filename[256];
    int ret, err, i;
    int numcpus = bpf_num_possible_cpus();
        struct config cfg = {
                .xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_DRV_MODE,
                .ifindex   = -1,
        };

    strncpy(cfg.filename, default_filename, sizeof(cfg.filename));

        /* Cmdline options can change these */
        parse_cmdline_args(argc, argv, long_options, &cfg, __doc__);

    /* Required option */
    if (cfg.ifindex == -1) {
        fprintf(stderr, "ERR: required option --dev missing\n");
        usage(argv[0], __doc__, long_options, (argc == 1));
        return EXIT_FAIL_OPTION;
    }

    if (setrlimit(RLIMIT_MEMLOCK, &r)) {
        perror("setrlimit(RLIMIT_MEMLOCK)");
        return 1;
    }

    snprintf(filename, sizeof(filename), "xdp_sample_pkts_kern.o");
    prog_load_attr.file = filename;

    if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
        return 1;

    if (!prog_fd) {
        printf("load_bpf_file: %s\n", strerror(errno));
        return 1;
    }

    map = bpf_map__next(NULL, obj);
    if (!map) {
        printf("finding a map in obj file failed\n");
        return 1;
    }
    map_fd = bpf_map__fd(map);

    err = do_attach(cfg.ifindex, prog_fd, cfg.ifname, cfg.xdp_flags);
    if (err)
        return err;

    if (signal(SIGINT, sig_handler) ||
        signal(SIGHUP, sig_handler) ||
        signal(SIGTERM, sig_handler)) {
        perror("signal");
        return 1;
    }

    test_bpf_perf_event(map_fd, numcpus);

    for (i = 0; i < numcpus; i++)
        if (perf_event_mmap_header(pmu_fds[i], &headers[i]) < 0)
            return 1;

    pd = pcap_open_dead(DLT_EN10MB, 65535);
    if (!pd)
        goto out;

    pdumper = pcap_dump_open(pd, cfg.filename);
    if (!pdumper)
        goto out;

    ret = perf_event_poller_multi(pmu_fds, headers, numcpus,
                      print_bpf_output, &done);

    pcap_dump_close(pdumper);
    pcap_close(pd);

out:
    do_detach(cfg.ifindex, cfg.ifname);
    printf("\n%u packet samples stored in %s\n", pcap_pkts, cfg.filename);
    return ret;
}
...