Skip to content

Commit 401718a

Browse files
authored
runtime: add network related helpers and maps (#297)
* add bpf_get_smp_processor_id * add xdp related functions * add helpers and map in maps
1 parent 6c60ff1 commit 401718a

File tree

4 files changed

+203
-5
lines changed

4 files changed

+203
-5
lines changed

runtime/extension/userspace_xdp.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef BPFTIME_EXTENSION_USERSPACE_XDP_HPP
2+
#define BPFTIME_EXTENSION_USERSPACE_XDP_HPP
3+
4+
#include <cstdint>
5+
6+
struct xdp_md_userspace
7+
{
8+
uint64_t data;
9+
uint64_t data_end;
10+
uint32_t data_meta;
11+
uint32_t ingress_ifindex;
12+
uint32_t rx_queue_index;
13+
uint32_t egress_ifindex;
14+
// additional fields
15+
uint64_t buffer_start; // record the start of the available buffer
16+
uint64_t buffer_end; // record the end of the available buffer
17+
};
18+
19+
#endif // BPFTIME_EXTENSION_USERSPACE_XDP_HPP

runtime/src/bpf_helper.cpp

Lines changed: 120 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "bpftime.hpp"
2424
#include "bpftime_shm.hpp"
2525
#include "bpftime_internal.h"
26+
#include "extension/userspace_xdp.h"
2627
#include <spdlog/spdlog.h>
2728
#include <vector>
2829
#include <bpftime_shm_internal.hpp>
@@ -104,17 +105,17 @@ uint64_t bpf_get_current_uid_gid(uint64_t, uint64_t, uint64_t, uint64_t,
104105

105106
uint64_t bpftime_ktime_get_ns(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
106107
{
107-
auto now = std::chrono::steady_clock::now();
108-
auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
109-
return ns.time_since_epoch().count();
108+
auto now = std::chrono::steady_clock::now();
109+
auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
110+
return ns.time_since_epoch().count();
110111
}
111112

112113
uint64_t bpftime_get_current_comm(uint64_t buf, uint64_t size, uint64_t,
113114
uint64_t, uint64_t)
114115
{
115116
static std::string filename_buf;
116117

117-
if (filename_buf.empty()) {
118+
if (unlikely(filename_buf.empty())) {
118119
char strbuf[PATH_MAX];
119120

120121
auto len = readlink("/proc/self/exe", strbuf,
@@ -219,6 +220,7 @@ uint64_t bpf_ringbuf_submit(uint64_t data, uint64_t flags, uint64_t, uint64_t,
219220
bpftime_ringbuf_submit(fd, (void *)(uintptr_t)data, false);
220221
return 0;
221222
}
223+
222224
uint64_t bpf_ringbuf_discard(uint64_t data, uint64_t flags, uint64_t, uint64_t,
223225
uint64_t)
224226
{
@@ -328,6 +330,7 @@ uint64_t bpftime_tail_call(uint64_t ctx, uint64_t prog_array, uint64_t index)
328330
close(to_call_fd);
329331
return run_opts.retval;
330332
}
333+
331334
uint64_t bpftime_get_attach_cookie(uint64_t ctx, uint64_t, uint64_t, uint64_t,
332335
uint64_t)
333336
{
@@ -340,6 +343,95 @@ uint64_t bpftime_get_attach_cookie(uint64_t ctx, uint64_t, uint64_t, uint64_t,
340343
return 0;
341344
}
342345
}
346+
347+
uint64_t bpftime_get_smp_processor_id()
348+
{
349+
int cpu = sched_getcpu();
350+
if (cpu == -1) {
351+
SPDLOG_ERROR("sched_getcpu error");
352+
return 0; // unlikely
353+
}
354+
return (uint64_t)cpu;
355+
}
356+
357+
// From https://github.com/microsoft/ebpf-for-windows
358+
int64_t bpftime_csum_diff(const void *from, int from_size, const void *to,
359+
int to_size, int seed)
360+
{
361+
int csum_diff = -EINVAL;
362+
363+
if ((from_size % 4 != 0) || (to_size % 4 != 0)) {
364+
// size of buffers should be a multiple of 4.
365+
goto Exit;
366+
}
367+
368+
csum_diff = seed;
369+
if (to != NULL) {
370+
for (int i = 0; i < to_size / 2; i++) {
371+
csum_diff += (uint16_t)(*((uint16_t *)to + i));
372+
}
373+
}
374+
if (from != NULL) {
375+
for (int i = 0; i < from_size / 2; i++) {
376+
csum_diff += (uint16_t)(~*((uint16_t *)from + i));
377+
}
378+
}
379+
380+
// Adding 16-bit unsigned integers or their one's complement will
381+
// produce a positive 32-bit integer, unless the length of the buffers
382+
// is so long, that the signed 32 bit output overflows and produces a
383+
// negative result.
384+
if (csum_diff < 0) {
385+
csum_diff = -EINVAL;
386+
}
387+
Exit:
388+
return csum_diff;
389+
}
390+
391+
#define ETH_HLEN 14 /* Total octets in header. */
392+
393+
long bpftime_xdp_adjust_head(struct xdp_md_userspace *xdp, int offset)
394+
{
395+
// We don't use xdp meta data
396+
uint64_t data = xdp->data + offset;
397+
if (unlikely(data > xdp->data_end - ETH_HLEN) || data > xdp->buffer_end)
398+
return -EINVAL;
399+
if (data < xdp->buffer_start) {
400+
// move the data so the buffer can place the new header
401+
memmove(reinterpret_cast<void *>(xdp->buffer_start +
402+
(xdp->buffer_start - data)),
403+
reinterpret_cast<void *>(xdp->data),
404+
xdp->data_end - xdp->data);
405+
data = xdp->buffer_start;
406+
}
407+
xdp->data = data;
408+
return 0;
409+
}
410+
411+
long bpftime_xdp_adjust_tail(struct xdp_md_userspace *xdp_md, int delta)
412+
{
413+
// We don't use xdp meta data
414+
uint64_t data = xdp_md->data_end + delta;
415+
if (data < xdp_md->data || data < xdp_md->buffer_start ||
416+
data > xdp_md->buffer_end) {
417+
return -EINVAL;
418+
}
419+
xdp_md->data_end = data;
420+
return 0;
421+
}
422+
423+
long bpftime_xdp_load_bytes(struct xdp_md_userspace *xdp_md, __u32 offset,
424+
void *buf, __u32 len)
425+
{
426+
// We don't support fragmented packets
427+
uint64_t data = xdp_md->data + offset;
428+
if (data + len > xdp_md->data_end) {
429+
return -EINVAL;
430+
}
431+
memcpy(buf, reinterpret_cast<void *>(data), len);
432+
return 0;
433+
}
434+
343435
} // extern "C"
344436

345437
namespace bpftime
@@ -643,6 +735,30 @@ const bpftime_helper_group kernel_helper_group = {
643735
.name = "bpf_probe_read",
644736
.fn = (void *)bpftime_probe_read,
645737
} },
738+
{ BPF_FUNC_get_smp_processor_id,
739+
bpftime_helper_info{
740+
.index = BPF_FUNC_get_smp_processor_id,
741+
.name = "bpf_get_smp_processor_id",
742+
.fn = (void *)bpftime_get_smp_processor_id,
743+
} },
744+
{ BPF_FUNC_csum_diff,
745+
bpftime_helper_info{
746+
.index = BPF_FUNC_csum_diff,
747+
.name = "bpf_csum_diff",
748+
.fn = (void *)bpftime_csum_diff,
749+
} },
750+
{ BPF_FUNC_xdp_adjust_head,
751+
bpftime_helper_info{
752+
.index = BPF_FUNC_xdp_adjust_head,
753+
.name = "bpf_xdp_adjust_head",
754+
.fn = (void *)bpftime_xdp_adjust_head,
755+
} },
756+
{ BPF_FUNC_xdp_adjust_tail,
757+
bpftime_helper_info{
758+
.index = BPF_FUNC_xdp_adjust_tail,
759+
.name = "bpf_xdp_adjust_tail",
760+
.fn = (void *)bpftime_xdp_adjust_tail,
761+
} },
646762
{ BPF_FUNC_probe_read_kernel,
647763
bpftime_helper_info{
648764
.index = BPF_FUNC_probe_read_kernel,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* SPDX-License-Identifier: MIT
2+
*
3+
* Copyright (c) 2022, eunomia-bpf org
4+
* All rights reserved.
5+
*/
6+
#ifndef _MAP_IN_MAP_HPP
7+
#define _MAP_IN_MAP_HPP
8+
9+
#include <bpf_map/map_common_def.hpp>
10+
#include "array_map.hpp"
11+
12+
namespace bpftime
13+
{
14+
15+
// implementation of array map
16+
class array_map_of_maps_impl : public array_map_impl {
17+
public:
18+
array_map_of_maps_impl(boost::interprocess::managed_shared_memory &memory, uint32_t max_entries) : array_map_impl(memory, sizeof(int), max_entries){
19+
}
20+
// TODO: add verify the correctness of the key
21+
void *elem_lookup(const void *key) {
22+
auto key_val = array_map_impl::elem_lookup(key);
23+
int map_id = *(int *)key_val;
24+
return (void*)((u_int64_t)map_id << 32);
25+
}
26+
};
27+
28+
} // namespace bpftime
29+
30+
#endif // _MAP_IN_MAP_HPP

runtime/src/handler/map_handler.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <bpf_map/shared/percpu_array_map_kernel_user.hpp>
1717
#include <bpf_map/shared/perf_event_array_kernel_user.hpp>
1818
#include <bpf_map/userspace/prog_array.hpp>
19+
#include <bpf_map/userspace/map_in_maps.hpp>
1920
#include <unistd.h>
2021

2122
using boost::interprocess::interprocess_sharable_mutex;
@@ -134,6 +135,11 @@ const void *bpf_map_handler::map_lookup_elem(const void *key,
134135
static_cast<prog_array_map_impl *>(map_impl_ptr.get());
135136
return do_lookup(impl);
136137
}
138+
case bpf_map_type::BPF_MAP_TYPE_ARRAY_OF_MAPS: {
139+
auto impl = static_cast<array_map_of_maps_impl *>(
140+
map_impl_ptr.get());
141+
return do_lookup(impl);
142+
}
137143
default:
138144
auto func_ptr = global_map_ops_table[(int)type].elem_lookup;
139145
if (func_ptr) {
@@ -221,6 +227,15 @@ long bpf_map_handler::map_update_elem(const void *key, const void *value,
221227
static_cast<prog_array_map_impl *>(map_impl_ptr.get());
222228
return do_update(impl);
223229
}
230+
case bpf_map_type::BPF_MAP_TYPE_ARRAY_OF_MAPS: {
231+
if (!from_syscall) {
232+
// Map in maps only support update from syscall
233+
return -EINVAL;
234+
}
235+
auto impl = static_cast<array_map_of_maps_impl *>(
236+
map_impl_ptr.get());
237+
return do_update(impl);
238+
}
224239
default:
225240
auto func_ptr = global_map_ops_table[(int)type].elem_update;
226241
if (func_ptr) {
@@ -297,6 +312,11 @@ int bpf_map_handler::bpf_map_get_next_key(const void *key, void *next_key,
297312
static_cast<prog_array_map_impl *>(map_impl_ptr.get());
298313
return do_get_next_key(impl);
299314
}
315+
case bpf_map_type::BPF_MAP_TYPE_ARRAY_OF_MAPS: {
316+
auto impl = static_cast<array_map_of_maps_impl *>(
317+
map_impl_ptr.get());
318+
return do_get_next_key(impl);
319+
}
300320
default:
301321
auto func_ptr =
302322
global_map_ops_table[(int)type].map_get_next_key;
@@ -384,6 +404,15 @@ long bpf_map_handler::map_delete_elem(const void *key, bool from_syscall) const
384404
static_cast<prog_array_map_impl *>(map_impl_ptr.get());
385405
return do_delete(impl);
386406
}
407+
case bpf_map_type::BPF_MAP_TYPE_ARRAY_OF_MAPS: {
408+
if (!from_syscall) {
409+
// Map in maps only support update from syscall
410+
return -EINVAL;
411+
}
412+
auto impl = static_cast<array_map_of_maps_impl *>(
413+
map_impl_ptr.get());
414+
return do_delete(impl);
415+
}
387416
default:
388417
auto func_ptr = global_map_ops_table[(int)type].elem_delete;
389418
if (func_ptr) {
@@ -476,7 +505,11 @@ int bpf_map_handler::map_init(managed_shared_memory &memory)
476505
max_entries);
477506
return 0;
478507
}
479-
508+
case bpf_map_type::BPF_MAP_TYPE_ARRAY_OF_MAPS: {
509+
map_impl_ptr = memory.construct<array_map_of_maps_impl>(
510+
container_name.c_str())(memory, max_entries);
511+
return 0;
512+
}
480513
default:
481514
if (bpftime_get_agent_config().allow_non_buildin_map_types) {
482515
SPDLOG_INFO("non-builtin map type: {}", (int)type);

0 commit comments

Comments
 (0)