lcc/glcc/lib/ebpf/ebpf_tracepoint.c (271 lines of code) (raw):
#include "ebpf_tracepoint.h"
#include <linux/tracepoint.h>
#include <linux/ftrace_event.h>
#include <linux/string.h>
#include "allsyms.h"
#include <linux/skbuff.h>
static __always_inline void __bpf_tracepoint_run(struct bpf_prog *prog, u64 *args)
{
rcu_read_lock();
preempt_disable();
(void)BPF_PROG_RUN(prog, args);
preempt_enable();
rcu_read_unlock();
}
static int ebpf_net_dev_xmit(void *data, void *skbaddr, int rc, void *dev, int len)
{
// trace_net_dev_xmit(skb, rc, dev, len);
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
void *skbaddr;
unsigned int len;
int rc;
u32 __data_loc_name;
char __data[0];
} arg = {
.skbaddr = skbaddr,
.rc = rc,
.len = len,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_netif_receive_skb(void *data, struct sk_buff *skb)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
struct sk_buff *skb;
unsigned int len;
} arg = {
.skb = skb,
.len = skb->len,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_sched_wakeup(void *data, struct task_struct *p, int success)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
char comm[TASK_COMM_LEN];
pid_t pid;
int prio;
int success;
int target_cpu;
} arg = {
.pid = p->pid,
.prio = p->prio,
.success = success,
.target_cpu = task_cpu(p),
};
memcpy(arg.comm, p->comm, TASK_COMM_LEN);
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_sched_wakeup_new(void *data, struct task_struct *p, int success)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
char comm[TASK_COMM_LEN];
pid_t pid;
int prio;
int success;
int target_cpu;
} arg = {
.pid = p->pid,
.prio = p->prio,
.success = success,
.target_cpu = task_cpu(p),
};
memcpy(arg.comm, p->comm, TASK_COMM_LEN);
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_sched_switch(void *data, struct task_struct *prev, struct task_struct *next)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
char prev_comm[TASK_COMM_LEN];
pid_t prev_pid;
int prev_prio;
long prev_state;
char next_comm[TASK_COMM_LEN];
pid_t next_pid;
int next_prio;
} arg = {
.prev_pid = prev->pid,
.prev_prio = prev->prio,
.prev_state = prev->state,
.next_pid = next->pid,
.next_prio = next->prio,
};
memcpy(arg.prev_comm, prev->comm, TASK_COMM_LEN);
memcpy(arg.next_comm, next->comm, TASK_COMM_LEN);
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_softirq_raise(void *data, unsigned int vec_nr)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
unsigned int vec;
} arg = {
.vec = vec_nr,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_net_dev_queue(void *data, struct sk_buff *skb)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args
{
struct trace_entry entry;
struct sk_buff *skb;
unsigned int len;
} arg = {
.skb = skb,
.len = skb->len,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_sched_stat_template(void *data, struct task_struct *tsk, u64 delay)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
struct trace_entry entry;
char comm[TASK_COMM_LEN];
pid_t pid;
u64 delay;
} arg = {
.pid = tsk->pid,
.delay = delay,
};
memcpy(arg.comm, tsk->comm, TASK_COMM_LEN);
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_workqueue_execute_start(void *data, struct work_struct *work)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
void *work;
void *function;
} arg = {
.work = work,
.function = work->func,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_workqueue_work_template(void *data, struct work_struct *work)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
void *work;
} arg = {
.work = work,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_mm_vmscan_direct_reclaim_begin_template(void *data, int order, int may_writepage, gfp_t gfp_flags)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
int order;
gfp_t gfp_flags;
} arg = {
.order = order,
.gfp_flags = gfp_flags,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_mm_vmscan_direct_reclaim_end_template(void *data, unsigned long nr_reclaimed)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
unsigned long nr_reclaimed;
} arg = {
.nr_reclaimed = nr_reclaimed,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_mm_vmscan_memcg_reclaim_begin_template(void *data, int order, int may_writepage, gfp_t gfp_flags)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
int order;
gfp_t gfp_flags;
} arg = {
.order = order,
.gfp_flags = gfp_flags,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static int ebpf_mm_vmscan_memcg_reclaim_end_template(void *data, unsigned long nr_reclaimed)
{
struct bpf_prog *prog = (struct bpf_prog *)data;
struct args {
unsigned long nr_reclaimed;
} arg = {
.nr_reclaimed = nr_reclaimed,
};
__bpf_tracepoint_run(prog, (u64 *)&arg);
return 0;
}
static struct bpf_tracepoint_event events_table[] =
{
{.name = "net_dev_queue", .bpf_func = ebpf_net_dev_queue},
{.name = "softirq_raise", .bpf_func = ebpf_softirq_raise},
{.name = "sched_wakeup", .bpf_func = ebpf_sched_wakeup},
{.name = "sched_wakeup_new", .bpf_func = ebpf_sched_wakeup_new},
{.name = "sched_switch", .bpf_func = ebpf_sched_switch},
{.name = "netif_receive_skb", .bpf_func = ebpf_netif_receive_skb},
{.name = "net_dev_xmit", .bpf_func = ebpf_net_dev_xmit},
{.name = "sched_stat_wait", .bpf_func = ebpf_sched_stat_template},
{.name = "sched_stat_iowait", .bpf_func = ebpf_sched_stat_template},
{.name = "sched_stat_blocked", .bpf_func = ebpf_sched_stat_template},
{.name = "workqueue_execute_start", .bpf_func = ebpf_workqueue_execute_start},
{.name = "workqueue_execute_end", .bpf_func = ebpf_workqueue_work_template},
{.name = "workqueue_activate_work", .bpf_func = ebpf_workqueue_work_template},
{.name = "mm_vmscan_direct_reclaim_begin", .bpf_func = ebpf_mm_vmscan_direct_reclaim_begin_template},
{.name = "mm_vmscan_direct_reclaim_end", .bpf_func = ebpf_mm_vmscan_direct_reclaim_end_template},
{.name = "mm_vmscan_memcg_reclaim_begin", .bpf_func = ebpf_mm_vmscan_memcg_reclaim_begin_template},
{.name = "mm_vmscan_memcg_reclaim_end", .bpf_func = ebpf_mm_vmscan_memcg_reclaim_end_template},
};
struct bpf_tracepoint_event *bpf_find_tracepoint(char *tp_name)
{
int i;
for (i = 0; i < sizeof(events_table) / sizeof(struct bpf_tracepoint_event); i++)
{
if (strcmp(events_table[i].name, tp_name) == 0)
{
return &events_table[i];
}
}
return NULL;
}
int bpf_tracepoint_register(struct bpf_tracepoint_event *bte, struct bpf_prog *prog)
{
return tracepoint_probe_register(bte->name, bte->bpf_func, prog);
}
void bpf_tracepoint_unregister(struct bpf_tracepoint_event *bte, struct bpf_prog *prog)
{
tracepoint_probe_unregister(bte->name, bte->bpf_func, prog);
}