]> Git Repo - linux.git/blob - tools/net/ynl/samples/page-pool.c
Linux 6.14-rc3
[linux.git] / tools / net / ynl / samples / page-pool.c
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3
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
13 struct 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
24 struct stats_array {
25         unsigned int i, max;
26         struct stat *s;
27 };
28
29 static 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
47 static 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
57 int 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("[%u]\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 ring
131                  * 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
143 err_free:
144         free(a.s);
145 err_close:
146         fprintf(stderr, "YNL: %s\n", ys->err.msg);
147         ynl_sock_destroy(ys);
148         return 2;
149 }
This page took 0.040474 seconds and 4 git commands to generate.