Skip to content

Commit

Permalink
Shared memory syscall success/error tracking (#258)
Browse files Browse the repository at this point in the history
  • Loading branch information
UmanShahzad authored Sep 23, 2021
1 parent 7bf3150 commit 4b638e3
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 0 deletions.
1 change: 1 addition & 0 deletions includes/netdata_ebpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This header has the common definitions for all `.c` files.
#include "netdata_mount.h"
#include "netdata_oomkill.h"
#include "netdata_process.h"
#include "netdata_shm.h"
#include "netdata_socket.h"
#include "netdata_softirq.h"
#include "netdata_sync.h"
Expand Down
23 changes: 23 additions & 0 deletions includes/netdata_shm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef _NETDATA_SHM_H_
#define _NETDATA_SHM_H_ 1

typedef struct netdata_shm {
__u64 get;
__u64 at;
__u64 dt;
__u64 ctl;
} netdata_shm_t;

enum shm_counters {
NETDATA_KEY_SHMGET_CALL,
NETDATA_KEY_SHMAT_CALL,
NETDATA_KEY_SHMDT_CALL,
NETDATA_KEY_SHMCTL_CALL,

// Keep this as last and don't skip numbers as it is used as element counter
NETDATA_SHM_END
};

#endif /* _NETDATA_SHM_H_ */
1 change: 1 addition & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ NETDATA_APPS= btrfs \
nfs \
oomkill \
process \
shm \
socket \
softirq \
sync \
Expand Down
1 change: 1 addition & 0 deletions kernel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Right now we have the following `eBPF` program collectors:
- `nfs_kern.c` : provides nfs monitoring.
- `oomkill_kern.c` : provides info on which processes got OOM killed.
- `process_kern.c` : provides process, file and VFS stats.
- `shm_kern.c` : monitor calls for syscalls `shmget`, `shmat`, `shmdt` and `shmctl`.
- `socket_kern.c` : provides network stats;
- `softirq_kern.c` : provides software interrupt (soft IRQ) latency monitoring.
- `swap_kern.c` : provides swap stats;
Expand Down
178 changes: 178 additions & 0 deletions kernel/shm_kern.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#define KBUILD_MODNAME "shm_netdata"
#include <linux/bpf.h>

#include <linux/threads.h>

#if (LINUX_VERSION_CODE > KERNEL_VERSION(5,4,14))
#include "bpf_helpers.h"
#include "bpf_tracing.h"
#else
#include "netdata_bpf_helpers.h"
#endif
#include "netdata_ebpf.h"

#if (LINUX_VERSION_CODE > KERNEL_VERSION(5,4,14))
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, __u32);
__type(value, __u64);
__uint(max_entries, NETDATA_SHM_END);
} tbl_shm SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
__type(key, __u32);
__type(value, netdata_shm_t);
__uint(max_entries, PID_MAX_DEFAULT);
} tbl_pid_shm SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32);
__type(value, __u32);
__uint(max_entries, NETDATA_CONTROLLER_END);
} shm_ctrl SEC(".maps");
#else
struct bpf_map_def SEC("maps") tbl_shm = {
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
.key_size = sizeof(__u32),
.value_size = sizeof(__u64),
.max_entries = NETDATA_SHM_END
};

struct bpf_map_def SEC("maps") tbl_pid_shm = {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
.type = BPF_MAP_TYPE_HASH,
#else
.type = BPF_MAP_TYPE_PERCPU_HASH,
#endif
.key_size = sizeof(__u32),
.value_size = sizeof(netdata_shm_t),
.max_entries = PID_MAX_DEFAULT
};

struct bpf_map_def SEC("maps") shm_ctrl = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(__u32),
.value_size = sizeof(__u32),
.max_entries = NETDATA_CONTROLLER_END
};
#endif

SEC("kprobe/" NETDATA_SYSCALL(shmget))
int netdata_syscall_shmget(struct pt_regs *ctx)
{
netdata_shm_t data = {};

libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMGET_CALL, 1);

// check if apps is enabled; if not, don't record apps data.
__u32 key = NETDATA_CONTROLLER_APPS_ENABLED;
__u32 *apps = bpf_map_lookup_elem(&shm_ctrl, &key);
if (apps) {
if (*apps == 0) {
return 0;
}
}

__u64 pid_tgid = bpf_get_current_pid_tgid();
key = (__u32)(pid_tgid >> 32);
netdata_shm_t *fill = bpf_map_lookup_elem(&tbl_pid_shm, &key);
if (fill) {
libnetdata_update_u64(&fill->get, 1);
} else {
data.get = 1;
bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY);
}

return 0;
}

SEC("kprobe/" NETDATA_SYSCALL(shmat))
int netdata_syscall_shmat(struct pt_regs *ctx)
{
netdata_shm_t data = {};

libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMAT_CALL, 1);

// check if apps is enabled; if not, don't record apps data.
__u32 key = NETDATA_CONTROLLER_APPS_ENABLED;
__u32 *apps = bpf_map_lookup_elem(&shm_ctrl, &key);
if (apps) {
if (*apps == 0) {
return 0;
}
}

__u64 pid_tgid = bpf_get_current_pid_tgid();
key = (__u32)(pid_tgid >> 32);
netdata_shm_t *fill = bpf_map_lookup_elem(&tbl_pid_shm, &key);
if (fill) {
libnetdata_update_u64(&fill->at, 1);
} else {
data.at = 1;
bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY);
}

return 0;
}

SEC("kprobe/" NETDATA_SYSCALL(shmdt))
int netdata_syscall_shmdt(struct pt_regs *ctx)
{
netdata_shm_t data = {};

libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMDT_CALL, 1);

// check if apps is enabled; if not, don't record apps data.
__u32 key = NETDATA_CONTROLLER_APPS_ENABLED;
__u32 *apps = bpf_map_lookup_elem(&shm_ctrl, &key);
if (apps) {
if (*apps == 0) {
return 0;
}
}

__u64 pid_tgid = bpf_get_current_pid_tgid();
key = (__u32)(pid_tgid >> 32);
netdata_shm_t *fill = bpf_map_lookup_elem(&tbl_pid_shm, &key);
if (fill) {
libnetdata_update_u64(&fill->dt, 1);
} else {
data.dt = 1;
bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY);
}

return 0;
}

SEC("kprobe/" NETDATA_SYSCALL(shmctl))
int netdata_syscall_shmctl(struct pt_regs *ctx)
{
netdata_shm_t data = {};

libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMCTL_CALL, 1);

// check if apps is enabled; if not, don't record apps data.
__u32 key = NETDATA_CONTROLLER_APPS_ENABLED;
__u32 *apps = bpf_map_lookup_elem(&shm_ctrl, &key);
if (apps) {
if (*apps == 0) {
return 0;
}
}

__u64 pid_tgid = bpf_get_current_pid_tgid();
key = (__u32)(pid_tgid >> 32);
netdata_shm_t *fill = bpf_map_lookup_elem(&tbl_pid_shm, &key);
if (fill) {
libnetdata_update_u64(&fill->ctl, 1);
} else {
data.ctl = 1;
bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY);
}

return 0;
}

char _license[] SEC("license") = "GPL";

0 comments on commit 4b638e3

Please sign in to comment.