Skip to content

Commit

Permalink
Fix netevent prog test (#145)
Browse files Browse the repository at this point in the history
* added prog test run to context

* Revert "added prog test run to context"

This reverts commit 9665259.

* fix context_create/destroy

* added unit test

* data_out fix

* add sleep for event_map read

* added negative test

* review changes

* added ctx_out

---------

Co-authored-by: Laksh Kotian <[email protected]>
Co-authored-by: Sharmi <[email protected]>
  • Loading branch information
3 people authored Nov 1, 2024
1 parent 671a8ba commit b375fbc
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 9 deletions.
18 changes: 9 additions & 9 deletions ebpf_extensions/neteventebpfext/netevent_ebpf_ext_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ _ebpf_netevent_program_context_create(
// Copy the event's pointer & size from the caller, to the out context.
netevent_event_context->netevent_event_md.event_data_start = (uint8_t*)data_in;
netevent_event_context->netevent_event_md.event_data_end = (uint8_t*)data_in + data_size_in;
*context = netevent_event_context;
*context = &netevent_event_context->netevent_event_md;
netevent_event_context = NULL;
result = EBPF_SUCCESS;

Expand All @@ -424,18 +424,19 @@ _ebpf_netevent_program_context_destroy(
_Inout_ size_t* context_size_out)
{
EBPF_EXT_LOG_ENTRY();
netevent_event_notify_context_t* netevent_event_context = NULL;
netevent_event_md_t* netevent_event_context_out = NULL;

netevent_event_notify_context_t* netevent_event_context = (netevent_event_notify_context_t*)context;
netevent_event_md_t* netevent_event_context_out = (netevent_event_md_t*)context_out;

if (!netevent_event_context) {
if (!context) {
goto Exit;
}

netevent_event_context = CONTAINING_RECORD(context, netevent_event_notify_context_t, netevent_event_md);
netevent_event_context_out = (netevent_event_md_t*)context_out;

if (context_out != NULL && *context_size_out >= sizeof(netevent_event_md_t)) {
// Copy the context to the caller.
memcpy(netevent_event_context_out, &netevent_event_context->netevent_event_md, sizeof(netevent_event_md_t));
*context_size_out = sizeof(netevent_event_md_t);

// Zero out the event context info.
netevent_event_context_out->event_data_start = 0;
Expand All @@ -446,9 +447,8 @@ _ebpf_netevent_program_context_destroy(
}

// Copy the event data to 'data_out'.
if (data_out != NULL && *data_size_out >= (size_t)(
netevent_event_context->netevent_event_md.event_data_end -
netevent_event_context->netevent_event_md.event_data_start)) {
if (data_out != NULL && *data_size_out >= (size_t)(netevent_event_context->netevent_event_md.event_data_end -
netevent_event_context->netevent_event_md.event_data_start)) {
memcpy(
data_out,
netevent_event_context->netevent_event_md.event_data_start,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ CATCH_REGISTER_LISTENER(cxplat_passed_test_log)
#define MAX_EVENTS_COUNT 1000
#define NETEVENT_EVENT_TEST_TIMEOUT_SEC 90
#define NETEVENT_EVENT_STRESS_TEST_TIMEOUT_SEC 90
#define MAX_PACKET_SIZE 1600

struct bpf_map* netevent_event_map;
struct bpf_map* command_map;
Expand Down Expand Up @@ -260,3 +261,98 @@ TEST_CASE("netevent_drivers_load_unload_stress", "[neteventebpfext]")
REQUIRE(neteventebpfext_driver.stop() == true);
REQUIRE(neteventebpfext_driver.unload() == true);
}

TEST_CASE("netevent_bpf_prog_run_test", "[neteventebpfext]")
{
// The BPF object will take some time to unload from the previous test
// TODO: Remove sleep once this issue is fixed: https://github.com/microsoft/ebpf-for-windows/issues/2667
std::this_thread::sleep_for(std::chrono::seconds(10));

// Load and start neteventebpfext extension driver.
driver_service neteventebpfext_driver;
REQUIRE(
neteventebpfext_driver.create(
L"neteventebpfext", driver_service::get_driver_path("neteventebpfext.sys").c_str()) == true);
REQUIRE(neteventebpfext_driver.start() == true);

// Load the NetEventMonitor native BPF program.
struct bpf_object* object = bpf_object__open("netevent_monitor.sys");
REQUIRE(object != nullptr);

int res = bpf_object__load(object);
REQUIRE(res == 0);

// Find and attach to the netevent_monitor BPF program.
bpf_program* netevent_monitor = bpf_object__find_program_by_name(object, "NetEventMonitor");
REQUIRE(netevent_monitor != nullptr);
bpf_link* netevent_monitor_link = bpf_program__attach(netevent_monitor);
REQUIRE(netevent_monitor_link != nullptr);

// Attach to the eBPF ring buffer event map.
bpf_map* netevent_events_map = bpf_object__find_map_by_name(object, "netevent_events_map");
REQUIRE(netevent_events_map != nullptr);
ring_buffer* ring =
ring_buffer__new(bpf_map__fd(netevent_events_map), netevent_monitor_event_callback, nullptr, nullptr);
REQUIRE(ring != nullptr);

// Initialize structures required for bpf_prog_test_run_opts
bpf_test_run_opts bpf_opts = {0};
netevent_event_md_t netevent_ctx_in = {0};
netevent_event_md_t netevent_ctx_out = {0};
unsigned char dummy_data_in[] = {NOTIFY_EVENT_TYPE_NETEVENT, 'a', 'b'};
const size_t dummy_data_size = sizeof(dummy_data_in);
unsigned char data_out[MAX_PACKET_SIZE] = {0};
uint32_t event_count_before = event_count;
fd_t netevent_program_fd = bpf_program__fd(netevent_monitor);
REQUIRE(netevent_program_fd != ebpf_fd_invalid);

// Prepare bpf_opts
bpf_opts.repeat = 1;
bpf_opts.ctx_in = &netevent_ctx_in;
bpf_opts.ctx_size_in = sizeof(netevent_ctx_in);
bpf_opts.ctx_out = &netevent_ctx_out;
bpf_opts.ctx_size_out = sizeof(netevent_ctx_out);
bpf_opts.data_in = &dummy_data_in;
bpf_opts.data_size_in = static_cast<uint32_t>(dummy_data_size);
// Set the data_out buffer to hold the output.
bpf_opts.data_out = data_out;
bpf_opts.data_size_out = sizeof(data_out);

// Execute the program
REQUIRE(bpf_prog_test_run_opts(netevent_program_fd, &bpf_opts) == 0);

REQUIRE(bpf_opts.data_size_out == dummy_data_size);
REQUIRE(memcmp(dummy_data_in, data_out, dummy_data_size) == 0);
REQUIRE(bpf_opts.ctx_size_out == sizeof(netevent_ctx_out));
std::this_thread::sleep_for(std::chrono::seconds(5));
REQUIRE(event_count == event_count_before + 1);

// Execute negative cases
bpf_opts.ctx_in = NULL;
bpf_opts.ctx_size_in = 0;

REQUIRE(bpf_prog_test_run_opts(netevent_program_fd, &bpf_opts) != 0);

// context smaller than netevent_md must be rejected
unsigned char smaller_ctx[sizeof(netevent_ctx_in) - 1];
bpf_opts.ctx_in = &smaller_ctx;
bpf_opts.ctx_size_in = sizeof(smaller_ctx);

REQUIRE(bpf_prog_test_run_opts(netevent_program_fd, &bpf_opts) != 0);

// Detach the program (link) from the attach point.
int link_fd = bpf_link__fd(netevent_monitor_link);
REQUIRE(link_fd != ebpf_fd_invalid);
REQUIRE(bpf_link_detach(link_fd) == 0);
REQUIRE(bpf_link__destroy(netevent_monitor_link) == 0);

// Free the ring buffer manager
ring_buffer__free(ring);

// Free the BPF object.
bpf_object__close(object);

// Stop and unload the neteventebpfext extension driver (NPI client).
REQUIRE(neteventebpfext_driver.stop() == true);
REQUIRE(neteventebpfext_driver.unload() == true);
}

0 comments on commit b375fbc

Please sign in to comment.