xref: /openbmc/linux/samples/bpf/lathist_user.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
125763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20fb1170eSDaniel Wagner /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
30fb1170eSDaniel Wagner  * Copyright (c) 2015 BMW Car IT GmbH
40fb1170eSDaniel Wagner  */
50fb1170eSDaniel Wagner #include <stdio.h>
60fb1170eSDaniel Wagner #include <unistd.h>
70fb1170eSDaniel Wagner #include <stdlib.h>
80fb1170eSDaniel Wagner #include <signal.h>
9*3677d0a1SDaniel T. Lee #include <bpf/libbpf.h>
102bf3e2efSJakub Kicinski #include <bpf/bpf.h>
110fb1170eSDaniel Wagner 
120fb1170eSDaniel Wagner #define MAX_ENTRIES	20
130fb1170eSDaniel Wagner #define MAX_CPU		4
140fb1170eSDaniel Wagner #define MAX_STARS	40
150fb1170eSDaniel Wagner 
160fb1170eSDaniel Wagner struct cpu_hist {
170fb1170eSDaniel Wagner 	long data[MAX_ENTRIES];
180fb1170eSDaniel Wagner 	long max;
190fb1170eSDaniel Wagner };
200fb1170eSDaniel Wagner 
210fb1170eSDaniel Wagner static struct cpu_hist cpu_hist[MAX_CPU];
220fb1170eSDaniel Wagner 
stars(char * str,long val,long max,int width)230fb1170eSDaniel Wagner static void stars(char *str, long val, long max, int width)
240fb1170eSDaniel Wagner {
250fb1170eSDaniel Wagner 	int i;
260fb1170eSDaniel Wagner 
270fb1170eSDaniel Wagner 	for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
280fb1170eSDaniel Wagner 		str[i] = '*';
290fb1170eSDaniel Wagner 	if (val > max)
300fb1170eSDaniel Wagner 		str[i - 1] = '+';
310fb1170eSDaniel Wagner 	str[i] = '\0';
320fb1170eSDaniel Wagner }
330fb1170eSDaniel Wagner 
print_hist(void)340fb1170eSDaniel Wagner static void print_hist(void)
350fb1170eSDaniel Wagner {
360fb1170eSDaniel Wagner 	char starstr[MAX_STARS];
370fb1170eSDaniel Wagner 	struct cpu_hist *hist;
380fb1170eSDaniel Wagner 	int i, j;
390fb1170eSDaniel Wagner 
400fb1170eSDaniel Wagner 	/* clear screen */
410fb1170eSDaniel Wagner 	printf("\033[2J");
420fb1170eSDaniel Wagner 
430fb1170eSDaniel Wagner 	for (j = 0; j < MAX_CPU; j++) {
440fb1170eSDaniel Wagner 		hist = &cpu_hist[j];
450fb1170eSDaniel Wagner 
460fb1170eSDaniel Wagner 		/* ignore CPUs without data (maybe offline?) */
470fb1170eSDaniel Wagner 		if (hist->max == 0)
480fb1170eSDaniel Wagner 			continue;
490fb1170eSDaniel Wagner 
500fb1170eSDaniel Wagner 		printf("CPU %d\n", j);
510fb1170eSDaniel Wagner 		printf("      latency        : count     distribution\n");
520fb1170eSDaniel Wagner 		for (i = 1; i <= MAX_ENTRIES; i++) {
530fb1170eSDaniel Wagner 			stars(starstr, hist->data[i - 1], hist->max, MAX_STARS);
540fb1170eSDaniel Wagner 			printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
550fb1170eSDaniel Wagner 				(1l << i) >> 1, (1l << i) - 1,
560fb1170eSDaniel Wagner 				hist->data[i - 1], MAX_STARS, starstr);
570fb1170eSDaniel Wagner 		}
580fb1170eSDaniel Wagner 	}
590fb1170eSDaniel Wagner }
600fb1170eSDaniel Wagner 
get_data(int fd)610fb1170eSDaniel Wagner static void get_data(int fd)
620fb1170eSDaniel Wagner {
630fb1170eSDaniel Wagner 	long key, value;
640fb1170eSDaniel Wagner 	int c, i;
650fb1170eSDaniel Wagner 
660fb1170eSDaniel Wagner 	for (i = 0; i < MAX_CPU; i++)
670fb1170eSDaniel Wagner 		cpu_hist[i].max = 0;
680fb1170eSDaniel Wagner 
690fb1170eSDaniel Wagner 	for (c = 0; c < MAX_CPU; c++) {
700fb1170eSDaniel Wagner 		for (i = 0; i < MAX_ENTRIES; i++) {
710fb1170eSDaniel Wagner 			key = c * MAX_ENTRIES + i;
72d40fc181SJoe Stringer 			bpf_map_lookup_elem(fd, &key, &value);
730fb1170eSDaniel Wagner 
740fb1170eSDaniel Wagner 			cpu_hist[c].data[i] = value;
750fb1170eSDaniel Wagner 			if (value > cpu_hist[c].max)
760fb1170eSDaniel Wagner 				cpu_hist[c].max = value;
770fb1170eSDaniel Wagner 		}
780fb1170eSDaniel Wagner 	}
790fb1170eSDaniel Wagner }
800fb1170eSDaniel Wagner 
main(int argc,char ** argv)810fb1170eSDaniel Wagner int main(int argc, char **argv)
820fb1170eSDaniel Wagner {
83*3677d0a1SDaniel T. Lee 	struct bpf_link *links[2];
84*3677d0a1SDaniel T. Lee 	struct bpf_program *prog;
85*3677d0a1SDaniel T. Lee 	struct bpf_object *obj;
860fb1170eSDaniel Wagner 	char filename[256];
87*3677d0a1SDaniel T. Lee 	int map_fd, i = 0;
880fb1170eSDaniel Wagner 
890fb1170eSDaniel Wagner 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
90*3677d0a1SDaniel T. Lee 	obj = bpf_object__open_file(filename, NULL);
91*3677d0a1SDaniel T. Lee 	if (libbpf_get_error(obj)) {
92*3677d0a1SDaniel T. Lee 		fprintf(stderr, "ERROR: opening BPF object file failed\n");
93*3677d0a1SDaniel T. Lee 		return 0;
94*3677d0a1SDaniel T. Lee 	}
950fb1170eSDaniel Wagner 
96*3677d0a1SDaniel T. Lee 	/* load BPF program */
97*3677d0a1SDaniel T. Lee 	if (bpf_object__load(obj)) {
98*3677d0a1SDaniel T. Lee 		fprintf(stderr, "ERROR: loading BPF object file failed\n");
99*3677d0a1SDaniel T. Lee 		goto cleanup;
100*3677d0a1SDaniel T. Lee 	}
101*3677d0a1SDaniel T. Lee 
102*3677d0a1SDaniel T. Lee 	map_fd = bpf_object__find_map_fd_by_name(obj, "my_lat");
103*3677d0a1SDaniel T. Lee 	if (map_fd < 0) {
104*3677d0a1SDaniel T. Lee 		fprintf(stderr, "ERROR: finding a map in obj file failed\n");
105*3677d0a1SDaniel T. Lee 		goto cleanup;
106*3677d0a1SDaniel T. Lee 	}
107*3677d0a1SDaniel T. Lee 
108*3677d0a1SDaniel T. Lee 	bpf_object__for_each_program(prog, obj) {
109*3677d0a1SDaniel T. Lee 		links[i] = bpf_program__attach(prog);
110*3677d0a1SDaniel T. Lee 		if (libbpf_get_error(links[i])) {
111*3677d0a1SDaniel T. Lee 			fprintf(stderr, "ERROR: bpf_program__attach failed\n");
112*3677d0a1SDaniel T. Lee 			links[i] = NULL;
113*3677d0a1SDaniel T. Lee 			goto cleanup;
114*3677d0a1SDaniel T. Lee 		}
115*3677d0a1SDaniel T. Lee 		i++;
1160fb1170eSDaniel Wagner 	}
1170fb1170eSDaniel Wagner 
1180fb1170eSDaniel Wagner 	while (1) {
119*3677d0a1SDaniel T. Lee 		get_data(map_fd);
1200fb1170eSDaniel Wagner 		print_hist();
1210fb1170eSDaniel Wagner 		sleep(5);
1220fb1170eSDaniel Wagner 	}
1230fb1170eSDaniel Wagner 
124*3677d0a1SDaniel T. Lee cleanup:
125*3677d0a1SDaniel T. Lee 	for (i--; i >= 0; i--)
126*3677d0a1SDaniel T. Lee 		bpf_link__destroy(links[i]);
127*3677d0a1SDaniel T. Lee 
128*3677d0a1SDaniel T. Lee 	bpf_object__close(obj);
1290fb1170eSDaniel Wagner 	return 0;
1300fb1170eSDaniel Wagner }
131