bpf_feature/
lib.rs

1//! A library focused on detecting supported eBPF features on the current host
2//!
3//! # Background
4//!
5//! The approaches here taken are similar to the way [bpftool](https://github.com/libbpf/bpftool)
6//! probes functionality on the host. We recommend users use the `bpftool feature`
7//! subcommand for interactive display of eBPF feature support but we
8//! developed this library for incorporating these detection techniques within Rust apps.
9//!
10//! ## Compatibility with bpftool
11//!
12//! This library is aimed to exactly match the detection features of `bpftool feature`. If
13//! this is not the case, we consider [it a bug](https://github.com/bpfdeploy-io/bpf-rs/issues).
14//!
15//! As an example of this, we recreated the default output of `bpftool feature` here:
16//! [`examples/feature-probe.rs`](https://github.com/bpfdeploy-io/bpf-rs/tree/main/bpf-feature/examples)
17//!
18//! # JSON
19//!
20//! We also support JSON output. This is powered by [Serde](https://github.com/serde-rs/serde),
21//! a popular serialization crate. Note that the JSON output differs in structure
22//! from the output of `bpftool feature probe --json` but semantically should be
23//! identical.
24//!
25//! To see an example of JSON out, see the example
26//! [`examples/json-dump.rs`](https://github.com/bpfdeploy-io/bpf-rs/tree/main/bpf-feature/examples).
27//!
28//! Serialization support is **NOT** enabled by default. Please pass in the `serde`
29//! feature to enable.
30//!
31//! ## Other serialization formats
32//!
33//! Because of the abstraction Serde provides, we are not restricted to JSON and it
34//! is possible to support other serialization formats. This should work out of the
35//! box but if issues occur, please let us know.
36//!
37//! # Design
38//!
39//! For detecting all functionality, we've exported a singular function [`detect`]
40//! that can be configured with options through [`DetectOpts`] (to pass in the
41//! defaults you can use [`DetectOpts::default()`]):
42//!
43//! ```
44//! use bpf_feature::{detect, DetectOpts};
45//!
46//! let features = detect(DetectOpts::default());
47//! // ...
48//! ```
49//!
50//! ## Modularity
51//!
52//! `detect` is not the only entrypoint publicly exported. We have organized
53//! related features into modules that export specific detections through a
54//! `features()` function:
55//!
56//! - [`bpf::features`]
57//! - [`kernel_config::features`]
58//! - [`runtime::features`]
59//! - [`misc::features`]
60//!
61//! This means that in your application can choose which features to run:
62//!
63//! ```
64//! use bpf_feature::kernel_config::{self, KERNEL_CONFIG_KEYS, KernelConfig};
65//!
66//! match kernel_config::features() {
67//!     Ok(KernelConfig { values }) => KERNEL_CONFIG_KEYS.iter().for_each(|&key| {
68//!         match values.get(key) {
69//!             Some(value) => println!("{} is set to {}", key, value),
70//!             None => println!("{} is not set", key),
71//!         };
72//!     }),
73//!     Err(err) => println!("skipping kernel config, {}", err),
74//! }
75//! ```
76#[cfg(feature = "serde")]
77use serde::Serialize;
78#[cfg(feature = "serde")]
79mod serde_ext;
80
81pub mod bpf;
82pub mod kernel_config;
83pub mod misc;
84pub mod runtime;
85
86/// Results of the entire feature detection set from [`detect`]
87#[derive(Debug)]
88#[cfg_attr(feature = "serde", derive(Serialize))]
89pub struct Features {
90    #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
91    pub runtime: Result<runtime::Runtime, runtime::RuntimeError>,
92    #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
93    pub kernel_config: Result<kernel_config::KernelConfig, kernel_config::KernelConfigError>,
94    #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
95    pub bpf: Result<bpf::Bpf, bpf::BpfError>,
96    pub misc: misc::Misc,
97}
98
99/// Options that can be passed into [`detect`]
100#[derive(Default)]
101pub struct DetectOpts {
102    pub full_helpers: bool,
103}
104
105/// Primary function to run entire feature detection set
106pub fn detect(opts: DetectOpts) -> Features {
107    Features {
108        runtime: runtime::features(),
109        kernel_config: kernel_config::features(),
110        bpf: bpf::features(bpf::BpfFeaturesOpts {
111            full_helpers: opts.full_helpers,
112        }),
113        misc: misc::features(),
114    }
115}