brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · 332f281 Raw
150 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3 4#include <stdio.h>5#include <string.h>6 7#include <ynl.h>8 9#include <net/if.h>10 11#include "netdev-user.h"12 13struct stat {14	unsigned int ifc;15 16	struct {17		unsigned int cnt;18		size_t refs, bytes;19	} live[2];20 21	size_t alloc_slow, alloc_fast, recycle_ring, recycle_cache;22};23 24struct stats_array {25	unsigned int i, max;26	struct stat *s;27};28 29static struct stat *find_ifc(struct stats_array *a, unsigned int ifindex)30{31	unsigned int i;32 33	for (i = 0; i < a->i; i++) {34		if (a->s[i].ifc == ifindex)35			return &a->s[i];36	}37 38	a->i++;39	if (a->i == a->max) {40		a->max *= 2;41		a->s = reallocarray(a->s, a->max, sizeof(*a->s));42	}43	a->s[i].ifc = ifindex;44	return &a->s[i];45}46 47static void count(struct stat *s, unsigned int l,48		  struct netdev_page_pool_get_rsp *pp)49{50	s->live[l].cnt++;51	if (pp->_present.inflight)52		s->live[l].refs += pp->inflight;53	if (pp->_present.inflight_mem)54		s->live[l].bytes += pp->inflight_mem;55}56 57int main(int argc, char **argv)58{59	struct netdev_page_pool_stats_get_list *pp_stats;60	struct netdev_page_pool_get_list *pools;61	struct stats_array a = {};62	struct ynl_error yerr;63	struct ynl_sock *ys;64 65	ys = ynl_sock_create(&ynl_netdev_family, &yerr);66	if (!ys) {67		fprintf(stderr, "YNL: %s\n", yerr.msg);68		return 1;69	}70 71	a.max = 128;72	a.s = calloc(a.max, sizeof(*a.s));73	if (!a.s)74		goto err_close;75 76	pools = netdev_page_pool_get_dump(ys);77	if (!pools)78		goto err_free;79 80	ynl_dump_foreach(pools, pp) {81		struct stat *s = find_ifc(&a, pp->ifindex);82 83		count(s, 1, pp);84		if (pp->_present.detach_time)85			count(s, 0, pp);86	}87	netdev_page_pool_get_list_free(pools);88 89	pp_stats = netdev_page_pool_stats_get_dump(ys);90	if (!pp_stats)91		goto err_free;92 93	ynl_dump_foreach(pp_stats, pp) {94		struct stat *s = find_ifc(&a, pp->info.ifindex);95 96		if (pp->_present.alloc_fast)97			s->alloc_fast += pp->alloc_fast;98		if (pp->_present.alloc_refill)99			s->alloc_fast += pp->alloc_refill;100		if (pp->_present.alloc_slow)101			s->alloc_slow += pp->alloc_slow;102		if (pp->_present.recycle_ring)103			s->recycle_ring += pp->recycle_ring;104		if (pp->_present.recycle_cached)105			s->recycle_cache += pp->recycle_cached;106	}107	netdev_page_pool_stats_get_list_free(pp_stats);108 109	for (unsigned int i = 0; i < a.i; i++) {110		char ifname[IF_NAMESIZE];111		struct stat *s = &a.s[i];112		const char *name;113		double recycle;114 115		if (!s->ifc) {116			name = "<orphan>\t";117		} else {118			name = if_indextoname(s->ifc, ifname);119			if (name)120				printf("%8s", name);121			printf("[%d]\t", s->ifc);122		}123 124		printf("page pools: %u (zombies: %u)\n",125		       s->live[1].cnt, s->live[0].cnt);126		printf("\t\trefs: %zu bytes: %zu (refs: %zu bytes: %zu)\n",127		       s->live[1].refs, s->live[1].bytes,128		       s->live[0].refs, s->live[0].bytes);129 130		/* We don't know how many pages are sitting in cache and ring131		 * so we will under-count the recycling rate a bit.132		 */133		recycle = (double)(s->recycle_ring + s->recycle_cache) /134			(s->alloc_fast + s->alloc_slow) * 100;135		printf("\t\trecycling: %.1lf%% (alloc: %zu:%zu recycle: %zu:%zu)\n",136		       recycle, s->alloc_slow, s->alloc_fast,137		       s->recycle_ring, s->recycle_cache);138	}139 140	ynl_sock_destroy(ys);141	return 0;142 143err_free:144	free(a.s);145err_close:146	fprintf(stderr, "YNL: %s\n", ys->err.msg);147	ynl_sock_destroy(ys);148	return 2;149}150