diff --git a/tests/stress/ebpf_mt_stress.h b/tests/stress/ebpf_mt_stress.h index 773b044b1..0a964ee58 100644 --- a/tests/stress/ebpf_mt_stress.h +++ b/tests/stress/ebpf_mt_stress.h @@ -53,8 +53,8 @@ struct test_control_info // The number of threads allocated per jit program. uint32_t threads_count{0}; - // The run time for each jit program test thread in seconds. - uint32_t duration{0}; + // The run time for each jit program test thread in minutes. + uint32_t duration_minutes{0}; // Flag to enable verbose progress output. bool verbose_output{false}; @@ -63,7 +63,7 @@ struct test_control_info bool extension_restart_enabled{false}; // Delay between extension restarts (in milliseconds). - uint32_t extension_restart_delay{0}; + uint32_t extension_restart_delay_ms{0}; // Programs to load. std::vector programs; @@ -82,7 +82,7 @@ struct stress_test_thread_context std::string file_name; bpf_prog_type program_type; ebpf_execution_type_t execution_type; - uint32_t runtime{0}; + uint32_t duration_minutes{0}; fd_t map_fd; ebpf_result_t result; }; diff --git a/tests/stress/ebpf_stress_tests.cpp b/tests/stress/ebpf_stress_tests.cpp index 66f6a3ae7..3e66074f6 100644 --- a/tests/stress/ebpf_stress_tests.cpp +++ b/tests/stress/ebpf_stress_tests.cpp @@ -62,10 +62,10 @@ get_test_control_info() test_control_info test_control{0}; test_control.threads_count = _test_threads_count_arg; - test_control.duration = _test_duration_arg; + test_control.duration_minutes = _test_duration_arg; test_control.verbose_output = _test_verbose_output_arg; test_control.extension_restart_enabled = _extension_restart_arg; - test_control.extension_restart_delay = _extension_restart_delay_arg; + test_control.extension_restart_delay_ms = _extension_restart_delay_arg; test_control.programs = _jit_programs; return test_control; diff --git a/tests/stress/km/stress_tests_km.cpp b/tests/stress/km/stress_tests_km.cpp index 294533966..4235c6022 100644 --- a/tests/stress/km/stress_tests_km.cpp +++ b/tests/stress/km/stress_tests_km.cpp @@ -63,21 +63,6 @@ _km_test_init() // No programs specified on the command line, so use the preferred default. _global_test_control_info.programs.push_back({"cgroup_sock_addr"}); } - - if (_global_test_control_info.programs.size()) { - LOG_INFO("test programs:"); - for (const auto& program : _global_test_control_info.programs) { - LOG_INFO("\t{}", program); - } - } - - LOG_INFO("test threads per program : {}", _global_test_control_info.threads_count); - LOG_INFO("test duration (in minutes) : {}", _global_test_control_info.duration); - LOG_INFO("test verbose output : {}", _global_test_control_info.verbose_output); - LOG_INFO("test extension restart : {}", _global_test_control_info.extension_restart_enabled); - if (_global_test_control_info.extension_restart_enabled) { - LOG_INFO("test extension restart delay: {} ms", _global_test_control_info.extension_restart_delay); - } }); } @@ -168,6 +153,8 @@ _restart_extension(const std::string& extension_name, uint32_t timeout) SC_HANDLE scm_handle = nullptr; SC_HANDLE service_handle = nullptr; + REQUIRE(extension_name.size() != 0); + // Get a handle to the SCM database. scm_handle = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); if (scm_handle == nullptr) { @@ -180,7 +167,7 @@ _restart_extension(const std::string& extension_name, uint32_t timeout) service_handle = OpenService( scm_handle, ws_extension_name.c_str(), (SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS)); if (service_handle == nullptr) { - LOG_ERROR("FATAL ERROR: OpenService failed. Error: {}", GetLastError()); + LOG_ERROR("FATAL ERROR: OpenService failed. Service:{}, Error: {}", extension_name, GetLastError()); CloseServiceHandle(scm_handle); status = false; goto exit; @@ -210,6 +197,45 @@ exit: return status; } +static std::thread +_start_extension_restart_thread( + const std::string& extension_name, uint32_t restart_delay_ms, uint32_t thread_lifetime_minutes) +{ + return std::thread( + [&](uint32_t local_restart_delay_ms, uint32_t local_thread_lifetime_minutes) { + // Delay the start of this thread for a bit to allow the ebpf programs to attach successfully. There's a + // window where if the extension is unloading/unloaded, an incoming attach might fail. + std::this_thread::sleep_for(std::chrono::seconds(3)); + + // Bump up the priority of this thread so it doesn't get bogged down by the test threads. + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) { + auto error = GetLastError(); + LOG_WARN( + "WARNING:{} - Failed to increase 'extension restart' thread priority. Error: {}", __func__, error); + } + + using sc = std::chrono::steady_clock; + auto endtime = sc::now() + std::chrono::minutes(local_thread_lifetime_minutes); + while (sc::now() < endtime) { + + // Drivers can sometimes take some time to stop and (re)start and we need to poll until we can determine + // the final status. 10 (ten) seconds seems a reasonable time for this polling. + constexpr uint32_t RESTART_TIMEOUT_SECONDS = 10; + LOG_VERBOSE("Toggling extension state for {} extension...", extension_name); + if (!_restart_extension(extension_name, RESTART_TIMEOUT_SECONDS)) { + exit(-1); + } + + LOG_VERBOSE( + "Next restart for {} extension after a delay of {} ms", extension_name, local_restart_delay_ms); + std::this_thread::sleep_for(std::chrono::milliseconds(local_restart_delay_ms)); + } + LOG_INFO("**** Extension restart thread done. Exiting. ****"); + }, + restart_delay_ms, + thread_lifetime_minutes); +} + struct bpf_object_ptr_deleter { void @@ -274,7 +300,7 @@ struct thread_context thread_role_type role{}; uint32_t thread_index{}; uint32_t compartment_id{}; - uint32_t duration{}; + uint32_t duration_minutes{}; bool extension_restart_enabled{}; fd_t map_fd; fd_t program_fd; @@ -531,7 +557,7 @@ static void _test_thread_function(thread_context& context) { using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(context.duration); + auto endtime = sc::now() + std::chrono::minutes(context.duration_minutes); while (sc::now() < endtime) { if (context.role == thread_role_type::CREATOR) { _do_creator_work(context); @@ -630,7 +656,7 @@ _mt_prog_load_stress_test(ebpf_execution_type_t program_type, const test_control } context_entry.thread_index = (compartment_id - 1); context_entry.compartment_id = compartment_id; - context_entry.duration = test_control_info.duration; + context_entry.duration_minutes = test_control_info.duration_minutes; context_entry.extension_restart_enabled = test_control_info.extension_restart_enabled; compartment_id++; @@ -639,43 +665,13 @@ _mt_prog_load_stress_test(ebpf_execution_type_t program_type, const test_control thread_entry = std::move(std::thread(_test_thread_function, std::ref(context_entry))); } + // If requested, start the 'extension stop-and-restart' thread for extension for this program type. if (test_control_info.extension_restart_enabled) { - - // If requested, start the 'extension stop-and-restart' thread for extension for this program type. - extension_restart_thread_table.push_back(std::thread([&]() { - // Delay the start of this thread for a bit to allow the ebpf programs to attach successfully. There's a - // window where if the extension is unloading/unloaded, an incoming attach might fail. - std::this_thread::sleep_for(std::chrono::seconds(3)); - - // Bump up the priority of this thread so it doesn't get bogged down by the test threads. - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) { - auto error = GetLastError(); - LOG_WARN( - "WARNING:{} - Failed to increase 'extension restart' thread priority. Error: {}", - __func__, - error); - } - - using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(test_control_info.duration); - while (sc::now() < endtime) { - - // Drivers can sometimes take some time to stop and (re)start and we need to poll until we can - // determine the final status. 10 (ten) seconds seems a reasonable time for this polling. - constexpr uint32_t RESTART_TIMEOUT_SECONDS = 10; - LOG_VERBOSE("Toggling extension state for {} extension...", program_attribs.extension_name); - if (!_restart_extension(program_attribs.extension_name, RESTART_TIMEOUT_SECONDS)) { - exit(-1); - } - - LOG_VERBOSE( - "Next restart for {} extension after a delay of {} ms", - program_attribs.extension_name, - test_control_info.extension_restart_delay); - std::this_thread::sleep_for(std::chrono::milliseconds(test_control_info.extension_restart_delay)); - } - LOG_INFO("**** Extension restart thread done. Exiting. ****"); - })); + auto restart_thread = _start_extension_restart_thread( + std::ref(program_attribs.extension_name), + test_control_info.extension_restart_delay_ms, + test_control_info.duration_minutes); + extension_restart_thread_table.push_back(std::move(restart_thread)); } } @@ -850,7 +846,7 @@ _invoke_test_thread_function(thread_context& context) // will/should resume once the extension is reloaded. Note that the count will not exactly match the actual connect // attempts as the program will not be invoked for connect attempts made while the extension is restarting. using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(context.duration); + auto endtime = sc::now() + std::chrono::minutes(context.duration_minutes); while (sc::now() < endtime) { uint16_t key = remote_port; @@ -904,8 +900,6 @@ _mt_invoke_prog_stress_test(ebpf_execution_type_t program_type, const test_contr total_threads, {{}, {}, false, {}, thread_role_type::ROLE_NOT_SET, 0, 0, 0, false, 0, 0, object_table}); std::vector test_thread_table(total_threads); - // Another table for the 'extension restart' thread. - std::vector extension_restart_thread_table{}; std::vector> program_file_map_names = { {{"cgroup_count_connect4.sys"}, {"connect4_count_map"}}, {{"cgroup_count_connect6.sys"}, {"connect6_count_map"}}}; @@ -922,7 +916,7 @@ _mt_invoke_prog_stress_test(ebpf_execution_type_t program_type, const test_contr context_entry.role = (i == 0 ? thread_role_type::MONITOR_IPV4 : thread_role_type::MONITOR_IPV6); context_entry.thread_index = i; context_entry.compartment_id = UNSPECIFIED_COMPARTMENT_ID; - context_entry.duration = test_control_info.duration; + context_entry.duration_minutes = test_control_info.duration_minutes; context_entry.extension_restart_enabled = test_control_info.extension_restart_enabled; // Now create the thread. @@ -930,41 +924,15 @@ _mt_invoke_prog_stress_test(ebpf_execution_type_t program_type, const test_contr thread_entry = std::move(std::thread(_invoke_test_thread_function, std::ref(context_entry))); } + // Another table for the 'extension restart' threads. + std::vector extension_restart_thread_table{}; + + // If requested, start the 'extension stop-and-restart' thread for extension for this program type. + std::string extension_name = {"netebpfext"}; if (test_control_info.extension_restart_enabled) { - - // Start the 'extension stop-and-restart' thread for extension for this program type. - extension_restart_thread_table.push_back(std::thread([&]() { - // Delay the start of this thread for a bit to allow the ebpf programs to attach successfully. There's a - // window where if the extension is unloading/unloaded, an incoming attach might fail. - std::this_thread::sleep_for(std::chrono::seconds(3)); - - // Bump up the priority of this thread so it doesn't get bogged down by the test threads. - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) { - error = GetLastError(); - LOG_WARN("WARNING:{} - Unable to increase 'extension restart' thread priority", __func__, error); - } - - std::string extension_name = {"netebpfext"}; - using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(test_control_info.duration); - while (sc::now() < endtime) { - LOG_VERBOSE("Toggling extension state for '{}' extension...", extension_name.c_str()); - - // Drivers can sometimes take some time to stop and (re)start and we need to poll until we can - // determine the final status. 10 (ten) seconds seems a reasonable timeout for this polling. - constexpr uint32_t RESTART_TIMEOUT_SECONDS = 10; - if (!_restart_extension(extension_name, RESTART_TIMEOUT_SECONDS)) { - exit(-1); - } - - LOG_VERBOSE( - "Next restart for {} extension after a delay of {} ms", - extension_name, - test_control_info.extension_restart_delay); - std::this_thread::sleep_for(std::chrono::milliseconds(test_control_info.extension_restart_delay)); - } - LOG_INFO("**** Extension restart thread done. Exiting. ****"); - })); + auto restart_thread = _start_extension_restart_thread( + std::ref(extension_name), test_control_info.extension_restart_delay_ms, test_control_info.duration_minutes); + extension_restart_thread_table.push_back(std::move(restart_thread)); } // Wait for threads to terminate. @@ -1000,7 +968,7 @@ _invoke_mt_sockaddr_thread_function(thread_context& context) (reinterpret_cast(&remote_endpoint))->sin_port = htons(remote_port); using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(context.duration); + auto endtime = sc::now() + std::chrono::minutes(context.duration_minutes); while (sc::now() < endtime) { // Now send out a small burst of TCP 'connect' attempts for the duration of the test. We do this to increase @@ -1046,7 +1014,7 @@ _mt_sockaddr_invoke_program_test(const test_control_info& test_control_info) context_entry.is_native_program = true; context_entry.role = thread_role_type::MONITOR_IPV6; context_entry.thread_index = i; - context_entry.duration = test_control_info.duration; + context_entry.duration_minutes = test_control_info.duration_minutes; context_entry.extension_restart_enabled = test_control_info.extension_restart_enabled; // Now create the thread. @@ -1054,43 +1022,15 @@ _mt_sockaddr_invoke_program_test(const test_control_info& test_control_info) thread_entry = std::move(std::thread(_invoke_mt_sockaddr_thread_function, std::ref(context_entry))); } - // Another table for the 'extension restart' thread. + // Another table for the 'extension restart' threads. std::vector extension_restart_thread_table{}; + + // If requested, start the 'extension stop-and-restart' thread for extension for this program type. + std::string extension_name = {"netebpfext"}; if (test_control_info.extension_restart_enabled) { - - // Start the 'extension stop-and-restart' thread for extension for this program type. - extension_restart_thread_table.push_back(std::thread([&]() { - // Delay the start of this thread for a bit to allow the ebpf programs to attach successfully. There's a - // window where if the extension is unloading/unloaded, an incoming attach might fail. - std::this_thread::sleep_for(std::chrono::seconds(3)); - - // Bump up the priority of this thread so it doesn't get bogged down by the test threads. - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) { - error = GetLastError(); - LOG_WARN("WARNING:{} - Unable to increase 'extension restart' thread priority", __func__, error); - } - - std::string extension_name = {"netebpfext"}; - using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(test_control_info.duration); - while (sc::now() < endtime) { - LOG_VERBOSE("Toggling extension state for '{}' extension...", extension_name.c_str()); - - // Drivers can sometimes take some time to stop and (re)start and we need to poll until we can - // determine the final status. 10 (ten) seconds seems a reasonable timeout for this polling. - constexpr uint32_t RESTART_TIMEOUT_SECONDS = 10; - if (!_restart_extension(extension_name, RESTART_TIMEOUT_SECONDS)) { - exit(-1); - } - - LOG_VERBOSE( - "Next restart for {} extension after a delay of {} ms", - extension_name, - test_control_info.extension_restart_delay); - std::this_thread::sleep_for(std::chrono::milliseconds(test_control_info.extension_restart_delay)); - } - LOG_INFO("**** Extension restart thread done. Exiting. ****"); - })); + auto restart_thread = _start_extension_restart_thread( + std::ref(extension_name), test_control_info.extension_restart_delay_ms, test_control_info.duration_minutes); + extension_restart_thread_table.push_back(std::move(restart_thread)); } // Wait for threads to terminate. @@ -1107,6 +1047,18 @@ _mt_sockaddr_invoke_program_test(const test_control_info& test_control_info) } } +static void +_print_test_control_info(const test_control_info& test_control_info) +{ + LOG_INFO("test threads per program : {}", test_control_info.threads_count); + LOG_INFO("test duration (in minutes) : {}", test_control_info.duration_minutes); + LOG_INFO("test verbose output : {}", test_control_info.verbose_output); + LOG_INFO("test extension restart : {}", test_control_info.extension_restart_enabled); + if (test_control_info.extension_restart_enabled) { + LOG_INFO("test extension restart delay: {} ms", test_control_info.extension_restart_delay_ms); + } +} + TEST_CASE("jit_load_attach_detach_unload_random_v4_test", "[mt_stress_test]") { // This test attempts to load the same JIT'ed ebpf program multiple times in different threads. This test @@ -1121,6 +1073,8 @@ TEST_CASE("jit_load_attach_detach_unload_random_v4_test", "[mt_stress_test]") _km_test_init(); LOG_INFO("\nStarting test *** jit_load_attach_detach_unload_random_v4_test ***"); test_control_info local_test_control_info = _global_test_control_info; + + _print_test_control_info(local_test_control_info); _mt_prog_load_stress_test(EBPF_EXECUTION_JIT, local_test_control_info); } @@ -1136,12 +1090,12 @@ TEST_CASE("native_load_attach_detach_unload_random_v4_test", "[mt_stress_test]") _km_test_init(); LOG_INFO("\nStarting test *** native_load_attach_detach_unload_random_v4_test ***"); test_control_info local_test_control_info = _global_test_control_info; - if (!local_test_control_info.extension_restart_enabled) { - // Enable the 'extension restart' thread to enable user mode error suppression. - // (The restart delay is set to a default value or the value specified (if any) on the command line) - local_test_control_info.extension_restart_enabled = true; - } + // Enforce enabling of the 'extension restart' thread for this test for increased stress. + // (The restart delay is set to the default value or the value specified (if any) on the command line.) + local_test_control_info.extension_restart_enabled = true; + + _print_test_control_info(local_test_control_info); _mt_prog_load_stress_test(EBPF_EXECUTION_NATIVE, local_test_control_info); } @@ -1157,15 +1111,15 @@ TEST_CASE("native_unique_load_attach_detach_unload_random_v4_test", "[mt_stress_ _km_test_init(); LOG_INFO("\nStarting test *** native_unique_load_attach_detach_unload_random_v4_test ***"); test_control_info local_test_control_info = _global_test_control_info; - if (!local_test_control_info.extension_restart_enabled) { - // Enable the 'extension restart' thread. - // (The restart delay is set to a default value or the value specified (if any) on the command line. - local_test_control_info.extension_restart_enabled = true; - } + // Enforce enabling of the 'extension restart' thread for this test for increased stress. + // (The restart delay is set to the default value or the value specified (if any) on the command line.) + local_test_control_info.extension_restart_enabled = true; // Use a unique native driver for each 'creator' thread. local_test_control_info.use_unique_native_programs = true; + + _print_test_control_info(local_test_control_info); _mt_prog_load_stress_test(EBPF_EXECUTION_NATIVE, local_test_control_info); } @@ -1195,7 +1149,12 @@ TEST_CASE("native_invoke_program_restart_extension_v4_test", "[mt_stress_test]") _km_test_init(); LOG_INFO("\nStarting test *** native_invoke_program_restart_extension_v4_test ***"); test_control_info local_test_control_info = _global_test_control_info; + + // Enforce enabling of the 'extension restart' thread for this test for increased stress. + // (The restart delay is set to the default value or the value specified (if any) on the command line.) local_test_control_info.extension_restart_enabled = true; + + _print_test_control_info(local_test_control_info); _mt_invoke_prog_stress_test(EBPF_EXECUTION_NATIVE, local_test_control_info); } @@ -1217,10 +1176,12 @@ TEST_CASE("sockaddr_invoke_program_test", "[mt_stress_test]") // We ignore the result of the 'connect' attempt as the intent here is to test the parallel invocation of the // WFP callout and ensure this test doesn't cause kernel mode crashes. // - // 3. Start the 'extension restart' thread in parallel to continuously restart the netebpf extension. + // 3. If specified, start the 'extension restart' thread as well to continuously restart the netebpf extension. _km_test_init(); LOG_INFO("\nStarting test *** sockaddr_invoke_program_test ***"); test_control_info local_test_control_info = _global_test_control_info; + + _print_test_control_info(local_test_control_info); _mt_sockaddr_invoke_program_test(local_test_control_info); } diff --git a/tests/stress/readme.md b/tests/stress/readme.md index d5b141fb2..d770cc5e2 100644 --- a/tests/stress/readme.md +++ b/tests/stress/readme.md @@ -8,13 +8,14 @@ _This application requires the `ebpfapi.dll` to be present in the DLL load path binary._ *Test specific command-line options (all optional, defaults used if not specified):* -- `-tt=NNNN`: Number of test threads to create. -- `-td=NNNN`: Test run-time in minutes. -- `-vo=`: Enable verbose output (default: false). -- `-er=`: Restart extension. -- `-erd=NNNN`: Extension restart delay (in milliseconds). +- `-tt=NNNN`: Number of test threads to create (Default: hard-coded). +- `-td=NNNN`: Test duration in minutes (Default: hard-coded). +- `-vo=`: Enable verbose output (Default: false). +- `-er=`: Restart extension (Default: false, where supported). +- `-erd=NNNN`: Extension restart delay in milliseconds (Default: hard-coded). -_This is a 'Catch2' test application and hence if no test name is provided on the command line, all tests are run in a sequential manner._ +_This is a 'Catch2' test application and hence if no test name is provided on the command line, all tests are run in a +sequential manner._ This application provides the following tests: @@ -22,22 +23,19 @@ This application provides the following tests: ## 1.1. jit_load_attach_detach_unload_random_v4_test - This test creates threads to randomly `load`, `attach`, `detach` and `close` JIT'ed ebpf program(s). (Details in code comments) +This test creates threads to randomly `load`, `attach`, `detach` and `close` JIT'ed ebpf program(s). +_(Details in code comments.)_ Sample commandline invocations: ### 1.1.1. `ebpf_stress_test_km jit_load_attach_detach_unload_random_v4_test` -- thread set size, test run-time: uses default values -- test trace output: none -- extension restart: disabled +- Uses default values for all supported options. ### 1.1.2. `ebpf_stress_test_km -tt=32 -td=5 -er=true jit_load_attach_detach_unload_random_v4_test` -- thread set size: 32 -- test run-time: 5 minutes. -- test trace output: none -- extension restart: enabled -- extension restart delay: default. +- Creates 32 test threads. +- Runs test for 5 minutes. +- Extension restart is enabled. ## 1.2. native_load_attach_detach_unload_random_v4_test @@ -48,9 +46,12 @@ program (.sys file). The command line options and their interpretation is identi Sample command line invocations: ### 1.2.1. `ebpf_stress_test_km native_load_attach_detach_unload_random_v4_test` -- use defaults. +- Uses default values for all supported options. ### 1.2.2. `ebpf_stress_test_km -tt=32 -td=5 -er=true native_load_attach_detach_unload_random_v4_test` +- Creates 32 test threads. +- Runs test for 5 minutes. +- Extension restart is enabled. ## 1.3. native_unique_load_attach_detach_unload_random_v4_test @@ -59,6 +60,9 @@ This test extends the ```native_load_attach_detach_unload_random_v4_test``` to u (The test makes unique copies of the same base native program at runtime). All other behavior is identical. ### 1.3.1. `ebpf_stress_test_km -tt=32 -td=5 -er=true native_unique_load_attach_detach_unload_random_v4_test` +- Creates 32 test threads. +- Runs test for 5 minutes. +- Extension restart enabled. ## 1.4. native_invoke_program_restart_extension_v4_test @@ -70,10 +74,34 @@ This test ignores the `-tt`, `-er` and `-erd` commandline parameters. Sample command line invocations: ### 1.4.1. `ebpf_stress_test_km native_invoke_program_restart_extension_v4_test` -- uses default run-time value. +- Uses default values for all supported options. ### 1.4.2. `ebpf_stress_test_km -td=15 -vo=true native_invoke_program_restart_extension_v4_test` -- runs test for 15 minutes, verbose test trace output enabled. +- Runs test for 15 minutes. +- Verbose test trace output enabled. + + +## 1.5. sockaddr_invoke_program_test +This test first loads a specific native eBPF program. It then creates the specified # of threads where each thread +attempts a TCP 'connect' to the remote endpoint `[::1]:` continuously in a +loop. The test set up ensures that the `thread_index` passed in each `thread_context` is unique to that thread. + +This causes the invocation of the in-kernel eBPF program which returns some (arbitrary) decision based on the end-point +port number. + +This test can be run with or without the extension restart option. + +Sample command line invocations: + +### 1.5.1. `ebpf_stress_test_km sockaddr_invoke_program_test` +- Uses default values for all supported options. + +### 1.5.2. `ebpf_stress_test_km -tt=32 -td=15 -vo=true -er=true -erd=250 sockaddr_invoke_program_test` +- Creates 32 test threads. +- Runs test for 15 minutes. +- Verbose test trace output enabled. +- Extension restart enabled. +- Delay of 250 ms between successive extension restarts. # 2.0. ebpf_stress_test_um.exe (test sources in .\um\) @@ -81,7 +109,7 @@ Sample command line invocations: This test application provides tests that are meant to be run against the user mode 'mock' of the eBPF sub-system. This application does not require the presence of the eBPF kernel drivers and can be run on the dev machine as well. -_This application requires the ```ebpfapi.dll``` to be present in the DLL load path or in the same directory as this +_This application requires the `ebpfapi.dll` to be present in the DLL load path or in the same directory as this binary._ @@ -98,15 +126,15 @@ This application provides the following tests: ## 2.1. load_attach_detach_unload_sequential_test This test loads, attaches, detaches and closes (in a sequential manner) the specified JIT'ed programs in their -respective thread sets. The test currently supprorts the `droppacket` and `bindmonitor_tailcall` programs only. -Either one or both can be specified, else `droppacket` is used by default. +respective thread sets. The test currently supprorts the `droppacket` and `bindmonitor_tailcall` programs only. Either +one or both can be specified, else `droppacket` is used by default. Sample command line invocations: ### 2.1.1. `ebpf_stress_test_um load_attach_detach_unload_sequential_test` -- uses default run-time values for threads and run-time, loads `droppacket` +- Uses default values for all supported options. ### 2.1.2. `ebpf_stress_test_km -tp="droppacket, bindmonitor_tailcall" -tt=32 -td=30 load_attach_detach_unload_sequential_test` -- uses `droppacket` and `bindmonitor_tailcall` programs -- creates a 32 thread set. -- runs the test for 30 minutes. +- Uses `droppacket` and `bindmonitor_tailcall` programs. +- creates 32 test threads. +- Runs the test for 30 minutes. diff --git a/tests/stress/um/stress_tests_um.cpp b/tests/stress/um/stress_tests_um.cpp index 61737b4c6..dd810b563 100644 --- a/tests/stress/um/stress_tests_um.cpp +++ b/tests/stress/um/stress_tests_um.cpp @@ -80,7 +80,7 @@ _bindmonitor_tailcall_stress_thread_function(const stress_test_thread_context& t { uint32_t count{0}; using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(test_params.runtime); + auto endtime = sc::now() + std::chrono::minutes(test_params.duration_minutes); while (sc::now() < endtime) { LOG_VERBOSE( @@ -142,7 +142,7 @@ _droppacket_stress_thread_function(const stress_test_thread_context& test_params UNREFERENCED_PARAMETER(test_params); uint32_t count{0}; using sc = std::chrono::steady_clock; - auto endtime = sc::now() + std::chrono::minutes(test_params.runtime); + auto endtime = sc::now() + std::chrono::minutes(test_params.duration_minutes); while (sc::now() < endtime) { LOG_VERBOSE( @@ -270,7 +270,7 @@ um_test_init() LOG_INFO("\t{}", program); } LOG_INFO("test threads per program : {}", _test_control_info.threads_count); - LOG_INFO("test duration (in minutes): {}", _test_control_info.duration); + LOG_INFO("test duration (in minutes): {}", _test_control_info.duration_minutes); LOG_INFO("test verbose output : {}", _test_control_info.verbose_output); }); } @@ -317,7 +317,7 @@ TEST_CASE("load_attach_detach_unload_sequential_test", "[mt_stress_test]") local_context.file_name = program_attributes.jit_file_name; local_context.program_type = program_attributes.program_type; local_context.execution_type = program_attributes.execution_type; - local_context.runtime = _test_control_info.duration; + local_context.duration_minutes = _test_control_info.duration_minutes; // ...And spawn the required test threads. auto [tv, ttc] = spawn_test_threads(