aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 17:31:10 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 17:31:10 -0500
commitb2fe5fa68642860e7de76167c3111623aa0d5de1 (patch)
treeb7f9b89b7039ecefbc35fe3c8e73a6ff972641dd /tools/lib
parenta103950e0dd2058df5e8a8d4a915707bdcf205f0 (diff)
parenta54667f6728c2714a400f3c884727da74b6d1717 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Significantly shrink the core networking routing structures. Result of http://vger.kernel.org/~davem/seoul2017_netdev_keynote.pdf 2) Add netdevsim driver for testing various offloads, from Jakub Kicinski. 3) Support cross-chip FDB operations in DSA, from Vivien Didelot. 4) Add a 2nd listener hash table for TCP, similar to what was done for UDP. From Martin KaFai Lau. 5) Add eBPF based queue selection to tun, from Jason Wang. 6) Lockless qdisc support, from John Fastabend. 7) SCTP stream interleave support, from Xin Long. 8) Smoother TCP receive autotuning, from Eric Dumazet. 9) Lots of erspan tunneling enhancements, from William Tu. 10) Add true function call support to BPF, from Alexei Starovoitov. 11) Add explicit support for GRO HW offloading, from Michael Chan. 12) Support extack generation in more netlink subsystems. From Alexander Aring, Quentin Monnet, and Jakub Kicinski. 13) Add 1000BaseX, flow control, and EEE support to mvneta driver. From Russell King. 14) Add flow table abstraction to netfilter, from Pablo Neira Ayuso. 15) Many improvements and simplifications to the NFP driver bpf JIT, from Jakub Kicinski. 16) Support for ipv6 non-equal cost multipath routing, from Ido Schimmel. 17) Add resource abstration to devlink, from Arkadi Sharshevsky. 18) Packet scheduler classifier shared filter block support, from Jiri Pirko. 19) Avoid locking in act_csum, from Davide Caratti. 20) devinet_ioctl() simplifications from Al viro. 21) More TCP bpf improvements from Lawrence Brakmo. 22) Add support for onlink ipv6 route flag, similar to ipv4, from David Ahern. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1925 commits) tls: Add support for encryption using async offload accelerator ip6mr: fix stale iterator net/sched: kconfig: Remove blank help texts openvswitch: meter: Use 64-bit arithmetic instead of 32-bit tcp_nv: fix potential integer overflow in tcpnv_acked r8169: fix RTL8168EP take too long to complete driver initialization. qmi_wwan: Add support for Quectel EP06 rtnetlink: enable IFLA_IF_NETNSID for RTM_NEWLINK ipmr: Fix ptrdiff_t print formatting ibmvnic: Wait for device response when changing MAC qlcnic: fix deadlock bug tcp: release sk_frag.page in tcp_disconnect ipv4: Get the address of interface correctly. net_sched: gen_estimator: fix lockdep splat net: macb: Handle HRESP error net/mlx5e: IPoIB, Fix copy-paste bug in flow steering refactoring ipv6: addrconf: break critical section in addrconf_verify_rtnl() ipv6: change route cache aging logic i40e/i40evf: Update DESC_NEEDED value to reflect larger value bnxt_en: cleanup DIM work on device shutdown ...
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/Makefile24
-rw-r--r--tools/lib/bpf/bpf.h2
-rw-r--r--tools/lib/bpf/libbpf.c200
3 files changed, 177 insertions, 49 deletions
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 4555304dc18e..83714ca1f22b 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -93,7 +93,6 @@ export prefix libdir src obj
93# Shell quotes 93# Shell quotes
94libdir_SQ = $(subst ','\'',$(libdir)) 94libdir_SQ = $(subst ','\'',$(libdir))
95libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) 95libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
96plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
97 96
98LIB_FILE = libbpf.a libbpf.so 97LIB_FILE = libbpf.a libbpf.so
99 98
@@ -150,7 +149,7 @@ CMD_TARGETS = $(LIB_FILE)
150 149
151TARGETS = $(CMD_TARGETS) 150TARGETS = $(CMD_TARGETS)
152 151
153all: fixdep $(VERSION_FILES) all_cmd 152all: fixdep all_cmd
154 153
155all_cmd: $(CMD_TARGETS) 154all_cmd: $(CMD_TARGETS)
156 155
@@ -169,21 +168,11 @@ $(OUTPUT)libbpf.so: $(BPF_IN)
169$(OUTPUT)libbpf.a: $(BPF_IN) 168$(OUTPUT)libbpf.a: $(BPF_IN)
170 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ 169 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
171 170
172define update_dir
173 (echo $1 > $@.tmp; \
174 if [ -r $@ ] && cmp -s $@ $@.tmp; then \
175 rm -f $@.tmp; \
176 else \
177 echo ' UPDATE $@'; \
178 mv -f $@.tmp $@; \
179 fi);
180endef
181
182define do_install 171define do_install
183 if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ 172 if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
184 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ 173 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
185 fi; \ 174 fi; \
186 $(INSTALL) $1 '$(DESTDIR_SQ)$2' 175 $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2'
187endef 176endef
188 177
189install_lib: all_cmd 178install_lib: all_cmd
@@ -192,7 +181,8 @@ install_lib: all_cmd
192 181
193install_headers: 182install_headers:
194 $(call QUIET_INSTALL, headers) \ 183 $(call QUIET_INSTALL, headers) \
195 $(call do_install,bpf.h,$(prefix)/include/bpf,644) 184 $(call do_install,bpf.h,$(prefix)/include/bpf,644); \
185 $(call do_install,libbpf.h,$(prefix)/include/bpf,644);
196 186
197install: install_lib 187install: install_lib
198 188
@@ -203,7 +193,7 @@ config-clean:
203 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null 193 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
204 194
205clean: 195clean:
206 $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd \ 196 $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so .*.d .*.cmd \
207 $(RM) LIBBPF-CFLAGS 197 $(RM) LIBBPF-CFLAGS
208 $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf 198 $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
209 199
@@ -213,10 +203,10 @@ PHONY += force elfdep bpfdep
213force: 203force:
214 204
215elfdep: 205elfdep:
216 @if [ "$(feature-libelf)" != "1" ]; then echo "No libelf found"; exit -1 ; fi 206 @if [ "$(feature-libelf)" != "1" ]; then echo "No libelf found"; exit 1 ; fi
217 207
218bpfdep: 208bpfdep:
219 @if [ "$(feature-bpf)" != "1" ]; then echo "BPF API too old"; exit -1 ; fi 209 @if [ "$(feature-bpf)" != "1" ]; then echo "BPF API too old"; exit 1 ; fi
220 210
221# Declare the contents of the .PHONY variable as phony. We keep that 211# Declare the contents of the .PHONY variable as phony. We keep that
222# information in a variable so we can use it in if_changed and friends. 212# information in a variable so we can use it in if_changed and friends.
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 6534889e2b2f..9f44c196931e 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -40,7 +40,7 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
40 __u32 map_flags); 40 __u32 map_flags);
41 41
42/* Recommend log buffer size */ 42/* Recommend log buffer size */
43#define BPF_LOG_BUF_SIZE 65536 43#define BPF_LOG_BUF_SIZE (256 * 1024)
44int bpf_load_program_name(enum bpf_prog_type type, const char *name, 44int bpf_load_program_name(enum bpf_prog_type type, const char *name,
45 const struct bpf_insn *insns, 45 const struct bpf_insn *insns,
46 size_t insns_cnt, const char *license, 46 size_t insns_cnt, const char *license,
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 5aa45f89da93..30c776375118 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -174,12 +174,19 @@ struct bpf_program {
174 char *name; 174 char *name;
175 char *section_name; 175 char *section_name;
176 struct bpf_insn *insns; 176 struct bpf_insn *insns;
177 size_t insns_cnt; 177 size_t insns_cnt, main_prog_cnt;
178 enum bpf_prog_type type; 178 enum bpf_prog_type type;
179 179
180 struct { 180 struct reloc_desc {
181 enum {
182 RELO_LD64,
183 RELO_CALL,
184 } type;
181 int insn_idx; 185 int insn_idx;
182 int map_idx; 186 union {
187 int map_idx;
188 int text_off;
189 };
183 } *reloc_desc; 190 } *reloc_desc;
184 int nr_reloc; 191 int nr_reloc;
185 192
@@ -234,6 +241,7 @@ struct bpf_object {
234 } *reloc; 241 } *reloc;
235 int nr_reloc; 242 int nr_reloc;
236 int maps_shndx; 243 int maps_shndx;
244 int text_shndx;
237 } efile; 245 } efile;
238 /* 246 /*
239 * All loaded bpf_object is linked in a list, which is 247 * All loaded bpf_object is linked in a list, which is
@@ -375,9 +383,13 @@ bpf_object__init_prog_names(struct bpf_object *obj)
375 size_t pi, si; 383 size_t pi, si;
376 384
377 for (pi = 0; pi < obj->nr_programs; pi++) { 385 for (pi = 0; pi < obj->nr_programs; pi++) {
378 char *name = NULL; 386 const char *name = NULL;
379 387
380 prog = &obj->programs[pi]; 388 prog = &obj->programs[pi];
389 if (prog->idx == obj->efile.text_shndx) {
390 name = ".text";
391 goto skip_search;
392 }
381 393
382 for (si = 0; si < symbols->d_size / sizeof(GElf_Sym) && !name; 394 for (si = 0; si < symbols->d_size / sizeof(GElf_Sym) && !name;
383 si++) { 395 si++) {
@@ -387,6 +399,8 @@ bpf_object__init_prog_names(struct bpf_object *obj)
387 continue; 399 continue;
388 if (sym.st_shndx != prog->idx) 400 if (sym.st_shndx != prog->idx)
389 continue; 401 continue;
402 if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL)
403 continue;
390 404
391 name = elf_strptr(obj->efile.elf, 405 name = elf_strptr(obj->efile.elf,
392 obj->efile.strtabidx, 406 obj->efile.strtabidx,
@@ -403,7 +417,7 @@ bpf_object__init_prog_names(struct bpf_object *obj)
403 prog->section_name); 417 prog->section_name);
404 return -EINVAL; 418 return -EINVAL;
405 } 419 }
406 420skip_search:
407 prog->name = strdup(name); 421 prog->name = strdup(name);
408 if (!prog->name) { 422 if (!prog->name) {
409 pr_warning("failed to allocate memory for prog sym %s\n", 423 pr_warning("failed to allocate memory for prog sym %s\n",
@@ -793,6 +807,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
793 } else if ((sh.sh_type == SHT_PROGBITS) && 807 } else if ((sh.sh_type == SHT_PROGBITS) &&
794 (sh.sh_flags & SHF_EXECINSTR) && 808 (sh.sh_flags & SHF_EXECINSTR) &&
795 (data->d_size > 0)) { 809 (data->d_size > 0)) {
810 if (strcmp(name, ".text") == 0)
811 obj->efile.text_shndx = idx;
796 err = bpf_object__add_program(obj, data->d_buf, 812 err = bpf_object__add_program(obj, data->d_buf,
797 data->d_size, name, idx); 813 data->d_size, name, idx);
798 if (err) { 814 if (err) {
@@ -854,11 +870,14 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
854} 870}
855 871
856static int 872static int
857bpf_program__collect_reloc(struct bpf_program *prog, 873bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
858 size_t nr_maps, GElf_Shdr *shdr, 874 Elf_Data *data, struct bpf_object *obj)
859 Elf_Data *data, Elf_Data *symbols,
860 int maps_shndx, struct bpf_map *maps)
861{ 875{
876 Elf_Data *symbols = obj->efile.symbols;
877 int text_shndx = obj->efile.text_shndx;
878 int maps_shndx = obj->efile.maps_shndx;
879 struct bpf_map *maps = obj->maps;
880 size_t nr_maps = obj->nr_maps;
862 int i, nrels; 881 int i, nrels;
863 882
864 pr_debug("collecting relocating info for: '%s'\n", 883 pr_debug("collecting relocating info for: '%s'\n",
@@ -891,8 +910,11 @@ bpf_program__collect_reloc(struct bpf_program *prog,
891 GELF_R_SYM(rel.r_info)); 910 GELF_R_SYM(rel.r_info));
892 return -LIBBPF_ERRNO__FORMAT; 911 return -LIBBPF_ERRNO__FORMAT;
893 } 912 }
913 pr_debug("relo for %lld value %lld name %d\n",
914 (long long) (rel.r_info >> 32),
915 (long long) sym.st_value, sym.st_name);
894 916
895 if (sym.st_shndx != maps_shndx) { 917 if (sym.st_shndx != maps_shndx && sym.st_shndx != text_shndx) {
896 pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n", 918 pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n",
897 prog->section_name, sym.st_shndx); 919 prog->section_name, sym.st_shndx);
898 return -LIBBPF_ERRNO__RELOC; 920 return -LIBBPF_ERRNO__RELOC;
@@ -901,6 +923,17 @@ bpf_program__collect_reloc(struct bpf_program *prog,
901 insn_idx = rel.r_offset / sizeof(struct bpf_insn); 923 insn_idx = rel.r_offset / sizeof(struct bpf_insn);
902 pr_debug("relocation: insn_idx=%u\n", insn_idx); 924 pr_debug("relocation: insn_idx=%u\n", insn_idx);
903 925
926 if (insns[insn_idx].code == (BPF_JMP | BPF_CALL)) {
927 if (insns[insn_idx].src_reg != BPF_PSEUDO_CALL) {
928 pr_warning("incorrect bpf_call opcode\n");
929 return -LIBBPF_ERRNO__RELOC;
930 }
931 prog->reloc_desc[i].type = RELO_CALL;
932 prog->reloc_desc[i].insn_idx = insn_idx;
933 prog->reloc_desc[i].text_off = sym.st_value;
934 continue;
935 }
936
904 if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { 937 if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
905 pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n", 938 pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
906 insn_idx, insns[insn_idx].code); 939 insn_idx, insns[insn_idx].code);
@@ -922,6 +955,7 @@ bpf_program__collect_reloc(struct bpf_program *prog,
922 return -LIBBPF_ERRNO__RELOC; 955 return -LIBBPF_ERRNO__RELOC;
923 } 956 }
924 957
958 prog->reloc_desc[i].type = RELO_LD64;
925 prog->reloc_desc[i].insn_idx = insn_idx; 959 prog->reloc_desc[i].insn_idx = insn_idx;
926 prog->reloc_desc[i].map_idx = map_idx; 960 prog->reloc_desc[i].map_idx = map_idx;
927 } 961 }
@@ -961,27 +995,76 @@ bpf_object__create_maps(struct bpf_object *obj)
961} 995}
962 996
963static int 997static int
998bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj,
999 struct reloc_desc *relo)
1000{
1001 struct bpf_insn *insn, *new_insn;
1002 struct bpf_program *text;
1003 size_t new_cnt;
1004
1005 if (relo->type != RELO_CALL)
1006 return -LIBBPF_ERRNO__RELOC;
1007
1008 if (prog->idx == obj->efile.text_shndx) {
1009 pr_warning("relo in .text insn %d into off %d\n",
1010 relo->insn_idx, relo->text_off);
1011 return -LIBBPF_ERRNO__RELOC;
1012 }
1013
1014 if (prog->main_prog_cnt == 0) {
1015 text = bpf_object__find_prog_by_idx(obj, obj->efile.text_shndx);
1016 if (!text) {
1017 pr_warning("no .text section found yet relo into text exist\n");
1018 return -LIBBPF_ERRNO__RELOC;
1019 }
1020 new_cnt = prog->insns_cnt + text->insns_cnt;
1021 new_insn = realloc(prog->insns, new_cnt * sizeof(*insn));
1022 if (!new_insn) {
1023 pr_warning("oom in prog realloc\n");
1024 return -ENOMEM;
1025 }
1026 memcpy(new_insn + prog->insns_cnt, text->insns,
1027 text->insns_cnt * sizeof(*insn));
1028 prog->insns = new_insn;
1029 prog->main_prog_cnt = prog->insns_cnt;
1030 prog->insns_cnt = new_cnt;
1031 }
1032 insn = &prog->insns[relo->insn_idx];
1033 insn->imm += prog->main_prog_cnt - relo->insn_idx;
1034 pr_debug("added %zd insn from %s to prog %s\n",
1035 text->insns_cnt, text->section_name, prog->section_name);
1036 return 0;
1037}
1038
1039static int
964bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) 1040bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj)
965{ 1041{
966 int i; 1042 int i, err;
967 1043
968 if (!prog || !prog->reloc_desc) 1044 if (!prog || !prog->reloc_desc)
969 return 0; 1045 return 0;
970 1046
971 for (i = 0; i < prog->nr_reloc; i++) { 1047 for (i = 0; i < prog->nr_reloc; i++) {
972 int insn_idx, map_idx; 1048 if (prog->reloc_desc[i].type == RELO_LD64) {
973 struct bpf_insn *insns = prog->insns; 1049 struct bpf_insn *insns = prog->insns;
1050 int insn_idx, map_idx;
974 1051
975 insn_idx = prog->reloc_desc[i].insn_idx; 1052 insn_idx = prog->reloc_desc[i].insn_idx;
976 map_idx = prog->reloc_desc[i].map_idx; 1053 map_idx = prog->reloc_desc[i].map_idx;
977 1054
978 if (insn_idx >= (int)prog->insns_cnt) { 1055 if (insn_idx >= (int)prog->insns_cnt) {
979 pr_warning("relocation out of range: '%s'\n", 1056 pr_warning("relocation out of range: '%s'\n",
980 prog->section_name); 1057 prog->section_name);
981 return -LIBBPF_ERRNO__RELOC; 1058 return -LIBBPF_ERRNO__RELOC;
1059 }
1060 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
1061 insns[insn_idx].imm = obj->maps[map_idx].fd;
1062 } else {
1063 err = bpf_program__reloc_text(prog, obj,
1064 &prog->reloc_desc[i]);
1065 if (err)
1066 return err;
982 } 1067 }
983 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
984 insns[insn_idx].imm = obj->maps[map_idx].fd;
985 } 1068 }
986 1069
987 zfree(&prog->reloc_desc); 1070 zfree(&prog->reloc_desc);
@@ -1024,7 +1107,6 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1024 Elf_Data *data = obj->efile.reloc[i].data; 1107 Elf_Data *data = obj->efile.reloc[i].data;
1025 int idx = shdr->sh_info; 1108 int idx = shdr->sh_info;
1026 struct bpf_program *prog; 1109 struct bpf_program *prog;
1027 size_t nr_maps = obj->nr_maps;
1028 1110
1029 if (shdr->sh_type != SHT_REL) { 1111 if (shdr->sh_type != SHT_REL) {
1030 pr_warning("internal error at %d\n", __LINE__); 1112 pr_warning("internal error at %d\n", __LINE__);
@@ -1038,11 +1120,9 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
1038 return -LIBBPF_ERRNO__RELOC; 1120 return -LIBBPF_ERRNO__RELOC;
1039 } 1121 }
1040 1122
1041 err = bpf_program__collect_reloc(prog, nr_maps, 1123 err = bpf_program__collect_reloc(prog,
1042 shdr, data, 1124 shdr, data,
1043 obj->efile.symbols, 1125 obj);
1044 obj->efile.maps_shndx,
1045 obj->maps);
1046 if (err) 1126 if (err)
1047 return err; 1127 return err;
1048 } 1128 }
@@ -1195,6 +1275,8 @@ bpf_object__load_progs(struct bpf_object *obj)
1195 int err; 1275 int err;
1196 1276
1197 for (i = 0; i < obj->nr_programs; i++) { 1277 for (i = 0; i < obj->nr_programs; i++) {
1278 if (obj->programs[i].idx == obj->efile.text_shndx)
1279 continue;
1198 err = bpf_program__load(&obj->programs[i], 1280 err = bpf_program__load(&obj->programs[i],
1199 obj->license, 1281 obj->license,
1200 obj->kern_version); 1282 obj->kern_version);
@@ -1721,6 +1803,45 @@ BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
1721BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); 1803BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
1722BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); 1804BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
1723 1805
1806#define BPF_PROG_SEC(string, type) { string, sizeof(string) - 1, type }
1807static const struct {
1808 const char *sec;
1809 size_t len;
1810 enum bpf_prog_type prog_type;
1811} section_names[] = {
1812 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
1813 BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE),
1814 BPF_PROG_SEC("kretprobe/", BPF_PROG_TYPE_KPROBE),
1815 BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT),
1816 BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
1817 BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
1818 BPF_PROG_SEC("cgroup/skb", BPF_PROG_TYPE_CGROUP_SKB),
1819 BPF_PROG_SEC("cgroup/sock", BPF_PROG_TYPE_CGROUP_SOCK),
1820 BPF_PROG_SEC("cgroup/dev", BPF_PROG_TYPE_CGROUP_DEVICE),
1821 BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS),
1822 BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB),
1823};
1824#undef BPF_PROG_SEC
1825
1826static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog)
1827{
1828 int i;
1829
1830 if (!prog->section_name)
1831 goto err;
1832
1833 for (i = 0; i < ARRAY_SIZE(section_names); i++)
1834 if (strncmp(prog->section_name, section_names[i].sec,
1835 section_names[i].len) == 0)
1836 return section_names[i].prog_type;
1837
1838err:
1839 pr_warning("failed to guess program type based on section name %s\n",
1840 prog->section_name);
1841
1842 return BPF_PROG_TYPE_UNSPEC;
1843}
1844
1724int bpf_map__fd(struct bpf_map *map) 1845int bpf_map__fd(struct bpf_map *map)
1725{ 1846{
1726 return map ? map->fd : -EINVAL; 1847 return map ? map->fd : -EINVAL;
@@ -1818,7 +1939,7 @@ long libbpf_get_error(const void *ptr)
1818int bpf_prog_load(const char *file, enum bpf_prog_type type, 1939int bpf_prog_load(const char *file, enum bpf_prog_type type,
1819 struct bpf_object **pobj, int *prog_fd) 1940 struct bpf_object **pobj, int *prog_fd)
1820{ 1941{
1821 struct bpf_program *prog; 1942 struct bpf_program *prog, *first_prog = NULL;
1822 struct bpf_object *obj; 1943 struct bpf_object *obj;
1823 int err; 1944 int err;
1824 1945
@@ -1826,13 +1947,30 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
1826 if (IS_ERR(obj)) 1947 if (IS_ERR(obj))
1827 return -ENOENT; 1948 return -ENOENT;
1828 1949
1829 prog = bpf_program__next(NULL, obj); 1950 bpf_object__for_each_program(prog, obj) {
1830 if (!prog) { 1951 /*
1952 * If type is not specified, try to guess it based on
1953 * section name.
1954 */
1955 if (type == BPF_PROG_TYPE_UNSPEC) {
1956 type = bpf_program__guess_type(prog);
1957 if (type == BPF_PROG_TYPE_UNSPEC) {
1958 bpf_object__close(obj);
1959 return -EINVAL;
1960 }
1961 }
1962
1963 bpf_program__set_type(prog, type);
1964 if (prog->idx != obj->efile.text_shndx && !first_prog)
1965 first_prog = prog;
1966 }
1967
1968 if (!first_prog) {
1969 pr_warning("object file doesn't contain bpf program\n");
1831 bpf_object__close(obj); 1970 bpf_object__close(obj);
1832 return -ENOENT; 1971 return -ENOENT;
1833 } 1972 }
1834 1973
1835 bpf_program__set_type(prog, type);
1836 err = bpf_object__load(obj); 1974 err = bpf_object__load(obj);
1837 if (err) { 1975 if (err) {
1838 bpf_object__close(obj); 1976 bpf_object__close(obj);
@@ -1840,6 +1978,6 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
1840 } 1978 }
1841 1979
1842 *pobj = obj; 1980 *pobj = obj;
1843 *prog_fd = bpf_program__fd(prog); 1981 *prog_fd = bpf_program__fd(first_prog);
1844 return 0; 1982 return 0;
1845} 1983}