Libbpf API compatibility (#350)
* Libbpf API compatibility Libbpf is incorporated as a submodule just for the header file. As discussed in issue #84, we cannot currently use the implementation since it is very Linux and GCC specific. This PR also fixes a bug where the user-mode API was calling CloseHandle directly instead of Platform::CloseHandle which is needed to make tests work with the mock platform. Addresses #84 Some code will be cleaner once issue #81 is done Signed-off-by: Dave Thaler <dthaler@microsoft.com>
This commit is contained in:
Родитель
4bebd3aaa1
Коммит
8006f181e0
|
@ -6,3 +6,6 @@
|
|||
path = external/ubpf
|
||||
url = https://github.com/iovisor/ubpf.git
|
||||
branch = master
|
||||
[submodule "external/libbpf"]
|
||||
path = external/libbpf
|
||||
url = https://github.com/libbpf/libbpf.git
|
||||
|
|
|
@ -5,34 +5,65 @@
|
|||
|
||||
LIBRARY
|
||||
EXPORTS
|
||||
ebpf_api_initiate
|
||||
ebpf_api_terminate
|
||||
ebpf_api_load_program
|
||||
ebpf_api_create_map
|
||||
ebpf_api_map_find_element
|
||||
ebpf_api_map_update_element
|
||||
ebpf_api_map_delete_element
|
||||
ebpf_api_get_next_map_key
|
||||
ebpf_api_elf_enumerate_sections
|
||||
ebpf_api_elf_disassemble_section
|
||||
ebpf_api_elf_verify_section
|
||||
ebpf_api_elf_free
|
||||
ebpf_api_pin_object
|
||||
ebpf_api_unpin_object
|
||||
ebpf_api_get_next_map
|
||||
ebpf_api_get_pinned_map
|
||||
ebpf_api_get_next_program
|
||||
ebpf_api_program_query_info
|
||||
ebpf_api_link_program
|
||||
ebpf_api_close_handle
|
||||
ebpf_api_get_pinned_map_info
|
||||
ebpf_api_map_info_free
|
||||
ebpf_free_string
|
||||
ebpf_map_get_fd
|
||||
ebpf_map_next
|
||||
ebpf_map_previous
|
||||
ebpf_object_close
|
||||
ebpf_program_get_fd
|
||||
ebpf_program_load
|
||||
ebpf_program_next
|
||||
ebpf_program_previous
|
||||
bpf_link__destroy
|
||||
bpf_map__fd
|
||||
bpf_map__is_pinned
|
||||
bpf_map__key_size
|
||||
bpf_map__max_entries
|
||||
bpf_map__next
|
||||
bpf_map__pin
|
||||
bpf_map__prev
|
||||
bpf_map__type
|
||||
bpf_map__unpin
|
||||
bpf_map__value_size
|
||||
bpf_object__close
|
||||
bpf_object__find_program_by_name
|
||||
bpf_object__name
|
||||
bpf_object__pin
|
||||
bpf_object__pin_maps
|
||||
bpf_object__pin_programs
|
||||
bpf_object__unpin_maps
|
||||
bpf_object__unpin_programs
|
||||
bpf_prog_load
|
||||
bpf_program__attach
|
||||
bpf_program__attach_xdp
|
||||
bpf_program__fd
|
||||
bpf_program__get_expected_attach_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__unpin
|
||||
ebpf_api_initiate
|
||||
ebpf_api_terminate
|
||||
ebpf_api_load_program
|
||||
ebpf_api_create_map
|
||||
ebpf_api_map_find_element
|
||||
ebpf_api_map_update_element
|
||||
ebpf_api_map_delete_element
|
||||
ebpf_api_get_next_map_key
|
||||
ebpf_api_elf_enumerate_sections
|
||||
ebpf_api_elf_disassemble_section
|
||||
ebpf_api_elf_verify_section
|
||||
ebpf_api_elf_free
|
||||
ebpf_api_pin_object
|
||||
ebpf_api_unpin_object
|
||||
ebpf_api_get_next_map
|
||||
ebpf_api_get_pinned_map
|
||||
ebpf_api_get_next_program
|
||||
ebpf_api_program_query_info
|
||||
ebpf_api_link_program
|
||||
ebpf_api_close_handle
|
||||
ebpf_api_get_pinned_map_info
|
||||
ebpf_api_map_info_free
|
||||
ebpf_free_string
|
||||
ebpf_map_get_fd
|
||||
ebpf_map_next
|
||||
ebpf_map_previous
|
||||
ebpf_object_close
|
||||
ebpf_program_get_fd
|
||||
ebpf_program_load
|
||||
ebpf_program_next
|
||||
ebpf_program_previous
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 90405ffa91abbdbfd9f56b70adbfa0be6cc0fe3f
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// // SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
// This file is needed since bpf.h includes it.
|
||||
// It should be thought of as platform/bpf.h not Linux per se.
|
||||
|
||||
#include "ebpf_program_types.h"
|
||||
#include "ebpf_api.h"
|
||||
#define LIBBPF_API
|
||||
#include "libbpf_common.h"
|
||||
#undef LIBBPF_DEPRECATED
|
||||
#define LIBBPF_DEPRECATED(x)
|
||||
|
||||
typedef uint8_t __u8;
|
||||
typedef uint32_t __u32;
|
||||
typedef uint64_t __u64;
|
||||
typedef uint32_t pid_t;
|
||||
|
||||
#define bpf_map _ebpf_map
|
||||
#define bpf_map_type _ebpf_map_type
|
||||
#define bpf_object _ebpf_object
|
||||
#define bpf_program _ebpf_program
|
||||
#define bpf_prog_info _ebpf_program_info
|
||||
#define BPF_MAP_TYPE_ARRAY EBPF_MAP_TYPE_ARRAY
|
||||
|
||||
enum bpf_prog_type
|
||||
{
|
||||
BPF_PROG_TYPE_UNKNOWN,
|
||||
BPF_PROG_TYPE_XDP,
|
||||
};
|
||||
|
||||
enum bpf_attach_type
|
||||
{
|
||||
BPF_ATTACH_TYPE_UNKNOWN,
|
||||
BPF_ATTACH_TYPE_XDP,
|
||||
};
|
||||
|
||||
enum bpf_func_id
|
||||
{
|
||||
BPF_FUNC_ID_UNKNOWN
|
||||
};
|
||||
|
||||
enum bpf_stats_type
|
||||
{
|
||||
BPF_STATS_TYPE_UNKNOWN
|
||||
};
|
|
@ -97,6 +97,7 @@
|
|||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)external\libbpf\src;$(SolutionDir)libs\api;$(SolutionDir)rpc_interface;$(SolutionDir)libs\service;$(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\external\elfio;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -115,6 +116,7 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)external\libbpf\src;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -132,7 +134,7 @@
|
|||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)libs\api;$(SolutionDir)rpc_interface;$(SolutionDir)libs\service;$(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\external\elfio;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)external\libbpf\src;$(SolutionDir)libs\api;$(SolutionDir)rpc_interface;$(SolutionDir)libs\service;$(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\external\elfio;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
|
@ -154,7 +156,7 @@
|
|||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)rpc_interface;$(SolutionDir)libs\service;$(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\external\elfio;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)external\libbpf\src;$(SolutionDir)rpc_interface;$(SolutionDir)libs\service;$(SolutionDir)libs\api_common;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)external\ebpf-verifier\external;$(SolutionDir)external\ebpf-verifier\external\elfio;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
|
@ -171,6 +173,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ebpf_api.cpp" />
|
||||
<ClCompile Include="libbpf_object.cpp" />
|
||||
<ClCompile Include="libbpf_program.cpp" />
|
||||
<ClCompile Include="libbpf_map.cpp" />
|
||||
<ClCompile Include="Verifier.cpp" />
|
||||
<ClCompile Include="windows_platform.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -201,4 +206,4 @@
|
|||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\boost.1.75.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.75.0.0\build\boost.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
|
@ -25,6 +25,15 @@
|
|||
<ClCompile Include="windows_platform.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libbpf_program.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libbpf_map.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libbpf_object.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
|
|
@ -29,7 +29,7 @@ typedef struct _ebpf_map
|
|||
char* name;
|
||||
ebpf_handle_t map_handle;
|
||||
fd_t map_fd;
|
||||
ebpf_map_definition_t map_defintion;
|
||||
ebpf_map_definition_t map_definition;
|
||||
char* pin_path;
|
||||
bool pinned;
|
||||
} ebpf_map_t;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include "api_common.hpp"
|
||||
#include "api_internal.h"
|
||||
|
@ -677,7 +678,7 @@ clean_up_ebpf_program(_In_ _Post_invalid_ ebpf_program_t* program)
|
|||
_ebpf_programs.erase(program->fd);
|
||||
}
|
||||
if (program->handle != ebpf_handle_invalid) {
|
||||
CloseHandle(program->handle);
|
||||
Platform::CloseHandle(program->handle);
|
||||
}
|
||||
free(program->byte_code);
|
||||
free(program->program_name);
|
||||
|
@ -702,7 +703,7 @@ clean_up_ebpf_map(_In_ _Post_invalid_ ebpf_map_t* map)
|
|||
_ebpf_maps.erase(map->map_fd);
|
||||
}
|
||||
if (map->map_handle != ebpf_handle_invalid) {
|
||||
CloseHandle(map->map_handle);
|
||||
Platform::CloseHandle(map->map_handle);
|
||||
}
|
||||
|
||||
free(map);
|
||||
|
@ -758,10 +759,10 @@ _initialize_map(_Out_ ebpf_map_t* map, _In_ const ebpf_object_t* object, _In_ co
|
|||
map->object = object;
|
||||
map->map_handle = (ebpf_handle_t)map_cache.handle;
|
||||
map->map_fd = map_cache.ebpf_map_descriptor.original_fd;
|
||||
map->map_defintion.type = (ebpf_map_type_t)map_cache.ebpf_map_descriptor.type;
|
||||
map->map_defintion.key_size = map_cache.ebpf_map_descriptor.key_size;
|
||||
map->map_defintion.value_size = map_cache.ebpf_map_descriptor.value_size;
|
||||
map->map_defintion.max_entries = map_cache.ebpf_map_descriptor.max_entries;
|
||||
map->map_definition.type = (ebpf_map_type_t)map_cache.ebpf_map_descriptor.type;
|
||||
map->map_definition.key_size = map_cache.ebpf_map_descriptor.key_size;
|
||||
map->map_definition.value_size = map_cache.ebpf_map_descriptor.value_size;
|
||||
map->map_definition.max_entries = map_cache.ebpf_map_descriptor.max_entries;
|
||||
map->pinned = false;
|
||||
map->pin_path = nullptr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#define PATH_MAX MAX_PATH
|
||||
#define strdup _strdup
|
||||
|
||||
static inline int
|
||||
libbpf_err(int ret)
|
||||
{
|
||||
if (ret < 0)
|
||||
errno = -ret;
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "api_internal.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#pragma warning(pop)
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
// This file implements APIs in LibBPF's libbpf.h and is based on code in external/libbpf/src/libbpf.c
|
||||
// used under the BSD-2-Clause license , so the coding style tries to match the libbpf.c style to
|
||||
// minimize diffs until libbpf becomes cross-platform capable. This is a temporary workaround for
|
||||
// issue #351 until we can compile and use libbpf.c directly.
|
||||
|
||||
struct bpf_map*
|
||||
bpf_map__next(const struct bpf_map* previous, const struct bpf_object* object)
|
||||
{
|
||||
return ebpf_map_next(previous, object);
|
||||
}
|
||||
|
||||
struct bpf_map*
|
||||
bpf_map__prev(const struct bpf_map* next, const struct bpf_object* object)
|
||||
{
|
||||
return ebpf_map_previous(next, object);
|
||||
}
|
||||
|
||||
int
|
||||
bpf_map__unpin(struct bpf_map* map, const char* path)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (map == NULL) {
|
||||
return libbpf_err(-EINVAL);
|
||||
}
|
||||
|
||||
err = ebpf_api_unpin_object((const uint8_t*)path, (uint32_t)strlen(path));
|
||||
if (err) {
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
map->pinned = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_map__pin(struct bpf_map* map, const char* path)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (map == NULL) {
|
||||
return libbpf_err(-EINVAL);
|
||||
}
|
||||
|
||||
err = ebpf_api_pin_object(map->map_handle, (const uint8_t*)path, (uint32_t)strlen(path));
|
||||
if (err)
|
||||
return libbpf_err(-err);
|
||||
|
||||
map->pinned = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__pin_maps(struct bpf_object* obj, const char* path)
|
||||
{
|
||||
struct bpf_map* map;
|
||||
int err;
|
||||
|
||||
if (!obj)
|
||||
return libbpf_err(-ENOENT);
|
||||
|
||||
bpf_object__for_each_map(map, obj)
|
||||
{
|
||||
char* pin_path = NULL;
|
||||
char buf[PATH_MAX];
|
||||
|
||||
if (path) {
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path, bpf_map__name(map));
|
||||
if (len < 0) {
|
||||
err = -EINVAL;
|
||||
goto err_unpin_maps;
|
||||
} else if (len >= PATH_MAX) {
|
||||
err = -ENAMETOOLONG;
|
||||
goto err_unpin_maps;
|
||||
}
|
||||
pin_path = buf;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bpf_map__pin(map, pin_path);
|
||||
if (err)
|
||||
goto err_unpin_maps;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unpin_maps:
|
||||
while ((map = bpf_map__prev(map, obj)) != NULL) {
|
||||
bpf_map__unpin(map, NULL);
|
||||
}
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__unpin_maps(struct bpf_object* obj, const char* path)
|
||||
{
|
||||
struct bpf_map* map;
|
||||
int err;
|
||||
|
||||
if (!obj)
|
||||
return libbpf_err(-ENOENT);
|
||||
|
||||
bpf_object__for_each_map(map, obj)
|
||||
{
|
||||
char* pin_path = NULL;
|
||||
char buf[PATH_MAX];
|
||||
|
||||
if (path) {
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path, bpf_map__name(map));
|
||||
if (len < 0)
|
||||
return libbpf_err(-EINVAL);
|
||||
else if (len >= PATH_MAX)
|
||||
return libbpf_err(-ENAMETOOLONG);
|
||||
pin_path = buf;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bpf_map__unpin(map, pin_path);
|
||||
if (err)
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char*
|
||||
bpf_map__name(const struct bpf_map* map)
|
||||
{
|
||||
return map ? map->name : NULL;
|
||||
}
|
||||
|
||||
enum bpf_map_type
|
||||
bpf_map__type(const struct bpf_map* map)
|
||||
{
|
||||
return map->map_definition.type;
|
||||
}
|
||||
|
||||
__u32
|
||||
bpf_map__key_size(const struct bpf_map* map)
|
||||
{
|
||||
return map->map_definition.key_size;
|
||||
}
|
||||
|
||||
__u32
|
||||
bpf_map__value_size(const struct bpf_map* map)
|
||||
{
|
||||
return map->map_definition.value_size;
|
||||
}
|
||||
|
||||
__u32
|
||||
bpf_map__max_entries(const struct bpf_map* map)
|
||||
{
|
||||
return map->map_definition.max_entries;
|
||||
}
|
||||
|
||||
bool
|
||||
bpf_map__is_pinned(const struct bpf_map* map)
|
||||
{
|
||||
return map->pinned;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_map__fd(const struct bpf_map* map)
|
||||
{
|
||||
return map ? map->map_fd : libbpf_err(-EINVAL);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "api_internal.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#pragma warning(pop)
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
// This file implements APIs in LibBPF's libbpf.h and is based on code in external/libbpf/src/libbpf.c
|
||||
// used under the BSD-2-Clause license , so the coding style tries to match the libbpf.c style to
|
||||
// minimize diffs until libbpf becomes cross-platform capable. This is a temporary workaround for
|
||||
// issue #351 until we can compile and use libbpf.c directly.
|
||||
|
||||
const char*
|
||||
bpf_object__name(const struct bpf_object* object)
|
||||
{
|
||||
return object->file_name;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__pin(struct bpf_object* obj, const char* path)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bpf_object__pin_maps(obj, path);
|
||||
if (err)
|
||||
return libbpf_err(err);
|
||||
|
||||
err = bpf_object__pin_programs(obj, path);
|
||||
if (err) {
|
||||
bpf_object__unpin_maps(obj, path);
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bpf_object__close(struct bpf_object* object)
|
||||
{
|
||||
ebpf_object_close(object);
|
||||
}
|
||||
|
||||
struct bpf_program*
|
||||
bpf_object__find_program_by_name(const struct bpf_object* obj, const char* name)
|
||||
{
|
||||
struct bpf_program* prog;
|
||||
|
||||
bpf_object__for_each_program(prog, obj)
|
||||
{
|
||||
if (!strcmp(prog->program_name, name))
|
||||
return prog;
|
||||
}
|
||||
errno = ENOENT;
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,278 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "api_internal.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#pragma warning(pop)
|
||||
#include "libbpf_internal.h"
|
||||
|
||||
// This file implements APIs in LibBPF's libbpf.h and is based on code in external/libbpf/src/libbpf.c
|
||||
// used under the BSD-2-Clause license , so the coding style tries to match the libbpf.c style to
|
||||
// minimize diffs until libbpf becomes cross-platform capable. This is a temporary workaround for
|
||||
// issue #351 until we can compile and use libbpf.c directly.
|
||||
|
||||
static const ebpf_program_type_t*
|
||||
_get_ebpf_program_type(enum bpf_prog_type type)
|
||||
{
|
||||
// TODO(issue #223): read this mapping from the registry
|
||||
switch (type) {
|
||||
case BPF_PROG_TYPE_XDP:
|
||||
return &EBPF_PROGRAM_TYPE_XDP;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const ebpf_attach_type_t*
|
||||
_get_ebpf_attach_type(enum bpf_attach_type type)
|
||||
{
|
||||
// TODO(issue #223): read this mapping from the registry
|
||||
switch (type) {
|
||||
case BPF_ATTACH_TYPE_XDP:
|
||||
return &EBPF_ATTACH_TYPE_XDP;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static enum bpf_attach_type
|
||||
_get_bpf_attach_type(const ebpf_attach_type_t* type)
|
||||
{
|
||||
// TODO(issue #223): read this mapping from the registry
|
||||
if (memcmp(type, &EBPF_ATTACH_TYPE_XDP, sizeof(*type)) == 0) {
|
||||
return BPF_ATTACH_TYPE_XDP;
|
||||
}
|
||||
return BPF_ATTACH_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_prog_load(const char* file_name, enum bpf_prog_type type, struct bpf_object** object, int* program_fd)
|
||||
{
|
||||
const ebpf_program_type_t* program_type = _get_ebpf_program_type(type);
|
||||
|
||||
if (program_type == nullptr) {
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const char* log_buffer;
|
||||
return (int)ebpf_program_load(
|
||||
file_name, program_type, nullptr, EBPF_EXECUTION_ANY, object, (fd_t*)program_fd, &log_buffer);
|
||||
}
|
||||
|
||||
int
|
||||
bpf_program__fd(const struct bpf_program* program)
|
||||
{
|
||||
return (int)ebpf_program_get_fd(program);
|
||||
}
|
||||
|
||||
const char*
|
||||
bpf_program__name(const struct bpf_program* program)
|
||||
{
|
||||
return program->program_name;
|
||||
}
|
||||
|
||||
const char*
|
||||
bpf_program__section_name(const struct bpf_program* program)
|
||||
{
|
||||
return program->section_name;
|
||||
}
|
||||
|
||||
size_t
|
||||
bpf_program__size(const struct bpf_program* program)
|
||||
{
|
||||
return program->byte_code_size;
|
||||
}
|
||||
|
||||
struct bpf_link*
|
||||
bpf_program__attach(struct bpf_program* program)
|
||||
{
|
||||
if (program == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ebpf_handle_t link_handle;
|
||||
uint32_t result = ebpf_api_link_program(program->handle, program->attach_type, &link_handle);
|
||||
if (result) {
|
||||
errno = result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The bpf_link structure is opaque so we can use the link handle directly.
|
||||
// TODO(issue #81): return pointer to ebpf_link_t.
|
||||
return (struct bpf_link*)link_handle;
|
||||
}
|
||||
|
||||
struct bpf_link*
|
||||
bpf_program__attach_xdp(struct bpf_program* program, int ifindex)
|
||||
{
|
||||
if (program == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: use ifindex
|
||||
UNREFERENCED_PARAMETER(ifindex);
|
||||
|
||||
ebpf_handle_t link_handle;
|
||||
uint32_t result = ebpf_api_link_program(program->handle, EBPF_ATTACH_TYPE_XDP, &link_handle);
|
||||
if (result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The bpf_link structure is opaque so we can use the link handle directly.
|
||||
// TODO(issue #81): return pointer to ebpf_link_t.
|
||||
return (struct bpf_link*)link_handle;
|
||||
}
|
||||
|
||||
struct bpf_program*
|
||||
bpf_program__next(struct bpf_program* previous, const struct bpf_object* object)
|
||||
{
|
||||
return ebpf_program_next(previous, object);
|
||||
}
|
||||
|
||||
struct bpf_program*
|
||||
bpf_program__prev(struct bpf_program* next, const struct bpf_object* object)
|
||||
{
|
||||
return ebpf_program_previous(next, object);
|
||||
}
|
||||
|
||||
int
|
||||
bpf_program__unpin(struct bpf_program* prog, const char* path)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (prog == NULL) {
|
||||
return libbpf_err(-EINVAL);
|
||||
}
|
||||
|
||||
err = ebpf_api_unpin_object((const uint8_t*)path, (uint32_t)strlen(path));
|
||||
if (err)
|
||||
return libbpf_err(-err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_program__pin(struct bpf_program* prog, const char* path)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (prog == NULL) {
|
||||
return libbpf_err(-EINVAL);
|
||||
}
|
||||
|
||||
err = ebpf_api_pin_object(prog->handle, (const uint8_t*)path, (uint32_t)strlen(path));
|
||||
if (err) {
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char*
|
||||
__bpf_program__pin_name(struct bpf_program* prog)
|
||||
{
|
||||
char *name, *p;
|
||||
|
||||
name = p = strdup(prog->section_name);
|
||||
while ((p = strchr(p, '/')) != NULL)
|
||||
*p = '_';
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__pin_programs(struct bpf_object* obj, const char* path)
|
||||
{
|
||||
struct bpf_program* prog;
|
||||
int err;
|
||||
|
||||
if (!obj)
|
||||
return libbpf_err(-ENOENT);
|
||||
|
||||
bpf_object__for_each_program(prog, obj)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path, __bpf_program__pin_name(prog));
|
||||
if (len < 0) {
|
||||
err = -EINVAL;
|
||||
goto err_unpin_programs;
|
||||
} else if (len >= PATH_MAX) {
|
||||
err = -ENAMETOOLONG;
|
||||
goto err_unpin_programs;
|
||||
}
|
||||
|
||||
err = bpf_program__pin(prog, buf);
|
||||
if (err) {
|
||||
goto err_unpin_programs;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unpin_programs:
|
||||
while ((prog = bpf_program__prev(prog, obj)) != NULL) {
|
||||
char buf[PATH_MAX];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path, __bpf_program__pin_name(prog));
|
||||
if (len < 0)
|
||||
continue;
|
||||
else if (len >= PATH_MAX)
|
||||
continue;
|
||||
|
||||
bpf_program__unpin(prog, path);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_object__unpin_programs(struct bpf_object* obj, const char* path)
|
||||
{
|
||||
struct bpf_program* prog;
|
||||
int err;
|
||||
|
||||
if (!obj)
|
||||
return libbpf_err(-ENOENT);
|
||||
|
||||
bpf_object__for_each_program(prog, obj)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path, __bpf_program__pin_name(prog));
|
||||
if (len < 0)
|
||||
return libbpf_err(-EINVAL);
|
||||
else if (len >= PATH_MAX)
|
||||
return libbpf_err(-ENAMETOOLONG);
|
||||
|
||||
err = bpf_program__unpin(prog, buf);
|
||||
if (err)
|
||||
return libbpf_err(err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bpf_link__destroy(struct bpf_link* link)
|
||||
{
|
||||
// TODO(issue #81): get handle from ebpf_link_t, and
|
||||
// detach before closing the handle.
|
||||
ebpf_handle_t link_handle = (ebpf_handle_t)link;
|
||||
uint32_t result = ebpf_api_close_handle(link_handle);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
enum bpf_attach_type
|
||||
bpf_program__get_expected_attach_type(const struct bpf_program* program)
|
||||
{
|
||||
return _get_bpf_attach_type(&program->attach_type);
|
||||
}
|
||||
|
||||
void
|
||||
bpf_program__set_expected_attach_type(struct bpf_program* program, enum bpf_attach_type type)
|
||||
{
|
||||
program->attach_type = *_get_ebpf_attach_type(type);
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#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 "mock.h"
|
||||
|
@ -161,7 +162,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
|||
uint32_t result = 0;
|
||||
const char* error_message = NULL;
|
||||
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP);
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||
|
||||
REQUIRE(
|
||||
|
@ -231,7 +232,7 @@ divide_by_zero_test(ebpf_execution_type_t execution_type)
|
|||
uint32_t result = 0;
|
||||
const char* error_message = NULL;
|
||||
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP);
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||
|
||||
REQUIRE(
|
||||
|
@ -339,7 +340,7 @@ bindmonitor_test(ebpf_execution_type_t execution_type)
|
|||
error_message = nullptr,
|
||||
result == EBPF_SUCCESS));
|
||||
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND);
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
||||
|
||||
REQUIRE(hook.attach(program_handle) == EBPF_SUCCESS);
|
||||
|
||||
|
@ -481,7 +482,7 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
|
|||
error_message = nullptr,
|
||||
result == EBPF_SUCCESS));
|
||||
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND);
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
||||
|
||||
std::string process_maps_name = "bindmonitor::process_maps";
|
||||
std::string limit_maps_name = "bindmonitor::limits_map";
|
||||
|
@ -562,7 +563,7 @@ TEST_CASE("enumerate_and_query_maps", "[end_to_end]")
|
|||
error_message = nullptr,
|
||||
result == EBPF_SUCCESS));
|
||||
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND);
|
||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
||||
|
||||
std::string process_maps_name = "bindmonitor::process_maps";
|
||||
std::string limit_maps_name = "bindmonitor::limits_map";
|
||||
|
|
|
@ -23,13 +23,13 @@ typedef std::unique_ptr<uint8_t, ebpf_free_memory_t> ebpf_memory_t;
|
|||
typedef class _single_instance_hook
|
||||
{
|
||||
public:
|
||||
_single_instance_hook(ebpf_program_type_t program_type)
|
||||
_single_instance_hook(ebpf_program_type_t program_type, ebpf_attach_type_t attach_type)
|
||||
: provider(nullptr), client_binding_context(nullptr), client_data(nullptr), client_dispatch_table(nullptr),
|
||||
link_handle(nullptr)
|
||||
{
|
||||
ebpf_guid_create(&attach_type);
|
||||
ebpf_guid_create(&client_id);
|
||||
attach_provider_data.supported_program_type = program_type;
|
||||
this->attach_type = attach_type;
|
||||
REQUIRE(
|
||||
ebpf_provider_load(
|
||||
&provider,
|
||||
|
@ -120,15 +120,13 @@ static ebpf_helper_function_prototype_t _ebpf_map_helper_function_prototype[] =
|
|||
EBPF_RETURN_TYPE_INTEGER,
|
||||
{EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY}}};
|
||||
|
||||
static ebpf_context_descriptor_t _ebpf_xdp_context_descriptor = {
|
||||
sizeof(xdp_md_t),
|
||||
EBPF_OFFSET_OF(xdp_md_t, data),
|
||||
EBPF_OFFSET_OF(xdp_md_t, data_end),
|
||||
EBPF_OFFSET_OF(xdp_md_t, data_meta)};
|
||||
static ebpf_program_info_t _ebpf_xdp_program_info = {
|
||||
{"xdp", &_ebpf_xdp_context_descriptor, {0}},
|
||||
EBPF_COUNT_OF(_ebpf_map_helper_function_prototype),
|
||||
_ebpf_map_helper_function_prototype};
|
||||
static ebpf_context_descriptor_t _ebpf_xdp_context_descriptor = {sizeof(xdp_md_t),
|
||||
EBPF_OFFSET_OF(xdp_md_t, data),
|
||||
EBPF_OFFSET_OF(xdp_md_t, data_end),
|
||||
EBPF_OFFSET_OF(xdp_md_t, data_meta)};
|
||||
static ebpf_program_info_t _ebpf_xdp_program_info = {{"xdp", &_ebpf_xdp_context_descriptor, {0}},
|
||||
EBPF_COUNT_OF(_ebpf_map_helper_function_prototype),
|
||||
_ebpf_map_helper_function_prototype};
|
||||
|
||||
static ebpf_program_data_t _ebpf_xdp_program_data = {&_ebpf_xdp_program_info, NULL};
|
||||
|
||||
|
@ -137,10 +135,9 @@ static ebpf_extension_data_t _ebpf_xdp_program_info_provider_data = {
|
|||
|
||||
static ebpf_context_descriptor_t _ebpf_bind_context_descriptor = {
|
||||
sizeof(bind_md_t), EBPF_OFFSET_OF(bind_md_t, app_id_start), EBPF_OFFSET_OF(bind_md_t, app_id_end), -1};
|
||||
static ebpf_program_info_t _ebpf_bind_program_info = {
|
||||
{"bind", &_ebpf_bind_context_descriptor, {0}},
|
||||
EBPF_COUNT_OF(_ebpf_map_helper_function_prototype),
|
||||
_ebpf_map_helper_function_prototype};
|
||||
static ebpf_program_info_t _ebpf_bind_program_info = {{"bind", &_ebpf_bind_context_descriptor, {0}},
|
||||
EBPF_COUNT_OF(_ebpf_map_helper_function_prototype),
|
||||
_ebpf_map_helper_function_prototype};
|
||||
|
||||
static ebpf_program_data_t _ebpf_bind_program_data = {&_ebpf_bind_program_info, NULL};
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "catch_wrapper.hpp"
|
||||
#include "ebpf_api.h"
|
||||
#include "ebpf_core.h"
|
||||
#include "helpers.h"
|
||||
#include "mock.h"
|
||||
#include "test_helper.hpp"
|
||||
|
||||
BOOL
|
||||
GlueCloseHandle(ebpf_handle_t hObject);
|
||||
|
||||
ebpf_handle_t
|
||||
GlueCreateFileW(
|
||||
PCWSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
PSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
ebpf_handle_t hTemplateFile);
|
||||
|
||||
BOOL
|
||||
GlueDeviceIoControl(
|
||||
ebpf_handle_t hDevice,
|
||||
DWORD dwIoControlCode,
|
||||
PVOID lpInBuffer,
|
||||
DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize,
|
||||
PDWORD lpBytesReturned,
|
||||
OVERLAPPED* lpOverlapped);
|
||||
|
||||
_test_helper_end_to_end::_test_helper_end_to_end()
|
||||
{
|
||||
device_io_control_handler = GlueDeviceIoControl;
|
||||
create_file_handler = GlueCreateFileW;
|
||||
close_handle_handler = GlueCloseHandle;
|
||||
REQUIRE(ebpf_core_initiate() == EBPF_SUCCESS);
|
||||
ec_initialized = true;
|
||||
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
||||
api_initialized = true;
|
||||
}
|
||||
|
||||
_test_helper_end_to_end::~_test_helper_end_to_end()
|
||||
{
|
||||
if (api_initialized)
|
||||
ebpf_api_terminate();
|
||||
if (ec_initialized)
|
||||
ebpf_core_terminate();
|
||||
|
||||
device_io_control_handler = nullptr;
|
||||
create_file_handler = nullptr;
|
||||
close_handle_handler = nullptr;
|
||||
}
|
||||
|
||||
_test_helper_libbpf::_test_helper_libbpf()
|
||||
{
|
||||
xdp_program_info = new program_info_provider_t(EBPF_PROGRAM_TYPE_XDP);
|
||||
hook = new single_instance_hook_t(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||
}
|
||||
|
||||
_test_helper_libbpf::~_test_helper_libbpf()
|
||||
{
|
||||
delete hook;
|
||||
delete xdp_program_info;
|
||||
}
|
|
@ -1,60 +1,29 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include "ebpf_api.h"
|
||||
#include "ebpf_core.h"
|
||||
#include "mock.h"
|
||||
|
||||
BOOL
|
||||
GlueCloseHandle(ebpf_handle_t hObject);
|
||||
|
||||
ebpf_handle_t
|
||||
GlueCreateFileW(
|
||||
PCWSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
PSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
ebpf_handle_t hTemplateFile);
|
||||
|
||||
BOOL
|
||||
GlueDeviceIoControl(
|
||||
ebpf_handle_t hDevice,
|
||||
DWORD dwIoControlCode,
|
||||
PVOID lpInBuffer,
|
||||
DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize,
|
||||
PDWORD lpBytesReturned,
|
||||
OVERLAPPED* lpOverlapped);
|
||||
|
||||
class _test_helper_end_to_end
|
||||
{
|
||||
public:
|
||||
_test_helper_end_to_end()
|
||||
{
|
||||
device_io_control_handler = GlueDeviceIoControl;
|
||||
create_file_handler = GlueCreateFileW;
|
||||
close_handle_handler = GlueCloseHandle;
|
||||
REQUIRE(ebpf_core_initiate() == EBPF_SUCCESS);
|
||||
ec_initialized = true;
|
||||
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
||||
api_initialized = true;
|
||||
}
|
||||
~_test_helper_end_to_end()
|
||||
{
|
||||
if (api_initialized)
|
||||
ebpf_api_terminate();
|
||||
if (ec_initialized)
|
||||
ebpf_core_terminate();
|
||||
|
||||
device_io_control_handler = nullptr;
|
||||
create_file_handler = nullptr;
|
||||
close_handle_handler = nullptr;
|
||||
}
|
||||
_test_helper_end_to_end();
|
||||
~_test_helper_end_to_end();
|
||||
|
||||
private:
|
||||
bool ec_initialized = false;
|
||||
bool api_initialized = false;
|
||||
};
|
||||
|
||||
class _program_info_provider;
|
||||
class _single_instance_hook;
|
||||
|
||||
class _test_helper_libbpf
|
||||
{
|
||||
public:
|
||||
_test_helper_libbpf();
|
||||
~_test_helper_libbpf();
|
||||
|
||||
private:
|
||||
_test_helper_end_to_end test_helper_end_to_end;
|
||||
_program_info_provider* xdp_program_info;
|
||||
_single_instance_hook* hook;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,251 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "catch_wrapper.hpp"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200)
|
||||
#include "libbpf.h"
|
||||
#pragma warning(pop)
|
||||
#include "test_helper.hpp"
|
||||
|
||||
// libbpf.h uses enum types and generates the
|
||||
// following warning whenever an enum type is used below:
|
||||
// "The enum type 'bpf_attach_type' is unscoped.
|
||||
// Prefer 'enum class' over 'enum'"
|
||||
#pragma warning(disable : 26812)
|
||||
|
||||
TEST_CASE("libbpf program", "[libbpf]")
|
||||
{
|
||||
_test_helper_libbpf test_helper;
|
||||
|
||||
struct bpf_object* object;
|
||||
int program_fd;
|
||||
int result = bpf_prog_load("droppacket.o", BPF_PROG_TYPE_XDP, &object, &program_fd);
|
||||
REQUIRE(result == 0);
|
||||
REQUIRE(object != nullptr);
|
||||
REQUIRE(program_fd != -1);
|
||||
|
||||
const char* name = bpf_object__name(object);
|
||||
REQUIRE(strcmp(name, "droppacket.o") == 0);
|
||||
|
||||
struct bpf_program* program = bpf_object__find_program_by_name(object, "DropPacket");
|
||||
REQUIRE(program != nullptr);
|
||||
|
||||
name = bpf_program__section_name(program);
|
||||
REQUIRE(strcmp(name, "xdp") == 0);
|
||||
|
||||
name = bpf_program__name(program);
|
||||
REQUIRE(strcmp(name, "DropPacket") == 0);
|
||||
|
||||
int fd2 = bpf_program__fd(program);
|
||||
REQUIRE(fd2 == program_fd);
|
||||
|
||||
size_t size = bpf_program__size(program);
|
||||
REQUIRE(size == 192);
|
||||
|
||||
REQUIRE(bpf_program__next(program, object) == nullptr);
|
||||
REQUIRE(bpf_program__prev(program, object) == nullptr);
|
||||
REQUIRE(bpf_program__next(nullptr, object) == program);
|
||||
REQUIRE(bpf_program__prev(nullptr, object) == program);
|
||||
|
||||
bpf_object__close(object);
|
||||
}
|
||||
|
||||
TEST_CASE("libbpf program pinning", "[libbpf]")
|
||||
{
|
||||
_test_helper_libbpf test_helper;
|
||||
const char* pin_path = "\\temp\\test";
|
||||
|
||||
struct bpf_object* object;
|
||||
int program_fd;
|
||||
int result = bpf_prog_load("droppacket.o", BPF_PROG_TYPE_XDP, &object, &program_fd);
|
||||
REQUIRE(result == 0);
|
||||
REQUIRE(object != nullptr);
|
||||
|
||||
struct bpf_program* program = bpf_object__find_program_by_name(object, "DropPacket");
|
||||
REQUIRE(program != nullptr);
|
||||
|
||||
// Try to pin the program.
|
||||
result = bpf_program__pin(program, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
// Make sure a duplicate pin fails.
|
||||
result = bpf_program__pin(program, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
result = bpf_program__unpin(program, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
// Make sure a duplicate unpin fails.
|
||||
result = bpf_program__unpin(program, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
// Try to pin all (1) programs in the object.
|
||||
result = bpf_object__pin_programs(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
// Make sure a duplicate pin fails.
|
||||
result = bpf_object__pin_programs(object, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
result = bpf_object__unpin_programs(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
// Try to pin all programs and maps in the object.
|
||||
result = bpf_object__pin(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
// Make sure a duplicate pin fails.
|
||||
result = bpf_object__pin_programs(object, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
// There is no bpf_object__unpin API, so
|
||||
// we have to unpin programs and maps separately.
|
||||
result = bpf_object__unpin_programs(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
result = bpf_object__unpin_maps(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
bpf_object__close(object);
|
||||
}
|
||||
|
||||
TEST_CASE("libbpf program attach", "[libbpf]")
|
||||
{
|
||||
_test_helper_libbpf test_helper;
|
||||
|
||||
struct bpf_object* object;
|
||||
int program_fd;
|
||||
int result = bpf_prog_load("droppacket.o", BPF_PROG_TYPE_XDP, &object, &program_fd);
|
||||
REQUIRE(result == 0);
|
||||
REQUIRE(object != nullptr);
|
||||
|
||||
struct bpf_program* program = bpf_object__find_program_by_name(object, "DropPacket");
|
||||
REQUIRE(program != nullptr);
|
||||
|
||||
// Based on the program type, verify that the
|
||||
// default attach type is set correctly.
|
||||
// TODO: it is not currently set. Update this
|
||||
// test once it is set correctly.
|
||||
enum bpf_attach_type type = bpf_program__get_expected_attach_type(program);
|
||||
REQUIRE(type == BPF_ATTACH_TYPE_UNKNOWN);
|
||||
|
||||
bpf_program__set_expected_attach_type(program, BPF_ATTACH_TYPE_XDP);
|
||||
|
||||
type = bpf_program__get_expected_attach_type(program);
|
||||
REQUIRE(type == BPF_ATTACH_TYPE_XDP);
|
||||
|
||||
bpf_link* link = bpf_program__attach(program);
|
||||
REQUIRE(link != nullptr);
|
||||
|
||||
result = bpf_link__destroy(link);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
// Verify that a duplicate link destroy fails.
|
||||
result = bpf_link__destroy(link);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
bpf_object__close(object);
|
||||
}
|
||||
|
||||
TEST_CASE("libbpf map", "[libbpf]")
|
||||
{
|
||||
_test_helper_libbpf test_helper;
|
||||
|
||||
struct bpf_object* object;
|
||||
int program_fd;
|
||||
int result = bpf_prog_load("droppacket.o", BPF_PROG_TYPE_XDP, &object, &program_fd);
|
||||
REQUIRE(result == 0);
|
||||
REQUIRE(object != nullptr);
|
||||
|
||||
// Get the first (and only) map.
|
||||
struct bpf_map* map = bpf_map__next(nullptr, object);
|
||||
REQUIRE(map != nullptr);
|
||||
|
||||
// Verify that it's the only map.
|
||||
REQUIRE(bpf_map__next(map, object) == nullptr);
|
||||
REQUIRE(bpf_map__prev(map, object) == nullptr);
|
||||
REQUIRE(bpf_map__prev(nullptr, object) == map);
|
||||
|
||||
const char* name = bpf_map__name(map);
|
||||
REQUIRE(name == nullptr); // droppacket.o has no map name.
|
||||
REQUIRE(bpf_map__type(map) == BPF_MAP_TYPE_ARRAY);
|
||||
REQUIRE(bpf_map__key_size(map) == 4);
|
||||
REQUIRE(bpf_map__value_size(map) == 8);
|
||||
REQUIRE(bpf_map__max_entries(map) == 1);
|
||||
REQUIRE(bpf_map__fd(map) > 0);
|
||||
|
||||
bpf_object__close(object);
|
||||
}
|
||||
|
||||
TEST_CASE("libbpf map pinning", "[libbpf]")
|
||||
{
|
||||
_test_helper_libbpf test_helper;
|
||||
const char* pin_path = "\\temp\\test";
|
||||
|
||||
struct bpf_object* object;
|
||||
int program_fd;
|
||||
int result = bpf_prog_load("droppacket.o", BPF_PROG_TYPE_XDP, &object, &program_fd);
|
||||
REQUIRE(result == 0);
|
||||
REQUIRE(object != nullptr);
|
||||
|
||||
struct bpf_map* map = bpf_map__next(nullptr, object);
|
||||
REQUIRE(map != nullptr);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == false);
|
||||
|
||||
// Try to pin the map.
|
||||
result = bpf_map__pin(map, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == true);
|
||||
|
||||
// Make sure a duplicate pin fails.
|
||||
result = bpf_map__pin(map, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
result = bpf_map__unpin(map, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == false);
|
||||
|
||||
// Make sure a duplicate unpin fails.
|
||||
result = bpf_map__unpin(map, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
// Try to pin all (1) maps in the object.
|
||||
result = bpf_object__pin_maps(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == true);
|
||||
|
||||
// Make sure a duplicate pin fails.
|
||||
result = bpf_object__pin_maps(object, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
result = bpf_object__unpin_maps(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == false);
|
||||
|
||||
// Try to pin all programs and maps in the object.
|
||||
result = bpf_object__pin(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == true);
|
||||
|
||||
// Make sure a duplicate pin fails.
|
||||
result = bpf_object__pin_maps(object, pin_path);
|
||||
REQUIRE(result != 0);
|
||||
|
||||
// There is no bpf_object__unpin API, so
|
||||
// we have to unpin programs and maps separately.
|
||||
result = bpf_object__unpin_programs(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
result = bpf_object__unpin_maps(object, pin_path);
|
||||
REQUIRE(result == 0);
|
||||
|
||||
REQUIRE(bpf_map__is_pinned(map) == false);
|
||||
|
||||
bpf_object__close(object);
|
||||
}
|
|
@ -95,7 +95,7 @@
|
|||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;$(SolutionDir)external\libbpf\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -110,7 +110,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;$(SolutionDir)external\libbpf\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -125,7 +125,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;$(SolutionDir)external\libbpf\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
|
@ -144,7 +144,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\ebpfnetsh;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(OutDir);$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)libs\service;$(SolutionDir)rpc_interface;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\execution_context;$(SolutionDir)tests\end_to_end;$(SolutionDir)external\libbpf\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
|
@ -203,6 +203,8 @@
|
|||
<ClCompile Include="..\end_to_end\end_to_end.cpp" />
|
||||
<ClCompile Include="..\end_to_end\mock.cpp" />
|
||||
<ClCompile Include="..\end_to_end\netsh_test.cpp" />
|
||||
<ClCompile Include="..\end_to_end\test_helper.cpp" />
|
||||
<ClCompile Include="libbpf_test.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\end_to_end\helpers.h" />
|
||||
|
|
|
@ -40,6 +40,12 @@
|
|||
<ClCompile Include="..\end_to_end\netsh_test.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libbpf_test.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\end_to_end\test_helper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\end_to_end\helpers.h">
|
||||
|
|
Загрузка…
Ссылка в новой задаче