Skip to content

Commit df95939

Browse files
Niklas SöderlundNobody
Niklas Söderlund
authored and
Nobody
committed
bpftool: Restore support for BPF offload-enabled feature probing
Commit 1a56c18 ("bpftool: Stop supporting BPF offload-enabled feature probing") removed the support to probe for BPF offload features. This is still something that is useful for NFP NIC that can support offloading of BPF programs. The reason for the dropped support was that libbpf starting with v1.0 would drop support for passing the ifindex to the BPF prog/map/helper feature probing APIs. In order to keep this useful feature for NFP restore the functionality by moving it directly into bpftool. The code restored is a simplified version of the code that existed in libbpf which supposed passing the ifindex. The simplification is that it only targets the cases where ifindex is given and call into libbpf for the cases where it's not. Before restoring support for probing offload features: # bpftool feature probe dev ens4np0 Scanning system call availability... bpf() syscall is available Scanning eBPF program types... Scanning eBPF map types... Scanning eBPF helper functions... eBPF helpers supported for program type sched_cls: eBPF helpers supported for program type xdp: Scanning miscellaneous eBPF features... Large program size limit is NOT available Bounded loop support is NOT available ISA extension v2 is NOT available ISA extension v3 is NOT available With support for probing offload features restored: # bpftool feature probe dev ens4np0 Scanning system call availability... bpf() syscall is available Scanning eBPF program types... eBPF program_type sched_cls is available eBPF program_type xdp is available Scanning eBPF map types... eBPF map_type hash is available eBPF map_type array is available Scanning eBPF helper functions... eBPF helpers supported for program type sched_cls: - bpf_map_lookup_elem - bpf_get_prandom_u32 - bpf_perf_event_output eBPF helpers supported for program type xdp: - bpf_map_lookup_elem - bpf_get_prandom_u32 - bpf_perf_event_output - bpf_xdp_adjust_head - bpf_xdp_adjust_tail Scanning miscellaneous eBPF features... Large program size limit is NOT available Bounded loop support is NOT available ISA extension v2 is NOT available ISA extension v3 is NOT available Signed-off-by: Niklas Söderlund <[email protected]> Signed-off-by: Simon Horman <[email protected]>
1 parent cb89d90 commit df95939

File tree

1 file changed

+139
-13
lines changed

1 file changed

+139
-13
lines changed

tools/bpf/bpftool/feature.c

Lines changed: 139 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <ctype.h>
55
#include <errno.h>
6+
#include <fcntl.h>
67
#include <string.h>
78
#include <unistd.h>
89
#include <net/if.h>
@@ -45,6 +46,11 @@ static bool run_as_unprivileged;
4546

4647
/* Miscellaneous utility functions */
4748

49+
static bool grep(const char *buffer, const char *pattern)
50+
{
51+
return !!strstr(buffer, pattern);
52+
}
53+
4854
static bool check_procfs(void)
4955
{
5056
struct statfs st_fs;
@@ -135,6 +141,32 @@ static void print_end_section(void)
135141

136142
/* Probing functions */
137143

144+
static int get_vendor_id(int ifindex)
145+
{
146+
char ifname[IF_NAMESIZE], path[64], buf[8];
147+
ssize_t len;
148+
int fd;
149+
150+
if (!if_indextoname(ifindex, ifname))
151+
return -1;
152+
153+
snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname);
154+
155+
fd = open(path, O_RDONLY | O_CLOEXEC);
156+
if (fd < 0)
157+
return -1;
158+
159+
len = read(fd, buf, sizeof(buf));
160+
close(fd);
161+
if (len < 0)
162+
return -1;
163+
if (len >= (ssize_t)sizeof(buf))
164+
return -1;
165+
buf[len] = '\0';
166+
167+
return strtol(buf, NULL, 0);
168+
}
169+
138170
static int read_procfs(const char *path)
139171
{
140172
char *endptr, *line = NULL;
@@ -478,6 +510,40 @@ static bool probe_bpf_syscall(const char *define_prefix)
478510
return res;
479511
}
480512

513+
static bool
514+
probe_prog_load_ifindex(enum bpf_prog_type prog_type,
515+
const struct bpf_insn *insns, size_t insns_cnt,
516+
char *log_buf, size_t log_buf_sz,
517+
__u32 ifindex)
518+
{
519+
LIBBPF_OPTS(bpf_prog_load_opts, opts,
520+
.log_buf = log_buf,
521+
.log_size = log_buf_sz,
522+
.log_level = log_buf ? 1 : 0,
523+
.prog_ifindex = ifindex,
524+
);
525+
int fd;
526+
527+
errno = 0;
528+
fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts);
529+
if (fd >= 0)
530+
close(fd);
531+
532+
return fd >= 0 && errno != EINVAL && errno != EOPNOTSUPP;
533+
}
534+
535+
static bool probe_prog_type_ifindex(enum bpf_prog_type prog_type, __u32 ifindex)
536+
{
537+
/* nfp returns -EINVAL on exit(0) with TC offload */
538+
struct bpf_insn insns[2] = {
539+
BPF_MOV64_IMM(BPF_REG_0, 2),
540+
BPF_EXIT_INSN()
541+
};
542+
543+
return probe_prog_load_ifindex(prog_type, insns, ARRAY_SIZE(insns),
544+
NULL, 0, ifindex);
545+
}
546+
481547
static void
482548
probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
483549
const char *define_prefix, __u32 ifindex)
@@ -488,11 +554,19 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
488554
bool res;
489555

490556
if (ifindex) {
491-
p_info("BPF offload feature probing is not supported");
492-
return;
557+
switch (prog_type) {
558+
case BPF_PROG_TYPE_SCHED_CLS:
559+
case BPF_PROG_TYPE_XDP:
560+
break;
561+
default:
562+
return;
563+
}
564+
565+
res = probe_prog_type_ifindex(prog_type, ifindex);
566+
} else {
567+
res = libbpf_probe_bpf_prog_type(prog_type, NULL);
493568
}
494569

495-
res = libbpf_probe_bpf_prog_type(prog_type, NULL);
496570
#ifdef USE_LIBCAP
497571
/* Probe may succeed even if program load fails, for unprivileged users
498572
* check that we did not fail because of insufficient permissions
@@ -521,6 +595,26 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
521595
define_prefix);
522596
}
523597

598+
static bool probe_map_type_ifindex(enum bpf_map_type map_type, __u32 ifindex)
599+
{
600+
LIBBPF_OPTS(bpf_map_create_opts, opts);
601+
int key_size, value_size, max_entries;
602+
int fd;
603+
604+
opts.map_ifindex = ifindex;
605+
606+
key_size = sizeof(__u32);
607+
value_size = sizeof(__u32);
608+
max_entries = 1;
609+
610+
fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries,
611+
&opts);
612+
if (fd >= 0)
613+
close(fd);
614+
615+
return fd >= 0;
616+
}
617+
524618
static void
525619
probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
526620
__u32 ifindex)
@@ -531,11 +625,18 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
531625
bool res;
532626

533627
if (ifindex) {
534-
p_info("BPF offload feature probing is not supported");
535-
return;
536-
}
628+
switch (map_type) {
629+
case BPF_MAP_TYPE_HASH:
630+
case BPF_MAP_TYPE_ARRAY:
631+
break;
632+
default:
633+
return;
634+
}
537635

538-
res = libbpf_probe_bpf_map_type(map_type, NULL);
636+
res = probe_map_type_ifindex(map_type, ifindex);
637+
} else {
638+
res = libbpf_probe_bpf_map_type(map_type, NULL);
639+
}
539640

540641
/* Probe result depends on the success of map creation, no additional
541642
* check required for unprivileged users
@@ -559,6 +660,33 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
559660
define_prefix);
560661
}
561662

663+
static bool
664+
probe_helper_ifindex(enum bpf_func_id id, enum bpf_prog_type prog_type,
665+
__u32 ifindex)
666+
{
667+
struct bpf_insn insns[2] = {
668+
BPF_EMIT_CALL(id),
669+
BPF_EXIT_INSN()
670+
};
671+
char buf[4096] = {};
672+
bool res;
673+
674+
probe_prog_load_ifindex(prog_type, insns, ARRAY_SIZE(insns), buf,
675+
sizeof(buf), ifindex);
676+
res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");
677+
678+
switch (get_vendor_id(ifindex)) {
679+
case 0x19ee: /* Netronome specific */
680+
res = res && !grep(buf, "not supported by FW") &&
681+
!grep(buf, "unsupported function id");
682+
break;
683+
default:
684+
break;
685+
}
686+
687+
return res;
688+
}
689+
562690
static void
563691
probe_helper_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
564692
const char *define_prefix, unsigned int id,
@@ -567,12 +695,10 @@ probe_helper_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
567695
bool res = false;
568696

569697
if (supported_type) {
570-
if (ifindex) {
571-
p_info("BPF offload feature probing is not supported");
572-
return;
573-
}
574-
575-
res = libbpf_probe_bpf_helper(prog_type, id, NULL);
698+
if (ifindex)
699+
res = probe_helper_ifindex(id, prog_type, ifindex);
700+
else
701+
res = libbpf_probe_bpf_helper(prog_type, id, NULL);
576702
#ifdef USE_LIBCAP
577703
/* Probe may succeed even if program load fails, for
578704
* unprivileged users check that we did not fail because of

0 commit comments

Comments
 (0)