Skip to content

Commit

Permalink
WIP perf event arrays.
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Agun committed Jan 29, 2025
1 parent 07beca5 commit a5f9711
Show file tree
Hide file tree
Showing 27 changed files with 2,163 additions and 75 deletions.
14 changes: 14 additions & 0 deletions include/bpf_helper_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,17 @@ EBPF_HELPER(uint64_t, bpf_ktime_get_ms, ());
#ifndef __doxygen
#define bpf_ktime_get_ms ((bpf_ktime_get_ms_t)BPF_FUNC_ktime_get_ms)
#endif

/**
* @brief Copy data into perf event array map.
*
* @param[in, out] map Pointer to perf event array map.
* @param[in] data Data to copy into perf event array map.
* @param[in] size Length of data.
* @param[in] flags Flags indicating if notification for new data availability should be sent.
* @returns 0 on success and a negative value on error.
*/
EBPF_HELPER(int, bpf_perf_event_output, (void* ctx, void* perf_event_array, uint64_t flags, void* data, uint64_t size));
#ifndef __doxygen
#define bpf_perf_event_output ((bpf_perf_event_output_t)BPF_FUNC_perf_event_output)
#endif
33 changes: 25 additions & 8 deletions include/ebpf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ extern "C"
* @deprecated Use ebpf_enumerate_programs() instead.
*/
__declspec(deprecated("Use ebpf_enumerate_programs() instead.")) _Must_inspect_result_ ebpf_result_t
ebpf_enumerate_sections(
_In_z_ const char* file,
bool verbose,
_Outptr_result_maybenull_ ebpf_section_info_t** infos,
_Outptr_result_maybenull_z_ const char** error_message) EBPF_NO_EXCEPT;
ebpf_enumerate_sections(
_In_z_ const char* file,
bool verbose,
_Outptr_result_maybenull_ ebpf_section_info_t** infos,
_Outptr_result_maybenull_z_ const char** error_message) EBPF_NO_EXCEPT;

/**
* @brief Free memory returned from \ref ebpf_enumerate_programs.
Expand All @@ -114,8 +114,8 @@ extern "C"
* @param[in] data Memory to free.
* @deprecated Use ebpf_free_programs() instead.
*/
__declspec(deprecated("Use ebpf_free_programs() instead.")) void ebpf_free_sections(
_In_opt_ _Post_invalid_ ebpf_section_info_t* infos) EBPF_NO_EXCEPT;
__declspec(deprecated("Use ebpf_free_programs() instead.")) void
ebpf_free_sections(_In_opt_ _Post_invalid_ ebpf_section_info_t* infos) EBPF_NO_EXCEPT;

/**
* @brief Convert an eBPF program to human readable byte code.
Expand Down Expand Up @@ -144,7 +144,8 @@ extern "C"
* @param[out] error_message On failure points to a text description of
* the error.
*/
__declspec(deprecated("Use ebpf_api_elf_disassemble_program() instead.")) uint32_t ebpf_api_elf_disassemble_section(
__declspec(deprecated("Use ebpf_api_elf_disassemble_program() instead.")) uint32_t
ebpf_api_elf_disassemble_section(
_In_z_ const char* file,
_In_z_ const char* section,
_Outptr_result_maybenull_z_ const char** disassembly,
Expand Down Expand Up @@ -578,6 +579,22 @@ extern "C"
ebpf_ring_buffer_map_write(
fd_t ring_buffer_map_fd, _In_reads_bytes_(data_length) const void* data, size_t data_length) EBPF_NO_EXCEPT;

/**
* @brief Write data into the perf event array map.
*
* @param [in] perf_event_array_map_fd perf event array map file descriptor.
* @param [in] data Pointer to data to be written.
* @param [in] data_length Length of data to be written.
* @retval EPBF_SUCCESS Successfully wrote record into perf event array.
* @retval EBPF_OUT_OF_SPACE Unable to output to perf event array due to inadequate space.
* @retval EBPF_NO_MEMORY Out of memory.
*/
_Must_inspect_result_ ebpf_result_t
ebpf_perf_event_array_map_write(
fd_t perf_event_array_map_fd,
_In_reads_bytes_(data_length) const void* data,
size_t data_length) EBPF_NO_EXCEPT;

#ifdef __cplusplus
}
#endif
8 changes: 8 additions & 0 deletions include/ebpf_core_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ typedef struct _ebpf_ring_buffer_map_async_query_result
size_t consumer;
} ebpf_ring_buffer_map_async_query_result_t;

typedef struct _ebpf_perf_event_array_map_async_query_result
{
// uint32_t cpu_id;
size_t producer;
size_t consumer;
size_t lost_count;
} ebpf_perf_event_array_map_async_query_result_t;

typedef enum _ebpf_object_type
{
EBPF_OBJECT_UNKNOWN,
Expand Down
1 change: 1 addition & 0 deletions include/ebpf_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: MIT
#pragma once

#include "ebpf_base.h"
#include "ebpf_result.h"
#include "ebpf_structs.h"
#include "ebpf_windows.h"
Expand Down
37 changes: 25 additions & 12 deletions include/ebpf_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,22 @@ typedef enum bpf_map_type
BPF_MAP_TYPE_ARRAY = 2, ///< Array, where the map key is the array index.
BPF_MAP_TYPE_PROG_ARRAY =
3, ///< Array of program fds usable with bpf_tail_call, where the map key is the array index.
BPF_MAP_TYPE_PERCPU_HASH = 4, ///< Per-CPU hash table.
BPF_MAP_TYPE_PERCPU_ARRAY = 5, ///< Per-CPU array.
BPF_MAP_TYPE_HASH_OF_MAPS = 6, ///< Hash table, where the map value is another map.
BPF_MAP_TYPE_ARRAY_OF_MAPS = 7, ///< Array, where the map value is another map.
BPF_MAP_TYPE_LRU_HASH = 8, ///< Least-recently-used hash table.
BPF_MAP_TYPE_LPM_TRIE = 9, ///< Longest prefix match trie.
BPF_MAP_TYPE_QUEUE = 10, ///< Queue.
BPF_MAP_TYPE_LRU_PERCPU_HASH = 11, ///< Per-CPU least-recently-used hash table.
BPF_MAP_TYPE_STACK = 12, ///< Stack.
BPF_MAP_TYPE_RINGBUF = 13 ///< Ring buffer.
BPF_MAP_TYPE_PERCPU_HASH = 4, ///< Per-CPU hash table.
BPF_MAP_TYPE_PERCPU_ARRAY = 5, ///< Per-CPU array.
BPF_MAP_TYPE_HASH_OF_MAPS = 6, ///< Hash table, where the map value is another map.
BPF_MAP_TYPE_ARRAY_OF_MAPS = 7, ///< Array, where the map value is another map.
BPF_MAP_TYPE_LRU_HASH = 8, ///< Least-recently-used hash table.
BPF_MAP_TYPE_LPM_TRIE = 9, ///< Longest prefix match trie.
BPF_MAP_TYPE_QUEUE = 10, ///< Queue.
BPF_MAP_TYPE_LRU_PERCPU_HASH = 11, ///< Per-CPU least-recently-used hash table.
BPF_MAP_TYPE_STACK = 12, ///< Stack.
BPF_MAP_TYPE_RINGBUF = 13, ///< Ring buffer.
BPF_MAP_TYPE_PERF_EVENT_ARRAY = 14, ///< Perf event array.
} ebpf_map_type_t;

#define BPF_MAP_TYPE_PER_CPU(X) \
((X) == BPF_MAP_TYPE_PERCPU_HASH || (X) == BPF_MAP_TYPE_PERCPU_ARRAY || (X) == BPF_MAP_TYPE_LRU_PERCPU_HASH)
#define BPF_MAP_TYPE_PER_CPU(X) \
((X) == BPF_MAP_TYPE_PERCPU_HASH || (X) == BPF_MAP_TYPE_PERCPU_ARRAY || (X) == BPF_MAP_TYPE_LRU_PERCPU_HASH || \
(X) == BPF_MAP_TYPE_PERF_EVENT_ARRAY)

static const char* const _ebpf_map_type_names[] = {
BPF_ENUM_TO_STRING(BPF_MAP_TYPE_UNSPEC),
Expand All @@ -51,6 +53,7 @@ static const char* const _ebpf_map_type_names[] = {
BPF_ENUM_TO_STRING(BPF_MAP_TYPE_LRU_PERCPU_HASH),
BPF_ENUM_TO_STRING(BPF_MAP_TYPE_STACK),
BPF_ENUM_TO_STRING(BPF_MAP_TYPE_RINGBUF),
BPF_ENUM_TO_STRING(BPF_MAP_TYPE_PERF_EVENT_ARRAY),
};

static const char* const _ebpf_map_display_names[] = {
Expand All @@ -68,6 +71,7 @@ static const char* const _ebpf_map_display_names[] = {
"lru_percpu_hash",
"stack",
"ringbuf",
"perf_event_array",
};

typedef enum ebpf_map_option
Expand Down Expand Up @@ -166,6 +170,7 @@ typedef enum
BPF_FUNC_strnlen_s = 29, ///< \ref bpf_strnlen_s
BPF_FUNC_ktime_get_boot_ms = 30, ///< \ref bpf_ktime_get_boot_ms
BPF_FUNC_ktime_get_ms = 31, ///< \ref bpf_ktime_get_ms
BPF_FUNC_perf_event_output = 32, ///< \ref bpf_perf_event_output
} ebpf_helper_id_t;

// Cross-platform BPF program types.
Expand Down Expand Up @@ -408,3 +413,11 @@ struct bpf_prog_info
uint32_t pinned_path_count; ///< Number of pinned paths.
uint32_t link_count; ///< Number of attached links.
};

/* BPF_FUNC_perf_event_output flags. */
#define EBPF_MAP_FLAG_INDEX_MASK 0xffffffffULL
#define EBPF_MAP_FLAG_INDEX_SHIFT 0
#define EBPF_MAP_FLAG_CURRENT_CPU EBPF_MAP_FLAG_INDEX_MASK
/* BPF_FUNC_perf_event_output for program types with data pointer in context */
#define EBPF_MAP_FLAG_CTXLEN_SHIFT 32
#define EBPF_MAP_FLAG_CTXLEN_MASK (0xfffffULL << EBPF_MAP_FLAG_CTXLEN_SHIFT)
32 changes: 32 additions & 0 deletions libs/api/api_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
struct bpf_object;

typedef struct _ebpf_ring_buffer_subscription ring_buffer_subscription_t;
typedef struct _ebpf_perf_event_array_subscription perf_event_array_subscription_t;

typedef struct bpf_program
{
Expand Down Expand Up @@ -659,6 +660,37 @@ ebpf_ring_buffer_map_subscribe(
bool
ebpf_ring_buffer_map_unsubscribe(_In_ _Post_invalid_ ring_buffer_subscription_t* subscription) noexcept;

typedef void (*perf_buffer_sample_fn)(void* ctx, int cpu, void* data, uint32_t size);
typedef void (*perf_buffer_lost_fn)(void* ctx, int cpu, uint64_t cnt);

/**
* @brief Subscribe for notifications from the input perf event array map.
*
* @param[in] perf_event_array_map_fd File descriptor to the perf event array map.
* @param[in, out] sample_callback_context Pointer to supplied context to be passed in notification callback.
* @param[in] sample_callback Function pointer to notification handler.
* @param[in] lost_callback Function pointer to lost record notification handler.
* @param[out] subscription Opaque pointer to perf event array subscription object.
*
* @retval EBPF_SUCCESS The operation was successful.
* @retval EBPF_NO_MEMORY Out of memory.
*/
_Must_inspect_result_ ebpf_result_t
ebpf_perf_event_array_map_subscribe(
fd_t perf_event_array_map_fd,
_Inout_opt_ void* callback_context,
perf_buffer_sample_fn sample_callback,
perf_buffer_lost_fn lost_callback,
_Outptr_ perf_event_array_subscription_t** subscription) noexcept;

/**
* @brief Unsubscribe from the perf event array map event notifications.
*
* @param[in] subscription Pointer to perf event array subscription to be canceled.
*/
bool
ebpf_perf_event_array_map_unsubscribe(_In_ _Post_invalid_ perf_event_array_subscription_t* subscription) noexcept;

/**
* @brief Get list of programs and stats in an ELF eBPF file.
* @param[in] file Name of ELF file containing eBPF program.
Expand Down
Loading

0 comments on commit a5f9711

Please sign in to comment.