#define CREATE_CMD
#include "bpf.h"
-static const char dash[100] = {[0 ... 99] = '-'};
-
#define MAX_MAPS 32
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)
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
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;
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;
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;
}
if (load_maps(nvme_fd, map_data, nr_maps))
return -EINVAL;
- map_data_count = nr_maps;
processed_sec[maps_shndx] = true;
}
}
}
- 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);
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 = {
};
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()
};
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;
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;