Skip to content

Commit

Permalink
Add support for unseeded integer hashing in hash-table
Browse files Browse the repository at this point in the history
Signed-off-by: Alan Jowett <[email protected]>
  • Loading branch information
Alan Jowett committed Aug 29, 2024
1 parent fb53c3d commit 9747f6f
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 3 deletions.
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

0 comments on commit 9747f6f

Please sign in to comment.