Add more libbpf APIs needed by bpftool (#576)
* Add more libbpf APIs needed by bpftool * Add missing export for existing bpf_map__name API * Add bpf_object__load * Add bpf_object__load_xattr * Add bpf_object__open_file * Add bpf_object__unload() API * Add bpf_program__get_type * Add bpf_program__set_type * Add bpf_program__unload() API * Add libbpf_get_error * Add libbpf_num_possible_cpus * Rename BPF_MAP_TYPE_UNSPECIFIED to BPF_MAP_TYPE_UNSPEC for libbpf compat * Rename BPF_PROG_TYPE_UNKNOWN to BPF_PROG_TYPE_UNSPEC for libbpf compat * Add attach_type to bpf_link_info * Add map_flags to bpf_map_info (but currently always 0) Fixes #575 Signed-off-by: Dave Thaler <dthaler@microsoft.com>
This commit is contained in:
Родитель
6a1c193b5b
Коммит
20d7a6565e
|
@ -19,6 +19,7 @@ EXPORTS
|
|||
bpf_map__is_pinned
|
||||
bpf_map__key_size
|
||||
bpf_map__max_entries
|
||||
bpf_map__name
|
||||
bpf_map__next
|
||||
bpf_map__pin
|
||||
bpf_map__prev
|
||||
|
@ -38,11 +39,15 @@ EXPORTS
|
|||
bpf_object__find_map_by_name
|
||||
bpf_object__find_map_fd_by_name
|
||||
bpf_object__find_program_by_name
|
||||
bpf_object__load
|
||||
bpf_object__load_xattr
|
||||
bpf_object__name
|
||||
bpf_object__next
|
||||
bpf_object__open_file
|
||||
bpf_object__pin
|
||||
bpf_object__pin_maps
|
||||
bpf_object__pin_programs
|
||||
bpf_object__unload
|
||||
bpf_object__unpin_maps
|
||||
bpf_object__unpin_programs
|
||||
bpf_prog_get_fd_by_id
|
||||
|
@ -52,12 +57,15 @@ EXPORTS
|
|||
bpf_program__attach_xdp
|
||||
bpf_program__fd
|
||||
bpf_program__get_expected_attach_type
|
||||
bpf_program__get_type
|
||||
bpf_program__name
|
||||
bpf_program__next
|
||||
bpf_program__pin
|
||||
bpf_program__prev
|
||||
bpf_program__section_name
|
||||
bpf_program__set_expected_attach_type
|
||||
bpf_program__set_type
|
||||
bpf_program__unload
|
||||
bpf_program__unpin
|
||||
ebpf_api_initiate
|
||||
ebpf_api_terminate
|
||||
|
@ -84,4 +92,6 @@ EXPORTS
|
|||
ebpf_program_attach_by_fd
|
||||
ebpf_program_load
|
||||
ebpf_program_query_info
|
||||
libbpf_get_error
|
||||
libbpf_num_possible_cpus
|
||||
libbpf_prog_type_by_name
|
||||
|
|
|
@ -199,7 +199,7 @@ bpf_map_update_elem(int fd, const void* key, const void* value, __u64 flags);
|
|||
|
||||
/**
|
||||
* @brief Get a file descriptor for a pinned object by pin path.
|
||||
* @param[in] path Pin path for the object.
|
||||
* @param[in] pathname Pin path for the object.
|
||||
*
|
||||
* @return file descriptor for the pinned object, or -1 if not found.
|
||||
*/
|
|
@ -267,6 +267,58 @@ bpf_object__find_map_fd_by_name(const struct bpf_object* obj, const char* name);
|
|||
struct bpf_program*
|
||||
bpf_object__find_program_by_name(const struct bpf_object* obj, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Load all the programs in a given object.
|
||||
*
|
||||
* @param[in] obj Object from which to load programs.
|
||||
*
|
||||
* @retval 0 The operation was successful.
|
||||
* @retval <0 An error occured, and errno was set.
|
||||
*
|
||||
* @exception EINVAL An invalid argument was provided.
|
||||
* @exception ENOMEM Out of memory.
|
||||
*
|
||||
* @sa bpf_object__load_xattr
|
||||
* @sa bpf_object__open
|
||||
* @sa bpf_object__unload
|
||||
* @sa bpf_prog_load
|
||||
*/
|
||||
int
|
||||
bpf_object__load(struct bpf_object* obj);
|
||||
|
||||
/**
|
||||
* @brief Unload all the programs in a given object.
|
||||
*
|
||||
* @param[in] obj Object in which to unload programs.
|
||||
*
|
||||
* @retval 0 The operation was successful.
|
||||
* @retval <0 An error occured, and errno was set.
|
||||
*
|
||||
* @sa bpf_object__load
|
||||
* @sa bpf_object__load_xattr
|
||||
* @sa bpf_prog_load
|
||||
*/
|
||||
int
|
||||
bpf_object__unload(struct bpf_object* obj);
|
||||
|
||||
/**
|
||||
* @brief Load all the programs in a given object.
|
||||
*
|
||||
* @param[in] attr Structure with load attributes.
|
||||
*
|
||||
* @retval 0 The operation was successful.
|
||||
* @retval <0 An error occured, and errno was set.
|
||||
*
|
||||
* @exception EINVAL An invalid argument was provided.
|
||||
* @exception ENOMEM Out of memory.
|
||||
*
|
||||
* @sa bpf_object__open
|
||||
* @sa bpf_object__load_xattr
|
||||
* @sa bpf_prog_load
|
||||
*/
|
||||
int
|
||||
bpf_object__load_xattr(struct bpf_object_load_attr* attr);
|
||||
|
||||
/**
|
||||
* @brief Get the name of an eBPF object.
|
||||
*
|
||||
|
@ -287,6 +339,17 @@ bpf_object__name(const struct bpf_object* obj);
|
|||
struct bpf_object*
|
||||
bpf_object__next(struct bpf_object* prev);
|
||||
|
||||
/**
|
||||
* @brief Open a file without loading the programs.
|
||||
*
|
||||
* @param[in] path File name to open.
|
||||
* @param[opts] opts Options to use when opening the object.
|
||||
*
|
||||
* @returns Pointer to an eBPF object, or NULL on failure.
|
||||
*/
|
||||
struct bpf_object*
|
||||
bpf_object__open_file(const char* path, const struct bpf_object_open_opts* opts);
|
||||
|
||||
/**
|
||||
* @brief Pin an eBPF object to a specified path.
|
||||
*
|
||||
|
@ -468,6 +531,18 @@ bpf_program__fd(const struct bpf_program* prog);
|
|||
enum bpf_attach_type
|
||||
bpf_program__get_expected_attach_type(const struct bpf_program* prog);
|
||||
|
||||
/**
|
||||
* @brief Get the program type for an eBPF program.
|
||||
*
|
||||
* @param[in] prog Program to check.
|
||||
*
|
||||
* @returns Program type.
|
||||
*
|
||||
* @sa bpf_program__get_expected_attach_type
|
||||
*/
|
||||
enum bpf_prog_type
|
||||
bpf_program__get_type(const struct bpf_program* prog);
|
||||
|
||||
/**
|
||||
* @brief Get the function name of an eBPF program.
|
||||
*
|
||||
|
@ -550,6 +625,28 @@ bpf_program__section_name(const struct bpf_program* prog);
|
|||
void
|
||||
bpf_program__set_expected_attach_type(struct bpf_program* prog, enum bpf_attach_type type);
|
||||
|
||||
/**
|
||||
* @brief Set the program type for an eBPF program.
|
||||
*
|
||||
* @param[in] prog Program to update.
|
||||
* @param[in] type Program type to set.
|
||||
*
|
||||
* @sa bpf_program__set_expected_attach_type
|
||||
*/
|
||||
void
|
||||
bpf_program__set_type(struct bpf_program* prog, enum bpf_prog_type type);
|
||||
|
||||
/**
|
||||
* @brief Unload a program.
|
||||
*
|
||||
* @param[in] prog Program to unload.
|
||||
*
|
||||
* @sa bpf_object__unload
|
||||
* @sa bpf_prog_load
|
||||
*/
|
||||
void
|
||||
bpf_program__unload(struct bpf_program* prog);
|
||||
|
||||
/**
|
||||
* @brief Unpin a program.
|
||||
*
|
||||
|
@ -583,6 +680,31 @@ libbpf_prog_type_by_name(const char* name, enum bpf_prog_type* prog_type, enum b
|
|||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name System-related functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get a negative error code based on errno and a possibly null pointer.
|
||||
*
|
||||
* @param[in] ptr Pointer that may be NULL.
|
||||
*
|
||||
* @returns Negative error code.
|
||||
*/
|
||||
long
|
||||
libbpf_get_error(const void* ptr);
|
||||
|
||||
/**
|
||||
* @brief Get the number of processors on the current system.
|
||||
*
|
||||
* @returns Number of processors.
|
||||
*/
|
||||
int
|
||||
libbpf_num_possible_cpus(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#else
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200) // Zero-sized array in struct/union
|
|
@ -33,7 +33,7 @@ extern "C"
|
|||
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_SAMPLE = {
|
||||
0xf788ef4b, 0x207d, 0x4dc3, {0x85, 0xcf, 0x0f, 0x2e, 0xa1, 0x07, 0x21, 0x3c}};
|
||||
|
||||
__declspec(selectany) ebpf_attach_type_t EBPF_PROGRAM_TYPE_UNSPECIFIED = {0};
|
||||
__declspec(selectany) ebpf_program_type_t EBPF_PROGRAM_TYPE_UNSPECIFIED = {0};
|
||||
|
||||
/** @brief Program type for handling incoming packets as early as possible.
|
||||
*
|
||||
|
@ -61,7 +61,7 @@ extern "C"
|
|||
0xf788ef4a, 0x207d, 0x4dc3, {0x85, 0xcf, 0x0f, 0x2e, 0xa1, 0x07, 0x21, 0x3c}};
|
||||
|
||||
typedef int32_t fd_t;
|
||||
const fd_t ebpf_fd_invalid = -1;
|
||||
extern __declspec(selectany) const fd_t ebpf_fd_invalid = -1;
|
||||
typedef intptr_t ebpf_handle_t;
|
||||
typedef struct _tlv_type_length_value tlv_type_length_value_t;
|
||||
|
||||
|
@ -366,10 +366,10 @@ extern "C"
|
|||
* EBPF_EXECUTION_ANY is specified, execution type will be decided by a
|
||||
* system-wide policy.
|
||||
* @param[out] object Returns pointer to ebpf_object object. The caller
|
||||
is expected to call ebpf_object_close() at the end.
|
||||
is expected to call bpf_object__close() at the end.
|
||||
* @param[out] program_fd Returns a file descriptor for the first program.
|
||||
* The caller should not call _close() on the fd, but should instead use
|
||||
* ebpf_object_close() to close this (and other) file descriptors.
|
||||
* bpf_object__close() to close this (and other) file descriptors.
|
||||
* @param[out] log_buffer Returns a pointer to a null-terminated log buffer.
|
||||
* The caller is responsible for freeing the returned log_buffer pointer
|
||||
* by calling ebpf_free_string().
|
||||
|
@ -479,7 +479,7 @@ extern "C"
|
|||
* @brief Get a program type and expected attach type by name.
|
||||
*
|
||||
* @param[in] name Name, as if it were a section name in an ELF file.
|
||||
* @param[out] prog_type Program type.
|
||||
* @param[out] program_type Program type.
|
||||
* @param[out] expected_attach_type Expected attach type.
|
||||
*
|
||||
* @retval EBPF_SUCCESS The operation was successful.
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
typedef enum bpf_map_type
|
||||
{
|
||||
BPF_MAP_TYPE_UNSPECIFIED = 0, ///< Unspecified map type.
|
||||
BPF_MAP_TYPE_HASH = 1, ///< Hash table.
|
||||
BPF_MAP_TYPE_ARRAY = 2, ///< Array, where the map key is the array index.
|
||||
BPF_MAP_TYPE_UNSPEC = 0, ///< Unspecified map type.
|
||||
BPF_MAP_TYPE_HASH = 1, ///< Hash table.
|
||||
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,
|
||||
|
@ -84,20 +84,47 @@ typedef enum
|
|||
// Cross-platform BPF program types.
|
||||
enum bpf_prog_type
|
||||
{
|
||||
BPF_PROG_TYPE_UNKNOWN,
|
||||
BPF_PROG_TYPE_UNSPEC,
|
||||
BPF_PROG_TYPE_XDP,
|
||||
BPF_PROG_TYPE_BIND, // TODO(#333): replace with cross-platform program type
|
||||
};
|
||||
|
||||
// The link type is used to tell which union member is present
|
||||
// in the bpf_link_info struct. There is exactly one non-zero value
|
||||
// per union member.
|
||||
enum bpf_link_type
|
||||
{
|
||||
BPF_LINK_TYPE_UNSPEC,
|
||||
BPF_LINK_TYPE_PLAIN,
|
||||
};
|
||||
|
||||
enum bpf_attach_type
|
||||
{
|
||||
BPF_ATTACH_TYPE_UNSPEC,
|
||||
BPF_ATTACH_TYPE_XDP,
|
||||
__MAX_BPF_ATTACH_TYPE,
|
||||
};
|
||||
|
||||
// Libbpf itself requires the following structs to be defined, but doesn't
|
||||
// care what fields they have. Applications such as bpftool on the other
|
||||
// hand depend on fields of specific names and types.
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) /* nameless struct/union */
|
||||
struct bpf_link_info
|
||||
{
|
||||
ebpf_id_t id; ///< Link ID.
|
||||
ebpf_id_t prog_id; ///< Program ID.
|
||||
ebpf_id_t id; ///< Link ID.
|
||||
ebpf_id_t prog_id; ///< Program ID.
|
||||
enum bpf_link_type type; ///< Link type.
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int attach_type; ///< Attach type integer.
|
||||
};
|
||||
};
|
||||
};
|
||||
#pragma warning(pop)
|
||||
|
||||
#define BPF_OBJ_NAME_LEN 64
|
||||
|
||||
|
@ -110,12 +137,17 @@ struct bpf_map_info
|
|||
uint32_t value_size; ///< Size in bytes of a map value.
|
||||
uint32_t max_entries; ///< Maximum number of entries allowed in the map.
|
||||
char name[BPF_OBJ_NAME_LEN]; ///< Null-terminated map name.
|
||||
uint32_t map_flags; ///< Map flags.
|
||||
|
||||
// Windows-specific fields.
|
||||
ebpf_id_t inner_map_id; ///< ID of inner map template.
|
||||
uint32_t pinned_path_count; ///< Number of pinned paths.
|
||||
};
|
||||
|
||||
#define BPF_ANY 0x0
|
||||
#define BPF_NOEXIST 0x1
|
||||
#define BPF_EXIST 0x2
|
||||
|
||||
struct bpf_prog_info
|
||||
{
|
||||
// Cross-platform fields.
|
||||
|
|
|
@ -13,17 +13,13 @@
|
|||
#undef LIBBPF_DEPRECATED
|
||||
#define LIBBPF_DEPRECATED(x)
|
||||
|
||||
typedef int32_t __s32;
|
||||
|
||||
typedef uint8_t __u8;
|
||||
typedef uint32_t __u32;
|
||||
typedef uint64_t __u64;
|
||||
typedef uint32_t pid_t;
|
||||
|
||||
enum bpf_attach_type
|
||||
{
|
||||
BPF_ATTACH_TYPE_UNSPEC,
|
||||
BPF_ATTACH_TYPE_XDP,
|
||||
};
|
||||
|
||||
enum bpf_func_id
|
||||
{
|
||||
BPF_FUNC_ID_UNKNOWN
|
||||
|
|
|
@ -178,6 +178,7 @@
|
|||
<ClCompile Include="libbpf_object.cpp" />
|
||||
<ClCompile Include="libbpf_program.cpp" />
|
||||
<ClCompile Include="libbpf_map.cpp" />
|
||||
<ClCompile Include="libbpf_system.cpp" />
|
||||
<ClCompile Include="Verifier.cpp" />
|
||||
<ClCompile Include="windows_platform.cpp" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
<ClCompile Include="libbpf_link.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libbpf_system.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
|
|
@ -61,9 +61,10 @@ typedef struct bpf_link
|
|||
|
||||
typedef struct bpf_object
|
||||
{
|
||||
char* file_name = nullptr;
|
||||
char* object_name = nullptr;
|
||||
std::vector<ebpf_program_t*> programs;
|
||||
std::vector<ebpf_map_t*> maps;
|
||||
bool loaded = false;
|
||||
} ebpf_object_t;
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -120,6 +121,17 @@ ebpf_program_next(_In_opt_ const struct bpf_program* previous, _In_ const struct
|
|||
_Ret_maybenull_ struct bpf_program*
|
||||
ebpf_program_previous(_In_opt_ const struct bpf_program* next, _In_ const struct bpf_object* object);
|
||||
|
||||
/**
|
||||
* @brief Unload an eBPF program.
|
||||
*
|
||||
* @param[in] program Program to unload.
|
||||
*
|
||||
* @retval EBPF_SUCCESS The operation was successful.
|
||||
* @retval EBPF_INVALID_ARGUMENT One or more parameters are wrong.
|
||||
*/
|
||||
ebpf_result_t
|
||||
ebpf_program_unload(_In_ struct bpf_program* program);
|
||||
|
||||
/**
|
||||
* @brief Get next map in ebpf_object object.
|
||||
*
|
||||
|
@ -179,7 +191,7 @@ ebpf_map_get_fd(_In_ const struct bpf_map* map);
|
|||
* @param[in] object Pointer to ebpf_object.
|
||||
*/
|
||||
void
|
||||
ebpf_object_close(_In_ _Post_invalid_ struct bpf_object* object);
|
||||
ebpf_object_close(_In_opt_ _Post_invalid_ struct bpf_object* object);
|
||||
|
||||
void
|
||||
initialize_map(_Out_ ebpf_map_t* map, _In_ const map_cache_t& map_cache);
|
||||
|
@ -391,3 +403,59 @@ ebpf_object_pin(fd_t fd, _In_z_ const char* path);
|
|||
*/
|
||||
fd_t
|
||||
ebpf_object_get(_In_z_ const char* path);
|
||||
|
||||
/**
|
||||
* @brief Open a file without loading the programs.
|
||||
*
|
||||
* @param[in] path File name to open.
|
||||
* @param[in] object_name Optional object name to override file name
|
||||
* as the object name.
|
||||
* @param[in] program_type Optional program type for all programs.
|
||||
* If NULL, the program type is derived from the section names.
|
||||
* @param[in] attach_type Default attach type for all programs.
|
||||
* If NULL, the attach type is derived from the section names.
|
||||
* @param[out] object Returns a pointer to the object created.
|
||||
* @param[out] error_message Error message string, which
|
||||
* the caller must free using ebpf_free_string().
|
||||
*
|
||||
* @retval EBPF_SUCCESS The operation was successful.
|
||||
* @retval EBPF_INVALID_ARGUMENT One or more parameters are wrong.
|
||||
* @retval EBPF_NO_MEMORY Out of memory.
|
||||
*/
|
||||
ebpf_result_t
|
||||
ebpf_object_open(
|
||||
_In_z_ const char* path,
|
||||
_In_opt_z_ const char* object_name,
|
||||
_In_opt_ const ebpf_program_type_t* program_type,
|
||||
_In_opt_ const ebpf_attach_type_t* attach_type,
|
||||
_Outptr_ struct bpf_object** object,
|
||||
_Outptr_result_maybenull_z_ const char** error_message) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Load all the programs in a given object.
|
||||
*
|
||||
* @param[in] object Object from which to load programs.
|
||||
* @param[in] execution_type Execution type.
|
||||
* @param[out] error_message Error message string, which
|
||||
* the caller must free using ebpf_free_string().
|
||||
*
|
||||
* @retval EBPF_SUCCESS The operation was successful.
|
||||
* @retval EBPF_INVALID_ARGUMENT One or more parameters are wrong.
|
||||
* @retval EBPF_NO_MEMORY Out of memory.
|
||||
*/
|
||||
ebpf_result_t
|
||||
ebpf_object_load(
|
||||
_Inout_ struct bpf_object* object,
|
||||
ebpf_execution_type_t execution_type,
|
||||
_Outptr_result_maybenull_z_ const char** error_message);
|
||||
|
||||
/**
|
||||
* @brief Unload all the programs in a given object.
|
||||
*
|
||||
* @param[in] object Object in which to unload programs.
|
||||
*
|
||||
* @retval EBPF_SUCCESS The operation was successful.
|
||||
* @retval EBPF_INVALID_ARGUMENT One or more parameters are wrong.
|
||||
*/
|
||||
ebpf_result_t
|
||||
ebpf_object_unload(_In_ struct bpf_object* object);
|
||||
|
|
|
@ -287,7 +287,7 @@ _get_map_descriptor_properties(
|
|||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
ebpf_map_t* map;
|
||||
|
||||
*type = BPF_MAP_TYPE_UNSPECIFIED;
|
||||
*type = BPF_MAP_TYPE_UNSPEC;
|
||||
*key_size = 0;
|
||||
*value_size = 0;
|
||||
|
||||
|
@ -1101,7 +1101,10 @@ ebpf_program_attach(
|
|||
} else {
|
||||
program_attach_type = &program->attach_type;
|
||||
}
|
||||
assert(program->handle != ebpf_handle_invalid);
|
||||
if (program->handle == ebpf_handle_invalid) {
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
result =
|
||||
_link_ebpf_program(program->handle, program_attach_type, link, (uint8_t*)attach_parameters, attach_params_size);
|
||||
|
@ -1285,12 +1288,8 @@ clean_up_ebpf_program(_In_ _Post_invalid_ ebpf_program_t* program)
|
|||
if (program == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (program->fd != ebpf_fd_invalid) {
|
||||
Platform::_close(program->fd);
|
||||
}
|
||||
if (program->handle != ebpf_handle_invalid) {
|
||||
_ebpf_programs.erase(program->handle);
|
||||
}
|
||||
ebpf_program_unload(program);
|
||||
|
||||
free(program->byte_code);
|
||||
free(program->program_name);
|
||||
free(program->section_name);
|
||||
|
@ -1313,7 +1312,7 @@ clean_up_ebpf_map(_In_ _Post_invalid_ ebpf_map_t* map)
|
|||
if (map == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (map->map_fd != 0) {
|
||||
if (map->map_fd > 0) {
|
||||
Platform::_close(map->map_fd);
|
||||
}
|
||||
if (map->map_handle != ebpf_handle_invalid) {
|
||||
|
@ -1392,6 +1391,7 @@ initialize_map(_Out_ ebpf_map_t* map, _In_ const map_cache_t& map_cache)
|
|||
static ebpf_result_t
|
||||
_initialize_ebpf_object_from_elf(
|
||||
_In_z_ const char* file_name,
|
||||
_In_opt_z_ const char* object_name,
|
||||
_In_opt_ const ebpf_program_type_t* expected_program_type,
|
||||
_In_opt_ const ebpf_attach_type_t* expected_attach_type,
|
||||
_Out_ ebpf_object_t& object,
|
||||
|
@ -1406,16 +1406,18 @@ _initialize_ebpf_object_from_elf(
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
object.file_name = _strdup(file_name);
|
||||
if (object.file_name == nullptr) {
|
||||
object.object_name = _strdup(object_name ? object_name : file_name);
|
||||
if (object.object_name == nullptr) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for (auto& program : object.programs) {
|
||||
program->fd = ebpf_fd_invalid;
|
||||
program->object = &object;
|
||||
}
|
||||
for (auto& map : object.maps) {
|
||||
map->map_fd = ebpf_fd_invalid;
|
||||
map->object = &object;
|
||||
}
|
||||
|
||||
|
@ -1475,6 +1477,214 @@ _get_next_map_to_create(std::vector<ebpf_map_t*>& maps)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_object_open(
|
||||
_In_z_ const char* path,
|
||||
_In_opt_z_ const char* object_name,
|
||||
_In_opt_ const ebpf_program_type_t* program_type,
|
||||
_In_opt_ const ebpf_attach_type_t* attach_type,
|
||||
_Outptr_ struct bpf_object** object,
|
||||
_Outptr_result_maybenull_z_ const char** error_message) noexcept
|
||||
{
|
||||
*error_message = nullptr;
|
||||
|
||||
ebpf_object_t* new_object = new (std::nothrow) ebpf_object_t();
|
||||
if (new_object == nullptr) {
|
||||
return EBPF_NO_MEMORY;
|
||||
}
|
||||
|
||||
ebpf_result_t result =
|
||||
_initialize_ebpf_object_from_elf(path, object_name, program_type, attach_type, *new_object, error_message);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
*object = new_object;
|
||||
_ebpf_objects.emplace_back(*object);
|
||||
|
||||
Done:
|
||||
clear_map_descriptors();
|
||||
if (result != EBPF_SUCCESS) {
|
||||
_clean_up_ebpf_object(new_object);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_object_create_maps(_Inout_ ebpf_object_t* object)
|
||||
{
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
|
||||
clear_map_descriptors();
|
||||
|
||||
// TODO: update ebpf_map_definition_t structure so that it contains flag and pinning information.
|
||||
for (int count = 0; count < object->maps.size(); count++) {
|
||||
ebpf_map_t* map = _get_next_map_to_create(object->maps);
|
||||
if (map == nullptr) {
|
||||
// Any remaining maps cannot be created.
|
||||
result = EBPF_INVALID_OBJECT;
|
||||
break;
|
||||
}
|
||||
|
||||
ebpf_handle_t inner_map_handle = (map->inner_map) ? map->inner_map->map_handle : ebpf_handle_invalid;
|
||||
result = _create_map(map->name, &map->map_definition, inner_map_handle, &map->map_handle);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
map->map_fd = _create_file_descriptor_for_handle(map->map_handle);
|
||||
}
|
||||
|
||||
if (result != EBPF_SUCCESS) {
|
||||
clean_up_ebpf_maps(object->maps);
|
||||
} else {
|
||||
for (auto& map : object->maps) {
|
||||
_ebpf_maps.insert(std::pair<ebpf_handle_t, ebpf_map_t*>(map->map_handle, map));
|
||||
}
|
||||
}
|
||||
clear_map_descriptors();
|
||||
return result;
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_object_load_programs(
|
||||
_Inout_ struct bpf_object* object,
|
||||
_In_ ebpf_execution_type_t execution_type,
|
||||
_Outptr_result_maybenull_z_ const char** log_buffer)
|
||||
{
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
std::vector<original_fd_handle_map_t> handle_map;
|
||||
uint32_t error_message_size = 0;
|
||||
|
||||
*log_buffer = nullptr;
|
||||
|
||||
for (auto& program : object->programs) {
|
||||
result = _create_program(
|
||||
program->program_type, object->object_name, program->section_name, program->program_name, &program->handle);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
program->fd = _create_file_descriptor_for_handle(program->handle);
|
||||
|
||||
// Populate load_info.
|
||||
ebpf_program_load_info load_info = {0};
|
||||
load_info.object_name = const_cast<char*>(object->object_name);
|
||||
load_info.section_name = const_cast<char*>(program->section_name);
|
||||
load_info.program_name = const_cast<char*>(program->program_name);
|
||||
load_info.program_type = program->program_type;
|
||||
load_info.program_handle = reinterpret_cast<file_handle_t>(program->handle);
|
||||
load_info.execution_type = execution_type;
|
||||
load_info.byte_code = program->byte_code;
|
||||
load_info.byte_code_size = program->byte_code_size;
|
||||
load_info.execution_context = execution_context_kernel_mode;
|
||||
load_info.map_count = (uint32_t)object->maps.size();
|
||||
|
||||
if (load_info.map_count > 0) {
|
||||
for (auto& map : object->maps) {
|
||||
fd_t inner_map_original_fd = (map->inner_map) ? map->inner_map->original_fd : ebpf_fd_invalid;
|
||||
handle_map.emplace_back(
|
||||
map->original_fd, inner_map_original_fd, reinterpret_cast<file_handle_t>(map->map_handle));
|
||||
}
|
||||
|
||||
load_info.handle_map = handle_map.data();
|
||||
}
|
||||
|
||||
result = ebpf_rpc_load_program(&load_info, log_buffer, &error_message_size);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == EBPF_SUCCESS) {
|
||||
for (auto& program : object->programs) {
|
||||
_ebpf_programs.insert(std::pair<ebpf_handle_t, ebpf_program_t*>(program->handle, program));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// This logic is intended to be similar to libbpf's bpf_object__load_xattr().
|
||||
ebpf_result_t
|
||||
ebpf_object_load(
|
||||
_Inout_ struct bpf_object* object,
|
||||
ebpf_execution_type_t execution_type,
|
||||
_Outptr_result_maybenull_z_ const char** log_buffer)
|
||||
{
|
||||
if (!object)
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
|
||||
if (object->loaded) {
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
try {
|
||||
result = _ebpf_object_create_maps(object);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
result = _ebpf_object_load_programs(object, execution_type, log_buffer);
|
||||
} catch (const std::bad_alloc&) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
goto Done;
|
||||
} catch (...) {
|
||||
result = EBPF_FAILED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
object->loaded = true; /* doesn't matter if successfully loaded or not */
|
||||
|
||||
Done:
|
||||
if (result != EBPF_SUCCESS) {
|
||||
ebpf_object_unload(object);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// This function is intended to work like libbpf's bpf_object__unload().
|
||||
ebpf_result_t
|
||||
ebpf_object_unload(_In_ struct bpf_object* object)
|
||||
{
|
||||
if (!object)
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
|
||||
for (auto& map : object->maps) {
|
||||
if (map->map_fd > 0) {
|
||||
Platform::_close(map->map_fd);
|
||||
map->map_fd = ebpf_fd_invalid;
|
||||
}
|
||||
if (map->map_handle != ebpf_handle_invalid) {
|
||||
_ebpf_maps.erase(map->map_handle);
|
||||
map->map_handle = ebpf_handle_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& program : object->programs) {
|
||||
ebpf_program_unload(program);
|
||||
}
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
}
|
||||
|
||||
// This function is intended to work like libbpf's bpf_program__unload().
|
||||
ebpf_result_t
|
||||
ebpf_program_unload(_In_ struct bpf_program* program)
|
||||
{
|
||||
if (!program)
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
|
||||
if (program->fd != ebpf_fd_invalid) {
|
||||
Platform::_close(program->fd);
|
||||
program->fd = ebpf_fd_invalid;
|
||||
}
|
||||
if (program->handle != ebpf_handle_invalid) {
|
||||
_ebpf_programs.erase(program->handle);
|
||||
program->handle = ebpf_handle_invalid;
|
||||
}
|
||||
return EBPF_SUCCESS;
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_load(
|
||||
_In_z_ const char* file_name,
|
||||
|
@ -1487,11 +1697,8 @@ ebpf_program_load(
|
|||
{
|
||||
ebpf_object_t* new_object = nullptr;
|
||||
ebpf_protocol_buffer_t request_buffer;
|
||||
uint32_t error_message_size = 0;
|
||||
std::vector<uintptr_t> handles;
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
ebpf_program_load_info load_info = {0};
|
||||
std::vector<original_fd_handle_map_t> handle_map;
|
||||
|
||||
if (file_name == nullptr || object == nullptr || program_fd == nullptr || log_buffer == nullptr) {
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
|
@ -1506,85 +1713,19 @@ ebpf_program_load(
|
|||
}
|
||||
|
||||
clear_map_descriptors();
|
||||
*log_buffer = nullptr;
|
||||
*object = nullptr;
|
||||
|
||||
try {
|
||||
new_object = new ebpf_object_t();
|
||||
if (new_object == nullptr) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
result = _initialize_ebpf_object_from_elf(file_name, program_type, attach_type, *new_object, log_buffer);
|
||||
result = ebpf_object_open(file_name, nullptr, program_type, attach_type, &new_object, log_buffer);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// Create all maps.
|
||||
// TODO: update ebpf_map_definition_t structure so that it contains flag and pinning information.
|
||||
for (int count = 0; count < new_object->maps.size(); count++) {
|
||||
ebpf_map_t* map = _get_next_map_to_create(new_object->maps);
|
||||
if (map == nullptr) {
|
||||
// Any remaining maps cannot be created.
|
||||
result = EBPF_INVALID_OBJECT;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
ebpf_handle_t inner_map_handle = (map->inner_map) ? map->inner_map->map_handle : ebpf_handle_invalid;
|
||||
result = _create_map(map->name, &map->map_definition, inner_map_handle, &map->map_handle);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
map->map_fd = _create_file_descriptor_for_handle(map->map_handle);
|
||||
}
|
||||
|
||||
for (auto& program : new_object->programs) {
|
||||
result = _create_program(
|
||||
program->program_type, file_name, program->section_name, program->program_name, &program->handle);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
program->fd = _create_file_descriptor_for_handle(program->handle);
|
||||
|
||||
// populate load_info.
|
||||
load_info.file_name = const_cast<char*>(file_name);
|
||||
load_info.section_name = const_cast<char*>(program->section_name);
|
||||
load_info.program_name = const_cast<char*>(program->program_name);
|
||||
load_info.program_type = program->program_type;
|
||||
load_info.program_handle = reinterpret_cast<file_handle_t>(program->handle);
|
||||
load_info.execution_type = execution_type;
|
||||
load_info.byte_code = program->byte_code;
|
||||
load_info.byte_code_size = program->byte_code_size;
|
||||
load_info.execution_context = execution_context_kernel_mode;
|
||||
load_info.map_count = (uint32_t)new_object->maps.size();
|
||||
|
||||
if (load_info.map_count > 0) {
|
||||
for (auto& map : new_object->maps) {
|
||||
fd_t inner_map_original_fd = (map->inner_map) ? map->inner_map->original_fd : ebpf_fd_invalid;
|
||||
handle_map.emplace_back(
|
||||
map->original_fd, inner_map_original_fd, reinterpret_cast<file_handle_t>(map->map_handle));
|
||||
}
|
||||
|
||||
load_info.handle_map = handle_map.data();
|
||||
}
|
||||
|
||||
result = ebpf_rpc_load_program(&load_info, log_buffer, &error_message_size);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& program : new_object->programs) {
|
||||
_ebpf_programs.insert(std::pair<ebpf_handle_t, ebpf_program_t*>(program->handle, program));
|
||||
}
|
||||
for (auto& map : new_object->maps) {
|
||||
_ebpf_maps.insert(std::pair<ebpf_handle_t, ebpf_map_t*>(map->map_handle, map));
|
||||
result = ebpf_object_load(new_object, execution_type, log_buffer);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
*object = new_object;
|
||||
_ebpf_objects.emplace_back(*object);
|
||||
*program_fd = new_object->programs[0]->fd;
|
||||
} catch (const std::bad_alloc&) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
|
@ -1596,7 +1737,7 @@ ebpf_program_load(
|
|||
|
||||
Done:
|
||||
if (result != EBPF_SUCCESS) {
|
||||
_clean_up_ebpf_object(new_object);
|
||||
ebpf_object_close(new_object);
|
||||
}
|
||||
clear_map_descriptors();
|
||||
return result;
|
||||
|
@ -1745,7 +1886,7 @@ ebpf_map_get_fd(_In_ const struct bpf_map* map)
|
|||
}
|
||||
|
||||
void
|
||||
ebpf_object_close(_In_ _Post_invalid_ struct bpf_object* object)
|
||||
ebpf_object_close(_In_opt_ _Post_invalid_ struct bpf_object* object)
|
||||
{
|
||||
if (object == nullptr) {
|
||||
return;
|
||||
|
|
|
@ -18,3 +18,10 @@ libbpf_result_err(ebpf_result_t result)
|
|||
{
|
||||
return libbpf_err(-ebpf_result_to_errno(result));
|
||||
}
|
||||
|
||||
static inline void*
|
||||
libbpf_err_ptr(int err)
|
||||
{
|
||||
errno = -err;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
const char*
|
||||
bpf_object__name(const struct bpf_object* object)
|
||||
{
|
||||
return object->file_name;
|
||||
return object->object_name;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -54,8 +54,7 @@ bpf_object__find_program_by_name(const struct bpf_object* obj, const char* name)
|
|||
if (!strcmp(prog->program_name, name))
|
||||
return prog;
|
||||
}
|
||||
errno = ENOENT;
|
||||
return nullptr;
|
||||
return (struct bpf_program*)libbpf_err_ptr(-ENOENT);
|
||||
}
|
||||
|
||||
struct bpf_object*
|
||||
|
@ -83,3 +82,43 @@ bpf_obj_get(const char* pathname)
|
|||
{
|
||||
return (int)ebpf_object_get(pathname);
|
||||
}
|
||||
|
||||
struct bpf_object*
|
||||
bpf_object__open_file(const char* path, const struct bpf_object_open_opts* opts)
|
||||
{
|
||||
if (!path) {
|
||||
return (struct bpf_object*)libbpf_err_ptr(-EINVAL);
|
||||
}
|
||||
|
||||
struct bpf_object* object;
|
||||
const char* error_message;
|
||||
ebpf_result_t result = ebpf_object_open(path, opts->object_name, nullptr, nullptr, &object, &error_message);
|
||||
ebpf_free_string(error_message);
|
||||
libbpf_result_err(result); // Set errno.
|
||||
return object;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__load_xattr(struct bpf_object_load_attr* attr)
|
||||
{
|
||||
const char* error_message;
|
||||
ebpf_result result = ebpf_object_load(attr->obj, EBPF_EXECUTION_ANY, &error_message);
|
||||
ebpf_free_string(error_message);
|
||||
return libbpf_result_err(result);
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__load(struct bpf_object* object)
|
||||
{
|
||||
struct bpf_object_load_attr attr = {
|
||||
.obj = object,
|
||||
};
|
||||
|
||||
return bpf_object__load_xattr(&attr);
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__unload(struct bpf_object* obj)
|
||||
{
|
||||
return libbpf_result_err(ebpf_object_unload(obj));
|
||||
}
|
||||
|
|
|
@ -27,6 +27,19 @@ _get_ebpf_program_type(enum bpf_prog_type type)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static enum bpf_prog_type
|
||||
_get_bpf_program_type(const ebpf_program_type_t* type)
|
||||
{
|
||||
// TODO(issue #223): read this mapping from the registry
|
||||
if (memcmp(type, &EBPF_PROGRAM_TYPE_XDP, sizeof(*type)) == 0) {
|
||||
return BPF_PROG_TYPE_XDP;
|
||||
}
|
||||
if (memcmp(type, &EBPF_PROGRAM_TYPE_BIND, sizeof(*type)) == 0) {
|
||||
return BPF_PROG_TYPE_BIND;
|
||||
}
|
||||
return BPF_PROG_TYPE_UNSPEC;
|
||||
}
|
||||
|
||||
static const ebpf_attach_type_t*
|
||||
_get_ebpf_attach_type(enum bpf_attach_type type)
|
||||
{
|
||||
|
@ -271,6 +284,19 @@ bpf_program__set_expected_attach_type(struct bpf_program* program, enum bpf_atta
|
|||
program->attach_type = *_get_ebpf_attach_type(type);
|
||||
}
|
||||
|
||||
enum bpf_prog_type
|
||||
bpf_program__get_type(const struct bpf_program* program)
|
||||
{
|
||||
return _get_bpf_program_type(&program->program_type);
|
||||
}
|
||||
|
||||
void
|
||||
bpf_program__set_type(struct bpf_program* program, enum bpf_prog_type type)
|
||||
{
|
||||
const ebpf_program_type_t* program_type = _get_ebpf_program_type(type);
|
||||
program->program_type = (program_type != nullptr) ? *program_type : EBPF_PROGRAM_TYPE_UNSPECIFIED;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_prog_get_fd_by_id(uint32_t id)
|
||||
{
|
||||
|
@ -318,3 +344,12 @@ libbpf_prog_type_by_name(const char* name, enum bpf_prog_type* prog_type, enum b
|
|||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
bpf_program__unload(struct bpf_program* prog)
|
||||
{
|
||||
ebpf_result_t result = ebpf_program_unload(prog);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
errno = ebpf_result_to_errno(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <windows.h>
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
long
|
||||
libbpf_get_error(const void* ptr)
|
||||
{
|
||||
/* Older versions of Linux encode error numbers in a
|
||||
* void* in some cases, so libbpf has to deal with both
|
||||
* that case and the simple case of using errno, so
|
||||
* exposes this API to be agnostic. But we always use
|
||||
* errno, so don't need to look at the ptr value.
|
||||
*/
|
||||
UNREFERENCED_PARAMETER(ptr);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int
|
||||
libbpf_num_possible_cpus(void)
|
||||
{
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
}
|
|
@ -120,7 +120,7 @@ get_program_type_windows(const std::string& section, const std::string&)
|
|||
#define BPF_MAP_TYPE(x) BPF_MAP_TYPE_##x, #x
|
||||
|
||||
static const EbpfMapType windows_map_types[] = {
|
||||
{BPF_MAP_TYPE(UNSPECIFIED)},
|
||||
{BPF_MAP_TYPE(UNSPEC)},
|
||||
{BPF_MAP_TYPE(HASH)},
|
||||
{BPF_MAP_TYPE(ARRAY), true},
|
||||
{BPF_MAP_TYPE(PROG_ARRAY), true, EbpfMapValueType::PROGRAM},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <netsh.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "ebpf_api.h"
|
||||
#include "ebpf_windows.h"
|
||||
#include "platform.h"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <netsh.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "ebpf_api.h"
|
||||
#include "ebpf_windows.h"
|
||||
#include "platform.h"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "ebpf_api.h"
|
||||
#include "ebpf_windows.h"
|
||||
#include "pins.h"
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
#include <windows.h>
|
||||
#include <combaseapi.h>
|
||||
#include <netsh.h>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "ebpf_api.h"
|
||||
#include "libbpf.h"
|
||||
#include "platform.h"
|
||||
#include "programs.h"
|
||||
#include "tokens.h"
|
||||
|
|
|
@ -188,6 +188,8 @@ ebpf_link_get_info(
|
|||
|
||||
info->id = link->object.id;
|
||||
info->prog_id = (link->program) ? ((ebpf_object_t*)link->program)->id : EBPF_ID_NONE;
|
||||
info->type = BPF_LINK_TYPE_PLAIN;
|
||||
info->attach_type = BPF_ATTACH_TYPE_UNSPEC; // TODO(#223): get actual integer, and also return attach_type_uuid
|
||||
|
||||
*info_size = sizeof(*info);
|
||||
return EBPF_SUCCESS;
|
||||
|
|
|
@ -872,7 +872,7 @@ ebpf_program_get_info(
|
|||
(char*)program->parameters.program_name.value,
|
||||
program->parameters.program_name.length);
|
||||
info->nr_map_ids = program->count_of_maps;
|
||||
info->type = BPF_PROG_TYPE_UNKNOWN; // TODO(issue #223): get integer if any.
|
||||
info->type = BPF_PROG_TYPE_UNSPEC; // TODO(issue #223): get integer if any.
|
||||
info->type_uuid = *ebpf_program_type(program);
|
||||
info->pinned_path_count = program->object.pinned_path_count;
|
||||
info->link_count = program->link_count;
|
||||
|
|
|
@ -45,8 +45,8 @@ import "wtypes.idl";
|
|||
|
||||
typedef struct _ebpf_program_load_info
|
||||
{
|
||||
// Optional file name.
|
||||
[string] char* file_name;
|
||||
// Object name.
|
||||
[string] char* object_name;
|
||||
// Optional section name.
|
||||
[string] char* section_name;
|
||||
// Optional program name.
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
#include "api_test.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "common_tests.h"
|
||||
#include <io.h>
|
||||
#include "service_helper.h"
|
||||
#include "libbpf.h"
|
||||
#define SAMPLE_PATH ""
|
||||
|
||||
#define EBPF_CORE_DRIVER_BINARY_NAME L"ebpfcore.sys"
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
#include <WinSock2.h>
|
||||
#include <in6addr.h> // Must come after Winsock2.h
|
||||
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "common_tests.h"
|
||||
#include "ebpf_bind_program_data.h"
|
||||
#include "ebpf_core.h"
|
||||
#include "ebpf_xdp_program_data.h"
|
||||
#include "helpers.h"
|
||||
#include "libbpf.h"
|
||||
#include "mock.h"
|
||||
#include "platform.h"
|
||||
#include "program_helper.h"
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
#include <windows.h>
|
||||
#include <netsh.h> // Must be included after windows.h
|
||||
#include <string.h>
|
||||
#include "ebpf_epoch.h"
|
||||
#include "bpf/bpf.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#pragma warning(pop)
|
||||
#include "ebpf_epoch.h"
|
||||
#include "netsh_test_helper.h"
|
||||
#include "platform.h"
|
||||
#include "programs.h"
|
||||
#include "test_helper.hpp"
|
||||
|
||||
TEST_CASE("show disassembly bpf.o", "[netsh][disassembly]")
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <windows.h>
|
||||
#include <netsh.h> // Must be included after windows.h
|
||||
#include <string.h>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "capture_helper.hpp"
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "elf.h"
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "ebpf_api.h"
|
||||
#include "ebpf_result.h"
|
||||
#include "libbpf.h"
|
||||
|
||||
void
|
||||
ebpf_test_pinned_map_enum();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <windows.h>
|
||||
#include <netsh.h> // Must be included after windows.h
|
||||
#include <string.h>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "capture_helper.hpp"
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "elf.h"
|
||||
|
@ -129,4 +129,4 @@ _run_netsh_command(
|
|||
|
||||
*result = NO_ERROR;
|
||||
return capture.get_stdout_contents();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
* @brief Utility functions for loading and attaching test eBPF programs.
|
||||
*/
|
||||
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "helpers.h"
|
||||
#include "libbpf.h"
|
||||
|
||||
typedef class _program_load_attach_helper
|
||||
{
|
||||
|
|
|
@ -169,8 +169,8 @@ static const char*
|
|||
_ebpf_map_type_t_to_string(ebpf_map_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case BPF_MAP_TYPE_UNSPECIFIED:
|
||||
return "BPF_MAP_TYPE_UNSPECIFIED";
|
||||
case BPF_MAP_TYPE_UNSPEC:
|
||||
return "BPF_MAP_TYPE_UNSPEC";
|
||||
case BPF_MAP_TYPE_HASH:
|
||||
return "BPF_MAP_TYPE_HASH";
|
||||
case BPF_MAP_TYPE_ARRAY:
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "ebpf_object.h"
|
||||
#include "ebpf_program.h"
|
||||
#include "helpers.h"
|
||||
#include "libbpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "performance_measure.h"
|
||||
|
||||
#define PERF_TEST(FUNCTION) \
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "common_tests.h"
|
||||
#include "libbpf.h"
|
||||
#include "netsh_test_helper.h"
|
||||
#include "program_helper.h"
|
||||
#include "service_helper.h"
|
||||
|
@ -161,4 +161,4 @@ TEST_CASE("netsh_add_program_test_sample_ebpf", "[sample_ext_test]")
|
|||
_run_netsh_command(handle_ebpf_add_program, L"test_sample_ebpf.o", L"pinned=none", nullptr, &result);
|
||||
REQUIRE(result == NO_ERROR);
|
||||
REQUIRE(output.starts_with("Loaded with"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
#include <io.h>
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include "bpf.h"
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "helpers.h"
|
||||
#include "bpf/bpf.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#pragma warning(pop)
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "helpers.h"
|
||||
#include "platform.h"
|
||||
#include "program_helper.h"
|
||||
#include "test_helper.hpp"
|
||||
|
@ -875,3 +875,49 @@ TEST_CASE("libbpf_prog_type_by_name", "[libbpf]")
|
|||
REQUIRE(prog_type == BPF_PROG_TYPE_XDP);
|
||||
REQUIRE(expected_attach_type == BPF_ATTACH_TYPE_XDP);
|
||||
}
|
||||
|
||||
TEST_CASE("libbpf_get_error", "[libbpf]")
|
||||
{
|
||||
errno = 123;
|
||||
REQUIRE(libbpf_get_error(nullptr) == -123);
|
||||
}
|
||||
|
||||
TEST_CASE("bpf_object__load", "[libbpf]")
|
||||
{
|
||||
_test_helper_libbpf test_helper;
|
||||
|
||||
const char* my_object_name = "my_object_name";
|
||||
struct bpf_object_open_opts opts = {0};
|
||||
opts.object_name = my_object_name;
|
||||
struct bpf_object* object = bpf_object__open_file("droppacket.o", &opts);
|
||||
REQUIRE(object != nullptr);
|
||||
|
||||
REQUIRE(strcmp(bpf_object__name(object), my_object_name) == 0);
|
||||
|
||||
struct bpf_program* program = bpf_object__find_program_by_name(object, "DropPacket");
|
||||
REQUIRE(program != nullptr);
|
||||
|
||||
REQUIRE(bpf_program__fd(program) == ebpf_fd_invalid);
|
||||
REQUIRE(bpf_program__get_type(program) == BPF_PROG_TYPE_XDP);
|
||||
|
||||
// Make sure we can override the program type if desired.
|
||||
bpf_program__set_type(program, BPF_PROG_TYPE_BIND);
|
||||
REQUIRE(bpf_program__get_type(program) == BPF_PROG_TYPE_BIND);
|
||||
|
||||
bpf_program__set_type(program, BPF_PROG_TYPE_XDP);
|
||||
|
||||
// Trying to attach the program should fail since it's not loaded yet.
|
||||
bpf_link* link = bpf_program__attach(program);
|
||||
REQUIRE(link == nullptr);
|
||||
REQUIRE(libbpf_get_error(link) == -EINVAL);
|
||||
|
||||
// Load the program.
|
||||
REQUIRE(bpf_object__load(object) == 0);
|
||||
|
||||
// Attach should now succeed.
|
||||
link = bpf_program__attach(program);
|
||||
REQUIRE(link != nullptr);
|
||||
|
||||
REQUIRE(bpf_link__destroy(link) == 0);
|
||||
bpf_object__close(object);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
#include "bpf.h"
|
||||
#include "bpf/bpf.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include "ebpf_api.h"
|
||||
#include "libbpf.h"
|
||||
|
||||
const char* process_map = "port_quota::process_map";
|
||||
const char* limits_map = "port_quota::limits_map";
|
||||
|
|
Загрузка…
Ссылка в новой задаче