xdp_adjust_head : Part 1
This commit is contained in:
Shankar Seal 2021-09-13 17:46:23 -07:00 коммит произвёл GitHub
Родитель 4d4c5b5cc7
Коммит e84efdf092
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 391 добавлений и 54 удалений

Просмотреть файл

@ -36,6 +36,27 @@ typedef enum _xdp_action
typedef xdp_action_t
xdp_hook_t(xdp_md_t* context);
// XDP helper functions.
#define XDP_EXT_HELPER_FN_BASE 0xFFFF
#ifndef __doxygen
#define EBPF_HELPER(return_type, name, args) typedef return_type(*name##_t) args
#endif
/**
* @brief Adjust XDP context data pointer.
*
* @param[in] ctx XDP context.
* @param[in] delta Number of bytes to move the data pointer by.
*
* @retval 0 The operation was successful.
* @retval <0 A failure occured.
*/
EBPF_HELPER(int, bpf_xdp_adjust_head, (xdp_md_t * ctx, int delta));
#ifndef __doxygen
#define bpf_xdp_adjust_head ((bpf_xdp_adjust_head_t)XDP_EXT_HELPER_FN_BASE + 1)
#endif
// BIND hook
typedef enum _bind_operation

Просмотреть файл

@ -21,6 +21,7 @@
#include "ebpf_xdp_program_data.h"
#include "ebpf_state.h"
#include "encode_program_info.h"
#include "net_ebpf_ext_program_info.h"
class _test_helper
{
@ -418,7 +419,9 @@ TEST_CASE("program_type_info_stored", "[platform]")
ebpf_program_info_decode(
&xdp_program_info, _ebpf_encoded_xdp_program_info_data, sizeof(_ebpf_encoded_xdp_program_info_data)) ==
EBPF_SUCCESS);
REQUIRE(xdp_program_info->count_of_helpers == ebpf_core_helper_functions_count);
REQUIRE(
xdp_program_info->count_of_helpers ==
ebpf_core_helper_functions_count + EBPF_COUNT_OF(_xdp_ebpf_extension_helper_function_prototype));
REQUIRE(strcmp(xdp_program_info->program_type_descriptor.name, "xdp") == 0);
ebpf_free(xdp_program_info);

Просмотреть файл

@ -47,8 +47,6 @@ ebpf_extension_load(
ebpf_extension_provider_t** hash_table_find_result = NULL;
ebpf_extension_client_t* local_extension_client = NULL;
UNREFERENCED_PARAMETER(extension_changed);
state = ebpf_lock_lock(&_ebpf_provider_table_lock);
if (provider_binding_context == NULL) {
@ -113,6 +111,10 @@ ebpf_extension_load(
if (provider_dispatch_table != NULL)
*provider_dispatch_table = local_extension_provider->provider_dispatch_table;
// Invoke extension changed on client.
if ((extension_changed != NULL) && (provider_data != NULL))
extension_changed(extension_client_context, provider_binding_context, *provider_data);
Done:
if (local_extension_provider && local_extension_client) {
ebpf_hash_table_delete(

Просмотреть файл

@ -37,6 +37,8 @@ Environment:
#include "ebpf_program_types.h"
#include "ebpf_windows.h"
#include "net_ebpf_ext_program_info.h"
#define NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION 0
//

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#include "ebpf_program_types.h"
#include "ebpf_platform.h"
#include "ebpf_nethooks.h"
#define XDP_EXT_HELPER_FUNCTION_START EBPF_MAX_GENERAL_HELPER_FUNCTION
// XDP Extension Helper function prototype descriptors.
static ebpf_helper_function_prototype_t _xdp_ebpf_extension_helper_function_prototype[] = {
{XDP_EXT_HELPER_FUNCTION_START + 1,
"bpf_xdp_adjust_head",
EBPF_RETURN_TYPE_INTEGER,
{EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_ANYTHING}}};
// XDP Extension program information.
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(_xdp_ebpf_extension_helper_function_prototype),
_xdp_ebpf_extension_helper_function_prototype};

Просмотреть файл

@ -21,14 +21,20 @@ HANDLE _net_ebpf_ext_l2_injection_handle = NULL;
static ebpf_ext_attach_hook_provider_registration_t* _ebpf_xdp_hook_provider_registration = NULL;
static ebpf_extension_provider_t* _ebpf_xdp_program_info_provider = NULL;
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}}, 0, NULL};
static int
_net_ebpf_xdp_adjust_head(xdp_md_t* ctx, int delta)
{
UNREFERENCED_PARAMETER(ctx);
UNREFERENCED_PARAMETER(delta);
return -1;
}
static ebpf_program_data_t _ebpf_xdp_program_data = {&_ebpf_xdp_program_info, NULL};
static const void* _ebpf_xdp_helper_functions[] = {(void*)&_net_ebpf_xdp_adjust_head};
static ebpf_helper_function_addresses_t _ebpf_xdp_helper_function_address_table = {
EBPF_COUNT_OF(_ebpf_xdp_helper_functions), (uint64_t*)_ebpf_xdp_helper_functions};
static ebpf_program_data_t _ebpf_xdp_program_data = {&_ebpf_xdp_program_info, &_ebpf_xdp_helper_function_address_table};
static ebpf_extension_data_t _ebpf_xdp_program_info_provider_data = {
NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_xdp_program_data), &_ebpf_xdp_program_data};

Просмотреть файл

@ -138,6 +138,7 @@
<ClInclude Include="net_ebpf_ext.h" />
<ClInclude Include="net_ebpf_ext_bind.h" />
<ClInclude Include="net_ebpf_ext_xdp.h" />
<ClInclude Include="net_ebpf_ext_program_info.h" />
<ClInclude Include="ebpf_ext_attach_provider.h" />
<ClInclude Include="resource.h" />
</ItemGroup>

Просмотреть файл

@ -52,6 +52,9 @@
<ClInclude Include="net_ebpf_ext_xdp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="net_ebpf_ext_program_info.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>

Просмотреть файл

@ -118,6 +118,12 @@ typedef class _udp_packet
return _packet.size();
}
std::vector<uint8_t>&
packet()
{
return _packet;
}
static const ebpf::UDP_HEADER*
_get_udp_header(_In_ const uint8_t* packet_buffer, ADDRESS_FAMILY address_family)
{
@ -1026,7 +1032,60 @@ _xdp_reflect_packet_test(ebpf_execution_type_t execution_type, ADDRESS_FAMILY ad
}
}
TEST_CASE("xdp-reflect-v4-jit", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET); }
TEST_CASE("xdp-reflect-v6-jit", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET6); }
static void
_xdp_encap_reflect_packet_test(ebpf_execution_type_t execution_type, ADDRESS_FAMILY address_family)
{
_test_helper_end_to_end test_helper;
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
program_load_attach_helper_t program_helper(
SAMPLE_PATH "reflect_packet.o", EBPF_PROGRAM_TYPE_XDP, "encap_reflect_packet", execution_type, hook);
// Dummy UDP datagram with fake IP and MAC addresses.
udp_packet_t packet(address_family);
packet.set_destination_port(ntohs(REFLECTION_TEST_PORT));
// Dummy context (not used by the eBPF program).
xdp_md_helper_t ctx(packet.packet());
uint8_t* ip_header = packet.packet().data() + sizeof(ebpf::ETHERNET_HEADER);
std::vector<uint8_t> original_ip_datagram(ip_header, packet.packet().data() + packet.packet().size());
int hook_result;
REQUIRE(hook.fire(&ctx, &hook_result) == EBPF_SUCCESS);
REQUIRE(hook_result == 3);
ebpf::ETHERNET_HEADER* ethernet_header = reinterpret_cast<ebpf::ETHERNET_HEADER*>(ctx.data);
REQUIRE(memcmp(ethernet_header->Destination, _test_source_mac.data(), sizeof(ethernet_header->Destination)) == 0);
REQUIRE(memcmp(ethernet_header->Source, _test_destination_mac.data(), sizeof(ethernet_header->Source)) == 0);
if (address_family == AF_INET) {
ebpf::IPV4_HEADER* ipv4 = reinterpret_cast<ebpf::IPV4_HEADER*>(ethernet_header + 1);
REQUIRE(ipv4->SourceAddress == _test_destination_ipv4.s_addr);
REQUIRE(ipv4->DestinationAddress == _test_source_ipv4.s_addr);
REQUIRE(ipv4->Protocol == IPPROTO_IPV4);
uint8_t* inner_ip_header = (uint8_t*)(ipv4 + 1);
REQUIRE(memcmp(inner_ip_header, original_ip_datagram.data(), original_ip_datagram.size()) == 0);
} else {
ebpf::IPV6_HEADER* ipv6 = reinterpret_cast<ebpf::IPV6_HEADER*>(ethernet_header + 1);
REQUIRE(memcmp(ipv6->SourceAddress, &_test_destination_ipv6, sizeof(ebpf::ipv6_address_t)) == 0);
REQUIRE(memcmp(ipv6->DestinationAddress, &_test_source_ipv6, sizeof(ebpf::ipv6_address_t)) == 0);
REQUIRE(ipv6->NextHeader == IPPROTO_IPV6);
uint8_t* inner_ip_header = (uint8_t*)(ipv6 + 1);
REQUIRE(memcmp(inner_ip_header, original_ip_datagram.data(), original_ip_datagram.size()) == 0);
}
}
TEST_CASE("xdp-reflect-v4-jit", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_JIT, AF_INET); }
TEST_CASE("xdp-reflect-v6-jit", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_JIT, AF_INET6); }
TEST_CASE("xdp-reflect-v4-interpret", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET); }
TEST_CASE("xdp-reflect-v6-interpret", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET6); }
TEST_CASE("xdp-reflect-v6-interpret", "[xdp_tests]") { _xdp_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET6); }
TEST_CASE("xdp-encap-reflect-v4-jit", "[xdp_tests]") { _xdp_encap_reflect_packet_test(EBPF_EXECUTION_JIT, AF_INET); }
TEST_CASE("xdp-encap-reflect-v6-jit", "[xdp_tests]") { _xdp_encap_reflect_packet_test(EBPF_EXECUTION_JIT, AF_INET6); }
TEST_CASE("xdp-encap-reflect-v4-interpret", "[xdp_tests]")
{
_xdp_encap_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET);
}
TEST_CASE("xdp-encap-reflect-v6-interpret", "[xdp_tests]")
{
_xdp_encap_reflect_packet_test(EBPF_EXECUTION_INTERPRET, AF_INET6);
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "ebpf_nethooks.h"
#include "ebpf_platform.h"
#include "ebpf_program_types.h"
#include "net_ebpf_ext_program_info.h"
#include "sample_ext_program_info.h"
typedef struct _ebpf_free_memory
@ -172,14 +173,64 @@ typedef class _single_instance_hook : public _hook_helper
#define TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION 0
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}}, 0, NULL};
typedef class xdp_md_helper : public xdp_md_t
{
public:
xdp_md_helper(std::vector<uint8_t>& packet)
: xdp_md_t{packet.data(), packet.data() + packet.size()}, _packet(&packet), _begin(0), _end(packet.size()){};
int
adjust_head(int delta)
{
int return_value = 0;
if (delta == 0)
// Nothing changes.
goto Done;
static ebpf_program_data_t _ebpf_xdp_program_data = {&_ebpf_xdp_program_info, NULL};
if (delta > 0) {
if (_begin + delta > _end) {
return_value = -1;
goto Done;
}
_begin += delta;
} else {
int abs_delta = -delta;
if (_begin >= abs_delta)
_begin -= abs_delta;
else {
size_t additional_space_needed = abs_delta - _begin;
// Prepend _packet with additional_space_needed count of 0.
_packet->insert(_packet->begin(), additional_space_needed, 0);
_begin = 0;
_end += additional_space_needed;
}
// Adjust xdp_md data pointers.
data = _packet->data();
data_end = _packet->data() + _packet->size();
}
Done:
return return_value;
}
private:
std::vector<uint8_t>* _packet;
size_t _begin;
size_t _end;
} xdp_md_helper_t;
static int
_test_xdp_adjust_head(xdp_md_t* ctx, int delta)
{
((xdp_md_helper_t*)ctx)->adjust_head(delta);
return 0;
}
static const void* _test_ebpf_xdp_helper_functions[] = {(void*)&_test_xdp_adjust_head};
static ebpf_helper_function_addresses_t _test_ebpf_xdp_helper_function_address_table = {
EBPF_COUNT_OF(_test_ebpf_xdp_helper_functions), (uint64_t*)_test_ebpf_xdp_helper_functions};
static ebpf_program_data_t _ebpf_xdp_program_data = {
&_ebpf_xdp_program_info, &_test_ebpf_xdp_helper_function_address_table};
static ebpf_extension_data_t _ebpf_xdp_program_info_provider_data = {
TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_xdp_program_data), &_ebpf_xdp_program_data};

Просмотреть файл

@ -72,6 +72,9 @@ clean_up_rpc_binding() { return RPC_S_OK; }
ebpf_result_t
ebpf_rpc_load_program(ebpf_program_load_info* info, const char** logs, uint32_t* logs_size)
{
// Set the handle of program being verified in thread-local storage.
set_program_under_verification(info->program_handle);
// Short circuit rpc call to service lib.
ebpf_result_t result = ebpf_verify_and_load_program(
&info->program_type,

Просмотреть файл

@ -130,7 +130,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(SolutionDir)libs\execution_context;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\sample\ext\inc;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(SolutionDir)libs\execution_context;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -149,7 +149,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(SolutionDir)libs\execution_context;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\sample\ext\inc;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(SolutionDir)libs\execution_context;$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>

Просмотреть файл

@ -125,7 +125,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample\ext\inc;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;%(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)libs\api_common;$(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)tests\sample\ext\inc;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample\ext\inc;;$(SolutionDir)\netebpfext;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>

Просмотреть файл

@ -17,6 +17,8 @@ ntohs(uint16_t us)
return us << 8 | us >> 8;
}
#define htons(x) ntohs(x)
typedef uint8_t mac_address_t[6];
#define ETHERNET_TYPE_IPV4 0x0800
@ -34,6 +36,8 @@ typedef struct _ETHERNET_HEADER
} ETHERNET_HEADER, *PETHERNET_HEADER;
#define IPPROTO_UDP 17
#define IPPROTO_IPV4 4
#define IPPROTO_IPV6 41
typedef struct _IPV4_HEADER
{

Просмотреть файл

@ -125,7 +125,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\execution_context;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(SolutionDir)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\execution_context;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(SolutionDir)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpplatest</LanguageStandard>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@ -142,7 +142,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\execution_context;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(SolutionDir)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\api;$(SolutionDir)libs\execution_context;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)external\ebpf-verifier\src;$(SolutionDir)tests\end_to_end;$(SolutionDir)tests\libs\util;$(SolutionDir)tests\libs\common;$(SolutionDir)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(OutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpplatest</LanguageStandard>
<TreatWarningAsError>true</TreatWarningAsError>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>

Просмотреть файл

@ -5,20 +5,13 @@
#include "ebpf.h"
#include "xdp_tests_common.h"
void
copy_mac_address(mac_address_t destination, mac_address_t source)
{
for (int i = 0; i < sizeof(mac_address_t); i++)
destination[i] = source[i];
}
void
swap_mac_addresses(ETHERNET_HEADER* ethernet_header)
{
mac_address_t mac = {0};
copy_mac_address(mac, ethernet_header->Destination);
copy_mac_address(ethernet_header->Destination, ethernet_header->Source);
copy_mac_address(ethernet_header->Source, mac);
memcpy(mac, ethernet_header->Destination, sizeof(mac_address_t));
memcpy(ethernet_header->Destination, ethernet_header->Source, sizeof(mac_address_t));
memcpy(ethernet_header->Source, mac, sizeof(mac_address_t));
}
void
@ -29,20 +22,13 @@ swap_ipv4_addresses(IPV4_HEADER* ipv4_header)
ipv4_header->SourceAddress = address;
}
void
copy_ipv6_address(ipv6_address_t destination, ipv6_address_t source)
{
for (int i = 0; i < sizeof(ipv6_address_t); i++)
destination[i] = source[i];
}
void
swap_ipv6_addresses(IPV6_HEADER* ipv6_header)
{
ipv6_address_t address = {0};
copy_ipv6_address(address, ipv6_header->DestinationAddress);
copy_ipv6_address(ipv6_header->DestinationAddress, ipv6_header->SourceAddress);
copy_ipv6_address(ipv6_header->SourceAddress, address);
memcpy(address, ipv6_header->DestinationAddress, sizeof(ipv6_address_t));
memcpy(ipv6_header->DestinationAddress, ipv6_header->SourceAddress, sizeof(ipv6_address_t));
memcpy(ipv6_header->SourceAddress, address, sizeof(ipv6_address_t));
}
//
@ -50,7 +36,7 @@ swap_ipv6_addresses(IPV6_HEADER* ipv6_header)
// by swapping the MAC and IP addresses. The program will only work for packets where UDP is the next header
// for IP header. For instance this will not work for AH packets.
//
SEC("xdp")
SEC("xdp/reflect")
int
reflect_packet(xdp_md_t* ctx)
{
@ -100,6 +86,166 @@ reflect_packet(xdp_md_t* ctx)
}
}
Done:
return rc;
}
int
encapsulate_ipv4_reflect_packet(xdp_md_t* ctx)
{
int rc = XDP_DROP;
// Adjust XDP context to allocate space for outer IPv4 header.
if (bpf_xdp_adjust_head(ctx, -sizeof(IPV4_HEADER)) < 0)
goto Done;
// The new ethernet header will be at the beginning of the expanded buffer.
char* next_header = (char*)ctx->data;
if ((char*)next_header + sizeof(ETHERNET_HEADER) > (char*)ctx->data_end)
goto Done;
ETHERNET_HEADER* new_ethernet_header = (ETHERNET_HEADER*)next_header;
// The old ethernet header is at an offset sizeof(IPV4_HEADER) from the start of the XDP buffer.
next_header = (char*)ctx->data;
if ((char*)next_header + sizeof(IPV4_HEADER) > (char*)ctx->data_end)
goto Done;
next_header = (char*)ctx->data + sizeof(IPV4_HEADER);
ETHERNET_HEADER* old_ethernet_header = (ETHERNET_HEADER*)next_header;
// The outer IPv4 header will be after the new ethernet header.
next_header = (char*)(new_ethernet_header + 1);
if ((char*)next_header + sizeof(IPV4_HEADER) > (char*)ctx->data_end)
goto Done;
IPV4_HEADER* outer_ipv4_header = (IPV4_HEADER*)next_header;
// The inner IPv4 header will be after the old ethernet header.
next_header = (char*)(old_ethernet_header + 1);
if ((char*)next_header + sizeof(IPV4_HEADER) > (char*)ctx->data_end)
goto Done;
IPV4_HEADER* inner_ipv4_header = (IPV4_HEADER*)next_header;
// Copy over the old ethernet header to the new one.
memcpy(new_ethernet_header, old_ethernet_header, sizeof(ETHERNET_HEADER));
// Swap the MAC addresses.
swap_mac_addresses(new_ethernet_header);
// Copy over the inner IP header to the encap IP header.
memcpy(outer_ipv4_header, inner_ipv4_header, sizeof(IPV4_HEADER));
// Swap the IP addresses.
swap_ipv4_addresses(outer_ipv4_header);
// Adjust header fields.
outer_ipv4_header->Protocol = IPPROTO_IPV4;
outer_ipv4_header->HeaderLength = sizeof(IPV4_HEADER) / sizeof(uint32_t);
outer_ipv4_header->TotalLength = htons((ntohs(inner_ipv4_header->TotalLength) + sizeof(IPV4_HEADER)));
outer_ipv4_header->HeaderChecksum = 0;
rc = XDP_TX;
Done:
return rc;
}
int
encapsulate_ipv6_reflect_packet(xdp_md_t* ctx)
{
int rc = XDP_DROP;
// Adjust XDP context to allocate space for outer IPv6 header.
if (bpf_xdp_adjust_head(ctx, -sizeof(IPV6_HEADER)) < 0)
goto Done;
// The new ethernet header will be at the beginning of the expanded buffer.
char* next_header = (char*)ctx->data;
if ((char*)next_header + sizeof(ETHERNET_HEADER) > (char*)ctx->data_end)
goto Done;
ETHERNET_HEADER* new_ethernet_header = (ETHERNET_HEADER*)next_header;
// The old ethernet header is at an offset sizeof(IPV6_HEADER) from the start of the XDP buffer.
next_header = (char*)ctx->data;
if ((char*)next_header + sizeof(IPV6_HEADER) > (char*)ctx->data_end)
goto Done;
next_header = (char*)ctx->data + sizeof(IPV6_HEADER);
ETHERNET_HEADER* old_ethernet_header = (ETHERNET_HEADER*)next_header;
// The outer IPv6 header will be after the new ethernet header.
next_header = (char*)(new_ethernet_header + 1);
if ((char*)next_header + sizeof(IPV6_HEADER) > (char*)ctx->data_end)
goto Done;
IPV6_HEADER* outer_ipv6_header = (IPV6_HEADER*)next_header;
// The inner IPv6 header will be after the old ethernet header.
next_header = (char*)(old_ethernet_header + 1);
if ((char*)next_header + sizeof(IPV6_HEADER) > (char*)ctx->data_end)
goto Done;
IPV6_HEADER* inner_ipv6_header = (IPV6_HEADER*)next_header;
// Copy over the old ethernet header to the new one.
memcpy(new_ethernet_header, old_ethernet_header, sizeof(ETHERNET_HEADER));
// Swap the MAC addresses.
swap_mac_addresses(new_ethernet_header);
// Copy over the inner IP header to the encap IP header.
memcpy(outer_ipv6_header, inner_ipv6_header, sizeof(IPV6_HEADER));
// Swap the IP addresses.
swap_ipv6_addresses(outer_ipv6_header);
// Adjust header fields.
outer_ipv6_header->NextHeader = IPPROTO_IPV6;
outer_ipv6_header->PayloadLength = htons((ntohs(inner_ipv6_header->PayloadLength) + sizeof(IPV6_HEADER)));
rc = XDP_TX;
Done:
return rc;
}
//
// Same as the reflect_packet function, except the reflected packet is encapsulated in a new IP header.
// The addresses on the outer IP header are the reverse of those on the inner IP header.
// This program uses the bpf_xdp_adjust_head helper function.
// (This program can only perform v4 in v4 and v6 in v6 encapsulation.)
//
SEC("xdp/encap_reflect")
int
encap_reflect_packet(xdp_md_t* ctx)
{
int rc = XDP_PASS;
ETHERNET_HEADER* ethernet_header = NULL;
char* next_header = (char*)ctx->data;
if ((char*)next_header + sizeof(ETHERNET_HEADER) > (char*)ctx->data_end)
goto Done;
ethernet_header = (ETHERNET_HEADER*)next_header;
next_header = (char*)(ethernet_header + 1);
if (ethernet_header->Type == ntohs(ETHERNET_TYPE_IPV4)) {
if ((char*)next_header + sizeof(IPV4_HEADER) > (char*)ctx->data_end)
goto Done;
// IPv4.
IPV4_HEADER* ipv4_header = (IPV4_HEADER*)next_header;
next_header = (char*)ipv4_header + sizeof(uint32_t) * ipv4_header->HeaderLength;
if (ipv4_header->Protocol == IPPROTO_UDP) {
if ((char*)next_header + sizeof(UDP_HEADER) > (char*)ctx->data_end)
goto Done;
// UDP.
UDP_HEADER* udp_header = (UDP_HEADER*)next_header;
if (udp_header->destPort == ntohs(REFLECTION_TEST_PORT))
rc = encapsulate_ipv4_reflect_packet(ctx);
}
} else if (ethernet_header->Type == ntohs(ETHERNET_TYPE_IPV6)) {
if ((char*)next_header + sizeof(IPV6_HEADER) > (char*)ctx->data_end)
goto Done;
// IPv6.
IPV6_HEADER* ipv6_header = (IPV6_HEADER*)next_header;
next_header = (char*)(ipv6_header + 1);
if (ipv6_header->NextHeader == IPPROTO_UDP) {
if ((char*)next_header + sizeof(UDP_HEADER) > (char*)ctx->data_end)
goto Done;
// UDP.
UDP_HEADER* udp_header = (UDP_HEADER*)next_header;
if (udp_header->destPort == ntohs(REFLECTION_TEST_PORT))
rc = encapsulate_ipv6_reflect_packet(ctx);
}
}
Done:
return rc;
}

Просмотреть файл

@ -126,7 +126,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\tests\xdp;$(SolutionDir)tools\encode_program_info;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(SolutionDir)\tests\xdp;$(SolutionDir)tools\encode_program_info;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -146,7 +146,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\tests\xdp;$(SolutionDir)tools\encode_program_info;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\api_common;$(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)tests\sample;$(SolutionDir)tests\sample\ext\inc;$(SolutionDir)\netebpfext;$(SolutionDir)\tests\xdp;$(SolutionDir)tools\encode_program_info;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>

Просмотреть файл

@ -1,10 +1,12 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <vector>
#include "ebpf_api.h"
#include "ebpf_nethooks.h"
#include "encode_program_info.h"
#include "net_ebpf_ext_program_info.h"
static ebpf_result_t
_emit_program_info_file(const char* file_name, const char* symbol_name, uint8_t* buffer, unsigned long buffer_size)
@ -72,8 +74,16 @@ _encode_xdp()
EBPF_OFFSET_OF(xdp_md_t, data_meta)};
ebpf_program_type_descriptor_t xdp_program_type = {"xdp", &xdp_context_descriptor, EBPF_PROGRAM_TYPE_XDP};
ebpf_program_info_t xdp_program_info = {xdp_program_type, 0, NULL};
xdp_program_info.count_of_helpers = ebpf_core_helper_functions_count;
xdp_program_info.helper_prototype = ebpf_core_helper_function_prototype;
xdp_program_info.count_of_helpers =
ebpf_core_helper_functions_count + EBPF_COUNT_OF(_xdp_ebpf_extension_helper_function_prototype);
std::vector<ebpf_helper_function_prototype_t> _helper_function_prototypes;
_helper_function_prototypes.assign(
ebpf_core_helper_function_prototype, ebpf_core_helper_function_prototype + ebpf_core_helper_functions_count);
_helper_function_prototypes.insert(
_helper_function_prototypes.end(),
_xdp_ebpf_extension_helper_function_prototype,
_xdp_ebpf_extension_helper_function_prototype + EBPF_COUNT_OF(_xdp_ebpf_extension_helper_function_prototype));
xdp_program_info.helper_prototype = _helper_function_prototypes.data();
return_value = ebpf_program_info_encode(&xdp_program_info, &buffer, &buffer_size);
if (return_value != EBPF_SUCCESS)
goto Done;

Просмотреть файл

@ -126,7 +126,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\api</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\api;$(SolutionDir)\netebpfext</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
@ -153,7 +153,7 @@ $(OutputPath)encode_program_info.exe</Command>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\api</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)libs\platform;$(SolutionDir)libs\platform\user;$(SolutionDir)libs\api;$(SolutionDir)\netebpfext</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>