static int do_help(int argc, char **argv) { if (json_output) { jsonw_null(json_wtr); return 0; } fprintf(stderr, "Usage: %s %s { show | list } CGROUP\n" " %s %s tree [CGROUP_ROOT]\n" " %s %s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n" " %s %s detach CGROUP ATTACH_TYPE PROG\n" " %s %s help\n" "\n" HELP_SPEC_ATTACH_TYPES "\n" " " HELP_SPEC_ATTACH_FLAGS "\n" " " HELP_SPEC_PROGRAM "\n" " " HELP_SPEC_OPTIONS "\n" "", bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); return 0; }
static int do_attach(int argc, char **argv) { enum bpf_attach_type attach_type; int cgroup_fd, prog_fd; int attach_flags = 0; int ret = -1; int i; if (argc < 4) { p_err("too few parameters for cgroup attach"); goto exit; } cgroup_fd = open(argv[0], O_RDONLY); if (cgroup_fd < 0) { p_err("can't open cgroup %s", argv[1]); goto exit; } attach_type = parse_attach_type(argv[1]); if (attach_type == __MAX_BPF_ATTACH_TYPE) { p_err("invalid attach type"); goto exit_cgroup; } argc -= 2; argv = &argv[2]; prog_fd = prog_parse_fd(&argc, &argv); if (prog_fd < 0) goto exit_cgroup; for (i = 0; i < argc; i++) { if (is_prefix(argv[i], "multi")) { attach_flags |= BPF_F_ALLOW_MULTI; } else if (is_prefix(argv[i], "override")) { attach_flags |= BPF_F_ALLOW_OVERRIDE; } else { p_err("unknown option: %s", argv[i]); goto exit_cgroup; } } if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, attach_flags)) { p_err("failed to attach program"); goto exit_prog; } if (json_output) jsonw_null(json_wtr); ret = 0; exit_prog: close(prog_fd); exit_cgroup: close(cgroup_fd); exit: return ret; }
/* * In JSON context we don't use the argument "value" we simply call jsonw_null * whereas FP context can use "value" to output anything */ void print_color_null(enum output_type type, enum color_attr color, const char *key, const char *fmt, const char *value) { if (_IS_JSON_CONTEXT(type)) { if (key) jsonw_null_field(_jw, key); else jsonw_null(_jw); } else if (_IS_FP_CONTEXT(type)) { color_fprintf(stdout, color, fmt, value); } }
static int do_detach(int argc, char **argv) { enum bpf_attach_type attach_type; int prog_fd, cgroup_fd; int ret = -1; if (argc < 4) { p_err("too few parameters for cgroup detach"); goto exit; } cgroup_fd = open(argv[0], O_RDONLY); if (cgroup_fd < 0) { p_err("can't open cgroup %s", argv[1]); goto exit; } attach_type = parse_attach_type(argv[1]); if (attach_type == __MAX_BPF_ATTACH_TYPE) { p_err("invalid attach type"); goto exit_cgroup; } argc -= 2; argv = &argv[2]; prog_fd = prog_parse_fd(&argc, &argv); if (prog_fd < 0) goto exit_cgroup; if (bpf_prog_detach2(prog_fd, cgroup_fd, attach_type)) { p_err("failed to detach program"); goto exit_prog; } if (json_output) jsonw_null(json_wtr); ret = 0; exit_prog: close(prog_fd); exit_cgroup: close(cgroup_fd); exit: return ret; }
static int do_help(int argc, char **argv) { if (json_output) { jsonw_null(json_wtr); return 0; } fprintf(stderr, "Usage: %s %s { show | list } [dev <devname>]\n" " %s %s help\n" "Note: Only xdp and tc attachments are supported now.\n" " For progs attached to cgroups, use \"bpftool cgroup\"\n" " to dump program attachments. For program types\n" " sk_{filter,skb,msg,reuseport} and lwt/seg6, please\n" " consult iproute2.\n", bin_name, argv[-2], bin_name, argv[-2]); return 0; }
static int do_help(int argc, char **argv) { if (json_output) { jsonw_null(json_wtr); return 0; } fprintf(stderr, "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" " %s batch file FILE\n" " %s version\n" "\n" " OBJECT := { prog | map | cgroup | perf | net | feature | btf }\n" " " HELP_SPEC_OPTIONS "\n" "", bin_name, bin_name, bin_name); return 0; }
static int do_help(int argc, char **argv) { if (json_output) { jsonw_null(json_wtr); return 0; } fprintf(stderr, "Usage: %s btf dump BTF_SRC\n" " %s btf help\n" "\n" " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n" " " HELP_SPEC_MAP "\n" " " HELP_SPEC_PROGRAM "\n" " " HELP_SPEC_OPTIONS "\n" "", bin_name, bin_name); return 0; }
static int do_show(int argc, char **argv) { int i, sock, ret, filter_idx = -1; struct bpf_netdev_t dev_array; unsigned int nl_pid; char err_buf[256]; if (argc == 2) { if (strcmp(argv[0], "dev") != 0) usage(); filter_idx = if_nametoindex(argv[1]); if (filter_idx == 0) { fprintf(stderr, "invalid dev name %s\n", argv[1]); return -1; } } else if (argc != 0) { usage(); } sock = libbpf_netlink_open(&nl_pid); if (sock < 0) { fprintf(stderr, "failed to open netlink sock\n"); return -1; } dev_array.devices = NULL; dev_array.used_len = 0; dev_array.array_len = 0; dev_array.filter_idx = filter_idx; if (json_output) jsonw_start_array(json_wtr); NET_START_OBJECT; NET_START_ARRAY("xdp", "%s:\n"); ret = libbpf_nl_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array); NET_END_ARRAY("\n"); if (!ret) { NET_START_ARRAY("tc", "%s:\n"); for (i = 0; i < dev_array.used_len; i++) { ret = show_dev_tc_bpf(sock, nl_pid, &dev_array.devices[i]); if (ret) break; } NET_END_ARRAY("\n"); } NET_END_OBJECT; if (json_output) jsonw_end_array(json_wtr); if (ret) { if (json_output) jsonw_null(json_wtr); libbpf_strerror(ret, err_buf, sizeof(err_buf)); fprintf(stderr, "Error: %s\n", err_buf); } free(dev_array.devices); close(sock); return ret; }
void jsonw_null_field(json_writer_t *self, const char *prop) { jsonw_name(self, prop); jsonw_null(self); }