Skip to content

Commit

Permalink
Increase MAX_TAIL_CALL_CNT to 33 tail calls (#2826)
Browse files Browse the repository at this point in the history
* Initial Commit

* Added tail call max exceed native test case

* Initial commit

* Initial commit

* Added bpf2c_tests/expected changed files

* Fixed the return value in bind_tailcall_max_native_test

* Addressed PR comments

* Update tests/unit/libbpf_test.cpp

Co-authored-by: Dave Thaler <[email protected]>

* Update tests/unit/libbpf_test.cpp

Co-authored-by: Dave Thaler <[email protected]>

* tests/unit/libbpf_test.cpp

* Moved MAX_TAIL_CALL_CNT to ebpf_structs.h as suggested

* Removed MAX_TAIL_CALL_CNT in api_test and stress_tests_km file

* Add the generated expected file for tail_call_max_exceed

* Removed MAX_TAIL_CALL_CNT from bpf_helpers.h

---------

Co-authored-by: Dave Thaler <[email protected]>
  • Loading branch information
shpalani and dthaler authored Sep 11, 2023
1 parent f595311 commit 5cc488f
Show file tree
Hide file tree
Showing 22 changed files with 32,586 additions and 6,795 deletions.
2 changes: 0 additions & 2 deletions include/bpf_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,3 @@
#endif

#include "bpf_helper_defs.h"

#define MAX_TAIL_CALL_CNT 32
2 changes: 2 additions & 0 deletions include/ebpf_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
#endif

#define MAX_TAIL_CALL_CNT 33

#define BPF_ENUM_TO_STRING(X) #X

typedef enum bpf_map_type
Expand Down
12 changes: 12 additions & 0 deletions installer/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,18 @@ SPDX-License-Identifier: MIT
<Component Id="TAIL_CALL_MULTIPLE_UM.PDB" DiskId="1" Guid="{D918F2DB-BC80-406F-B0AD-0C340D5EF280}">
<File Id="TAIL_CALL_MULTIPLE_UM.PDB" Name="tail_call_multiple_um.pdb" Source="$(var.SolutionDir)$(var.Platform)\$(var.Configuration)\tail_call_multiple_um.pdb" />
</Component>
<Component Id="TAIL_CALL_MAX_EXCEED.O" DiskId="1" Guid="{A3E840BD-B510-4F02-80A6-1EA0553C6746}">
<File Id="TAIL_CALL_MAX_EXCEED.O" Name="tail_call_max_exceed.o" Source="$(var.SolutionDir)$(var.Platform)\$(var.Configuration)\tail_call_recursive.o" />
</Component>
<Component Id="TAIL_CALL_MAX_EXCEED.SYS" DiskId="1" Guid="{D3EE01E4-8258-46D4-89FA-C207960C90E6}">
<File Id="TAIL_CALL_MAX_EXCEED.SYS" Name="tail_call_max_exceed.sys" Source="$(var.SolutionDir)$(var.Platform)\$(var.Configuration)\tail_call_recursive.sys" />
</Component>
<Component Id="TAIL_CALL_MAX_EXCEED_UM.DLL" DiskId="1" Guid="{916F7BF5-6B8A-4C99-A09F-102CBB404AA5}">
<File Id="TAIL_CALL_MAX_EXCEED_UM.DLL" Name="tail_call_max_exceed_um.dll" Source="$(var.SolutionDir)$(var.Platform)\$(var.Configuration)\tail_call_recursive_um.dll" />
</Component>
<Component Id="TAIL_CALL_MAX_EXCEED_UM.PDB" DiskId="1" Guid="{9A1BFAAD-D94F-4805-842F-B8DB77B6FC6C}">
<File Id="TAIL_CALL_MAX_EXCEED_UM.PDB" Name="tail_call_max_exceed_um.pdb" Source="$(var.SolutionDir)$(var.Platform)\$(var.Configuration)\tail_call_recursive_um.pdb" />
</Component>
<Component Id="TAIL_CALL_RECURSIVE.O" DiskId="1" Guid="{7469C19C-7706-44B7-BA35-6F27195F311A}">
<File Id="TAIL_CALL_RECURSIVE.O" Name="tail_call_recursive.o" Source="$(var.SolutionDir)$(var.Platform)\$(var.Configuration)\tail_call_recursive.o" />
</Component>
Expand Down
7 changes: 5 additions & 2 deletions libs/execution_context/ebpf_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -1348,10 +1348,12 @@ ebpf_program_set_tail_call(_In_ const ebpf_program_t* next_program)
}

if (state == NULL) {
EBPF_LOG_MESSAGE_STRING(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, "ebpf tail call state load:", "NULL");
return EBPF_INVALID_ARGUMENT;
}

if (state->tail_call_state.count == (MAX_TAIL_CALL_CNT - 1)) {
if (state->tail_call_state.count == (MAX_TAIL_CALL_CNT)) {
EBPF_OBJECT_RELEASE_REFERENCE(&((ebpf_program_t*)next_program)->object);
return EBPF_NO_MORE_TAIL_CALLS;
}
Expand Down Expand Up @@ -1389,7 +1391,8 @@ ebpf_program_invoke(
// High volume call - Skip entry/exit logging.
const ebpf_program_t* current_program = program;

for (execution_state->tail_call_state.count = 0; execution_state->tail_call_state.count < MAX_TAIL_CALL_CNT;
// Top-level tail caller(1) + tail callees(33).
for (execution_state->tail_call_state.count = 0; execution_state->tail_call_state.count < MAX_TAIL_CALL_CNT + 1;
execution_state->tail_call_state.count++) {

if (current_program->parameters.code_type == EBPF_CODE_JIT ||
Expand Down
4 changes: 4 additions & 0 deletions scripts/deploy-ebpf.ps1.in
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ $source_directory="."
"tail_call_map_um.dll",
"tail_call_map_um.pdb",
"tail_call_map.sys",
"tail_call_max_exceed.o",
"tail_call_max_exceed_um.dll",
"tail_call_max_exceed_um.pdb",
"tail_call_max_exceed.sys",
"tail_call_multiple.o",
"tail_call_multiple_um.dll",
"tail_call_multiple_um.pdb",
Expand Down
57 changes: 57 additions & 0 deletions tests/api_test/api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,63 @@ TEST_CASE("bindmonitor_tailcall_native_test", "[native_tests]")
cleanup();
}

void
bind_tailcall_test(_In_ struct bpf_object* object)
{
UNREFERENCED_PARAMETER(object);
WSAData data;
SOCKET sockets[2];
REQUIRE(WSAStartup(2, &data) == 0);

// Now, trigger bind. bind should not succeed.
REQUIRE(perform_bind(&sockets[0], 30000) != 0);
REQUIRE(perform_bind(&sockets[1], 30001) != 0);

WSACleanup();
}

#define MAX_TAIL_CALL_PROGS MAX_TAIL_CALL_CNT + 2

TEST_CASE("bind_tailcall_max_native_test", "[native_tests]")
{
struct bpf_object* object = nullptr;
hook_helper_t hook(EBPF_ATTACH_TYPE_BIND);

program_load_attach_helper_t _helper;
_helper.initialize(
"tail_call_max_exceed.sys",
BPF_PROG_TYPE_BIND,
"bind_test_caller",
EBPF_EXECUTION_NATIVE,
nullptr,
0,
hook);
object = _helper.get_object();

fd_t prog_map_fd = bpf_object__find_map_fd_by_name(object, "bind_tail_call_map");
REQUIRE(prog_map_fd > 0);

struct bpf_program* caller = bpf_object__find_program_by_name(object, "bind_test_caller");
REQUIRE(caller != nullptr);

// Check each tail call program in the map.
for (int i = 0; i < MAX_TAIL_CALL_PROGS; i++) {
std::string program_name{"bind_test_callee"};
program_name += std::to_string(i);

struct bpf_program* program = bpf_object__find_program_by_name(object, program_name.c_str());
REQUIRE(program != nullptr);
}

// Perform bind test.
bind_tailcall_test(object);

// Clean up tail calls.
for (int index = 0; index < MAX_TAIL_CALL_PROGS; index++) {
REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
}
}

#define SOCKET_TEST_PORT 0x3bbf

TEST_CASE("bpf_get_current_pid_tgid", "[helpers]")
Expand Down
1 change: 1 addition & 0 deletions tests/bpf2c_tests/elf_bpf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ DECLARE_TEST("sockops", _test_mode::Verify)
DECLARE_TEST("tail_call", _test_mode::Verify)
DECLARE_TEST("tail_call_bad", _test_mode::Verify)
DECLARE_TEST("tail_call_map", _test_mode::Verify)
DECLARE_TEST("tail_call_max_exceed", _test_mode::Verify)
DECLARE_TEST("tail_call_multiple", _test_mode::Verify)
DECLARE_TEST("tail_call_recursive", _test_mode::Verify)
DECLARE_TEST("tail_call_sequential", _test_mode::Verify)
Expand Down
Loading

0 comments on commit 5cc488f

Please sign in to comment.