162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci#include <stdio.h>
362306a36Sopenharmony_ci#include <fcntl.h>
462306a36Sopenharmony_ci#include <poll.h>
562306a36Sopenharmony_ci#include <time.h>
662306a36Sopenharmony_ci#include <signal.h>
762306a36Sopenharmony_ci#include <bpf/libbpf.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistatic __u64 time_get_ns(void)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	struct timespec ts;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	clock_gettime(CLOCK_MONOTONIC, &ts);
1462306a36Sopenharmony_ci	return ts.tv_sec * 1000000000ull + ts.tv_nsec;
1562306a36Sopenharmony_ci}
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic __u64 start_time;
1862306a36Sopenharmony_cistatic __u64 cnt;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define MAX_CNT 100000ll
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	struct {
2562306a36Sopenharmony_ci		__u64 pid;
2662306a36Sopenharmony_ci		__u64 cookie;
2762306a36Sopenharmony_ci	} *e = data;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	if (e->cookie != 0x12345678) {
3062306a36Sopenharmony_ci		printf("BUG pid %llx cookie %llx sized %d\n",
3162306a36Sopenharmony_ci		       e->pid, e->cookie, size);
3262306a36Sopenharmony_ci		return;
3362306a36Sopenharmony_ci	}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	cnt++;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	if (cnt == MAX_CNT) {
3862306a36Sopenharmony_ci		printf("recv %lld events per sec\n",
3962306a36Sopenharmony_ci		       MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
4062306a36Sopenharmony_ci		return;
4162306a36Sopenharmony_ci	}
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciint main(int argc, char **argv)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	struct bpf_link *link = NULL;
4762306a36Sopenharmony_ci	struct bpf_program *prog;
4862306a36Sopenharmony_ci	struct perf_buffer *pb;
4962306a36Sopenharmony_ci	struct bpf_object *obj;
5062306a36Sopenharmony_ci	int map_fd, ret = 0;
5162306a36Sopenharmony_ci	char filename[256];
5262306a36Sopenharmony_ci	FILE *f;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
5562306a36Sopenharmony_ci	obj = bpf_object__open_file(filename, NULL);
5662306a36Sopenharmony_ci	if (libbpf_get_error(obj)) {
5762306a36Sopenharmony_ci		fprintf(stderr, "ERROR: opening BPF object file failed\n");
5862306a36Sopenharmony_ci		return 0;
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	/* load BPF program */
6262306a36Sopenharmony_ci	if (bpf_object__load(obj)) {
6362306a36Sopenharmony_ci		fprintf(stderr, "ERROR: loading BPF object file failed\n");
6462306a36Sopenharmony_ci		goto cleanup;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
6862306a36Sopenharmony_ci	if (map_fd < 0) {
6962306a36Sopenharmony_ci		fprintf(stderr, "ERROR: finding a map in obj file failed\n");
7062306a36Sopenharmony_ci		goto cleanup;
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
7462306a36Sopenharmony_ci	if (libbpf_get_error(prog)) {
7562306a36Sopenharmony_ci		fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
7662306a36Sopenharmony_ci		goto cleanup;
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	link = bpf_program__attach(prog);
8062306a36Sopenharmony_ci	if (libbpf_get_error(link)) {
8162306a36Sopenharmony_ci		fprintf(stderr, "ERROR: bpf_program__attach failed\n");
8262306a36Sopenharmony_ci		link = NULL;
8362306a36Sopenharmony_ci		goto cleanup;
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	pb = perf_buffer__new(map_fd, 8, print_bpf_output, NULL, NULL, NULL);
8762306a36Sopenharmony_ci	ret = libbpf_get_error(pb);
8862306a36Sopenharmony_ci	if (ret) {
8962306a36Sopenharmony_ci		printf("failed to setup perf_buffer: %d\n", ret);
9062306a36Sopenharmony_ci		return 1;
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
9462306a36Sopenharmony_ci	(void) f;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	start_time = time_get_ns();
9762306a36Sopenharmony_ci	while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) {
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci	kill(0, SIGINT);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cicleanup:
10262306a36Sopenharmony_ci	bpf_link__destroy(link);
10362306a36Sopenharmony_ci	bpf_object__close(obj);
10462306a36Sopenharmony_ci	return ret;
10562306a36Sopenharmony_ci}
106