diff --git a/fact-ebpf/src/bpf/maps.h b/fact-ebpf/src/bpf/maps.h index 57cef10e..465b8793 100644 --- a/fact-ebpf/src/bpf/maps.h +++ b/fact-ebpf/src/bpf/maps.h @@ -96,7 +96,7 @@ struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __type(key, __u64); __type(value, struct d_instantiate_ctx_t); - __uint(max_entries, 16384); + __uint(max_entries, 512); } d_instantiate_ctx SEC(".maps"); __always_inline static struct d_instantiate_ctx_t* get_d_instantiate_ctx() { diff --git a/fact/src/bpf/mod.rs b/fact/src/bpf/mod.rs index c8fc8851..1eb58add 100644 --- a/fact/src/bpf/mod.rs +++ b/fact/src/bpf/mod.rs @@ -108,6 +108,7 @@ impl Bpf { ) .map_max_entries(RINGBUFFER_NAME, bpf_config.ringbuf_size() * 1024) .map_max_entries("inode_map", bpf_config.inodes_max()) + .map_max_entries("d_instantiate_ctx", bpf_config.d_instantiate_ctx_size()) .load(fact_ebpf::EBPF_OBJ) .context("failed to load eBPF object") } diff --git a/fact/src/config/mod.rs b/fact/src/config/mod.rs index 229bd0f9..567da9d1 100644 --- a/fact/src/config/mod.rs +++ b/fact/src/config/mod.rs @@ -569,6 +569,7 @@ impl TryFrom<&yaml::Hash> for OTelConfig { pub struct BpfConfig { ringbuf_size: Option, inodes_max: Option, + d_instantiate_ctx_size: Option, pub programs: HashMap, } @@ -582,6 +583,10 @@ impl BpfConfig { self.inodes_max = Some(inodes_max); } + if let Some(d_inst_size) = from.d_instantiate_ctx_size { + self.d_instantiate_ctx_size = Some(d_inst_size); + } + for (k, v) in &from.programs { self.programs.entry(k.clone()).or_default().update(v); } @@ -595,6 +600,10 @@ impl BpfConfig { self.inodes_max.unwrap_or(65536) } + pub fn d_instantiate_ctx_size(&self) -> u32 { + self.d_instantiate_ctx_size.unwrap_or(512) + } + pub fn program_is_enabled(&self, name: &str) -> bool { self.programs.get(name).map(|c| c.enabled()).unwrap_or(true) } @@ -630,6 +639,15 @@ impl TryFrom<&yaml::Hash> for BpfConfig { }; bpf.inodes_max = Some(inode_max as u32); } + "d_instantiate_ctx_size" => match v.as_i64() { + Some(size) if size > 0 && size < u32::MAX as i64 => { + bpf.d_instantiate_ctx_size = Some(size as u32); + } + Some(size) => { + bail!("bpf.d_instantiate_ctx_size field has invalid value: {size}") + } + None => bail!("bpf.d_instantiate_ctx_size field has incorrect type: {v:?}"), + }, "programs" => { let Some(programs) = v.as_hash() else { bail!("bpf.programs field has incorrect type: {v:?}"); @@ -845,6 +863,19 @@ pub struct FactCli { #[arg(long, short, env = "FACT_INODES_MAX")] inodes_max: Option, + /// Sets the maximum number of entries that can be added to the + /// d_instantiate_ctx map. + /// + /// This is an advanced configuration parameter, it can be used to + /// increase the amount of in-flight events that use the + /// d_instantiate LSM hook for resolving inode numbers. + #[arg( + long = "d-inst-size", + env = "FACT_D_INSTANTIATE_CTX_SIZE", + value_parser = clap::value_parser!(u32).range(1..u32::MAX as i64) + )] + d_instantiate_ctx_size: Option, + /// Whether configuration should be hotreloaded #[arg(long, overrides_with = "no_hotreload", env = "FACT_HOTRELOAD")] hotreload: bool, @@ -904,6 +935,7 @@ impl FactCli { bpf: BpfConfig { ringbuf_size: self.ringbuf_size, inodes_max: self.inodes_max, + d_instantiate_ctx_size: self.d_instantiate_ctx_size, programs: HashMap::new(), }, skip_pre_flight: resolve_bool_arg(self.skip_pre_flight, self.no_skip_pre_flight), diff --git a/fact/src/config/tests.rs b/fact/src/config/tests.rs index 14adda96..596ca711 100644 --- a/fact/src/config/tests.rs +++ b/fact/src/config/tests.rs @@ -351,6 +351,19 @@ fn parsing() { ..Default::default() }, ), + ( + r#" + bpf: + d_instantiate_ctx_size: 64 + "#, + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(64), + ..Default::default() + }, + ..Default::default() + }, + ), ( r#" bpf: @@ -482,6 +495,7 @@ fn parsing() { bpf: ringbuf_size: 8192 inodes_max: 64 + d_instantiate_ctx_size: 64 programs: file_open: enabled: false @@ -521,6 +535,7 @@ fn parsing() { bpf: BpfConfig { ringbuf_size: Some(8192), inodes_max: Some(64), + d_instantiate_ctx_size: Some(64), programs: HashMap::from([ ( "file_open".into(), @@ -860,6 +875,27 @@ paths: "#, "inodes_max field has incorrect type: Boolean(true)", ), + ( + r#" + bpf: + d_instantiate_ctx_size: 0 + "#, + "bpf.d_instantiate_ctx_size field has invalid value: 0", + ), + ( + r#" + bpf: + d_instantiate_ctx_size: 5000000000 + "#, + "bpf.d_instantiate_ctx_size field has invalid value: 5000000000", + ), + ( + r#" + bpf: + d_instantiate_ctx_size: true + "#, + "bpf.d_instantiate_ctx_size field has incorrect type: Boolean(true)", + ), ( r#" bpf: @@ -1643,6 +1679,60 @@ fn update() { ..Default::default() }, ), + ( + r#" + bpf: + d_instantiate_ctx_size: 16384 + "#, + FactConfig::default(), + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(16384), + ..Default::default() + }, + ..Default::default() + }, + ), + ( + r#" + bpf: + d_instantiate_ctx_size: 16384 + "#, + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(8192), + ..Default::default() + }, + ..Default::default() + }, + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(16384), + ..Default::default() + }, + ..Default::default() + }, + ), + ( + r#" + bpf: + d_instantiate_ctx_size: 16384 + "#, + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(16384), + ..Default::default() + }, + ..Default::default() + }, + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(16384), + ..Default::default() + }, + ..Default::default() + }, + ), ( r#" bpf: @@ -1837,6 +1927,7 @@ fn update() { bpf: ringbuf_size: 16384 inodes_max: 8192 + d_instantiate_ctx_size: 8192 programs: file_open: enabled: false @@ -1871,6 +1962,7 @@ fn update() { bpf: BpfConfig { ringbuf_size: Some(64), inodes_max: Some(4096), + d_instantiate_ctx_size: Some(4096), programs: HashMap::from([( "path_unlink".into(), BpfProgConfig { @@ -1910,6 +2002,7 @@ fn update() { bpf: BpfConfig { ringbuf_size: Some(16384), inodes_max: Some(8192), + d_instantiate_ctx_size: Some(8192), programs: HashMap::from([ ( "path_unlink".into(), @@ -1960,6 +2053,7 @@ fn defaults() { assert!(!config.json()); assert_eq!(config.bpf.ringbuf_size(), 8192); assert_eq!(config.bpf.inodes_max(), 65536); + assert_eq!(config.bpf.d_instantiate_ctx_size(), 512); assert!(config.hotreload()); assert_eq!(config.grpc.backoff.initial(), Duration::from_secs(1)); assert_eq!(config.grpc.backoff.max(), Duration::from_secs(60)); @@ -2110,6 +2204,19 @@ fn env_vars() { ..Default::default() }, ), + ( + EnvVar { + name: "FACT_D_INSTANTIATE_CTX_SIZE", + value: "1024", + }, + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(1024), + ..Default::default() + }, + ..Default::default() + }, + ), ( EnvVar { name: "FACT_PATHS", @@ -2388,6 +2495,20 @@ fn env_vars_override_yaml() { ..Default::default() }, ), + ( + EnvVar { + name: "FACT_D_INSTANTIATE_CTX_SIZE", + value: "2048", + }, + "bpf:\n d_instantiate_ctx_size: 1024", + FactConfig { + bpf: BpfConfig { + d_instantiate_ctx_size: Some(2048), + ..Default::default() + }, + ..Default::default() + }, + ), ( EnvVar { name: "FACT_URL", @@ -2611,6 +2732,13 @@ fn env_vars_invalid_values() { }, "error: invalid value 'not_a_number' for '--ringbuf-size ': invalid digit found in string", ), + ( + EnvVar { + name: "FACT_D_INSTANTIATE_CTX_SIZE", + value: "not_a_number", + }, + "error: invalid value 'not_a_number' for '--d-inst-size ': invalid digit found in string", + ), ( EnvVar { name: "FACT_ENDPOINT_ADDRESS",