17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <locale.h> 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <stropts.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <kstat.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <getopt.h> 407c478bd9Sstevel@tonic-gate #include <unistd.h> 417c478bd9Sstevel@tonic-gate #include <libintl.h> 427c478bd9Sstevel@tonic-gate #include <libdlpi.h> 437c478bd9Sstevel@tonic-gate #include <libdladm.h> 447c478bd9Sstevel@tonic-gate #include <liblaadm.h> 457c478bd9Sstevel@tonic-gate #include <libmacadm.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #define AGGR_DRIVER "aggr" 487c478bd9Sstevel@tonic-gate #define AGGR_DEV "aggr0" 497c478bd9Sstevel@tonic-gate #define MAXPORT 256 507c478bd9Sstevel@tonic-gate #define DUMP_LACP_FORMAT " %-9s %-8s %-7s %-12s " \ 517c478bd9Sstevel@tonic-gate "%-5s %-4s %-4s %-9s %-7s\n" 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate typedef struct pktsum_s { 547c478bd9Sstevel@tonic-gate uint64_t ipackets; 557c478bd9Sstevel@tonic-gate uint64_t opackets; 567c478bd9Sstevel@tonic-gate uint64_t rbytes; 577c478bd9Sstevel@tonic-gate uint64_t obytes; 587c478bd9Sstevel@tonic-gate uint32_t ierrors; 597c478bd9Sstevel@tonic-gate uint32_t oerrors; 607c478bd9Sstevel@tonic-gate } pktsum_t; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate typedef struct show_link_state { 637c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 647c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 657c478bd9Sstevel@tonic-gate boolean_t ls_stats; 667c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 677c478bd9Sstevel@tonic-gate boolean_t ls_parseable; 687c478bd9Sstevel@tonic-gate } show_link_state_t; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 717c478bd9Sstevel@tonic-gate uint32_t gs_key; 727c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 737c478bd9Sstevel@tonic-gate boolean_t gs_found; 747c478bd9Sstevel@tonic-gate boolean_t gs_stats; 757c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 767c478bd9Sstevel@tonic-gate pktsum_t gs_prevstats[MAXPORT]; 777c478bd9Sstevel@tonic-gate boolean_t gs_parseable; 787c478bd9Sstevel@tonic-gate } show_grp_state_t; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate typedef struct show_mac_state { 817c478bd9Sstevel@tonic-gate boolean_t ms_firstonly; 827c478bd9Sstevel@tonic-gate boolean_t ms_donefirst; 837c478bd9Sstevel@tonic-gate pktsum_t ms_prevstats; 847c478bd9Sstevel@tonic-gate boolean_t ms_parseable; 857c478bd9Sstevel@tonic-gate } show_mac_state_t; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate typedef struct port_state { 887c478bd9Sstevel@tonic-gate char *state_name; 897c478bd9Sstevel@tonic-gate aggr_port_state_t state_num; 907c478bd9Sstevel@tonic-gate } port_state_t; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate static port_state_t port_states[] = { 937c478bd9Sstevel@tonic-gate {"standby", AGGR_PORT_STATE_STANDBY }, 947c478bd9Sstevel@tonic-gate {"attached", AGGR_PORT_STATE_ATTACHED } 957c478bd9Sstevel@tonic-gate }; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate #define NPORTSTATES (sizeof (port_states) / sizeof (port_state_t)) 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate static void do_show_link(int, char **); 1007c478bd9Sstevel@tonic-gate static void do_create_aggr(int, char **); 1017c478bd9Sstevel@tonic-gate static void do_delete_aggr(int, char **); 1027c478bd9Sstevel@tonic-gate static void do_add_aggr(int, char **); 1037c478bd9Sstevel@tonic-gate static void do_remove_aggr(int, char **); 1047c478bd9Sstevel@tonic-gate static void do_modify_aggr(int, char **); 1057c478bd9Sstevel@tonic-gate static void do_show_aggr(int, char **); 1067c478bd9Sstevel@tonic-gate static void do_up_aggr(int, char **); 1077c478bd9Sstevel@tonic-gate static void do_down_aggr(int, char **); 1087c478bd9Sstevel@tonic-gate static void do_show_dev(int, char **); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static void link_stats(const char *, uint32_t); 1117c478bd9Sstevel@tonic-gate static void aggr_stats(uint16_t, uint32_t); 1127c478bd9Sstevel@tonic-gate static void dev_stats(const char *dev, uint32_t); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static void get_mac_stats(const char *, uint_t, pktsum_t *); 1157c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 1167c478bd9Sstevel@tonic-gate static uint64_t mac_ifspeed(const char *, uint_t); 1177c478bd9Sstevel@tonic-gate static char *mac_link_state(const char *, uint_t); 1187c478bd9Sstevel@tonic-gate static char *mac_link_duplex(const char *, uint_t); 1197c478bd9Sstevel@tonic-gate static void stats_total(pktsum_t *, pktsum_t *, pktsum_t *); 1207c478bd9Sstevel@tonic-gate static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *); 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate typedef struct cmd { 1237c478bd9Sstevel@tonic-gate char *c_name; 1247c478bd9Sstevel@tonic-gate void (*c_fn)(int, char **); 1257c478bd9Sstevel@tonic-gate } cmd_t; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 1287c478bd9Sstevel@tonic-gate { "show-link", do_show_link }, 129*210db224Sericheng { "show-dev", do_show_dev }, 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate { "create-aggr", do_create_aggr }, 1327c478bd9Sstevel@tonic-gate { "delete-aggr", do_delete_aggr }, 1337c478bd9Sstevel@tonic-gate { "add-aggr", do_add_aggr }, 1347c478bd9Sstevel@tonic-gate { "remove-aggr", do_remove_aggr }, 1357c478bd9Sstevel@tonic-gate { "modify-aggr", do_modify_aggr }, 1367c478bd9Sstevel@tonic-gate { "show-aggr", do_show_aggr }, 1377c478bd9Sstevel@tonic-gate { "up-aggr", do_up_aggr }, 138*210db224Sericheng { "down-aggr", do_down_aggr } 1397c478bd9Sstevel@tonic-gate }; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate static const struct option longopts[] = { 1427c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 1437c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 1447c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 1457c478bd9Sstevel@tonic-gate {"lacp-mode", required_argument, 0, 'l'}, 1467c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 1477c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 1487c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 1497c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 1507c478bd9Sstevel@tonic-gate {"lacp", no_argument, 0, 'L'}, 1517c478bd9Sstevel@tonic-gate {"temporary", no_argument, 0, 't'}, 1527c478bd9Sstevel@tonic-gate {"root-dir", required_argument, 0, 'r'}, 1537c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 1547c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 1557c478bd9Sstevel@tonic-gate }; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate static char *progname; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate #define PRINT_ERR_DIAG(s, diag, func) { \ 1607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(s), progname, strerror(errno)); \ 1617c478bd9Sstevel@tonic-gate if (diag != 0) \ 1627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", func(diag)); \ 1637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); \ 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static void 1677c478bd9Sstevel@tonic-gate usage(void) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 170*210db224Sericheng "usage: dladm create-aggr [-t] [-R <root-dir>] [-P <policy>]\n" 1717c478bd9Sstevel@tonic-gate " [-l <mode>] [-T <time>]\n" 1727c478bd9Sstevel@tonic-gate " [-u <address>] -d <dev> ... <key>\n" 1737c478bd9Sstevel@tonic-gate " delete-aggr [-t] [-R <root-dir>] <key>\n" 1747c478bd9Sstevel@tonic-gate " add-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n" 1757c478bd9Sstevel@tonic-gate " remove-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n" 1767c478bd9Sstevel@tonic-gate " modify-aggr [-t] [-R <root-dir>] [-P <policy>]\n" 1777c478bd9Sstevel@tonic-gate " [-l <mode>] [-T <time>] [-u <address>] <key>\n" 1787c478bd9Sstevel@tonic-gate " show-aggr [-L] [-s] [-i <interval>] [-p] [<key>]\n" 1797c478bd9Sstevel@tonic-gate " show-dev [-s] [-i <interval>] [-p] [<dev>]\n" 1807c478bd9Sstevel@tonic-gate " show-link [-s] [-i <interval>] [-p] [<name>]\n")); 1817c478bd9Sstevel@tonic-gate exit(1); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate int 1857c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 1867c478bd9Sstevel@tonic-gate { 1877c478bd9Sstevel@tonic-gate int i; 1887c478bd9Sstevel@tonic-gate cmd_t *cmdp; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1917c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 1927c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1937c478bd9Sstevel@tonic-gate #endif 1947c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate progname = argv[0]; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate if (argc < 2) 1997c478bd9Sstevel@tonic-gate usage(); 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 2027c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 2037c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 2047c478bd9Sstevel@tonic-gate cmdp->c_fn(argc - 1, &argv[1]); 2057c478bd9Sstevel@tonic-gate exit(0); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 2107c478bd9Sstevel@tonic-gate progname, argv[1]); 2117c478bd9Sstevel@tonic-gate usage(); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate return (0); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate static void 2187c478bd9Sstevel@tonic-gate do_create_aggr(int argc, char *argv[]) 2197c478bd9Sstevel@tonic-gate { 2207c478bd9Sstevel@tonic-gate char option; 2217c478bd9Sstevel@tonic-gate uint16_t key; 2227c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 2237c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 2247c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 2257c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 2267c478bd9Sstevel@tonic-gate uint_t nport = 0; 2277c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 2287c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 2297c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 2307c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 2317c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 2327c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 2337c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 2347c478bd9Sstevel@tonic-gate char *altroot = NULL; 2357c478bd9Sstevel@tonic-gate char *endp = NULL; 2367c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate opterr = 0; 2397c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:l:P:R:tu:T:", 2407c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 2417c478bd9Sstevel@tonic-gate switch (option) { 2427c478bd9Sstevel@tonic-gate case 'd': 2437c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 2447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2457c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 2467c478bd9Sstevel@tonic-gate progname); 2477c478bd9Sstevel@tonic-gate exit(1); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 2517c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 2527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2537c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 2547c478bd9Sstevel@tonic-gate progname); 2557c478bd9Sstevel@tonic-gate exit(1); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate port[nport].lp_port = 0; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate nport++; 2617c478bd9Sstevel@tonic-gate break; 2627c478bd9Sstevel@tonic-gate case 'P': 2637c478bd9Sstevel@tonic-gate if (P_arg) { 2647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2657c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 2667c478bd9Sstevel@tonic-gate "more than once\n"), progname); 2677c478bd9Sstevel@tonic-gate usage(); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 2737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2747c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 2757c478bd9Sstevel@tonic-gate progname, optarg); 2767c478bd9Sstevel@tonic-gate exit(1); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate break; 2797c478bd9Sstevel@tonic-gate case 'u': 2807c478bd9Sstevel@tonic-gate if (u_arg) { 2817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2827c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 2837c478bd9Sstevel@tonic-gate "more than once\n"), progname); 2847c478bd9Sstevel@tonic-gate usage(); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 2907c478bd9Sstevel@tonic-gate mac_addr)) { 2917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2927c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 2937c478bd9Sstevel@tonic-gate progname, optarg); 2947c478bd9Sstevel@tonic-gate exit(1); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate case 'l': 2997c478bd9Sstevel@tonic-gate if (l_arg) { 3007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3017c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 3027c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3037c478bd9Sstevel@tonic-gate usage(); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 3097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3107c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 3117c478bd9Sstevel@tonic-gate progname, optarg); 3127c478bd9Sstevel@tonic-gate exit(1); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate break; 3167c478bd9Sstevel@tonic-gate case 'T': 3177c478bd9Sstevel@tonic-gate if (T_arg) { 3187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3197c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 3207c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3217c478bd9Sstevel@tonic-gate usage(); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 3277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3287c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 3297c478bd9Sstevel@tonic-gate " '%s'\n"), 3307c478bd9Sstevel@tonic-gate progname, optarg); 3317c478bd9Sstevel@tonic-gate exit(1); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate break; 3357c478bd9Sstevel@tonic-gate case 't': 3367c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 3377c478bd9Sstevel@tonic-gate break; 3387c478bd9Sstevel@tonic-gate case 'R': 3397c478bd9Sstevel@tonic-gate altroot = optarg; 3407c478bd9Sstevel@tonic-gate break; 3417c478bd9Sstevel@tonic-gate case ':': 3427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3437c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 3447c478bd9Sstevel@tonic-gate progname, optopt); 3457c478bd9Sstevel@tonic-gate exit(1); 3467c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3477c478bd9Sstevel@tonic-gate case '?': 3487c478bd9Sstevel@tonic-gate default: 3497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3507c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 3517c478bd9Sstevel@tonic-gate progname, optopt); 3527c478bd9Sstevel@tonic-gate exit(1); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate if (nport == 0) 3577c478bd9Sstevel@tonic-gate usage(); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 3607c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 3617c478bd9Sstevel@tonic-gate usage(); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate errno = 0; 3647c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 3657c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 3667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3677c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 3687c478bd9Sstevel@tonic-gate progname, key); 3697c478bd9Sstevel@tonic-gate exit(1); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate if (laadm_create(key, nport, port, policy, mac_addr_fixed, 3737c478bd9Sstevel@tonic-gate mac_addr, lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 3747c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: create operation failed: %s", diag, 3757c478bd9Sstevel@tonic-gate laadm_diag); 3767c478bd9Sstevel@tonic-gate exit(1); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate static void 3817c478bd9Sstevel@tonic-gate do_delete_aggr(int argc, char *argv[]) 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate uint16_t key; 3847c478bd9Sstevel@tonic-gate char option; 3857c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 3867c478bd9Sstevel@tonic-gate char *altroot = NULL; 3877c478bd9Sstevel@tonic-gate char *endp = NULL; 3887c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate opterr = 0; 3917c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":R:t", longopts, 3927c478bd9Sstevel@tonic-gate NULL)) != -1) { 3937c478bd9Sstevel@tonic-gate switch (option) { 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate case 't': 3967c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 3977c478bd9Sstevel@tonic-gate break; 3987c478bd9Sstevel@tonic-gate case 'R': 3997c478bd9Sstevel@tonic-gate altroot = optarg; 4007c478bd9Sstevel@tonic-gate break; 4017c478bd9Sstevel@tonic-gate case ':': 4027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4037c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 4047c478bd9Sstevel@tonic-gate progname, optopt); 4057c478bd9Sstevel@tonic-gate exit(1); 4067c478bd9Sstevel@tonic-gate break; 4077c478bd9Sstevel@tonic-gate case '?': 4087c478bd9Sstevel@tonic-gate default: 4097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4107c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 4117c478bd9Sstevel@tonic-gate progname, optopt); 4127c478bd9Sstevel@tonic-gate exit(1); 4137c478bd9Sstevel@tonic-gate break; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 4187c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 4197c478bd9Sstevel@tonic-gate usage(); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate errno = 0; 4227c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 4237c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 4247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4257c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 4267c478bd9Sstevel@tonic-gate progname, key); 4277c478bd9Sstevel@tonic-gate exit(1); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (laadm_delete(key, t_arg, altroot, &diag) < 0) { 4317c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: delete operation failed: %s", diag, 4327c478bd9Sstevel@tonic-gate laadm_diag); 4337c478bd9Sstevel@tonic-gate exit(1); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate static void 4387c478bd9Sstevel@tonic-gate do_add_aggr(int argc, char *argv[]) 4397c478bd9Sstevel@tonic-gate { 4407c478bd9Sstevel@tonic-gate char option; 4417c478bd9Sstevel@tonic-gate uint16_t key; 4427c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 4437c478bd9Sstevel@tonic-gate uint_t nport = 0; 4447c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 4457c478bd9Sstevel@tonic-gate char *altroot = NULL; 4467c478bd9Sstevel@tonic-gate char *endp = NULL; 4477c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate opterr = 0; 4507c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", longopts, 4517c478bd9Sstevel@tonic-gate NULL)) != -1) { 4527c478bd9Sstevel@tonic-gate switch (option) { 4537c478bd9Sstevel@tonic-gate case 'd': 4547c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 4557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4567c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 4577c478bd9Sstevel@tonic-gate progname); 4587c478bd9Sstevel@tonic-gate exit(1); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 4627c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 4637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4647c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 4657c478bd9Sstevel@tonic-gate progname); 4667c478bd9Sstevel@tonic-gate exit(1); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate port[nport].lp_port = 0; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate nport++; 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate case 't': 4737c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 4747c478bd9Sstevel@tonic-gate break; 4757c478bd9Sstevel@tonic-gate case 'R': 4767c478bd9Sstevel@tonic-gate altroot = optarg; 4777c478bd9Sstevel@tonic-gate break; 4787c478bd9Sstevel@tonic-gate case ':': 4797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4807c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 4817c478bd9Sstevel@tonic-gate progname, optopt); 4827c478bd9Sstevel@tonic-gate exit(1); 4837c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4847c478bd9Sstevel@tonic-gate case '?': 4857c478bd9Sstevel@tonic-gate default: 4867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4877c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 4887c478bd9Sstevel@tonic-gate progname, optopt); 4897c478bd9Sstevel@tonic-gate exit(1); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate if (nport == 0) 4947c478bd9Sstevel@tonic-gate usage(); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 4977c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 4987c478bd9Sstevel@tonic-gate usage(); 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate errno = 0; 5017c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 5027c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 5037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5047c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 5057c478bd9Sstevel@tonic-gate progname, key); 5067c478bd9Sstevel@tonic-gate exit(1); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if (laadm_add(key, nport, port, t_arg, altroot, &diag) < 0) { 5107c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: add operation failed: %s", diag, 5117c478bd9Sstevel@tonic-gate laadm_diag); 5127c478bd9Sstevel@tonic-gate exit(1); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate static void 5177c478bd9Sstevel@tonic-gate do_remove_aggr(int argc, char *argv[]) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate char option; 5207c478bd9Sstevel@tonic-gate uint16_t key; 5217c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 5227c478bd9Sstevel@tonic-gate uint_t nport = 0; 5237c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 5247c478bd9Sstevel@tonic-gate char *altroot = NULL; 5257c478bd9Sstevel@tonic-gate char *endp = NULL; 5267c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate opterr = 0; 5297c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", 5307c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 5317c478bd9Sstevel@tonic-gate switch (option) { 5327c478bd9Sstevel@tonic-gate case 'd': 5337c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 5347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5357c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 5367c478bd9Sstevel@tonic-gate progname); 5377c478bd9Sstevel@tonic-gate exit(1); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 5417c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 5427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5437c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 5447c478bd9Sstevel@tonic-gate progname); 5457c478bd9Sstevel@tonic-gate exit(1); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate port[nport].lp_port = 0; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate nport++; 5507c478bd9Sstevel@tonic-gate break; 5517c478bd9Sstevel@tonic-gate case 't': 5527c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 5537c478bd9Sstevel@tonic-gate break; 5547c478bd9Sstevel@tonic-gate case 'R': 5557c478bd9Sstevel@tonic-gate altroot = optarg; 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate case ':': 5587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5597c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 5607c478bd9Sstevel@tonic-gate progname, optopt); 5617c478bd9Sstevel@tonic-gate exit(1); 5627c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 5637c478bd9Sstevel@tonic-gate case '?': 5647c478bd9Sstevel@tonic-gate default: 5657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5667c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 5677c478bd9Sstevel@tonic-gate progname, optopt); 5687c478bd9Sstevel@tonic-gate exit(1); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate if (nport == 0) 5737c478bd9Sstevel@tonic-gate usage(); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 5767c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 5777c478bd9Sstevel@tonic-gate usage(); 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate errno = 0; 5807c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 5817c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 5827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5837c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 5847c478bd9Sstevel@tonic-gate progname, key); 5857c478bd9Sstevel@tonic-gate exit(1); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate if (laadm_remove(key, nport, port, t_arg, altroot, &diag) < 0) { 5897c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: remove operation failed: %s", diag, 5907c478bd9Sstevel@tonic-gate laadm_diag); 5917c478bd9Sstevel@tonic-gate exit(1); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate static void 5967c478bd9Sstevel@tonic-gate do_modify_aggr(int argc, char *argv[]) 5977c478bd9Sstevel@tonic-gate { 5987c478bd9Sstevel@tonic-gate char option; 5997c478bd9Sstevel@tonic-gate uint16_t key; 6007c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 6017c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 6027c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 6037c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 6047c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 6057c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 6067c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 6077c478bd9Sstevel@tonic-gate char *altroot = NULL; 6087c478bd9Sstevel@tonic-gate char *endp = NULL; 6097c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate opterr = 0; 6127c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":l:P:R:tu:T:", longopts, 6137c478bd9Sstevel@tonic-gate NULL)) != -1) { 6147c478bd9Sstevel@tonic-gate switch (option) { 6157c478bd9Sstevel@tonic-gate case 'P': 6167c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_POLICY) { 6177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6187c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 6197c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6207c478bd9Sstevel@tonic-gate usage(); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_POLICY; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 6267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6277c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 6287c478bd9Sstevel@tonic-gate progname, optarg); 6297c478bd9Sstevel@tonic-gate exit(1); 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate case 'u': 6337c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_MAC) { 6347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6357c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 6367c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6377c478bd9Sstevel@tonic-gate usage(); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_MAC; 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 6437c478bd9Sstevel@tonic-gate mac_addr)) { 6447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6457c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 6467c478bd9Sstevel@tonic-gate progname, optarg); 6477c478bd9Sstevel@tonic-gate exit(1); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate break; 6517c478bd9Sstevel@tonic-gate case 'l': 6527c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_MODE) { 6537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6547c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 6557c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6567c478bd9Sstevel@tonic-gate usage(); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_MODE; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 6627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6637c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 6647c478bd9Sstevel@tonic-gate progname, optarg); 6657c478bd9Sstevel@tonic-gate exit(1); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate case 'T': 6707c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_TIMER) { 6717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6727c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 6737c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6747c478bd9Sstevel@tonic-gate usage(); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_TIMER; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 6807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6817c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 6827c478bd9Sstevel@tonic-gate " '%s'\n"), 6837c478bd9Sstevel@tonic-gate progname, optarg); 6847c478bd9Sstevel@tonic-gate exit(1); 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate break; 6887c478bd9Sstevel@tonic-gate case 't': 6897c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 6907c478bd9Sstevel@tonic-gate break; 6917c478bd9Sstevel@tonic-gate case 'R': 6927c478bd9Sstevel@tonic-gate altroot = optarg; 6937c478bd9Sstevel@tonic-gate break; 6947c478bd9Sstevel@tonic-gate case ':': 6957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6967c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 6977c478bd9Sstevel@tonic-gate progname, optopt); 6987c478bd9Sstevel@tonic-gate exit(1); 6997c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 7007c478bd9Sstevel@tonic-gate case '?': 7017c478bd9Sstevel@tonic-gate default: 7027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7037c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 7047c478bd9Sstevel@tonic-gate progname, optopt); 7057c478bd9Sstevel@tonic-gate exit(1); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if (modify_mask == 0) { 7107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: at least one of the " 7117c478bd9Sstevel@tonic-gate "-PulT options must be specified\n"), progname); 7127c478bd9Sstevel@tonic-gate usage(); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 7167c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 7177c478bd9Sstevel@tonic-gate usage(); 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate errno = 0; 7207c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 7217c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 7227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7237c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 7247c478bd9Sstevel@tonic-gate progname, key); 7257c478bd9Sstevel@tonic-gate exit(1); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate if (laadm_modify(key, modify_mask, policy, mac_addr_fixed, mac_addr, 7307c478bd9Sstevel@tonic-gate lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 7317c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: modify operation failed: %s", diag, 7327c478bd9Sstevel@tonic-gate laadm_diag); 7337c478bd9Sstevel@tonic-gate exit(1); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate static void 7387c478bd9Sstevel@tonic-gate do_up_aggr(int argc, char *argv[]) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate uint16_t key = 0; 7417c478bd9Sstevel@tonic-gate char *endp = NULL; 7427c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 7457c478bd9Sstevel@tonic-gate if (argc == 2) { 7467c478bd9Sstevel@tonic-gate errno = 0; 7477c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 7487c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 7497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7507c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 7517c478bd9Sstevel@tonic-gate progname, key); 7527c478bd9Sstevel@tonic-gate exit(1); 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate } else if (argc > 2) { 7557c478bd9Sstevel@tonic-gate usage(); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (laadm_up(key, NULL, &diag) < 0) { 7597c478bd9Sstevel@tonic-gate if (key != 0) { 7607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7617c478bd9Sstevel@tonic-gate gettext("%s: could not bring up aggregation" 7627c478bd9Sstevel@tonic-gate " '%u' : %s"), progname, key, strerror(errno)); 7637c478bd9Sstevel@tonic-gate if (diag != 0) 7647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", 7657c478bd9Sstevel@tonic-gate laadm_diag(diag)); 7667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 7677c478bd9Sstevel@tonic-gate } else { 7687c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG( 7697c478bd9Sstevel@tonic-gate "%s: could not bring aggregations up: %s", 7707c478bd9Sstevel@tonic-gate diag, laadm_diag); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate exit(1); 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate static void 7777c478bd9Sstevel@tonic-gate do_down_aggr(int argc, char *argv[]) 7787c478bd9Sstevel@tonic-gate { 7797c478bd9Sstevel@tonic-gate uint16_t key = 0; 7807c478bd9Sstevel@tonic-gate char *endp = NULL; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 7837c478bd9Sstevel@tonic-gate if (argc == 2) { 7847c478bd9Sstevel@tonic-gate errno = 0; 7857c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 7867c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 7877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7887c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 7897c478bd9Sstevel@tonic-gate progname, key); 7907c478bd9Sstevel@tonic-gate exit(1); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate } else if (argc > 2) { 7937c478bd9Sstevel@tonic-gate usage(); 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate if (laadm_down(key) < 0) { 7977c478bd9Sstevel@tonic-gate if (key != 0) { 7987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7997c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregation" 8007c478bd9Sstevel@tonic-gate " down '%u' : %s"), 8017c478bd9Sstevel@tonic-gate progname, key, strerror(errno)); 8027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 8037c478bd9Sstevel@tonic-gate } else { 8047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8057c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregations" 8067c478bd9Sstevel@tonic-gate " down: %s"), progname, strerror(errno)); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate exit(1); 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate #define TYPE_WIDTH 10 813*210db224Sericheng 814*210db224Sericheng static void 815*210db224Sericheng print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy) 816*210db224Sericheng { 817*210db224Sericheng char type[TYPE_WIDTH]; 818*210db224Sericheng 819*210db224Sericheng if (!legacy) { 820*210db224Sericheng if (dap->da_vid != 0) { 821*210db224Sericheng (void) snprintf(type, TYPE_WIDTH, "vlan %u", 822*210db224Sericheng dap->da_vid); 823*210db224Sericheng } else { 824*210db224Sericheng (void) snprintf(type, TYPE_WIDTH, "non-vlan"); 825*210db224Sericheng } 826*210db224Sericheng if (strcmp(dap->da_dev, AGGR_DEV) == 0) { 827*210db224Sericheng (void) printf("%s type=%s mtu=%d key=%u\n", 828*210db224Sericheng name, type, dap->da_max_sdu, dap->da_port); 829*210db224Sericheng } else { 830*210db224Sericheng (void) printf("%s type=%s mtu=%d device=%s\n", 831*210db224Sericheng name, type, dap->da_max_sdu, dap->da_dev); 832*210db224Sericheng } 833*210db224Sericheng } else { 834*210db224Sericheng (void) printf("%s type=legacy mtu=%d device=%s\n", 835*210db224Sericheng name, dap->da_max_sdu, name); 836*210db224Sericheng } 837*210db224Sericheng } 838*210db224Sericheng 839*210db224Sericheng static void 840*210db224Sericheng print_link(const char *name, dladm_attr_t *dap, boolean_t legacy) 841*210db224Sericheng { 842*210db224Sericheng char type[TYPE_WIDTH]; 843*210db224Sericheng 844*210db224Sericheng if (!legacy) { 845*210db224Sericheng if (dap->da_vid != 0) { 846*210db224Sericheng (void) snprintf(type, TYPE_WIDTH, gettext("vlan %u"), 847*210db224Sericheng dap->da_vid); 848*210db224Sericheng } else { 849*210db224Sericheng (void) snprintf(type, TYPE_WIDTH, gettext("non-vlan")); 850*210db224Sericheng } 851*210db224Sericheng if (strcmp(dap->da_dev, AGGR_DEV) == 0) { 852*210db224Sericheng (void) printf(gettext("%-9s\ttype: %s\tmtu: %d" 853*210db224Sericheng "\taggregation: key %u\n"), name, type, 854*210db224Sericheng dap->da_max_sdu, dap->da_port); 855*210db224Sericheng } else { 856*210db224Sericheng (void) printf(gettext("%-9s\ttype: %s\tmtu: " 857*210db224Sericheng "%d\tdevice: %s\n"), name, type, dap->da_max_sdu, 858*210db224Sericheng dap->da_dev); 859*210db224Sericheng } 860*210db224Sericheng } else { 861*210db224Sericheng (void) printf(gettext("%-9s\ttype: legacy\tmtu: " 862*210db224Sericheng "%d\tdevice: %s\n"), name, dap->da_max_sdu, name); 863*210db224Sericheng } 864*210db224Sericheng } 865*210db224Sericheng 866*210db224Sericheng static int 867*210db224Sericheng get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy) 868*210db224Sericheng { 869*210db224Sericheng int err; 870*210db224Sericheng 871*210db224Sericheng if ((err = dladm_info(name, dlattrp)) == 0) { 872*210db224Sericheng *legacy = B_FALSE; 873*210db224Sericheng } else if (err < 0 && errno == ENODEV) { 874*210db224Sericheng int fd; 875*210db224Sericheng dlpi_if_attr_t dia; 876*210db224Sericheng dl_info_ack_t dlia; 877*210db224Sericheng 878*210db224Sericheng /* 879*210db224Sericheng * A return value of ENODEV means that the specified 880*210db224Sericheng * device is not gldv3. 881*210db224Sericheng */ 882*210db224Sericheng if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 && 883*210db224Sericheng dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, 884*210db224Sericheng NULL, NULL) != -1) { 885*210db224Sericheng (void) dlpi_close(fd); 886*210db224Sericheng 887*210db224Sericheng *legacy = B_TRUE; 888*210db224Sericheng bzero(dlattrp, sizeof (*dlattrp)); 889*210db224Sericheng dlattrp->da_max_sdu = (uint_t)dlia.dl_max_sdu; 890*210db224Sericheng } else { 891*210db224Sericheng errno = ENOENT; 892*210db224Sericheng return (-1); 893*210db224Sericheng } 894*210db224Sericheng } else { 895*210db224Sericheng /* 896*210db224Sericheng * If the return value is not ENODEV, this means that 897*210db224Sericheng * user is either passing in a bogus interface name 898*210db224Sericheng * or a vlan interface name that doesn't exist yet. 899*210db224Sericheng */ 900*210db224Sericheng errno = ENOENT; 901*210db224Sericheng return (-1); 902*210db224Sericheng } 903*210db224Sericheng return (0); 904*210db224Sericheng } 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9077c478bd9Sstevel@tonic-gate static void 9087c478bd9Sstevel@tonic-gate show_link(void *arg, const char *name) 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate dladm_attr_t dlattr; 911*210db224Sericheng boolean_t legacy = B_TRUE; 9127c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 9137c478bd9Sstevel@tonic-gate 914*210db224Sericheng if (get_if_info(name, &dlattr, &legacy) < 0) { 915*210db224Sericheng (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), 9167c478bd9Sstevel@tonic-gate progname, name); 9177c478bd9Sstevel@tonic-gate exit(1); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 920*210db224Sericheng if (state->ls_parseable) { 921*210db224Sericheng print_link_parseable(name, &dlattr, legacy); 9227c478bd9Sstevel@tonic-gate } else { 923*210db224Sericheng print_link(name, &dlattr, legacy); 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate static void 9287c478bd9Sstevel@tonic-gate show_link_stats(void *arg, const char *name) 9297c478bd9Sstevel@tonic-gate { 9307c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 9317c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 9347c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 9357c478bd9Sstevel@tonic-gate return; 9367c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 9377c478bd9Sstevel@tonic-gate } else { 9387c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate get_link_stats(name, &stats); 9427c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ls_prevstats); 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate (void) printf("%s", name); 9457c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 9467c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 9477c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 9487c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 9497c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 9507c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate static void 9567c478bd9Sstevel@tonic-gate dump_grp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate char policy_str[LAADM_POLICY_STR_LEN]; 9597c478bd9Sstevel@tonic-gate char addr_str[ETHERADDRL * 3]; 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate if (!parseable) { 9627c478bd9Sstevel@tonic-gate (void) printf(gettext("key: %d (0x%04x)"), 9637c478bd9Sstevel@tonic-gate grp->lg_key, grp->lg_key); 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate (void) printf(gettext("\tpolicy: %s"), 9667c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate (void) printf(gettext("\taddress: %s (%s)\n"), 9697c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str), 9707c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? gettext("fixed") : gettext("auto")); 9717c478bd9Sstevel@tonic-gate } else { 9727c478bd9Sstevel@tonic-gate (void) printf("aggr key=%d", grp->lg_key); 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate (void) printf(" policy=%s", 9757c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate (void) printf(" address=%s", 9787c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str)); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate (void) printf(" address-type=%s\n", 9817c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? "fixed" : "auto"); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate static void 9867c478bd9Sstevel@tonic-gate dump_grp_lacp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 9877c478bd9Sstevel@tonic-gate { 9887c478bd9Sstevel@tonic-gate const char *lacp_mode_str = laadm_lacp_mode_to_str(grp->lg_lacp_mode); 9897c478bd9Sstevel@tonic-gate const char *lacp_timer_str = 9907c478bd9Sstevel@tonic-gate laadm_lacp_timer_to_str(grp->lg_lacp_timer); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (!parseable) { 9937c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLACP mode: %s"), lacp_mode_str); 9947c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLACP timer: %s\n"), lacp_timer_str); 9957c478bd9Sstevel@tonic-gate } else { 9967c478bd9Sstevel@tonic-gate (void) printf(" lacp-mode=%s", lacp_mode_str); 9977c478bd9Sstevel@tonic-gate (void) printf(" lacp-timer=%s\n", lacp_timer_str); 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate static void 10027c478bd9Sstevel@tonic-gate dump_grp_stats(laadm_grp_attr_sys_t *grp) 10037c478bd9Sstevel@tonic-gate { 10047c478bd9Sstevel@tonic-gate (void) printf("key: %d", grp->lg_key); 10057c478bd9Sstevel@tonic-gate (void) printf("\tipackets rbytes opackets obytes "); 10067c478bd9Sstevel@tonic-gate (void) printf("%%ipkts %%opkts\n"); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate static void 10107c478bd9Sstevel@tonic-gate dump_ports_lacp_head(void) 10117c478bd9Sstevel@tonic-gate { 10127c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, gettext("device"), gettext("activity"), 10137c478bd9Sstevel@tonic-gate gettext("timeout"), gettext("aggregatable"), gettext("sync"), 10147c478bd9Sstevel@tonic-gate gettext("coll"), gettext("dist"), gettext("defaulted"), 10157c478bd9Sstevel@tonic-gate gettext("expired")); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate static void 10197c478bd9Sstevel@tonic-gate dump_ports_head(void) 10207c478bd9Sstevel@tonic-gate { 10217c478bd9Sstevel@tonic-gate (void) printf(gettext(" device\taddress\t\t speed\t\tduplex\tlink\t" 10227c478bd9Sstevel@tonic-gate "state\n")); 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate static char * 10267c478bd9Sstevel@tonic-gate port_state_to_str(aggr_port_state_t state_num) 10277c478bd9Sstevel@tonic-gate { 10287c478bd9Sstevel@tonic-gate int i; 10297c478bd9Sstevel@tonic-gate port_state_t *state; 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate for (i = 0; i < NPORTSTATES; i++) { 10327c478bd9Sstevel@tonic-gate state = &port_states[i]; 10337c478bd9Sstevel@tonic-gate if (state->state_num == state_num) 10347c478bd9Sstevel@tonic-gate return (state->state_name); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate return ("unknown"); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate static void 10417c478bd9Sstevel@tonic-gate dump_port(laadm_port_attr_sys_t *port, boolean_t parseable) 10427c478bd9Sstevel@tonic-gate { 10437c478bd9Sstevel@tonic-gate char *dev = port->lp_devname; 10447c478bd9Sstevel@tonic-gate uint_t portnum = port->lp_port; 10457c478bd9Sstevel@tonic-gate char buf[ETHERADDRL * 3]; 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate if (!parseable) { 10487c478bd9Sstevel@tonic-gate (void) printf(" %-9s\t%s", dev, laadm_mac_addr_to_str( 10497c478bd9Sstevel@tonic-gate port->lp_mac, buf)); 10507c478bd9Sstevel@tonic-gate (void) printf("\t %-5u Mbps", (int)(mac_ifspeed(dev, portnum) / 10517c478bd9Sstevel@tonic-gate 1000000ull)); 10527c478bd9Sstevel@tonic-gate (void) printf("\t%s", mac_link_duplex(dev, portnum)); 10537c478bd9Sstevel@tonic-gate (void) printf("\t%s", mac_link_state(dev, portnum)); 10547c478bd9Sstevel@tonic-gate (void) printf("\t%s\n", port_state_to_str(port->lp_state)); 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate } else { 10577c478bd9Sstevel@tonic-gate (void) printf(" device=%s address=%s", dev, 10587c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(port->lp_mac, buf)); 10597c478bd9Sstevel@tonic-gate (void) printf(" speed=%u", (int)(mac_ifspeed(dev, portnum) / 10607c478bd9Sstevel@tonic-gate 1000000ull)); 10617c478bd9Sstevel@tonic-gate (void) printf(" duplex=%s", mac_link_duplex(dev, portnum)); 10627c478bd9Sstevel@tonic-gate (void) printf(" link=%s", mac_link_state(dev, portnum)); 10637c478bd9Sstevel@tonic-gate (void) printf(" port=%s", port_state_to_str(port->lp_state)); 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate static void 10687c478bd9Sstevel@tonic-gate dump_port_lacp(laadm_port_attr_sys_t *port) 10697c478bd9Sstevel@tonic-gate { 10707c478bd9Sstevel@tonic-gate aggr_lacp_state_t *state = &port->lp_lacp_state; 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, 10737c478bd9Sstevel@tonic-gate port->lp_devname, state->bit.activity ? "active" : "passive", 10747c478bd9Sstevel@tonic-gate state->bit.timeout ? "short" : "long", 10757c478bd9Sstevel@tonic-gate state->bit.aggregation ? "yes" : "no", 10767c478bd9Sstevel@tonic-gate state->bit.sync ? "yes" : "no", 10777c478bd9Sstevel@tonic-gate state->bit.collecting ? "yes" : "no", 10787c478bd9Sstevel@tonic-gate state->bit.distributing ? "yes" : "no", 10797c478bd9Sstevel@tonic-gate state->bit.defaulted ? "yes" : "no", 10807c478bd9Sstevel@tonic-gate state->bit.expired ? "yes" : "no"); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate static void 10847c478bd9Sstevel@tonic-gate dump_port_stat(int index, show_grp_state_t *state, pktsum_t *port_stats, 10857c478bd9Sstevel@tonic-gate pktsum_t *tot_stats) 10867c478bd9Sstevel@tonic-gate { 10877c478bd9Sstevel@tonic-gate pktsum_t diff_stats; 10887c478bd9Sstevel@tonic-gate pktsum_t *old_stats = &state->gs_prevstats[index]; 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, port_stats, old_stats); 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", diff_stats.ipackets); 10937c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 10947c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 10957c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate if (tot_stats->ipackets == 0) 10987c478bd9Sstevel@tonic-gate (void) printf("\t-"); 10997c478bd9Sstevel@tonic-gate else 11007c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 11017c478bd9Sstevel@tonic-gate (double)tot_stats->ipackets * 100); 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate if (tot_stats->opackets == 0) 11047c478bd9Sstevel@tonic-gate (void) printf("\t-"); 11057c478bd9Sstevel@tonic-gate else 11067c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 11077c478bd9Sstevel@tonic-gate (double)tot_stats->opackets * 100); 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate (void) printf("\n"); 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate *old_stats = *port_stats; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate static int 11157c478bd9Sstevel@tonic-gate show_key(void *arg, laadm_grp_attr_sys_t *grp) 11167c478bd9Sstevel@tonic-gate { 11177c478bd9Sstevel@tonic-gate show_grp_state_t *state = (show_grp_state_t *)arg; 11187c478bd9Sstevel@tonic-gate int i; 11197c478bd9Sstevel@tonic-gate pktsum_t pktsumtot, port_stat; 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate if (state->gs_key != 0 && state->gs_key != grp->lg_key) 11227c478bd9Sstevel@tonic-gate return (0); 11237c478bd9Sstevel@tonic-gate if (state->gs_firstonly) { 11247c478bd9Sstevel@tonic-gate if (state->gs_found) 11257c478bd9Sstevel@tonic-gate return (0); 11267c478bd9Sstevel@tonic-gate } else { 11277c478bd9Sstevel@tonic-gate bzero(&state->gs_prevstats, sizeof (state->gs_prevstats)); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate state->gs_found = B_TRUE; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate if (state->gs_stats) { 11337c478bd9Sstevel@tonic-gate /* show statistics */ 11347c478bd9Sstevel@tonic-gate dump_grp_stats(grp); 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 11377c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 11387c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 11397c478bd9Sstevel@tonic-gate get_mac_stats(grp->lg_ports[i].lp_devname, 11407c478bd9Sstevel@tonic-gate grp->lg_ports[i].lp_port, &port_stat); 11417c478bd9Sstevel@tonic-gate stats_total(&pktsumtot, &port_stat, 11427c478bd9Sstevel@tonic-gate &state->gs_prevstats[i]); 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate (void) printf(" Total"); 11467c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", pktsumtot.ipackets); 11477c478bd9Sstevel@tonic-gate (void) printf("%-12llu", pktsumtot.rbytes); 11487c478bd9Sstevel@tonic-gate (void) printf("%-10llu", pktsumtot.opackets); 11497c478bd9Sstevel@tonic-gate (void) printf("%-12llu\n", pktsumtot.obytes); 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 11527c478bd9Sstevel@tonic-gate get_mac_stats(grp->lg_ports[i].lp_devname, 11537c478bd9Sstevel@tonic-gate grp->lg_ports[i].lp_port, &port_stat); 11547c478bd9Sstevel@tonic-gate (void) printf(" %s", grp->lg_ports[i].lp_devname); 11557c478bd9Sstevel@tonic-gate dump_port_stat(i, state, &port_stat, &pktsumtot); 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate } else if (state->gs_lacp) { 11587c478bd9Sstevel@tonic-gate /* show LACP info */ 11597c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 11607c478bd9Sstevel@tonic-gate dump_grp_lacp(grp, state->gs_parseable); 11617c478bd9Sstevel@tonic-gate dump_ports_lacp_head(); 11627c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) 11637c478bd9Sstevel@tonic-gate dump_port_lacp(&grp->lg_ports[i]); 11647c478bd9Sstevel@tonic-gate } else { 11657c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 11667c478bd9Sstevel@tonic-gate if (!state->gs_parseable) 11677c478bd9Sstevel@tonic-gate dump_ports_head(); 11687c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 11697c478bd9Sstevel@tonic-gate if (state->gs_parseable) 11707c478bd9Sstevel@tonic-gate (void) printf("dev key=%d", grp->lg_key); 11717c478bd9Sstevel@tonic-gate dump_port(&grp->lg_ports[i], state->gs_parseable); 11727c478bd9Sstevel@tonic-gate if (state->gs_parseable) 11737c478bd9Sstevel@tonic-gate (void) printf("\n"); 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate return (0); 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate static int 11817c478bd9Sstevel@tonic-gate kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf) 11827c478bd9Sstevel@tonic-gate { 11837c478bd9Sstevel@tonic-gate kstat_named_t *knp; 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL) 11867c478bd9Sstevel@tonic-gate return (-1); 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate if (knp->data_type != type) 11897c478bd9Sstevel@tonic-gate return (-1); 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate switch (type) { 11927c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT64: 11937c478bd9Sstevel@tonic-gate *(uint64_t *)buf = knp->value.ui64; 11947c478bd9Sstevel@tonic-gate break; 11957c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT32: 11967c478bd9Sstevel@tonic-gate *(uint32_t *)buf = knp->value.ui32; 11977c478bd9Sstevel@tonic-gate break; 11987c478bd9Sstevel@tonic-gate default: 11997c478bd9Sstevel@tonic-gate return (-1); 12007c478bd9Sstevel@tonic-gate } 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate return (0); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate static void 1206*210db224Sericheng show_dev(void *arg, const char *dev) 12077c478bd9Sstevel@tonic-gate { 12087c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate /* aggregations are already managed by a set of subcommands */ 12117c478bd9Sstevel@tonic-gate if (strcmp(dev, AGGR_DEV) == 0) 12127c478bd9Sstevel@tonic-gate return; 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate if (!state->ms_parseable) { 12177c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tlink: %s"), 1218*210db224Sericheng mac_link_state(dev, 0)); 12197c478bd9Sstevel@tonic-gate (void) printf(gettext("\tspeed: %-5u Mbps"), 1220*210db224Sericheng (unsigned int)(mac_ifspeed(dev, 0) / 1000000ull)); 12217c478bd9Sstevel@tonic-gate (void) printf(gettext("\tduplex: %s\n"), 1222*210db224Sericheng mac_link_duplex(dev, 0)); 12237c478bd9Sstevel@tonic-gate } else { 1224*210db224Sericheng (void) printf(" link=%s", mac_link_state(dev, 0)); 12257c478bd9Sstevel@tonic-gate (void) printf(" speed=%u", 1226*210db224Sericheng (unsigned int)(mac_ifspeed(dev, 0) / 1000000ull)); 1227*210db224Sericheng (void) printf(" duplex=%s\n", mac_link_duplex(dev, 0)); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12327c478bd9Sstevel@tonic-gate static void 1233*210db224Sericheng show_dev_stats(void *arg, const char *dev) 12347c478bd9Sstevel@tonic-gate { 12357c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 12367c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate /* aggregations are already managed by a set of subcommands */ 12397c478bd9Sstevel@tonic-gate if (strcmp(dev, AGGR_DEV) == 0) 12407c478bd9Sstevel@tonic-gate return; 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate if (state->ms_firstonly) { 12437c478bd9Sstevel@tonic-gate if (state->ms_donefirst) 12447c478bd9Sstevel@tonic-gate return; 12457c478bd9Sstevel@tonic-gate state->ms_donefirst = B_TRUE; 12467c478bd9Sstevel@tonic-gate } else { 12477c478bd9Sstevel@tonic-gate bzero(&state->ms_prevstats, sizeof (state->ms_prevstats)); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate 1250*210db224Sericheng get_mac_stats(dev, 0, &stats); 12517c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ms_prevstats); 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 12547c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 12557c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 12567c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 12577c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 12587c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 12597c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate state->ms_prevstats = stats; 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate static void 12657c478bd9Sstevel@tonic-gate do_show_link(int argc, char *argv[]) 12667c478bd9Sstevel@tonic-gate { 12677c478bd9Sstevel@tonic-gate char *name = NULL; 12687c478bd9Sstevel@tonic-gate int option; 12697c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 12707c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 12717c478bd9Sstevel@tonic-gate uint32_t interval = 0; 12727c478bd9Sstevel@tonic-gate show_link_state_t state; 12737c478bd9Sstevel@tonic-gate char *endp = NULL; 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate state.ls_stats = B_FALSE; 12767c478bd9Sstevel@tonic-gate state.ls_parseable = B_FALSE; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate opterr = 0; 12797c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 12807c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 12817c478bd9Sstevel@tonic-gate switch (option) { 12827c478bd9Sstevel@tonic-gate case 'p': 12837c478bd9Sstevel@tonic-gate state.ls_parseable = B_TRUE; 12847c478bd9Sstevel@tonic-gate break; 12857c478bd9Sstevel@tonic-gate case 's': 12867c478bd9Sstevel@tonic-gate if (s_arg) { 12877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 12887c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 12897c478bd9Sstevel@tonic-gate "more than once\n"), progname); 12907c478bd9Sstevel@tonic-gate usage(); 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 12947c478bd9Sstevel@tonic-gate break; 12957c478bd9Sstevel@tonic-gate case 'i': 12967c478bd9Sstevel@tonic-gate if (i_arg) { 12977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 12987c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 12997c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13007c478bd9Sstevel@tonic-gate usage(); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate errno = 0; 13067c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 13077c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 13087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13097c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 13107c478bd9Sstevel@tonic-gate " '%d'\n"), 13117c478bd9Sstevel@tonic-gate progname, interval); 13127c478bd9Sstevel@tonic-gate exit(1); 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate break; 13157c478bd9Sstevel@tonic-gate case ':': 13167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13177c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 13187c478bd9Sstevel@tonic-gate progname, optopt); 13197c478bd9Sstevel@tonic-gate exit(1); 13207c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 13217c478bd9Sstevel@tonic-gate case '?': 13227c478bd9Sstevel@tonic-gate default: 13237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13247c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 13257c478bd9Sstevel@tonic-gate progname, optopt); 13267c478bd9Sstevel@tonic-gate exit(1); 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 13317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 13327c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 13337c478bd9Sstevel@tonic-gate usage(); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 13387c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 13397c478bd9Sstevel@tonic-gate name = argv[optind]; 13407c478bd9Sstevel@tonic-gate else if (optind != argc) 13417c478bd9Sstevel@tonic-gate usage(); 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate if (s_arg) { 13447c478bd9Sstevel@tonic-gate link_stats(name, interval); 13457c478bd9Sstevel@tonic-gate return; 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 1348*210db224Sericheng if (name == NULL) { 13497c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link, &state); 1350*210db224Sericheng } else { 13517c478bd9Sstevel@tonic-gate show_link(&state, name); 13527c478bd9Sstevel@tonic-gate } 1353*210db224Sericheng } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate static void 13567c478bd9Sstevel@tonic-gate do_show_aggr(int argc, char *argv[]) 13577c478bd9Sstevel@tonic-gate { 13587c478bd9Sstevel@tonic-gate int option; 13597c478bd9Sstevel@tonic-gate uint16_t key = 0; 13607c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 13617c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 13627c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 13637c478bd9Sstevel@tonic-gate show_grp_state_t state; 13647c478bd9Sstevel@tonic-gate uint32_t interval = 0; 13657c478bd9Sstevel@tonic-gate char *endp = NULL; 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate state.gs_stats = B_FALSE; 13687c478bd9Sstevel@tonic-gate state.gs_lacp = B_FALSE; 13697c478bd9Sstevel@tonic-gate state.gs_parseable = B_FALSE; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate opterr = 0; 13727c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":Lpsi:", 13737c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 13747c478bd9Sstevel@tonic-gate switch (option) { 13757c478bd9Sstevel@tonic-gate case 'L': 13767c478bd9Sstevel@tonic-gate if (L_arg) { 13777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13787c478bd9Sstevel@tonic-gate "%s: the option -L cannot be specified " 13797c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13807c478bd9Sstevel@tonic-gate usage(); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate if (s_arg || i_arg) { 13847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13857c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used with " 13867c478bd9Sstevel@tonic-gate "any of -is\n"), progname); 13877c478bd9Sstevel@tonic-gate usage(); 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate state.gs_lacp = B_TRUE; 13937c478bd9Sstevel@tonic-gate break; 13947c478bd9Sstevel@tonic-gate case 'p': 13957c478bd9Sstevel@tonic-gate state.gs_parseable = B_TRUE; 13967c478bd9Sstevel@tonic-gate break; 13977c478bd9Sstevel@tonic-gate case 's': 13987c478bd9Sstevel@tonic-gate if (s_arg) { 13997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14007c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 14017c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14027c478bd9Sstevel@tonic-gate usage(); 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate if (L_arg) { 14067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14077c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used " 14087c478bd9Sstevel@tonic-gate "with -k\n"), progname); 14097c478bd9Sstevel@tonic-gate usage(); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 14137c478bd9Sstevel@tonic-gate break; 14147c478bd9Sstevel@tonic-gate case 'i': 14157c478bd9Sstevel@tonic-gate if (i_arg) { 14167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14177c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 14187c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14197c478bd9Sstevel@tonic-gate usage(); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate if (L_arg) { 14237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14247c478bd9Sstevel@tonic-gate "%s: the option -i cannot be used " 14257c478bd9Sstevel@tonic-gate "with -L\n"), progname); 14267c478bd9Sstevel@tonic-gate usage(); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate errno = 0; 14327c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 14337c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 14347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14357c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 14367c478bd9Sstevel@tonic-gate " '%d'\n"), 14377c478bd9Sstevel@tonic-gate progname, interval); 14387c478bd9Sstevel@tonic-gate exit(1); 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate break; 14417c478bd9Sstevel@tonic-gate case ':': 14427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14437c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 14447c478bd9Sstevel@tonic-gate progname, optopt); 14457c478bd9Sstevel@tonic-gate exit(1); 14467c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 14477c478bd9Sstevel@tonic-gate case '?': 14487c478bd9Sstevel@tonic-gate default: 14497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14507c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 14517c478bd9Sstevel@tonic-gate progname, optopt); 14527c478bd9Sstevel@tonic-gate exit(1); 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 14577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 14587c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 14597c478bd9Sstevel@tonic-gate usage(); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 14637c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 14647c478bd9Sstevel@tonic-gate errno = 0; 14657c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 14667c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 14677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14687c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 14697c478bd9Sstevel@tonic-gate progname, key); 14707c478bd9Sstevel@tonic-gate exit(1); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate } else if (optind != argc) { 14737c478bd9Sstevel@tonic-gate usage(); 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate if (s_arg) { 14777c478bd9Sstevel@tonic-gate aggr_stats(key, interval); 14787c478bd9Sstevel@tonic-gate return; 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate state.gs_key = key; 14827c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate if (key != 0 && !state.gs_found) { 14877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14887c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 14897c478bd9Sstevel@tonic-gate progname, key); 14907c478bd9Sstevel@tonic-gate exit(1); 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate static void 14957c478bd9Sstevel@tonic-gate do_show_dev(int argc, char *argv[]) 14967c478bd9Sstevel@tonic-gate { 14977c478bd9Sstevel@tonic-gate int option; 14987c478bd9Sstevel@tonic-gate char *dev = NULL; 14997c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 15007c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 15017c478bd9Sstevel@tonic-gate uint32_t interval = 0; 15027c478bd9Sstevel@tonic-gate show_mac_state_t state; 15037c478bd9Sstevel@tonic-gate char *endp = NULL; 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate state.ms_parseable = B_FALSE; 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate opterr = 0; 15087c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 15097c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 15107c478bd9Sstevel@tonic-gate switch (option) { 15117c478bd9Sstevel@tonic-gate case 'p': 15127c478bd9Sstevel@tonic-gate state.ms_parseable = B_TRUE; 15137c478bd9Sstevel@tonic-gate break; 15147c478bd9Sstevel@tonic-gate case 's': 15157c478bd9Sstevel@tonic-gate if (s_arg) { 15167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15177c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 15187c478bd9Sstevel@tonic-gate "more than once\n"), progname); 15197c478bd9Sstevel@tonic-gate usage(); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 15237c478bd9Sstevel@tonic-gate break; 15247c478bd9Sstevel@tonic-gate case 'i': 15257c478bd9Sstevel@tonic-gate if (i_arg) { 15267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15277c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 15287c478bd9Sstevel@tonic-gate "more than once\n"), progname); 15297c478bd9Sstevel@tonic-gate usage(); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate errno = 0; 15357c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 15367c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 15377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15387c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 15397c478bd9Sstevel@tonic-gate " '%d'\n"), 15407c478bd9Sstevel@tonic-gate progname, interval); 15417c478bd9Sstevel@tonic-gate exit(1); 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate break; 15447c478bd9Sstevel@tonic-gate case ':': 15457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15467c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 15477c478bd9Sstevel@tonic-gate progname, optopt); 15487c478bd9Sstevel@tonic-gate exit(1); 15497c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 15507c478bd9Sstevel@tonic-gate case '?': 15517c478bd9Sstevel@tonic-gate default: 15527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15537c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 15547c478bd9Sstevel@tonic-gate progname, optopt); 15557c478bd9Sstevel@tonic-gate exit(1); 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate } 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 15607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 15617c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 15627c478bd9Sstevel@tonic-gate usage(); 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate /* get dev name (optional last argument) */ 15667c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 15677c478bd9Sstevel@tonic-gate dev = argv[optind]; 15687c478bd9Sstevel@tonic-gate else if (optind != argc) 15697c478bd9Sstevel@tonic-gate usage(); 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate if ((dev != NULL) && (strcmp(dev, AGGR_DEV) == 0)) { 15727c478bd9Sstevel@tonic-gate /* aggregations are already managed by a set of subcommands */ 15737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15747c478bd9Sstevel@tonic-gate gettext("%s: non-existant device '%s'\n"), 15757c478bd9Sstevel@tonic-gate progname, dev); 15767c478bd9Sstevel@tonic-gate exit(1); 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate if (s_arg) { 15807c478bd9Sstevel@tonic-gate dev_stats(dev, interval); 15817c478bd9Sstevel@tonic-gate return; 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate if (dev == NULL) 15857c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev, &state, B_TRUE); 15867c478bd9Sstevel@tonic-gate else 1587*210db224Sericheng show_dev(&state, dev); 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15917c478bd9Sstevel@tonic-gate static void 15927c478bd9Sstevel@tonic-gate link_stats(const char *link, uint32_t interval) 15937c478bd9Sstevel@tonic-gate { 1594*210db224Sericheng dladm_attr_t dlattr; 1595*210db224Sericheng boolean_t legacy; 15967c478bd9Sstevel@tonic-gate show_link_state_t state; 15977c478bd9Sstevel@tonic-gate 1598*210db224Sericheng if (link != NULL && get_if_info(link, &dlattr, &legacy) < 0) { 1599*210db224Sericheng (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), 16007c478bd9Sstevel@tonic-gate progname, link); 16017c478bd9Sstevel@tonic-gate exit(1); 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate /* 16067c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16077c478bd9Sstevel@tonic-gate * only for the first MAC port. 16087c478bd9Sstevel@tonic-gate */ 16097c478bd9Sstevel@tonic-gate state.ls_firstonly = (interval != 0); 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate for (;;) { 16127c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 16137c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate state.ls_donefirst = B_FALSE; 16167c478bd9Sstevel@tonic-gate if (link == NULL) 16177c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link_stats, &state); 16187c478bd9Sstevel@tonic-gate else 16197c478bd9Sstevel@tonic-gate show_link_stats(&state, link); 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate if (interval == 0) 16227c478bd9Sstevel@tonic-gate break; 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate (void) sleep(interval); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16297c478bd9Sstevel@tonic-gate static void 16307c478bd9Sstevel@tonic-gate aggr_stats(uint16_t key, uint32_t interval) 16317c478bd9Sstevel@tonic-gate { 16327c478bd9Sstevel@tonic-gate show_grp_state_t state; 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16357c478bd9Sstevel@tonic-gate state.gs_stats = B_TRUE; 16367c478bd9Sstevel@tonic-gate state.gs_key = key; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate /* 16397c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16407c478bd9Sstevel@tonic-gate * only for the first group. 16417c478bd9Sstevel@tonic-gate */ 16427c478bd9Sstevel@tonic-gate state.gs_firstonly = (interval != 0); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate for (;;) { 16457c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 16467c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 16477c478bd9Sstevel@tonic-gate if (state.gs_key != 0 && !state.gs_found) { 16487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16497c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 16507c478bd9Sstevel@tonic-gate progname, key); 16517c478bd9Sstevel@tonic-gate exit(1); 16527c478bd9Sstevel@tonic-gate } 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate if (interval == 0) 16557c478bd9Sstevel@tonic-gate break; 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate (void) sleep(interval); 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate } 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16627c478bd9Sstevel@tonic-gate static void 16637c478bd9Sstevel@tonic-gate dev_stats(const char *dev, uint32_t interval) 16647c478bd9Sstevel@tonic-gate { 16657c478bd9Sstevel@tonic-gate show_mac_state_t state; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate /* 16707c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16717c478bd9Sstevel@tonic-gate * only for the first MAC port. 16727c478bd9Sstevel@tonic-gate */ 16737c478bd9Sstevel@tonic-gate state.ms_firstonly = (interval != 0); 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate for (;;) { 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 16787c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate state.ms_donefirst = B_FALSE; 1681*210db224Sericheng if (dev == NULL) 16827c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev_stats, &state, B_TRUE); 1683*210db224Sericheng else 1684*210db224Sericheng show_dev_stats(&state, dev); 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate if (interval == 0) 16877c478bd9Sstevel@tonic-gate break; 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate (void) sleep(interval); 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate /* accumulate stats (s1 += (s2 - s3)) */ 16947c478bd9Sstevel@tonic-gate static void 16957c478bd9Sstevel@tonic-gate stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 16967c478bd9Sstevel@tonic-gate { 16977c478bd9Sstevel@tonic-gate s1->ipackets += (s2->ipackets - s3->ipackets); 16987c478bd9Sstevel@tonic-gate s1->opackets += (s2->opackets - s3->opackets); 16997c478bd9Sstevel@tonic-gate s1->rbytes += (s2->rbytes - s3->rbytes); 17007c478bd9Sstevel@tonic-gate s1->obytes += (s2->obytes - s3->obytes); 17017c478bd9Sstevel@tonic-gate s1->ierrors += (s2->ierrors - s3->ierrors); 17027c478bd9Sstevel@tonic-gate s1->oerrors += (s2->oerrors - s3->oerrors); 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate /* compute stats differences (s1 = s2 - s3) */ 17067c478bd9Sstevel@tonic-gate static void 17077c478bd9Sstevel@tonic-gate stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 17087c478bd9Sstevel@tonic-gate { 17097c478bd9Sstevel@tonic-gate s1->ipackets = s2->ipackets - s3->ipackets; 17107c478bd9Sstevel@tonic-gate s1->opackets = s2->opackets - s3->opackets; 17117c478bd9Sstevel@tonic-gate s1->rbytes = s2->rbytes - s3->rbytes; 17127c478bd9Sstevel@tonic-gate s1->obytes = s2->obytes - s3->obytes; 17137c478bd9Sstevel@tonic-gate s1->ierrors = s2->ierrors - s3->ierrors; 17147c478bd9Sstevel@tonic-gate s1->oerrors = s2->oerrors - s3->oerrors; 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate static void 17187c478bd9Sstevel@tonic-gate get_stats(char *module, int instance, char *name, pktsum_t *stats) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 17217c478bd9Sstevel@tonic-gate kstat_t *ksp; 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 17247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17257c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 17267c478bd9Sstevel@tonic-gate progname); 17277c478bd9Sstevel@tonic-gate return; 17287c478bd9Sstevel@tonic-gate } 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, module, instance, name)) == NULL) { 17317c478bd9Sstevel@tonic-gate /* 17327c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 17337c478bd9Sstevel@tonic-gate * driver was already detached. 17347c478bd9Sstevel@tonic-gate */ 17357c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 17367c478bd9Sstevel@tonic-gate return; 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) 17407c478bd9Sstevel@tonic-gate goto bail; 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64, 17437c478bd9Sstevel@tonic-gate &stats->ipackets) < 0) 17447c478bd9Sstevel@tonic-gate goto bail; 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64, 17477c478bd9Sstevel@tonic-gate &stats->opackets) < 0) 17487c478bd9Sstevel@tonic-gate goto bail; 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64, 17517c478bd9Sstevel@tonic-gate &stats->rbytes) < 0) 17527c478bd9Sstevel@tonic-gate goto bail; 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64, 17557c478bd9Sstevel@tonic-gate &stats->obytes) < 0) 17567c478bd9Sstevel@tonic-gate goto bail; 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32, 17597c478bd9Sstevel@tonic-gate &stats->ierrors) < 0) 17607c478bd9Sstevel@tonic-gate goto bail; 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32, 17637c478bd9Sstevel@tonic-gate &stats->oerrors) < 0) 17647c478bd9Sstevel@tonic-gate goto bail; 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 17677c478bd9Sstevel@tonic-gate return; 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate bail: 17707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17717c478bd9Sstevel@tonic-gate gettext("%s: kstat operation failed\n"), 17727c478bd9Sstevel@tonic-gate progname); 17737c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate static void 17777c478bd9Sstevel@tonic-gate get_mac_stats(const char *dev, uint_t port, pktsum_t *stats) 17787c478bd9Sstevel@tonic-gate { 17797c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 17847c478bd9Sstevel@tonic-gate get_stats((char *)dev, 0, name, stats); 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate static void 17887c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 17897c478bd9Sstevel@tonic-gate { 17907c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 17917c478bd9Sstevel@tonic-gate get_stats(NULL, -1, (char *)link, stats); 17927c478bd9Sstevel@tonic-gate } 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate static uint64_t 17957c478bd9Sstevel@tonic-gate mac_ifspeed(const char *dev, uint_t port) 17967c478bd9Sstevel@tonic-gate { 17977c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 17987c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 17997c478bd9Sstevel@tonic-gate kstat_t *ksp; 18007c478bd9Sstevel@tonic-gate uint64_t ifspeed = 0; 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 18037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18047c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 18057c478bd9Sstevel@tonic-gate progname); 18067c478bd9Sstevel@tonic-gate return (0); 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 18107c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, (char *)dev, 0, name)) == NULL) { 18117c478bd9Sstevel@tonic-gate /* 18127c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 18137c478bd9Sstevel@tonic-gate * driver was already detached. 18147c478bd9Sstevel@tonic-gate */ 18157c478bd9Sstevel@tonic-gate goto bail; 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 18197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18207c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 18217c478bd9Sstevel@tonic-gate progname); 18227c478bd9Sstevel@tonic-gate goto bail; 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64, &ifspeed) < 0) { 18267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18277c478bd9Sstevel@tonic-gate gettext("%s: kstat value failed\n"), 18287c478bd9Sstevel@tonic-gate progname); 18297c478bd9Sstevel@tonic-gate goto bail; 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate bail: 18337c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 18347c478bd9Sstevel@tonic-gate return (ifspeed); 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate static char * 18387c478bd9Sstevel@tonic-gate mac_link_state(const char *dev, uint_t port) 18397c478bd9Sstevel@tonic-gate { 18407c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 18417c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 18427c478bd9Sstevel@tonic-gate kstat_t *ksp; 18437c478bd9Sstevel@tonic-gate link_state_t link_state; 18447c478bd9Sstevel@tonic-gate char *state_str = "unknown"; 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 18477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18487c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 18497c478bd9Sstevel@tonic-gate progname); 18507c478bd9Sstevel@tonic-gate return (state_str); 18517c478bd9Sstevel@tonic-gate } 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 18547c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, (char *)dev, 0, name)) == NULL) { 18557c478bd9Sstevel@tonic-gate /* 18567c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 18577c478bd9Sstevel@tonic-gate * driver was already detached. 18587c478bd9Sstevel@tonic-gate */ 18597c478bd9Sstevel@tonic-gate goto bail; 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 18637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18647c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 18657c478bd9Sstevel@tonic-gate progname); 18667c478bd9Sstevel@tonic-gate goto bail; 18677c478bd9Sstevel@tonic-gate } 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "link_state", KSTAT_DATA_UINT32, 18707c478bd9Sstevel@tonic-gate &link_state) < 0) { 18717c478bd9Sstevel@tonic-gate goto bail; 18727c478bd9Sstevel@tonic-gate } 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate switch (link_state) { 18757c478bd9Sstevel@tonic-gate case LINK_STATE_UP: 18767c478bd9Sstevel@tonic-gate state_str = "up"; 18777c478bd9Sstevel@tonic-gate break; 18787c478bd9Sstevel@tonic-gate case LINK_STATE_DOWN: 18797c478bd9Sstevel@tonic-gate state_str = "down"; 18807c478bd9Sstevel@tonic-gate break; 18817c478bd9Sstevel@tonic-gate default: 18827c478bd9Sstevel@tonic-gate break; 18837c478bd9Sstevel@tonic-gate } 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate bail: 18867c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 18877c478bd9Sstevel@tonic-gate return (state_str); 18887c478bd9Sstevel@tonic-gate } 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate static char * 18927c478bd9Sstevel@tonic-gate mac_link_duplex(const char *dev, uint_t port) 18937c478bd9Sstevel@tonic-gate { 18947c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 18957c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 18967c478bd9Sstevel@tonic-gate kstat_t *ksp; 18977c478bd9Sstevel@tonic-gate link_duplex_t link_duplex; 18987c478bd9Sstevel@tonic-gate char *duplex_str = "unknown"; 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 19017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19027c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 19037c478bd9Sstevel@tonic-gate progname); 19047c478bd9Sstevel@tonic-gate return (duplex_str); 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 19087c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, (char *)dev, 0, name)) == NULL) { 19097c478bd9Sstevel@tonic-gate /* 19107c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 19117c478bd9Sstevel@tonic-gate * driver was already detached. 19127c478bd9Sstevel@tonic-gate */ 19137c478bd9Sstevel@tonic-gate goto bail; 19147c478bd9Sstevel@tonic-gate } 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 19177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19187c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 19197c478bd9Sstevel@tonic-gate progname); 19207c478bd9Sstevel@tonic-gate goto bail; 19217c478bd9Sstevel@tonic-gate } 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "link_duplex", KSTAT_DATA_UINT32, 19247c478bd9Sstevel@tonic-gate &link_duplex) < 0) { 19257c478bd9Sstevel@tonic-gate goto bail; 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate switch (link_duplex) { 19287c478bd9Sstevel@tonic-gate case LINK_DUPLEX_FULL: 19297c478bd9Sstevel@tonic-gate duplex_str = "full"; 19307c478bd9Sstevel@tonic-gate break; 19317c478bd9Sstevel@tonic-gate case LINK_DUPLEX_HALF: 19327c478bd9Sstevel@tonic-gate duplex_str = "half"; 19337c478bd9Sstevel@tonic-gate break; 19347c478bd9Sstevel@tonic-gate default: 19357c478bd9Sstevel@tonic-gate break; 19367c478bd9Sstevel@tonic-gate } 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate bail: 19397c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 19407c478bd9Sstevel@tonic-gate return (duplex_str); 19417c478bd9Sstevel@tonic-gate } 1942