]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
wip bpf
authorChristoph Hellwig <hch@lst.de>
Thu, 12 Nov 2020 10:10:13 +0000 (11:10 +0100)
committerChristoph Hellwig <hch@lst.de>
Thu, 12 Nov 2020 13:16:07 +0000 (14:16 +0100)
plugins/bpf/bpf.c

index a63faf0a310106c25e89e14fee076c4fc461ef68..276847a6e28c83be1fcde02d6976df8a3bff3ca3 100644 (file)
@@ -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;