GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/mbufs.c Lines: 0 177 0.0 %
Date: 2017-11-07 Branches: 0 114 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mbufs.c,v 1.41 2016/04/04 16:26:00 sthen Exp $ */
2
/*
3
 * Copyright (c) 2008 Can Erkin Acar <canacar@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <sys/signal.h>
19
#include <sys/socket.h>
20
#include <sys/sysctl.h>
21
#include <sys/queue.h>
22
#include <sys/mbuf.h>
23
#include <sys/pool.h>
24
#include <net/if.h>
25
#include <sys/sockio.h>
26
#include <sys/ioctl.h>
27
28
#include <err.h>
29
#include <errno.h>
30
#include <ifaddrs.h>
31
#include <stdlib.h>
32
#include <string.h>
33
34
#include "systat.h"
35
36
/* pool info */
37
int mbpool_index = -1;
38
int mclpools_index[MCLPOOLS];
39
int mclpool_count = 0;
40
struct kinfo_pool mbpool;
41
u_int mcllivelocks, mcllivelocks_cur, mcllivelocks_diff;
42
43
/* interfaces */
44
static int num_ifs = 0;
45
struct if_info {
46
	char name[16];
47
	struct if_rxrinfo data;
48
} *interfaces = NULL;
49
50
static int sock;
51
52
void print_mb(void);
53
int read_mb(void);
54
int select_mb(void);
55
static void showmbuf(struct if_info *, int, int);
56
57
/* Define fields */
58
field_def fields_mbuf[] = {
59
	{"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
60
	{"RXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
61
	{"TXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
62
	{"LIVELOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
63
	{"SIZE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
64
	{"ALIVE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65
	{"LWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
66
	{"HWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
67
	{"CWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
68
};
69
70
71
#define FLD_MB_IFACE	FIELD_ADDR(fields_mbuf,0)
72
#define FLD_MB_RXDELAY	FIELD_ADDR(fields_mbuf,1)
73
#define FLD_MB_TXDELAY	FIELD_ADDR(fields_mbuf,2)
74
#define FLD_MB_LLOCKS	FIELD_ADDR(fields_mbuf,3)
75
#define FLD_MB_MSIZE	FIELD_ADDR(fields_mbuf,4)
76
#define FLD_MB_MALIVE	FIELD_ADDR(fields_mbuf,5)
77
#define FLD_MB_MLWM	FIELD_ADDR(fields_mbuf,6)
78
#define FLD_MB_MHWM	FIELD_ADDR(fields_mbuf,7)
79
#define FLD_MB_MCWM	FIELD_ADDR(fields_mbuf,8)
80
81
82
/* Define views */
83
field_def *view_mbuf[] = {
84
	FLD_MB_IFACE,
85
	FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM,
86
	FLD_MB_MCWM, NULL
87
};
88
89
/* Define view managers */
90
91
struct view_manager mbuf_mgr = {
92
	"Mbufs", select_mb, read_mb, NULL, print_header,
93
	print_mb, keyboard_callback, NULL, NULL
94
};
95
96
field_view views_mb[] = {
97
	{view_mbuf, "mbufs", '4', &mbuf_mgr},
98
	{NULL, NULL, 0, NULL}
99
};
100
101
102
int
103
initmembufs(void)
104
{
105
	struct if_rxring_info *ifr;
106
	field_view *v;
107
	int i, mib[4], npools;
108
	struct kinfo_pool pool;
109
	char pname[32];
110
	size_t size;
111
112
	sock = socket(AF_INET, SOCK_DGRAM, 0);
113
	if (sock == -1) {
114
		err(1, "socket()");
115
		/* NOTREACHED */
116
	}
117
118
	/* set up the "System" interface */
119
120
	interfaces = calloc(1, sizeof(*interfaces));
121
	if (interfaces == NULL)
122
		err(1, "calloc: interfaces");
123
124
	ifr = calloc(MCLPOOLS, sizeof(*ifr));
125
	if (ifr == NULL)
126
		err(1, "calloc: system pools");
127
128
	strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name));
129
	interfaces[0].data.ifri_total = MCLPOOLS;
130
	interfaces[0].data.ifri_entries = ifr;
131
	num_ifs = 1;
132
133
	/* go through all pools to identify mbuf and cluster pools */
134
135
	mib[0] = CTL_KERN;
136
	mib[1] = KERN_POOL;
137
	mib[2] = KERN_POOL_NPOOLS;
138
	size = sizeof(npools);
139
140
	if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
141
		err(1, "sysctl(KERN_POOL_NPOOLS)");
142
		/* NOTREACHED */
143
	}
144
145
	for (i = 1; i <= npools; i++) {
146
		mib[0] = CTL_KERN;
147
		mib[1] = KERN_POOL;
148
		mib[2] = KERN_POOL_NAME;
149
		mib[3] = i;
150
		size = sizeof(pname);
151
		if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) {
152
			continue;
153
		}
154
155
		if (strcmp(pname, "mbufpl") == 0) {
156
			mbpool_index = i;
157
			continue;
158
		}
159
160
		if (strncmp(pname, "mcl", 3) != 0)
161
			continue;
162
163
		if (mclpool_count == MCLPOOLS) {
164
			warnx("mbufs: Too many mcl* pools");
165
			break;
166
		}
167
168
		mib[2] = KERN_POOL_POOL;
169
		size = sizeof(pool);
170
171
		if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
172
			err(1, "sysctl(KERN_POOL_POOL, %d)", i);
173
			/* NOTREACHED */
174
		}
175
176
		snprintf(ifr[mclpool_count].ifr_name,
177
		    sizeof(ifr[mclpool_count].ifr_name), "%dk",
178
		    pool.pr_size / 1024);
179
		ifr[mclpool_count].ifr_size = pool.pr_size;
180
181
		mclpools_index[mclpool_count++] = i;
182
	}
183
184
	if (mclpool_count != MCLPOOLS)
185
		warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS);
186
187
	/* add view to the engine */
188
	for (v = views_mb; v->name != NULL; v++)
189
		add_view(v);
190
191
	/* finally read it once */
192
	read_mb();
193
194
	return(1);
195
}
196
197
int
198
select_mb(void)
199
{
200
	num_disp = 0;
201
	return (0);
202
}
203
204
int
205
read_mb(void)
206
{
207
	struct kinfo_pool pool;
208
	struct ifaddrs *ifap = NULL, *ifa;
209
	struct if_info *ifi;
210
	struct if_rxring_info *ifr;
211
	int mib[4];
212
	int i, p, nif, ret = 1, rv;
213
	u_int rings;
214
	size_t size;
215
216
	mib[0] = CTL_KERN;
217
	mib[1] = KERN_NETLIVELOCKS;
218
	size = sizeof(mcllivelocks_cur);
219
	if (sysctl(mib, 2, &mcllivelocks_cur, &size, NULL, 0) < 0 &&
220
	    errno != EOPNOTSUPP) {
221
		error("sysctl(KERN_NETLIVELOCKS)");
222
		goto exit;
223
	}
224
	mcllivelocks_diff = mcllivelocks_cur - mcllivelocks;
225
	mcllivelocks = mcllivelocks_cur;
226
227
	num_disp = 0;
228
	if (getifaddrs(&ifap)) {
229
		error("getifaddrs: %s", strerror(errno));
230
		return (1);
231
	}
232
233
	nif = 1;
234
	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
235
		if (ifa->ifa_addr == NULL ||
236
		    ifa->ifa_addr->sa_family != AF_LINK)
237
			continue;
238
239
		nif++;
240
	}
241
242
	if (num_ifs < nif) {
243
		ifi = reallocarray(interfaces, nif, sizeof(*interfaces));
244
		if (ifi == NULL) {
245
			error("reallocarray: %d interfaces", nif);
246
			goto exit;
247
		}
248
249
		interfaces = ifi;
250
		while (num_ifs < nif)
251
			memset(&interfaces[num_ifs++], 0, sizeof(*interfaces));
252
	}
253
254
	/* Fill in the "real" interfaces */
255
	ifi = interfaces + 1;
256
257
	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
258
		if (ifa->ifa_addr == NULL ||
259
		    ifa->ifa_addr->sa_family != AF_LINK)
260
			continue;
261
262
		strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name));
263
		for (;;) {
264
			struct ifreq ifreq;
265
			rings = ifi->data.ifri_total;
266
267
			memset(&ifreq, 0, sizeof(ifreq));
268
			strlcpy(ifreq.ifr_name, ifa->ifa_name,
269
			    sizeof(ifreq.ifr_name));
270
			ifreq.ifr_data = (caddr_t)&ifi->data;
271
272
			rv = ioctl(sock, SIOCGIFRXR, &ifreq);
273
			if (rv == -1) {
274
				if (errno == ENOTTY) {
275
					free(ifi->data.ifri_entries);
276
					ifi->data.ifri_total = 0;
277
					ifi->data.ifri_entries = NULL;
278
					break;
279
				}
280
281
				error("ioctl(SIOCGIFRXR) %s", strerror(errno));
282
				break;
283
			}
284
285
			if (rings >= ifi->data.ifri_total)
286
				break;
287
288
			ifr = reallocarray(ifi->data.ifri_entries,
289
			    ifi->data.ifri_total, sizeof(*ifr));
290
			if (ifr == NULL) {
291
				ifi->data.ifri_total = rings;
292
				error("reallocarray: %u rings",
293
				    ifi->data.ifri_total);
294
				goto exit;
295
			}
296
297
			ifi->data.ifri_entries = ifr;
298
		}
299
300
		ifi++;
301
	}
302
303
	/* Fill in the "System" entry from pools */
304
305
	mib[0] = CTL_KERN;
306
	mib[1] = KERN_POOL;
307
	mib[2] = KERN_POOL_POOL;
308
	mib[3] = mbpool_index;
309
	size = sizeof(mbpool);
310
311
	if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) {
312
		error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
313
		goto exit;
314
	}
315
316
	for (i = 0; i < mclpool_count; i++) {
317
		ifr = &interfaces[0].data.ifri_entries[i];
318
319
		mib[3] = mclpools_index[i];
320
		size = sizeof(pool);
321
322
		if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
323
			error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
324
			continue;
325
		}
326
327
		ifr->ifr_info.rxr_alive = pool.pr_nget - pool.pr_nput;
328
		ifr->ifr_info.rxr_hwm = pool.pr_hiwat;
329
	}
330
331
	num_disp = 1;
332
	ret = 0;
333
334
	for (i = 0; i < num_ifs; i++) {
335
		struct if_info *ifi = &interfaces[i];
336
		int pnd = num_disp;
337
		for (p = 0; p < ifi->data.ifri_total; p++) {
338
			ifr = &ifi->data.ifri_entries[p];
339
			if (ifr->ifr_info.rxr_alive == 0)
340
				continue;
341
			num_disp++;
342
		}
343
		if (i && pnd == num_disp)
344
			num_disp++;
345
	}
346
347
 exit:
348
	if (ifap)
349
		freeifaddrs(ifap);
350
	return (ret);
351
}
352
353
void
354
print_mb(void)
355
{
356
	int i, p, n, count = 0;
357
358
	showmbuf(interfaces, -1, 1);
359
360
	for (n = i = 0; i < num_ifs; i++) {
361
		struct if_info *ifi = &interfaces[i];
362
		int pcnt = count;
363
		int showif = i;
364
365
		if (maxprint > 0 && count >= maxprint)
366
			return;
367
368
		for (p = 0; p < ifi->data.ifri_total; p++) {
369
			struct if_rxring_info *ifr = &ifi->data.ifri_entries[p];
370
			if (ifr->ifr_info.rxr_alive == 0)
371
				continue;
372
			if (n++ >= dispstart) {
373
				showmbuf(ifi, p, showif);
374
				showif = 0;
375
				count++;
376
			}
377
		}
378
379
		if (i && pcnt == count) {
380
			/* only print the first line */
381
			if (n++ >= dispstart) {
382
				showmbuf(ifi, -1, 1);
383
				count++;
384
			}
385
		}
386
	}
387
}
388
389
390
static void
391
showmbuf(struct if_info *ifi, int p, int showif)
392
{
393
	if (showif)
394
		print_fld_str(FLD_MB_IFACE, ifi->name);
395
396
	if (p == -1 && ifi == interfaces) {
397
		print_fld_uint(FLD_MB_LLOCKS, mcllivelocks_diff);
398
		print_fld_size(FLD_MB_MSIZE, mbpool.pr_size);
399
		print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput);
400
		print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat);
401
	}
402
403
	if (p >= 0 && p < mclpool_count) {
404
		struct if_rxring_info *ifr = &ifi->data.ifri_entries[p];
405
		struct if_rxring *rxr= &ifr->ifr_info;
406
		print_fld_uint(FLD_MB_MSIZE, ifr->ifr_size);
407
		print_fld_uint(FLD_MB_MALIVE, rxr->rxr_alive);
408
		if (rxr->rxr_lwm)
409
			print_fld_size(FLD_MB_MLWM, rxr->rxr_lwm);
410
		if (rxr->rxr_hwm)
411
			print_fld_size(FLD_MB_MHWM, rxr->rxr_hwm);
412
		if (rxr->rxr_cwm)
413
			print_fld_size(FLD_MB_MCWM, rxr->rxr_cwm);
414
	}
415
416
	end_line();
417
}