Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/ynl/samples/page-pool.c
26285 views
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
}
150
151