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 5219a2a31Shl157128 * Common Development and Distribution License (the "License"). 6219a2a31Shl157128 * 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 /* 22219a2a31Shl157128 * 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 47*ba2e4443Sseb #define AGGR_DRV "aggr" 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 113*ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 1147c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 115*ba2e4443Sseb static uint64_t mac_ifspeed(const char *); 116*ba2e4443Sseb static char *mac_link_state(const char *); 117*ba2e4443Sseb static char *mac_link_duplex(const char *); 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 nport++; 2657c478bd9Sstevel@tonic-gate break; 2667c478bd9Sstevel@tonic-gate case 'P': 2677c478bd9Sstevel@tonic-gate if (P_arg) { 2687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2697c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 2707c478bd9Sstevel@tonic-gate "more than once\n"), progname); 2717c478bd9Sstevel@tonic-gate usage(); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 2777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2787c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 2797c478bd9Sstevel@tonic-gate progname, optarg); 2807c478bd9Sstevel@tonic-gate exit(1); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate break; 2837c478bd9Sstevel@tonic-gate case 'u': 2847c478bd9Sstevel@tonic-gate if (u_arg) { 2857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2867c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 2877c478bd9Sstevel@tonic-gate "more than once\n"), progname); 2887c478bd9Sstevel@tonic-gate usage(); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 2947c478bd9Sstevel@tonic-gate mac_addr)) { 2957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2967c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 2977c478bd9Sstevel@tonic-gate progname, optarg); 2987c478bd9Sstevel@tonic-gate exit(1); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate break; 3027c478bd9Sstevel@tonic-gate case 'l': 3037c478bd9Sstevel@tonic-gate if (l_arg) { 3047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3057c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 3067c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3077c478bd9Sstevel@tonic-gate usage(); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 3137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3147c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 3157c478bd9Sstevel@tonic-gate progname, optarg); 3167c478bd9Sstevel@tonic-gate exit(1); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate break; 3207c478bd9Sstevel@tonic-gate case 'T': 3217c478bd9Sstevel@tonic-gate if (T_arg) { 3227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3237c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 3247c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3257c478bd9Sstevel@tonic-gate usage(); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 3317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3327c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 3337c478bd9Sstevel@tonic-gate " '%s'\n"), 3347c478bd9Sstevel@tonic-gate progname, optarg); 3357c478bd9Sstevel@tonic-gate exit(1); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate case 't': 3407c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 3417c478bd9Sstevel@tonic-gate break; 3427c478bd9Sstevel@tonic-gate case 'R': 3437c478bd9Sstevel@tonic-gate altroot = optarg; 3447c478bd9Sstevel@tonic-gate break; 3457c478bd9Sstevel@tonic-gate case ':': 3467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3477c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 3487c478bd9Sstevel@tonic-gate progname, optopt); 3497c478bd9Sstevel@tonic-gate exit(1); 3507c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3517c478bd9Sstevel@tonic-gate case '?': 3527c478bd9Sstevel@tonic-gate default: 3537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3547c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 3557c478bd9Sstevel@tonic-gate progname, optopt); 3567c478bd9Sstevel@tonic-gate exit(1); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (nport == 0) 3617c478bd9Sstevel@tonic-gate usage(); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 3647c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 3657c478bd9Sstevel@tonic-gate usage(); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate errno = 0; 3687c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 3697c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 3707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3717c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 3727c478bd9Sstevel@tonic-gate progname, key); 3737c478bd9Sstevel@tonic-gate exit(1); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate if (laadm_create(key, nport, port, policy, mac_addr_fixed, 3777c478bd9Sstevel@tonic-gate mac_addr, lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 3787c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: create operation failed: %s", diag, 3797c478bd9Sstevel@tonic-gate laadm_diag); 3807c478bd9Sstevel@tonic-gate exit(1); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate static void 3857c478bd9Sstevel@tonic-gate do_delete_aggr(int argc, char *argv[]) 3867c478bd9Sstevel@tonic-gate { 3877c478bd9Sstevel@tonic-gate uint16_t key; 3887c478bd9Sstevel@tonic-gate char option; 3897c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 3907c478bd9Sstevel@tonic-gate char *altroot = NULL; 3917c478bd9Sstevel@tonic-gate char *endp = NULL; 3927c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate opterr = 0; 3957c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":R:t", longopts, 3967c478bd9Sstevel@tonic-gate NULL)) != -1) { 3977c478bd9Sstevel@tonic-gate switch (option) { 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate case 't': 4007c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 4017c478bd9Sstevel@tonic-gate break; 4027c478bd9Sstevel@tonic-gate case 'R': 4037c478bd9Sstevel@tonic-gate altroot = optarg; 4047c478bd9Sstevel@tonic-gate break; 4057c478bd9Sstevel@tonic-gate case ':': 4067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4077c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 4087c478bd9Sstevel@tonic-gate progname, optopt); 4097c478bd9Sstevel@tonic-gate exit(1); 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate case '?': 4127c478bd9Sstevel@tonic-gate default: 4137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4147c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 4157c478bd9Sstevel@tonic-gate progname, optopt); 4167c478bd9Sstevel@tonic-gate exit(1); 4177c478bd9Sstevel@tonic-gate break; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 4227c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 4237c478bd9Sstevel@tonic-gate usage(); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate errno = 0; 4267c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 4277c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 4287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4297c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 4307c478bd9Sstevel@tonic-gate progname, key); 4317c478bd9Sstevel@tonic-gate exit(1); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate if (laadm_delete(key, t_arg, altroot, &diag) < 0) { 4357c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: delete operation failed: %s", diag, 4367c478bd9Sstevel@tonic-gate laadm_diag); 4377c478bd9Sstevel@tonic-gate exit(1); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate static void 4427c478bd9Sstevel@tonic-gate do_add_aggr(int argc, char *argv[]) 4437c478bd9Sstevel@tonic-gate { 4447c478bd9Sstevel@tonic-gate char option; 4457c478bd9Sstevel@tonic-gate uint16_t key; 4467c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 4477c478bd9Sstevel@tonic-gate uint_t nport = 0; 4487c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 4497c478bd9Sstevel@tonic-gate char *altroot = NULL; 4507c478bd9Sstevel@tonic-gate char *endp = NULL; 4517c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate opterr = 0; 4547c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", longopts, 4557c478bd9Sstevel@tonic-gate NULL)) != -1) { 4567c478bd9Sstevel@tonic-gate switch (option) { 4577c478bd9Sstevel@tonic-gate case 'd': 4587c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 4597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4607c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 4617c478bd9Sstevel@tonic-gate progname); 4627c478bd9Sstevel@tonic-gate exit(1); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 4667c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 4677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4687c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 4697c478bd9Sstevel@tonic-gate progname); 4707c478bd9Sstevel@tonic-gate exit(1); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate nport++; 4737c478bd9Sstevel@tonic-gate break; 4747c478bd9Sstevel@tonic-gate case 't': 4757c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 4767c478bd9Sstevel@tonic-gate break; 4777c478bd9Sstevel@tonic-gate case 'R': 4787c478bd9Sstevel@tonic-gate altroot = optarg; 4797c478bd9Sstevel@tonic-gate break; 4807c478bd9Sstevel@tonic-gate case ':': 4817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4827c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 4837c478bd9Sstevel@tonic-gate progname, optopt); 4847c478bd9Sstevel@tonic-gate exit(1); 4857c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4867c478bd9Sstevel@tonic-gate case '?': 4877c478bd9Sstevel@tonic-gate default: 4887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4897c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 4907c478bd9Sstevel@tonic-gate progname, optopt); 4917c478bd9Sstevel@tonic-gate exit(1); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate if (nport == 0) 4967c478bd9Sstevel@tonic-gate usage(); 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 4997c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 5007c478bd9Sstevel@tonic-gate usage(); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate errno = 0; 5037c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 5047c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 5057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5067c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 5077c478bd9Sstevel@tonic-gate progname, key); 5087c478bd9Sstevel@tonic-gate exit(1); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate if (laadm_add(key, nport, port, t_arg, altroot, &diag) < 0) { 512219a2a31Shl157128 /* 513219a2a31Shl157128 * checking ENOTSUP is a temporary workaround 514219a2a31Shl157128 * and should be removed once 6399681 is fixed. 515219a2a31Shl157128 */ 516219a2a31Shl157128 if (errno == ENOTSUP) { 517219a2a31Shl157128 (void) fprintf(stderr, 518219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 519219a2a31Shl157128 progname, 520219a2a31Shl157128 gettext("device capabilities don't match")); 521219a2a31Shl157128 exit(ENOTSUP); 522219a2a31Shl157128 } 5237c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: add operation failed: %s", diag, 5247c478bd9Sstevel@tonic-gate laadm_diag); 5257c478bd9Sstevel@tonic-gate exit(1); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate static void 5307c478bd9Sstevel@tonic-gate do_remove_aggr(int argc, char *argv[]) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate char option; 5337c478bd9Sstevel@tonic-gate uint16_t key; 5347c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 5357c478bd9Sstevel@tonic-gate uint_t nport = 0; 5367c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 5377c478bd9Sstevel@tonic-gate char *altroot = NULL; 5387c478bd9Sstevel@tonic-gate char *endp = NULL; 5397c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate opterr = 0; 5427c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", 5437c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 5447c478bd9Sstevel@tonic-gate switch (option) { 5457c478bd9Sstevel@tonic-gate case 'd': 5467c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 5477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5487c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 5497c478bd9Sstevel@tonic-gate progname); 5507c478bd9Sstevel@tonic-gate exit(1); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 5547c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 5557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5567c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 5577c478bd9Sstevel@tonic-gate progname); 5587c478bd9Sstevel@tonic-gate exit(1); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate nport++; 5617c478bd9Sstevel@tonic-gate break; 5627c478bd9Sstevel@tonic-gate case 't': 5637c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 5647c478bd9Sstevel@tonic-gate break; 5657c478bd9Sstevel@tonic-gate case 'R': 5667c478bd9Sstevel@tonic-gate altroot = optarg; 5677c478bd9Sstevel@tonic-gate break; 5687c478bd9Sstevel@tonic-gate case ':': 5697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5707c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 5717c478bd9Sstevel@tonic-gate progname, optopt); 5727c478bd9Sstevel@tonic-gate exit(1); 5737c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 5747c478bd9Sstevel@tonic-gate case '?': 5757c478bd9Sstevel@tonic-gate default: 5767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5777c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 5787c478bd9Sstevel@tonic-gate progname, optopt); 5797c478bd9Sstevel@tonic-gate exit(1); 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if (nport == 0) 5847c478bd9Sstevel@tonic-gate usage(); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 5877c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 5887c478bd9Sstevel@tonic-gate usage(); 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate errno = 0; 5917c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 5927c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 5937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5947c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 5957c478bd9Sstevel@tonic-gate progname, key); 5967c478bd9Sstevel@tonic-gate exit(1); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate if (laadm_remove(key, nport, port, t_arg, altroot, &diag) < 0) { 6007c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: remove operation failed: %s", diag, 6017c478bd9Sstevel@tonic-gate laadm_diag); 6027c478bd9Sstevel@tonic-gate exit(1); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate static void 6077c478bd9Sstevel@tonic-gate do_modify_aggr(int argc, char *argv[]) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate char option; 6107c478bd9Sstevel@tonic-gate uint16_t key; 6117c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 6127c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 6137c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 6147c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 6157c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 6167c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 6177c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 6187c478bd9Sstevel@tonic-gate char *altroot = NULL; 6197c478bd9Sstevel@tonic-gate char *endp = NULL; 6207c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate opterr = 0; 6237c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":l:P:R:tu:T:", longopts, 6247c478bd9Sstevel@tonic-gate NULL)) != -1) { 6257c478bd9Sstevel@tonic-gate switch (option) { 6267c478bd9Sstevel@tonic-gate case 'P': 6277c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_POLICY) { 6287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6297c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 6307c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6317c478bd9Sstevel@tonic-gate usage(); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_POLICY; 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 6377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6387c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 6397c478bd9Sstevel@tonic-gate progname, optarg); 6407c478bd9Sstevel@tonic-gate exit(1); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate break; 6437c478bd9Sstevel@tonic-gate case 'u': 6447c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_MAC) { 6457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6467c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 6477c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6487c478bd9Sstevel@tonic-gate usage(); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_MAC; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 6547c478bd9Sstevel@tonic-gate mac_addr)) { 6557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6567c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 6577c478bd9Sstevel@tonic-gate progname, optarg); 6587c478bd9Sstevel@tonic-gate exit(1); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate break; 6627c478bd9Sstevel@tonic-gate case 'l': 6637c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_MODE) { 6647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6657c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 6667c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6677c478bd9Sstevel@tonic-gate usage(); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_MODE; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 6737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6747c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 6757c478bd9Sstevel@tonic-gate progname, optarg); 6767c478bd9Sstevel@tonic-gate exit(1); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate break; 6807c478bd9Sstevel@tonic-gate case 'T': 6817c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_TIMER) { 6827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6837c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 6847c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6857c478bd9Sstevel@tonic-gate usage(); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_TIMER; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 6917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6927c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 6937c478bd9Sstevel@tonic-gate " '%s'\n"), 6947c478bd9Sstevel@tonic-gate progname, optarg); 6957c478bd9Sstevel@tonic-gate exit(1); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate break; 6997c478bd9Sstevel@tonic-gate case 't': 7007c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 7017c478bd9Sstevel@tonic-gate break; 7027c478bd9Sstevel@tonic-gate case 'R': 7037c478bd9Sstevel@tonic-gate altroot = optarg; 7047c478bd9Sstevel@tonic-gate break; 7057c478bd9Sstevel@tonic-gate case ':': 7067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7077c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 7087c478bd9Sstevel@tonic-gate progname, optopt); 7097c478bd9Sstevel@tonic-gate exit(1); 7107c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 7117c478bd9Sstevel@tonic-gate case '?': 7127c478bd9Sstevel@tonic-gate default: 7137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7147c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 7157c478bd9Sstevel@tonic-gate progname, optopt); 7167c478bd9Sstevel@tonic-gate exit(1); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (modify_mask == 0) { 7217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: at least one of the " 7227c478bd9Sstevel@tonic-gate "-PulT options must be specified\n"), progname); 7237c478bd9Sstevel@tonic-gate usage(); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 7277c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 7287c478bd9Sstevel@tonic-gate usage(); 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate errno = 0; 7317c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 7327c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 7337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7347c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 7357c478bd9Sstevel@tonic-gate progname, key); 7367c478bd9Sstevel@tonic-gate exit(1); 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (laadm_modify(key, modify_mask, policy, mac_addr_fixed, mac_addr, 7417c478bd9Sstevel@tonic-gate lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 7427c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: modify operation failed: %s", diag, 7437c478bd9Sstevel@tonic-gate laadm_diag); 7447c478bd9Sstevel@tonic-gate exit(1); 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate static void 7497c478bd9Sstevel@tonic-gate do_up_aggr(int argc, char *argv[]) 7507c478bd9Sstevel@tonic-gate { 7517c478bd9Sstevel@tonic-gate uint16_t key = 0; 7527c478bd9Sstevel@tonic-gate char *endp = NULL; 7537c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 7567c478bd9Sstevel@tonic-gate if (argc == 2) { 7577c478bd9Sstevel@tonic-gate errno = 0; 7587c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 7597c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 7607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7617c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 7627c478bd9Sstevel@tonic-gate progname, key); 7637c478bd9Sstevel@tonic-gate exit(1); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } else if (argc > 2) { 7667c478bd9Sstevel@tonic-gate usage(); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate if (laadm_up(key, NULL, &diag) < 0) { 7707c478bd9Sstevel@tonic-gate if (key != 0) { 7717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7727c478bd9Sstevel@tonic-gate gettext("%s: could not bring up aggregation" 7737c478bd9Sstevel@tonic-gate " '%u' : %s"), progname, key, strerror(errno)); 7747c478bd9Sstevel@tonic-gate if (diag != 0) 7757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", 7767c478bd9Sstevel@tonic-gate laadm_diag(diag)); 7777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 7787c478bd9Sstevel@tonic-gate } else { 7797c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG( 7807c478bd9Sstevel@tonic-gate "%s: could not bring aggregations up: %s", 7817c478bd9Sstevel@tonic-gate diag, laadm_diag); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate exit(1); 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate static void 7887c478bd9Sstevel@tonic-gate do_down_aggr(int argc, char *argv[]) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate uint16_t key = 0; 7917c478bd9Sstevel@tonic-gate char *endp = NULL; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 7947c478bd9Sstevel@tonic-gate if (argc == 2) { 7957c478bd9Sstevel@tonic-gate errno = 0; 7967c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 7977c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 7987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7997c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 8007c478bd9Sstevel@tonic-gate progname, key); 8017c478bd9Sstevel@tonic-gate exit(1); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } else if (argc > 2) { 8047c478bd9Sstevel@tonic-gate usage(); 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate if (laadm_down(key) < 0) { 8087c478bd9Sstevel@tonic-gate if (key != 0) { 8097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8107c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregation" 8117c478bd9Sstevel@tonic-gate " down '%u' : %s"), 8127c478bd9Sstevel@tonic-gate progname, key, strerror(errno)); 8137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 8147c478bd9Sstevel@tonic-gate } else { 8157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8167c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregations" 8177c478bd9Sstevel@tonic-gate " down: %s"), progname, strerror(errno)); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate exit(1); 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate #define TYPE_WIDTH 10 824210db224Sericheng 825210db224Sericheng static void 826210db224Sericheng print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy) 827210db224Sericheng { 828210db224Sericheng char type[TYPE_WIDTH]; 829210db224Sericheng 830210db224Sericheng if (!legacy) { 831*ba2e4443Sseb char drv[LIFNAMSIZ]; 832*ba2e4443Sseb int instance; 833*ba2e4443Sseb 834210db224Sericheng if (dap->da_vid != 0) { 835210db224Sericheng (void) snprintf(type, TYPE_WIDTH, "vlan %u", 836210db224Sericheng dap->da_vid); 837210db224Sericheng } else { 838210db224Sericheng (void) snprintf(type, TYPE_WIDTH, "non-vlan"); 839210db224Sericheng } 840*ba2e4443Sseb if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0) 841*ba2e4443Sseb return; 842*ba2e4443Sseb if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) { 843210db224Sericheng (void) printf("%s type=%s mtu=%d key=%u\n", 844*ba2e4443Sseb name, type, dap->da_max_sdu, instance); 845210db224Sericheng } else { 846210db224Sericheng (void) printf("%s type=%s mtu=%d device=%s\n", 847210db224Sericheng name, type, dap->da_max_sdu, dap->da_dev); 848210db224Sericheng } 849210db224Sericheng } else { 850210db224Sericheng (void) printf("%s type=legacy mtu=%d device=%s\n", 851210db224Sericheng name, dap->da_max_sdu, name); 852210db224Sericheng } 853210db224Sericheng } 854210db224Sericheng 855210db224Sericheng static void 856210db224Sericheng print_link(const char *name, dladm_attr_t *dap, boolean_t legacy) 857210db224Sericheng { 858210db224Sericheng char type[TYPE_WIDTH]; 859210db224Sericheng 860210db224Sericheng if (!legacy) { 861*ba2e4443Sseb char drv[LIFNAMSIZ]; 862*ba2e4443Sseb int instance; 863*ba2e4443Sseb 864210db224Sericheng if (dap->da_vid != 0) { 865210db224Sericheng (void) snprintf(type, TYPE_WIDTH, gettext("vlan %u"), 866210db224Sericheng dap->da_vid); 867210db224Sericheng } else { 868210db224Sericheng (void) snprintf(type, TYPE_WIDTH, gettext("non-vlan")); 869210db224Sericheng } 870*ba2e4443Sseb if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0) 871*ba2e4443Sseb return; 872*ba2e4443Sseb if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) { 873210db224Sericheng (void) printf(gettext("%-9s\ttype: %s\tmtu: %d" 874210db224Sericheng "\taggregation: key %u\n"), name, type, 875*ba2e4443Sseb dap->da_max_sdu, instance); 876210db224Sericheng } else { 877210db224Sericheng (void) printf(gettext("%-9s\ttype: %s\tmtu: " 878210db224Sericheng "%d\tdevice: %s\n"), name, type, dap->da_max_sdu, 879210db224Sericheng dap->da_dev); 880210db224Sericheng } 881210db224Sericheng } else { 882210db224Sericheng (void) printf(gettext("%-9s\ttype: legacy\tmtu: " 883210db224Sericheng "%d\tdevice: %s\n"), name, dap->da_max_sdu, name); 884210db224Sericheng } 885210db224Sericheng } 886210db224Sericheng 887210db224Sericheng static int 888210db224Sericheng get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy) 889210db224Sericheng { 890210db224Sericheng int err; 891210db224Sericheng 892210db224Sericheng if ((err = dladm_info(name, dlattrp)) == 0) { 893210db224Sericheng *legacy = B_FALSE; 894210db224Sericheng } else if (err < 0 && errno == ENODEV) { 895210db224Sericheng int fd; 896210db224Sericheng dlpi_if_attr_t dia; 897210db224Sericheng dl_info_ack_t dlia; 898210db224Sericheng 899210db224Sericheng /* 900210db224Sericheng * A return value of ENODEV means that the specified 901210db224Sericheng * device is not gldv3. 902210db224Sericheng */ 903210db224Sericheng if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 && 904210db224Sericheng dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, 905210db224Sericheng NULL, NULL) != -1) { 906210db224Sericheng (void) dlpi_close(fd); 907210db224Sericheng 908210db224Sericheng *legacy = B_TRUE; 909210db224Sericheng bzero(dlattrp, sizeof (*dlattrp)); 910210db224Sericheng dlattrp->da_max_sdu = (uint_t)dlia.dl_max_sdu; 911210db224Sericheng } else { 912210db224Sericheng errno = ENOENT; 913210db224Sericheng return (-1); 914210db224Sericheng } 915210db224Sericheng } else { 916210db224Sericheng /* 917210db224Sericheng * If the return value is not ENODEV, this means that 918210db224Sericheng * user is either passing in a bogus interface name 919210db224Sericheng * or a vlan interface name that doesn't exist yet. 920210db224Sericheng */ 921210db224Sericheng errno = ENOENT; 922210db224Sericheng return (-1); 923210db224Sericheng } 924210db224Sericheng return (0); 925210db224Sericheng } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9287c478bd9Sstevel@tonic-gate static void 9297c478bd9Sstevel@tonic-gate show_link(void *arg, const char *name) 9307c478bd9Sstevel@tonic-gate { 9317c478bd9Sstevel@tonic-gate dladm_attr_t dlattr; 932210db224Sericheng boolean_t legacy = B_TRUE; 9337c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 9347c478bd9Sstevel@tonic-gate 935210db224Sericheng if (get_if_info(name, &dlattr, &legacy) < 0) { 936210db224Sericheng (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), 9377c478bd9Sstevel@tonic-gate progname, name); 9387c478bd9Sstevel@tonic-gate exit(1); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 941210db224Sericheng if (state->ls_parseable) { 942210db224Sericheng print_link_parseable(name, &dlattr, legacy); 9437c478bd9Sstevel@tonic-gate } else { 944210db224Sericheng print_link(name, &dlattr, legacy); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate static void 9497c478bd9Sstevel@tonic-gate show_link_stats(void *arg, const char *name) 9507c478bd9Sstevel@tonic-gate { 9517c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 9527c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 9557c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 9567c478bd9Sstevel@tonic-gate return; 9577c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 9587c478bd9Sstevel@tonic-gate } else { 9597c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate get_link_stats(name, &stats); 9637c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ls_prevstats); 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate (void) printf("%s", name); 9667c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 9677c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 9687c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 9697c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 9707c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 9717c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate static void 9777c478bd9Sstevel@tonic-gate dump_grp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 9787c478bd9Sstevel@tonic-gate { 9797c478bd9Sstevel@tonic-gate char policy_str[LAADM_POLICY_STR_LEN]; 9807c478bd9Sstevel@tonic-gate char addr_str[ETHERADDRL * 3]; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate if (!parseable) { 9837c478bd9Sstevel@tonic-gate (void) printf(gettext("key: %d (0x%04x)"), 9847c478bd9Sstevel@tonic-gate grp->lg_key, grp->lg_key); 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate (void) printf(gettext("\tpolicy: %s"), 9877c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate (void) printf(gettext("\taddress: %s (%s)\n"), 9907c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str), 9917c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? gettext("fixed") : gettext("auto")); 9927c478bd9Sstevel@tonic-gate } else { 9937c478bd9Sstevel@tonic-gate (void) printf("aggr key=%d", grp->lg_key); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate (void) printf(" policy=%s", 9967c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate (void) printf(" address=%s", 9997c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str)); 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate (void) printf(" address-type=%s\n", 10027c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? "fixed" : "auto"); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate static void 10077c478bd9Sstevel@tonic-gate dump_grp_lacp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 10087c478bd9Sstevel@tonic-gate { 10097c478bd9Sstevel@tonic-gate const char *lacp_mode_str = laadm_lacp_mode_to_str(grp->lg_lacp_mode); 10107c478bd9Sstevel@tonic-gate const char *lacp_timer_str = 10117c478bd9Sstevel@tonic-gate laadm_lacp_timer_to_str(grp->lg_lacp_timer); 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate if (!parseable) { 10147c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLACP mode: %s"), lacp_mode_str); 10157c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLACP timer: %s\n"), lacp_timer_str); 10167c478bd9Sstevel@tonic-gate } else { 10177c478bd9Sstevel@tonic-gate (void) printf(" lacp-mode=%s", lacp_mode_str); 10187c478bd9Sstevel@tonic-gate (void) printf(" lacp-timer=%s\n", lacp_timer_str); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate static void 10237c478bd9Sstevel@tonic-gate dump_grp_stats(laadm_grp_attr_sys_t *grp) 10247c478bd9Sstevel@tonic-gate { 10257c478bd9Sstevel@tonic-gate (void) printf("key: %d", grp->lg_key); 10267c478bd9Sstevel@tonic-gate (void) printf("\tipackets rbytes opackets obytes "); 10277c478bd9Sstevel@tonic-gate (void) printf("%%ipkts %%opkts\n"); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate static void 10317c478bd9Sstevel@tonic-gate dump_ports_lacp_head(void) 10327c478bd9Sstevel@tonic-gate { 10337c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, gettext("device"), gettext("activity"), 10347c478bd9Sstevel@tonic-gate gettext("timeout"), gettext("aggregatable"), gettext("sync"), 10357c478bd9Sstevel@tonic-gate gettext("coll"), gettext("dist"), gettext("defaulted"), 10367c478bd9Sstevel@tonic-gate gettext("expired")); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate static void 10407c478bd9Sstevel@tonic-gate dump_ports_head(void) 10417c478bd9Sstevel@tonic-gate { 10427c478bd9Sstevel@tonic-gate (void) printf(gettext(" device\taddress\t\t speed\t\tduplex\tlink\t" 10437c478bd9Sstevel@tonic-gate "state\n")); 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate static char * 10477c478bd9Sstevel@tonic-gate port_state_to_str(aggr_port_state_t state_num) 10487c478bd9Sstevel@tonic-gate { 10497c478bd9Sstevel@tonic-gate int i; 10507c478bd9Sstevel@tonic-gate port_state_t *state; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate for (i = 0; i < NPORTSTATES; i++) { 10537c478bd9Sstevel@tonic-gate state = &port_states[i]; 10547c478bd9Sstevel@tonic-gate if (state->state_num == state_num) 10557c478bd9Sstevel@tonic-gate return (state->state_name); 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate return ("unknown"); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate static void 10627c478bd9Sstevel@tonic-gate dump_port(laadm_port_attr_sys_t *port, boolean_t parseable) 10637c478bd9Sstevel@tonic-gate { 10647c478bd9Sstevel@tonic-gate char *dev = port->lp_devname; 10657c478bd9Sstevel@tonic-gate char buf[ETHERADDRL * 3]; 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate if (!parseable) { 10687c478bd9Sstevel@tonic-gate (void) printf(" %-9s\t%s", dev, laadm_mac_addr_to_str( 10697c478bd9Sstevel@tonic-gate port->lp_mac, buf)); 1070*ba2e4443Sseb (void) printf("\t %-5u Mbps", (int)(mac_ifspeed(dev) / 10717c478bd9Sstevel@tonic-gate 1000000ull)); 1072*ba2e4443Sseb (void) printf("\t%s", mac_link_duplex(dev)); 1073*ba2e4443Sseb (void) printf("\t%s", mac_link_state(dev)); 10747c478bd9Sstevel@tonic-gate (void) printf("\t%s\n", port_state_to_str(port->lp_state)); 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate } else { 10777c478bd9Sstevel@tonic-gate (void) printf(" device=%s address=%s", dev, 10787c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(port->lp_mac, buf)); 1079*ba2e4443Sseb (void) printf(" speed=%u", (int)(mac_ifspeed(dev) / 10807c478bd9Sstevel@tonic-gate 1000000ull)); 1081*ba2e4443Sseb (void) printf(" duplex=%s", mac_link_duplex(dev)); 1082*ba2e4443Sseb (void) printf(" link=%s", mac_link_state(dev)); 10837c478bd9Sstevel@tonic-gate (void) printf(" port=%s", port_state_to_str(port->lp_state)); 10847c478bd9Sstevel@tonic-gate } 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate static void 10887c478bd9Sstevel@tonic-gate dump_port_lacp(laadm_port_attr_sys_t *port) 10897c478bd9Sstevel@tonic-gate { 10907c478bd9Sstevel@tonic-gate aggr_lacp_state_t *state = &port->lp_lacp_state; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, 10937c478bd9Sstevel@tonic-gate port->lp_devname, state->bit.activity ? "active" : "passive", 10947c478bd9Sstevel@tonic-gate state->bit.timeout ? "short" : "long", 10957c478bd9Sstevel@tonic-gate state->bit.aggregation ? "yes" : "no", 10967c478bd9Sstevel@tonic-gate state->bit.sync ? "yes" : "no", 10977c478bd9Sstevel@tonic-gate state->bit.collecting ? "yes" : "no", 10987c478bd9Sstevel@tonic-gate state->bit.distributing ? "yes" : "no", 10997c478bd9Sstevel@tonic-gate state->bit.defaulted ? "yes" : "no", 11007c478bd9Sstevel@tonic-gate state->bit.expired ? "yes" : "no"); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate static void 11047c478bd9Sstevel@tonic-gate dump_port_stat(int index, show_grp_state_t *state, pktsum_t *port_stats, 11057c478bd9Sstevel@tonic-gate pktsum_t *tot_stats) 11067c478bd9Sstevel@tonic-gate { 11077c478bd9Sstevel@tonic-gate pktsum_t diff_stats; 11087c478bd9Sstevel@tonic-gate pktsum_t *old_stats = &state->gs_prevstats[index]; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, port_stats, old_stats); 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", diff_stats.ipackets); 11137c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 11147c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 11157c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate if (tot_stats->ipackets == 0) 11187c478bd9Sstevel@tonic-gate (void) printf("\t-"); 11197c478bd9Sstevel@tonic-gate else 11207c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 11217c478bd9Sstevel@tonic-gate (double)tot_stats->ipackets * 100); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate if (tot_stats->opackets == 0) 11247c478bd9Sstevel@tonic-gate (void) printf("\t-"); 11257c478bd9Sstevel@tonic-gate else 11267c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 11277c478bd9Sstevel@tonic-gate (double)tot_stats->opackets * 100); 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate (void) printf("\n"); 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate *old_stats = *port_stats; 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate static int 11357c478bd9Sstevel@tonic-gate show_key(void *arg, laadm_grp_attr_sys_t *grp) 11367c478bd9Sstevel@tonic-gate { 11377c478bd9Sstevel@tonic-gate show_grp_state_t *state = (show_grp_state_t *)arg; 11387c478bd9Sstevel@tonic-gate int i; 11397c478bd9Sstevel@tonic-gate pktsum_t pktsumtot, port_stat; 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate if (state->gs_key != 0 && state->gs_key != grp->lg_key) 11427c478bd9Sstevel@tonic-gate return (0); 11437c478bd9Sstevel@tonic-gate if (state->gs_firstonly) { 11447c478bd9Sstevel@tonic-gate if (state->gs_found) 11457c478bd9Sstevel@tonic-gate return (0); 11467c478bd9Sstevel@tonic-gate } else { 11477c478bd9Sstevel@tonic-gate bzero(&state->gs_prevstats, sizeof (state->gs_prevstats)); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate state->gs_found = B_TRUE; 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate if (state->gs_stats) { 11537c478bd9Sstevel@tonic-gate /* show statistics */ 11547c478bd9Sstevel@tonic-gate dump_grp_stats(grp); 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 11577c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 11587c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1159*ba2e4443Sseb get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat); 11607c478bd9Sstevel@tonic-gate stats_total(&pktsumtot, &port_stat, 11617c478bd9Sstevel@tonic-gate &state->gs_prevstats[i]); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate (void) printf(" Total"); 11657c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", pktsumtot.ipackets); 11667c478bd9Sstevel@tonic-gate (void) printf("%-12llu", pktsumtot.rbytes); 11677c478bd9Sstevel@tonic-gate (void) printf("%-10llu", pktsumtot.opackets); 11687c478bd9Sstevel@tonic-gate (void) printf("%-12llu\n", pktsumtot.obytes); 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1171*ba2e4443Sseb get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat); 11727c478bd9Sstevel@tonic-gate (void) printf(" %s", grp->lg_ports[i].lp_devname); 11737c478bd9Sstevel@tonic-gate dump_port_stat(i, state, &port_stat, &pktsumtot); 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate } else if (state->gs_lacp) { 11767c478bd9Sstevel@tonic-gate /* show LACP info */ 11777c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 11787c478bd9Sstevel@tonic-gate dump_grp_lacp(grp, state->gs_parseable); 11797c478bd9Sstevel@tonic-gate dump_ports_lacp_head(); 11807c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) 11817c478bd9Sstevel@tonic-gate dump_port_lacp(&grp->lg_ports[i]); 11827c478bd9Sstevel@tonic-gate } else { 11837c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 11847c478bd9Sstevel@tonic-gate if (!state->gs_parseable) 11857c478bd9Sstevel@tonic-gate dump_ports_head(); 11867c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 11877c478bd9Sstevel@tonic-gate if (state->gs_parseable) 11887c478bd9Sstevel@tonic-gate (void) printf("dev key=%d", grp->lg_key); 11897c478bd9Sstevel@tonic-gate dump_port(&grp->lg_ports[i], state->gs_parseable); 11907c478bd9Sstevel@tonic-gate if (state->gs_parseable) 11917c478bd9Sstevel@tonic-gate (void) printf("\n"); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate return (0); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate static int 11997c478bd9Sstevel@tonic-gate kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf) 12007c478bd9Sstevel@tonic-gate { 12017c478bd9Sstevel@tonic-gate kstat_named_t *knp; 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL) 12047c478bd9Sstevel@tonic-gate return (-1); 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate if (knp->data_type != type) 12077c478bd9Sstevel@tonic-gate return (-1); 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate switch (type) { 12107c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT64: 12117c478bd9Sstevel@tonic-gate *(uint64_t *)buf = knp->value.ui64; 12127c478bd9Sstevel@tonic-gate break; 12137c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT32: 12147c478bd9Sstevel@tonic-gate *(uint32_t *)buf = knp->value.ui32; 12157c478bd9Sstevel@tonic-gate break; 12167c478bd9Sstevel@tonic-gate default: 12177c478bd9Sstevel@tonic-gate return (-1); 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate return (0); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate static void 1224210db224Sericheng show_dev(void *arg, const char *dev) 12257c478bd9Sstevel@tonic-gate { 12267c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate if (!state->ms_parseable) { 12317c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tlink: %s"), 1232*ba2e4443Sseb mac_link_state(dev)); 12337c478bd9Sstevel@tonic-gate (void) printf(gettext("\tspeed: %-5u Mbps"), 1234*ba2e4443Sseb (unsigned int)(mac_ifspeed(dev) / 1000000ull)); 12357c478bd9Sstevel@tonic-gate (void) printf(gettext("\tduplex: %s\n"), 1236*ba2e4443Sseb mac_link_duplex(dev)); 12377c478bd9Sstevel@tonic-gate } else { 1238*ba2e4443Sseb (void) printf(" link=%s", mac_link_state(dev)); 12397c478bd9Sstevel@tonic-gate (void) printf(" speed=%u", 1240*ba2e4443Sseb (unsigned int)(mac_ifspeed(dev) / 1000000ull)); 1241*ba2e4443Sseb (void) printf(" duplex=%s\n", mac_link_duplex(dev)); 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12467c478bd9Sstevel@tonic-gate static void 1247210db224Sericheng show_dev_stats(void *arg, const char *dev) 12487c478bd9Sstevel@tonic-gate { 12497c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 12507c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate if (state->ms_firstonly) { 12537c478bd9Sstevel@tonic-gate if (state->ms_donefirst) 12547c478bd9Sstevel@tonic-gate return; 12557c478bd9Sstevel@tonic-gate state->ms_donefirst = B_TRUE; 12567c478bd9Sstevel@tonic-gate } else { 12577c478bd9Sstevel@tonic-gate bzero(&state->ms_prevstats, sizeof (state->ms_prevstats)); 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 1260*ba2e4443Sseb get_mac_stats(dev, &stats); 12617c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ms_prevstats); 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 12647c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 12657c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 12667c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 12677c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 12687c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 12697c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate state->ms_prevstats = stats; 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate static void 12757c478bd9Sstevel@tonic-gate do_show_link(int argc, char *argv[]) 12767c478bd9Sstevel@tonic-gate { 12777c478bd9Sstevel@tonic-gate char *name = NULL; 12787c478bd9Sstevel@tonic-gate int option; 12797c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 12807c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 12817c478bd9Sstevel@tonic-gate uint32_t interval = 0; 12827c478bd9Sstevel@tonic-gate show_link_state_t state; 12837c478bd9Sstevel@tonic-gate char *endp = NULL; 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate state.ls_stats = B_FALSE; 12867c478bd9Sstevel@tonic-gate state.ls_parseable = B_FALSE; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate opterr = 0; 12897c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 12907c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 12917c478bd9Sstevel@tonic-gate switch (option) { 12927c478bd9Sstevel@tonic-gate case 'p': 12937c478bd9Sstevel@tonic-gate state.ls_parseable = B_TRUE; 12947c478bd9Sstevel@tonic-gate break; 12957c478bd9Sstevel@tonic-gate case 's': 12967c478bd9Sstevel@tonic-gate if (s_arg) { 12977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 12987c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 12997c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13007c478bd9Sstevel@tonic-gate usage(); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 13047c478bd9Sstevel@tonic-gate break; 13057c478bd9Sstevel@tonic-gate case 'i': 13067c478bd9Sstevel@tonic-gate if (i_arg) { 13077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13087c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 13097c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13107c478bd9Sstevel@tonic-gate usage(); 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate errno = 0; 13167c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 13177c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 13187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13197c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 13207c478bd9Sstevel@tonic-gate " '%d'\n"), 13217c478bd9Sstevel@tonic-gate progname, interval); 13227c478bd9Sstevel@tonic-gate exit(1); 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate break; 13257c478bd9Sstevel@tonic-gate case ':': 13267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13277c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 13287c478bd9Sstevel@tonic-gate progname, optopt); 13297c478bd9Sstevel@tonic-gate exit(1); 13307c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 13317c478bd9Sstevel@tonic-gate case '?': 13327c478bd9Sstevel@tonic-gate default: 13337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13347c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 13357c478bd9Sstevel@tonic-gate progname, optopt); 13367c478bd9Sstevel@tonic-gate exit(1); 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 13417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 13427c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 13437c478bd9Sstevel@tonic-gate usage(); 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 13487c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 13497c478bd9Sstevel@tonic-gate name = argv[optind]; 13507c478bd9Sstevel@tonic-gate else if (optind != argc) 13517c478bd9Sstevel@tonic-gate usage(); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (s_arg) { 13547c478bd9Sstevel@tonic-gate link_stats(name, interval); 13557c478bd9Sstevel@tonic-gate return; 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate 1358210db224Sericheng if (name == NULL) { 13597c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link, &state); 1360210db224Sericheng } else { 13617c478bd9Sstevel@tonic-gate show_link(&state, name); 13627c478bd9Sstevel@tonic-gate } 1363210db224Sericheng } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate static void 13667c478bd9Sstevel@tonic-gate do_show_aggr(int argc, char *argv[]) 13677c478bd9Sstevel@tonic-gate { 13687c478bd9Sstevel@tonic-gate int option; 13697c478bd9Sstevel@tonic-gate uint16_t key = 0; 13707c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 13717c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 13727c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 13737c478bd9Sstevel@tonic-gate show_grp_state_t state; 13747c478bd9Sstevel@tonic-gate uint32_t interval = 0; 13757c478bd9Sstevel@tonic-gate char *endp = NULL; 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate state.gs_stats = B_FALSE; 13787c478bd9Sstevel@tonic-gate state.gs_lacp = B_FALSE; 13797c478bd9Sstevel@tonic-gate state.gs_parseable = B_FALSE; 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate opterr = 0; 13827c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":Lpsi:", 13837c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 13847c478bd9Sstevel@tonic-gate switch (option) { 13857c478bd9Sstevel@tonic-gate case 'L': 13867c478bd9Sstevel@tonic-gate if (L_arg) { 13877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13887c478bd9Sstevel@tonic-gate "%s: the option -L cannot be specified " 13897c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13907c478bd9Sstevel@tonic-gate usage(); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate if (s_arg || i_arg) { 13947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13957c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used with " 13967c478bd9Sstevel@tonic-gate "any of -is\n"), progname); 13977c478bd9Sstevel@tonic-gate usage(); 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate state.gs_lacp = B_TRUE; 14037c478bd9Sstevel@tonic-gate break; 14047c478bd9Sstevel@tonic-gate case 'p': 14057c478bd9Sstevel@tonic-gate state.gs_parseable = B_TRUE; 14067c478bd9Sstevel@tonic-gate break; 14077c478bd9Sstevel@tonic-gate case 's': 14087c478bd9Sstevel@tonic-gate if (s_arg) { 14097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14107c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 14117c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14127c478bd9Sstevel@tonic-gate usage(); 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate if (L_arg) { 14167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14177c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used " 14187c478bd9Sstevel@tonic-gate "with -k\n"), progname); 14197c478bd9Sstevel@tonic-gate usage(); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 14237c478bd9Sstevel@tonic-gate break; 14247c478bd9Sstevel@tonic-gate case 'i': 14257c478bd9Sstevel@tonic-gate if (i_arg) { 14267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14277c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 14287c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14297c478bd9Sstevel@tonic-gate usage(); 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate if (L_arg) { 14337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14347c478bd9Sstevel@tonic-gate "%s: the option -i cannot be used " 14357c478bd9Sstevel@tonic-gate "with -L\n"), progname); 14367c478bd9Sstevel@tonic-gate usage(); 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate errno = 0; 14427c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 14437c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 14447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14457c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 14467c478bd9Sstevel@tonic-gate " '%d'\n"), 14477c478bd9Sstevel@tonic-gate progname, interval); 14487c478bd9Sstevel@tonic-gate exit(1); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate break; 14517c478bd9Sstevel@tonic-gate case ':': 14527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14537c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 14547c478bd9Sstevel@tonic-gate progname, optopt); 14557c478bd9Sstevel@tonic-gate exit(1); 14567c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 14577c478bd9Sstevel@tonic-gate case '?': 14587c478bd9Sstevel@tonic-gate default: 14597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14607c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 14617c478bd9Sstevel@tonic-gate progname, optopt); 14627c478bd9Sstevel@tonic-gate exit(1); 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 14677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 14687c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 14697c478bd9Sstevel@tonic-gate usage(); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 14737c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 14747c478bd9Sstevel@tonic-gate errno = 0; 14757c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 14767c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 14777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14787c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 14797c478bd9Sstevel@tonic-gate progname, key); 14807c478bd9Sstevel@tonic-gate exit(1); 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate } else if (optind != argc) { 14837c478bd9Sstevel@tonic-gate usage(); 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate if (s_arg) { 14877c478bd9Sstevel@tonic-gate aggr_stats(key, interval); 14887c478bd9Sstevel@tonic-gate return; 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate state.gs_key = key; 14927c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if (key != 0 && !state.gs_found) { 14977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14987c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 14997c478bd9Sstevel@tonic-gate progname, key); 15007c478bd9Sstevel@tonic-gate exit(1); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate static void 15057c478bd9Sstevel@tonic-gate do_show_dev(int argc, char *argv[]) 15067c478bd9Sstevel@tonic-gate { 15077c478bd9Sstevel@tonic-gate int option; 15087c478bd9Sstevel@tonic-gate char *dev = NULL; 15097c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 15107c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 15117c478bd9Sstevel@tonic-gate uint32_t interval = 0; 15127c478bd9Sstevel@tonic-gate show_mac_state_t state; 15137c478bd9Sstevel@tonic-gate char *endp = NULL; 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate state.ms_parseable = B_FALSE; 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate opterr = 0; 15187c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 15197c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 15207c478bd9Sstevel@tonic-gate switch (option) { 15217c478bd9Sstevel@tonic-gate case 'p': 15227c478bd9Sstevel@tonic-gate state.ms_parseable = B_TRUE; 15237c478bd9Sstevel@tonic-gate break; 15247c478bd9Sstevel@tonic-gate case 's': 15257c478bd9Sstevel@tonic-gate if (s_arg) { 15267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15277c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 15287c478bd9Sstevel@tonic-gate "more than once\n"), progname); 15297c478bd9Sstevel@tonic-gate usage(); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 15337c478bd9Sstevel@tonic-gate break; 15347c478bd9Sstevel@tonic-gate case 'i': 15357c478bd9Sstevel@tonic-gate if (i_arg) { 15367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15377c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 15387c478bd9Sstevel@tonic-gate "more than once\n"), progname); 15397c478bd9Sstevel@tonic-gate usage(); 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate errno = 0; 15457c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 15467c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 15477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15487c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 15497c478bd9Sstevel@tonic-gate " '%d'\n"), 15507c478bd9Sstevel@tonic-gate progname, interval); 15517c478bd9Sstevel@tonic-gate exit(1); 15527c478bd9Sstevel@tonic-gate } 15537c478bd9Sstevel@tonic-gate break; 15547c478bd9Sstevel@tonic-gate case ':': 15557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15567c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 15577c478bd9Sstevel@tonic-gate progname, optopt); 15587c478bd9Sstevel@tonic-gate exit(1); 15597c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 15607c478bd9Sstevel@tonic-gate case '?': 15617c478bd9Sstevel@tonic-gate default: 15627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15637c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 15647c478bd9Sstevel@tonic-gate progname, optopt); 15657c478bd9Sstevel@tonic-gate exit(1); 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 15707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 15717c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 15727c478bd9Sstevel@tonic-gate usage(); 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate /* get dev name (optional last argument) */ 15767c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 15777c478bd9Sstevel@tonic-gate dev = argv[optind]; 15787c478bd9Sstevel@tonic-gate else if (optind != argc) 15797c478bd9Sstevel@tonic-gate usage(); 15807c478bd9Sstevel@tonic-gate 1581cd93090eSericheng if (dev != NULL) { 1582cd93090eSericheng int index; 1583cd93090eSericheng char drv[LIFNAMSIZ]; 1584cd93090eSericheng dladm_attr_t dlattr; 1585cd93090eSericheng boolean_t legacy; 1586cd93090eSericheng 1587cd93090eSericheng /* 1588cd93090eSericheng * Check for invalid devices. 1589cd93090eSericheng * aggregations and vlans are not considered devices. 1590cd93090eSericheng */ 1591cd93090eSericheng if (strncmp(dev, "aggr", 4) == 0 || 1592cd93090eSericheng dlpi_if_parse(dev, drv, &index) < 0 || 1593cd93090eSericheng index >= 1000 || 1594cd93090eSericheng get_if_info(dev, &dlattr, &legacy) < 0) { 15957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1596cd93090eSericheng gettext("%s: invalid device '%s'\n"), 15977c478bd9Sstevel@tonic-gate progname, dev); 15987c478bd9Sstevel@tonic-gate exit(1); 15997c478bd9Sstevel@tonic-gate } 1600cd93090eSericheng } 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate if (s_arg) { 16037c478bd9Sstevel@tonic-gate dev_stats(dev, interval); 16047c478bd9Sstevel@tonic-gate return; 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate if (dev == NULL) 16087c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev, &state, B_TRUE); 16097c478bd9Sstevel@tonic-gate else 1610210db224Sericheng show_dev(&state, dev); 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16147c478bd9Sstevel@tonic-gate static void 16157c478bd9Sstevel@tonic-gate link_stats(const char *link, uint32_t interval) 16167c478bd9Sstevel@tonic-gate { 1617210db224Sericheng dladm_attr_t dlattr; 1618210db224Sericheng boolean_t legacy; 16197c478bd9Sstevel@tonic-gate show_link_state_t state; 16207c478bd9Sstevel@tonic-gate 1621210db224Sericheng if (link != NULL && get_if_info(link, &dlattr, &legacy) < 0) { 1622210db224Sericheng (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), 16237c478bd9Sstevel@tonic-gate progname, link); 16247c478bd9Sstevel@tonic-gate exit(1); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate /* 16297c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16307c478bd9Sstevel@tonic-gate * only for the first MAC port. 16317c478bd9Sstevel@tonic-gate */ 16327c478bd9Sstevel@tonic-gate state.ls_firstonly = (interval != 0); 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate for (;;) { 16357c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 16367c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate state.ls_donefirst = B_FALSE; 16397c478bd9Sstevel@tonic-gate if (link == NULL) 16407c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link_stats, &state); 16417c478bd9Sstevel@tonic-gate else 16427c478bd9Sstevel@tonic-gate show_link_stats(&state, link); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate if (interval == 0) 16457c478bd9Sstevel@tonic-gate break; 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate (void) sleep(interval); 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16527c478bd9Sstevel@tonic-gate static void 16537c478bd9Sstevel@tonic-gate aggr_stats(uint16_t key, uint32_t interval) 16547c478bd9Sstevel@tonic-gate { 16557c478bd9Sstevel@tonic-gate show_grp_state_t state; 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16587c478bd9Sstevel@tonic-gate state.gs_stats = B_TRUE; 16597c478bd9Sstevel@tonic-gate state.gs_key = key; 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate /* 16627c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16637c478bd9Sstevel@tonic-gate * only for the first group. 16647c478bd9Sstevel@tonic-gate */ 16657c478bd9Sstevel@tonic-gate state.gs_firstonly = (interval != 0); 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate for (;;) { 16687c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 16697c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 16707c478bd9Sstevel@tonic-gate if (state.gs_key != 0 && !state.gs_found) { 16717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16727c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 16737c478bd9Sstevel@tonic-gate progname, key); 16747c478bd9Sstevel@tonic-gate exit(1); 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate if (interval == 0) 16787c478bd9Sstevel@tonic-gate break; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate (void) sleep(interval); 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate } 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16857c478bd9Sstevel@tonic-gate static void 16867c478bd9Sstevel@tonic-gate dev_stats(const char *dev, uint32_t interval) 16877c478bd9Sstevel@tonic-gate { 16887c478bd9Sstevel@tonic-gate show_mac_state_t state; 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate /* 16937c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16947c478bd9Sstevel@tonic-gate * only for the first MAC port. 16957c478bd9Sstevel@tonic-gate */ 16967c478bd9Sstevel@tonic-gate state.ms_firstonly = (interval != 0); 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate for (;;) { 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 17017c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate state.ms_donefirst = B_FALSE; 1704210db224Sericheng if (dev == NULL) 17057c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev_stats, &state, B_TRUE); 1706210db224Sericheng else 1707210db224Sericheng show_dev_stats(&state, dev); 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate if (interval == 0) 17107c478bd9Sstevel@tonic-gate break; 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate (void) sleep(interval); 17137c478bd9Sstevel@tonic-gate } 17147c478bd9Sstevel@tonic-gate } 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate /* accumulate stats (s1 += (s2 - s3)) */ 17177c478bd9Sstevel@tonic-gate static void 17187c478bd9Sstevel@tonic-gate stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate s1->ipackets += (s2->ipackets - s3->ipackets); 17217c478bd9Sstevel@tonic-gate s1->opackets += (s2->opackets - s3->opackets); 17227c478bd9Sstevel@tonic-gate s1->rbytes += (s2->rbytes - s3->rbytes); 17237c478bd9Sstevel@tonic-gate s1->obytes += (s2->obytes - s3->obytes); 17247c478bd9Sstevel@tonic-gate s1->ierrors += (s2->ierrors - s3->ierrors); 17257c478bd9Sstevel@tonic-gate s1->oerrors += (s2->oerrors - s3->oerrors); 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate /* compute stats differences (s1 = s2 - s3) */ 17297c478bd9Sstevel@tonic-gate static void 17307c478bd9Sstevel@tonic-gate stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 17317c478bd9Sstevel@tonic-gate { 17327c478bd9Sstevel@tonic-gate s1->ipackets = s2->ipackets - s3->ipackets; 17337c478bd9Sstevel@tonic-gate s1->opackets = s2->opackets - s3->opackets; 17347c478bd9Sstevel@tonic-gate s1->rbytes = s2->rbytes - s3->rbytes; 17357c478bd9Sstevel@tonic-gate s1->obytes = s2->obytes - s3->obytes; 17367c478bd9Sstevel@tonic-gate s1->ierrors = s2->ierrors - s3->ierrors; 17377c478bd9Sstevel@tonic-gate s1->oerrors = s2->oerrors - s3->oerrors; 17387c478bd9Sstevel@tonic-gate } 17397c478bd9Sstevel@tonic-gate 1740cd93090eSericheng /* 1741*ba2e4443Sseb * In the following routines, we do the first kstat_lookup() assuming that 1742*ba2e4443Sseb * the device is gldv3-based and that the kstat name is the one passed in 1743*ba2e4443Sseb * as the "name" argument. If the lookup fails, we redo the kstat_lookup() 1744*ba2e4443Sseb * omitting the kstat name. This second lookup is needed for getting kstats 1745*ba2e4443Sseb * from legacy devices. This can fail too if the device is not attached or 1746*ba2e4443Sseb * the device is legacy and doesn't export the kstats we need. 1747cd93090eSericheng */ 17487c478bd9Sstevel@tonic-gate static void 17497c478bd9Sstevel@tonic-gate get_stats(char *module, int instance, char *name, pktsum_t *stats) 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 17527c478bd9Sstevel@tonic-gate kstat_t *ksp; 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 17557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17567c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 17577c478bd9Sstevel@tonic-gate progname); 17587c478bd9Sstevel@tonic-gate return; 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate 1761cd93090eSericheng if ((ksp = kstat_lookup(kcp, module, instance, name)) == NULL && 1762*ba2e4443Sseb (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) { 17637c478bd9Sstevel@tonic-gate /* 17647c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 17657c478bd9Sstevel@tonic-gate * driver was already detached. 17667c478bd9Sstevel@tonic-gate */ 17677c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 17687c478bd9Sstevel@tonic-gate return; 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) 17727c478bd9Sstevel@tonic-gate goto bail; 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64, 17757c478bd9Sstevel@tonic-gate &stats->ipackets) < 0) 17767c478bd9Sstevel@tonic-gate goto bail; 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64, 17797c478bd9Sstevel@tonic-gate &stats->opackets) < 0) 17807c478bd9Sstevel@tonic-gate goto bail; 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64, 17837c478bd9Sstevel@tonic-gate &stats->rbytes) < 0) 17847c478bd9Sstevel@tonic-gate goto bail; 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64, 17877c478bd9Sstevel@tonic-gate &stats->obytes) < 0) 17887c478bd9Sstevel@tonic-gate goto bail; 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32, 17917c478bd9Sstevel@tonic-gate &stats->ierrors) < 0) 17927c478bd9Sstevel@tonic-gate goto bail; 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32, 17957c478bd9Sstevel@tonic-gate &stats->oerrors) < 0) 17967c478bd9Sstevel@tonic-gate goto bail; 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 17997c478bd9Sstevel@tonic-gate return; 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate bail: 18027c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate static void 1806*ba2e4443Sseb get_mac_stats(const char *dev, pktsum_t *stats) 18077c478bd9Sstevel@tonic-gate { 1808*ba2e4443Sseb char module[LIFNAMSIZ]; 1809*ba2e4443Sseb int instance; 18107c478bd9Sstevel@tonic-gate 1811*ba2e4443Sseb if (dlpi_if_parse(dev, module, &instance) != 0) 1812*ba2e4443Sseb return; 18137c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 1814*ba2e4443Sseb get_stats(module, instance, "mac", stats); 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate static void 18187c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 18197c478bd9Sstevel@tonic-gate { 1820*ba2e4443Sseb char module[LIFNAMSIZ]; 1821*ba2e4443Sseb int instance; 1822*ba2e4443Sseb 1823*ba2e4443Sseb if (dlpi_if_parse(link, module, &instance) != 0) 1824*ba2e4443Sseb return; 18257c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 1826*ba2e4443Sseb get_stats(module, instance, (char *)link, stats); 18277c478bd9Sstevel@tonic-gate } 18287c478bd9Sstevel@tonic-gate 1829*ba2e4443Sseb static int 1830*ba2e4443Sseb get_single_mac_stat(const char *dev, const char *name, uint8_t type, 1831*ba2e4443Sseb void *val) 18327c478bd9Sstevel@tonic-gate { 1833*ba2e4443Sseb char module[LIFNAMSIZ]; 1834*ba2e4443Sseb int instance; 18357c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 18367c478bd9Sstevel@tonic-gate kstat_t *ksp; 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 18397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18407c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 18417c478bd9Sstevel@tonic-gate progname); 1842*ba2e4443Sseb return (-1); 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate 1845*ba2e4443Sseb if (dlpi_if_parse(dev, module, &instance) != 0) 1846*ba2e4443Sseb return (-1); 1847*ba2e4443Sseb if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL && 1848*ba2e4443Sseb (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) { 18497c478bd9Sstevel@tonic-gate /* 18507c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 18517c478bd9Sstevel@tonic-gate * driver was already detached. 18527c478bd9Sstevel@tonic-gate */ 18537c478bd9Sstevel@tonic-gate goto bail; 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 18577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18587c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 18597c478bd9Sstevel@tonic-gate progname); 18607c478bd9Sstevel@tonic-gate goto bail; 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 1863*ba2e4443Sseb if (kstat_value(ksp, name, type, val) < 0) 18647c478bd9Sstevel@tonic-gate goto bail; 1865*ba2e4443Sseb 1866*ba2e4443Sseb (void) kstat_close(kcp); 1867*ba2e4443Sseb return (0); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate bail: 18707c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 1871*ba2e4443Sseb return (-1); 1872*ba2e4443Sseb } 1873*ba2e4443Sseb 1874*ba2e4443Sseb static uint64_t 1875*ba2e4443Sseb mac_ifspeed(const char *dev) 1876*ba2e4443Sseb { 1877*ba2e4443Sseb uint64_t ifspeed = 0; 1878*ba2e4443Sseb 1879*ba2e4443Sseb (void) get_single_mac_stat(dev, "ifspeed", KSTAT_DATA_UINT64, &ifspeed); 18807c478bd9Sstevel@tonic-gate return (ifspeed); 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate static char * 1884*ba2e4443Sseb mac_link_state(const char *dev) 18857c478bd9Sstevel@tonic-gate { 18867c478bd9Sstevel@tonic-gate link_state_t link_state; 18877c478bd9Sstevel@tonic-gate char *state_str = "unknown"; 18887c478bd9Sstevel@tonic-gate 1889*ba2e4443Sseb if (get_single_mac_stat(dev, "link_state", KSTAT_DATA_UINT32, 1890*ba2e4443Sseb &link_state) != 0) { 18917c478bd9Sstevel@tonic-gate return (state_str); 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate switch (link_state) { 18957c478bd9Sstevel@tonic-gate case LINK_STATE_UP: 18967c478bd9Sstevel@tonic-gate state_str = "up"; 18977c478bd9Sstevel@tonic-gate break; 18987c478bd9Sstevel@tonic-gate case LINK_STATE_DOWN: 18997c478bd9Sstevel@tonic-gate state_str = "down"; 19007c478bd9Sstevel@tonic-gate break; 19017c478bd9Sstevel@tonic-gate default: 19027c478bd9Sstevel@tonic-gate break; 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate return (state_str); 19067c478bd9Sstevel@tonic-gate } 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate static char * 1910*ba2e4443Sseb mac_link_duplex(const char *dev) 19117c478bd9Sstevel@tonic-gate { 19127c478bd9Sstevel@tonic-gate link_duplex_t link_duplex; 19137c478bd9Sstevel@tonic-gate char *duplex_str = "unknown"; 19147c478bd9Sstevel@tonic-gate 1915*ba2e4443Sseb if (get_single_mac_stat(dev, "link_duplex", KSTAT_DATA_UINT32, 1916*ba2e4443Sseb &link_duplex) != 0) { 19177c478bd9Sstevel@tonic-gate return (duplex_str); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate switch (link_duplex) { 19217c478bd9Sstevel@tonic-gate case LINK_DUPLEX_FULL: 19227c478bd9Sstevel@tonic-gate duplex_str = "full"; 19237c478bd9Sstevel@tonic-gate break; 19247c478bd9Sstevel@tonic-gate case LINK_DUPLEX_HALF: 19257c478bd9Sstevel@tonic-gate duplex_str = "half"; 19267c478bd9Sstevel@tonic-gate break; 19277c478bd9Sstevel@tonic-gate default: 19287c478bd9Sstevel@tonic-gate break; 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate return (duplex_str); 19327c478bd9Sstevel@tonic-gate } 1933