summaryrefslogtreecommitdiffstats
path: root/tools/bpf/bpftool
diff options
context:
space:
mode:
authorQuentin Monnet <quentin.monnet@netronome.com>2019-01-17 10:27:57 -0500
committerAlexei Starovoitov <ast@kernel.org>2019-01-23 01:15:40 -0500
commitf9499fedf28547b496066b65de9180eaf3a7dc50 (patch)
tree7b7bc8531772b316434b8f78cad55371a8ef6960 /tools/bpf/bpftool
parentd267cff46753b0e8b2f169ff4a3f1bb40c2387a8 (diff)
tools: bpftool: add probes for a network device
bpftool gained support for probing the current system in order to see what program and map types, and what helpers are available on that system. This patch adds the possibility to pass an interface index to libbpf (and hence to the kernel) when trying to load the programs or to create the maps, in order to see what items a given network device can support. A new keyword "dev <ifname>" can be used as an alternative to "kernel" to indicate that the given device should be tested. If no target ("dev" or "kernel") is specified bpftool defaults to probing the kernel. Sample output: # bpftool -p feature probe dev lo { "syscall_config": { "have_bpf_syscall": true }, "program_types": { "have_sched_cls_prog_type": false, "have_xdp_prog_type": false }, ... } As the target is a network device, /proc/ parameters and kernel configuration are NOT dumped. Availability of the bpf() syscall is still probed, so we can return early if that syscall is not usable (since there is no point in attempting the remaining probes in this case). Among the program types, only the ones that can be offloaded are probed. All map types are probed, as there is no specific rule telling which one could or could not be supported by a device in the future. All helpers are probed (but only for offload-able program types). Caveat: as bpftool does not attempt to attach programs to the device at the moment, probes do not entirely reflect what the device accepts: typically, for Netronome's nfp, results will announce that TC cls offload is available even if support has been deactivated (with e.g. ethtool -K eth1 hw-tc-offload off). v2: - All helpers are probed, whereas previous version would only probe the ones compatible with an offload-able program type. This is because we do not keep a default compatible program type for each helper anymore. Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Stanislav Fomichev <sdf@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/bpf/bpftool')
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-feature.rst18
-rw-r--r--tools/bpf/bpftool/feature.c69
2 files changed, 73 insertions, 14 deletions
diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
index 53092995f46b..8d489a26e3c9 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
@@ -19,14 +19,18 @@ SYNOPSIS
19MAP COMMANDS 19MAP COMMANDS
20============= 20=============
21 21
22| **bpftool** **feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]] 22| **bpftool** **feature probe** [*COMPONENT*] [**macros** [**prefix** *PREFIX*]]
23| **bpftool** **feature help** 23| **bpftool** **feature help**
24|
25| *COMPONENT* := { **kernel** | **dev** *NAME* }
24 26
25DESCRIPTION 27DESCRIPTION
26=========== 28===========
27 **bpftool feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]] 29 **bpftool feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]]
28 Probe the running kernel and dump a number of eBPF-related 30 Probe the running kernel and dump a number of eBPF-related
29 parameters, such as availability of the **bpf()** system call. 31 parameters, such as availability of the **bpf()** system call,
32 JIT status, eBPF program types availability, eBPF helper
33 functions availability, and more.
30 34
31 If the **macros** keyword (but not the **-j** option) is 35 If the **macros** keyword (but not the **-j** option) is
32 passed, a subset of the output is dumped as a list of 36 passed, a subset of the output is dumped as a list of
@@ -37,12 +41,20 @@ DESCRIPTION
37 avoid conflicts on macro names when including the output of 41 avoid conflicts on macro names when including the output of
38 this command as a header file. 42 this command as a header file.
39 43
40 Keyword **kernel** can be omitted. 44 Keyword **kernel** can be omitted. If no probe target is
45 specified, probing the kernel is the default behaviour.
41 46
42 Note that when probed, some eBPF helpers (e.g. 47 Note that when probed, some eBPF helpers (e.g.
43 **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may 48 **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may
44 print warnings to kernel logs. 49 print warnings to kernel logs.
45 50
51 **bpftool feature probe dev** *NAME* [**macros** [**prefix** *PREFIX*]]
52 Probe network device for supported eBPF features and dump
53 results to the console.
54
55 The two keywords **macros** and **prefix** have the same
56 role as when probing the kernel.
57
46 **bpftool feature help** 58 **bpftool feature help**
47 Print short help message. 59 Print short help message.
48 60
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index a62e637953b7..993c6f1e5473 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -5,6 +5,7 @@
5#include <errno.h> 5#include <errno.h>
6#include <string.h> 6#include <string.h>
7#include <unistd.h> 7#include <unistd.h>
8#include <net/if.h>
8#include <sys/utsname.h> 9#include <sys/utsname.h>
9#include <sys/vfs.h> 10#include <sys/vfs.h>
10 11
@@ -23,6 +24,7 @@
23enum probe_component { 24enum probe_component {
24 COMPONENT_UNSPEC, 25 COMPONENT_UNSPEC,
25 COMPONENT_KERNEL, 26 COMPONENT_KERNEL,
27 COMPONENT_DEVICE,
26}; 28};
27 29
28#define BPF_HELPER_MAKE_ENTRY(name) [BPF_FUNC_ ## name] = "bpf_" # name 30#define BPF_HELPER_MAKE_ENTRY(name) [BPF_FUNC_ ## name] = "bpf_" # name
@@ -456,14 +458,24 @@ static bool probe_bpf_syscall(const char *define_prefix)
456 458
457static void 459static void
458probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types, 460probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
459 const char *define_prefix) 461 const char *define_prefix, __u32 ifindex)
460{ 462{
461 char feat_name[128], plain_desc[128], define_name[128]; 463 char feat_name[128], plain_desc[128], define_name[128];
462 const char *plain_comment = "eBPF program_type "; 464 const char *plain_comment = "eBPF program_type ";
463 size_t maxlen; 465 size_t maxlen;
464 bool res; 466 bool res;
465 467
466 res = bpf_probe_prog_type(prog_type, 0); 468 if (ifindex)
469 /* Only test offload-able program types */
470 switch (prog_type) {
471 case BPF_PROG_TYPE_SCHED_CLS:
472 case BPF_PROG_TYPE_XDP:
473 break;
474 default:
475 return;
476 }
477
478 res = bpf_probe_prog_type(prog_type, ifindex);
467 479
468 supported_types[prog_type] |= res; 480 supported_types[prog_type] |= res;
469 481
@@ -482,14 +494,15 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
482} 494}
483 495
484static void 496static void
485probe_map_type(enum bpf_map_type map_type, const char *define_prefix) 497probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
498 __u32 ifindex)
486{ 499{
487 char feat_name[128], plain_desc[128], define_name[128]; 500 char feat_name[128], plain_desc[128], define_name[128];
488 const char *plain_comment = "eBPF map_type "; 501 const char *plain_comment = "eBPF map_type ";
489 size_t maxlen; 502 size_t maxlen;
490 bool res; 503 bool res;
491 504
492 res = bpf_probe_map_type(map_type, 0); 505 res = bpf_probe_map_type(map_type, ifindex);
493 506
494 maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1; 507 maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
495 if (strlen(map_type_name[map_type]) > maxlen) { 508 if (strlen(map_type_name[map_type]) > maxlen) {
@@ -507,13 +520,23 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix)
507 520
508static void 521static void
509probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type, 522probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
510 const char *define_prefix) 523 const char *define_prefix, __u32 ifindex)
511{ 524{
512 const char *ptype_name = prog_type_name[prog_type]; 525 const char *ptype_name = prog_type_name[prog_type];
513 char feat_name[128]; 526 char feat_name[128];
514 unsigned int id; 527 unsigned int id;
515 bool res; 528 bool res;
516 529
530 if (ifindex)
531 /* Only test helpers for offload-able program types */
532 switch (prog_type) {
533 case BPF_PROG_TYPE_SCHED_CLS:
534 case BPF_PROG_TYPE_XDP:
535 break;
536 default:
537 return;
538 }
539
517 if (json_output) { 540 if (json_output) {
518 sprintf(feat_name, "%s_available_helpers", ptype_name); 541 sprintf(feat_name, "%s_available_helpers", ptype_name);
519 jsonw_name(json_wtr, feat_name); 542 jsonw_name(json_wtr, feat_name);
@@ -527,7 +550,7 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
527 if (!supported_type) 550 if (!supported_type)
528 res = false; 551 res = false;
529 else 552 else
530 res = bpf_probe_helper(id, prog_type, 0); 553 res = bpf_probe_helper(id, prog_type, ifindex);
531 554
532 if (json_output) { 555 if (json_output) {
533 if (res) 556 if (res)
@@ -553,7 +576,9 @@ static int do_probe(int argc, char **argv)
553 enum probe_component target = COMPONENT_UNSPEC; 576 enum probe_component target = COMPONENT_UNSPEC;
554 const char *define_prefix = NULL; 577 const char *define_prefix = NULL;
555 bool supported_types[128] = {}; 578 bool supported_types[128] = {};
579 __u32 ifindex = 0;
556 unsigned int i; 580 unsigned int i;
581 char *ifname;
557 582
558 /* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN). 583 /* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN).
559 * Let's approximate, and restrict usage to root user only. 584 * Let's approximate, and restrict usage to root user only.
@@ -573,6 +598,24 @@ static int do_probe(int argc, char **argv)
573 } 598 }
574 target = COMPONENT_KERNEL; 599 target = COMPONENT_KERNEL;
575 NEXT_ARG(); 600 NEXT_ARG();
601 } else if (is_prefix(*argv, "dev")) {
602 NEXT_ARG();
603
604 if (target != COMPONENT_UNSPEC || ifindex) {
605 p_err("component to probe already specified");
606 return -1;
607 }
608 if (!REQ_ARGS(1))
609 return -1;
610
611 target = COMPONENT_DEVICE;
612 ifname = GET_ARG();
613 ifindex = if_nametoindex(ifname);
614 if (!ifindex) {
615 p_err("unrecognized netdevice '%s': %s", ifname,
616 strerror(errno));
617 return -1;
618 }
576 } else if (is_prefix(*argv, "macros") && !define_prefix) { 619 } else if (is_prefix(*argv, "macros") && !define_prefix) {
577 define_prefix = ""; 620 define_prefix = "";
578 NEXT_ARG(); 621 NEXT_ARG();
@@ -591,7 +634,7 @@ static int do_probe(int argc, char **argv)
591 return -1; 634 return -1;
592 define_prefix = GET_ARG(); 635 define_prefix = GET_ARG();
593 } else { 636 } else {
594 p_err("expected no more arguments, 'kernel', 'macros' or 'prefix', got: '%s'?", 637 p_err("expected no more arguments, 'kernel', 'dev', 'macros' or 'prefix', got: '%s'?",
595 *argv); 638 *argv);
596 return -1; 639 return -1;
597 } 640 }
@@ -627,6 +670,8 @@ static int do_probe(int argc, char **argv)
627 else 670 else
628 printf("\n"); 671 printf("\n");
629 break; 672 break;
673 default:
674 break;
630 } 675 }
631 676
632 print_start_section("syscall_config", 677 print_start_section("syscall_config",
@@ -644,7 +689,7 @@ static int do_probe(int argc, char **argv)
644 define_prefix); 689 define_prefix);
645 690
646 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++) 691 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
647 probe_prog_type(i, supported_types, define_prefix); 692 probe_prog_type(i, supported_types, define_prefix, ifindex);
648 693
649 print_end_then_start_section("map_types", 694 print_end_then_start_section("map_types",
650 "Scanning eBPF map types...", 695 "Scanning eBPF map types...",
@@ -652,7 +697,7 @@ static int do_probe(int argc, char **argv)
652 define_prefix); 697 define_prefix);
653 698
654 for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++) 699 for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
655 probe_map_type(i, define_prefix); 700 probe_map_type(i, define_prefix, ifindex);
656 701
657 print_end_then_start_section("helpers", 702 print_end_then_start_section("helpers",
658 "Scanning eBPF helper functions...", 703 "Scanning eBPF helper functions...",
@@ -676,7 +721,7 @@ static int do_probe(int argc, char **argv)
676 define_prefix); 721 define_prefix);
677 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++) 722 for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
678 probe_helpers_for_progtype(i, supported_types[i], 723 probe_helpers_for_progtype(i, supported_types[i],
679 define_prefix); 724 define_prefix, ifindex);
680 725
681exit_close_json: 726exit_close_json:
682 if (json_output) { 727 if (json_output) {
@@ -697,8 +742,10 @@ static int do_help(int argc, char **argv)
697 } 742 }
698 743
699 fprintf(stderr, 744 fprintf(stderr,
700 "Usage: %s %s probe [kernel] [macros [prefix PREFIX]]\n" 745 "Usage: %s %s probe [COMPONENT] [macros [prefix PREFIX]]\n"
701 " %s %s help\n" 746 " %s %s help\n"
747 "\n"
748 " COMPONENT := { kernel | dev NAME }\n"
702 "", 749 "",
703 bin_name, argv[-2], bin_name, argv[-2]); 750 bin_name, argv[-2], bin_name, argv[-2]);
704 751