Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4ec4d61

Browse files
committedNov 26, 2024··
testing, some more functionality, etc. host heuristics tests disabled for now
1 parent 296084f commit 4ec4d61

File tree

7 files changed

+291
-119
lines changed

7 files changed

+291
-119
lines changed
 

‎collector/lib/HostHeuristics.cpp

+20-17
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#include "HostHeuristics.h"
22

33
#include "Logging.h"
4+
#include "host/src/lib.rs.h"
45

56
namespace collector {
67

78
namespace {
89

910
static const char* g_switch_collection_hint = "HINT: You may alternatively want to disable collection with collector.collectionMethod=NO_COLLECTION";
1011

12+
using HostInfo = ::rust::Box<collector::rust::HostInfo>;
13+
1114
class Heuristic {
1215
public:
1316
// Process the given HostInfo and CollectorConfig to adjust HostConfig as necessary.
@@ -20,38 +23,38 @@ class Heuristic {
2023
class CollectionHeuristic : public Heuristic {
2124
void Process(HostInfo& host, const CollectorConfig& config, HostConfig* hconfig) const {
2225
// All our probes depend on eBPF.
23-
if (!host.HasEBPFSupport()) {
24-
CLOG(FATAL) << host.GetDistro() << " " << host.GetKernelVersion().release
26+
if (!host->has_ebpf_support()) {
27+
CLOG(FATAL) << host->distro().c_str() << " " << host->kernel_version()->release().c_str()
2528
<< " does not support eBPF, which is a requirement for Collector.";
2629
}
2730

28-
auto kernel = host.GetKernelVersion();
31+
auto kernel = host->kernel_version();
2932
// If we're configured to use eBPF with BTF, we try to be conservative
3033
// and fail instead of falling-back to ebpf.
3134
if (config.GetCollectionMethod() == CollectionMethod::CORE_BPF) {
32-
if (!host.HasBTFSymbols()) {
35+
if (!host->has_btf_symbols()) {
3336
CLOG(FATAL) << "Missing BTF symbols, core_bpf is not available. "
3437
<< "They can be provided by the kernel when configured with DEBUG_INFO_BTF, "
3538
<< "or as file. "
3639
<< g_switch_collection_hint;
3740
}
3841

39-
if (!host.HasBPFRingBufferSupport()) {
42+
if (!host->has_bpf_ringbuf_support()) {
4043
CLOG(FATAL) << "Missing RingBuffer support, core_bpf is not available. "
4144
<< g_switch_collection_hint;
4245
}
4346

44-
if (!host.HasBPFTracingSupport()) {
47+
if (!host->has_bpf_tracing_support()) {
4548
CLOG(FATAL) << "Missing BPF tracepoint support.";
4649
}
4750
}
4851

4952
// If configured to use regular eBPF, still verify if CORE_BPF is supported.
5053
if (config.GetCollectionMethod() == CollectionMethod::EBPF) {
51-
if (host.HasBTFSymbols() &&
52-
host.HasBPFRingBufferSupport() &&
53-
host.HasBPFTracingSupport() &&
54-
kernel.machine != "ppc64le") {
54+
if (host->has_btf_symbols() &&
55+
host->has_bpf_ringbuf_support() &&
56+
host->has_bpf_tracing_support() &&
57+
kernel->machine() != "ppc64le") {
5558
CLOG(INFO) << "CORE_BPF collection method is available. "
5659
<< "Check the documentation to compare features of "
5760
<< "available collection methods.";
@@ -64,22 +67,22 @@ class DockerDesktopHeuristic : public Heuristic {
6467
public:
6568
// Docker Desktop does not support eBPF so we don't support it.
6669
void Process(HostInfo& host, const CollectorConfig& config, HostConfig* hconfig) const {
67-
if (host.IsDockerDesktop()) {
68-
CLOG(FATAL) << host.GetDistro() << " does not support eBPF.";
70+
if (host->is_docker_desktop()) {
71+
CLOG(FATAL) << host->distro().c_str() << " does not support eBPF.";
6972
}
7073
}
7174
};
7275

7376
class PowerHeuristic : public Heuristic {
7477
public:
7578
void Process(HostInfo& host, const CollectorConfig& config, HostConfig* hconfig) const {
76-
auto k = host.GetKernelVersion();
79+
auto k = host->kernel_version();
7780

78-
if (k.machine != "ppc64le") {
81+
if (k->machine() != "ppc64le") {
7982
return;
8083
}
8184

82-
if (k.kernel == 4 && k.major == 18 && k.build_id < 477) {
85+
if (k->kernel() == 4 && k->major() == 18 && k->build_id() < 477) {
8386
CLOG(FATAL) << "RHEL 8.6 (kernel < 4.18.0-477) on ppc64le does not support CORE_BPF";
8487
}
8588
}
@@ -89,7 +92,7 @@ class CPUHeuristic : public Heuristic {
8992
public:
9093
// Enrich HostConfig with the number of possible CPU cores.
9194
void Process(HostInfo& host, const CollectorConfig& config, HostConfig* hconfig) const {
92-
hconfig->SetNumPossibleCPUs(host.NumPossibleCPU());
95+
hconfig->SetNumPossibleCPUs(host->num_possible_cpu());
9396
}
9497
};
9598

@@ -103,7 +106,7 @@ const std::unique_ptr<Heuristic> g_host_heuristics[] = {
103106
} // namespace
104107

105108
HostConfig ProcessHostHeuristics(const CollectorConfig& config) {
106-
HostInfo& host_info = HostInfo::Instance();
109+
HostInfo host_info = collector::rust::host_info();
107110
HostConfig host_config;
108111
for (auto& heuristic : g_host_heuristics) {
109112
heuristic->Process(host_info, config, &host_config);

‎collector/lib/HostHeuristics.h

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include "CollectorConfig.h"
55
#include "HostConfig.h"
6-
#include "HostInfo.h"
76

87
namespace collector {
98

‎collector/lib/rust/host/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ edition = "2021"
55

66
[dependencies]
77
cxx = "1.0"
8+
libbpf-rs = "0.24.8"
9+
libc = "0.2.164"
10+
log = "0.4.22"
811
regex = "1.11.1"
912
uname = "0.1.1"
1013

‎collector/lib/rust/host/src/info.rs

+115-36
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
use log::{debug, info, warn};
2+
3+
use std::io::Error;
4+
5+
use libbpf_rs::libbpf_sys::{
6+
libbpf_num_possible_cpus, libbpf_probe_bpf_prog_type, BPF_PROG_TYPE_TRACING,
7+
};
8+
19
use crate::KernelVersion;
210

311
use std::fs::File;
@@ -25,6 +33,7 @@ pub enum SecureBootStatus {
2533
Unset = 0,
2634
}
2735

36+
#[derive(Default)]
2837
pub struct HostInfo {
2938
os: String,
3039
build: String,
@@ -151,46 +160,38 @@ impl HostInfo {
151160
// TODO: not sure I like the layout of this, perhaps it needs a revisit
152161
let locations = vec![
153162
// try canonical vmlinux BTF through sysfs first
154-
("/sys/kernel/btf/vmlinux".to_string(), false),
163+
PathBuf::from("/sys/kernel/btf/vmlinux"),
155164
// fall back to trying to find vmlinux on disk otherwise
156-
(format!("/boot/vmlinux-{}", self.kernel.release), false),
157-
(
158-
format!(
159-
"/lib/modules/{}/vmlinux-{}",
160-
self.kernel.release, self.kernel.release
161-
),
162-
false,
163-
),
164-
(
165-
format!("/lib/modules/{}/build/vmlinux", self.kernel.release),
166-
false,
167-
),
168-
(
169-
format!("/usr/lib/modules/{}/kernel/vmlinux", self.kernel.release),
170-
true,
171-
),
172-
(
173-
format!("/usr/lib/debug/boot/vmlinux-{}", self.kernel.release),
174-
true,
175-
),
176-
(
177-
format!("/usr/lib/debug/boot/vmlinux-{}.debug", self.kernel.release),
178-
true,
179-
),
180-
(
181-
format!("/usr/lib/debug/lib/modules/{}/vmlinux", self.kernel.release),
182-
true,
183-
),
165+
PathBuf::from(format!("/boot/vmlinux-{}", self.kernel.release)),
166+
PathBuf::from(format!(
167+
"/lib/modules/{}/vmlinux-{}",
168+
self.kernel.release, self.kernel.release
169+
)),
170+
PathBuf::from(format!(
171+
"/lib/modules/{}/build/vmlinux",
172+
self.kernel.release
173+
)),
174+
host_path(format!(
175+
"/usr/lib/modules/{}/kernel/vmlinux",
176+
self.kernel.release
177+
)),
178+
host_path(format!(
179+
"/usr/lib/debug/boot/vmlinux-{}",
180+
self.kernel.release
181+
)),
182+
host_path(format!(
183+
"/usr/lib/debug/boot/vmlinux-{}.debug",
184+
self.kernel.release
185+
)),
186+
host_path(format!(
187+
"/usr/lib/debug/lib/modules/{}/vmlinux",
188+
self.kernel.release
189+
)),
184190
];
185191

186192
for location in locations {
187-
let path = if location.1 {
188-
host_path(location.0)
189-
} else {
190-
PathBuf::from(location.0)
191-
};
192-
193-
if path.exists() {
193+
if location.exists() {
194+
debug!("BTF symbols found in {:?}", location);
194195
return true;
195196
}
196197
}
@@ -210,6 +211,33 @@ impl HostInfo {
210211
pub fn secure_boot_status(&self) -> SecureBootStatus {
211212
SecureBootStatus::Unset
212213
}
214+
215+
pub fn num_possible_cpu(&self) -> i64 {
216+
(unsafe { libbpf_num_possible_cpus() }) as i64
217+
}
218+
219+
pub fn has_bpf_tracing_support(&self) -> bool {
220+
let res = unsafe { libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_TRACING, std::ptr::null()) };
221+
222+
if res == 0 {
223+
info!(
224+
"BPF tracepoint program type is not supported (errno = {:?})",
225+
Error::last_os_error()
226+
);
227+
}
228+
229+
if res < 0 {
230+
warn!(
231+
"Unable to check for the BPF tracepoint program support. Assuming it is available"
232+
);
233+
}
234+
235+
res != 0
236+
}
237+
238+
pub fn has_bpf_ringbuf_support(&self) -> bool {
239+
false
240+
}
213241
}
214242

215243
/// Constructs a path joined from the host root (usually /host)
@@ -222,3 +250,54 @@ fn host_path<P: Into<PathBuf>>(path: P) -> PathBuf {
222250
pub fn host_info() -> Box<HostInfo> {
223251
Box::new(HostInfo::new())
224252
}
253+
254+
#[cfg(test)]
255+
mod tests {
256+
use super::*;
257+
258+
#[test]
259+
fn test_is_rhel76() {
260+
let mut host = HostInfo {
261+
kernel: KernelVersion::new("3.10.0-957.10.1.el7.x86_64", "", ""),
262+
os: "rhel".to_string(),
263+
..Default::default()
264+
};
265+
266+
assert!(
267+
host.is_rhel76(),
268+
"3.10.0-957.10.1.el7.x86_64 should be RHEL 7.6"
269+
);
270+
271+
host.kernel = KernelVersion::new("4.11.0-18.10.1.el8.x86_64", "", "");
272+
273+
assert!(
274+
!host.is_rhel76(),
275+
"4.11.0-18.10.1.el8.x86_64 shouldn't be RHEL 7.6"
276+
);
277+
}
278+
279+
#[test]
280+
fn test_cos_identification() {
281+
assert!(
282+
HostInfo {
283+
os: "cos".to_string(),
284+
build: "123".to_string(),
285+
..Default::default()
286+
}
287+
.is_cos(),
288+
"COS should be identified"
289+
);
290+
}
291+
292+
#[test]
293+
fn test_ubuntu_identification() {
294+
assert!(
295+
HostInfo {
296+
os: "ubuntu".to_string(),
297+
..Default::default()
298+
}
299+
.is_ubuntu(),
300+
"Ubuntu should be identified"
301+
);
302+
}
303+
}

0 commit comments

Comments
 (0)
Please sign in to comment.