mbufs.c revision 1.29
1/* $OpenBSD: mbufs.c,v 1.29 2010/09/23 10:49:55 dlg 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#include <sys/param.h> 18#include <sys/types.h> 19#include <sys/socket.h> 20#include <sys/sysctl.h> 21#include <sys/mbuf.h> 22#include <sys/pool.h> 23#include <net/if.h> 24 25#include <err.h> 26#include <errno.h> 27#include <ifaddrs.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include "systat.h" 32 33 34/* pool info for mcl* pools */ 35struct mclpool_info { 36 char title[16]; 37 int pool_offset; 38 int size; 39} mclpools[MCLPOOLS]; 40 41int mclpool_count = 0; 42int mbpool_index = -1; 43struct pool mbpool; 44 45/* interfaces */ 46static int num_ifs; 47struct if_info { 48 char name[16]; 49 struct if_data data; 50} *interfaces = NULL; 51 52void print_mb(void); 53int read_mb(void); 54int select_mb(void); 55static void showmbuf(struct if_info *, int, int); 56 57 58/* Define fields */ 59field_def fields_mbuf[] = { 60 {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 61 {"RXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 62 {"TXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 63 {"LIVELOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 64 {"SIZE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 65 {"ALIVE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 66 {"LWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 67 {"HWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 68 {"CWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 69}; 70 71 72#define FIELD_ADDR(x) (&fields_mbuf[x]) 73 74#define FLD_MB_IFACE FIELD_ADDR(0) 75#define FLD_MB_RXDELAY FIELD_ADDR(1) 76#define FLD_MB_TXDELAY FIELD_ADDR(2) 77#define FLD_MB_LLOCKS FIELD_ADDR(3) 78#define FLD_MB_MSIZE FIELD_ADDR(4) 79#define FLD_MB_MALIVE FIELD_ADDR(5) 80#define FLD_MB_MLWM FIELD_ADDR(6) 81#define FLD_MB_MHWM FIELD_ADDR(7) 82#define FLD_MB_MCWM FIELD_ADDR(8) 83 84 85/* Define views */ 86field_def *view_mbuf[] = { 87 FLD_MB_IFACE, 88#if NOTYET 89 FLD_MB_RXDELAY, FLD_MB_TXDELAY, 90#endif 91 FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM, 92 FLD_MB_MCWM, NULL 93}; 94 95/* Define view managers */ 96 97struct view_manager mbuf_mgr = { 98 "Mbufs", select_mb, read_mb, NULL, print_header, 99 print_mb, keyboard_callback, NULL, NULL 100}; 101 102field_view views_mb[] = { 103 {view_mbuf, "mbufs", '4', &mbuf_mgr}, 104 {NULL, NULL, 0, NULL} 105}; 106 107 108int 109initmembufs(void) 110{ 111 field_view *v; 112 int i, mib[4], npools; 113 struct pool pool; 114 char pname[32]; 115 size_t size; 116 117 /* go through all pools to identify mbuf and cluster pools */ 118 bzero(mclpools, sizeof(mclpools)); 119 120 mib[0] = CTL_KERN; 121 mib[1] = KERN_POOL; 122 mib[2] = KERN_POOL_NPOOLS; 123 size = sizeof(npools); 124 125 if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) { 126 err(1, "sysctl(KERN_POOL_NPOOLS)"); 127 /* NOTREACHED */ 128 } 129 130 for (i = 1; i <= npools; i++) { 131 mib[0] = CTL_KERN; 132 mib[1] = KERN_POOL; 133 mib[2] = KERN_POOL_NAME; 134 mib[3] = i; 135 size = sizeof(pname); 136 if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) { 137 continue; 138 } 139 140 if (strcmp(pname, "mbpl") == 0) { 141 mbpool_index = i; 142 continue; 143 } 144 145 if (strncmp(pname, "mcl", 3) != 0) 146 continue; 147 148 if (mclpool_count == MCLPOOLS) { 149 warnx("mbufs: Too many mcl* pools"); 150 break; 151 } 152 153 mib[2] = KERN_POOL_POOL; 154 size = sizeof(struct pool); 155 156 if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) { 157 err(1, "sysctl(KERN_POOL_POOL, %d)", i); 158 /* NOTREACHED */ 159 } 160 161 mclpools[mclpool_count].size = pool.pr_size; 162 mclpools[mclpool_count].pool_offset = i; 163 snprintf(mclpools[mclpool_count].title, 164 sizeof(mclpools[0].title), "%dk", 165 pool.pr_size / 1024); 166 167 mclpool_count++; 168 } 169 170 if (mclpool_count != MCLPOOLS) 171 warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS); 172 173 /* add view to the engine */ 174 for (v = views_mb; v->name != NULL; v++) 175 add_view(v); 176 177 178 /* finally read it once */ 179 read_mb(); 180 181 return(1); 182} 183 184int 185select_mb(void) 186{ 187 num_disp = 0; 188 return (0); 189} 190 191int 192read_mb(void) 193{ 194 struct pool pool; 195 struct ifaddrs *ifap, *ifa; 196 struct if_info *ifi; 197 int mib[4]; 198 int i, p, nif, ret = 1; 199 size_t size; 200 201 num_disp = 0; 202 if (getifaddrs(&ifap)) { 203 error("getifaddrs: %s", strerror(errno)); 204 return (1); 205 } 206 207 nif = 1; 208 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) 209 if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK) 210 nif++; 211 212 if (interfaces == NULL || num_ifs < nif) { 213 size_t len = sizeof(*ifi) * nif; 214 if (nif > SIZE_MAX / sizeof(*ifi)) { 215 error("overflow allocting %u interfaces", nif); 216 goto exit; 217 } 218 219 ifi = realloc(interfaces, len); 220 if (ifi == NULL) { 221 error("realloc: out of memory allocating %lld bytes", 222 (long long) len); 223 goto exit; 224 } 225 226 interfaces = ifi; 227 num_ifs = nif; 228 } 229 230 /* Fill in the "real" interfaces */ 231 ifi = interfaces + 1; 232 233 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 234 if (ifa->ifa_addr == NULL || 235 ifa->ifa_addr->sa_family != AF_LINK) 236 continue; 237 238 strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name)); 239 240 if (ifa->ifa_data) 241 memcpy(&ifi->data, ifa->ifa_data, sizeof(ifi->data)); 242 else 243 bzero(&ifi->data, sizeof(ifi->data)); 244 ifi++; 245 } 246 247 /* Fill in the "System" entry from pools */ 248 bzero(interfaces, sizeof(interfaces[0])); 249 strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name)); 250 251 mib[0] = CTL_KERN; 252 mib[1] = KERN_POOL; 253 mib[2] = KERN_POOL_POOL; 254 mib[3] = mbpool_index; 255 size = sizeof(struct pool); 256 257 if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) { 258 error("sysctl(KERN_POOL_POOL, %d)", mib[3]); 259 goto exit; 260 } 261 262 for (i = 0; i < mclpool_count; i++) { 263 struct mclpool *mp = &interfaces[0].data.ifi_mclpool[i]; 264 265 mib[3] = mclpools[i].pool_offset; 266 size = sizeof(struct pool); 267 268 if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) { 269 error("sysctl(KERN_POOL_POOL, %d)", mib[3]); 270 continue; 271 } 272 273 mp->mcl_alive = pool.pr_nget - pool.pr_nput; 274 mp->mcl_hwm = pool.pr_hiwat; 275 } 276 277 num_disp = 1; 278 ret = 0; 279 280 for (i = 0; i < num_ifs; i++) { 281 struct if_info *ifi = &interfaces[i]; 282 int pnd = num_disp; 283 for (p = 0; p < mclpool_count; p++) { 284 struct mclpool *mp = &ifi->data.ifi_mclpool[p]; 285 if (mp->mcl_alive == 0) 286 continue; 287 num_disp++; 288 } 289 if (i && pnd == num_disp) 290 num_disp++; 291 } 292 293 exit: 294 freeifaddrs(ifap); 295 return (ret); 296} 297 298void 299print_mb(void) 300{ 301 int i, p, n, count = 0; 302 303 showmbuf(interfaces, -1, 1); 304 305 for (n = i = 0; i < num_ifs; i++) { 306 struct if_info *ifi = &interfaces[i]; 307 int pcnt = count; 308 int showif = i; 309 310 if (maxprint > 0 && count >= maxprint) 311 return; 312 313 for (p = 0; p < mclpool_count; p++) { 314 struct mclpool *mp = &ifi->data.ifi_mclpool[p]; 315 if (mp->mcl_alive == 0) 316 continue; 317 if (n++ >= dispstart) { 318 showmbuf(ifi, p, showif); 319 showif = 0; 320 count++; 321 } 322 } 323 324 if (i && pcnt == count) { 325 /* only print the first line */ 326 if (n++ >= dispstart) { 327 showmbuf(ifi, -1, 1); 328 count++; 329 } 330 } 331 332 333 } 334} 335 336 337static void 338showmbuf(struct if_info *ifi, int p, int showif) 339{ 340 if (showif) 341 print_fld_str(FLD_MB_IFACE, ifi->name); 342 343 if (p == -1 && ifi == interfaces) { 344 print_fld_size(FLD_MB_MSIZE, mbpool.pr_size); 345 print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput); 346 print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat); 347 } 348 349#if NOTYET 350 print_fld_uint(FLD_MB_RXDELAY, ifi->data.ifi_rxdelay); 351 print_fld_uint(FLD_MB_TXDELAY, ifi->data.ifi_txdelay); 352 if (ifi->data.ifi_livelocks) 353 print_fld_size(FLD_MB_LLOCKS, ifi->data.ifi_livelocks); 354#endif 355 356 if (p >= 0 && p < mclpool_count) { 357 struct mclpool *mp = &ifi->data.ifi_mclpool[p]; 358 359 print_fld_str(FLD_MB_MSIZE, mclpools[p].title); 360 print_fld_uint(FLD_MB_MALIVE, mp->mcl_alive); 361 if (mp->mcl_lwm) 362 print_fld_size(FLD_MB_MLWM, mp->mcl_lwm); 363 if (mp->mcl_hwm) 364 print_fld_size(FLD_MB_MHWM, mp->mcl_hwm); 365 if (mp->mcl_cwm) 366 print_fld_size(FLD_MB_MCWM, mp->mcl_cwm); 367 } 368 369 end_line(); 370} 371