Skip to content
Draft
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
22 changes: 20 additions & 2 deletions include/bpf2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,23 @@ extern "C"
helper_function_t address;
} btf_resolved_function_data_t;

/**
* @brief Stable map definition embedded in native module metadata.
*
* New native map properties must be added to map_entry_t instead of this structure.
*/
typedef struct _ebpf_native_map_definition
{
ebpf_map_type_t type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
uint32_t inner_map_idx;
ebpf_pin_type_t pinning;
uint32_t id;
uint32_t inner_id;
} ebpf_native_map_definition_t;

/**
* @brief Map entry.
* This structure contains the address of the map and the map definition. The address is written into the entry
Expand All @@ -121,8 +138,9 @@ extern "C"
uint64_t zero_marker[2];

ebpf_native_module_header_t header;
ebpf_map_definition_in_file_t definition;
ebpf_native_map_definition_t definition;
const char* name;
uint32_t map_flags;
} map_entry_t;

typedef struct _map_data
Expand Down Expand Up @@ -311,7 +329,7 @@ extern "C"
EBPF_NATIVE_BTF_RESOLVED_FUNCTION_DATA_CURRENT_VERSION_TOTAL_SIZE}

#define EBPF_NATIVE_MAP_ENTRY_CURRENT_VERSION 1
#define EBPF_NATIVE_MAP_ENTRY_CURRENT_VERSION_SIZE EBPF_SIZE_INCLUDING_FIELD(map_entry_t, name)
#define EBPF_NATIVE_MAP_ENTRY_CURRENT_VERSION_SIZE EBPF_SIZE_INCLUDING_FIELD(map_entry_t, map_flags)
#define EBPF_NATIVE_MAP_ENTRY_CURRENT_VERSION_TOTAL_SIZE sizeof(map_entry_t)
#define EBPF_NATIVE_MAP_ENTRY_HEADER \
{EBPF_NATIVE_MAP_ENTRY_CURRENT_VERSION, \
Expand Down
13 changes: 12 additions & 1 deletion include/ebpf_core_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@
/**
* @brief eBPF Map Information
*/
typedef struct _ebpf_map_info_definition
{
ebpf_map_type_t type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
ebpf_id_t inner_map_id;
ebpf_pin_type_t pinning;
} ebpf_map_info_definition_t;

typedef struct _ebpf_map_info
{
ebpf_map_definition_in_memory_t definition;
// This definition must remain ABI-compatible with clients built before map_flags was added.
ebpf_map_info_definition_t definition;
_Field_z_ char* pin_path;
} ebpf_map_info_t;

Expand Down
5 changes: 5 additions & 0 deletions include/ebpf_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ static const char* const _ebpf_pin_type_names[] = {
typedef uint32_t ebpf_id_t;
#define EBPF_ID_NONE 0

/// Do not enforce max_entries limit on hash maps.
#define BPF_F_NO_MAX_ENTRIES 1

/**
* @brief eBPF Map Definition as it is stored in memory.
*/
Expand All @@ -117,6 +120,7 @@ typedef struct _ebpf_map_definition_in_memory
uint32_t max_entries; ///< Maximum number of entries allowed in the map.
ebpf_id_t inner_map_id;
ebpf_pin_type_t pinning;
uint32_t map_flags; ///< Map flags (e.g., BPF_F_NO_MAX_ENTRIES).
} ebpf_map_definition_in_memory_t;

/**
Expand All @@ -142,6 +146,7 @@ typedef struct _ebpf_map_definition_in_file
/** For a map of map, inner_id is the id of the inner map template.
*/
uint32_t inner_id;
uint32_t map_flags; ///< Map creation flags.
} ebpf_map_definition_in_file_t;

typedef enum
Expand Down
2 changes: 1 addition & 1 deletion include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ typedef struct
uint32_t key_size; ///< Size in bytes of keys.
uint32_t value_size; ///< Size in bytes of values.
uint32_t max_entries; ///< Maximum number of entries in the map.
uint32_t map_flags; ///< Not supported, must be zero.
uint32_t map_flags; ///< Map flags. Supported: BPF_F_NO_MAX_ENTRIES.
uint32_t inner_map_fd; ///< File descriptor of inner map.
uint32_t numa_node; ///< Not supported, must be zero.
char map_name[SYS_BPF_OBJ_NAME_LEN]; ///< Map name.
Expand Down
2 changes: 2 additions & 0 deletions libs/api/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ _parse_btf_map_info_and_populate_cache(const ELFIO::elfio& reader, const vector<
btf_map_descriptor.key_size,
btf_map_descriptor.value_size,
btf_map_descriptor.max_entries,
0,
(uint32_t)ebpf_fd_invalid,
btf_inner_type_id,
entry.section_offset,
Expand All @@ -317,6 +318,7 @@ _parse_btf_map_info_and_populate_cache(const ELFIO::elfio& reader, const vector<
btf_map_descriptor.key_size,
btf_map_descriptor.value_size,
btf_map_descriptor.max_entries,
0,
(uint32_t)ebpf_fd_invalid,
btf_inner_type_id,
MAXSIZE_T,
Expand Down
30 changes: 24 additions & 6 deletions libs/api/ebpf_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "bpf2c.h"
#include "device_helper.hpp"
#include "ebpf_api.h"
#include "ebpf_native_structs.h"
#include "ebpf_protocol.h"
#include "ebpf_ring_buffer_record.h"
#include "ebpf_serialize.h"
Expand Down Expand Up @@ -377,7 +378,8 @@ ebpf_map_create(

ebpf_assert(map_fd);

if (opts && (opts->map_flags != 0 || opts->numa_node != 0 || opts->map_ifindex != 0)) {
if (opts &&
((opts->map_flags & ~(uint32_t)BPF_F_NO_MAX_ENTRIES) != 0 || opts->numa_node != 0 || opts->map_ifindex != 0)) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
Expand All @@ -388,6 +390,7 @@ ebpf_map_create(
map_definition.key_size = key_size;
map_definition.value_size = value_size;
map_definition.max_entries = max_entries;
map_definition.map_flags = opts ? opts->map_flags : 0;

// bpf_map_create_opts has inner_map_fd defined as __u32, so it cannot be set to
// ebpf_fd_invalid (-1). Hence treat inner_map_fd = 0 as ebpf_fd_invalid.
Expand Down Expand Up @@ -2531,6 +2534,7 @@ initialize_map(_Out_ ebpf_map_t* map, _In_ const map_cache_t& map_cache) noexcep
map->map_definition.value_size = map_cache.verifier_map_descriptor.value_size;
map->map_definition.max_entries = map_cache.verifier_map_descriptor.max_entries;
map->map_definition.pinning = map_cache.pinning;
map->map_definition.map_flags = map_cache.map_flags;
map->map_id = map_cache.id;
map->map_definition.inner_map_id = map_cache.inner_id;
map->inner_map_original_fd = map_cache.verifier_map_descriptor.inner_map_fd;
Expand Down Expand Up @@ -2571,6 +2575,7 @@ _initialize_ebpf_maps_native(
ebpf_assert(map->map_definition.key_size == info.key_size);
ebpf_assert(map->map_definition.value_size == info.value_size);
ebpf_assert(map->map_definition.max_entries == info.max_entries);
ebpf_assert(map->map_definition.map_flags == info.map_flags);

map->map_definition.inner_map_id = info.inner_map_id;
map->map_fd = _create_file_descriptor_for_handle(map_handles[i]);
Expand Down Expand Up @@ -3056,16 +3061,27 @@ _ebpf_pe_get_map_definitions(
map_offset += 8;
}
if (pe_context->object != nullptr) {
for (int map_index = 0; map_offset + sizeof(map_entry_t) <= section_header.Misc.VirtualSize;
map_offset += sizeof(map_entry_t), map_index++) {
map_entry_t* entry = (map_entry_t*)(buffer->buf + map_offset);
if (entry->zero_marker[0] != 0 || entry->zero_marker[1] != 0) {
for (int map_index = 0;
map_offset + EBPF_OFFSET_OF(map_entry_t, header) + sizeof(ebpf_native_module_header_t) <=
section_header.Misc.VirtualSize;
map_index++) {
const map_entry_t* source_entry = (const map_entry_t*)(buffer->buf + map_offset);
if (source_entry->zero_marker[0] != 0 || source_entry->zero_marker[1] != 0) {
// bpf2c generates a section that has map names longer than sizeof(map_entry_t)
// at the end of the section. This entry seems to be a map name string, so we've
// reached the end of the maps.
break;
}

map_entry_t normalized_entry = {};
if (source_entry->header.total_size > section_header.Misc.VirtualSize - map_offset ||
!ebpf_native_map_entry_to_current(&normalized_entry, source_entry)) {
pe_context->result = EBPF_INVALID_OBJECT;
goto Error;
}
map_offset += (uint32_t)source_entry->header.total_size;
const map_entry_t* entry = &normalized_entry;

map = (ebpf_map_t*)ebpf_allocate_with_tag(sizeof(ebpf_map_t), EBPF_POOL_TAG_DEFAULT);
if (map == nullptr) {
goto Error;
Expand All @@ -3079,6 +3095,7 @@ _ebpf_pe_get_map_definitions(
map->map_definition.max_entries = entry->definition.max_entries;
map->map_definition.pinning = entry->definition.pinning;
map->map_definition.inner_map_id = entry->definition.inner_id;
map->map_definition.map_flags = entry->map_flags;
map->inner_map_original_fd = map_idx_to_original_fd(entry->definition.inner_map_idx);
map->pinned = false;
map->reused = false;
Expand Down Expand Up @@ -3586,7 +3603,8 @@ _ebpf_validate_map(_In_ const ebpf_map_t* map, fd_t original_map_fd) NO_EXCEPT_T
}

if (info.type != map->map_definition.type || info.key_size != map->map_definition.key_size ||
info.value_size != map->map_definition.value_size || info.max_entries != map->map_definition.max_entries) {
info.value_size != map->map_definition.value_size || info.max_entries != map->map_definition.max_entries ||
info.map_flags != map->map_definition.map_flags) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
Expand Down
1 change: 1 addition & 0 deletions libs/api/windows_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ _parse_maps_section_windows(
s.key_size,
s.value_size,
s.max_entries,
s.map_flags,
inner_map_original_fd,
s.inner_id,
section_offset,
Expand Down
9 changes: 6 additions & 3 deletions libs/api_common/api_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,18 @@ typedef struct _map_cache
prevail::EbpfMapDescriptor verifier_map_descriptor;
ebpf_pin_type_t pinning;
uint32_t inner_id;
uint32_t map_flags;

_map_cache()
: handle(0), id(EBPF_ID_NONE), section_offset(0), verifier_map_descriptor(), pinning(LIBBPF_PIN_NONE),
inner_id(EBPF_ID_NONE)
inner_id(EBPF_ID_NONE), map_flags(0)
{
}

_map_cache(
ebpf_handle_t handle, size_t section_offset, prevail::EbpfMapDescriptor descriptor, ebpf_pin_type_t pinning)
: handle(handle), id(EBPF_ID_NONE), section_offset(section_offset), verifier_map_descriptor(descriptor),
pinning(pinning), inner_id(EBPF_ID_NONE)
pinning(pinning), inner_id(EBPF_ID_NONE), map_flags(0)
{
}

Expand All @@ -90,11 +91,12 @@ typedef struct _map_cache
unsigned int key_size,
unsigned int value_size,
unsigned int max_entries,
uint32_t _map_flags,
fd_t inner_map_original_fd,
unsigned int _inner_id,
size_t section_offset,
ebpf_pin_type_t pinning)
: handle(handle), section_offset(section_offset), pinning(pinning)
: handle(handle), section_offset(section_offset), pinning(pinning), map_flags(_map_flags)
{
verifier_map_descriptor.original_fd = original_fd;
verifier_map_descriptor.type = type;
Expand Down Expand Up @@ -125,6 +127,7 @@ cache_map_handle(
uint32_t key_size,
uint32_t value_size,
uint32_t max_entries,
uint32_t map_flags,
uint32_t inner_map_original_fd,
uint32_t inner_id,
size_t section_offset,
Expand Down
4 changes: 4 additions & 0 deletions libs/api_common/map_descriptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ cache_map_original_file_descriptor_with_handle(
uint32_t key_size,
uint32_t value_size,
uint32_t max_entries,
uint32_t map_flags,
uint32_t inner_map_original_fd,
uint32_t inner_id,
ebpf_handle_t handle,
Expand All @@ -111,6 +112,7 @@ cache_map_original_file_descriptor_with_handle(
key_size,
value_size,
max_entries,
map_flags,
inner_map_original_fd,
inner_id,
section_offset,
Expand All @@ -126,6 +128,7 @@ cache_map_handle(
uint32_t key_size,
uint32_t value_size,
uint32_t max_entries,
uint32_t map_flags,
uint32_t inner_map_original_fd,
uint32_t inner_id,
size_t section_offset,
Expand All @@ -139,6 +142,7 @@ cache_map_handle(
key_size,
value_size,
max_entries,
map_flags,
inner_map_original_fd,
(inner_id ? inner_id : EBPF_ID_NONE),
section_offset,
Expand Down
1 change: 1 addition & 0 deletions libs/api_common/map_descriptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ cache_map_original_file_descriptor_with_handle(
uint32_t key_size,
uint32_t value_size,
uint32_t max_entries,
uint32_t map_flags,
uint32_t inner_map_original_fd,
uint32_t inner_id,
ebpf_handle_t handle,
Expand Down
34 changes: 30 additions & 4 deletions libs/execution_context/ebpf_maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1274,8 +1274,17 @@ _create_hash_map(
if (inner_map_handle != ebpf_handle_invalid) {
return EBPF_INVALID_ARGUMENT;
}
bool no_max_entries = (map_definition->map_flags & BPF_F_NO_MAX_ENTRIES) != 0;
return _create_hash_map_internal(
sizeof(ebpf_core_map_t), map_definition, 0, 0, false, NULL, NULL, EBPF_HASH_TABLE_NOTIFICATION_TYPE_NONE, map);
sizeof(ebpf_core_map_t),
map_definition,
0,
0,
!no_max_entries,
NULL,
NULL,
EBPF_HASH_TABLE_NOTIFICATION_TYPE_NONE,
map);
}

static void
Expand Down Expand Up @@ -1344,12 +1353,13 @@ _create_object_hash_map(

*map = NULL;

bool no_max_entries = (map_definition->map_flags & BPF_F_NO_MAX_ENTRIES) != 0;
result = _create_hash_map_internal(
sizeof(ebpf_core_object_map_t),
map_definition,
actual_value_size,
0,
false,
!no_max_entries,
NULL,
NULL,
EBPF_HASH_TABLE_NOTIFICATION_TYPE_NONE,
Expand Down Expand Up @@ -2227,12 +2237,13 @@ _create_lpm_map(
goto Exit;
}

bool no_max_entries = (map_definition->map_flags & BPF_F_NO_MAX_ENTRIES) != 0;
result = _create_hash_map_internal(
lpm_data_size,
map_definition,
0,
0,
false,
!no_max_entries,
_lpm_extract,
NULL,
EBPF_HASH_TABLE_NOTIFICATION_TYPE_NONE,
Expand Down Expand Up @@ -3793,6 +3804,21 @@ ebpf_map_create(
goto Exit;
}

// Validate map_flags. Only BPF_F_NO_MAX_ENTRIES is supported, and only for hash-based map types.
if (ebpf_map_definition->map_flags != 0) {
if (ebpf_map_definition->map_flags & ~(uint32_t)BPF_F_NO_MAX_ENTRIES) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (ebpf_map_definition->map_flags & BPF_F_NO_MAX_ENTRIES) {
if (type != BPF_MAP_TYPE_HASH && type != BPF_MAP_TYPE_PERCPU_HASH && type != BPF_MAP_TYPE_HASH_OF_MAPS &&
type != BPF_MAP_TYPE_LPM_TRIE) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
}
}

const ebpf_map_metadata_table_properties_t* properties = _ebpf_map_metadata_table_query(type);

if (properties == NULL) {
Expand Down Expand Up @@ -4202,7 +4228,7 @@ ebpf_map_get_info(
info->key_size = map->ebpf_map_definition.key_size;
info->value_size = map->original_value_size;
info->max_entries = map->ebpf_map_definition.max_entries;
info->map_flags = 0;
info->map_flags = map->ebpf_map_definition.map_flags;
if (info->type == BPF_MAP_TYPE_ARRAY_OF_MAPS || info->type == BPF_MAP_TYPE_HASH_OF_MAPS) {
ebpf_core_object_map_t* object_map = EBPF_FROM_FIELD(ebpf_core_object_map_t, core_map, map);
info->inner_map_id = object_map->core_map.ebpf_map_definition.inner_map_id
Expand Down
Loading
Loading