forked from Minki/linux
2bf3e2ef42
There are two files in the tree called libbpf.h which is becoming problematic. Most samples don't actually need the local libbpf.h they simply include it to get to bpf/bpf.h. Include bpf/bpf.h directly instead. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Acked-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
107 lines
2.2 KiB
C
107 lines
2.2 KiB
C
/* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
* License as published by the Free Software Foundation.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <poll.h>
|
|
#include <linux/perf_event.h>
|
|
#include <linux/bpf.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mman.h>
|
|
#include <time.h>
|
|
#include <signal.h>
|
|
#include <libbpf.h>
|
|
#include "bpf_load.h"
|
|
#include "perf-sys.h"
|
|
#include "trace_helpers.h"
|
|
|
|
static int pmu_fd;
|
|
|
|
static __u64 time_get_ns(void)
|
|
{
|
|
struct timespec ts;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
return ts.tv_sec * 1000000000ull + ts.tv_nsec;
|
|
}
|
|
|
|
static __u64 start_time;
|
|
|
|
#define MAX_CNT 100000ll
|
|
|
|
static int print_bpf_output(void *data, int size)
|
|
{
|
|
static __u64 cnt;
|
|
struct {
|
|
__u64 pid;
|
|
__u64 cookie;
|
|
} *e = data;
|
|
|
|
if (e->cookie != 0x12345678) {
|
|
printf("BUG pid %llx cookie %llx sized %d\n",
|
|
e->pid, e->cookie, size);
|
|
return LIBBPF_PERF_EVENT_ERROR;
|
|
}
|
|
|
|
cnt++;
|
|
|
|
if (cnt == MAX_CNT) {
|
|
printf("recv %lld events per sec\n",
|
|
MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
|
|
return LIBBPF_PERF_EVENT_DONE;
|
|
}
|
|
|
|
return LIBBPF_PERF_EVENT_CONT;
|
|
}
|
|
|
|
static void test_bpf_perf_event(void)
|
|
{
|
|
struct perf_event_attr attr = {
|
|
.sample_type = PERF_SAMPLE_RAW,
|
|
.type = PERF_TYPE_SOFTWARE,
|
|
.config = PERF_COUNT_SW_BPF_OUTPUT,
|
|
};
|
|
int key = 0;
|
|
|
|
pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
|
|
|
|
assert(pmu_fd >= 0);
|
|
assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
|
|
ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
char filename[256];
|
|
FILE *f;
|
|
int ret;
|
|
|
|
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
|
|
|
if (load_bpf_file(filename)) {
|
|
printf("%s", bpf_log_buf);
|
|
return 1;
|
|
}
|
|
|
|
test_bpf_perf_event();
|
|
|
|
if (perf_event_mmap(pmu_fd) < 0)
|
|
return 1;
|
|
|
|
f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
|
|
(void) f;
|
|
|
|
start_time = time_get_ns();
|
|
ret = perf_event_poller(pmu_fd, print_bpf_output);
|
|
kill(0, SIGINT);
|
|
return ret;
|
|
}
|