Register program type specific helper functions to uBPF in interpreted mode (#402)
* Register program type specific helper functions to uBPF in interpreted mode. Co-authored-by: Dave Thaler <dthaler@microsoft.com>
This commit is contained in:
Родитель
b917cc5ba8
Коммит
5519c26f5b
|
@ -52,23 +52,21 @@ static ebpf_helper_function_prototype_t _ebpf_map_helper_function_prototype[] =
|
||||||
{EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_OF_PROGRAMS, EBPF_ARGUMENT_TYPE_ANYTHING}},
|
{EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_OF_PROGRAMS, EBPF_ARGUMENT_TYPE_ANYTHING}},
|
||||||
};
|
};
|
||||||
|
|
||||||
static ebpf_program_info_t _ebpf_global_helper_program_info = {
|
static ebpf_program_info_t _ebpf_global_helper_program_info = {{"global_helper", NULL, {0}},
|
||||||
{"global_helper", NULL, {0}},
|
EBPF_COUNT_OF(_ebpf_map_helper_function_prototype),
|
||||||
EBPF_COUNT_OF(_ebpf_map_helper_function_prototype),
|
_ebpf_map_helper_function_prototype};
|
||||||
_ebpf_map_helper_function_prototype};
|
|
||||||
|
|
||||||
static const void* _ebpf_general_helpers[] = {
|
static const void* _ebpf_general_helpers[] = {NULL,
|
||||||
NULL,
|
(void*)&_ebpf_core_map_find_element,
|
||||||
(void*)&_ebpf_core_map_find_element,
|
(void*)&_ebpf_core_map_update_element,
|
||||||
(void*)&_ebpf_core_map_update_element,
|
(void*)&_ebpf_core_map_delete_element,
|
||||||
(void*)&_ebpf_core_map_delete_element,
|
(void*)&_ebpf_core_tail_call};
|
||||||
(void*)&_ebpf_core_tail_call};
|
|
||||||
|
|
||||||
static ebpf_extension_provider_t* _ebpf_global_helper_function_provider_context = NULL;
|
static ebpf_extension_provider_t* _ebpf_global_helper_function_provider_context = NULL;
|
||||||
static ebpf_helper_function_addresses_t _ebpf_global_helper_function_dispatch_table = {
|
static ebpf_helper_function_addresses_t _ebpf_global_helper_function_dispatch_table = {
|
||||||
EBPF_COUNT_OF(_ebpf_general_helpers), (uint64_t*)_ebpf_general_helpers};
|
EBPF_COUNT_OF(_ebpf_general_helpers), (uint64_t*)_ebpf_general_helpers};
|
||||||
static ebpf_program_data_t _ebpf_global_helper_function_program_data = {
|
static ebpf_program_data_t _ebpf_global_helper_function_program_data = {&_ebpf_global_helper_program_info,
|
||||||
&_ebpf_global_helper_program_info, &_ebpf_global_helper_function_dispatch_table};
|
&_ebpf_global_helper_function_dispatch_table};
|
||||||
|
|
||||||
static ebpf_extension_data_t _ebpf_global_helper_function_extension_data = {
|
static ebpf_extension_data_t _ebpf_global_helper_function_extension_data = {
|
||||||
EBPF_CORE_GLOBAL_HELPER_EXTENSION_VERSION,
|
EBPF_CORE_GLOBAL_HELPER_EXTENSION_VERSION,
|
||||||
|
@ -164,13 +162,7 @@ _ebpf_core_protocol_load_code(_In_ const ebpf_operation_load_code_request_t* req
|
||||||
code = (uint8_t*)request->code;
|
code = (uint8_t*)request->code;
|
||||||
code_length = request->header.length - EBPF_OFFSET_OF(ebpf_operation_load_code_request_t, code);
|
code_length = request->header.length - EBPF_OFFSET_OF(ebpf_operation_load_code_request_t, code);
|
||||||
|
|
||||||
if (request->code_type == EBPF_CODE_NATIVE) {
|
retval = ebpf_program_load_code(program, request->code_type, code, code_length);
|
||||||
retval = ebpf_program_load_machine_code(program, code, code_length);
|
|
||||||
} else {
|
|
||||||
retval =
|
|
||||||
ebpf_program_load_byte_code(program, (ebpf_instruction_t*)code, code_length / sizeof(ebpf_instruction_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval != EBPF_SUCCESS)
|
if (retval != EBPF_SUCCESS)
|
||||||
goto Done;
|
goto Done;
|
||||||
|
|
||||||
|
@ -216,12 +208,13 @@ _ebpf_core_protocol_resolve_helper(
|
||||||
if (return_value != EBPF_SUCCESS)
|
if (return_value != EBPF_SUCCESS)
|
||||||
goto Done;
|
goto Done;
|
||||||
|
|
||||||
for (helper_index = 0; helper_index < count_of_helpers; helper_index++) {
|
return_value = ebpf_program_set_helper_function_ids(program, count_of_helpers, request_helper_ids);
|
||||||
return_value = ebpf_program_get_helper_function_address(
|
if (return_value != EBPF_SUCCESS)
|
||||||
program, request_helper_ids[helper_index], &reply->address[helper_index]);
|
goto Done;
|
||||||
if (return_value != EBPF_SUCCESS)
|
|
||||||
goto Done;
|
return_value = ebpf_program_get_helper_function_addresses(program, count_of_helpers, reply->address);
|
||||||
}
|
if (return_value != EBPF_SUCCESS)
|
||||||
|
goto Done;
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
if (return_value == EBPF_SUCCESS)
|
if (return_value == EBPF_SUCCESS)
|
||||||
|
@ -662,9 +655,9 @@ static ebpf_result_t
|
||||||
_ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
|
_ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
|
||||||
{
|
{
|
||||||
ebpf_result_t retval;
|
ebpf_result_t retval;
|
||||||
const ebpf_utf8_string_t name = {
|
const ebpf_utf8_string_t name = {(uint8_t*)request->name,
|
||||||
(uint8_t*)request->name,
|
request->header.length -
|
||||||
request->header.length - EBPF_OFFSET_OF(ebpf_operation_update_pinning_request_t, name)};
|
EBPF_OFFSET_OF(ebpf_operation_update_pinning_request_t, name)};
|
||||||
ebpf_object_t* object = NULL;
|
ebpf_object_t* object = NULL;
|
||||||
|
|
||||||
if (name.length == 0) {
|
if (name.length == 0) {
|
||||||
|
|
|
@ -41,17 +41,25 @@ typedef struct _ebpf_program
|
||||||
ebpf_extension_client_t* program_info_client;
|
ebpf_extension_client_t* program_info_client;
|
||||||
const void* program_info_binding_context;
|
const void* program_info_binding_context;
|
||||||
const ebpf_extension_data_t* program_info_provider_data;
|
const ebpf_extension_data_t* program_info_provider_data;
|
||||||
uint32_t helper_function_count;
|
// Program type specific helper function count.
|
||||||
|
uint32_t provider_helper_function_count;
|
||||||
bool program_invalidated;
|
bool program_invalidated;
|
||||||
|
|
||||||
ebpf_trampoline_table_t* trampoline_table;
|
ebpf_trampoline_table_t* trampoline_table;
|
||||||
|
|
||||||
|
// Array of helper function ids referred by this program.
|
||||||
|
size_t helper_function_count;
|
||||||
|
uint32_t* helper_function_ids;
|
||||||
|
|
||||||
ebpf_epoch_work_item_t* cleanup_work_item;
|
ebpf_epoch_work_item_t* cleanup_work_item;
|
||||||
|
|
||||||
ebpf_list_entry_t links;
|
ebpf_list_entry_t links;
|
||||||
ebpf_lock_t links_lock;
|
ebpf_lock_t links_lock;
|
||||||
} ebpf_program_t;
|
} ebpf_program_t;
|
||||||
|
|
||||||
|
static ebpf_result_t
|
||||||
|
_ebpf_program_register_helpers(ebpf_program_t* program);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_ebpf_program_detach_links(_Inout_ ebpf_program_t* program)
|
_ebpf_program_detach_links(_Inout_ ebpf_program_t* program)
|
||||||
{
|
{
|
||||||
|
@ -70,6 +78,7 @@ _ebpf_program_program_info_provider_changed(
|
||||||
{
|
{
|
||||||
ebpf_result_t return_value;
|
ebpf_result_t return_value;
|
||||||
ebpf_program_t* program = (ebpf_program_t*)client_binding_context;
|
ebpf_program_t* program = (ebpf_program_t*)client_binding_context;
|
||||||
|
uint32_t* provider_helper_function_ids = NULL;
|
||||||
|
|
||||||
if (provider_data == NULL) {
|
if (provider_data == NULL) {
|
||||||
// Extension is detaching. Program will get invalidated.
|
// Extension is detaching. Program will get invalidated.
|
||||||
|
@ -85,31 +94,63 @@ _ebpf_program_program_info_provider_changed(
|
||||||
|
|
||||||
helper_function_addresses = program_data->helper_function_addresses;
|
helper_function_addresses = program_data->helper_function_addresses;
|
||||||
|
|
||||||
if ((program->helper_function_count > 0) &&
|
if ((program->provider_helper_function_count > 0) &&
|
||||||
(helper_function_addresses->helper_function_count != program->helper_function_count))
|
(helper_function_addresses->helper_function_count != program->provider_helper_function_count))
|
||||||
// A program info provider cannot modify helper function count upon reload.
|
// A program info provider cannot modify helper function count upon reload.
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
if (helper_function_addresses != NULL) {
|
if (helper_function_addresses != NULL) {
|
||||||
|
ebpf_program_info_t* program_info = program_data->program_info;
|
||||||
|
ebpf_helper_function_prototype_t* helper_prototypes = NULL;
|
||||||
|
ebpf_assert(program_info != NULL);
|
||||||
|
if (program_info->count_of_helpers != helper_function_addresses->helper_function_count) {
|
||||||
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
helper_prototypes = program_info->helper_prototype;
|
||||||
|
if (helper_prototypes == NULL) {
|
||||||
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
if (!program->trampoline_table) {
|
if (!program->trampoline_table) {
|
||||||
// Program info provider is being loaded for the first time. Allocate trampoline table.
|
// Program info provider is being loaded for the first time. Allocate trampoline table.
|
||||||
program->helper_function_count = helper_function_addresses->helper_function_count;
|
program->provider_helper_function_count = helper_function_addresses->helper_function_count;
|
||||||
return_value =
|
return_value =
|
||||||
ebpf_allocate_trampoline_table(program->helper_function_count, &program->trampoline_table);
|
ebpf_allocate_trampoline_table(program->provider_helper_function_count, &program->trampoline_table);
|
||||||
if (return_value != EBPF_SUCCESS)
|
if (return_value != EBPF_SUCCESS)
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
_Analysis_assume_(program->provider_helper_function_count > 0);
|
||||||
|
provider_helper_function_ids =
|
||||||
|
(uint32_t*)ebpf_allocate(sizeof(uint32_t) * program->provider_helper_function_count);
|
||||||
|
if (provider_helper_function_ids == NULL) {
|
||||||
|
return_value = EBPF_NO_MEMORY;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
for (uint32_t index = 0; index < program->provider_helper_function_count; index++)
|
||||||
|
provider_helper_function_ids[index] = helper_prototypes[index].helper_id;
|
||||||
// Update trampoline table with new helper function addresses.
|
// Update trampoline table with new helper function addresses.
|
||||||
return_value = ebpf_update_trampoline_table(program->trampoline_table, helper_function_addresses);
|
return_value = ebpf_update_trampoline_table(
|
||||||
|
program->trampoline_table,
|
||||||
|
program->provider_helper_function_count,
|
||||||
|
provider_helper_function_ids,
|
||||||
|
helper_function_addresses);
|
||||||
if (return_value != EBPF_SUCCESS)
|
if (return_value != EBPF_SUCCESS)
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
if (program->code_or_vm.vm != NULL) {
|
||||||
|
// Register with uBPF for interpreted mode.
|
||||||
|
return_value = _ebpf_program_register_helpers(program);
|
||||||
|
if (return_value != EBPF_SUCCESS)
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
program->program_info_binding_context = provider_binding_context;
|
program->program_info_binding_context = provider_binding_context;
|
||||||
program->program_info_provider_data = provider_data;
|
program->program_info_provider_data = provider_data;
|
||||||
Exit:
|
Exit:
|
||||||
|
ebpf_free(provider_helper_function_ids);
|
||||||
program->program_invalidated = (program->program_info_provider_data == NULL);
|
program->program_invalidated = (program->program_info_provider_data == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +215,8 @@ _ebpf_program_epoch_free(void* context)
|
||||||
|
|
||||||
ebpf_free_trampoline_table(program->trampoline_table);
|
ebpf_free_trampoline_table(program->trampoline_table);
|
||||||
|
|
||||||
|
ebpf_free(program->helper_function_ids);
|
||||||
|
|
||||||
ebpf_free(program->cleanup_work_item);
|
ebpf_free(program->cleanup_work_item);
|
||||||
ebpf_free(program);
|
ebpf_free(program);
|
||||||
}
|
}
|
||||||
|
@ -359,14 +402,15 @@ ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, size_t m
|
||||||
return EBPF_SUCCESS;
|
return EBPF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ebpf_result_t
|
static ebpf_result_t
|
||||||
ebpf_program_load_machine_code(ebpf_program_t* program, uint8_t* machine_code, size_t machine_code_size)
|
_ebpf_program_load_machine_code(
|
||||||
|
_Inout_ ebpf_program_t* program, _In_ const uint8_t* machine_code, size_t machine_code_size)
|
||||||
{
|
{
|
||||||
ebpf_result_t return_value;
|
ebpf_result_t return_value;
|
||||||
uint8_t* local_machine_code = NULL;
|
uint8_t* local_machine_code = NULL;
|
||||||
ebpf_memory_descriptor_t* local_code_memory_descriptor = NULL;
|
ebpf_memory_descriptor_t* local_code_memory_descriptor = NULL;
|
||||||
|
|
||||||
if (program->parameters.code_type != EBPF_CODE_NONE) {
|
if (program->parameters.code_type != EBPF_CODE_NATIVE) {
|
||||||
return_value = EBPF_INVALID_ARGUMENT;
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -385,7 +429,6 @@ ebpf_program_load_machine_code(ebpf_program_t* program, uint8_t* machine_code, s
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
program->parameters.code_type = EBPF_CODE_NATIVE;
|
|
||||||
program->code_or_vm.code.code_memory_descriptor = local_code_memory_descriptor;
|
program->code_or_vm.code.code_memory_descriptor = local_code_memory_descriptor;
|
||||||
program->code_or_vm.code.code_pointer = local_machine_code;
|
program->code_or_vm.code.code_pointer = local_machine_code;
|
||||||
local_code_memory_descriptor = NULL;
|
local_code_memory_descriptor = NULL;
|
||||||
|
@ -401,35 +444,59 @@ Done:
|
||||||
static ebpf_result_t
|
static ebpf_result_t
|
||||||
_ebpf_program_register_helpers(ebpf_program_t* program)
|
_ebpf_program_register_helpers(ebpf_program_t* program)
|
||||||
{
|
{
|
||||||
|
ebpf_result_t result = EBPF_SUCCESS;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
ebpf_program_data_t* general_helper_program_data =
|
ebpf_program_data_t* general_helper_program_data =
|
||||||
(ebpf_program_data_t*)program->general_helper_provider_data->data;
|
(ebpf_program_data_t*)program->general_helper_provider_data->data;
|
||||||
ebpf_helper_function_addresses_t* general_helper_function_addresses =
|
ebpf_helper_function_addresses_t* general_helper_function_addresses =
|
||||||
general_helper_program_data->helper_function_addresses;
|
general_helper_program_data->helper_function_addresses;
|
||||||
size_t count = general_helper_function_addresses->helper_function_count;
|
|
||||||
|
|
||||||
for (index = 0; index < count; index++) {
|
ebpf_assert(program->code_or_vm.vm != NULL);
|
||||||
const void* helper = (void*)general_helper_function_addresses->helper_function_address[index];
|
|
||||||
|
for (index = 0; index < program->helper_function_count; index++) {
|
||||||
|
uint32_t helper_function_id = program->helper_function_ids[index];
|
||||||
|
const void* helper = NULL;
|
||||||
|
if (helper_function_id > EBPF_MAX_GENERAL_HELPER_FUNCTION) {
|
||||||
|
// Get the program-type specific helper function address from the trampoline table.
|
||||||
|
result = ebpf_get_trampoline_helper_address(
|
||||||
|
program->trampoline_table,
|
||||||
|
(size_t)(helper_function_id - (EBPF_MAX_GENERAL_HELPER_FUNCTION + 1)),
|
||||||
|
(void**)&helper);
|
||||||
|
if (result != EBPF_SUCCESS)
|
||||||
|
goto Exit;
|
||||||
|
} else {
|
||||||
|
// Get the general helper function address.
|
||||||
|
if (helper_function_id > general_helper_function_addresses->helper_function_count) {
|
||||||
|
result = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
helper = (void*)general_helper_function_addresses->helper_function_address[helper_function_id];
|
||||||
|
}
|
||||||
if (helper == NULL)
|
if (helper == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ubpf_register(program->code_or_vm.vm, (unsigned int)index, NULL, (void*)helper) < 0)
|
if (ubpf_register(program->code_or_vm.vm, (unsigned int)index, NULL, (void*)helper) < 0) {
|
||||||
return EBPF_INVALID_ARGUMENT;
|
result = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return EBPF_SUCCESS;
|
|
||||||
|
Exit:
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ebpf_result_t
|
static ebpf_result_t
|
||||||
ebpf_program_load_byte_code(ebpf_program_t* program, ebpf_instruction_t* instructions, size_t instruction_count)
|
_ebpf_program_load_byte_code(
|
||||||
|
_Inout_ ebpf_program_t* program, _In_ const ebpf_instruction_t* instructions, size_t instruction_count)
|
||||||
{
|
{
|
||||||
ebpf_result_t return_value;
|
ebpf_result_t return_value;
|
||||||
char* error_message = NULL;
|
char* error_message = NULL;
|
||||||
if (program->parameters.code_type != EBPF_CODE_NONE) {
|
|
||||||
|
if (program->parameters.code_type != EBPF_CODE_EBPF) {
|
||||||
return_value = EBPF_INVALID_ARGUMENT;
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
program->parameters.code_type = EBPF_CODE_EBPF;
|
|
||||||
program->code_or_vm.vm = ubpf_create();
|
program->code_or_vm.vm = ubpf_create();
|
||||||
if (!program->code_or_vm.vm) {
|
if (!program->code_or_vm.vm) {
|
||||||
return_value = EBPF_NO_MEMORY;
|
return_value = EBPF_NO_MEMORY;
|
||||||
|
@ -465,6 +532,22 @@ Done:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ebpf_result_t
|
||||||
|
ebpf_program_load_code(
|
||||||
|
_Inout_ ebpf_program_t* program, ebpf_code_type_t code_type, _In_ const uint8_t* code, size_t code_size)
|
||||||
|
{
|
||||||
|
ebpf_result_t result = EBPF_SUCCESS;
|
||||||
|
program->parameters.code_type = code_type;
|
||||||
|
if (program->parameters.code_type == EBPF_CODE_NATIVE)
|
||||||
|
result = _ebpf_program_load_machine_code(program, code, code_size);
|
||||||
|
else if (program->parameters.code_type == EBPF_CODE_EBPF)
|
||||||
|
result = _ebpf_program_load_byte_code(
|
||||||
|
program, (const ebpf_instruction_t*)code, code_size / sizeof(ebpf_instruction_t));
|
||||||
|
else
|
||||||
|
result = EBPF_INVALID_ARGUMENT;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out_ uint32_t* result)
|
ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out_ uint32_t* result)
|
||||||
{
|
{
|
||||||
|
@ -488,8 +571,8 @@ ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ebpf_result_t
|
static ebpf_result_t
|
||||||
ebpf_program_get_helper_function_address(
|
_ebpf_program_get_helper_function_address(
|
||||||
_In_ const ebpf_program_t* program, const uint32_t helper_function_id, uint64_t* address)
|
_In_ const ebpf_program_t* program, const uint32_t helper_function_id, uint64_t* address)
|
||||||
{
|
{
|
||||||
if (helper_function_id > EBPF_MAX_GENERAL_HELPER_FUNCTION) {
|
if (helper_function_id > EBPF_MAX_GENERAL_HELPER_FUNCTION) {
|
||||||
|
@ -520,6 +603,59 @@ ebpf_program_get_helper_function_address(
|
||||||
return EBPF_SUCCESS;
|
return EBPF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ebpf_result_t
|
||||||
|
ebpf_program_get_helper_function_addresses(
|
||||||
|
_In_ const ebpf_program_t* program, size_t addresses_count, _Out_writes_(addresses_count) uint64_t* addresses)
|
||||||
|
{
|
||||||
|
ebpf_result_t result = EBPF_SUCCESS;
|
||||||
|
|
||||||
|
if (program->helper_function_count > addresses_count) {
|
||||||
|
result = EBPF_INSUFFICIENT_BUFFER;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t index = 0; index < program->helper_function_count; index++) {
|
||||||
|
result =
|
||||||
|
_ebpf_program_get_helper_function_address(program, program->helper_function_ids[index], &addresses[index]);
|
||||||
|
if (result != EBPF_SUCCESS)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ebpf_result_t
|
||||||
|
ebpf_program_set_helper_function_ids(
|
||||||
|
_Inout_ ebpf_program_t* program,
|
||||||
|
const size_t helper_function_count,
|
||||||
|
_In_reads_(helper_function_count) const uint32_t* helper_function_ids)
|
||||||
|
{
|
||||||
|
ebpf_result_t result = EBPF_SUCCESS;
|
||||||
|
|
||||||
|
if (program->helper_function_ids != NULL) {
|
||||||
|
// Helper function IDs already set.
|
||||||
|
result = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_function_count == 0)
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
|
program->helper_function_count = helper_function_count;
|
||||||
|
program->helper_function_ids = ebpf_allocate(sizeof(uint32_t) * helper_function_count);
|
||||||
|
if (program->helper_function_ids == NULL) {
|
||||||
|
result = EBPF_NO_MEMORY;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t index = 0; index < helper_function_count; index++)
|
||||||
|
program->helper_function_ids[index] = helper_function_ids[index];
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ebpf_result_t
|
ebpf_result_t
|
||||||
ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_program_info_t** program_info)
|
ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_program_info_t** program_info)
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,31 +109,20 @@ extern "C"
|
||||||
ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, size_t maps_count);
|
ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, size_t maps_count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load a block of machine code into the program instance.
|
* @brief Load a block of eBPF code into the program instance.
|
||||||
*
|
*
|
||||||
* @param[in] program Program instance to load the machine code into.
|
* @param[in, out] program Program instance to load the eBPF code into.
|
||||||
* @param[in] machine_code Pointer to memory containing the machine code.
|
* @param[in] code_type Specifies whether eBPF code is JIT compiled or byte code.
|
||||||
* @param[in] machine_code_size Size of the memory block containing the machine
|
* @param[in] code Pointer to memory containing the eBPF code.
|
||||||
|
* @param[in] machine_size Size of the memory block containing the eBPF
|
||||||
* code.
|
* code.
|
||||||
* @retval EBPF_SUCCESS The operation was successful.
|
* @retval EBPF_SUCCESS The operation was successful.
|
||||||
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
||||||
* program instance.
|
* program instance.
|
||||||
*/
|
*/
|
||||||
ebpf_result_t
|
ebpf_result_t
|
||||||
ebpf_program_load_machine_code(ebpf_program_t* program, uint8_t* machine_code, size_t machine_code_size);
|
ebpf_program_load_code(
|
||||||
|
_Inout_ ebpf_program_t* program, ebpf_code_type_t code_type, _In_ const uint8_t* code, size_t code_size);
|
||||||
/**
|
|
||||||
* @brief Load a block of eBPF instructions into the program instance.
|
|
||||||
*
|
|
||||||
* @param[in] program Program instance to load the byte code into.
|
|
||||||
* @param[in] instructions Pointer to array of eBPF instructions.
|
|
||||||
* @param[in] instruction_count Count of eBPF instructions to load.
|
|
||||||
* @retval EBPF_SUCCESS The operation was successful.
|
|
||||||
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
||||||
* program instance.
|
|
||||||
*/
|
|
||||||
ebpf_result_t
|
|
||||||
ebpf_program_load_byte_code(ebpf_program_t* program, ebpf_instruction_t* instructions, size_t instruction_count);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Invoke an ebpf_program_t instance.
|
* @brief Invoke an ebpf_program_t instance.
|
||||||
|
@ -146,17 +135,39 @@ extern "C"
|
||||||
ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out_ uint32_t* result);
|
ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out_ uint32_t* result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the address of a helper function.
|
* @brief Store the helper function IDs that are used by the eBPF program in an array
|
||||||
|
* inside the program object. The array index is the helper function ID to be used by
|
||||||
|
* uBPF whereas the array value is the actual helper ID.
|
||||||
*
|
*
|
||||||
* @param[in] program Program object to query this on.
|
* @param[in, out] program Program object to query this on.
|
||||||
* @param[in] helper_function_id Helper function ID to look up.
|
* @param[in] helper_function_count Count of helper functions.
|
||||||
* @param[out] address Address of the helper function.
|
* @param[in] helper_function_ids Array of helper function IDs to store.
|
||||||
* @retval EBPF_SUCCESS The operation was successful.
|
* @retval EBPF_SUCCESS The operation was successful.
|
||||||
* @retval EBPF_INVALID_ARGUMENT The helper_function_id is not valid.
|
* @retval EBPF_INVALID_ARGUMENT The helper function IDs array is already populated.
|
||||||
|
* @retval EBPF_NO_MEMORY Could not allocate array of helper function IDs.
|
||||||
*/
|
*/
|
||||||
ebpf_result_t
|
ebpf_result_t
|
||||||
ebpf_program_get_helper_function_address(
|
ebpf_program_set_helper_function_ids(
|
||||||
_In_ const ebpf_program_t* program, const uint32_t helper_function_id, uint64_t* address);
|
_Inout_ ebpf_program_t* program,
|
||||||
|
const size_t helper_function_count,
|
||||||
|
_In_reads_(helper_function_count) const uint32_t* helper_function_ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the address of a helper functions referred to by the program. Assumes
|
||||||
|
* ebpf_program_set_helper_function_ids has already been invoked on the program object.
|
||||||
|
*
|
||||||
|
* @param[in] program Program object to query this on.
|
||||||
|
* @param[in] addresses_count Length of caller supplied output array.
|
||||||
|
* @param[out] address Caller supplied output array where the addresses of the helper functions are written to.
|
||||||
|
* @retval EBPF_SUCCESS The operation was successful.
|
||||||
|
* @retval EBPF_INSUFFICIENT_BUFFER Output array is insufficient.
|
||||||
|
* @retval EBPF_INVALID_ARGUMENT At least one helper function id is not valid.
|
||||||
|
*/
|
||||||
|
ebpf_result_t
|
||||||
|
ebpf_program_get_helper_function_addresses(
|
||||||
|
_In_ const ebpf_program_t* program,
|
||||||
|
const size_t addresses_count,
|
||||||
|
_Out_writes_(addresses_count) uint64_t* addresses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Attach a link object to an eBPF program.
|
* @brief Attach a link object to an eBPF program.
|
||||||
|
|
|
@ -125,6 +125,7 @@ TEST_CASE("map_crud_operations_hash_per_cpu", "[execution_context]")
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_FUNCTION_RETURN 42
|
#define TEST_FUNCTION_RETURN 42
|
||||||
|
#define TOTAL_HELPER_COUNT 3
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
test_function()
|
test_function()
|
||||||
|
@ -179,29 +180,35 @@ TEST_CASE("program", "[execution_context]")
|
||||||
ebpf_result_t (*test_function)();
|
ebpf_result_t (*test_function)();
|
||||||
auto provider_function1 = []() { return (ebpf_result_t)TEST_FUNCTION_RETURN; };
|
auto provider_function1 = []() { return (ebpf_result_t)TEST_FUNCTION_RETURN; };
|
||||||
ebpf_result_t (*function_pointer1)() = provider_function1;
|
ebpf_result_t (*function_pointer1)() = provider_function1;
|
||||||
|
uint32_t test_function_ids[] = {(EBPF_MAX_GENERAL_HELPER_FUNCTION + 1)};
|
||||||
const void* helper_functions[] = {(void*)function_pointer1};
|
const void* helper_functions[] = {(void*)function_pointer1};
|
||||||
ebpf_helper_function_addresses_t helper_function_addresses = {
|
ebpf_helper_function_addresses_t helper_function_addresses = {EBPF_COUNT_OF(helper_functions),
|
||||||
EBPF_COUNT_OF(helper_functions), (uint64_t*)helper_functions};
|
(uint64_t*)helper_functions};
|
||||||
|
|
||||||
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
|
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
|
||||||
REQUIRE(ebpf_update_trampoline_table(table, &helper_function_addresses) == EBPF_SUCCESS);
|
REQUIRE(
|
||||||
|
ebpf_update_trampoline_table(
|
||||||
|
table, EBPF_COUNT_OF(test_function_ids), test_function_ids, &helper_function_addresses) == EBPF_SUCCESS);
|
||||||
REQUIRE(ebpf_get_trampoline_function(table, 0, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
|
REQUIRE(ebpf_get_trampoline_function(table, 0, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// Size of the actual function is unknown, but we know the allocation is on page granularity.
|
// Size of the actual function is unknown, but we know the allocation is on page granularity.
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
ebpf_program_load_machine_code(program.get(), reinterpret_cast<uint8_t*>(test_function), PAGE_SIZE) ==
|
ebpf_program_load_code(program.get(), EBPF_CODE_NATIVE, reinterpret_cast<uint8_t*>(test_function), PAGE_SIZE) ==
|
||||||
EBPF_SUCCESS);
|
EBPF_SUCCESS);
|
||||||
uint32_t result = 0;
|
uint32_t result = 0;
|
||||||
bind_md_t ctx{0};
|
bind_md_t ctx{0};
|
||||||
ebpf_program_invoke(program.get(), &ctx, &result);
|
ebpf_program_invoke(program.get(), &ctx, &result);
|
||||||
REQUIRE(result == TEST_FUNCTION_RETURN);
|
REQUIRE(result == TEST_FUNCTION_RETURN);
|
||||||
|
|
||||||
uint64_t address = 0;
|
uint64_t addresses[TOTAL_HELPER_COUNT] = {};
|
||||||
REQUIRE(ebpf_program_get_helper_function_address(program.get(), 1, &address) == EBPF_SUCCESS);
|
uint32_t helper_function_ids[] = {1, 0, 2};
|
||||||
REQUIRE(address != 0);
|
REQUIRE(
|
||||||
REQUIRE(ebpf_program_get_helper_function_address(program.get(), 0, &address) == EBPF_SUCCESS);
|
ebpf_program_set_helper_function_ids(program.get(), EBPF_COUNT_OF(helper_function_ids), helper_function_ids) ==
|
||||||
REQUIRE(address == 0);
|
EBPF_SUCCESS);
|
||||||
REQUIRE(ebpf_program_get_helper_function_address(program.get(), 0xFFFF, &address) == EBPF_INVALID_ARGUMENT);
|
REQUIRE(
|
||||||
REQUIRE(address == 0);
|
ebpf_program_get_helper_function_addresses(program.get(), EBPF_COUNT_OF(helper_function_ids), addresses) ==
|
||||||
ebpf_free_trampoline_table(table);
|
EBPF_SUCCESS);
|
||||||
|
REQUIRE(addresses[0] != 0);
|
||||||
|
REQUIRE(addresses[1] == 0);
|
||||||
|
REQUIRE(addresses[2] != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -698,14 +698,19 @@ extern "C"
|
||||||
* @brief Populate the function pointers in a trampoline table.
|
* @brief Populate the function pointers in a trampoline table.
|
||||||
*
|
*
|
||||||
* @param[in] trampoline_table Trampoline table to populate.
|
* @param[in] trampoline_table Trampoline table to populate.
|
||||||
|
* @param[in] helper_function_count Count of helper functions.
|
||||||
|
* @param[in] helper_function_ids Array of helper function IDs.
|
||||||
* @param[in] dispatch_table Dispatch table to populate from.
|
* @param[in] dispatch_table Dispatch table to populate from.
|
||||||
* @retval EBPF_SUCCESS The operation was successful.
|
* @retval EBPF_SUCCESS The operation was successful.
|
||||||
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
||||||
* operation.
|
* operation.
|
||||||
|
* @retval EBPF_INVALID_ARGUMENT An invalid argument was supplied.
|
||||||
*/
|
*/
|
||||||
ebpf_result_t
|
ebpf_result_t
|
||||||
ebpf_update_trampoline_table(
|
ebpf_update_trampoline_table(
|
||||||
_Inout_ ebpf_trampoline_table_t* trampoline_table,
|
_Inout_ ebpf_trampoline_table_t* trampoline_table,
|
||||||
|
uint32_t helper_function_count,
|
||||||
|
_In_reads_(helper_function_count) const uint32_t* helper_function_ids,
|
||||||
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses);
|
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -723,6 +728,21 @@ extern "C"
|
||||||
ebpf_get_trampoline_function(
|
ebpf_get_trampoline_function(
|
||||||
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** function);
|
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** function);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the address of the helper function from the trampoline table entry.
|
||||||
|
*
|
||||||
|
* @param[in] trampoline_table Trampoline table to query.
|
||||||
|
* @param[in] index Index of trampoline table entry.
|
||||||
|
* @param[out] helper_address Pointer to memory that contains the address to helper function on success.
|
||||||
|
* @retval EBPF_SUCCESS The operation was successful.
|
||||||
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
||||||
|
* operation.
|
||||||
|
* @retval EBPF_INVALID_ARGUMENT An invalid argument was supplied.
|
||||||
|
*/
|
||||||
|
ebpf_result_t
|
||||||
|
ebpf_get_trampoline_helper_address(
|
||||||
|
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** helper_address);
|
||||||
|
|
||||||
typedef struct _ebpf_program_info ebpf_program_info_t;
|
typedef struct _ebpf_program_info ebpf_program_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,6 +63,8 @@ ebpf_free_trampoline_table(_Frees_ptr_opt_ ebpf_trampoline_table_t* trampoline_t
|
||||||
ebpf_result_t
|
ebpf_result_t
|
||||||
ebpf_update_trampoline_table(
|
ebpf_update_trampoline_table(
|
||||||
_Inout_ ebpf_trampoline_table_t* trampoline_table,
|
_Inout_ ebpf_trampoline_table_t* trampoline_table,
|
||||||
|
uint32_t helper_function_count,
|
||||||
|
_In_reads_(helper_function_count) const uint32_t* helper_function_ids,
|
||||||
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses)
|
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses)
|
||||||
{
|
{
|
||||||
#if defined(_AMD64_)
|
#if defined(_AMD64_)
|
||||||
|
@ -70,6 +72,8 @@ ebpf_update_trampoline_table(
|
||||||
size_t function_count = helper_function_addresses->helper_function_count;
|
size_t function_count = helper_function_addresses->helper_function_count;
|
||||||
ebpf_trampoline_entry_t* local_entries;
|
ebpf_trampoline_entry_t* local_entries;
|
||||||
ebpf_result_t return_value;
|
ebpf_result_t return_value;
|
||||||
|
size_t index;
|
||||||
|
uint32_t helper_index;
|
||||||
|
|
||||||
if (function_count != trampoline_table->entry_count) {
|
if (function_count != trampoline_table->entry_count) {
|
||||||
return_value = EBPF_INVALID_ARGUMENT;
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
|
@ -88,12 +92,18 @@ ebpf_update_trampoline_table(
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index;
|
for (helper_index = 0; helper_index < helper_function_count; helper_index++) {
|
||||||
for (index = 0; index < trampoline_table->entry_count; index++) {
|
ebpf_assert(helper_function_ids[helper_index] > EBPF_MAX_GENERAL_HELPER_FUNCTION);
|
||||||
|
_Analysis_assume_(helper_function_ids[helper_index] > EBPF_MAX_GENERAL_HELPER_FUNCTION);
|
||||||
|
index = helper_function_ids[helper_index] - (EBPF_MAX_GENERAL_HELPER_FUNCTION + 1);
|
||||||
|
if (index > trampoline_table->entry_count) {
|
||||||
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
local_entries[index].load_rax = 0xa148;
|
local_entries[index].load_rax = 0xa148;
|
||||||
local_entries[index].indirect_address = &local_entries[index].address;
|
local_entries[index].indirect_address = &local_entries[index].address;
|
||||||
local_entries[index].jmp_rax = 0xe0ff;
|
local_entries[index].jmp_rax = 0xe0ff;
|
||||||
local_entries[index].address = (void*)helper_function_addresses->helper_function_address[index];
|
local_entries[index].address = (void*)helper_function_addresses->helper_function_address[helper_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
|
@ -130,3 +140,29 @@ ebpf_get_trampoline_function(_In_ const ebpf_trampoline_table_t* trampoline_tabl
|
||||||
Exit:
|
Exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ebpf_result_t
|
||||||
|
ebpf_get_trampoline_helper_address(
|
||||||
|
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** helper_address)
|
||||||
|
{
|
||||||
|
ebpf_trampoline_entry_t* local_entries;
|
||||||
|
ebpf_result_t return_value;
|
||||||
|
|
||||||
|
if (index >= trampoline_table->entry_count) {
|
||||||
|
return_value = EBPF_INVALID_ARGUMENT;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_entries =
|
||||||
|
(ebpf_trampoline_entry_t*)ebpf_memory_descriptor_get_base_address(trampoline_table->memory_descriptor);
|
||||||
|
if (!local_entries) {
|
||||||
|
return_value = EBPF_NO_MEMORY;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*helper_address = local_entries[index].address;
|
||||||
|
|
||||||
|
return_value = EBPF_SUCCESS;
|
||||||
|
Exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
|
@ -331,6 +331,7 @@ TEST_CASE("trampoline_test", "[platform]")
|
||||||
auto provider_function1 = []() { return EBPF_SUCCESS; };
|
auto provider_function1 = []() { return EBPF_SUCCESS; };
|
||||||
ebpf_result_t (*function_pointer1)() = provider_function1;
|
ebpf_result_t (*function_pointer1)() = provider_function1;
|
||||||
const void* helper_functions1[] = {(void*)function_pointer1};
|
const void* helper_functions1[] = {(void*)function_pointer1};
|
||||||
|
const uint32_t provider_helper_function_ids[] = {(uint32_t)(EBPF_MAX_GENERAL_HELPER_FUNCTION + 1)};
|
||||||
ebpf_helper_function_addresses_t helper_function_addresses1 = {
|
ebpf_helper_function_addresses_t helper_function_addresses1 = {
|
||||||
EBPF_COUNT_OF(helper_functions1), (uint64_t*)helper_functions1};
|
EBPF_COUNT_OF(helper_functions1), (uint64_t*)helper_functions1};
|
||||||
|
|
||||||
|
@ -341,13 +342,23 @@ TEST_CASE("trampoline_test", "[platform]")
|
||||||
EBPF_COUNT_OF(helper_functions1), (uint64_t*)helper_functions2};
|
EBPF_COUNT_OF(helper_functions1), (uint64_t*)helper_functions2};
|
||||||
|
|
||||||
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
|
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
|
||||||
REQUIRE(ebpf_update_trampoline_table(table, &helper_function_addresses1) == EBPF_SUCCESS);
|
REQUIRE(
|
||||||
|
ebpf_update_trampoline_table(
|
||||||
|
table,
|
||||||
|
EBPF_COUNT_OF(provider_helper_function_ids),
|
||||||
|
provider_helper_function_ids,
|
||||||
|
&helper_function_addresses1) == EBPF_SUCCESS);
|
||||||
REQUIRE(ebpf_get_trampoline_function(table, 0, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
|
REQUIRE(ebpf_get_trampoline_function(table, 0, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// Verify that the trampoline function invokes the provider function
|
// Verify that the trampoline function invokes the provider function
|
||||||
REQUIRE(test_function() == EBPF_SUCCESS);
|
REQUIRE(test_function() == EBPF_SUCCESS);
|
||||||
|
|
||||||
REQUIRE(ebpf_update_trampoline_table(table, &helper_function_addresses2) == EBPF_SUCCESS);
|
REQUIRE(
|
||||||
|
ebpf_update_trampoline_table(
|
||||||
|
table,
|
||||||
|
EBPF_COUNT_OF(provider_helper_function_ids),
|
||||||
|
provider_helper_function_ids,
|
||||||
|
&helper_function_addresses2) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// Verify that the trampoline function now invokes the new provider function
|
// Verify that the trampoline function now invokes the new provider function
|
||||||
REQUIRE(test_function() == EBPF_OBJECT_ALREADY_EXISTS);
|
REQUIRE(test_function() == EBPF_OBJECT_ALREADY_EXISTS);
|
||||||
|
|
|
@ -334,11 +334,12 @@ ebpf_verify_and_load_program(
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> helper_id_adddress;
|
||||||
|
result = _build_helper_id_to_address_map(program_handle, byte_code_buffer, helper_id_adddress);
|
||||||
|
if (result != EBPF_SUCCESS)
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
if (execution_type == EBPF_EXECUTION_JIT) {
|
if (execution_type == EBPF_EXECUTION_JIT) {
|
||||||
std::vector<uint64_t> helper_id_adddress;
|
|
||||||
result = _build_helper_id_to_address_map(program_handle, byte_code_buffer, helper_id_adddress);
|
|
||||||
if (result != EBPF_SUCCESS)
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
ebpf_code_buffer_t machine_code(MAX_CODE_SIZE_IN_BYTES);
|
ebpf_code_buffer_t machine_code(MAX_CODE_SIZE_IN_BYTES);
|
||||||
size_t machine_code_size = machine_code.size();
|
size_t machine_code_size = machine_code.size();
|
||||||
|
|
|
@ -49,7 +49,8 @@ _program_load_helper(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("test_test", "[test_test]")
|
void
|
||||||
|
sample_ebpf_ext_test(ebpf_execution_type_t execution_type)
|
||||||
{
|
{
|
||||||
ebpf_result_t result;
|
ebpf_result_t result;
|
||||||
struct bpf_object* object = nullptr;
|
struct bpf_object* object = nullptr;
|
||||||
|
@ -70,7 +71,7 @@ TEST_CASE("test_test", "[test_test]")
|
||||||
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
||||||
|
|
||||||
result =
|
result =
|
||||||
_program_load_helper("test_sample_ebpf.o", &EBPF_PROGRAM_TYPE_SAMPLE, EBPF_EXECUTION_JIT, &object, &program_fd);
|
_program_load_helper("test_sample_ebpf.o", &EBPF_PROGRAM_TYPE_SAMPLE, execution_type, &object, &program_fd);
|
||||||
|
|
||||||
REQUIRE(result == EBPF_SUCCESS);
|
REQUIRE(result == EBPF_SUCCESS);
|
||||||
REQUIRE(program_fd > 0);
|
REQUIRE(program_fd > 0);
|
||||||
|
@ -129,3 +130,7 @@ TEST_CASE("test_test", "[test_test]")
|
||||||
|
|
||||||
ebpf_api_terminate();
|
ebpf_api_terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("jit_test", "[test_test]") { sample_ebpf_ext_test(EBPF_EXECUTION_JIT); }
|
||||||
|
|
||||||
|
TEST_CASE("interpret_test", "[test_test]") { sample_ebpf_ext_test(EBPF_EXECUTION_INTERPRET); }
|
Загрузка…
Ссылка в новой задаче