19406b485SYonghong Song // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 29406b485SYonghong Song // Copyright (C) 2020 Facebook 39406b485SYonghong Song 49406b485SYonghong Song #define _GNU_SOURCE 5d8793acaSYonghong Song #include <unistd.h> 69406b485SYonghong Song #include <linux/err.h> 79406b485SYonghong Song #include <bpf/libbpf.h> 89406b485SYonghong Song 99406b485SYonghong Song #include "main.h" 109406b485SYonghong Song 119406b485SYonghong Song static int do_pin(int argc, char **argv) 129406b485SYonghong Song { 13d8793acaSYonghong Song DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, iter_opts); 1474fc097dSYonghong Song union bpf_iter_link_info linfo; 159406b485SYonghong Song const char *objfile, *path; 169406b485SYonghong Song struct bpf_program *prog; 179406b485SYonghong Song struct bpf_object *obj; 189406b485SYonghong Song struct bpf_link *link; 19d8793acaSYonghong Song int err = -1, map_fd = -1; 209406b485SYonghong Song 219406b485SYonghong Song if (!REQ_ARGS(2)) 229406b485SYonghong Song usage(); 239406b485SYonghong Song 249406b485SYonghong Song objfile = GET_ARG(); 259406b485SYonghong Song path = GET_ARG(); 269406b485SYonghong Song 27d8793acaSYonghong Song /* optional arguments */ 28d8793acaSYonghong Song if (argc) { 29d8793acaSYonghong Song if (is_prefix(*argv, "map")) { 30d8793acaSYonghong Song NEXT_ARG(); 31d8793acaSYonghong Song 32d8793acaSYonghong Song if (!REQ_ARGS(2)) { 33d8793acaSYonghong Song p_err("incorrect map spec"); 34d8793acaSYonghong Song return -1; 35d8793acaSYonghong Song } 36d8793acaSYonghong Song 37d8793acaSYonghong Song map_fd = map_parse_fd(&argc, &argv); 38d8793acaSYonghong Song if (map_fd < 0) 39d8793acaSYonghong Song return -1; 4074fc097dSYonghong Song 4174fc097dSYonghong Song memset(&linfo, 0, sizeof(linfo)); 4274fc097dSYonghong Song linfo.map.map_fd = map_fd; 4374fc097dSYonghong Song iter_opts.link_info = &linfo; 4474fc097dSYonghong Song iter_opts.link_info_len = sizeof(linfo); 45d8793acaSYonghong Song } 46d8793acaSYonghong Song } 47d8793acaSYonghong Song 489406b485SYonghong Song obj = bpf_object__open(objfile); 499406b485SYonghong Song if (IS_ERR(obj)) { 509406b485SYonghong Song p_err("can't open objfile %s", objfile); 51d8793acaSYonghong Song goto close_map_fd; 529406b485SYonghong Song } 539406b485SYonghong Song 549406b485SYonghong Song err = bpf_object__load(obj); 559406b485SYonghong Song if (err) { 569406b485SYonghong Song p_err("can't load objfile %s", objfile); 579406b485SYonghong Song goto close_obj; 589406b485SYonghong Song } 599406b485SYonghong Song 609406b485SYonghong Song prog = bpf_program__next(NULL, obj); 619406b485SYonghong Song if (!prog) { 629406b485SYonghong Song p_err("can't find bpf program in objfile %s", objfile); 639406b485SYonghong Song goto close_obj; 649406b485SYonghong Song } 659406b485SYonghong Song 66d8793acaSYonghong Song link = bpf_program__attach_iter(prog, &iter_opts); 679406b485SYonghong Song if (IS_ERR(link)) { 689406b485SYonghong Song err = PTR_ERR(link); 699406b485SYonghong Song p_err("attach_iter failed for program %s", 709406b485SYonghong Song bpf_program__name(prog)); 719406b485SYonghong Song goto close_obj; 729406b485SYonghong Song } 739406b485SYonghong Song 749406b485SYonghong Song err = mount_bpffs_for_pin(path); 759406b485SYonghong Song if (err) 769406b485SYonghong Song goto close_link; 779406b485SYonghong Song 789406b485SYonghong Song err = bpf_link__pin(link, path); 799406b485SYonghong Song if (err) { 809406b485SYonghong Song p_err("pin_iter failed for program %s to path %s", 819406b485SYonghong Song bpf_program__name(prog), path); 829406b485SYonghong Song goto close_link; 839406b485SYonghong Song } 849406b485SYonghong Song 859406b485SYonghong Song close_link: 869406b485SYonghong Song bpf_link__destroy(link); 879406b485SYonghong Song close_obj: 889406b485SYonghong Song bpf_object__close(obj); 89d8793acaSYonghong Song close_map_fd: 90d8793acaSYonghong Song if (map_fd >= 0) 91d8793acaSYonghong Song close(map_fd); 929406b485SYonghong Song return err; 939406b485SYonghong Song } 949406b485SYonghong Song 959406b485SYonghong Song static int do_help(int argc, char **argv) 969406b485SYonghong Song { 979406b485SYonghong Song fprintf(stderr, 98d8793acaSYonghong Song "Usage: %1$s %2$s pin OBJ PATH [map MAP]\n" 9990040351SQuentin Monnet " %1$s %2$s help\n" 100*c07ba629SQuentin Monnet "\n" 101d8793acaSYonghong Song " " HELP_SPEC_MAP "\n" 102*c07ba629SQuentin Monnet " " HELP_SPEC_OPTIONS " }\n" 10390040351SQuentin Monnet "", 10490040351SQuentin Monnet bin_name, "iter"); 1059406b485SYonghong Song 1069406b485SYonghong Song return 0; 1079406b485SYonghong Song } 1089406b485SYonghong Song 1099406b485SYonghong Song static const struct cmd cmds[] = { 1109406b485SYonghong Song { "help", do_help }, 1119406b485SYonghong Song { "pin", do_pin }, 1129406b485SYonghong Song { 0 } 1139406b485SYonghong Song }; 1149406b485SYonghong Song 1159406b485SYonghong Song int do_iter(int argc, char **argv) 1169406b485SYonghong Song { 1179406b485SYonghong Song return cmd_select(cmds, argc, argv, do_help); 1189406b485SYonghong Song } 119