On 12/13/2018 01:19 PM, Quentin Monnet wrote: > Similarly to what was done for program types and map types, add a set of > probes to test the availability of the different eBPF helper functions > on the current system. > > Sample output: > > # bpftool feature probe kernel > ... > Scanning eBPF helper functions... > eBPF helper bpf_map_lookup_elem is available > eBPF helper bpf_map_update_elem is available > eBPF helper bpf_map_delete_elem is available > ... > > # bpftool --json --pretty feature probe kernel > { > ... > "helpers": { > "have_bpf_map_lookup_elem_helper": true, > "have_bpf_map_update_elem_helper": true, > "have_bpf_map_delete_elem_helper": true, > ... > } > } > > # bpftool feature probe kernel macros prefix BPFTOOL_ > ... > /*** eBPF helper functions ***/ > #define BPFTOOL_BPF_MAP_LOOKUP_ELEM_HELPER > #define BPFTOOL_BPF_MAP_UPDATE_ELEM_HELPER > #define BPFTOOL_BPF_MAP_DELETE_ELEM_HELPER
Small nit: instead of BPFTOOL_ prefix, would it make sense to generally use Have_ prefix (similar to json output). The former seems somewhat bpftool related though it solely probes the underlying kernel. > ... > > Signed-off-by: Quentin Monnet <quentin.mon...@netronome.com> > Reviewed-by: Jakub Kicinski <jakub.kicin...@netronome.com> > --- > .../bpftool/Documentation/bpftool-feature.rst | 4 + > tools/bpf/bpftool/feature.c | 152 ++++++++++++++++++ > 2 files changed, 156 insertions(+) > > diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst > b/tools/bpf/bpftool/Documentation/bpftool-feature.rst > index 23920a7490e9..083d30510cce 100644 > --- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst > +++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst > @@ -39,6 +39,10 @@ DESCRIPTION > names when including the output of this command as a header > file. > > + Note that when probed, some eBPF helpers (e.g. > + **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may > + print warnings to kernel logs. > + > **bpftool feature help** > Print short help message. > > diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c > index 85928f172413..77221fff6ba9 100644 > --- a/tools/bpf/bpftool/feature.c > +++ b/tools/bpf/bpftool/feature.c > @@ -24,6 +24,113 @@ enum probe_component { > COMPONENT_KERNEL, > }; > > +#define MAX_HELPER_NAME_LEN 32 > +struct helper_param { > + enum bpf_prog_type progtype; > + const char name[MAX_HELPER_NAME_LEN]; > +}; > + > +/* helper_progtype_and_name[index] associates to the BPF helper function of > id > + * "index" a name and a program type to run this helper with. In order to > probe > + * helper availability for programs offloaded to a network device, use > + * offload-compatible types (e.g. XDP) everywhere we can. Caveats: helper > + * probing may fail currently if only TC (but not XDP) is supported for > + * offload. > + */ > +static const struct helper_param helper_progtype_and_name[] = { > + { BPF_PROG_TYPE_XDP, "no_helper_with_id_0" }, > + { BPF_PROG_TYPE_XDP, "bpf_map_lookup_elem" }, > + { BPF_PROG_TYPE_XDP, "bpf_map_update_elem" }, > + { BPF_PROG_TYPE_XDP, "bpf_map_delete_elem" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_probe_read" }, > + { BPF_PROG_TYPE_XDP, "bpf_ktime_get_ns" }, > + { BPF_PROG_TYPE_XDP, "bpf_trace_printk" }, > + { BPF_PROG_TYPE_XDP, "bpf_get_prandom_u32" }, > + { BPF_PROG_TYPE_XDP, "bpf_get_smp_processor_id" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_store_bytes" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_l3_csum_replace" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_l4_csum_replace" }, > + { BPF_PROG_TYPE_XDP, "bpf_tail_call" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_clone_redirect" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_current_pid_tgid" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_current_uid_gid" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_current_comm" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_get_cgroup_classid" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_vlan_push" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_vlan_pop" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_get_tunnel_key" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_set_tunnel_key" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_perf_event_read" }, > + { BPF_PROG_TYPE_XDP, "bpf_redirect" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_get_route_realm" }, > + { BPF_PROG_TYPE_XDP, "bpf_perf_event_output" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_load_bytes" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_stackid" }, > + { BPF_PROG_TYPE_XDP, "bpf_csum_diff" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_get_tunnel_opt" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_set_tunnel_opt" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_change_proto" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_change_type" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_under_cgroup" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_get_hash_recalc" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_current_task" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_probe_write_user" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_current_task_under_cgroup" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_change_tail" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_pull_data" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_csum_update" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_set_hash_invalid" }, > + { BPF_PROG_TYPE_XDP, "bpf_get_numa_node_id" }, > + { BPF_PROG_TYPE_SK_SKB, "bpf_skb_change_head" }, > + { BPF_PROG_TYPE_XDP, "bpf_xdp_adjust_head" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_probe_read_str" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_get_socket_cookie" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_get_socket_uid" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_set_hash" }, > + { BPF_PROG_TYPE_SOCK_OPS, "bpf_setsockopt" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_adjust_room" }, > + { BPF_PROG_TYPE_XDP, "bpf_redirect_map" }, > + { BPF_PROG_TYPE_SK_SKB, "bpf_sk_redirect_map" }, > + { BPF_PROG_TYPE_SOCK_OPS, "bpf_sock_map_update" }, > + { BPF_PROG_TYPE_XDP, "bpf_xdp_adjust_meta" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_perf_event_read_value" }, > + { BPF_PROG_TYPE_PERF_EVENT, "bpf_perf_prog_read_value" }, > + { BPF_PROG_TYPE_SOCK_OPS, "bpf_getsockopt" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_override_return" }, > + { BPF_PROG_TYPE_SOCK_OPS, "bpf_sock_ops_cb_flags_set" }, > + { BPF_PROG_TYPE_SK_MSG, "bpf_msg_redirect_map" }, > + { BPF_PROG_TYPE_SK_MSG, "bpf_msg_apply_bytes" }, > + { BPF_PROG_TYPE_SK_MSG, "bpf_msg_cork_bytes" }, > + { BPF_PROG_TYPE_SK_MSG, "bpf_msg_pull_data" }, > + { BPF_PROG_TYPE_CGROUP_SOCK_ADDR, "bpf_bind" }, > + { BPF_PROG_TYPE_XDP, "bpf_xdp_adjust_tail" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_get_xfrm_state" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_stack" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_load_bytes_relative" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_fib_lookup" }, > + { BPF_PROG_TYPE_SOCK_OPS, "bpf_sock_hash_update" }, > + { BPF_PROG_TYPE_SK_MSG, "bpf_msg_redirect_hash" }, > + { BPF_PROG_TYPE_SK_SKB, "bpf_sk_redirect_hash" }, > + { BPF_PROG_TYPE_LWT_IN, "bpf_lwt_push_encap" }, > + { BPF_PROG_TYPE_LWT_SEG6LOCAL, "bpf_lwt_seg6_store_bytes" }, > + { BPF_PROG_TYPE_LWT_SEG6LOCAL, "bpf_lwt_seg6_adjust_srh" }, > + { BPF_PROG_TYPE_LWT_SEG6LOCAL, "bpf_lwt_seg6_action" }, > + { BPF_PROG_TYPE_LIRC_MODE2, "bpf_rc_repeat" }, > + { BPF_PROG_TYPE_LIRC_MODE2, "bpf_rc_keydown" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_cgroup_id" }, > + { BPF_PROG_TYPE_KPROBE, "bpf_get_current_cgroup_id" }, > + { BPF_PROG_TYPE_CGROUP_SKB, "bpf_get_local_storage" }, > + { BPF_PROG_TYPE_SK_REUSEPORT, "bpf_sk_select_reuseport" }, > + { BPF_PROG_TYPE_SCHED_CLS, "bpf_skb_ancestor_cgroup_id" }, > + { BPF_PROG_TYPE_SK_SKB, "bpf_sk_lookup_tcp" }, > + { BPF_PROG_TYPE_SK_SKB, "bpf_sk_lookup_udp" }, > + { BPF_PROG_TYPE_SK_SKB, "bpf_sk_release" }, > + { BPF_PROG_TYPE_XDP, "bpf_map_push_elem" }, > + { BPF_PROG_TYPE_XDP, "bpf_map_pop_elem" }, > + { BPF_PROG_TYPE_XDP, "bpf_map_peek_elem" }, > + { BPF_PROG_TYPE_SK_MSG, "bpf_msg_push_data" }, Some of these helpers like bpf_perf_event_output are available on multiple types; should they all be tested in case the one probed prog type would not be available on the underlying kernel? Thanks, Daniel