From f026933f21789eefa2791531908ae4950094a76b Mon Sep 17 00:00:00 2001 From: Shankar Seal <74580197+shankarseal@users.noreply.github.com> Date: Tue, 23 Jan 2024 07:30:34 -0800 Subject: [PATCH] Bpf export (#443) --- src/bpfexport/bpfexport.c | 57 +++++++++++++++++++++++++++ src/bpfexport/bpfexport.rc | 56 +++++++++++++++++++++++++++ src/bpfexport/bpfexport.vcxproj | 68 +++++++++++++++++++++++++++++++++ src/xdp/ebpfstore.h | 58 ++++++++++++++++++++++++++++ src/xdp/program.c | 36 +---------------- src/xdpinstaller/Product.wxs | 4 +- test/bpf/bpf.vcxproj | 20 ++++++++++ tools/create-devkit.ps1 | 2 + tools/prepare-machine.ps1 | 9 ----- tools/setup.ps1 | 2 - xdp.sln | 14 ++++++- 11 files changed, 277 insertions(+), 49 deletions(-) create mode 100644 src/bpfexport/bpfexport.c create mode 100644 src/bpfexport/bpfexport.rc create mode 100644 src/bpfexport/bpfexport.vcxproj create mode 100644 src/xdp/ebpfstore.h diff --git a/src/bpfexport/bpfexport.c b/src/bpfexport/bpfexport.c new file mode 100644 index 00000000..1943878a --- /dev/null +++ b/src/bpfexport/bpfexport.c @@ -0,0 +1,57 @@ +// +// Copyright (c) Microsoft Corporation. +// + +#include +#include +// +// Work around various eBPF compilation bugs. +// +#define USER_MODE 1 +#pragma warning(push) +#pragma warning(disable:4005) // 'WIN32_LEAN_AND_MEAN': macro redefinition +#include +#include +#pragma warning(pop) +#undef USER_MODE + +INT +__cdecl +main( + INT argc, + CHAR *argv[] + ) +{ + ebpf_result_t result; + int exit_code = 0; + + if (argc == 2 && !_strcmpi("--clear", argv[1])) { + for (uint32_t i = 0; i < RTL_NUMBER_OF(EbpfXdpSectionInfo); i++) { + result = ebpf_store_delete_section_information(&EbpfXdpSectionInfo[i]); + if (result != EBPF_SUCCESS) { + fprintf(stderr, "ebpf_store_delete_section_information failed: %u\n", result); + exit_code = -1; + } + } + + result = ebpf_store_delete_program_information(&EbpfXdpProgramInfo); + if (result != EBPF_SUCCESS) { + fprintf(stderr, "ebpf_store_delete_program_information failed: %u\n", result); + exit_code = -1; + } + } else { + result = ebpf_store_update_section_information(&EbpfXdpSectionInfo[0], RTL_NUMBER_OF(EbpfXdpSectionInfo)); + if (result != EBPF_SUCCESS) { + fprintf(stderr, "ebpf_store_update_section_information failed: %u\n", result); + exit_code = -1; + } + + result = ebpf_store_update_program_information(&EbpfXdpProgramInfo, 1); + if (result != EBPF_SUCCESS) { + fprintf(stderr, "ebpf_store_update_program_information failed: %u\n", result); + exit_code = -1; + } + } + + return exit_code; +} diff --git a/src/bpfexport/bpfexport.rc b/src/bpfexport/bpfexport.rc new file mode 100644 index 00000000..5c146a44 --- /dev/null +++ b/src/bpfexport/bpfexport.rc @@ -0,0 +1,56 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// + +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// + +#include +#include + +#define VER_FILETYPE VFT_APP +#define VER_FILESUBTYPE VFT2_UNKNOWN + +#define VER_FILEVERSION XDP_MAJOR_VERSION, XDP_MINOR_VERSION, XDP_PATCH_VERSION, 0 +#define VER_FILEVERSION_STR STR(XDP_MAJOR_VERSION) "." STR(XDP_MINOR_VERSION) "." STR(XDP_PATCH_VERSION) ".0\0" +#define VER_PRODUCTVERSION_STR XDP_VERSION_STR + +#define VER_FILEDESCRIPTION_STR "Microsoft\256 XDP eBPF Export Tool" +#define VER_ORIGINALFILENAME_STR "bpfexport.exe" + +#define VER_COMPANYNAME_STR "Microsoft Corporation" +#define VER_LEGALCOPYRIGHT_STR "\251 Microsoft Corporation. All rights reserved." +#define VER_PRODUCTNAME_STR "Microsoft\256 XDP" +#define VER_INTERNALNAME_STR "bpfexport" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VER_FILETYPE +FILESUBTYPE VER_FILESUBTYPE + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04B0 + END +END \ No newline at end of file diff --git a/src/bpfexport/bpfexport.vcxproj b/src/bpfexport/bpfexport.vcxproj new file mode 100644 index 00000000..19047add --- /dev/null +++ b/src/bpfexport/bpfexport.vcxproj @@ -0,0 +1,68 @@ + + + + + + + + + + + 16.0 + Win32Proj + {8f8830ff-1648-4772-87ed-f5da091fc931} + bpfexport + + + Windows10 + WindowsApplicationForDrivers10.0 + Application + + + + + + + + + + + xdp_bpfexport + $(SolutionDir)artifacts\bin\$(Platform)_$(Configuration)\ + + + + + $(SolutionDir)published\private; + %(AdditionalIncludeDirectories) + + + XDP_MAJOR_VERSION=$(XdpMajorVersion); + XDP_MINOR_VERSION=$(XdpMinorVersion); + XDP_PATCH_VERSION=$(XdpPatchVersion); + %(PreprocessorDefinitions) + + + XDP_BUILD_VERSION=$(BUILD_BUILDID); + %(PreprocessorDefinitions) + + + + + + + $(SolutionDir)src\xdp; + %(AdditionalIncludeDirectories) + + + + Console + + onecore.lib; + %(AdditionalDependencies) + + + + + + diff --git a/src/xdp/ebpfstore.h b/src/xdp/ebpfstore.h new file mode 100644 index 00000000..6756dc36 --- /dev/null +++ b/src/xdp/ebpfstore.h @@ -0,0 +1,58 @@ +// +// Copyright (c) Microsoft Corporation. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +static const ebpf_context_descriptor_t EbpfXdpContextDescriptor = { + .size = sizeof(xdp_md_t), + .data = FIELD_OFFSET(xdp_md_t, data), + .end = FIELD_OFFSET(xdp_md_t, data_end), + .meta = FIELD_OFFSET(xdp_md_t, data_meta), +}; + +#define XDP_EXT_HELPER_FUNCTION_START EBPF_MAX_GENERAL_HELPER_FUNCTION + +// XDP helper function prototype descriptors. +static const ebpf_helper_function_prototype_t EbpfXdpHelperFunctionPrototype[] = { + { + .helper_id = XDP_EXT_HELPER_FUNCTION_START + 1, + .name = "bpf_xdp_adjust_head", + .return_type = EBPF_RETURN_TYPE_INTEGER, + .arguments = { + EBPF_ARGUMENT_TYPE_PTR_TO_CTX, + EBPF_ARGUMENT_TYPE_ANYTHING, + }, + }, +}; + +#pragma warning(suppress:4090) // 'initializing': different 'const' qualifiers +const ebpf_program_info_t EbpfXdpProgramInfo = { +#pragma warning(suppress:4090) // 'initializing': different 'const' qualifiers + .program_type_descriptor = { + .name = "xdp", + .context_descriptor = &EbpfXdpContextDescriptor, + .program_type = EBPF_PROGRAM_TYPE_XDP_INIT, + BPF_PROG_TYPE_XDP, + }, + .count_of_program_type_specific_helpers = RTL_NUMBER_OF(EbpfXdpHelperFunctionPrototype), + .program_type_specific_helper_prototype = EbpfXdpHelperFunctionPrototype, +}; + +#define DECLARE_XDP_SECTION(_section_name) \ + (const wchar_t*)_section_name, &EBPF_PROGRAM_TYPE_XDP, &EBPF_ATTACH_TYPE_XDP, \ + BPF_PROG_TYPE_XDP, BPF_XDP + +const ebpf_program_section_info_t DECLSPEC_SELECTANY EbpfXdpSectionInfo[] = { + { + DECLARE_XDP_SECTION(L"xdp") + } +}; \ No newline at end of file diff --git a/src/xdp/program.c b/src/xdp/program.c index 9f1a5bde..012f1bc2 100644 --- a/src/xdp/program.c +++ b/src/xdp/program.c @@ -8,6 +8,7 @@ // #include "precomp.h" +#include "ebpfstore.h" #include "programinspect.h" #include "program.tmh" @@ -621,41 +622,6 @@ XdpProgramTraceObject( XdpProgramTrace(&ProgramObject->Program); } -static const ebpf_context_descriptor_t EbpfXdpContextDescriptor = { - .size = sizeof(xdp_md_t), - .data = FIELD_OFFSET(xdp_md_t, data), - .end = FIELD_OFFSET(xdp_md_t, data_end), - .meta = FIELD_OFFSET(xdp_md_t, data_meta), -}; - -#define XDP_EXT_HELPER_FUNCTION_START EBPF_MAX_GENERAL_HELPER_FUNCTION - -// XDP helper function prototype descriptors. -static const ebpf_helper_function_prototype_t EbpfXdpHelperFunctionPrototype[] = { - { - .helper_id = XDP_EXT_HELPER_FUNCTION_START + 1, - .name = "bpf_xdp_adjust_head", - .return_type = EBPF_RETURN_TYPE_INTEGER, - .arguments = { - EBPF_ARGUMENT_TYPE_PTR_TO_CTX, - EBPF_ARGUMENT_TYPE_ANYTHING, - }, - }, -}; - -#pragma warning(suppress:4090) // 'initializing': different 'const' qualifiers -static const ebpf_program_info_t EbpfXdpProgramInfo = { -#pragma warning(suppress:4090) // 'initializing': different 'const' qualifiers - .program_type_descriptor = { - .name = "xdp", - .context_descriptor = &EbpfXdpContextDescriptor, - .program_type = EBPF_PROGRAM_TYPE_XDP_INIT, - BPF_PROG_TYPE_XDP, - }, - .count_of_program_type_specific_helpers = RTL_NUMBER_OF(EbpfXdpHelperFunctionPrototype), - .program_type_specific_helper_prototype = EbpfXdpHelperFunctionPrototype, -}; - static int EbpfXdpAdjustHead( diff --git a/src/xdpinstaller/Product.wxs b/src/xdpinstaller/Product.wxs index db18d113..9ecd1aed 100644 --- a/src/xdpinstaller/Product.wxs +++ b/src/xdpinstaller/Product.wxs @@ -56,7 +56,6 @@ SPDX-License-Identifier: MIT - @@ -73,6 +72,9 @@ SPDX-License-Identifier: MIT + + + diff --git a/test/bpf/bpf.vcxproj b/test/bpf/bpf.vcxproj index c4df8582..6c20ae25 100644 --- a/test/bpf/bpf.vcxproj +++ b/test/bpf/bpf.vcxproj @@ -2,6 +2,12 @@ + + + {8f8830ff-1648-4772-87ed-f5da091fc931} + false + + 16.0 Win32Proj @@ -25,6 +31,20 @@ bpf $(SolutionDir)artifacts\bin\$(Platform)_$(Configuration)\bpf\ + + + + set PATH=%PATH%;$(EbpfPackagePath)build\native\bin + $(SolutionDir)artifacts\bin\$(Platform)_$(Configuration)\xdp_bpfexport.exe + + + + + set PATH=%PATH%;$(EbpfPackagePath)build\native\bin + $(SolutionDir)artifacts\bin\$(Platform)_$(Configuration)\xdp_bpfexport.exe --clear + + + CppCode diff --git a/tools/create-devkit.ps1 b/tools/create-devkit.ps1 index 03722c80..7f1550a2 100644 --- a/tools/create-devkit.ps1 +++ b/tools/create-devkit.ps1 @@ -36,6 +36,7 @@ copy "artifacts\bin\$($Platform)_$($Config)\rxfilter.exe" $DstPath\bin copy "artifacts\bin\$($Platform)_$($Config)\xdpcfg.exe" $DstPath\bin copy "artifacts\bin\$($Platform)_$($Config)\xskbench.exe" $DstPath\bin copy "artifacts\bin\$($Platform)_$($Config)\xskfwd.exe" $DstPath\bin +copy "artifacts\bin\$($Platform)_$($Config)\xdp_bpfexport.exe" $DstPath\bin New-Item -Path $DstPath\symbols -ItemType Directory > $null copy "artifacts\bin\$($Platform)_$($Config)\xdp.pdb" $DstPath\symbols @@ -45,6 +46,7 @@ copy "artifacts\bin\$($Platform)_$($Config)\rxfilter.pdb" $DstPath\symbols copy "artifacts\bin\$($Platform)_$($Config)\xdpcfg.pdb" $DstPath\symbols copy "artifacts\bin\$($Platform)_$($Config)\xskbench.pdb" $DstPath\symbols copy "artifacts\bin\$($Platform)_$($Config)\xskfwd.pdb" $DstPath\symbols +copy "artifacts\bin\$($Platform)_$($Config)\xdp_bpfexport.pdb" $DstPath\symbols New-Item -Path $DstPath\include -ItemType Directory > $null copy -Recurse published\external\* $DstPath\include diff --git a/tools/prepare-machine.ps1 b/tools/prepare-machine.ps1 index 3a12c8e5..5d186402 100644 --- a/tools/prepare-machine.ps1 +++ b/tools/prepare-machine.ps1 @@ -274,15 +274,6 @@ if ($Cleanup) { if (!(cmd /c "clang --version 2>&1" | Select-String "clang version 11.")) { Write-Error "Compiling eBPF programs on Windows requires clang version 11" } - - $EbpfExportProgram = "$EbpfNugetRestoreDir/build/native/bin/export_program_info.exe" - - if (!(Test-Path $EbpfExportProgram)) { - Write-Error "Missing eBPF helper export_program_info.exe. Is the NuGet package installed?" - } - - Write-Verbose $EbpfExportProgram - & $EbpfExportProgram | Write-Verbose } if ($ForFunctionalTest) { diff --git a/tools/setup.ps1 b/tools/setup.ps1 index 528d6675..6759d956 100644 --- a/tools/setup.ps1 +++ b/tools/setup.ps1 @@ -593,8 +593,6 @@ function Install-Ebpf { if (!$? -or !(Test-Path $EbpfPath)) { Write-Error "eBPF could not be installed" } - # Stop eBPF's XDP hook since it conflicts with our XDP implementation. - Stop-Service netebpfext Refresh-Path } diff --git a/xdp.sln b/xdp.sln index 374ac7a3..2c07da23 100644 --- a/xdp.sln +++ b/xdp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29728.190 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34408.163 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nmr", "src\nmr\nmr.vcxproj", "{F389859E-1D0C-4F30-BAEC-6A5E44B8190E}" EndProject @@ -75,6 +75,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xdppcw", "src\xdppcw\xdppcw EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pktfuzz", "test\pktfuzz\pktfuzz.vcxproj", "{A1864618-ED3D-43C5-8013-A177F9CF73D9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bpfexport", "src\bpfexport\bpfexport.vcxproj", "{8F8830FF-1648-4772-87ED-F5DA091FC931}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -463,6 +465,14 @@ Global {A1864618-ED3D-43C5-8013-A177F9CF73D9}.Release|x64.ActiveCfg = Release|x64 {A1864618-ED3D-43C5-8013-A177F9CF73D9}.Release|x64.Build.0 = Release|x64 {A1864618-ED3D-43C5-8013-A177F9CF73D9}.Release|x64.Deploy.0 = Release|x64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Debug|ARM64.Build.0 = Debug|ARM64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Debug|x64.ActiveCfg = Debug|x64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Debug|x64.Build.0 = Debug|x64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Release|ARM64.ActiveCfg = Release|ARM64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Release|ARM64.Build.0 = Release|ARM64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Release|x64.ActiveCfg = Release|x64 + {8F8830FF-1648-4772-87ED-F5DA091FC931}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE