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