From b9fdc85429fc637c2f60cd82e6883c65352e1ee6 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Wed, 22 Jan 2025 15:10:44 +0100 Subject: [PATCH] new(test/libscap): add hotplug tests to libscap_test suite. Signed-off-by: Federico Di Pierro --- test/libscap/helpers/engines.cpp | 49 ++++++++++++++++++- test/libscap/helpers/engines.h | 4 ++ test/libscap/test_suites/engines/bpf/bpf.cpp | 18 +++++++ .../libscap/test_suites/engines/kmod/kmod.cpp | 18 +++++++ .../engines/modern_bpf/modern_bpf.cpp | 18 +++++++ 5 files changed, 106 insertions(+), 1 deletion(-) diff --git a/test/libscap/helpers/engines.cpp b/test/libscap/helpers/engines.cpp index e68243524e..13f8f63b77 100644 --- a/test/libscap/helpers/engines.cpp +++ b/test/libscap/helpers/engines.cpp @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include "engines.h" /* We are supposing that if we overcome this threshold, all buffers are full. * Probably this threshold is too low, but it depends on the machine's workload. @@ -205,6 +205,53 @@ void check_event_order(scap_t *h) { } #endif +void check_hotplug_event(scap_t *h, std::ofstream &cpu_file) { + // Start capture + ASSERT_EQ(scap_start_capture(h), SCAP_SUCCESS); + + // Enable back cpu 1 + cpu_file.seekp(0, std::ios::beg); + cpu_file << "1"; + cpu_file.flush(); + + // Set the affinity on first CPU + cpu_set_t set, starting_set; + sched_getaffinity(0, sizeof(cpu_set_t), &starting_set); + + CPU_ZERO(&set); // clear cpu mask + CPU_SET(1, &set); // set cpu 1 + sched_setaffinity(0, sizeof(cpu_set_t), &set); + + // Generate some syscalls on CPU 1 to make sure we generate an event + cpu_file.close(); + + // Reset affinity + sched_setaffinity(0, sizeof(cpu_set_t), &starting_set); + + ASSERT_EQ(scap_stop_capture(h), SCAP_SUCCESS); + + scap_evt *evt = NULL; + uint16_t buffer_id; + uint32_t flags; + bool found_hotplug = false; + + int num_consecutive_timeouts = 0; + while(num_consecutive_timeouts < 50 && !found_hotplug) { + if(scap_next(h, &evt, &buffer_id, &flags) == SCAP_SUCCESS) { + if(evt->type == PPME_CPU_HOTPLUG_E) { + found_hotplug = true; + break; + } + } else { + num_consecutive_timeouts++; + } + } + + scap_close(h); + + ASSERT_TRUE(found_hotplug); +} + /* Right now this is used only by the modern bpf * This is extracted from `libbpf_num_possible_cpus()`. * We avoid to include libbpf just for this helper. diff --git a/test/libscap/helpers/engines.h b/test/libscap/helpers/engines.h index 18c3fb3124..375afe25f8 100644 --- a/test/libscap/helpers/engines.h +++ b/test/libscap/helpers/engines.h @@ -1,7 +1,11 @@ #include +#include +#include void check_event_is_not_overwritten(scap_t* h); void check_event_order(scap_t* h); +void check_hotplug_event(scap_t* h, std::ofstream& cpu_file); + int num_possible_cpus(void); diff --git a/test/libscap/test_suites/engines/bpf/bpf.cpp b/test/libscap/test_suites/engines/bpf/bpf.cpp index 1f1b6c0c29..39cad9723c 100644 --- a/test/libscap/test_suites/engines/bpf/bpf.cpp +++ b/test/libscap/test_suites/engines/bpf/bpf.cpp @@ -279,3 +279,21 @@ TEST(bpf, metrics_v2_check_empty) { ASSERT_EQ(rc, SCAP_SUCCESS); scap_close(h); } + +TEST(bpf, hotplug) { + char error_buffer[FILENAME_MAX] = {0}; + int ret = 0; + + // Disable cpu 1 + std::ofstream cpu_file("/sys/devices/system/cpu/cpu1/online"); + ASSERT_TRUE(cpu_file.is_open()); + cpu_file << "0"; + cpu_file.flush(); + + // open scap + scap_t* h = open_bpf_engine(error_buffer, &ret, 4 * 4096, LIBSCAP_TEST_BPF_PROBE_PATH); + ASSERT_FALSE(!h || ret != SCAP_SUCCESS) + << "unable to open bpf engine: " << error_buffer << std::endl; + + check_hotplug_event(h, cpu_file); +} diff --git a/test/libscap/test_suites/engines/kmod/kmod.cpp b/test/libscap/test_suites/engines/kmod/kmod.cpp index d3ef47cfb6..ff94bf058b 100644 --- a/test/libscap/test_suites/engines/kmod/kmod.cpp +++ b/test/libscap/test_suites/engines/kmod/kmod.cpp @@ -333,3 +333,21 @@ TEST(kmod, metrics_v2_check_empty) { ASSERT_EQ(rc, SCAP_SUCCESS); scap_close(h); } + +TEST(kmod, hotplug) { + char error_buffer[FILENAME_MAX] = {0}; + int ret = 0; + + // Disable cpu 1 + std::ofstream cpu_file("/sys/devices/system/cpu/cpu1/online"); + ASSERT_TRUE(cpu_file.is_open()); + cpu_file << "0"; + cpu_file.flush(); + + // open scap + scap_t* h = open_kmod_engine(error_buffer, &ret, 4 * 4096, LIBSCAP_TEST_KERNEL_MODULE_PATH); + ASSERT_FALSE(!h || ret != SCAP_SUCCESS) + << "unable to open kmod engine: " << error_buffer << std::endl; + + check_hotplug_event(h, cpu_file); +} diff --git a/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp b/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp index 8b50651b99..cf57ee5e7b 100644 --- a/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp +++ b/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp @@ -417,3 +417,21 @@ TEST(modern_bpf, double_metrics_v2_call) { scap_close(h); } + +TEST(modern_bpf, hotplug) { + char error_buffer[FILENAME_MAX] = {0}; + int ret = 0; + + // Disable cpu 1 + std::ofstream cpu_file("/sys/devices/system/cpu/cpu1/online"); + ASSERT_TRUE(cpu_file.is_open()); + cpu_file << "0"; + cpu_file.flush(); + + // open scap + scap_t* h = open_modern_bpf_engine(error_buffer, &ret, 1 * 1024 * 1024, 0, true); + ASSERT_FALSE(!h || ret != SCAP_SUCCESS) + << "unable to open modern bpf engine: " << error_buffer << std::endl; + + check_hotplug_event(h, cpu_file); +}