Skip to content
Closed
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
90 changes: 81 additions & 9 deletions gotests/cgo_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ struct netdata_ringbuf_stats {
uint64_t bytes;
};

struct netdata_socket_ringbuf_ctx {
struct netdata_ringbuf_stats *stats;
uint64_t handle;
};

extern void socketRingbufSample(uint64_t handle, void *data, size_t size);

#ifdef LIBBPF_MAJOR_VERSION
static int netdata_libbpf_probe_bpf_map_type(unsigned int map_type)
{
Expand All @@ -48,6 +55,11 @@ static int netdata_libbpf_num_possible_cpus(void)
return libbpf_num_possible_cpus();
}

static long netdata_sc_pagesize(void)
{
return sysconf(_SC_PAGESIZE);
}

static int netdata_open_capture_socket(int program_fd)
{
struct sockaddr_ll bind_addr = { 0 };
Expand Down Expand Up @@ -132,37 +144,75 @@ static int netdata_ring_buffer_sample_cb(void *ctx, void *data, size_t size)
return 0;
}

static struct netdata_ringbuf_stats *netdata_ringbuf_stats_new(void)
static int netdata_socket_ring_buffer_sample_cb(void *ctx, void *data, size_t size)
{
struct netdata_socket_ringbuf_ctx *socket_ctx = ctx;

if (socket_ctx) {
if (socket_ctx->stats) {
socket_ctx->stats->samples++;
socket_ctx->stats->bytes += size;
}
socketRingbufSample(socket_ctx->handle, data, size);
}

return 0;
}

struct netdata_ringbuf_stats *netdata_ringbuf_stats_new(void)
{
return calloc(1, sizeof(struct netdata_ringbuf_stats));
}

static void netdata_ringbuf_stats_free(struct netdata_ringbuf_stats *stats)
void netdata_ringbuf_stats_free(struct netdata_ringbuf_stats *stats)
{
free(stats);
}

static uint64_t netdata_ringbuf_stats_samples(const struct netdata_ringbuf_stats *stats)
uint64_t netdata_ringbuf_stats_samples(const struct netdata_ringbuf_stats *stats)
{
return stats ? stats->samples : 0;
}

static uint64_t netdata_ringbuf_stats_bytes(const struct netdata_ringbuf_stats *stats)
uint64_t netdata_ringbuf_stats_bytes(const struct netdata_ringbuf_stats *stats)
{
return stats ? stats->bytes : 0;
}

static struct ring_buffer *netdata_ring_buffer_new(int map_fd, struct netdata_ringbuf_stats *stats)
struct ring_buffer *netdata_ring_buffer_new(int map_fd, struct netdata_ringbuf_stats *stats)
{
return ring_buffer__new(map_fd, netdata_ring_buffer_sample_cb, stats, NULL);
}

static int netdata_ring_buffer_poll(struct ring_buffer *rb, int timeout_ms)
struct netdata_socket_ringbuf_ctx *netdata_socket_ringbuf_ctx_new(struct netdata_ringbuf_stats *stats, uint64_t handle)
{
struct netdata_socket_ringbuf_ctx *ctx = calloc(1, sizeof(*ctx));

if (!ctx)
return NULL;

ctx->stats = stats;
ctx->handle = handle;

return ctx;
}

void netdata_socket_ringbuf_ctx_free(struct netdata_socket_ringbuf_ctx *ctx)
{
free(ctx);
}

struct ring_buffer *netdata_socket_ring_buffer_new(int map_fd, struct netdata_socket_ringbuf_ctx *ctx)
{
return ring_buffer__new(map_fd, netdata_socket_ring_buffer_sample_cb, ctx, NULL);
}

int netdata_ring_buffer_poll(struct ring_buffer *rb, int timeout_ms)
{
return ring_buffer__poll(rb, timeout_ms);
}

static uint64_t netdata_ring_buffer_avail_data(const struct ring_buffer *rb)
uint64_t netdata_ring_buffer_avail_data(const struct ring_buffer *rb)
{
struct ring *ring = ring_buffer__ring((struct ring_buffer *)rb, 0);

Expand All @@ -172,7 +222,7 @@ static uint64_t netdata_ring_buffer_avail_data(const struct ring_buffer *rb)
return (uint64_t)ring__avail_data_size(ring);
}

static uint64_t netdata_ring_buffer_size(const struct ring_buffer *rb)
uint64_t netdata_ring_buffer_size(const struct ring_buffer *rb)
{
struct ring *ring = ring_buffer__ring((struct ring_buffer *)rb, 0);

Expand All @@ -182,7 +232,7 @@ static uint64_t netdata_ring_buffer_size(const struct ring_buffer *rb)
return (uint64_t)ring__size(ring);
}

static void netdata_ring_buffer_free(struct ring_buffer *rb)
void netdata_ring_buffer_free(struct ring_buffer *rb)
{
ring_buffer__free(rb);
}
Expand Down Expand Up @@ -229,6 +279,7 @@ const (
bpfMapTypePerCPUArray = uint32(C.BPF_MAP_TYPE_PERCPU_ARRAY)
bpfMapTypeRingBuf = uint32(C.BPF_MAP_TYPE_RINGBUF)
bpfMapTypeUserRingBuf = uint32(C.BPF_MAP_TYPE_USER_RINGBUF)
bpfMapTypeArena = uint32(C.BPF_MAP_TYPE_ARENA)
)

type bpfObject struct {
Expand Down Expand Up @@ -426,6 +477,27 @@ func (m *bpfMap) name() string {
return C.GoString(C.bpf_map__name(m.ptr))
}

// initialValue returns a pointer to the arena data section for BPF_MAP_TYPE_ARENA maps.
// libbpf places the data section at the END of the arena mmap:
// base + (total_sz - roundup(data_sz, PAGE_SIZE))
// The caller must NOT munmap this pointer; libbpf owns the mapping.
func (m *bpfMap) initialValue() unsafe.Pointer {
var size C.size_t
base := unsafe.Pointer(C.bpf_map__initial_value(m.ptr, &size))
if base == nil || size == 0 {
return nil
}

pageSize := uintptr(C.netdata_sc_pagesize())
totalSz := uintptr(C.bpf_map__max_entries(m.ptr)) * pageSize
dataSz := uintptr(size)
roundedDataSz := (dataSz + pageSize - 1) &^ (pageSize - 1)
if roundedDataSz > totalSz {
return nil
}
return unsafe.Add(base, totalSz-roundedDataSz)
}

func probeMapTypeSupport(mapType uint32) int {
return int(C.netdata_libbpf_probe_bpf_map_type(C.uint(mapType)))
}
Expand Down
28 changes: 21 additions & 7 deletions gotests/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ var (
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagMDFlush, name: "mdflush"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagMount, name: "mount"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "msync"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSocket, name: "socket", ctrlTable: "socket_ctrl"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagSocket, name: "socket", ctrlTable: "socket_ctrl"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagDNS, name: "dns"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagNFS, name: "nfs", ctrlTable: "nfs_ctrl"},
{kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagNetworkViewer, name: "network_viewer", ctrlTable: "nv_ctrl"},
Expand Down Expand Up @@ -483,8 +483,8 @@ func helpText(exe string) string {
"--content Test content stored inside hash tables.\n"+
"--iteration Number of iterations when content is read, default value is 1.\n"+
"--pid Specify the number that identifies PID that will be monitored: 0 - Real Parent PID (Default), 1 - Parent PID, 2 - All PID, and 3 - Ignore PID (ring buffer mode).\n"+
"--buffer Test ring buffer versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns).\n"+
"--arena Test arena versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns).\n\n"+
"--buffer Test ring buffer versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns, socket).\n"+
"--arena Test arena versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns, socket).\n\n"+
"You can also specify an unique eBPF program developed by Netdata with the following\n"+
"options:\n"+
"--btrfs Latency for btrfs.\n"+
Expand Down Expand Up @@ -839,6 +839,8 @@ func mapTypeName(mapType uint32) string {
return "ringbuf"
case bpfMapTypeUserRingBuf:
return "user_ringbuf"
case bpfMapTypeArena:
return "arena"
default:
return fmt.Sprintf("type_%d", mapType)
}
Expand Down Expand Up @@ -1025,6 +1027,7 @@ func moduleHasBuffer(name string) bool {
"swap": true,
"vfs": true,
"dns": true,
"socket": true,
}
return bufferModules[name]
}
Expand All @@ -1040,6 +1043,7 @@ func moduleHasArena(name string) bool {
"swap": true,
"vfs": true,
"dns": true,
"socket": true,
}
return arenaModules[name]
}
Expand Down Expand Up @@ -1223,10 +1227,14 @@ func ebpfTester(w io.Writer, filename string, names *[]specifyName, maps bool, c
}

if maps {
if ctrl != "" {
fillCtrl(obj, ctrl, opts.mapLevel, nprocesses)
if hasSocketTable(obj) {
runSocketTableTester(w, obj, opts.iterations)
} else {
if ctrl != "" {
fillCtrl(obj, ctrl, opts.mapLevel, nprocesses)
}
testMaps(w, obj, ctrl, opts.iterations, nprocesses)
}
testMaps(w, obj, ctrl, opts.iterations, nprocesses)
}

for _, link := range summary.links {
Expand Down Expand Up @@ -1338,7 +1346,7 @@ func isPerCPUMapType(mapType uint32) bool {
}

func isRingBufferMapType(mapType uint32) bool {
return mapType == bpfMapTypeRingBuf || mapType == bpfMapTypeUserRingBuf
return mapType == bpfMapTypeRingBuf || mapType == bpfMapTypeUserRingBuf || mapType == bpfMapTypeArena
}

func isUserRingBufferMapType(mapType uint32) bool {
Expand Down Expand Up @@ -1540,6 +1548,12 @@ func testMaps(w io.Writer, obj *bpfObject, ctrl string, iterations int, nprocess
tables := 0
for m := obj.firstMap(); m != nil; m = obj.nextMap(m) {
meta := m.meta()
if meta.Name == "socket_events" {
runSocketRingBufferTester(w, obj, iterations)
fmt.Fprint(w, " ]\n }\n },\n")
tables++
continue
}
if !supportsMapKeyValueIO(meta.Type) {
testRingBufferMap(w, meta, iterations)
fmt.Fprint(w, " ]\n }\n },\n")
Expand Down
Loading