Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for unseeded integer hashing in hash-table #3801

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions libs/runtime/ebpf_async.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ ebpf_async_initiate()
const ebpf_hash_table_creation_options_t options = {
.key_size = sizeof(ebpf_handle_t),
.value_size = sizeof(ebpf_async_tracker_t),
.use_unseeded_integer_hashing = true,
};

EBPF_RETURN_RESULT(ebpf_hash_table_create(&_ebpf_async_tracker_table, &options));
Expand Down
45 changes: 43 additions & 2 deletions libs/runtime/ebpf_hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ struct _ebpf_hash_table

void* notification_context; //< Context to pass to notification functions.
ebpf_hash_table_notification_function notification_callback;
bool use_integer_hashing; // Use integer hashing if key is integer and is either 1, 2, 4, or 8 bytes.
// Note: The hashing function doesn't support secrets and is prone to hash collision
// attacks so only use when the data is trusted.
_Field_size_(bucket_count) ebpf_hash_bucket_header_and_lock_t buckets[1]; // Pointer to array of buckets.
};

Expand Down Expand Up @@ -154,6 +157,28 @@ _ebpf_murmur3_32(_In_reads_((length_in_bits + 7) / 8) const uint8_t* key, size_t
return hash;
}

static inline uint32_t
_ebpf_integer_hash_function_32bit(uint32_t key)
{
key ^= key >> 16;
key *= 0x7feb352d;
key ^= key >> 15;
key *= 0x846ca68b;
key ^= key >> 16;
return key;
}

static inline uint64_t
_ebpf_integer_hash_function_64bit(uint64_t key)
{
key ^= key >> 33;
key *= 0xff51afd7ed558ccd;
key ^= key >> 33;
key *= 0xc4ceb9fe1a85ec53;
key ^= key >> 33;
return key;
}

/**
* @brief Compare keys assuming they are integers.
*
Expand Down Expand Up @@ -287,8 +312,23 @@ _ebpf_hash_table_compute_bucket_index(_In_ const ebpf_hash_table_t* hash_table,
length = hash_table->key_size * 8;
data = key;
}
uint32_t hash_value = _ebpf_murmur3_32(data, length, hash_table->seed);
return hash_value & hash_table->bucket_count_mask;
if (hash_table->use_integer_hashing) {
switch (length) {
case 1:
return _ebpf_integer_hash_function_32bit(*(uint8_t*)data) & hash_table->bucket_count_mask;
case 2:
return _ebpf_integer_hash_function_32bit(*(uint16_t*)data) & hash_table->bucket_count_mask;
case 4:
return _ebpf_integer_hash_function_32bit(*(uint32_t*)data) & hash_table->bucket_count_mask;
case 8:
return (uint32_t)(_ebpf_integer_hash_function_64bit(*(uint64_t*)data) & hash_table->bucket_count_mask);
default:
return _ebpf_murmur3_32(data, length, hash_table->seed) & hash_table->bucket_count_mask;
}
} else {
uint32_t hash_value = _ebpf_murmur3_32(data, length, hash_table->seed);
return hash_value & hash_table->bucket_count_mask;
}
}

/**
Expand Down Expand Up @@ -692,6 +732,7 @@ ebpf_hash_table_create(_Out_ ebpf_hash_table_t** hash_table, _In_ const ebpf_has
table->supplemental_value_size = options->supplemental_value_size;
table->notification_context = options->notification_context;
table->notification_callback = options->notification_callback;
table->use_integer_hashing = options->use_unseeded_integer_hashing;

*hash_table = table;
retval = EBPF_SUCCESS;
Expand Down
4 changes: 3 additions & 1 deletion libs/runtime/ebpf_hash_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ extern "C"
size_t supplemental_value_size; //< Size of supplemental value to store in each entry - defaults to 0.
void* notification_context; //< Context to pass to notification functions.
ebpf_hash_table_notification_function
notification_callback; //< Function to call when value storage is allocated or freed.
notification_callback; //< Function to call when value storage is allocated or freed.
bool use_unseeded_integer_hashing; //< Use unseeded integer hashing for this key. Key must be an integer of size
// 1, 2, 4, or 8 bytes.
} ebpf_hash_table_creation_options_t;

/**
Expand Down
1 change: 1 addition & 0 deletions libs/runtime/ebpf_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ ebpf_object_tracking_initiate()
.value_size = sizeof(ebpf_id_entry_t),
.max_entries = EBPF_HASH_TABLE_NO_LIMIT,
.minimum_bucket_count = 1024,
.use_unseeded_integer_hashing = true,
};

memset(_ebpf_object_reference_history, 0, sizeof(_ebpf_object_reference_history));
Expand Down
1 change: 1 addition & 0 deletions libs/runtime/ebpf_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ ebpf_state_initiate()
.key_size = sizeof(uint64_t),
.value_size = sizeof(ebpf_state_entry_t),
.minimum_bucket_count = ebpf_get_cpu_count(),
.use_unseeded_integer_hashing = true,
};

return_value = ebpf_hash_table_create(&_ebpf_state_thread_table, &options);
Expand Down
Loading