Skip to content

Commit

Permalink
Libbpf API compatibility
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dthaler committed Jul 28, 2021
1 parent 4bebd3a commit 5c0645a
Show file tree
Hide file tree
Showing 18 changed files with 879 additions and 82 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -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
1 change: 1 addition & 0 deletions external/libbpf
Submodule libbpf added at 90405f
47 changes: 47 additions & 0 deletions include/linux/bpf.h
@@ -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
};
11 changes: 8 additions & 3 deletions libs/api/api.vcxproj
Expand Up @@ -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>
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -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>
9 changes: 9 additions & 0 deletions libs/api/api.vcxproj.filters
Expand Up @@ -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">
Expand Down
2 changes: 1 addition & 1 deletion libs/api/api_internal.h
Expand Up @@ -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;
Expand Down
13 changes: 7 additions & 6 deletions libs/api/ebpf_api.cpp
Expand Up @@ -3,6 +3,7 @@

#include "pch.h"

#include <fcntl.h>
#include <io.h>
#include "api_common.hpp"
#include "api_internal.h"
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions libs/api/libbpf_internal.h
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#pragma once

static inline int
libbpf_err(int ret)
{
if (ret < 0)
errno = -ret;
return ret;
}
152 changes: 152 additions & 0 deletions libs/api/libbpf_map.cpp
@@ -0,0 +1,152 @@
// 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 bpf.h
// and is based on code in libbpf.c.

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)
{
char fullpath[MAX_PATH];
int length = snprintf(fullpath, sizeof(fullpath), "%s/%s", path, map->name);
if (length < 0) {
return -EINVAL;
} else if (length > sizeof(fullpath)) {
return -ENAMETOOLONG;
}

uint32_t result = ebpf_api_unpin_object((const uint8_t*)fullpath, (uint32_t)strlen(fullpath));
if (result) {
return libbpf_err(result);
}

// TODO(issue #81): ebpf_api_unpin_object should set this.
map->pinned = false;

return 0;
}

static void
_unpin_previous_maps(_In_ ebpf_map_t* map, _In_ struct bpf_object* object, const char* path)
{
for (map = bpf_map__prev(map, object); map; map = bpf_map__prev(map, object)) {
bpf_map__unpin(map, path);
}
}

int
bpf_map__pin(struct bpf_map* map, const char* path)
{
char fullpath[MAX_PATH];

int length = snprintf(fullpath, sizeof(fullpath), "%s/%s", path, map->name);
if (length < 0) {
return libbpf_err(-EINVAL);
}

int result = ebpf_api_pin_object(map->map_handle, (const uint8_t*)fullpath, (uint32_t)strlen(fullpath));
if (result) {
return libbpf_err(result);
}

// TODO(issue #81): ebpf_api_pin_object should set this.
map->pinned = true;

return 0;
}

int
bpf_object__pin_maps(struct bpf_object* object, const char* path)
{
struct bpf_map* map;

if (!object) {
return libbpf_err(-ENOENT);
}

bpf_object__for_each_map(map, object)
{
int result = bpf_map__pin(map, path);
if (result) {
_unpin_previous_maps(map, object, path);
return result;
}
}

return 0;
}

int
bpf_object__unpin_maps(struct bpf_object* object, const char* path)
{
struct bpf_map* map;

if (!object) {
return libbpf_err(-ENOENT);
}

bpf_object__for_each_map(map, object)
{
int result = bpf_map__unpin(map, path);
if (result) {
return libbpf_err(result);
}
}

return 0;
}

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);
}
56 changes: 56 additions & 0 deletions libs/api/libbpf_object.cpp
@@ -0,0 +1,56 @@
// 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 bpf.h
// and is based on code in libbpf.c.

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* object, const char* name)
{
struct bpf_program* program;

bpf_object__for_each_program(program, object)
{
if (!strcmp(program->program_name, name))
return program;
}
errno = ENOENT;
return nullptr;
}

0 comments on commit 5c0645a

Please sign in to comment.