1/* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 */ 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31 32#include <sys/types.h> 33#include <sys/sysctl.h> 34#include <sys/ioctl.h> 35#include <sys/socket.h> 36#include <sys/queue.h> 37#include <net/if.h> 38#include <net/if_mib.h> 39#include <net/if_types.h> 40#include <net/if_atm.h> 41#include <net/if_media.h> 42#include <netnatm/natm.h> 43#include <dev/utopia/utopia.h> 44#include <dev/utopia/suni.h> 45#include <dev/utopia/idtphy.h> 46 47#include "atmconfig.h" 48#include "private.h" 49#include "diag.h" 50 51static void diag_list(int, char *[]); 52static void diag_config(int, char *[]); 53static void diag_vcc(int, char *[]); 54static void diag_phy_show(int, char *[]); 55static void diag_phy_set(int, char *[]); 56static void diag_phy_print(int, char *[]); 57static void diag_phy_stats(int, char *[]); 58static void diag_stats(int, char *[]); 59 60static const struct cmdtab diag_phy_tab[] = { 61 { "show", NULL, diag_phy_show }, 62 { "set", NULL, diag_phy_set }, 63 { "stats", NULL, diag_phy_stats }, 64 { "print", NULL, diag_phy_print }, 65 { NULL, NULL, NULL }, 66}; 67 68const struct cmdtab diag_tab[] = { 69 { "list", NULL, diag_list }, 70 { "config", NULL, diag_config }, 71 { "phy", diag_phy_tab, NULL }, 72 { "stats", NULL, diag_stats }, 73 { "vcc", NULL, diag_vcc }, 74 { NULL, NULL, NULL } 75}; 76 77static const struct utopia_print suni_lite[] = { SUNI_PRINT_LITE }; 78static const struct utopia_print suni_ultra[] = { SUNI_PRINT_ULTRA }; 79static const struct utopia_print suni_622[] = { SUNI_PRINT_622 }; 80static const struct utopia_print idt77105[] = { IDTPHY_PRINT_77105 }; 81static const struct utopia_print idt77155[] = { IDTPHY_PRINT_77155 }; 82 83static const struct { 84 const struct utopia_print *tab; 85 u_int len; 86 u_int type; 87} phy_print[] = { 88 { suni_lite, sizeof(suni_lite) / sizeof(suni_lite[0]), 89 UTP_TYPE_SUNI_LITE }, 90 { suni_ultra, sizeof(suni_ultra) / sizeof(suni_ultra[0]), 91 UTP_TYPE_SUNI_ULTRA }, 92 { suni_622, sizeof(suni_622) / sizeof(suni_622[0]), 93 UTP_TYPE_SUNI_622 }, 94 { idt77105, sizeof(idt77105) / sizeof(idt77105[0]), 95 UTP_TYPE_IDT77105 }, 96 { idt77155, sizeof(idt77155) / sizeof(idt77155[0]), 97 UTP_TYPE_IDT77155 }, 98}; 99 100static const u_int utopia_addreg[] = { UTP_REG_ADD }; 101 102/* 103 * Driver statistics printing 104 */ 105static const char *const print_stats_pca200e[] = { 106 "cmd_queue_full:", 107 "get_stat_errors:", 108 "clr_stat_errors:", 109 "get_prom_errors:", 110 "suni_reg_errors:", 111 "tx_queue_full:", 112 "tx_queue_almost_full:", 113 "tx_pdu2big:", 114 "tx_too_many_segs:", 115 "tx_retry:", 116 "fix_empty:", 117 "fix_addr_copy:", 118 "fix_addr_noext:", 119 "fix_addr_ext:", 120 "fix_len_noext:", 121 "fix_len_copy:", 122 "fix_len:", 123 "rx_badvc:", 124 "rx_closed:", 125 NULL 126}; 127static const char *const print_stats_he[] = { 128 "tdprq_full:", 129 "hbuf_error:", 130 "crc_error:", 131 "len_error:", 132 "flow_closed:", 133 "flow_drop:", 134 "tpd_no_mem:", 135 "rx_seg:", 136 "empty_hbuf:", 137 "short_aal5:", 138 "badlen_aal5:", 139 "bug_bad_isw:", 140 "bug_no_irq_upd:", 141 "itype_tbrq:", 142 "itype_tpd:", 143 "itype_rbps:", 144 "itype_rbpl:", 145 "itype_rbrq:", 146 "itype_rbrqt:", 147 "itype_unknown:", 148 "itype_phys:", 149 "itype_err:", 150 "defrag:", 151 "mcc:", 152 "oec:", 153 "dcc:", 154 "cec:", 155 "no_rcv_mbuf:", 156 NULL 157}; 158static const char *const print_stats_eni[] = { 159 "ttrash:", 160 "mfixaddr:", 161 "mfixlen:", 162 "mfixfail:", 163 "txmbovr:", 164 "dmaovr:", 165 "txoutspace:", 166 "txdtqout:", 167 "launch:", 168 "hwpull:", 169 "swadd:", 170 "rxqnotus:", 171 "rxqus:", 172 "rxdrqout:", 173 "rxmbufout:", 174 "txnomap:", 175 "vtrash:", 176 "otrash:", 177 NULL 178}; 179 180static const char *const print_stats_idt77211[] = { 181 "need_copy:", 182 "copy_failed:", 183 "out_of_tbds:", 184 "no_txmaps:", 185 "tx_load_err:", 186 "tx_qfull:", 187 NULL 188}; 189static const char *const print_stats_idt77252[] = { 190 "raw_cells:", 191 "raw_no_vcc:", 192 "raw_no_buf:", 193 "tx_qfull:", 194 "tx_out_of_tbds:", 195 "tx_out_of_maps:", 196 "tx_load_err:", 197 NULL 198}; 199static const char *const print_stats_virtual[] = { 200 "dummy:", 201 NULL 202}; 203static const char *const *const print_stats[] = { 204 [ATM_DEVICE_UNKNOWN] = NULL, 205 [ATM_DEVICE_PCA200E] = print_stats_pca200e, 206 [ATM_DEVICE_HE155] = print_stats_he, 207 [ATM_DEVICE_HE622] = print_stats_he, 208 [ATM_DEVICE_ENI155P] = print_stats_eni, 209 [ATM_DEVICE_ADP155P] = print_stats_eni, 210 [ATM_DEVICE_FORELE25] = print_stats_idt77211, 211 [ATM_DEVICE_FORELE155] = print_stats_idt77211, 212 [ATM_DEVICE_NICSTAR25] = print_stats_idt77211, 213 [ATM_DEVICE_NICSTAR155] = print_stats_idt77211, 214 [ATM_DEVICE_IDTABR25] = print_stats_idt77252, 215 [ATM_DEVICE_IDTABR155] = print_stats_idt77252, 216 [ATM_DEVICE_PROATM25] = print_stats_idt77252, 217 [ATM_DEVICE_PROATM155] = print_stats_idt77252, 218 [ATM_DEVICE_VIRTUAL] = print_stats_virtual, 219}; 220 221struct diagif_list diagif_list = TAILQ_HEAD_INITIALIZER(diagif_list); 222 223/* 224 * Fetch a phy sysctl 225 */ 226static int 227phy_fetch(const char *ifname, const char *var, void *val, size_t len, 228 int err_fatal) 229{ 230 char *str; 231 232 if (asprintf(&str, "hw.atm.%s.phy_%s", ifname, var) == -1) 233 err(1, NULL); 234 if (sysctlbyname(str, val, &len, NULL, 0) == -1) { 235 if (err_fatal || errno != ENOENT) 236 err(1, "%s", str); 237 free(str); 238 return (-1); 239 } 240 free(str); 241 return (0); 242} 243 244/* 245 * Fetch the list of all ATM network interfaces and their MIBs. 246 */ 247void 248diagif_fetch(void) 249{ 250 size_t len; 251 int count; 252 int name[6]; 253 struct ifmibdata mib; 254 struct ifatm_mib atm; 255 int idx; 256 struct diagif *d; 257 258 while ((d = TAILQ_FIRST(&diagif_list)) != NULL) { 259 if (d->vtab != NULL) 260 free(d->vtab); 261 TAILQ_REMOVE(&diagif_list, d, link); 262 free(d); 263 } 264 265 len = sizeof(count); 266 if (sysctlbyname("net.link.generic.system.ifcount", &count, &len, 267 NULL, 0) == -1) 268 err(1, "ifcount"); 269 270 name[0] = CTL_NET; 271 name[1] = PF_LINK; 272 name[2] = NETLINK_GENERIC; 273 name[3] = IFMIB_IFDATA; 274 275 for (idx = 1; idx <= count; idx++) { 276 name[4] = idx; 277 name[5] = IFDATA_GENERAL; 278 len = sizeof(mib); 279 if (sysctl(name, 6, &mib, &len, NULL, 0) == -1) 280 err(1, "interface %d: general mib", idx); 281 if (mib.ifmd_data.ifi_type == IFT_ATM) { 282 name[5] = IFDATA_LINKSPECIFIC; 283 len = sizeof(atm); 284 if (sysctl(name, 6, &atm, &len, NULL, 0) == -1) 285 err(1, "interface %d: ATM mib", idx); 286 287 d = malloc(sizeof(*d)); 288 if (d == NULL) 289 err(1, NULL); 290 bzero(d, sizeof(*d)); 291 d->mib = atm; 292 d->index = idx; 293 strcpy(d->ifname, mib.ifmd_name); 294 TAILQ_INSERT_TAIL(&diagif_list, d, link); 295 296 if (phy_fetch(d->ifname, "type", &d->phy_type, 297 sizeof(d->phy_type), 0) == 0) { 298 d->phy_present = 1; 299 phy_fetch(d->ifname, "loopback", 300 &d->phy_loopback, 301 sizeof(d->phy_loopback), 1); 302 phy_fetch(d->ifname, "name", &d->phy_name, 303 sizeof(d->phy_name), 1); 304 phy_fetch(d->ifname, "state", &d->phy_state, 305 sizeof(d->phy_state), 1); 306 phy_fetch(d->ifname, "carrier", &d->phy_carrier, 307 sizeof(d->phy_carrier), 1); 308 } 309 } 310 } 311} 312 313/* 314 * "<radix><bit>STRING\011<mask><pattern>STRING\012<mask><radix>STRING" 315 */ 316static char * 317printb8(uint32_t val, const char *descr) 318{ 319 static char buffer[1000]; 320 char *ptr; 321 int tmp = 0; 322 u_char mask, pattern; 323 324 if (*descr++ == '\010') 325 sprintf(buffer, "%#o", val); 326 else 327 sprintf(buffer, "%#x", val); 328 ptr = buffer + strlen(buffer); 329 330 *ptr++ = '<'; 331 while (*descr) { 332 if (*descr == '\11') { 333 descr++; 334 mask = *descr++; 335 pattern = *descr++; 336 if ((val & mask) == pattern) { 337 if (tmp++) 338 *ptr++ = ','; 339 while (*descr >= ' ') 340 *ptr++ = *descr++; 341 } else { 342 while (*descr >= ' ') 343 descr++; 344 } 345 } else if (*descr == '\12') { 346 descr++; 347 mask = *descr++; 348 pattern = *descr++; 349 if (tmp++) 350 *ptr++ = ','; 351 while (*descr >= ' ') 352 *ptr++ = *descr++; 353 *ptr++ = '='; 354 if (pattern == 8) 355 sprintf(ptr, "%#o", 356 (val & mask) >> (ffs(mask)-1)); 357 else if (pattern == 10) 358 sprintf(ptr, "%u", 359 (val & mask) >> (ffs(mask)-1)); 360 else 361 sprintf(ptr, "%#x", 362 (val & mask) >> (ffs(mask)-1)); 363 ptr += strlen(ptr); 364 } else { 365 if (val & (1 << (*descr++ - 1))) { 366 if (tmp++) 367 *ptr++ = ','; 368 while (*descr >= ' ') 369 *ptr++ = *descr++; 370 } else { 371 while (*descr >= ' ') 372 descr++; 373 } 374 } 375 } 376 *ptr++ = '>'; 377 *ptr++ = '\0'; 378 379 return (buffer); 380} 381 382/* 383 * "<radix><bit>STRING<bit>STRING" 384 */ 385static char * 386printb(uint32_t val, const char *descr) 387{ 388 static char buffer[1000]; 389 char *ptr; 390 int tmp = 0; 391 392 if (*descr++ == '\010') 393 sprintf(buffer, "%#o", val); 394 else 395 sprintf(buffer, "%#x", val); 396 ptr = buffer + strlen(buffer); 397 398 *ptr++ = '<'; 399 while (*descr) { 400 if (val & (1 << (*descr++ - 1))) { 401 if (tmp++) 402 *ptr++ = ','; 403 while (*descr > ' ') 404 *ptr++ = *descr++; 405 } else { 406 while (*descr > ' ') 407 descr++; 408 } 409 } 410 *ptr++ = '>'; 411 *ptr++ = '\0'; 412 413 return (buffer); 414} 415 416 417static void 418diag_loop(int argc, char *argv[], const char *text, 419 void (*func)(const struct diagif *)) 420{ 421 int i; 422 struct diagif *aif; 423 424 heading_init(); 425 if (argc > 0) { 426 for (i = 0; i < argc; i++) { 427 TAILQ_FOREACH(aif, &diagif_list, link) { 428 if (strcmp(argv[i], aif->ifname) == 0) { 429 heading("%s", text); 430 (*func)(aif); 431 break; 432 } 433 } 434 if (aif == NULL) 435 warnx("%s: no such ATM interface", argv[i]); 436 } 437 } else { 438 TAILQ_FOREACH(aif, &diagif_list, link) { 439 heading("%s", text); 440 (*func)(aif); 441 } 442 } 443} 444 445/* 446 * Print the config line for the given interface 447 */ 448static void 449config_line1(const struct diagif *aif) 450{ 451 printf("%-6u%-9s%-8u%-5u%-6u%-5u%-6u%02x:%02x:%02x:%02x:%02x:%02x\n", 452 aif->index, aif->ifname, aif->mib.pcr, (1 << aif->mib.vpi_bits) - 1, 453 (1 << aif->mib.vci_bits) - 1, aif->mib.max_vpcs, aif->mib.max_vccs, 454 aif->mib.esi[0], aif->mib.esi[1], aif->mib.esi[2], 455 aif->mib.esi[3], aif->mib.esi[4], aif->mib.esi[5]); 456} 457 458static void 459config_line2(const struct diagif *aif) 460{ 461 u_int d, i; 462 463 static const struct { 464 const char *dev; 465 const char *vendor; 466 } devs[] = { 467 ATM_DEVICE_NAMES 468 }; 469 static const struct { 470 u_int media; 471 const char *const name; 472 } medias[] = IFM_SUBTYPE_ATM_DESCRIPTIONS; 473 474 for (i = 0; medias[i].name; i++) 475 if (aif->mib.media == medias[i].media) 476 break; 477 478 if ((d = aif->mib.device) >= sizeof(devs) / sizeof(devs[0])) 479 d = 0; 480 481 printf("%-6u%-9s%-12.11s%-13.12s%-8u%-6x%-6x %s\n", aif->index, 482 aif->ifname, devs[d].vendor, devs[d].dev, aif->mib.serial, 483 aif->mib.hw_version, aif->mib.sw_version, 484 medias[i].name ? medias[i].name : "unknown"); 485} 486 487static void 488diag_config(int argc, char *argv[]) 489{ 490 int opt; 491 492 static int hardware; 493 static int atm; 494 495 static const struct option opts[] = { 496 { "hardware", OPT_SIMPLE, &hardware }, 497 { "atm", OPT_SIMPLE, &atm }, 498 { NULL, 0, NULL } 499 }; 500 501 static const char config_text1[] = 502 "Interface Max Max\n" 503 "Index Name PCR VPI VCI VPCs VCCs ESI\n"; 504 static const char config_text2[] = 505 "Interface Version\n" 506 "Index Name Vendor Card " 507 "Serial HW SW Media\n"; 508 509 while ((opt = parse_options(&argc, &argv, opts)) != -1) 510 switch (opt) { 511 } 512 513 diagif_fetch(); 514 if (TAILQ_EMPTY(&diagif_list)) 515 errx(1, "no ATM interfaces found"); 516 517 if (!atm && !hardware) 518 atm = 1; 519 520 if (atm) 521 diag_loop(argc, argv, config_text1, config_line1); 522 if (hardware) 523 diag_loop(argc, argv, config_text2, config_line2); 524 525} 526 527static void 528diag_list(int argc, char *argv[]) 529{ 530 int opt; 531 struct diagif *aif; 532 533 static const struct option opts[] = { 534 { NULL, 0, NULL } 535 }; 536 537 while ((opt = parse_options(&argc, &argv, opts)) != -1) 538 switch (opt) { 539 } 540 541 if (argc > 0) 542 errx(1, "no arguments required for 'diag list'"); 543 544 diagif_fetch(); 545 if (TAILQ_EMPTY(&diagif_list)) 546 errx(1, "no ATM interfaces found"); 547 548 TAILQ_FOREACH(aif, &diagif_list, link) 549 printf("%s ", aif->ifname); 550 printf("\n"); 551} 552 553/* 554 * Print the config line for the given interface 555 */ 556static void 557phy_show_line(const struct diagif *aif) 558{ 559 printf("%-6u%-9s", aif->index, aif->ifname); 560 if (aif->phy_present) 561 printf("%-5u%-25s0x%-9x", aif->phy_type, 562 aif->phy_name, aif->phy_loopback); 563 printf("\n"); 564} 565 566static void 567diag_phy_show(int argc, char *argv[]) 568{ 569 int opt; 570 571 static const struct option opts[] = { 572 { NULL, 0, NULL } 573 }; 574 575 static const char phy_show_text[] = 576 "Interface Phy\n" 577 "Index Name Type Name Loopback State\n"; 578 579 while ((opt = parse_options(&argc, &argv, opts)) != -1) 580 switch (opt) { 581 } 582 583 diagif_fetch(); 584 if (TAILQ_EMPTY(&diagif_list)) 585 errx(1, "no ATM interfaces found"); 586 587 diag_loop(argc, argv, phy_show_text, phy_show_line); 588} 589 590/* 591 * Make sure the interface exists and has a phy 592 */ 593static struct diagif * 594diagif_get_phy(const char *arg) 595{ 596 struct diagif *aif; 597 598 diagif_fetch(); 599 TAILQ_FOREACH(aif, &diagif_list, link) 600 if (strcmp(aif->ifname, arg) == 0) 601 break; 602 if (aif == NULL) 603 errx(1, "no such interface: %s", arg); 604 if (!aif->phy_present) 605 errx(1, "interface %s has no phy", arg); 606 607 return (aif); 608} 609 610static void 611diag_phy_set(int argc, char *argv[]) 612{ 613 int opt; 614 uint8_t reg[3]; 615 u_long res; 616 char *end; 617 char *str; 618 619 static const struct option opts[] = { 620 { NULL, 0, NULL } 621 }; 622 623 while ((opt = parse_options(&argc, &argv, opts)) != -1) 624 switch (opt) { 625 } 626 627 if (argc != 4) 628 errx(1, "missing arguments for 'diag phy set'"); 629 630 errno = 0; 631 res = strtoul(argv[1], &end, 0); 632 if (errno != 0) 633 err(1, "register number"); 634 if (*end != '\0') 635 errx(1, "malformed register number '%s'", argv[1]); 636 if (res > 0xff) 637 errx(1, "register number too large"); 638 reg[0] = res; 639 640 errno = 0; 641 res = strtoul(argv[2], &end, 0); 642 if (errno != 0) 643 err(1, "mask"); 644 if (*end != '\0') 645 errx(1, "malformed mask '%s'", argv[1]); 646 if (res > 0xff) 647 errx(1, "mask too large"); 648 reg[1] = res; 649 650 errno = 0; 651 res = strtoul(argv[3], &end, 0); 652 if (errno != 0) 653 err(1, "value"); 654 if (*end != '\0') 655 errx(1, "malformed value '%s'", argv[1]); 656 if (res > 0xff) 657 errx(1, "value too large"); 658 reg[2] = res; 659 660 (void)diagif_get_phy(argv[0]); 661 662 if (asprintf(&str, "hw.atm.%s.phy_regs", argv[0]) == -1) 663 err(1, NULL); 664 665 if (sysctlbyname(str, NULL, NULL, reg, 3 * sizeof(uint8_t))) 666 err(1, "%s", str); 667 668 free(str); 669} 670 671static void 672diag_phy_print(int argc, char *argv[]) 673{ 674 int opt; 675 char *str; 676 size_t len, len1; 677 uint8_t *regs; 678 u_int type, i; 679 const struct utopia_print *p; 680 681 static int numeric; 682 683 static const struct option opts[] = { 684 { "numeric", OPT_SIMPLE, &numeric }, 685 { NULL, 0, NULL } 686 }; 687 688 while ((opt = parse_options(&argc, &argv, opts)) != -1) 689 switch (opt) { 690 } 691 692 if (argc != 1) 693 errx(1, "need device name for 'diag phy print'"); 694 695 (void)diagif_get_phy(argv[0]); 696 697 if (asprintf(&str, "hw.atm.%s.phy_regs", argv[0]) == -1) 698 err(1, NULL); 699 len = 0; 700 if (sysctlbyname(str, NULL, &len, NULL, 0)) 701 err(1, "'%s' not found", str); 702 703 regs = malloc(len); 704 if (regs == NULL) 705 err(1, NULL); 706 707 if (sysctlbyname(str, regs, &len, NULL, 0)) 708 err(1, "'%s' not found", str); 709 free(str); 710 711 if (numeric) { 712 for (i = 0; i < len; i++) { 713 if (i % 16 == 0) 714 printf("%02x: ", i); 715 if (i % 16 == 8) 716 printf(" "); 717 printf(" %02x", regs[i]); 718 if (i % 16 == 15) 719 printf("\n"); 720 } 721 if (i % 16 != 0) 722 printf("\n"); 723 } else { 724 if (asprintf(&str, "hw.atm.%s.phy_type", argv[0]) == -1) 725 err(1, NULL); 726 len1 = sizeof(type); 727 if (sysctlbyname(str, &type, &len1, NULL, 0)) 728 err(1, "'%s' not found", str); 729 free(str); 730 731 for (i = 0; i < sizeof(phy_print) / sizeof(phy_print[0]); i++) 732 if (type == phy_print[i].type) 733 break; 734 if (i == sizeof(phy_print) / sizeof(phy_print[0])) 735 errx(1, "unknown PHY chip type %u\n", type); 736 737 for (p = phy_print[i].tab; 738 p < phy_print[i].tab + phy_print[i].len; 739 p++) { 740 if (p->reg + utopia_addreg[p->type] > len) 741 /* don't have this register */ 742 continue; 743 744 printf("%s:%*s", p->name, 40 - (int)strlen(p->name),""); 745 746 switch (p->type) { 747 748 case UTP_REGT_BITS: 749 printf("%s\n", printb8(regs[p->reg], p->fmt)); 750 break; 751 752 case UTP_REGT_INT8: 753 printf("%#x\n", regs[p->reg]); 754 break; 755 756 case UTP_REGT_INT10BITS: 757 printf("%#x %s\n", regs[p->reg] | 758 ((regs[p->reg + 1] & 0x3) << 8), 759 printb8(regs[p->reg + 1], p->fmt)); 760 break; 761 762 case UTP_REGT_INT12: 763 printf("%#x\n", regs[p->reg] | 764 ((regs[p->reg + 1] & 0xf) << 8)); 765 break; 766 767 case UTP_REGT_INT16: 768 printf("%#x\n", regs[p->reg] | 769 (regs[p->reg + 1] << 8)); 770 break; 771 772 case UTP_REGT_INT19: 773 printf("%#x\n", regs[p->reg] | 774 (regs[p->reg + 1] << 8) | 775 ((regs[p->reg + 2] & 0x7) << 16)); 776 break; 777 778 case UTP_REGT_INT20: 779 printf("%#x\n", regs[p->reg] | 780 (regs[p->reg + 1] << 8) | 781 ((regs[p->reg + 2] & 0xf) << 16)); 782 break; 783 784 case UTP_REGT_INT21: 785 printf("%#x\n", regs[p->reg] | 786 (regs[p->reg + 1] << 8) | 787 ((regs[p->reg + 2] & 0x1f) << 16)); 788 break; 789 790 default: 791 abort(); 792 } 793 } 794 } 795 free(regs); 796} 797 798static void 799diag_phy_stats(int argc, char *argv[]) 800{ 801 int opt; 802 size_t len; 803 char *str; 804 struct utopia_stats1 stats1; 805 u_int foo; 806 807 static int clear; 808 809 static const struct option opts[] = { 810 { "clear", OPT_SIMPLE, &clear }, 811 { NULL, 0, NULL } 812 }; 813 814 while ((opt = parse_options(&argc, &argv, opts)) != -1) 815 switch (opt) { 816 } 817 818 if (argc != 1) 819 errx(1, "need device name for 'diag phy stats'"); 820 821 (void)diagif_get_phy(argv[0]); 822 823 if (asprintf(&str, "hw.atm.%s.phy_stats", argv[0]) == -1) 824 err(1, NULL); 825 826 len = sizeof(stats1); 827 if (sysctlbyname(str, &stats1, &len, 828 clear ? &foo : NULL, clear ? sizeof(foo) : 0)) 829 err(1, "'%s' not found", str); 830 if (len < sizeof(stats1.version)) 831 errx(1, "phy statistics too short %zu", len); 832 833 switch (stats1.version) { 834 835 case 1: 836 if (len != sizeof(stats1)) 837 errx(1, "bad phy stats length %zu (expecting %zu)", 838 len, sizeof(stats1)); 839 break; 840 841 default: 842 errx(1, "unknown phy stats version %u", stats1.version); 843 } 844 845 free(str); 846 847 printf("rx_sbip: %llu\n", (unsigned long long)stats1.rx_sbip); 848 printf("rx_lbip: %llu\n", (unsigned long long)stats1.rx_lbip); 849 printf("rx_lfebe: %llu\n", (unsigned long long)stats1.rx_lfebe); 850 printf("rx_pbip: %llu\n", (unsigned long long)stats1.rx_pbip); 851 printf("rx_pfebe: %llu\n", (unsigned long long)stats1.rx_pfebe); 852 printf("rx_cells: %llu\n", (unsigned long long)stats1.rx_cells); 853 printf("rx_corr: %llu\n", (unsigned long long)stats1.rx_corr); 854 printf("rx_uncorr: %llu\n", (unsigned long long)stats1.rx_uncorr); 855 printf("rx_symerr: %llu\n", (unsigned long long)stats1.rx_symerr); 856 printf("tx_cells: %llu\n", (unsigned long long)stats1.tx_cells); 857} 858 859/* 860 * Fetch the table of open vccs 861 */ 862void 863diagif_fetch_vcc(struct diagif *aif, int fd) 864{ 865 struct ifreq ifr; 866 867 if (aif->vtab != NULL) 868 return; 869 870 strncpy(ifr.ifr_name, aif->ifname, IFNAMSIZ); 871 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; 872 873 aif->vtab = malloc(sizeof(*aif->vtab) + sizeof(aif->vtab->vccs[0]) * 874 aif->mib.max_vccs); 875 if (aif->vtab == NULL) 876 err(1, NULL); 877 ifr.ifr_data = (caddr_t)aif->vtab; 878 879 if (ioctl(fd, SIOCATMGVCCS, &ifr) == -1) 880 err(1, "SIOCATMGVCCS"); 881} 882 883/* 884 * Print the VCC table for this interface. 885 */ 886static void 887print_channel(const struct diagif *aif) 888{ 889 const struct atmio_vcc *v; 890 891 static const char *const aal_tab[] = { 892 [ATMIO_AAL_0] = "0", 893 [ATMIO_AAL_34] = "3/4", 894 [ATMIO_AAL_5] = "5", 895 [ATMIO_AAL_RAW] = "raw", 896 }; 897 static const char *const traffic_tab[] = { 898 [ATMIO_TRAFFIC_UBR] = "ubr", 899 [ATMIO_TRAFFIC_CBR] = "cbr", 900 [ATMIO_TRAFFIC_ABR] = "abr", 901 [ATMIO_TRAFFIC_VBR] = "vbr", 902 }; 903 904 for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) { 905 printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname, 906 v->vpi, v->vci); 907 908 if (v->aal >= sizeof(aal_tab)/sizeof(aal_tab[0]) || 909 aal_tab[v->aal] == NULL) 910 printf("bad "); 911 else 912 printf("%-4s", aal_tab[v->aal]); 913 914 if (v->traffic >= sizeof(traffic_tab)/sizeof(traffic_tab[0]) || 915 traffic_tab[v->traffic] == NULL) 916 printf("bad "); 917 else 918 printf("%-8s", traffic_tab[v->traffic]); 919 920 printf("%-6u%-6u%s\n", v->rmtu, v->tmtu, 921 printb(v->flags, ATMIO_FLAGS)); 922 } 923} 924 925/* 926 * Print the VCC table for this interface, traffic parameters. 927 */ 928static void 929print_traffic(const struct diagif *aif) 930{ 931 const struct atmio_vcc *v; 932 933 for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) { 934 printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname, 935 v->vpi, v->vci); 936 937 switch (v->traffic) { 938 939 case ATMIO_TRAFFIC_CBR: 940 printf("%u", v->tparam.pcr); 941 break; 942 943 case ATMIO_TRAFFIC_UBR: 944 printf("%-8u %u", v->tparam.pcr, 945 v->tparam.mcr); 946 break; 947 948 case ATMIO_TRAFFIC_VBR: 949 printf("%-8u%-8u%-8u", v->tparam.pcr, v->tparam.scr, 950 v->tparam.mbs); 951 break; 952 953 case ATMIO_TRAFFIC_ABR: 954 printf("%-8u %-8u", 955 v->tparam.pcr, v->tparam.mcr); 956 break; 957 } 958 printf("\n"); 959 } 960} 961 962/* 963 * Print the VCC table for this interface, ABR traffic parameters. 964 */ 965static void 966print_abr(const struct diagif *aif) 967{ 968 const struct atmio_vcc *v; 969 970 for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) { 971 printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname, 972 v->vpi, v->vci); 973 974 if (v->traffic == ATMIO_TRAFFIC_ABR) { 975 printf("%-8u%-8u%-4u%-4u%-5u%-5u%-5u%u", 976 v->tparam.icr, v->tparam.tbe, v->tparam.nrm, 977 v->tparam.trm, v->tparam.adtf, v->tparam.rif, 978 v->tparam.rdf, v->tparam.cdf); 979 } 980 printf("\n"); 981 } 982} 983 984static void 985diag_vcc_loop(void (*func)(const struct diagif *), const char *text, 986 int argc, char *argv[], int fd) 987{ 988 struct diagif *aif; 989 990 heading_init(); 991 if (argc == 0) { 992 TAILQ_FOREACH(aif, &diagif_list, link) { 993 diagif_fetch_vcc(aif, fd); 994 if (aif->vtab->count != 0) { 995 heading("%s", text); 996 (*func)(aif); 997 } 998 } 999 1000 } else { 1001 for (optind = 0; optind < argc; optind++) { 1002 TAILQ_FOREACH(aif, &diagif_list, link) 1003 if (strcmp(aif->ifname, argv[optind]) == 0) { 1004 diagif_fetch_vcc(aif, fd); 1005 if (aif->vtab->count != 0) { 1006 heading("%s", text); 1007 (*func)(aif); 1008 } 1009 break; 1010 } 1011 if (aif == NULL) 1012 warnx("no such interface '%s'", argv[optind]); 1013 } 1014 } 1015} 1016 1017static void 1018diag_vcc(int argc, char *argv[]) 1019{ 1020 int opt, fd; 1021 1022 static int channel, traffic, abr; 1023 static const struct option opts[] = { 1024 { "abr", OPT_SIMPLE, &abr }, 1025 { "channel", OPT_SIMPLE, &channel }, 1026 { "traffic", OPT_SIMPLE, &traffic }, 1027 { NULL, 0, NULL } 1028 }; 1029 static const char head_channel[] = 1030 "Interface\n" 1031 "Index Name VPI VCI AAL Traffic RxMTU TxMTU Flags\n"; 1032 static const char head_traffic[] = 1033 "Interface Traffic parameters\n" 1034 "Index Name VPI VCI PCR SCR MBS MCR\n"; 1035 static const char head_abr[] = 1036 "Interface ABR traffic parameters\n" 1037 "Index Name VPI VCI ICR TBE NRM TRM ADTF RIF RDF " 1038 "CDF\n"; 1039 1040 while ((opt = parse_options(&argc, &argv, opts)) != -1) 1041 switch (opt) { 1042 } 1043 1044 fd = socket(PF_NATM, SOCK_STREAM, PROTO_NATMAAL5); 1045 if (fd < 0) 1046 err(1, "socket"); 1047 1048 diagif_fetch(); 1049 if (TAILQ_EMPTY(&diagif_list)) 1050 errx(1, "no ATM interfaces found"); 1051 1052 if (!channel && !traffic && !abr) 1053 channel = 1; 1054 1055 if (channel) 1056 diag_vcc_loop(print_channel, head_channel, argc, argv, fd); 1057 if (traffic) 1058 diag_vcc_loop(print_traffic, head_traffic, argc, argv, fd); 1059 if (abr) 1060 diag_vcc_loop(print_abr, head_abr, argc, argv, fd); 1061} 1062 1063/* 1064 * Print driver-internal statistics 1065 */ 1066static void 1067diag_stats(int argc, char *argv[]) 1068{ 1069 int opt; 1070 char *str; 1071 size_t len; 1072 uint32_t *stats; 1073 struct diagif *aif; 1074 u_int i; 1075 1076 static const struct option opts[] = { 1077 { NULL, 0, NULL } 1078 }; 1079 1080 while ((opt = parse_options(&argc, &argv, opts)) != -1) 1081 switch (opt) { 1082 } 1083 1084 if (argc != 1) 1085 errx(1, "need one arg for 'diag stats'"); 1086 1087 diagif_fetch(); 1088 TAILQ_FOREACH(aif, &diagif_list, link) 1089 if (strcmp(aif->ifname, argv[0]) == 0) 1090 break; 1091 1092 if (aif == NULL) 1093 errx(1, "interface '%s' not found", argv[0]); 1094 1095 if (asprintf(&str, "hw.atm.%s.istats", argv[0]) == -1) 1096 err(1, NULL); 1097 len = 0; 1098 if (sysctlbyname(str, NULL, &len, NULL, 0)) 1099 err(1, "'%s' not found", str); 1100 1101 stats = malloc(len); 1102 if (stats == NULL) 1103 err(1, NULL); 1104 1105 if (sysctlbyname(str, stats, &len, NULL, 0)) 1106 err(1, "'%s' not found", str); 1107 free(str); 1108 1109 if (aif->mib.device >= sizeof(print_stats) / sizeof(print_stats[0]) || 1110 print_stats[aif->mib.device] == NULL) 1111 errx(1, "unknown stats format (%u)", aif->mib.device); 1112 1113 for (i = 0; print_stats[aif->mib.device][i] != NULL; i++) { 1114 if (i * sizeof(uint32_t) >= len) 1115 errx(1, "debug info too short (version mismatch?)"); 1116 printf("%-22s%u\n", print_stats[aif->mib.device][i], stats[i]); 1117 } 1118 free(stats); 1119 1120 if (i != len / sizeof(uint32_t)) 1121 errx(1, "debug info too long (version mismatch?)"); 1122} 1123