From: Christoph Hellwig Date: Thu, 12 Nov 2020 10:10:13 +0000 (+0100) Subject: wip X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fbpf;p=users%2Fhch%2Fnvme-cli.git wip --- diff --git a/plugins/bpf/bpf.c b/plugins/bpf/bpf.c index a63faf0..276847a 100644 --- a/plugins/bpf/bpf.c +++ b/plugins/bpf/bpf.c @@ -30,8 +30,6 @@ #define CREATE_CMD #include "bpf.h" -static const char dash[100] = {[0 ... 99] = '-'}; - #define MAX_MAPS 32 struct bpf_load_map_def { @@ -44,17 +42,22 @@ struct bpf_load_map_def { unsigned int numa_node; }; +static struct bpf_map_ids { + int id; + char *name; +} map_ids[MAX_MAPS] = { + [0 ... MAX_MAPS - 1] = { + .id = -1, + }, +}; +static int nr_map_ids; + struct bpf_map_data { int id; char *name; size_t elf_offset; struct bpf_load_map_def def; }; -static int map_id[MAX_MAPS]; -static struct bpf_map_data map_data[MAX_MAPS]; -static int map_data_count; - -static bool processed_sec[128]; static int get_sec(Elf * elf, int i, GElf_Ehdr * ehdr, char **shname, GElf_Shdr * shdr, Elf_Data ** data) @@ -176,7 +179,7 @@ static int load_elf_maps_section(struct bpf_map_data *maps, int maps_shndx, nr_maps++; } - /* Align to map_id[] order, via sort on offset in sym.st_value */ + /* Align to maps[] order, via sort on offset in sym.st_value */ qsort(sym, nr_maps, sizeof(GElf_Sym), cmp_symbols); /* Keeping compatible with ELF maps section changes @@ -271,18 +274,36 @@ static int create_map(int nvme_fd, struct bpf_map_data *map) return cmd.result; } -static int load_maps(int nvme_fd, struct bpf_map_data *maps, int nr_maps) +static int find_map(struct bpf_map_data *map) { int i; + for (i = 0; i < nr_map_ids; i++) { + if (strcmp(map_ids[i].name, map->name) == 0) + return map_ids[i].id; + } + + return -1; +} + +static int load_maps(int nvme_fd, struct bpf_map_data *maps, int nr_maps) +{ + int id, i; + for (i = 0; i < nr_maps; i++) { - map_id[i] = create_map(nvme_fd, &maps[i]); - if (map_id[i] < 0) { - printf("failed to create map %d (%s): %d %s\n", - i, maps[i].name, errno, strerror(errno)); - return -EINVAL; + id = find_map(&maps[i]); + if (id < 0) { + id = create_map(nvme_fd, &maps[i]); + if (id < 0) { + printf("failed to create map %d (%s): %d %s\n", + i, maps[i].name, errno, strerror(errno)); + return -EINVAL; + } + map_ids[nr_map_ids].name = strdup(maps[i].name); + map_ids[nr_map_ids].id = id; + nr_map_ids++; } - maps[i].id = map_id[i]; + maps[i].id = id; } return 0; @@ -315,6 +336,12 @@ static int load_prog(int nvme_fd, struct bpf_insn *prog, int size, static int nvme_bpf_load_program(int nvme_fd, int fd, __u32 slot) { + struct bpf_map_data map_data[MAX_MAPS] = { + [0 ... MAX_MAPS - 1] = { + .id = -1, + }, + }; + bool processed_sec[128]; GElf_Ehdr ehdr; GElf_Shdr shdr, shdr_prog; Elf_Data *data_maps = NULL; @@ -343,12 +370,8 @@ static int nvme_bpf_load_program(int nvme_fd, int fd, __u32 slot) continue; if (strcmp(shname, "maps") == 0) { - int j; - maps_shndx = i; data_maps = data; - for (j = 0; j < MAX_MAPS; j++) - map_data[j].id = -1; } else if (shdr.sh_type == SHT_SYMTAB) { strtabidx = shdr.sh_link; symbols = data; @@ -370,7 +393,6 @@ static int nvme_bpf_load_program(int nvme_fd, int fd, __u32 slot) } if (load_maps(nvme_fd, map_data, nr_maps)) return -EINVAL; - map_data_count = nr_maps; processed_sec[maps_shndx] = true; } @@ -418,33 +440,36 @@ static int nvme_bpf_load_program(int nvme_fd, int fd, __u32 slot) } } - return nr_maps; + return 0; } -static void nvme_bpf_show_maps(int nr_maps) +static void nvme_bpf_show_maps(void) { + static const char dash[100] = {[0 ... 99] = '-'}; int i; printf("%-32s %-32s\n", "Name", "ID"); printf("%-.32s %-.32s\n", dash, dash); - for (i = 0; i < nr_maps; i++) - printf("%-32s %-32u\n", map_data[i].name, map_data[i].id); + for (i = 0; i < nr_map_ids; i++) + printf("%-32s %-32u\n", + map_ids[i].name, map_ids[i].id); } -static void nvme_bpf_show_maps_json(int nr_maps) +static void nvme_bpf_show_maps_json(void) { struct json_object *root = json_create_object(); struct json_array *maps; int i; maps = json_create_array(); - for (i = 0; i < nr_maps; i++) { - struct bpf_map_data *map = &map_data[i]; + for (i = 0; i < nr_map_ids; i++) { struct json_object *map_attrs = json_create_object(); - json_object_add_value_string(map_attrs, "Name", map->name); - json_object_add_value_int(map_attrs, "ID", map->id); + json_object_add_value_string(map_attrs, "Name", + map_ids[i].name); + json_object_add_value_int(map_attrs, "ID", + map_ids[i].id); json_array_add_value_object(maps, map_attrs); } json_object_add_value_array(root, "Maps", maps); @@ -453,20 +478,23 @@ static void nvme_bpf_show_maps_json(int nr_maps) json_free_object(root); } -static const char *output_format_no_binary = "Output format: normal|json"; - static int load_program(int argc, char **argv, struct command *cmd, struct plugin *plugin) { + static const char *output_format_no_binary = + "Output format: normal|json"; const char *desc = "Load an eBPF program into the NVMe controller"; - const char *pname = "File name of the eBPF program"; - const char *slot = "eBPF program slot"; + const char *pname = "File names of the eBPF programs"; + const char *slot = "eBPF program slots"; enum nvme_print_flags flags; int fd, pfd, ret = -EINVAL; + char *programs[256]; + int slots[256]; + int np, ns, i; struct config { char *output_format; - char *program; - __u32 slot; + char *programs; + char *slots; }; struct config cfg = { @@ -474,10 +502,10 @@ static int load_program(int argc, char **argv, struct command *cmd, }; OPT_ARGS(opts) = { - OPT_FMT("output-format", 'o', &cfg.output_format, + OPT_FMT("output-format", 'o', &cfg.output_format, output_format_no_binary), - OPT_FILE("program", 'p', &cfg.program, pname), - OPT_UINT("slot", 's', &cfg.slot, slot), + OPT_LIST("programs", 'p', &cfg.programs, pname), + OPT_LIST("slots", 's', &cfg.slots, slot), OPT_END() }; @@ -485,11 +513,6 @@ static int load_program(int argc, char **argv, struct command *cmd, if (fd < 0) return errno; - if (!strlen(cfg.program)) { - fprintf(stderr, "program argument is required\n"); - goto close_fd; - } - flags = validate_output_format(cfg.output_format); if (flags < 0) { ret = flags; @@ -500,23 +523,50 @@ static int load_program(int argc, char **argv, struct command *cmd, goto close_fd; } - pfd = open(cfg.program, O_RDONLY); - if (pfd < 0) { - perror("failed to open program"); + ret = -EINVAL; + np = argconfig_parse_comma_sep_array_string(cfg.programs, programs, + ARRAY_SIZE(programs)); + if (!np) { + fprintf(stderr, "No program provided\n"); + goto close_fd; + } + ns = argconfig_parse_comma_sep_array(cfg.slots, slots, ARRAY_SIZE(slots)); + if (!ns) { + fprintf(stderr, "No slot provided\n"); + goto close_fd; + } + if (np != ns) { + fprintf(stderr, "Nr of programs does not match nr of slots\n"); goto close_fd; } - ret = nvme_bpf_load_program(fd, pfd, cfg.slot); - if (ret > 0) { - if (flags & JSON) - nvme_bpf_show_maps_json(ret); - else - nvme_bpf_show_maps(ret); + for (i = 0; i < np; i++) { + if (!strlen(programs[i])) { + fprintf(stderr, "program argument is required\n"); + goto close_fd; + } + + + pfd = open(programs[i], O_RDONLY); + if (pfd < 0) { + perror("failed to open program"); + goto close_fd; + } + + ret = nvme_bpf_load_program(fd, pfd, slots[i]); + close(pfd); + if (ret < 0) { + fprintf(stderr, "failed to load bpf program %s: %d\n", + programs[i], ret); + goto close_fd; + } } - else if (ret < 0) - fprintf(stderr, "failed to load bpf program: %d\n", ret); - close(pfd); + if (flags & JSON) + nvme_bpf_show_maps_json(); + else + nvme_bpf_show_maps(); + close_fd: close(fd); return ret > 0 ? 0 : ret;