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
51 static void diag_list(int, char *[]);
52 static void diag_config(int, char *[]);
53 static void diag_vcc(int, char *[]);
54 static void diag_phy_show(int, char *[]);
55 static void diag_phy_set(int, char *[]);
56 static void diag_phy_print(int, char *[]);
57 static void diag_phy_stats(int, char *[]);
58 static void diag_stats(int, char *[]);
59
60 static 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
68 const 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
77 static const struct utopia_print suni_lite[] = { SUNI_PRINT_LITE };
78 static const struct utopia_print suni_ultra[] = { SUNI_PRINT_ULTRA };
79 static const struct utopia_print suni_622[] = { SUNI_PRINT_622 };
80 static const struct utopia_print idt77105[] = { IDTPHY_PRINT_77105 };
81 static const struct utopia_print idt77155[] = { IDTPHY_PRINT_77155 };
82
83 static 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
100 static const u_int utopia_addreg[] = { UTP_REG_ADD };
101
102 /*
103 * Driver statistics printing
104 */
105 static 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 };
127 static 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 };
158 static 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
180 static 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 };
189 static 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 };
199 static const char *const print_stats_virtual[] = {
200 "dummy:",
201 NULL
202 };
203 static 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
221 struct diagif_list diagif_list = TAILQ_HEAD_INITIALIZER(diagif_list);
222
223 /*
224 * Fetch a phy sysctl
225 */
226 static int
phy_fetch(const char * ifname,const char * var,void * val,size_t len,int err_fatal)227 phy_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 */
247 void
diagif_fetch(void)248 diagif_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 */
316 static char *
printb8(uint32_t val,const char * descr)317 printb8(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 */
385 static char *
printb(uint32_t val,const char * descr)386 printb(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
417 static void
diag_loop(int argc,char * argv[],const char * text,void (* func)(const struct diagif *))418 diag_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 */
448 static void
config_line1(const struct diagif * aif)449 config_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
458 static void
config_line2(const struct diagif * aif)459 config_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
487 static void
diag_config(int argc,char * argv[])488 diag_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
527 static void
diag_list(int argc,char * argv[])528 diag_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 */
556 static void
phy_show_line(const struct diagif * aif)557 phy_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
566 static void
diag_phy_show(int argc,char * argv[])567 diag_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 */
593 static struct diagif *
diagif_get_phy(const char * arg)594 diagif_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
610 static void
diag_phy_set(int argc,char * argv[])611 diag_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
671 static void
diag_phy_print(int argc,char * argv[])672 diag_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
798 static void
diag_phy_stats(int argc,char * argv[])799 diag_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 */
862 void
diagif_fetch_vcc(struct diagif * aif,int fd)863 diagif_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 */
886 static void
print_channel(const struct diagif * aif)887 print_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 */
928 static void
print_traffic(const struct diagif * aif)929 print_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 */
965 static void
print_abr(const struct diagif * aif)966 print_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
984 static void
diag_vcc_loop(void (* func)(const struct diagif *),const char * text,int argc,char * argv[],int fd)985 diag_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
1017 static void
diag_vcc(int argc,char * argv[])1018 diag_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 */
1066 static void
diag_stats(int argc,char * argv[])1067 diag_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