Skip to content
Draft

fix #4791

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion .github/workflows/reusable-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,29 @@ jobs:
with:
msbuild-architecture: x64

- name: Cache chocolatey packages
if: steps.skip_check.outputs.should_skip != 'true'
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684
env:
cache-name: cache-choco-packages
with:
path: C:\ProgramData\chocolatey
key: ${{ runner.os }}-choco-llvm-18.1.8

- name: Install LLVM 18.1.8
if: steps.skip_check.outputs.should_skip != 'true'
run: |
# Install LLVM 18.1.8 to ensure consistent version across runners
try {
choco install llvm --version=18.1.8 --allow-downgrade -y --force
# Add installed LLVM to PATH first so it takes precedence
echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
Write-Host "Successfully installed LLVM 18.1.8"
} catch {
Write-Warning "Failed to install LLVM 18.1.8 via chocolatey: $($_.Exception.Message)"
Write-Host "Continuing with pre-installed LLVM version"
}

- name: Add Visual Studio LLVM to path
if: steps.skip_check.outputs.should_skip != 'true'
run: |
Expand All @@ -158,7 +181,7 @@ jobs:
if: steps.skip_check.outputs.should_skip != 'true'
shell: cmd
run:
'"c:\Program Files\llvm\bin\clang.exe" --version'
'"C:\Program Files\LLVM\bin\clang.exe" --version'

- name: Cache nuget packages
if: steps.skip_check.outputs.should_skip != 'true'
Expand Down
89 changes: 68 additions & 21 deletions libs/execution_context/ebpf_maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ typedef struct _ebpf_map_metadata_table
void (*delete_map)(_In_ _Post_invalid_ ebpf_core_map_t* map);
ebpf_result_t (*associate_program)(_Inout_ ebpf_map_t* map, _In_ const ebpf_program_t* program);
ebpf_result_t (*find_entry)(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, bool delete_on_success, _Outptr_ uint8_t** data);
_Inout_ ebpf_core_map_t* map,
_In_opt_ const uint8_t* key,
bool delete_on_success,
bool helper_function,
_Outptr_ uint8_t** data);
ebpf_core_object_t* (*get_object_from_entry)(_Inout_ ebpf_core_map_t* map, _In_ const uint8_t* key);
ebpf_result_t (*update_entry)(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, _In_ const uint8_t* value, ebpf_map_option_t option);
Expand Down Expand Up @@ -524,9 +528,15 @@ _delete_array_map(_In_ _Post_invalid_ ebpf_core_map_t* map)

static ebpf_result_t
_find_array_map_entry(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, bool delete_on_success, _Outptr_ uint8_t** data)
_Inout_ ebpf_core_map_t* map,
_In_opt_ const uint8_t* key,
bool delete_on_success,
bool helper_function,
_Outptr_ uint8_t** data)
{
uint32_t key_value;
UNREFERENCED_PARAMETER(helper_function);

if (!map || !key || delete_on_success) {
return EBPF_INVALID_ARGUMENT;
}
Expand All @@ -544,11 +554,15 @@ _find_array_map_entry(

static ebpf_result_t
_find_array_map_entry_with_reference(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, bool delete_on_success, _Outptr_ uint8_t** data)
_Inout_ ebpf_core_map_t* map,
_In_opt_ const uint8_t* key,
bool delete_on_success,
bool helper_function,
_Outptr_ uint8_t** data)
{
ebpf_assert(map->ebpf_map_definition.value_size == sizeof(ebpf_id_t));

ebpf_result_t result = _find_array_map_entry(map, key, delete_on_success, data);
ebpf_result_t result = _find_array_map_entry(map, key, delete_on_success, helper_function, data);

if (result != EBPF_SUCCESS) {
return result;
Expand Down Expand Up @@ -960,7 +974,7 @@ _delete_array_map_entry_with_reference(
uint8_t* entry;
ebpf_core_object_map_t* object_map = EBPF_FROM_FIELD(ebpf_core_object_map_t, core_map, map);
ebpf_lock_state_t lock_state = ebpf_lock_lock(&object_map->lock);
result = _find_array_map_entry(map, key, false, &entry);
result = _find_array_map_entry(map, key, false, true, &entry);
if (result == EBPF_SUCCESS) {
ebpf_id_t id = *(ebpf_id_t*)entry;
if (id) {
Expand Down Expand Up @@ -1001,7 +1015,7 @@ _get_object_from_array_map_entry(_Inout_ ebpf_core_map_t* map, _In_ const uint8_

ebpf_core_object_t* object = NULL;
uint8_t* value = NULL;
if (_find_array_map_entry(map, (uint8_t*)&index, false, &value) == EBPF_SUCCESS) {
if (_find_array_map_entry(map, (uint8_t*)&index, false, true, &value) == EBPF_SUCCESS) {
ebpf_id_t id = *(ebpf_id_t*)&map->data[index * map->ebpf_map_definition.value_size];
ebpf_object_type_t value_type =
(map->ebpf_map_definition.type == BPF_MAP_TYPE_PROG_ARRAY) ? EBPF_OBJECT_PROGRAM : EBPF_OBJECT_MAP;
Expand Down Expand Up @@ -1339,12 +1353,21 @@ _uninitialize_lru_entry(_Inout_ ebpf_core_lru_map_t* map, _Inout_ ebpf_lru_entry

static void
_lru_hash_table_notification(
_In_ void* context, _In_ ebpf_hash_table_notification_type_t type, _In_ const uint8_t* key, _In_ uint8_t* value)
_In_ void* context,
_In_ ebpf_hash_table_notification_type_t type,
_In_opt_ const void* operation_context,
_In_ const uint8_t* key,
_In_ uint8_t* value)
{
ebpf_core_lru_map_t* lru_map = (ebpf_core_lru_map_t*)context;
ebpf_lru_entry_t* entry = (ebpf_lru_entry_t*)_get_supplemental_value(&lru_map->core_map, value);
// Map the current CPU to a partition.
uint32_t partition = ebpf_get_current_cpu() % lru_map->partition_count;
bool helper_function = true;
if (operation_context) {
helper_function = *(bool*)operation_context;
}

switch (type) {
case EBPF_HASH_TABLE_NOTIFICATION_TYPE_ALLOCATE:
_initialize_lru_entry(lru_map, entry, partition, key);
Expand All @@ -1353,7 +1376,12 @@ _lru_hash_table_notification(
_uninitialize_lru_entry(lru_map, entry);
break;
case EBPF_HASH_TABLE_NOTIFICATION_TYPE_USE:
_insert_into_hot_list(lru_map, partition, entry);
if (helper_function) {
// Only when the entry is accessed via helper function, insert it into the hot list.
// This is to avoid the hot list from being filled with entries that are accessed via the user mode APIs.
_insert_into_hot_list(lru_map, partition, entry);
}
// _insert_into_hot_list(lru_map, partition, entry);
break;
default:
ebpf_assert(!"Invalid notification type");
Expand Down Expand Up @@ -1567,14 +1595,19 @@ _reap_oldest_map_entry(_Inout_ ebpf_core_map_t* map)

static ebpf_result_t
_find_hash_map_entry(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, bool delete_on_success, _Outptr_ uint8_t** data)
_Inout_ ebpf_core_map_t* map,
_In_opt_ const uint8_t* key,
bool delete_on_success,
bool helper_function,
_Outptr_ uint8_t** data)
{
uint8_t* value = NULL;
if (!map || !key) {
return EBPF_INVALID_ARGUMENT;
}

if (ebpf_hash_table_find((ebpf_hash_table_t*)map->data, key, &value) != EBPF_SUCCESS) {
if (ebpf_hash_table_find_with_context((ebpf_hash_table_t*)map->data, key, &helper_function, &value) !=
EBPF_SUCCESS) {
value = NULL;
}

Expand Down Expand Up @@ -1604,7 +1637,7 @@ _get_object_from_hash_map_entry(_In_ ebpf_core_map_t* map, _In_ const uint8_t* k
{
ebpf_core_object_t* object = NULL;
uint8_t* value = NULL;
if (_find_hash_map_entry(map, key, false, &value) == EBPF_SUCCESS) {
if (_find_hash_map_entry(map, key, false, true, &value) == EBPF_SUCCESS) {
ebpf_id_t id = *(ebpf_id_t*)value;
if (ebpf_object_pointer_by_id(id, EBPF_OBJECT_MAP, &object) != EBPF_SUCCESS) {
object = NULL;
Expand Down Expand Up @@ -1772,7 +1805,7 @@ _delete_map_hash_map_entry(_Inout_ ebpf_core_map_t* map, _In_ const uint8_t* key
ebpf_lock_state_t lock_state = ebpf_lock_lock(&object_map->lock);

uint8_t* value = NULL;
ebpf_result_t result = _find_hash_map_entry(map, key, true, &value);
ebpf_result_t result = _find_hash_map_entry(map, key, true, true, &value);
if (result == EBPF_SUCCESS) {
ebpf_id_t id = *(ebpf_id_t*)value;
if (id) {
Expand Down Expand Up @@ -1848,12 +1881,12 @@ _update_entry_per_cpu(

const ebpf_map_metadata_table_t* table = ebpf_map_get_table(map->ebpf_map_definition.type);
uint8_t* target;
if (table->find_entry(map, key, false, &target) != EBPF_SUCCESS) {
if (table->find_entry(map, key, false, true, &target) != EBPF_SUCCESS) {
ebpf_result_t return_value = table->update_entry(map, key, NULL, option);
if (return_value != EBPF_SUCCESS) {
return return_value;
}
if (table->find_entry(map, key, false, &target) != EBPF_SUCCESS) {
if (table->find_entry(map, key, false, true, &target) != EBPF_SUCCESS) {
return EBPF_NO_MEMORY;
}
}
Expand Down Expand Up @@ -1918,7 +1951,11 @@ _create_lpm_map(

static ebpf_result_t
_find_lpm_map_entry(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, bool delete_on_success, _Outptr_ uint8_t** data)
_Inout_ ebpf_core_map_t* map,
_In_opt_ const uint8_t* key,
bool delete_on_success,
bool helper_function,
_Outptr_ uint8_t** data)
{
if (!map || !key || delete_on_success) {
return EBPF_INVALID_ARGUMENT;
Expand All @@ -1939,7 +1976,7 @@ _find_lpm_map_entry(
ebpf_bitmap_start_reverse_search_at((ebpf_bitmap_t*)trie_map->data, &cursor, original_prefix_length);
lpm_key->prefix_length = (uint32_t)ebpf_bitmap_reverse_search_next_bit(&cursor);
while (lpm_key->prefix_length != MAXUINT32) {
if (_find_hash_map_entry(map, key, false, &value) == EBPF_SUCCESS) {
if (_find_hash_map_entry(map, key, false, helper_function, &value) == EBPF_SUCCESS) {
break;
}
lpm_key->prefix_length = (uint32_t)ebpf_bitmap_reverse_search_next_bit(&cursor);
Expand Down Expand Up @@ -2066,7 +2103,11 @@ _delete_circular_map(_In_ _Post_invalid_ ebpf_core_map_t* map)

static ebpf_result_t
_find_circular_map_entry(
_Inout_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, bool delete_on_success, _Outptr_ uint8_t** data)
_Inout_ ebpf_core_map_t* map,
_In_opt_ const uint8_t* key,
bool delete_on_success,
bool helper_function,
_Outptr_ uint8_t** data)
{
if (!map) {
return EBPF_INVALID_ARGUMENT;
Expand All @@ -2075,6 +2116,7 @@ _find_circular_map_entry(
// Queue uses no key, but the caller always passes in a non-null pointer (with a 0 key size)
// so we cannot require key to be null.
UNREFERENCED_PARAMETER(key);
UNREFERENCED_PARAMETER(helper_function);

ebpf_core_circular_map_t* circular_map = EBPF_FROM_FIELD(ebpf_core_circular_map_t, core_map, map);
ebpf_lock_state_t state = ebpf_lock_lock(&circular_map->lock);
Expand Down Expand Up @@ -3136,8 +3178,9 @@ ebpf_map_find_entry(
return_value = (uint8_t*)object;
}
} else {
ebpf_result_t result =
table->find_entry(map, key, flags & EBPF_MAP_FIND_FLAG_DELETE ? true : false, &return_value);
bool delete_on_find = (flags & EBPF_MAP_FIND_FLAG_DELETE) ? true : false;
bool helper = (flags & EBPF_MAP_FLAG_HELPER) ? true : false;
ebpf_result_t result = table->find_entry(map, key, delete_on_find, helper, &return_value);
if (result != EBPF_SUCCESS) {
return result;
}
Expand Down Expand Up @@ -3438,6 +3481,8 @@ ebpf_map_pop_entry(_Inout_ ebpf_map_t* map, size_t value_size, _Out_writes_(valu
return EBPF_INVALID_ARGUMENT;
}

bool helper_function = (flags & EBPF_MAP_FLAG_HELPER) ? true : false;

const ebpf_map_metadata_table_t* table = ebpf_map_get_table(map->ebpf_map_definition.type);

if (table->find_entry == NULL) {
Expand All @@ -3449,7 +3494,7 @@ ebpf_map_pop_entry(_Inout_ ebpf_map_t* map, size_t value_size, _Out_writes_(valu
return EBPF_OPERATION_NOT_SUPPORTED;
}

ebpf_result_t result = table->find_entry(map, NULL, true, &return_value);
ebpf_result_t result = table->find_entry(map, NULL, true, helper_function, &return_value);
if (result != EBPF_SUCCESS) {
return result;
}
Expand All @@ -3466,6 +3511,8 @@ ebpf_map_peek_entry(_Inout_ ebpf_map_t* map, size_t value_size, _Out_writes_(val
return EBPF_INVALID_ARGUMENT;
}

bool helper_function = (flags & EBPF_MAP_FLAG_HELPER) ? true : false;

const ebpf_map_metadata_table_t* table = ebpf_map_get_table(map->ebpf_map_definition.type);

if (table->find_entry == NULL) {
Expand All @@ -3477,7 +3524,7 @@ ebpf_map_peek_entry(_Inout_ ebpf_map_t* map, size_t value_size, _Out_writes_(val
return EBPF_OPERATION_NOT_SUPPORTED;
}

ebpf_result_t result = table->find_entry(map, NULL, false, &return_value);
ebpf_result_t result = table->find_entry(map, NULL, false, helper_function, &return_value);
if (result != EBPF_SUCCESS) {
return result;
}
Expand Down
8 changes: 7 additions & 1 deletion libs/runtime/ebpf_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,11 @@ static const NTSTATUS _ebpf_result_mapping[] = {
NTSTATUS
ebpf_result_to_ntstatus(ebpf_result_t result)
{
return (result < EBPF_RESULT_COUNT) ? _ebpf_result_mapping[result] : STATUS_UNSUCCESSFUL;
if (result < 0) {
return STATUS_UNSUCCESSFUL;
}
if (result > ARRAYSIZE(_ebpf_result_mapping)) {
return STATUS_UNSUCCESSFUL;
}
return _ebpf_result_mapping[result];
}
20 changes: 15 additions & 5 deletions libs/runtime/ebpf_hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ _ebpf_hash_table_replace_bucket(
}
if (hash_table->notification_callback) {
hash_table->notification_callback(
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_ALLOCATE, key, new_data);
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_ALLOCATE, NULL, key, new_data);
}
}

Expand Down Expand Up @@ -695,11 +695,11 @@ _ebpf_hash_table_replace_bucket(
if (hash_table->notification_callback) {
if (new_data) {
hash_table->notification_callback(
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_FREE, key, new_data);
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_FREE, NULL, key, new_data);
}
if (old_data) {
hash_table->notification_callback(
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_FREE, key, old_data);
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_FREE, NULL, key, old_data);
}
}

Expand Down Expand Up @@ -801,7 +801,11 @@ ebpf_hash_table_destroy(_In_opt_ _Post_ptr_invalid_ ebpf_hash_table_t* hash_tabl
}

_Must_inspect_result_ ebpf_result_t
ebpf_hash_table_find(_In_ const ebpf_hash_table_t* hash_table, _In_ const uint8_t* key, _Outptr_ uint8_t** value)
ebpf_hash_table_find_with_context(
_In_ const ebpf_hash_table_t* hash_table,
_In_ const uint8_t* key,
_In_opt_ const void* context,
_Outptr_ uint8_t** value)
{
ebpf_result_t retval;
uint32_t bucket_index;
Expand Down Expand Up @@ -839,13 +843,19 @@ ebpf_hash_table_find(_In_ const ebpf_hash_table_t* hash_table, _In_ const uint8_
*value = data;
if (hash_table->notification_callback) {
hash_table->notification_callback(
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_USE, key, data);
hash_table->notification_context, EBPF_HASH_TABLE_NOTIFICATION_TYPE_USE, context, key, data);
}
retval = EBPF_SUCCESS;
Done:
return retval;
}

_Must_inspect_result_ ebpf_result_t
ebpf_hash_table_find(_In_ const ebpf_hash_table_t* hash_table, _In_ const uint8_t* key, _Outptr_ uint8_t** value)
{
return ebpf_hash_table_find_with_context(hash_table, key, NULL, value);
}

_Must_inspect_result_ ebpf_result_t
ebpf_hash_table_update(
_Inout_ ebpf_hash_table_t* hash_table,
Expand Down
8 changes: 8 additions & 0 deletions libs/runtime/ebpf_hash_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern "C"
typedef void (*ebpf_hash_table_notification_function)(
_Inout_ void* context,
_In_ ebpf_hash_table_notification_type_t type,
_In_opt_ const void* operation_context, //< Context passed to ebpf_hash_table_* functions.
_In_ const uint8_t* key,
_Inout_ uint8_t* value);

Expand Down Expand Up @@ -101,6 +102,13 @@ extern "C"
_Must_inspect_result_ ebpf_result_t
ebpf_hash_table_find(_In_ const ebpf_hash_table_t* hash_table, _In_ const uint8_t* key, _Outptr_ uint8_t** value);

_Must_inspect_result_ ebpf_result_t
ebpf_hash_table_find_with_context(
_In_ const ebpf_hash_table_t* hash_table,
_In_ const uint8_t* key,
_In_opt_ const void* context,
_Outptr_ uint8_t** value);

/**
* @brief Insert or update an entry in the hash table.
*
Expand Down
Loading
Loading