Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add map examples #14

Merged
merged 7 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
- name: Run example
run: |
./build/vm-llvm-example
./build/maps-example

- name: Run tests
run: |
Expand Down
3 changes: 3 additions & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
ignore:
- "build"
- "test"
- "example"

coverage:
status:
Expand All @@ -15,3 +17,4 @@ coverage:
target: auto
base: auto
only_pulls: false
threshold: 25%
6 changes: 6 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ bpftime_add_executable(vm-llvm-example
add_dependencies(vm-llvm-example llvmbpf_vm spdlog::spdlog)
target_link_libraries(vm-llvm-example llvmbpf_vm)

bpftime_add_executable(maps-example
./maps.cpp
)

add_dependencies(maps-example llvmbpf_vm spdlog::spdlog)
target_link_libraries(maps-example llvmbpf_vm)
12 changes: 8 additions & 4 deletions example/basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
#include <cassert>
#include "llvmbpf.hpp"

using namespace bpftime;
Expand Down Expand Up @@ -71,7 +72,7 @@ const unsigned char bpf_function_call_print[] =
"\xb7\x00\x00\x00\x00\x00\x00\x00"
"\x95\x00\x00\x00\x00\x00\x00\x00";

void run_ebpf_prog(const void *code, size_t code_len)
uint64_t run_ebpf_prog(const void *code, size_t code_len)
{
uint64_t res = 0;
llvmbpf_vm vm;
Expand All @@ -96,13 +97,16 @@ void run_ebpf_prog(const void *code, size_t code_len)
exit(1);
}
printf("res = %" PRIu64 "\n", res);
return res;
}

int main(int argc, char *argv[])
{
run_ebpf_prog(bpf_add_mem_64_bit, sizeof(bpf_add_mem_64_bit));
run_ebpf_prog(bpf_mul_64_bit, sizeof(bpf_mul_64_bit));
assert(run_ebpf_prog(bpf_add_mem_64_bit, sizeof(bpf_add_mem_64_bit)) ==
3433728102);
assert(run_ebpf_prog(bpf_mul_64_bit, sizeof(bpf_mul_64_bit)) == 2);
// here we use string for the code
run_ebpf_prog(bpf_function_call_print, sizeof(bpf_function_call_print) - 1);
assert(run_ebpf_prog(bpf_function_call_print,
sizeof(bpf_function_call_print) - 1) == 0);
return 0;
}
131 changes: 131 additions & 0 deletions example/maps.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include <cstdint>
#include <iostream>
#include <ostream>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
#include <cassert>
#include "llvmbpf.hpp"

using namespace bpftime;
const unsigned char xdp_counter_bytecode[] = "\x79\x16\x00\x00\x00\x00\x00\x00"
"\x79\x17\x08\x00\x00\x00\x00\x00"
"\xb7\x01\x00\x00\x00\x00\x00\x00"
"\x63\x1a\xfc\xff\x00\x00\x00\x00"
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
"\x07\x02\x00\x00\xfc\xff\xff\xff"
"\x18\x11\x00\x00\x05\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x85\x00\x00\x00\x01\x00\x00\x00"
"\xbf\x01\x00\x00\x00\x00\x00\x00"
"\xb7\x00\x00\x00\x02\x00\x00\x00"
"\x15\x01\x18\x00\x00\x00\x00\x00"
"\x61\x11\x00\x00\x00\x00\x00\x00"
"\x55\x01\x16\x00\x00\x00\x00\x00"
"\x18\x21\x00\x00\x06\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x79\x12\x00\x00\x00\x00\x00\x00"
"\x07\x02\x00\x00\x01\x00\x00\x00"
"\x7b\x21\x00\x00\x00\x00\x00\x00"
"\xb7\x00\x00\x00\x01\x00\x00\x00"
"\xbf\x61\x00\x00\x00\x00\x00\x00"
"\x07\x01\x00\x00\x0e\x00\x00\x00"
"\x2d\x71\x0d\x00\x00\x00\x00\x00"
"\x69\x61\x00\x00\x00\x00\x00\x00"
"\x69\x62\x06\x00\x00\x00\x00\x00"
"\x6b\x26\x00\x00\x00\x00\x00\x00"
"\x69\x62\x08\x00\x00\x00\x00\x00"
"\x69\x63\x02\x00\x00\x00\x00\x00"
"\x6b\x36\x08\x00\x00\x00\x00\x00"
"\x6b\x26\x02\x00\x00\x00\x00\x00"
"\x69\x62\x0a\x00\x00\x00\x00\x00"
"\x69\x63\x04\x00\x00\x00\x00\x00"
"\x6b\x36\x0a\x00\x00\x00\x00\x00"
"\x6b\x16\x06\x00\x00\x00\x00\x00"
"\x6b\x26\x04\x00\x00\x00\x00\x00"
"\xb7\x00\x00\x00\x03\x00\x00\x00"
"\x95\x00\x00\x00\x00\x00\x00\x00";

uint8_t bpf_mem[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };

uint32_t ctl_array[2] = { 0, 0 };
uint64_t cntrs_array[2] = { 0, 0 };

void *bpf_map_lookup_elem(uint64_t map_fd, void *key)
{
std::cout << "bpf_map_lookup_elem " << map_fd << std::endl;
if (map_fd == 5) {
return &ctl_array[*(uint32_t *)key];
} else if (map_fd == 6) {
return &cntrs_array[*(uint32_t *)key];
} else {
return nullptr;
}
return 0;
}

uint64_t map_by_fd(uint32_t fd)
{
std::cout << "map_by_fd " << fd << std::endl;
return fd;
}

uint64_t map_val(uint64_t val)
{
std::cout << "map_val " << val << std::endl;
if (val == 5) {
return (uint64_t)(void *)ctl_array;
} else if (val == 6) {
return (uint64_t)(void *)cntrs_array;
} else {
return 0;
}
}

int main(int argc, char *argv[])
{
auto code = xdp_counter_bytecode;
size_t code_len = sizeof(xdp_counter_bytecode) - 1;
uint64_t res = 0;
llvmbpf_vm vm;
std::cout << "running ebpf prog, code len: " << code_len << std::endl;

res = vm.load_code(code, code_len);
if (res) {
std::cout << vm.get_error_message() << std::endl;
exit(1);
}
vm.register_external_function(1, "bpf_map_lookup_elem",
(void *)bpf_map_lookup_elem);
// set the lddw helpers for accessing maps
vm.set_lddw_helpers(map_by_fd, nullptr, map_val, nullptr, nullptr);
auto func = vm.compile();
if (!func) {
std::cout << vm.get_error_message() << std::endl;
exit(1);
}
// Map value (counter) should be 0
std::cout << "cntrs_array[0] = " << cntrs_array[0] << std::endl;
int err = vm.exec(&bpf_mem, sizeof(bpf_mem), res);
assert(err == 0 && cntrs_array[0] == 1);
std::cout << "\nreturn value = " << res << std::endl;
// counter should be 1
std::cout << "cntrs_array[0] = " << cntrs_array[0] << std::endl;

err = vm.exec(&bpf_mem, sizeof(bpf_mem), res);
assert(err == 0 && cntrs_array[0] == 2);
std::cout << "\nreturn value = " << res << std::endl;
// counter should be 2
std::cout << "cntrs_array[0] = " << cntrs_array[0] << std::endl;

// Change the value of the control array can change the return value
ctl_array[0] = 1;
err = vm.exec(&bpf_mem, sizeof(bpf_mem), res);
assert(err == 0);
std::cout << "\nreturn value = " << res << std::endl;
return 0;
}
48 changes: 32 additions & 16 deletions src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,8 @@
std::to_string(size) +
") or mode (" +
std::to_string(mode) +
") for non-standard load operations",
") for non-standard load operations" +
" at pc " + std::to_string(pc),

Check warning on line 612 in src/compiler.cpp

View check run for this annotation

Codecov / codecov/patch

src/compiler.cpp#L611-L612

Added lines #L611 - L612 were not covered by tests
llvm::inconvertibleErrorCode());
}
if (pc + 1 >= insts.size()) {
Expand All @@ -619,8 +620,8 @@
llvm::inconvertibleErrorCode());
}
const auto &nextinst = insts[pc + 1];
if (nextinst.opcode || nextinst.dst ||
nextinst.src || nextinst.offset) {
if (nextinst.opcode || nextinst.dst || nextinst.src ||
nextinst.offset) {
return llvm::make_error<llvm::StringError>(
"Loaded LDDW at pc=" +
std::to_string(pc) +
Expand Down Expand Up @@ -677,7 +678,9 @@
if (!vm.map_val) {
return llvm::make_error<
llvm::StringError>(
"map_val is not provided, unable to compile",
"map_val is not provided, unable to compile at pc " +
std::to_string(
pc),
llvm::inconvertibleErrorCode());
}
builder.CreateStore(
Expand All @@ -688,7 +691,6 @@
} else {
SPDLOG_DEBUG(
"map_val is required to be evaluated at runtime, emitting calling instructions");

if (auto itrMapVal = lddwHelper.find(
LDDW_HELPER_MAP_VAL);
itrMapVal != lddwHelper.end()) {
Expand All @@ -708,7 +710,9 @@
} else {
return llvm::make_error<
llvm::StringError>(
"Using lddw helper 2, which requires map_val to be defined.",
"Using lddw helper 2, which requires map_val to be defined at pc " +
std::to_string(

Check warning on line 714 in src/compiler.cpp

View check run for this annotation

Codecov / codecov/patch

src/compiler.cpp#L713-L714

Added lines #L713 - L714 were not covered by tests
pc),
llvm::inconvertibleErrorCode());
}
}
Expand All @@ -720,7 +724,8 @@
if (!vm.var_addr) {
return llvm::make_error<
llvm::StringError>(
"var_addr is not provided, unable to compile",
"var_addr is not provided, unable to compile at pc " +
std::to_string(pc),

Check warning on line 728 in src/compiler.cpp

View check run for this annotation

Codecov / codecov/patch

src/compiler.cpp#L727-L728

Added lines #L727 - L728 were not covered by tests
llvm::inconvertibleErrorCode());
}
builder.CreateStore(
Expand All @@ -733,7 +738,8 @@
if (!vm.code_addr) {
return llvm::make_error<
llvm::StringError>(
"code_addr is not provided, unable to compile",
"code_addr is not provided, unable to compile at pc " +
std::to_string(pc),

Check warning on line 742 in src/compiler.cpp

View check run for this annotation

Codecov / codecov/patch

src/compiler.cpp#L741-L742

Added lines #L741 - L742 were not covered by tests
llvm::inconvertibleErrorCode());
}
builder.CreateStore(
Expand Down Expand Up @@ -786,7 +792,9 @@
} else {
return llvm::make_error<
llvm::StringError>(
"map_val is not provided, unable to compile",
"map_val is not provided, unable to compile at pc " +
std::to_string(

Check warning on line 796 in src/compiler.cpp

View check run for this annotation

Codecov / codecov/patch

src/compiler.cpp#L795-L796

Added lines #L795 - L796 were not covered by tests
pc),
llvm::inconvertibleErrorCode());
}

Expand All @@ -812,7 +820,9 @@
} else {
return llvm::make_error<
llvm::StringError>(
"Using lddw helper 6, which requires map_val",
"Using lddw helper 6 at pc " +
std::to_string(

Check warning on line 824 in src/compiler.cpp

View check run for this annotation

Codecov / codecov/patch

src/compiler.cpp#L823-L824

Added lines #L823 - L824 were not covered by tests
pc),
llvm::inconvertibleErrorCode());
}
}
Expand Down Expand Up @@ -1056,7 +1066,8 @@
builder, &regs[0],
llvm::AtomicRMWInst::BinOp::Add, inst,
inst.opcode == EBPF_ATOMIC_OPCODE_64,
(inst.imm & EBPF_ATOMIC_OP_FETCH) == EBPF_ATOMIC_OP_FETCH);
(inst.imm & EBPF_ATOMIC_OP_FETCH) ==
EBPF_ATOMIC_OP_FETCH);
break;
}

Expand All @@ -1066,7 +1077,8 @@
builder, &regs[0],
llvm::AtomicRMWInst::BinOp::And, inst,
inst.opcode == EBPF_ATOMIC_OPCODE_64,
(inst.imm & EBPF_ATOMIC_OP_FETCH) == EBPF_ATOMIC_OP_FETCH);
(inst.imm & EBPF_ATOMIC_OP_FETCH) ==
EBPF_ATOMIC_OP_FETCH);
break;
}

Expand All @@ -1076,7 +1088,8 @@
builder, &regs[0],
llvm::AtomicRMWInst::BinOp::Or, inst,
inst.opcode == EBPF_ATOMIC_OPCODE_64,
(inst.imm & EBPF_ATOMIC_OP_FETCH) == EBPF_ATOMIC_OP_FETCH);
(inst.imm & EBPF_ATOMIC_OP_FETCH) ==
EBPF_ATOMIC_OP_FETCH);
break;
}
case EBPF_ATOMIC_XOR:
Expand All @@ -1085,7 +1098,8 @@
builder, &regs[0],
llvm::AtomicRMWInst::BinOp::Xor, inst,
inst.opcode == EBPF_ATOMIC_OPCODE_64,
(inst.imm & EBPF_ATOMIC_OP_FETCH) == EBPF_ATOMIC_OP_FETCH);
(inst.imm & EBPF_ATOMIC_OP_FETCH) ==
EBPF_ATOMIC_OP_FETCH);
break;
}
case EBPF_ATOMIC_OP_XCHG: {
Expand All @@ -1097,7 +1111,8 @@
break;
}
case EBPF_ATOMIC_OP_CMPXCHG: {
bool is64 = inst.opcode == EBPF_ATOMIC_OPCODE_64;
bool is64 =
inst.opcode == EBPF_ATOMIC_OPCODE_64;
auto vPtr = builder.CreateGEP(
builder.getInt8Ty(),
builder.CreateLoad(builder.getPtrTy(),
Expand Down Expand Up @@ -1138,7 +1153,8 @@
default:
return llvm::make_error<llvm::StringError>(
"Unsupported or illegal opcode: " +
std::to_string(inst.opcode),
std::to_string(inst.opcode) +
" at pc " + std::to_string(pc),
llvm::inconvertibleErrorCode());
}
}
Expand Down
Loading
Loading