18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/unistd.h>
38c2ecf20Sopenharmony_ci#include <linux/bpf.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <stdlib.h>
68c2ecf20Sopenharmony_ci#include <stdio.h>
78c2ecf20Sopenharmony_ci#include <unistd.h>
88c2ecf20Sopenharmony_ci#include <string.h>
98c2ecf20Sopenharmony_ci#include <errno.h>
108c2ecf20Sopenharmony_ci#include <arpa/inet.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <bpf/bpf.h>
138c2ecf20Sopenharmony_ci#include "bpf_util.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define MAX_INDEX 64
168c2ecf20Sopenharmony_ci#define MAX_STARS 38
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic void stars(char *str, long val, long max, int width)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	int i;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
238c2ecf20Sopenharmony_ci		str[i] = '*';
248c2ecf20Sopenharmony_ci	if (val > max)
258c2ecf20Sopenharmony_ci		str[i - 1] = '+';
268c2ecf20Sopenharmony_ci	str[i] = '\0';
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciint main(int argc, char **argv)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	unsigned int nr_cpus = bpf_num_possible_cpus();
328c2ecf20Sopenharmony_ci	const char *map_filename = "/sys/fs/bpf/tc/globals/lwt_len_hist_map";
338c2ecf20Sopenharmony_ci	uint64_t values[nr_cpus], sum, max_value = 0, data[MAX_INDEX] = {};
348c2ecf20Sopenharmony_ci	uint64_t key = 0, next_key, max_key = 0;
358c2ecf20Sopenharmony_ci	char starstr[MAX_STARS];
368c2ecf20Sopenharmony_ci	int i, map_fd;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	map_fd = bpf_obj_get(map_filename);
398c2ecf20Sopenharmony_ci	if (map_fd < 0) {
408c2ecf20Sopenharmony_ci		fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n",
418c2ecf20Sopenharmony_ci			map_filename, strerror(errno), errno);
428c2ecf20Sopenharmony_ci		return -1;
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
468c2ecf20Sopenharmony_ci		if (next_key >= MAX_INDEX) {
478c2ecf20Sopenharmony_ci			fprintf(stderr, "Key %lu out of bounds\n", next_key);
488c2ecf20Sopenharmony_ci			continue;
498c2ecf20Sopenharmony_ci		}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci		bpf_map_lookup_elem(map_fd, &next_key, values);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		sum = 0;
548c2ecf20Sopenharmony_ci		for (i = 0; i < nr_cpus; i++)
558c2ecf20Sopenharmony_ci			sum += values[i];
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci		data[next_key] = sum;
588c2ecf20Sopenharmony_ci		if (sum && next_key > max_key)
598c2ecf20Sopenharmony_ci			max_key = next_key;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci		if (sum > max_value)
628c2ecf20Sopenharmony_ci			max_value = sum;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		key = next_key;
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	for (i = 1; i <= max_key + 1; i++) {
688c2ecf20Sopenharmony_ci		stars(starstr, data[i - 1], max_value, MAX_STARS);
698c2ecf20Sopenharmony_ci		printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
708c2ecf20Sopenharmony_ci		       (1l << i) >> 1, (1l << i) - 1, data[i - 1],
718c2ecf20Sopenharmony_ci		       MAX_STARS, starstr);
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	close(map_fd);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	return 0;
778c2ecf20Sopenharmony_ci}
78