diff options
author | Jakub Kicinski <jakub.kicinski@netronome.com> | 2018-07-10 17:43:03 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-07-11 16:13:34 -0400 |
commit | c8406848badd0a0b040b0d286e612678662a2ab3 (patch) | |
tree | 268065cfe8a88a0dd001d3fb0808526d473568bf /tools/bpf/bpftool/prog.c | |
parent | 07f2d4eac2a850fc9649b27aa935cdcd263fb1ff (diff) |
tools: bpftool: reimplement bpf_prog_load() for prog load
bpf_prog_load() is a very useful helper but it doesn't give us full
flexibility of modifying the BPF objects before loading. Open code
bpf_prog_load() in bpftool so we can add extra logic in following
commits.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/bpf/bpftool/prog.c')
-rw-r--r-- | tools/bpf/bpftool/prog.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 98695585bbb6..2bdd5ecd1aad 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include <sys/types.h> | 43 | #include <sys/types.h> |
44 | #include <sys/stat.h> | 44 | #include <sys/stat.h> |
45 | 45 | ||
46 | #include <linux/err.h> | ||
47 | |||
46 | #include <bpf.h> | 48 | #include <bpf.h> |
47 | #include <libbpf.h> | 49 | #include <libbpf.h> |
48 | 50 | ||
@@ -682,17 +684,20 @@ static int do_pin(int argc, char **argv) | |||
682 | 684 | ||
683 | static int do_load(int argc, char **argv) | 685 | static int do_load(int argc, char **argv) |
684 | { | 686 | { |
685 | struct bpf_prog_load_attr attr = { | 687 | enum bpf_attach_type expected_attach_type; |
688 | struct bpf_object_open_attr attr = { | ||
686 | .prog_type = BPF_PROG_TYPE_UNSPEC, | 689 | .prog_type = BPF_PROG_TYPE_UNSPEC, |
687 | }; | 690 | }; |
688 | const char *objfile, *pinfile; | 691 | struct bpf_program *prog; |
689 | struct bpf_object *obj; | 692 | struct bpf_object *obj; |
690 | int prog_fd; | 693 | struct bpf_map *map; |
694 | const char *pinfile; | ||
695 | __u32 ifindex = 0; | ||
691 | int err; | 696 | int err; |
692 | 697 | ||
693 | if (!REQ_ARGS(2)) | 698 | if (!REQ_ARGS(2)) |
694 | return -1; | 699 | return -1; |
695 | objfile = GET_ARG(); | 700 | attr.file = GET_ARG(); |
696 | pinfile = GET_ARG(); | 701 | pinfile = GET_ARG(); |
697 | 702 | ||
698 | while (argc) { | 703 | while (argc) { |
@@ -719,7 +724,7 @@ static int do_load(int argc, char **argv) | |||
719 | strcat(type, "/"); | 724 | strcat(type, "/"); |
720 | 725 | ||
721 | err = libbpf_prog_type_by_name(type, &attr.prog_type, | 726 | err = libbpf_prog_type_by_name(type, &attr.prog_type, |
722 | &attr.expected_attach_type); | 727 | &expected_attach_type); |
723 | free(type); | 728 | free(type); |
724 | if (err < 0) { | 729 | if (err < 0) { |
725 | p_err("unknown program type '%s'", *argv); | 730 | p_err("unknown program type '%s'", *argv); |
@@ -729,15 +734,15 @@ static int do_load(int argc, char **argv) | |||
729 | } else if (is_prefix(*argv, "dev")) { | 734 | } else if (is_prefix(*argv, "dev")) { |
730 | NEXT_ARG(); | 735 | NEXT_ARG(); |
731 | 736 | ||
732 | if (attr.ifindex) { | 737 | if (ifindex) { |
733 | p_err("offload device already specified"); | 738 | p_err("offload device already specified"); |
734 | return -1; | 739 | return -1; |
735 | } | 740 | } |
736 | if (!REQ_ARGS(1)) | 741 | if (!REQ_ARGS(1)) |
737 | return -1; | 742 | return -1; |
738 | 743 | ||
739 | attr.ifindex = if_nametoindex(*argv); | 744 | ifindex = if_nametoindex(*argv); |
740 | if (!attr.ifindex) { | 745 | if (!ifindex) { |
741 | p_err("unrecognized netdevice '%s': %s", | 746 | p_err("unrecognized netdevice '%s': %s", |
742 | *argv, strerror(errno)); | 747 | *argv, strerror(errno)); |
743 | return -1; | 748 | return -1; |
@@ -750,14 +755,44 @@ static int do_load(int argc, char **argv) | |||
750 | } | 755 | } |
751 | } | 756 | } |
752 | 757 | ||
753 | attr.file = objfile; | 758 | obj = bpf_object__open_xattr(&attr); |
754 | 759 | if (IS_ERR_OR_NULL(obj)) { | |
755 | if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) { | 760 | p_err("failed to open object file"); |
756 | p_err("failed to load program"); | ||
757 | return -1; | 761 | return -1; |
758 | } | 762 | } |
759 | 763 | ||
760 | if (do_pin_fd(prog_fd, pinfile)) | 764 | prog = bpf_program__next(NULL, obj); |
765 | if (!prog) { | ||
766 | p_err("object file doesn't contain any bpf program"); | ||
767 | goto err_close_obj; | ||
768 | } | ||
769 | |||
770 | bpf_program__set_ifindex(prog, ifindex); | ||
771 | if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { | ||
772 | const char *sec_name = bpf_program__title(prog, false); | ||
773 | |||
774 | err = libbpf_prog_type_by_name(sec_name, &attr.prog_type, | ||
775 | &expected_attach_type); | ||
776 | if (err < 0) { | ||
777 | p_err("failed to guess program type based on section name %s\n", | ||
778 | sec_name); | ||
779 | goto err_close_obj; | ||
780 | } | ||
781 | } | ||
782 | bpf_program__set_type(prog, attr.prog_type); | ||
783 | bpf_program__set_expected_attach_type(prog, expected_attach_type); | ||
784 | |||
785 | bpf_map__for_each(map, obj) | ||
786 | if (!bpf_map__is_offload_neutral(map)) | ||
787 | bpf_map__set_ifindex(map, ifindex); | ||
788 | |||
789 | err = bpf_object__load(obj); | ||
790 | if (err) { | ||
791 | p_err("failed to load object file"); | ||
792 | goto err_close_obj; | ||
793 | } | ||
794 | |||
795 | if (do_pin_fd(bpf_program__fd(prog), pinfile)) | ||
761 | goto err_close_obj; | 796 | goto err_close_obj; |
762 | 797 | ||
763 | if (json_output) | 798 | if (json_output) |