summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-feature.rst4
-rw-r--r--tools/bpf/bpftool/feature.c51
-rw-r--r--tools/lib/bpf/libbpf.h2
-rw-r--r--tools/lib/bpf/libbpf.map1
-rw-r--r--tools/lib/bpf/libbpf_probes.c63
5 files changed, 121 insertions, 0 deletions
diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
index 40ac13c0b782..255e3b3629a0 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
@@ -30,6 +30,10 @@ DESCRIPTION
30 30
31 Keyword **kernel** can be omitted. 31 Keyword **kernel** can be omitted.
32 32
33 Note that when probed, some eBPF helpers (e.g.
34 **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may
35 print warnings to kernel logs.
36
33 **bpftool feature help** 37 **bpftool feature help**
34 Print short help message. 38 Print short help message.
35 39
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index cc731475c74b..55c8d215ca44 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -25,6 +25,13 @@ enum probe_component {
25 COMPONENT_KERNEL, 25 COMPONENT_KERNEL,
26}; 26};
27 27
28#define BPF_HELPER_MAKE_ENTRY(name) [BPF_FUNC_ ## name] = "bpf_" # name
29static const char * const helper_name[] = {
30 __BPF_FUNC_MAPPER(BPF_HELPER_MAKE_ENTRY)
31};
32
33#undef BPF_HELPER_MAKE_ENTRY
34
28/* Miscellaneous utility functions */ 35/* Miscellaneous utility functions */
29 36
30static bool check_procfs(void) 37static bool check_procfs(void)
@@ -458,6 +465,44 @@ static void probe_map_type(enum bpf_map_type map_type)
458 print_bool_feature(feat_name, plain_desc, res); 465 print_bool_feature(feat_name, plain_desc, res);
459} 466}
460 467
468static void
469probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
470{
471 const char *ptype_name = prog_type_name[prog_type];
472 char feat_name[128];
473 unsigned int id;
474 bool res;
475
476 if (json_output) {
477 sprintf(feat_name, "%s_available_helpers", ptype_name);
478 jsonw_name(json_wtr, feat_name);
479 jsonw_start_array(json_wtr);
480 } else {
481 printf("eBPF helpers supported for program type %s:",
482 ptype_name);
483 }
484
485 for (id = 1; id < ARRAY_SIZE(helper_name); id++) {
486 if (!supported_type)
487 res = false;
488 else
489 res = bpf_probe_helper(id, prog_type, 0);
490
491 if (json_output) {
492 if (res)
493 jsonw_string(json_wtr, helper_name[id]);
494 } else {
495 if (res)
496 printf("\n\t- %s", helper_name[id]);
497 }
498 }
499
500 if (json_output)
501 jsonw_end_array(json_wtr);
502 else
503 printf("\n");
504}
505
461static int do_probe(int argc, char **argv) 506static int do_probe(int argc, char **argv)
462{ 507{
463 enum probe_component target = COMPONENT_UNSPEC; 508 enum probe_component target = COMPONENT_UNSPEC;
@@ -533,6 +578,12 @@ static int do_probe(int argc, char **argv)
533 for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++) 578 for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
534 probe_map_type(i); 579 probe_map_type(i);
535 580
581 print_end_then_start_section("helpers",
582 "Scanning eBPF helper functions...");
583
584 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
585 probe_helpers_for_progtype(i, supported_types[i]);
586
536exit_close_json: 587exit_close_json:
537 if (json_output) { 588 if (json_output) {
538 /* End current "section" of probes */ 589 /* End current "section" of probes */
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 72385f6f9415..62ae6cb93da1 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -366,6 +366,8 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
366LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type, 366LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
367 __u32 ifindex); 367 __u32 ifindex);
368LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex); 368LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
369LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
370 enum bpf_prog_type prog_type, __u32 ifindex);
369 371
370#ifdef __cplusplus 372#ifdef __cplusplus
371} /* extern "C" */ 373} /* extern "C" */
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index bb2dfc3b2d7b..266bc95d0142 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -127,6 +127,7 @@ LIBBPF_0.0.1 {
127 127
128LIBBPF_0.0.2 { 128LIBBPF_0.0.2 {
129 global: 129 global:
130 bpf_probe_helper;
130 bpf_probe_map_type; 131 bpf_probe_map_type;
131 bpf_probe_prog_type; 132 bpf_probe_prog_type;
132} LIBBPF_0.0.1; 133} LIBBPF_0.0.1;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index f511bd317b87..8c3a1c04dcb2 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -2,7 +2,11 @@
2/* Copyright (c) 2019 Netronome Systems, Inc. */ 2/* Copyright (c) 2019 Netronome Systems, Inc. */
3 3
4#include <errno.h> 4#include <errno.h>
5#include <fcntl.h>
6#include <string.h>
7#include <stdlib.h>
5#include <unistd.h> 8#include <unistd.h>
9#include <net/if.h>
6#include <sys/utsname.h> 10#include <sys/utsname.h>
7 11
8#include <linux/filter.h> 12#include <linux/filter.h>
@@ -11,6 +15,37 @@
11#include "bpf.h" 15#include "bpf.h"
12#include "libbpf.h" 16#include "libbpf.h"
13 17
18static bool grep(const char *buffer, const char *pattern)
19{
20 return !!strstr(buffer, pattern);
21}
22
23static int get_vendor_id(int ifindex)
24{
25 char ifname[IF_NAMESIZE], path[64], buf[8];
26 ssize_t len;
27 int fd;
28
29 if (!if_indextoname(ifindex, ifname))
30 return -1;
31
32 snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname);
33
34 fd = open(path, O_RDONLY);
35 if (fd < 0)
36 return -1;
37
38 len = read(fd, buf, sizeof(buf));
39 close(fd);
40 if (len < 0)
41 return -1;
42 if (len >= (ssize_t)sizeof(buf))
43 return -1;
44 buf[len] = '\0';
45
46 return strtol(buf, NULL, 0);
47}
48
14static int get_kernel_version(void) 49static int get_kernel_version(void)
15{ 50{
16 int version, subversion, patchlevel; 51 int version, subversion, patchlevel;
@@ -177,3 +212,31 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
177 212
178 return fd >= 0; 213 return fd >= 0;
179} 214}
215
216bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,
217 __u32 ifindex)
218{
219 struct bpf_insn insns[2] = {
220 BPF_EMIT_CALL(id),
221 BPF_EXIT_INSN()
222 };
223 char buf[4096] = {};
224 bool res;
225
226 probe_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf),
227 ifindex);
228 res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");
229
230 if (ifindex) {
231 switch (get_vendor_id(ifindex)) {
232 case 0x19ee: /* Netronome specific */
233 res = res && !grep(buf, "not supported by FW") &&
234 !grep(buf, "unsupported function id");
235 break;
236 default:
237 break;
238 }
239 }
240
241 return res;
242}