Skip to content

Commit

Permalink
testing, some more functionality, etc. host heuristics tests disabled…
Browse files Browse the repository at this point in the history
… for now
  • Loading branch information
Stringy committed Dec 23, 2024
1 parent 0bb9c9a commit 0222fff
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 119 deletions.
37 changes: 20 additions & 17 deletions collector/lib/HostHeuristics.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#include "HostHeuristics.h"

#include "Logging.h"
#include "host/src/lib.rs.h"

namespace collector {

namespace {

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

using HostInfo = ::rust::Box<collector::rust::HostInfo>;

class Heuristic {
public:
// Process the given HostInfo and CollectorConfig to adjust HostConfig as necessary.
Expand All @@ -20,38 +23,38 @@ class Heuristic {
class CollectionHeuristic : public Heuristic {
void Process(HostInfo& host, const CollectorConfig& config, HostConfig* hconfig) const {
// All our probes depend on eBPF.
if (!host.HasEBPFSupport()) {
CLOG(FATAL) << host.GetDistro() << " " << host.GetKernelVersion().release
if (!host->has_ebpf_support()) {
CLOG(FATAL) << host->distro().c_str() << " " << host->kernel_version()->release().c_str()
<< " does not support eBPF, which is a requirement for Collector.";
}

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

if (!host.HasBPFRingBufferSupport()) {
if (!host->has_bpf_ringbuf_support()) {
CLOG(FATAL) << "Missing RingBuffer support, core_bpf is not available. "
<< g_switch_collection_hint;
}

if (!host.HasBPFTracingSupport()) {
if (!host->has_bpf_tracing_support()) {
CLOG(FATAL) << "Missing BPF tracepoint support.";
}
}

// If configured to use regular eBPF, still verify if CORE_BPF is supported.
if (config.GetCollectionMethod() == CollectionMethod::EBPF) {
if (host.HasBTFSymbols() &&
host.HasBPFRingBufferSupport() &&
host.HasBPFTracingSupport() &&
kernel.machine != "ppc64le") {
if (host->has_btf_symbols() &&
host->has_bpf_ringbuf_support() &&
host->has_bpf_tracing_support() &&
kernel->machine() != "ppc64le") {
CLOG(INFO) << "CORE_BPF collection method is available. "
<< "Check the documentation to compare features of "
<< "available collection methods.";
Expand All @@ -64,22 +67,22 @@ class DockerDesktopHeuristic : public Heuristic {
public:
// Docker Desktop does not support eBPF so we don't support it.
void Process(HostInfo& host, const CollectorConfig& config, HostConfig* hconfig) const {
if (host.IsDockerDesktop()) {
CLOG(FATAL) << host.GetDistro() << " does not support eBPF.";
if (host->is_docker_desktop()) {
CLOG(FATAL) << host->distro().c_str() << " does not support eBPF.";
}
}
};

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

if (k.machine != "ppc64le") {
if (k->machine() != "ppc64le") {
return;
}

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

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

HostConfig ProcessHostHeuristics(const CollectorConfig& config) {
HostInfo& host_info = HostInfo::Instance();
HostInfo host_info = collector::rust::host_info();
HostConfig host_config;
for (auto& heuristic : g_host_heuristics) {
heuristic->Process(host_info, config, &host_config);
Expand Down
1 change: 0 additions & 1 deletion collector/lib/HostHeuristics.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "CollectorConfig.h"
#include "HostConfig.h"
#include "HostInfo.h"

namespace collector {

Expand Down
3 changes: 3 additions & 0 deletions collector/lib/rust/host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ edition = "2021"

[dependencies]
cxx = "1.0"
libbpf-rs = "0.24.8"
libc = "0.2.164"
log = "0.4.22"
regex = "1.11.1"
uname = "0.1.1"

Expand Down
151 changes: 115 additions & 36 deletions collector/lib/rust/host/src/info.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
use log::{debug, info, warn};

use std::io::Error;

use libbpf_rs::libbpf_sys::{
libbpf_num_possible_cpus, libbpf_probe_bpf_prog_type, BPF_PROG_TYPE_TRACING,
};

use crate::KernelVersion;

use std::fs::File;
Expand Down Expand Up @@ -25,6 +33,7 @@ pub enum SecureBootStatus {
Unset = 0,
}

#[derive(Default)]
pub struct HostInfo {
os: String,
build: String,
Expand Down Expand Up @@ -151,46 +160,38 @@ impl HostInfo {
// TODO: not sure I like the layout of this, perhaps it needs a revisit
let locations = vec![
// try canonical vmlinux BTF through sysfs first
("/sys/kernel/btf/vmlinux".to_string(), false),
PathBuf::from("/sys/kernel/btf/vmlinux"),
// fall back to trying to find vmlinux on disk otherwise
(format!("/boot/vmlinux-{}", self.kernel.release), false),
(
format!(
"/lib/modules/{}/vmlinux-{}",
self.kernel.release, self.kernel.release
),
false,
),
(
format!("/lib/modules/{}/build/vmlinux", self.kernel.release),
false,
),
(
format!("/usr/lib/modules/{}/kernel/vmlinux", self.kernel.release),
true,
),
(
format!("/usr/lib/debug/boot/vmlinux-{}", self.kernel.release),
true,
),
(
format!("/usr/lib/debug/boot/vmlinux-{}.debug", self.kernel.release),
true,
),
(
format!("/usr/lib/debug/lib/modules/{}/vmlinux", self.kernel.release),
true,
),
PathBuf::from(format!("/boot/vmlinux-{}", self.kernel.release)),
PathBuf::from(format!(
"/lib/modules/{}/vmlinux-{}",
self.kernel.release, self.kernel.release
)),
PathBuf::from(format!(
"/lib/modules/{}/build/vmlinux",
self.kernel.release
)),
host_path(format!(
"/usr/lib/modules/{}/kernel/vmlinux",
self.kernel.release
)),
host_path(format!(
"/usr/lib/debug/boot/vmlinux-{}",
self.kernel.release
)),
host_path(format!(
"/usr/lib/debug/boot/vmlinux-{}.debug",
self.kernel.release
)),
host_path(format!(
"/usr/lib/debug/lib/modules/{}/vmlinux",
self.kernel.release
)),
];

for location in locations {
let path = if location.1 {
host_path(location.0)
} else {
PathBuf::from(location.0)
};

if path.exists() {
if location.exists() {
debug!("BTF symbols found in {:?}", location);
return true;
}
}
Expand All @@ -210,6 +211,33 @@ impl HostInfo {
pub fn secure_boot_status(&self) -> SecureBootStatus {
SecureBootStatus::Unset
}

pub fn num_possible_cpu(&self) -> i64 {
(unsafe { libbpf_num_possible_cpus() }) as i64
}

pub fn has_bpf_tracing_support(&self) -> bool {
let res = unsafe { libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_TRACING, std::ptr::null()) };

if res == 0 {
info!(
"BPF tracepoint program type is not supported (errno = {:?})",
Error::last_os_error()
);
}

if res < 0 {
warn!(
"Unable to check for the BPF tracepoint program support. Assuming it is available"
);
}

res != 0
}

pub fn has_bpf_ringbuf_support(&self) -> bool {
false
}
}

/// Constructs a path joined from the host root (usually /host)
Expand All @@ -222,3 +250,54 @@ fn host_path<P: Into<PathBuf>>(path: P) -> PathBuf {
pub fn host_info() -> Box<HostInfo> {
Box::new(HostInfo::new())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_is_rhel76() {
let mut host = HostInfo {
kernel: KernelVersion::new("3.10.0-957.10.1.el7.x86_64", "", ""),
os: "rhel".to_string(),
..Default::default()
};

assert!(
host.is_rhel76(),
"3.10.0-957.10.1.el7.x86_64 should be RHEL 7.6"
);

host.kernel = KernelVersion::new("4.11.0-18.10.1.el8.x86_64", "", "");

assert!(
!host.is_rhel76(),
"4.11.0-18.10.1.el8.x86_64 shouldn't be RHEL 7.6"
);
}

#[test]
fn test_cos_identification() {
assert!(
HostInfo {
os: "cos".to_string(),
build: "123".to_string(),
..Default::default()
}
.is_cos(),
"COS should be identified"
);
}

#[test]
fn test_ubuntu_identification() {
assert!(
HostInfo {
os: "ubuntu".to_string(),
..Default::default()
}
.is_ubuntu(),
"Ubuntu should be identified"
);
}
}
Loading

0 comments on commit 0222fff

Please sign in to comment.