* 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:
Dave Thaler 2021-07-30 15:34:21 -07:00 коммит произвёл GitHub
Родитель 4bebd3aaa1
Коммит 8006f181e0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 1037 добавлений и 113 удалений

3
.gitmodules поставляемый
Просмотреть файл

@ -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

1
external/libbpf поставляемый Submodule

@ -0,0 +1 @@
Subproject commit 90405ffa91abbdbfd9f56b70adbfa0be6cc0fe3f

47
include/linux/bpf.h Normal file
Просмотреть файл

@ -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;
}

184
libs/api/libbpf_map.cpp Normal file
Просмотреть файл

@ -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;
}

278
libs/api/libbpf_program.cpp Normal file
Просмотреть файл

@ -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;
};

251
tests/unit/libbpf_test.cpp Normal file
Просмотреть файл

@ -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">