1+ //! Features derived from compile-time kernel configuration
2+ //!
3+ //! The Linux kernel accepts an assortment of flags that can be enabled or disabled
4+ //! at compilation. These configuration flags are used to determine which eBPF
5+ //! features are eventually available on the running kernel.
6+ //!
7+ //! Depending on your distribution, your kernel config can be available in a number
8+ //! of locations such as:
9+ //!
10+ //! - `/proc/config.gz`
11+ //! - `/boot/config`
12+ //! - `/boot/config-$(uname -r)`
13+ //!
14+ //! This module will search for and read your kernel configuration for relevant
15+ //! eBPF flags. If you believe a flag is missing or incorrectly added to
16+ //! the set in [`KERNEL_CONFIG_KEYS`], please file [an issue](https://github.com/bpfdeploy-io/bpf-rs).
117use flate2:: bufread:: GzDecoder ;
218use nix:: sys:: utsname;
319use std:: {
@@ -13,40 +29,7 @@ use bpf_rs_macros::SerializeFromDisplay;
1329#[ cfg( feature = "serde" ) ]
1430use serde:: Serialize ;
1531
16- #[ non_exhaustive]
17- #[ derive( ThisError , Debug ) ]
18- #[ cfg_attr( feature = "serde" , derive( Serialize ) ) ]
19- pub enum KernelConfigError {
20- #[ error( "can't open file" ) ]
21- NotFound ,
22- #[ error( "file data format unknown" ) ]
23- ContentsUnknown ,
24- #[ error( "can't read from file" ) ]
25- ReadFail ,
26- }
27-
28- #[ derive( Debug ) ]
29- #[ cfg_attr( feature = "serde" , derive( SerializeFromDisplay ) ) ]
30- pub enum ConfigValue {
31- Y ,
32- N ,
33- M ,
34- Other ( String ) ,
35- }
36-
37- impl Display for ConfigValue {
38- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
39- match self {
40- ConfigValue :: Y => write ! ( f, "y" ) ,
41- ConfigValue :: N => write ! ( f, "n" ) ,
42- ConfigValue :: M => write ! ( f, "m" ) ,
43- ConfigValue :: Other ( value) => write ! ( f, "{}" , value) ,
44- }
45- }
46- }
47-
48- pub type KernelConfigValues = HashMap < & ' static str , ConfigValue > ;
49-
32+ /// Entire set of kernel config flags to determine support of
5033pub const KERNEL_CONFIG_KEYS : [ & ' static str ; 35 ] = [
5134 "CONFIG_BPF" ,
5235 "CONFIG_BPF_SYSCALL" ,
@@ -85,9 +68,63 @@ pub const KERNEL_CONFIG_KEYS: [&'static str; 35] = [
8568 "CONFIG_HZ" ,
8669] ;
8770
71+
72+ /// Possible errors when reading a kernel's config file
73+ #[ non_exhaustive]
74+ #[ derive( ThisError , Debug ) ]
75+ #[ cfg_attr( feature = "serde" , derive( Serialize ) ) ]
76+ pub enum KernelConfigError {
77+ /// Kernel config file was not found
78+ #[ error( "can't open file" ) ]
79+ NotFound ,
80+ /// Could not parse contents of config file
81+ #[ error( "file data format unknown" ) ]
82+ ContentsUnknown ,
83+ /// IO error reading the config file
84+ #[ error( "can't read from file" ) ]
85+ ReadFail ,
86+ }
87+
88+ /// Variant of possible config values (e.g. `y`, `n`, `m` etc.)
89+ #[ derive( Debug ) ]
90+ #[ cfg_attr( feature = "serde" , derive( SerializeFromDisplay ) ) ]
91+ pub enum ConfigValue {
92+ /// This kernel feature is available.
93+ Y ,
94+ /// This kernel feature is **NOT** available.
95+ ///
96+ /// This might mean that you need to upgrade your kernel, flag an issue
97+ /// with your Linux distro or compile your own kernel to get the necessary
98+ /// functionality.
99+ N ,
100+ /// This kernel feature is available *as a module only*.
101+ ///
102+ /// This means that the feature is available on your system as a kernel
103+ /// module but might require privileged enabling of it to gain functionality.
104+ M ,
105+ /// This kernel flag is an unstructured value determined at compile time
106+ Other ( String ) ,
107+ }
108+
109+ impl Display for ConfigValue {
110+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
111+ match self {
112+ ConfigValue :: Y => write ! ( f, "y" ) ,
113+ ConfigValue :: N => write ! ( f, "n" ) ,
114+ ConfigValue :: M => write ! ( f, "m" ) ,
115+ ConfigValue :: Other ( value) => write ! ( f, "{}" , value) ,
116+ }
117+ }
118+ }
119+
120+ type KernelConfigValues = HashMap < & ' static str , ConfigValue > ;
121+
122+ /// Primarily just a wrapper for kernel config values
88123#[ derive( Debug ) ]
89124#[ cfg_attr( feature = "serde" , derive( Serialize ) ) ]
90125pub struct KernelConfig {
126+ /// A HashMap of kernel config values with the key being the
127+ /// flag and the value derived from reading the kernel config file
91128 #[ cfg_attr( feature = "serde" , serde( flatten) ) ]
92129 pub values : KernelConfigValues ,
93130}
@@ -157,6 +194,8 @@ impl KernelConfig {
157194 }
158195}
159196
197+ /// This module's main function to read and determine support of kernel config
198+ /// flags
160199pub fn features ( ) -> Result < KernelConfig , KernelConfigError > {
161200 return Ok ( KernelConfig {
162201 values : KernelConfig :: probe_kernel_config ( ) ?,
0 commit comments