1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <locale.h> 31*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 34*7c478bd9Sstevel@tonic-gate #include <string.h> 35*7c478bd9Sstevel@tonic-gate #include <stropts.h> 36*7c478bd9Sstevel@tonic-gate #include <errno.h> 37*7c478bd9Sstevel@tonic-gate #include <kstat.h> 38*7c478bd9Sstevel@tonic-gate #include <strings.h> 39*7c478bd9Sstevel@tonic-gate #include <getopt.h> 40*7c478bd9Sstevel@tonic-gate #include <unistd.h> 41*7c478bd9Sstevel@tonic-gate #include <libintl.h> 42*7c478bd9Sstevel@tonic-gate #include <libdlpi.h> 43*7c478bd9Sstevel@tonic-gate #include <libdladm.h> 44*7c478bd9Sstevel@tonic-gate #include <liblaadm.h> 45*7c478bd9Sstevel@tonic-gate #include <libmacadm.h> 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #define AGGR_DRIVER "aggr" 48*7c478bd9Sstevel@tonic-gate #define AGGR_DEV "aggr0" 49*7c478bd9Sstevel@tonic-gate #define MAXPORT 256 50*7c478bd9Sstevel@tonic-gate #define DUMP_LACP_FORMAT " %-9s %-8s %-7s %-12s " \ 51*7c478bd9Sstevel@tonic-gate "%-5s %-4s %-4s %-9s %-7s\n" 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate typedef struct pktsum_s { 54*7c478bd9Sstevel@tonic-gate uint64_t ipackets; 55*7c478bd9Sstevel@tonic-gate uint64_t opackets; 56*7c478bd9Sstevel@tonic-gate uint64_t rbytes; 57*7c478bd9Sstevel@tonic-gate uint64_t obytes; 58*7c478bd9Sstevel@tonic-gate uint32_t ierrors; 59*7c478bd9Sstevel@tonic-gate uint32_t oerrors; 60*7c478bd9Sstevel@tonic-gate } pktsum_t; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate typedef struct show_link_state { 63*7c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 64*7c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 65*7c478bd9Sstevel@tonic-gate boolean_t ls_stats; 66*7c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 67*7c478bd9Sstevel@tonic-gate boolean_t ls_parseable; 68*7c478bd9Sstevel@tonic-gate } show_link_state_t; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 71*7c478bd9Sstevel@tonic-gate uint32_t gs_key; 72*7c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 73*7c478bd9Sstevel@tonic-gate boolean_t gs_found; 74*7c478bd9Sstevel@tonic-gate boolean_t gs_stats; 75*7c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 76*7c478bd9Sstevel@tonic-gate pktsum_t gs_prevstats[MAXPORT]; 77*7c478bd9Sstevel@tonic-gate boolean_t gs_parseable; 78*7c478bd9Sstevel@tonic-gate } show_grp_state_t; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate typedef struct show_mac_state { 81*7c478bd9Sstevel@tonic-gate boolean_t ms_firstonly; 82*7c478bd9Sstevel@tonic-gate boolean_t ms_donefirst; 83*7c478bd9Sstevel@tonic-gate pktsum_t ms_prevstats; 84*7c478bd9Sstevel@tonic-gate boolean_t ms_parseable; 85*7c478bd9Sstevel@tonic-gate } show_mac_state_t; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate typedef struct port_state { 88*7c478bd9Sstevel@tonic-gate char *state_name; 89*7c478bd9Sstevel@tonic-gate aggr_port_state_t state_num; 90*7c478bd9Sstevel@tonic-gate } port_state_t; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static port_state_t port_states[] = { 93*7c478bd9Sstevel@tonic-gate {"standby", AGGR_PORT_STATE_STANDBY }, 94*7c478bd9Sstevel@tonic-gate {"attached", AGGR_PORT_STATE_ATTACHED } 95*7c478bd9Sstevel@tonic-gate }; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate #define NPORTSTATES (sizeof (port_states) / sizeof (port_state_t)) 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate static void do_create_vlan(int, char **); 100*7c478bd9Sstevel@tonic-gate static void do_delete_vlan(int, char **); 101*7c478bd9Sstevel@tonic-gate static void do_show_link(int, char **); 102*7c478bd9Sstevel@tonic-gate static void do_up_link(int, char **); 103*7c478bd9Sstevel@tonic-gate static void do_init_link(int, char **); 104*7c478bd9Sstevel@tonic-gate static void do_create_aggr(int, char **); 105*7c478bd9Sstevel@tonic-gate static void do_delete_aggr(int, char **); 106*7c478bd9Sstevel@tonic-gate static void do_add_aggr(int, char **); 107*7c478bd9Sstevel@tonic-gate static void do_remove_aggr(int, char **); 108*7c478bd9Sstevel@tonic-gate static void do_modify_aggr(int, char **); 109*7c478bd9Sstevel@tonic-gate static void do_show_aggr(int, char **); 110*7c478bd9Sstevel@tonic-gate static void do_up_aggr(int, char **); 111*7c478bd9Sstevel@tonic-gate static void do_down_aggr(int, char **); 112*7c478bd9Sstevel@tonic-gate static void do_show_dev(int, char **); 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate static void link_stats(const char *, uint32_t); 115*7c478bd9Sstevel@tonic-gate static void aggr_stats(uint16_t, uint32_t); 116*7c478bd9Sstevel@tonic-gate static void dev_stats(const char *dev, uint32_t); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate static void get_mac_stats(const char *, uint_t, pktsum_t *); 119*7c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 120*7c478bd9Sstevel@tonic-gate static uint64_t mac_ifspeed(const char *, uint_t); 121*7c478bd9Sstevel@tonic-gate static char *mac_link_state(const char *, uint_t); 122*7c478bd9Sstevel@tonic-gate static char *mac_link_duplex(const char *, uint_t); 123*7c478bd9Sstevel@tonic-gate static void stats_total(pktsum_t *, pktsum_t *, pktsum_t *); 124*7c478bd9Sstevel@tonic-gate static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *); 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate typedef struct cmd { 127*7c478bd9Sstevel@tonic-gate char *c_name; 128*7c478bd9Sstevel@tonic-gate void (*c_fn)(int, char **); 129*7c478bd9Sstevel@tonic-gate } cmd_t; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 132*7c478bd9Sstevel@tonic-gate { "create-vlan", do_create_vlan }, 133*7c478bd9Sstevel@tonic-gate { "delete-vlan", do_delete_vlan }, 134*7c478bd9Sstevel@tonic-gate { "show-link", do_show_link }, 135*7c478bd9Sstevel@tonic-gate { "up-link", do_up_link }, 136*7c478bd9Sstevel@tonic-gate { "init-link", do_init_link }, 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate { "create-aggr", do_create_aggr }, 139*7c478bd9Sstevel@tonic-gate { "delete-aggr", do_delete_aggr }, 140*7c478bd9Sstevel@tonic-gate { "add-aggr", do_add_aggr }, 141*7c478bd9Sstevel@tonic-gate { "remove-aggr", do_remove_aggr }, 142*7c478bd9Sstevel@tonic-gate { "modify-aggr", do_modify_aggr }, 143*7c478bd9Sstevel@tonic-gate { "show-aggr", do_show_aggr }, 144*7c478bd9Sstevel@tonic-gate { "up-aggr", do_up_aggr }, 145*7c478bd9Sstevel@tonic-gate { "down-aggr", do_down_aggr }, 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate { "show-dev", do_show_dev } 148*7c478bd9Sstevel@tonic-gate }; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate static const struct option longopts[] = { 151*7c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 152*7c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 153*7c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 154*7c478bd9Sstevel@tonic-gate {"lacp-mode", required_argument, 0, 'l'}, 155*7c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 156*7c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 157*7c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 158*7c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 159*7c478bd9Sstevel@tonic-gate {"lacp", no_argument, 0, 'L'}, 160*7c478bd9Sstevel@tonic-gate {"temporary", no_argument, 0, 't'}, 161*7c478bd9Sstevel@tonic-gate {"root-dir", required_argument, 0, 'r'}, 162*7c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 163*7c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 164*7c478bd9Sstevel@tonic-gate }; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate static char *progname; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate #define PRINT_ERR_DIAG(s, diag, func) { \ 169*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(s), progname, strerror(errno)); \ 170*7c478bd9Sstevel@tonic-gate if (diag != 0) \ 171*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", func(diag)); \ 172*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); \ 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate static void 176*7c478bd9Sstevel@tonic-gate usage(void) 177*7c478bd9Sstevel@tonic-gate { 178*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 179*7c478bd9Sstevel@tonic-gate "usage: dladm create-vlan [-t] [-R <root-dir>] -v <vlan> -d <dev>\n" 180*7c478bd9Sstevel@tonic-gate " delete-vlan [-t] [-R <root-dir>] -v <vlan> -d <dev>\n" 181*7c478bd9Sstevel@tonic-gate " create-aggr [-t] [-R <root-dir>] [-P <policy>]\n" 182*7c478bd9Sstevel@tonic-gate " [-l <mode>] [-T <time>]\n" 183*7c478bd9Sstevel@tonic-gate " [-u <address>] -d <dev> ... <key>\n" 184*7c478bd9Sstevel@tonic-gate " delete-aggr [-t] [-R <root-dir>] <key>\n" 185*7c478bd9Sstevel@tonic-gate " add-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n" 186*7c478bd9Sstevel@tonic-gate " remove-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n" 187*7c478bd9Sstevel@tonic-gate " modify-aggr [-t] [-R <root-dir>] [-P <policy>]\n" 188*7c478bd9Sstevel@tonic-gate " [-l <mode>] [-T <time>] [-u <address>] <key>\n" 189*7c478bd9Sstevel@tonic-gate " show-aggr [-L] [-s] [-i <interval>] [-p] [<key>]\n" 190*7c478bd9Sstevel@tonic-gate " show-dev [-s] [-i <interval>] [-p] [<dev>]\n" 191*7c478bd9Sstevel@tonic-gate " show-link [-s] [-i <interval>] [-p] [<name>]\n")); 192*7c478bd9Sstevel@tonic-gate exit(1); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate int 196*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate int i; 199*7c478bd9Sstevel@tonic-gate cmd_t *cmdp; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 202*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 203*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 204*7c478bd9Sstevel@tonic-gate #endif 205*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate progname = argv[0]; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (argc < 2) 210*7c478bd9Sstevel@tonic-gate usage(); 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 213*7c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 214*7c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 215*7c478bd9Sstevel@tonic-gate cmdp->c_fn(argc - 1, &argv[1]); 216*7c478bd9Sstevel@tonic-gate exit(0); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 221*7c478bd9Sstevel@tonic-gate progname, argv[1]); 222*7c478bd9Sstevel@tonic-gate usage(); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate return (0); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate static void 228*7c478bd9Sstevel@tonic-gate do_create_vlan(int argc, char *argv[]) 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 231*7c478bd9Sstevel@tonic-gate char driver[MAXNAMELEN]; 232*7c478bd9Sstevel@tonic-gate int instance; 233*7c478bd9Sstevel@tonic-gate dladm_attr_t dlattr; 234*7c478bd9Sstevel@tonic-gate int value; 235*7c478bd9Sstevel@tonic-gate char option; 236*7c478bd9Sstevel@tonic-gate boolean_t v_arg = B_FALSE; 237*7c478bd9Sstevel@tonic-gate boolean_t d_arg = B_FALSE; 238*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 239*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 240*7c478bd9Sstevel@tonic-gate char *endp = NULL; 241*7c478bd9Sstevel@tonic-gate dladm_diag_t diag = 0; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate bzero(&dlattr, sizeof (dladm_attr_t)); 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate opterr = 0; 246*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:tv:", longopts, 247*7c478bd9Sstevel@tonic-gate NULL)) != -1) { 248*7c478bd9Sstevel@tonic-gate switch (option) { 249*7c478bd9Sstevel@tonic-gate case 'v': 250*7c478bd9Sstevel@tonic-gate if (v_arg) { 251*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option " 252*7c478bd9Sstevel@tonic-gate "-v cannot be specified more than once\n"), 253*7c478bd9Sstevel@tonic-gate progname); 254*7c478bd9Sstevel@tonic-gate usage(); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate v_arg = B_TRUE; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate errno = 0; 260*7c478bd9Sstevel@tonic-gate value = (int)strtol(optarg, &endp, 10); 261*7c478bd9Sstevel@tonic-gate if (errno != 0 || value < 1 || value > 4094 || 262*7c478bd9Sstevel@tonic-gate *endp != '\0') { 263*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 264*7c478bd9Sstevel@tonic-gate gettext("%s: illegal VLAN identifier" 265*7c478bd9Sstevel@tonic-gate " '%d'\n"), progname, value); 266*7c478bd9Sstevel@tonic-gate exit(1); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate dlattr.da_vid = (uint16_t)value; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate break; 272*7c478bd9Sstevel@tonic-gate case 'd': 273*7c478bd9Sstevel@tonic-gate if (d_arg) { 274*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 275*7c478bd9Sstevel@tonic-gate "%s: the option -d cannot be specified " 276*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 277*7c478bd9Sstevel@tonic-gate usage(); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate d_arg = B_TRUE; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (strlcpy(dlattr.da_dev, optarg, MAXNAMELEN) >= 283*7c478bd9Sstevel@tonic-gate MAXNAMELEN) { 284*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 285*7c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 286*7c478bd9Sstevel@tonic-gate progname); 287*7c478bd9Sstevel@tonic-gate exit(1); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate break; 290*7c478bd9Sstevel@tonic-gate case 't': 291*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 292*7c478bd9Sstevel@tonic-gate break; 293*7c478bd9Sstevel@tonic-gate case 'R': 294*7c478bd9Sstevel@tonic-gate altroot = optarg; 295*7c478bd9Sstevel@tonic-gate break; 296*7c478bd9Sstevel@tonic-gate case ':': 297*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 298*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 299*7c478bd9Sstevel@tonic-gate progname, optopt); 300*7c478bd9Sstevel@tonic-gate exit(1); 301*7c478bd9Sstevel@tonic-gate break; 302*7c478bd9Sstevel@tonic-gate case '?': 303*7c478bd9Sstevel@tonic-gate default: 304*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 305*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 306*7c478bd9Sstevel@tonic-gate progname, optopt); 307*7c478bd9Sstevel@tonic-gate exit(1); 308*7c478bd9Sstevel@tonic-gate break; 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate if (optind != argc) { 313*7c478bd9Sstevel@tonic-gate usage(); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate if (dlattr.da_dev[0] == '\0') { 317*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 318*7c478bd9Sstevel@tonic-gate gettext("%s: no device specified\n"), 319*7c478bd9Sstevel@tonic-gate progname); 320*7c478bd9Sstevel@tonic-gate exit(1); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate if (dlattr.da_vid == 0) { 324*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 325*7c478bd9Sstevel@tonic-gate gettext("%s: no VLAN ID specified\n"), 326*7c478bd9Sstevel@tonic-gate progname); 327*7c478bd9Sstevel@tonic-gate exit(1); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate if (dlpi_if_parse(dlattr.da_dev, driver, &instance) < 0 || 331*7c478bd9Sstevel@tonic-gate instance < 0) { 332*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 333*7c478bd9Sstevel@tonic-gate gettext("%s: badly formatted device '%s'\n"), 334*7c478bd9Sstevel@tonic-gate progname, dlattr.da_dev); 335*7c478bd9Sstevel@tonic-gate exit(1); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN, "%s%d", driver, 339*7c478bd9Sstevel@tonic-gate (dlattr.da_vid * 1000) + instance); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * For aggregations, the da_dev is always AGGR_DEV, and the 343*7c478bd9Sstevel@tonic-gate * aggregation key (the instance integer extracted above by 344*7c478bd9Sstevel@tonic-gate * dlpi_if_parse) is da_port. 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate if (strcmp(driver, AGGR_DRIVER) == 0) { 347*7c478bd9Sstevel@tonic-gate (void) strlcpy(dlattr.da_dev, AGGR_DEV, MAXNAMELEN); 348*7c478bd9Sstevel@tonic-gate dlattr.da_port = instance; 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (dladm_link(name, &dlattr, (t_arg ? DLADM_LINK_TEMP : 0), 352*7c478bd9Sstevel@tonic-gate altroot, &diag) < 0) { 353*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: link operation failed: %s", diag, 354*7c478bd9Sstevel@tonic-gate dladm_diag); 355*7c478bd9Sstevel@tonic-gate exit(1); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if (dladm_sync() < 0) { 359*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 360*7c478bd9Sstevel@tonic-gate gettext("%s: sync operation failed"), 361*7c478bd9Sstevel@tonic-gate progname); 362*7c478bd9Sstevel@tonic-gate perror(" "); 363*7c478bd9Sstevel@tonic-gate exit(1); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate static void 368*7c478bd9Sstevel@tonic-gate do_delete_vlan(int argc, char *argv[]) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate char option; 371*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 372*7c478bd9Sstevel@tonic-gate boolean_t v_arg = B_FALSE; 373*7c478bd9Sstevel@tonic-gate boolean_t d_arg = B_FALSE; 374*7c478bd9Sstevel@tonic-gate char device[MAXNAMELEN]; 375*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 376*7c478bd9Sstevel@tonic-gate char driver[MAXNAMELEN]; 377*7c478bd9Sstevel@tonic-gate int instance; 378*7c478bd9Sstevel@tonic-gate int vid; 379*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 380*7c478bd9Sstevel@tonic-gate char *endp = NULL; 381*7c478bd9Sstevel@tonic-gate dladm_diag_t diag = 0; 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate opterr = 0; 384*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":R:td:v:", longopts, 385*7c478bd9Sstevel@tonic-gate NULL)) != -1) { 386*7c478bd9Sstevel@tonic-gate switch (option) { 387*7c478bd9Sstevel@tonic-gate case 'v': 388*7c478bd9Sstevel@tonic-gate if (v_arg) { 389*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option " 390*7c478bd9Sstevel@tonic-gate "-v cannot be specified more than once\n"), 391*7c478bd9Sstevel@tonic-gate progname); 392*7c478bd9Sstevel@tonic-gate usage(); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate v_arg = B_TRUE; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate errno = 0; 398*7c478bd9Sstevel@tonic-gate vid = (int)strtol(optarg, &endp, 10); 399*7c478bd9Sstevel@tonic-gate if (errno != 0 || vid < 1 || vid > 4094 || 400*7c478bd9Sstevel@tonic-gate *endp != '\0') { 401*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 402*7c478bd9Sstevel@tonic-gate gettext("%s: illegal VLAN identifier" 403*7c478bd9Sstevel@tonic-gate " '%d'\n"), progname, vid); 404*7c478bd9Sstevel@tonic-gate exit(1); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate case 'd': 409*7c478bd9Sstevel@tonic-gate if (d_arg) { 410*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 411*7c478bd9Sstevel@tonic-gate "%s: the option -d cannot be specified " 412*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 413*7c478bd9Sstevel@tonic-gate usage(); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate d_arg = B_TRUE; 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate if (strlcpy(device, optarg, MAXNAMELEN) >= 419*7c478bd9Sstevel@tonic-gate MAXNAMELEN) { 420*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 421*7c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 422*7c478bd9Sstevel@tonic-gate progname); 423*7c478bd9Sstevel@tonic-gate exit(1); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate break; 426*7c478bd9Sstevel@tonic-gate case 't': 427*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 428*7c478bd9Sstevel@tonic-gate break; 429*7c478bd9Sstevel@tonic-gate case 'R': 430*7c478bd9Sstevel@tonic-gate altroot = optarg; 431*7c478bd9Sstevel@tonic-gate break; 432*7c478bd9Sstevel@tonic-gate case ':': 433*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 434*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 435*7c478bd9Sstevel@tonic-gate progname, optopt); 436*7c478bd9Sstevel@tonic-gate exit(1); 437*7c478bd9Sstevel@tonic-gate break; 438*7c478bd9Sstevel@tonic-gate case '?': 439*7c478bd9Sstevel@tonic-gate default: 440*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 441*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 442*7c478bd9Sstevel@tonic-gate progname, optopt); 443*7c478bd9Sstevel@tonic-gate exit(1); 444*7c478bd9Sstevel@tonic-gate break; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (optind != argc) 449*7c478bd9Sstevel@tonic-gate usage(); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate if (d_arg == B_FALSE) { 452*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 453*7c478bd9Sstevel@tonic-gate gettext("%s: no device specified\n"), 454*7c478bd9Sstevel@tonic-gate progname); 455*7c478bd9Sstevel@tonic-gate exit(1); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate if (v_arg == B_FALSE) { 459*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 460*7c478bd9Sstevel@tonic-gate gettext("%s: no VLAN ID specified\n"), 461*7c478bd9Sstevel@tonic-gate progname); 462*7c478bd9Sstevel@tonic-gate exit(1); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate if (dlpi_if_parse(device, driver, &instance) < 0 || 466*7c478bd9Sstevel@tonic-gate instance < 0) { 467*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 468*7c478bd9Sstevel@tonic-gate gettext("%s: badly formatted device '%s'\n"), 469*7c478bd9Sstevel@tonic-gate progname, device); 470*7c478bd9Sstevel@tonic-gate exit(1); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN, "%s%d", driver, 474*7c478bd9Sstevel@tonic-gate (vid * 1000) + instance); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate if (dladm_unlink(name, t_arg, altroot, &diag) < 0) { 477*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: unlink operation failed: %s", diag, 478*7c478bd9Sstevel@tonic-gate dladm_diag); 479*7c478bd9Sstevel@tonic-gate exit(1); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate if (dladm_sync() < 0) { 483*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 484*7c478bd9Sstevel@tonic-gate gettext("%s: sync operation failed"), 485*7c478bd9Sstevel@tonic-gate progname); 486*7c478bd9Sstevel@tonic-gate perror(" "); 487*7c478bd9Sstevel@tonic-gate exit(1); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate static void 492*7c478bd9Sstevel@tonic-gate do_create_aggr(int argc, char *argv[]) 493*7c478bd9Sstevel@tonic-gate { 494*7c478bd9Sstevel@tonic-gate char option; 495*7c478bd9Sstevel@tonic-gate uint16_t key; 496*7c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 497*7c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 498*7c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 499*7c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 500*7c478bd9Sstevel@tonic-gate uint_t nport = 0; 501*7c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 502*7c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 503*7c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 504*7c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 505*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 506*7c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 507*7c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 508*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 509*7c478bd9Sstevel@tonic-gate char *endp = NULL; 510*7c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate opterr = 0; 513*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:l:P:R:tu:T:", 514*7c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 515*7c478bd9Sstevel@tonic-gate switch (option) { 516*7c478bd9Sstevel@tonic-gate case 'd': 517*7c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 518*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 519*7c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 520*7c478bd9Sstevel@tonic-gate progname); 521*7c478bd9Sstevel@tonic-gate exit(1); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 525*7c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 526*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 527*7c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 528*7c478bd9Sstevel@tonic-gate progname); 529*7c478bd9Sstevel@tonic-gate exit(1); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate port[nport].lp_port = 0; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate nport++; 535*7c478bd9Sstevel@tonic-gate break; 536*7c478bd9Sstevel@tonic-gate case 'P': 537*7c478bd9Sstevel@tonic-gate if (P_arg) { 538*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 539*7c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 540*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 541*7c478bd9Sstevel@tonic-gate usage(); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 547*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 548*7c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 549*7c478bd9Sstevel@tonic-gate progname, optarg); 550*7c478bd9Sstevel@tonic-gate exit(1); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate break; 553*7c478bd9Sstevel@tonic-gate case 'u': 554*7c478bd9Sstevel@tonic-gate if (u_arg) { 555*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 556*7c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 557*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 558*7c478bd9Sstevel@tonic-gate usage(); 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 564*7c478bd9Sstevel@tonic-gate mac_addr)) { 565*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 566*7c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 567*7c478bd9Sstevel@tonic-gate progname, optarg); 568*7c478bd9Sstevel@tonic-gate exit(1); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate break; 572*7c478bd9Sstevel@tonic-gate case 'l': 573*7c478bd9Sstevel@tonic-gate if (l_arg) { 574*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 575*7c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 576*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 577*7c478bd9Sstevel@tonic-gate usage(); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 583*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 584*7c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 585*7c478bd9Sstevel@tonic-gate progname, optarg); 586*7c478bd9Sstevel@tonic-gate exit(1); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate break; 590*7c478bd9Sstevel@tonic-gate case 'T': 591*7c478bd9Sstevel@tonic-gate if (T_arg) { 592*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 593*7c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 594*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 595*7c478bd9Sstevel@tonic-gate usage(); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 601*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 602*7c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 603*7c478bd9Sstevel@tonic-gate " '%s'\n"), 604*7c478bd9Sstevel@tonic-gate progname, optarg); 605*7c478bd9Sstevel@tonic-gate exit(1); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate break; 609*7c478bd9Sstevel@tonic-gate case 't': 610*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 611*7c478bd9Sstevel@tonic-gate break; 612*7c478bd9Sstevel@tonic-gate case 'R': 613*7c478bd9Sstevel@tonic-gate altroot = optarg; 614*7c478bd9Sstevel@tonic-gate break; 615*7c478bd9Sstevel@tonic-gate case ':': 616*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 617*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 618*7c478bd9Sstevel@tonic-gate progname, optopt); 619*7c478bd9Sstevel@tonic-gate exit(1); 620*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 621*7c478bd9Sstevel@tonic-gate case '?': 622*7c478bd9Sstevel@tonic-gate default: 623*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 624*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 625*7c478bd9Sstevel@tonic-gate progname, optopt); 626*7c478bd9Sstevel@tonic-gate exit(1); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate if (nport == 0) 631*7c478bd9Sstevel@tonic-gate usage(); 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 634*7c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 635*7c478bd9Sstevel@tonic-gate usage(); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate errno = 0; 638*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 639*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 640*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 641*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 642*7c478bd9Sstevel@tonic-gate progname, key); 643*7c478bd9Sstevel@tonic-gate exit(1); 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate if (laadm_create(key, nport, port, policy, mac_addr_fixed, 647*7c478bd9Sstevel@tonic-gate mac_addr, lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 648*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: create operation failed: %s", diag, 649*7c478bd9Sstevel@tonic-gate laadm_diag); 650*7c478bd9Sstevel@tonic-gate exit(1); 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate static void 655*7c478bd9Sstevel@tonic-gate do_delete_aggr(int argc, char *argv[]) 656*7c478bd9Sstevel@tonic-gate { 657*7c478bd9Sstevel@tonic-gate uint16_t key; 658*7c478bd9Sstevel@tonic-gate char option; 659*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 660*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 661*7c478bd9Sstevel@tonic-gate char *endp = NULL; 662*7c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate opterr = 0; 665*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":R:t", longopts, 666*7c478bd9Sstevel@tonic-gate NULL)) != -1) { 667*7c478bd9Sstevel@tonic-gate switch (option) { 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate case 't': 670*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 671*7c478bd9Sstevel@tonic-gate break; 672*7c478bd9Sstevel@tonic-gate case 'R': 673*7c478bd9Sstevel@tonic-gate altroot = optarg; 674*7c478bd9Sstevel@tonic-gate break; 675*7c478bd9Sstevel@tonic-gate case ':': 676*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 677*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 678*7c478bd9Sstevel@tonic-gate progname, optopt); 679*7c478bd9Sstevel@tonic-gate exit(1); 680*7c478bd9Sstevel@tonic-gate break; 681*7c478bd9Sstevel@tonic-gate case '?': 682*7c478bd9Sstevel@tonic-gate default: 683*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 684*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 685*7c478bd9Sstevel@tonic-gate progname, optopt); 686*7c478bd9Sstevel@tonic-gate exit(1); 687*7c478bd9Sstevel@tonic-gate break; 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 692*7c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 693*7c478bd9Sstevel@tonic-gate usage(); 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate errno = 0; 696*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 697*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 698*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 699*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 700*7c478bd9Sstevel@tonic-gate progname, key); 701*7c478bd9Sstevel@tonic-gate exit(1); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate if (laadm_delete(key, t_arg, altroot, &diag) < 0) { 705*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: delete operation failed: %s", diag, 706*7c478bd9Sstevel@tonic-gate laadm_diag); 707*7c478bd9Sstevel@tonic-gate exit(1); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate static void 712*7c478bd9Sstevel@tonic-gate do_add_aggr(int argc, char *argv[]) 713*7c478bd9Sstevel@tonic-gate { 714*7c478bd9Sstevel@tonic-gate char option; 715*7c478bd9Sstevel@tonic-gate uint16_t key; 716*7c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 717*7c478bd9Sstevel@tonic-gate uint_t nport = 0; 718*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 719*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 720*7c478bd9Sstevel@tonic-gate char *endp = NULL; 721*7c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate opterr = 0; 724*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", longopts, 725*7c478bd9Sstevel@tonic-gate NULL)) != -1) { 726*7c478bd9Sstevel@tonic-gate switch (option) { 727*7c478bd9Sstevel@tonic-gate case 'd': 728*7c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 729*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 730*7c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 731*7c478bd9Sstevel@tonic-gate progname); 732*7c478bd9Sstevel@tonic-gate exit(1); 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 736*7c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 737*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 738*7c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 739*7c478bd9Sstevel@tonic-gate progname); 740*7c478bd9Sstevel@tonic-gate exit(1); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate port[nport].lp_port = 0; 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate nport++; 745*7c478bd9Sstevel@tonic-gate break; 746*7c478bd9Sstevel@tonic-gate case 't': 747*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 748*7c478bd9Sstevel@tonic-gate break; 749*7c478bd9Sstevel@tonic-gate case 'R': 750*7c478bd9Sstevel@tonic-gate altroot = optarg; 751*7c478bd9Sstevel@tonic-gate break; 752*7c478bd9Sstevel@tonic-gate case ':': 753*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 754*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 755*7c478bd9Sstevel@tonic-gate progname, optopt); 756*7c478bd9Sstevel@tonic-gate exit(1); 757*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 758*7c478bd9Sstevel@tonic-gate case '?': 759*7c478bd9Sstevel@tonic-gate default: 760*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 761*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 762*7c478bd9Sstevel@tonic-gate progname, optopt); 763*7c478bd9Sstevel@tonic-gate exit(1); 764*7c478bd9Sstevel@tonic-gate } 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate if (nport == 0) 768*7c478bd9Sstevel@tonic-gate usage(); 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 771*7c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 772*7c478bd9Sstevel@tonic-gate usage(); 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate errno = 0; 775*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 776*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 777*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 778*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 779*7c478bd9Sstevel@tonic-gate progname, key); 780*7c478bd9Sstevel@tonic-gate exit(1); 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate if (laadm_add(key, nport, port, t_arg, altroot, &diag) < 0) { 784*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: add operation failed: %s", diag, 785*7c478bd9Sstevel@tonic-gate laadm_diag); 786*7c478bd9Sstevel@tonic-gate exit(1); 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate static void 791*7c478bd9Sstevel@tonic-gate do_remove_aggr(int argc, char *argv[]) 792*7c478bd9Sstevel@tonic-gate { 793*7c478bd9Sstevel@tonic-gate char option; 794*7c478bd9Sstevel@tonic-gate uint16_t key; 795*7c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 796*7c478bd9Sstevel@tonic-gate uint_t nport = 0; 797*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 798*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 799*7c478bd9Sstevel@tonic-gate char *endp = NULL; 800*7c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate opterr = 0; 803*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", 804*7c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 805*7c478bd9Sstevel@tonic-gate switch (option) { 806*7c478bd9Sstevel@tonic-gate case 'd': 807*7c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 808*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 809*7c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 810*7c478bd9Sstevel@tonic-gate progname); 811*7c478bd9Sstevel@tonic-gate exit(1); 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 815*7c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 816*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 817*7c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 818*7c478bd9Sstevel@tonic-gate progname); 819*7c478bd9Sstevel@tonic-gate exit(1); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate port[nport].lp_port = 0; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate nport++; 824*7c478bd9Sstevel@tonic-gate break; 825*7c478bd9Sstevel@tonic-gate case 't': 826*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 827*7c478bd9Sstevel@tonic-gate break; 828*7c478bd9Sstevel@tonic-gate case 'R': 829*7c478bd9Sstevel@tonic-gate altroot = optarg; 830*7c478bd9Sstevel@tonic-gate break; 831*7c478bd9Sstevel@tonic-gate case ':': 832*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 833*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 834*7c478bd9Sstevel@tonic-gate progname, optopt); 835*7c478bd9Sstevel@tonic-gate exit(1); 836*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 837*7c478bd9Sstevel@tonic-gate case '?': 838*7c478bd9Sstevel@tonic-gate default: 839*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 840*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 841*7c478bd9Sstevel@tonic-gate progname, optopt); 842*7c478bd9Sstevel@tonic-gate exit(1); 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate if (nport == 0) 847*7c478bd9Sstevel@tonic-gate usage(); 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 850*7c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 851*7c478bd9Sstevel@tonic-gate usage(); 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate errno = 0; 854*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 855*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 856*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 857*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 858*7c478bd9Sstevel@tonic-gate progname, key); 859*7c478bd9Sstevel@tonic-gate exit(1); 860*7c478bd9Sstevel@tonic-gate } 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate if (laadm_remove(key, nport, port, t_arg, altroot, &diag) < 0) { 863*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: remove operation failed: %s", diag, 864*7c478bd9Sstevel@tonic-gate laadm_diag); 865*7c478bd9Sstevel@tonic-gate exit(1); 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate static void 870*7c478bd9Sstevel@tonic-gate do_modify_aggr(int argc, char *argv[]) 871*7c478bd9Sstevel@tonic-gate { 872*7c478bd9Sstevel@tonic-gate char option; 873*7c478bd9Sstevel@tonic-gate uint16_t key; 874*7c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 875*7c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 876*7c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 877*7c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 878*7c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 879*7c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 880*7c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 881*7c478bd9Sstevel@tonic-gate char *altroot = NULL; 882*7c478bd9Sstevel@tonic-gate char *endp = NULL; 883*7c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate opterr = 0; 886*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":l:P:R:tu:T:", longopts, 887*7c478bd9Sstevel@tonic-gate NULL)) != -1) { 888*7c478bd9Sstevel@tonic-gate switch (option) { 889*7c478bd9Sstevel@tonic-gate case 'P': 890*7c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_POLICY) { 891*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 892*7c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 893*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 894*7c478bd9Sstevel@tonic-gate usage(); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_POLICY; 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 900*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 901*7c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 902*7c478bd9Sstevel@tonic-gate progname, optarg); 903*7c478bd9Sstevel@tonic-gate exit(1); 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate break; 906*7c478bd9Sstevel@tonic-gate case 'u': 907*7c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_MAC) { 908*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 909*7c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 910*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 911*7c478bd9Sstevel@tonic-gate usage(); 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_MAC; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 917*7c478bd9Sstevel@tonic-gate mac_addr)) { 918*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 919*7c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 920*7c478bd9Sstevel@tonic-gate progname, optarg); 921*7c478bd9Sstevel@tonic-gate exit(1); 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate break; 925*7c478bd9Sstevel@tonic-gate case 'l': 926*7c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_MODE) { 927*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 928*7c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 929*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 930*7c478bd9Sstevel@tonic-gate usage(); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_MODE; 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 936*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 937*7c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 938*7c478bd9Sstevel@tonic-gate progname, optarg); 939*7c478bd9Sstevel@tonic-gate exit(1); 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate break; 943*7c478bd9Sstevel@tonic-gate case 'T': 944*7c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_TIMER) { 945*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 946*7c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 947*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 948*7c478bd9Sstevel@tonic-gate usage(); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_TIMER; 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 954*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 955*7c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 956*7c478bd9Sstevel@tonic-gate " '%s'\n"), 957*7c478bd9Sstevel@tonic-gate progname, optarg); 958*7c478bd9Sstevel@tonic-gate exit(1); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate break; 962*7c478bd9Sstevel@tonic-gate case 't': 963*7c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 964*7c478bd9Sstevel@tonic-gate break; 965*7c478bd9Sstevel@tonic-gate case 'R': 966*7c478bd9Sstevel@tonic-gate altroot = optarg; 967*7c478bd9Sstevel@tonic-gate break; 968*7c478bd9Sstevel@tonic-gate case ':': 969*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 970*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 971*7c478bd9Sstevel@tonic-gate progname, optopt); 972*7c478bd9Sstevel@tonic-gate exit(1); 973*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 974*7c478bd9Sstevel@tonic-gate case '?': 975*7c478bd9Sstevel@tonic-gate default: 976*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 977*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 978*7c478bd9Sstevel@tonic-gate progname, optopt); 979*7c478bd9Sstevel@tonic-gate exit(1); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate } 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate if (modify_mask == 0) { 984*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: at least one of the " 985*7c478bd9Sstevel@tonic-gate "-PulT options must be specified\n"), progname); 986*7c478bd9Sstevel@tonic-gate usage(); 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 990*7c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 991*7c478bd9Sstevel@tonic-gate usage(); 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate errno = 0; 994*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 995*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 996*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 997*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 998*7c478bd9Sstevel@tonic-gate progname, key); 999*7c478bd9Sstevel@tonic-gate exit(1); 1000*7c478bd9Sstevel@tonic-gate } 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate if (laadm_modify(key, modify_mask, policy, mac_addr_fixed, mac_addr, 1004*7c478bd9Sstevel@tonic-gate lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 1005*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: modify operation failed: %s", diag, 1006*7c478bd9Sstevel@tonic-gate laadm_diag); 1007*7c478bd9Sstevel@tonic-gate exit(1); 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate static void 1012*7c478bd9Sstevel@tonic-gate do_up_link(int argc, char *argv[]) 1013*7c478bd9Sstevel@tonic-gate { 1014*7c478bd9Sstevel@tonic-gate char *name = NULL; 1015*7c478bd9Sstevel@tonic-gate dladm_diag_t diag = 0; 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 1018*7c478bd9Sstevel@tonic-gate if (argc == 2) 1019*7c478bd9Sstevel@tonic-gate name = argv[1]; 1020*7c478bd9Sstevel@tonic-gate else if (argc > 2) 1021*7c478bd9Sstevel@tonic-gate usage(); 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate if (dladm_up(name, &diag) < 0) { 1024*7c478bd9Sstevel@tonic-gate if (name != NULL) { 1025*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1026*7c478bd9Sstevel@tonic-gate gettext("%s: could not bring up link '%s' : %s"), 1027*7c478bd9Sstevel@tonic-gate progname, name, strerror(errno)); 1028*7c478bd9Sstevel@tonic-gate if (diag != 0) 1029*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", 1030*7c478bd9Sstevel@tonic-gate dladm_diag(diag)); 1031*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 1032*7c478bd9Sstevel@tonic-gate } else { 1033*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: could not bring links up: %s", 1034*7c478bd9Sstevel@tonic-gate diag, dladm_diag); 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate exit(1); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate static void 1041*7c478bd9Sstevel@tonic-gate do_up_aggr(int argc, char *argv[]) 1042*7c478bd9Sstevel@tonic-gate { 1043*7c478bd9Sstevel@tonic-gate uint16_t key = 0; 1044*7c478bd9Sstevel@tonic-gate char *endp = NULL; 1045*7c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 1048*7c478bd9Sstevel@tonic-gate if (argc == 2) { 1049*7c478bd9Sstevel@tonic-gate errno = 0; 1050*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 1051*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 1052*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1053*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 1054*7c478bd9Sstevel@tonic-gate progname, key); 1055*7c478bd9Sstevel@tonic-gate exit(1); 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate } else if (argc > 2) { 1058*7c478bd9Sstevel@tonic-gate usage(); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate if (laadm_up(key, NULL, &diag) < 0) { 1062*7c478bd9Sstevel@tonic-gate if (key != 0) { 1063*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1064*7c478bd9Sstevel@tonic-gate gettext("%s: could not bring up aggregation" 1065*7c478bd9Sstevel@tonic-gate " '%u' : %s"), progname, key, strerror(errno)); 1066*7c478bd9Sstevel@tonic-gate if (diag != 0) 1067*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", 1068*7c478bd9Sstevel@tonic-gate laadm_diag(diag)); 1069*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 1070*7c478bd9Sstevel@tonic-gate } else { 1071*7c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG( 1072*7c478bd9Sstevel@tonic-gate "%s: could not bring aggregations up: %s", 1073*7c478bd9Sstevel@tonic-gate diag, laadm_diag); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate exit(1); 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate static void 1080*7c478bd9Sstevel@tonic-gate do_down_aggr(int argc, char *argv[]) 1081*7c478bd9Sstevel@tonic-gate { 1082*7c478bd9Sstevel@tonic-gate uint16_t key = 0; 1083*7c478bd9Sstevel@tonic-gate char *endp = NULL; 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 1086*7c478bd9Sstevel@tonic-gate if (argc == 2) { 1087*7c478bd9Sstevel@tonic-gate errno = 0; 1088*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 1089*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 1090*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1091*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 1092*7c478bd9Sstevel@tonic-gate progname, key); 1093*7c478bd9Sstevel@tonic-gate exit(1); 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate } else if (argc > 2) { 1096*7c478bd9Sstevel@tonic-gate usage(); 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate if (laadm_down(key) < 0) { 1100*7c478bd9Sstevel@tonic-gate if (key != 0) { 1101*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1102*7c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregation" 1103*7c478bd9Sstevel@tonic-gate " down '%u' : %s"), 1104*7c478bd9Sstevel@tonic-gate progname, key, strerror(errno)); 1105*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 1106*7c478bd9Sstevel@tonic-gate } else { 1107*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1108*7c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregations" 1109*7c478bd9Sstevel@tonic-gate " down: %s"), progname, strerror(errno)); 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate exit(1); 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate static void 1116*7c478bd9Sstevel@tonic-gate create(void *arg, const char *dev, uint_t port) 1117*7c478bd9Sstevel@tonic-gate { 1118*7c478bd9Sstevel@tonic-gate dladm_attr_t dlattr; 1119*7c478bd9Sstevel@tonic-gate dladm_diag_t diag; 1120*7c478bd9Sstevel@tonic-gate int flags; 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate if (port != 0) 1123*7c478bd9Sstevel@tonic-gate return; 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate if (strlcpy(dlattr.da_dev, dev, MAXNAMELEN) >= MAXNAMELEN) { 1126*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1127*7c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 1128*7c478bd9Sstevel@tonic-gate progname); 1129*7c478bd9Sstevel@tonic-gate exit(1); 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate dlattr.da_port = 0; 1133*7c478bd9Sstevel@tonic-gate dlattr.da_vid = 0; 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate flags = DLADM_LINK_FORCED; 1136*7c478bd9Sstevel@tonic-gate if (arg != NULL) 1137*7c478bd9Sstevel@tonic-gate flags |= DLADM_LINK_TEMP; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate (void) dladm_link(dlattr.da_dev, &dlattr, flags, NULL, &diag); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1143*7c478bd9Sstevel@tonic-gate static void 1144*7c478bd9Sstevel@tonic-gate do_init_link(int argc, char *argv[]) 1145*7c478bd9Sstevel@tonic-gate { 1146*7c478bd9Sstevel@tonic-gate if (argc != 1 && strcmp(argv[1], "-t") != 0) 1147*7c478bd9Sstevel@tonic-gate usage(); 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate (void) macadm_walk(create, (void *)(argc > 1), B_FALSE); 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate #define TYPE_WIDTH 10 1153*7c478bd9Sstevel@tonic-gate #define MAC_WIDTH 23 1154*7c478bd9Sstevel@tonic-gate #define MTU_WIDTH 11 1155*7c478bd9Sstevel@tonic-gate #define STATE_WIDTH 15 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1158*7c478bd9Sstevel@tonic-gate static void 1159*7c478bd9Sstevel@tonic-gate show_link(void *arg, const char *name) 1160*7c478bd9Sstevel@tonic-gate { 1161*7c478bd9Sstevel@tonic-gate dladm_attr_t dlattr; 1162*7c478bd9Sstevel@tonic-gate char type[TYPE_WIDTH]; 1163*7c478bd9Sstevel@tonic-gate int fd; 1164*7c478bd9Sstevel@tonic-gate dlpi_if_attr_t dia; 1165*7c478bd9Sstevel@tonic-gate dl_info_ack_t dlia; 1166*7c478bd9Sstevel@tonic-gate t_uscalar_t dl_max_sdu; 1167*7c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 && 1170*7c478bd9Sstevel@tonic-gate dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, 1171*7c478bd9Sstevel@tonic-gate NULL, NULL) != -1) { 1172*7c478bd9Sstevel@tonic-gate (void) dlpi_close(fd); 1173*7c478bd9Sstevel@tonic-gate dl_max_sdu = dlia.dl_max_sdu; 1174*7c478bd9Sstevel@tonic-gate } else { 1175*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1176*7c478bd9Sstevel@tonic-gate gettext("%s: invalid device '%s'\n"), 1177*7c478bd9Sstevel@tonic-gate progname, name); 1178*7c478bd9Sstevel@tonic-gate exit(1); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate if (dladm_info(name, &dlattr) < 0) { 1182*7c478bd9Sstevel@tonic-gate if (!state->ls_parseable) { 1183*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-9s\ttype: legacy" 1184*7c478bd9Sstevel@tonic-gate "\tmtu: %d\tdevice: %s\n"), 1185*7c478bd9Sstevel@tonic-gate name, (int)dl_max_sdu, name); 1186*7c478bd9Sstevel@tonic-gate } else { 1187*7c478bd9Sstevel@tonic-gate (void) printf("%s type=legacy mtu=%d device=%s\n", 1188*7c478bd9Sstevel@tonic-gate name, (int)dl_max_sdu, name); 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate } else { 1191*7c478bd9Sstevel@tonic-gate if (dlattr.da_vid != 0) { 1192*7c478bd9Sstevel@tonic-gate (void) snprintf(type, TYPE_WIDTH, 1193*7c478bd9Sstevel@tonic-gate state->ls_parseable ? "vlan %u" : 1194*7c478bd9Sstevel@tonic-gate gettext("vlan %u"), dlattr.da_vid); 1195*7c478bd9Sstevel@tonic-gate } else { 1196*7c478bd9Sstevel@tonic-gate (void) snprintf(type, TYPE_WIDTH, 1197*7c478bd9Sstevel@tonic-gate state->ls_parseable ? "non-vlan" : 1198*7c478bd9Sstevel@tonic-gate gettext("non-vlan")); 1199*7c478bd9Sstevel@tonic-gate } 1200*7c478bd9Sstevel@tonic-gate 1201*7c478bd9Sstevel@tonic-gate if (strcmp(dlattr.da_dev, AGGR_DEV) == 0) { 1202*7c478bd9Sstevel@tonic-gate if (!state->ls_parseable) { 1203*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-9s\ttype: %s" 1204*7c478bd9Sstevel@tonic-gate "\tmtu: %d\taggregation: key %u\n"), 1205*7c478bd9Sstevel@tonic-gate name, type, (int)dl_max_sdu, 1206*7c478bd9Sstevel@tonic-gate dlattr.da_port); 1207*7c478bd9Sstevel@tonic-gate } else { 1208*7c478bd9Sstevel@tonic-gate (void) printf("%s type=%s mtu=%d key=%u\n", 1209*7c478bd9Sstevel@tonic-gate name, type, (int)dl_max_sdu, 1210*7c478bd9Sstevel@tonic-gate dlattr.da_port); 1211*7c478bd9Sstevel@tonic-gate } 1212*7c478bd9Sstevel@tonic-gate } else { 1213*7c478bd9Sstevel@tonic-gate if (!state->ls_parseable) { 1214*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%-9s\ttype: %s" 1215*7c478bd9Sstevel@tonic-gate "\tmtu: %d\tdevice: %s\n"), 1216*7c478bd9Sstevel@tonic-gate name, type, (int)dl_max_sdu, 1217*7c478bd9Sstevel@tonic-gate dlattr.da_dev); 1218*7c478bd9Sstevel@tonic-gate } else { 1219*7c478bd9Sstevel@tonic-gate (void) printf("%s type=%s mtu=%d device=%s\n", 1220*7c478bd9Sstevel@tonic-gate name, type, (int)dl_max_sdu, dlattr.da_dev); 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate } 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate static void 1227*7c478bd9Sstevel@tonic-gate show_link_stats(void *arg, const char *name) 1228*7c478bd9Sstevel@tonic-gate { 1229*7c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 1230*7c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 1233*7c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 1234*7c478bd9Sstevel@tonic-gate return; 1235*7c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 1236*7c478bd9Sstevel@tonic-gate } else { 1237*7c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate get_link_stats(name, &stats); 1241*7c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ls_prevstats); 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate (void) printf("%s", name); 1244*7c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 1245*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 1246*7c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 1247*7c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 1248*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 1249*7c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 1252*7c478bd9Sstevel@tonic-gate } 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate static void 1255*7c478bd9Sstevel@tonic-gate dump_grp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 1256*7c478bd9Sstevel@tonic-gate { 1257*7c478bd9Sstevel@tonic-gate char policy_str[LAADM_POLICY_STR_LEN]; 1258*7c478bd9Sstevel@tonic-gate char addr_str[ETHERADDRL * 3]; 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate if (!parseable) { 1261*7c478bd9Sstevel@tonic-gate (void) printf(gettext("key: %d (0x%04x)"), 1262*7c478bd9Sstevel@tonic-gate grp->lg_key, grp->lg_key); 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tpolicy: %s"), 1265*7c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 1266*7c478bd9Sstevel@tonic-gate 1267*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\taddress: %s (%s)\n"), 1268*7c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str), 1269*7c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? gettext("fixed") : gettext("auto")); 1270*7c478bd9Sstevel@tonic-gate } else { 1271*7c478bd9Sstevel@tonic-gate (void) printf("aggr key=%d", grp->lg_key); 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate (void) printf(" policy=%s", 1274*7c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate (void) printf(" address=%s", 1277*7c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str)); 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate (void) printf(" address-type=%s\n", 1280*7c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? "fixed" : "auto"); 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate } 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate static void 1285*7c478bd9Sstevel@tonic-gate dump_grp_lacp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 1286*7c478bd9Sstevel@tonic-gate { 1287*7c478bd9Sstevel@tonic-gate const char *lacp_mode_str = laadm_lacp_mode_to_str(grp->lg_lacp_mode); 1288*7c478bd9Sstevel@tonic-gate const char *lacp_timer_str = 1289*7c478bd9Sstevel@tonic-gate laadm_lacp_timer_to_str(grp->lg_lacp_timer); 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate if (!parseable) { 1292*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLACP mode: %s"), lacp_mode_str); 1293*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLACP timer: %s\n"), lacp_timer_str); 1294*7c478bd9Sstevel@tonic-gate } else { 1295*7c478bd9Sstevel@tonic-gate (void) printf(" lacp-mode=%s", lacp_mode_str); 1296*7c478bd9Sstevel@tonic-gate (void) printf(" lacp-timer=%s\n", lacp_timer_str); 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate static void 1301*7c478bd9Sstevel@tonic-gate dump_grp_stats(laadm_grp_attr_sys_t *grp) 1302*7c478bd9Sstevel@tonic-gate { 1303*7c478bd9Sstevel@tonic-gate (void) printf("key: %d", grp->lg_key); 1304*7c478bd9Sstevel@tonic-gate (void) printf("\tipackets rbytes opackets obytes "); 1305*7c478bd9Sstevel@tonic-gate (void) printf("%%ipkts %%opkts\n"); 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate static void 1309*7c478bd9Sstevel@tonic-gate dump_ports_lacp_head(void) 1310*7c478bd9Sstevel@tonic-gate { 1311*7c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, gettext("device"), gettext("activity"), 1312*7c478bd9Sstevel@tonic-gate gettext("timeout"), gettext("aggregatable"), gettext("sync"), 1313*7c478bd9Sstevel@tonic-gate gettext("coll"), gettext("dist"), gettext("defaulted"), 1314*7c478bd9Sstevel@tonic-gate gettext("expired")); 1315*7c478bd9Sstevel@tonic-gate } 1316*7c478bd9Sstevel@tonic-gate 1317*7c478bd9Sstevel@tonic-gate static void 1318*7c478bd9Sstevel@tonic-gate dump_ports_head(void) 1319*7c478bd9Sstevel@tonic-gate { 1320*7c478bd9Sstevel@tonic-gate (void) printf(gettext(" device\taddress\t\t speed\t\tduplex\tlink\t" 1321*7c478bd9Sstevel@tonic-gate "state\n")); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate static char * 1325*7c478bd9Sstevel@tonic-gate port_state_to_str(aggr_port_state_t state_num) 1326*7c478bd9Sstevel@tonic-gate { 1327*7c478bd9Sstevel@tonic-gate int i; 1328*7c478bd9Sstevel@tonic-gate port_state_t *state; 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate for (i = 0; i < NPORTSTATES; i++) { 1331*7c478bd9Sstevel@tonic-gate state = &port_states[i]; 1332*7c478bd9Sstevel@tonic-gate if (state->state_num == state_num) 1333*7c478bd9Sstevel@tonic-gate return (state->state_name); 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate return ("unknown"); 1337*7c478bd9Sstevel@tonic-gate } 1338*7c478bd9Sstevel@tonic-gate 1339*7c478bd9Sstevel@tonic-gate static void 1340*7c478bd9Sstevel@tonic-gate dump_port(laadm_port_attr_sys_t *port, boolean_t parseable) 1341*7c478bd9Sstevel@tonic-gate { 1342*7c478bd9Sstevel@tonic-gate char *dev = port->lp_devname; 1343*7c478bd9Sstevel@tonic-gate uint_t portnum = port->lp_port; 1344*7c478bd9Sstevel@tonic-gate char buf[ETHERADDRL * 3]; 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate if (!parseable) { 1347*7c478bd9Sstevel@tonic-gate (void) printf(" %-9s\t%s", dev, laadm_mac_addr_to_str( 1348*7c478bd9Sstevel@tonic-gate port->lp_mac, buf)); 1349*7c478bd9Sstevel@tonic-gate (void) printf("\t %-5u Mbps", (int)(mac_ifspeed(dev, portnum) / 1350*7c478bd9Sstevel@tonic-gate 1000000ull)); 1351*7c478bd9Sstevel@tonic-gate (void) printf("\t%s", mac_link_duplex(dev, portnum)); 1352*7c478bd9Sstevel@tonic-gate (void) printf("\t%s", mac_link_state(dev, portnum)); 1353*7c478bd9Sstevel@tonic-gate (void) printf("\t%s\n", port_state_to_str(port->lp_state)); 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate } else { 1356*7c478bd9Sstevel@tonic-gate (void) printf(" device=%s address=%s", dev, 1357*7c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(port->lp_mac, buf)); 1358*7c478bd9Sstevel@tonic-gate (void) printf(" speed=%u", (int)(mac_ifspeed(dev, portnum) / 1359*7c478bd9Sstevel@tonic-gate 1000000ull)); 1360*7c478bd9Sstevel@tonic-gate (void) printf(" duplex=%s", mac_link_duplex(dev, portnum)); 1361*7c478bd9Sstevel@tonic-gate (void) printf(" link=%s", mac_link_state(dev, portnum)); 1362*7c478bd9Sstevel@tonic-gate (void) printf(" port=%s", port_state_to_str(port->lp_state)); 1363*7c478bd9Sstevel@tonic-gate } 1364*7c478bd9Sstevel@tonic-gate } 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate static void 1367*7c478bd9Sstevel@tonic-gate dump_port_lacp(laadm_port_attr_sys_t *port) 1368*7c478bd9Sstevel@tonic-gate { 1369*7c478bd9Sstevel@tonic-gate aggr_lacp_state_t *state = &port->lp_lacp_state; 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, 1372*7c478bd9Sstevel@tonic-gate port->lp_devname, state->bit.activity ? "active" : "passive", 1373*7c478bd9Sstevel@tonic-gate state->bit.timeout ? "short" : "long", 1374*7c478bd9Sstevel@tonic-gate state->bit.aggregation ? "yes" : "no", 1375*7c478bd9Sstevel@tonic-gate state->bit.sync ? "yes" : "no", 1376*7c478bd9Sstevel@tonic-gate state->bit.collecting ? "yes" : "no", 1377*7c478bd9Sstevel@tonic-gate state->bit.distributing ? "yes" : "no", 1378*7c478bd9Sstevel@tonic-gate state->bit.defaulted ? "yes" : "no", 1379*7c478bd9Sstevel@tonic-gate state->bit.expired ? "yes" : "no"); 1380*7c478bd9Sstevel@tonic-gate } 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate static void 1383*7c478bd9Sstevel@tonic-gate dump_port_stat(int index, show_grp_state_t *state, pktsum_t *port_stats, 1384*7c478bd9Sstevel@tonic-gate pktsum_t *tot_stats) 1385*7c478bd9Sstevel@tonic-gate { 1386*7c478bd9Sstevel@tonic-gate pktsum_t diff_stats; 1387*7c478bd9Sstevel@tonic-gate pktsum_t *old_stats = &state->gs_prevstats[index]; 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, port_stats, old_stats); 1390*7c478bd9Sstevel@tonic-gate 1391*7c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", diff_stats.ipackets); 1392*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 1393*7c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 1394*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate if (tot_stats->ipackets == 0) 1397*7c478bd9Sstevel@tonic-gate (void) printf("\t-"); 1398*7c478bd9Sstevel@tonic-gate else 1399*7c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 1400*7c478bd9Sstevel@tonic-gate (double)tot_stats->ipackets * 100); 1401*7c478bd9Sstevel@tonic-gate 1402*7c478bd9Sstevel@tonic-gate if (tot_stats->opackets == 0) 1403*7c478bd9Sstevel@tonic-gate (void) printf("\t-"); 1404*7c478bd9Sstevel@tonic-gate else 1405*7c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 1406*7c478bd9Sstevel@tonic-gate (double)tot_stats->opackets * 100); 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1409*7c478bd9Sstevel@tonic-gate 1410*7c478bd9Sstevel@tonic-gate *old_stats = *port_stats; 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate static int 1414*7c478bd9Sstevel@tonic-gate show_key(void *arg, laadm_grp_attr_sys_t *grp) 1415*7c478bd9Sstevel@tonic-gate { 1416*7c478bd9Sstevel@tonic-gate show_grp_state_t *state = (show_grp_state_t *)arg; 1417*7c478bd9Sstevel@tonic-gate int i; 1418*7c478bd9Sstevel@tonic-gate pktsum_t pktsumtot, port_stat; 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate if (state->gs_key != 0 && state->gs_key != grp->lg_key) 1421*7c478bd9Sstevel@tonic-gate return (0); 1422*7c478bd9Sstevel@tonic-gate if (state->gs_firstonly) { 1423*7c478bd9Sstevel@tonic-gate if (state->gs_found) 1424*7c478bd9Sstevel@tonic-gate return (0); 1425*7c478bd9Sstevel@tonic-gate } else { 1426*7c478bd9Sstevel@tonic-gate bzero(&state->gs_prevstats, sizeof (state->gs_prevstats)); 1427*7c478bd9Sstevel@tonic-gate } 1428*7c478bd9Sstevel@tonic-gate 1429*7c478bd9Sstevel@tonic-gate state->gs_found = B_TRUE; 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate if (state->gs_stats) { 1432*7c478bd9Sstevel@tonic-gate /* show statistics */ 1433*7c478bd9Sstevel@tonic-gate dump_grp_stats(grp); 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 1436*7c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 1437*7c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1438*7c478bd9Sstevel@tonic-gate get_mac_stats(grp->lg_ports[i].lp_devname, 1439*7c478bd9Sstevel@tonic-gate grp->lg_ports[i].lp_port, &port_stat); 1440*7c478bd9Sstevel@tonic-gate stats_total(&pktsumtot, &port_stat, 1441*7c478bd9Sstevel@tonic-gate &state->gs_prevstats[i]); 1442*7c478bd9Sstevel@tonic-gate } 1443*7c478bd9Sstevel@tonic-gate 1444*7c478bd9Sstevel@tonic-gate (void) printf(" Total"); 1445*7c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", pktsumtot.ipackets); 1446*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", pktsumtot.rbytes); 1447*7c478bd9Sstevel@tonic-gate (void) printf("%-10llu", pktsumtot.opackets); 1448*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu\n", pktsumtot.obytes); 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1451*7c478bd9Sstevel@tonic-gate get_mac_stats(grp->lg_ports[i].lp_devname, 1452*7c478bd9Sstevel@tonic-gate grp->lg_ports[i].lp_port, &port_stat); 1453*7c478bd9Sstevel@tonic-gate (void) printf(" %s", grp->lg_ports[i].lp_devname); 1454*7c478bd9Sstevel@tonic-gate dump_port_stat(i, state, &port_stat, &pktsumtot); 1455*7c478bd9Sstevel@tonic-gate } 1456*7c478bd9Sstevel@tonic-gate } else if (state->gs_lacp) { 1457*7c478bd9Sstevel@tonic-gate /* show LACP info */ 1458*7c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 1459*7c478bd9Sstevel@tonic-gate dump_grp_lacp(grp, state->gs_parseable); 1460*7c478bd9Sstevel@tonic-gate dump_ports_lacp_head(); 1461*7c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) 1462*7c478bd9Sstevel@tonic-gate dump_port_lacp(&grp->lg_ports[i]); 1463*7c478bd9Sstevel@tonic-gate } else { 1464*7c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 1465*7c478bd9Sstevel@tonic-gate if (!state->gs_parseable) 1466*7c478bd9Sstevel@tonic-gate dump_ports_head(); 1467*7c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1468*7c478bd9Sstevel@tonic-gate if (state->gs_parseable) 1469*7c478bd9Sstevel@tonic-gate (void) printf("dev key=%d", grp->lg_key); 1470*7c478bd9Sstevel@tonic-gate dump_port(&grp->lg_ports[i], state->gs_parseable); 1471*7c478bd9Sstevel@tonic-gate if (state->gs_parseable) 1472*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1473*7c478bd9Sstevel@tonic-gate } 1474*7c478bd9Sstevel@tonic-gate } 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate return (0); 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate 1479*7c478bd9Sstevel@tonic-gate static int 1480*7c478bd9Sstevel@tonic-gate kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf) 1481*7c478bd9Sstevel@tonic-gate { 1482*7c478bd9Sstevel@tonic-gate kstat_named_t *knp; 1483*7c478bd9Sstevel@tonic-gate 1484*7c478bd9Sstevel@tonic-gate if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL) 1485*7c478bd9Sstevel@tonic-gate return (-1); 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate if (knp->data_type != type) 1488*7c478bd9Sstevel@tonic-gate return (-1); 1489*7c478bd9Sstevel@tonic-gate 1490*7c478bd9Sstevel@tonic-gate switch (type) { 1491*7c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT64: 1492*7c478bd9Sstevel@tonic-gate *(uint64_t *)buf = knp->value.ui64; 1493*7c478bd9Sstevel@tonic-gate break; 1494*7c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT32: 1495*7c478bd9Sstevel@tonic-gate *(uint32_t *)buf = knp->value.ui32; 1496*7c478bd9Sstevel@tonic-gate break; 1497*7c478bd9Sstevel@tonic-gate default: 1498*7c478bd9Sstevel@tonic-gate return (-1); 1499*7c478bd9Sstevel@tonic-gate } 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate return (0); 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate 1504*7c478bd9Sstevel@tonic-gate static void 1505*7c478bd9Sstevel@tonic-gate show_dev(void *arg, const char *dev, uint_t port) 1506*7c478bd9Sstevel@tonic-gate { 1507*7c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate /* aggregations are already managed by a set of subcommands */ 1510*7c478bd9Sstevel@tonic-gate if (strcmp(dev, AGGR_DEV) == 0) 1511*7c478bd9Sstevel@tonic-gate return; 1512*7c478bd9Sstevel@tonic-gate 1513*7c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 1514*7c478bd9Sstevel@tonic-gate if (port != 0) 1515*7c478bd9Sstevel@tonic-gate (void) printf("/%d", port); 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate if (!state->ms_parseable) { 1518*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tlink: %s"), 1519*7c478bd9Sstevel@tonic-gate mac_link_state(dev, port)); 1520*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tspeed: %-5u Mbps"), 1521*7c478bd9Sstevel@tonic-gate (unsigned int)(mac_ifspeed(dev, port) / 1000000ull)); 1522*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tduplex: %s\n"), 1523*7c478bd9Sstevel@tonic-gate mac_link_duplex(dev, port)); 1524*7c478bd9Sstevel@tonic-gate } else { 1525*7c478bd9Sstevel@tonic-gate (void) printf(" link=%s", mac_link_state(dev, port)); 1526*7c478bd9Sstevel@tonic-gate (void) printf(" speed=%u", 1527*7c478bd9Sstevel@tonic-gate (unsigned int)(mac_ifspeed(dev, port) / 1000000ull)); 1528*7c478bd9Sstevel@tonic-gate (void) printf(" duplex=%s\n", mac_link_duplex(dev, port)); 1529*7c478bd9Sstevel@tonic-gate } 1530*7c478bd9Sstevel@tonic-gate } 1531*7c478bd9Sstevel@tonic-gate 1532*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1533*7c478bd9Sstevel@tonic-gate static void 1534*7c478bd9Sstevel@tonic-gate show_dev_stats(void *arg, const char *dev, uint_t port) 1535*7c478bd9Sstevel@tonic-gate { 1536*7c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 1537*7c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate /* aggregations are already managed by a set of subcommands */ 1540*7c478bd9Sstevel@tonic-gate if (strcmp(dev, AGGR_DEV) == 0) 1541*7c478bd9Sstevel@tonic-gate return; 1542*7c478bd9Sstevel@tonic-gate 1543*7c478bd9Sstevel@tonic-gate if (state->ms_firstonly) { 1544*7c478bd9Sstevel@tonic-gate if (state->ms_donefirst) 1545*7c478bd9Sstevel@tonic-gate return; 1546*7c478bd9Sstevel@tonic-gate state->ms_donefirst = B_TRUE; 1547*7c478bd9Sstevel@tonic-gate } else { 1548*7c478bd9Sstevel@tonic-gate bzero(&state->ms_prevstats, sizeof (state->ms_prevstats)); 1549*7c478bd9Sstevel@tonic-gate } 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate get_mac_stats(dev, port, &stats); 1552*7c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ms_prevstats); 1553*7c478bd9Sstevel@tonic-gate 1554*7c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 1555*7c478bd9Sstevel@tonic-gate if (port != 0) 1556*7c478bd9Sstevel@tonic-gate (void) printf("/%d", port); 1557*7c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 1558*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 1559*7c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 1560*7c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 1561*7c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 1562*7c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate state->ms_prevstats = stats; 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate static void 1568*7c478bd9Sstevel@tonic-gate do_show_link(int argc, char *argv[]) 1569*7c478bd9Sstevel@tonic-gate { 1570*7c478bd9Sstevel@tonic-gate char *name = NULL; 1571*7c478bd9Sstevel@tonic-gate int option; 1572*7c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 1573*7c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 1574*7c478bd9Sstevel@tonic-gate uint32_t interval = 0; 1575*7c478bd9Sstevel@tonic-gate show_link_state_t state; 1576*7c478bd9Sstevel@tonic-gate char *endp = NULL; 1577*7c478bd9Sstevel@tonic-gate 1578*7c478bd9Sstevel@tonic-gate state.ls_stats = B_FALSE; 1579*7c478bd9Sstevel@tonic-gate state.ls_parseable = B_FALSE; 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate opterr = 0; 1582*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 1583*7c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 1584*7c478bd9Sstevel@tonic-gate switch (option) { 1585*7c478bd9Sstevel@tonic-gate case 'p': 1586*7c478bd9Sstevel@tonic-gate state.ls_parseable = B_TRUE; 1587*7c478bd9Sstevel@tonic-gate break; 1588*7c478bd9Sstevel@tonic-gate case 's': 1589*7c478bd9Sstevel@tonic-gate if (s_arg) { 1590*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1591*7c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 1592*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1593*7c478bd9Sstevel@tonic-gate usage(); 1594*7c478bd9Sstevel@tonic-gate } 1595*7c478bd9Sstevel@tonic-gate 1596*7c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 1597*7c478bd9Sstevel@tonic-gate break; 1598*7c478bd9Sstevel@tonic-gate case 'i': 1599*7c478bd9Sstevel@tonic-gate if (i_arg) { 1600*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1601*7c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 1602*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1603*7c478bd9Sstevel@tonic-gate usage(); 1604*7c478bd9Sstevel@tonic-gate } 1605*7c478bd9Sstevel@tonic-gate 1606*7c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 1607*7c478bd9Sstevel@tonic-gate 1608*7c478bd9Sstevel@tonic-gate errno = 0; 1609*7c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 1610*7c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 1611*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1612*7c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 1613*7c478bd9Sstevel@tonic-gate " '%d'\n"), 1614*7c478bd9Sstevel@tonic-gate progname, interval); 1615*7c478bd9Sstevel@tonic-gate exit(1); 1616*7c478bd9Sstevel@tonic-gate } 1617*7c478bd9Sstevel@tonic-gate break; 1618*7c478bd9Sstevel@tonic-gate case ':': 1619*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1620*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 1621*7c478bd9Sstevel@tonic-gate progname, optopt); 1622*7c478bd9Sstevel@tonic-gate exit(1); 1623*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1624*7c478bd9Sstevel@tonic-gate case '?': 1625*7c478bd9Sstevel@tonic-gate default: 1626*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1627*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 1628*7c478bd9Sstevel@tonic-gate progname, optopt); 1629*7c478bd9Sstevel@tonic-gate exit(1); 1630*7c478bd9Sstevel@tonic-gate } 1631*7c478bd9Sstevel@tonic-gate } 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 1634*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 1635*7c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 1636*7c478bd9Sstevel@tonic-gate usage(); 1637*7c478bd9Sstevel@tonic-gate } 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 1641*7c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 1642*7c478bd9Sstevel@tonic-gate name = argv[optind]; 1643*7c478bd9Sstevel@tonic-gate else if (optind != argc) 1644*7c478bd9Sstevel@tonic-gate usage(); 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate if (s_arg) { 1647*7c478bd9Sstevel@tonic-gate link_stats(name, interval); 1648*7c478bd9Sstevel@tonic-gate return; 1649*7c478bd9Sstevel@tonic-gate } 1650*7c478bd9Sstevel@tonic-gate 1651*7c478bd9Sstevel@tonic-gate if (name == NULL) 1652*7c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link, &state); 1653*7c478bd9Sstevel@tonic-gate else 1654*7c478bd9Sstevel@tonic-gate show_link(&state, name); 1655*7c478bd9Sstevel@tonic-gate } 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate static void 1658*7c478bd9Sstevel@tonic-gate do_show_aggr(int argc, char *argv[]) 1659*7c478bd9Sstevel@tonic-gate { 1660*7c478bd9Sstevel@tonic-gate int option; 1661*7c478bd9Sstevel@tonic-gate uint16_t key = 0; 1662*7c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 1663*7c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 1664*7c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 1665*7c478bd9Sstevel@tonic-gate show_grp_state_t state; 1666*7c478bd9Sstevel@tonic-gate uint32_t interval = 0; 1667*7c478bd9Sstevel@tonic-gate char *endp = NULL; 1668*7c478bd9Sstevel@tonic-gate 1669*7c478bd9Sstevel@tonic-gate state.gs_stats = B_FALSE; 1670*7c478bd9Sstevel@tonic-gate state.gs_lacp = B_FALSE; 1671*7c478bd9Sstevel@tonic-gate state.gs_parseable = B_FALSE; 1672*7c478bd9Sstevel@tonic-gate 1673*7c478bd9Sstevel@tonic-gate opterr = 0; 1674*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":Lpsi:", 1675*7c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 1676*7c478bd9Sstevel@tonic-gate switch (option) { 1677*7c478bd9Sstevel@tonic-gate case 'L': 1678*7c478bd9Sstevel@tonic-gate if (L_arg) { 1679*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1680*7c478bd9Sstevel@tonic-gate "%s: the option -L cannot be specified " 1681*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1682*7c478bd9Sstevel@tonic-gate usage(); 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate 1685*7c478bd9Sstevel@tonic-gate if (s_arg || i_arg) { 1686*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1687*7c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used with " 1688*7c478bd9Sstevel@tonic-gate "any of -is\n"), progname); 1689*7c478bd9Sstevel@tonic-gate usage(); 1690*7c478bd9Sstevel@tonic-gate } 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate state.gs_lacp = B_TRUE; 1695*7c478bd9Sstevel@tonic-gate break; 1696*7c478bd9Sstevel@tonic-gate case 'p': 1697*7c478bd9Sstevel@tonic-gate state.gs_parseable = B_TRUE; 1698*7c478bd9Sstevel@tonic-gate break; 1699*7c478bd9Sstevel@tonic-gate case 's': 1700*7c478bd9Sstevel@tonic-gate if (s_arg) { 1701*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1702*7c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 1703*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1704*7c478bd9Sstevel@tonic-gate usage(); 1705*7c478bd9Sstevel@tonic-gate } 1706*7c478bd9Sstevel@tonic-gate 1707*7c478bd9Sstevel@tonic-gate if (L_arg) { 1708*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1709*7c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used " 1710*7c478bd9Sstevel@tonic-gate "with -k\n"), progname); 1711*7c478bd9Sstevel@tonic-gate usage(); 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate 1714*7c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 1715*7c478bd9Sstevel@tonic-gate break; 1716*7c478bd9Sstevel@tonic-gate case 'i': 1717*7c478bd9Sstevel@tonic-gate if (i_arg) { 1718*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1719*7c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 1720*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1721*7c478bd9Sstevel@tonic-gate usage(); 1722*7c478bd9Sstevel@tonic-gate } 1723*7c478bd9Sstevel@tonic-gate 1724*7c478bd9Sstevel@tonic-gate if (L_arg) { 1725*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1726*7c478bd9Sstevel@tonic-gate "%s: the option -i cannot be used " 1727*7c478bd9Sstevel@tonic-gate "with -L\n"), progname); 1728*7c478bd9Sstevel@tonic-gate usage(); 1729*7c478bd9Sstevel@tonic-gate } 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 1732*7c478bd9Sstevel@tonic-gate 1733*7c478bd9Sstevel@tonic-gate errno = 0; 1734*7c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 1735*7c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 1736*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1737*7c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 1738*7c478bd9Sstevel@tonic-gate " '%d'\n"), 1739*7c478bd9Sstevel@tonic-gate progname, interval); 1740*7c478bd9Sstevel@tonic-gate exit(1); 1741*7c478bd9Sstevel@tonic-gate } 1742*7c478bd9Sstevel@tonic-gate break; 1743*7c478bd9Sstevel@tonic-gate case ':': 1744*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1745*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 1746*7c478bd9Sstevel@tonic-gate progname, optopt); 1747*7c478bd9Sstevel@tonic-gate exit(1); 1748*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1749*7c478bd9Sstevel@tonic-gate case '?': 1750*7c478bd9Sstevel@tonic-gate default: 1751*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1752*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 1753*7c478bd9Sstevel@tonic-gate progname, optopt); 1754*7c478bd9Sstevel@tonic-gate exit(1); 1755*7c478bd9Sstevel@tonic-gate } 1756*7c478bd9Sstevel@tonic-gate } 1757*7c478bd9Sstevel@tonic-gate 1758*7c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 1759*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 1760*7c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 1761*7c478bd9Sstevel@tonic-gate usage(); 1762*7c478bd9Sstevel@tonic-gate } 1763*7c478bd9Sstevel@tonic-gate 1764*7c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 1765*7c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 1766*7c478bd9Sstevel@tonic-gate errno = 0; 1767*7c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 1768*7c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 1769*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1770*7c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 1771*7c478bd9Sstevel@tonic-gate progname, key); 1772*7c478bd9Sstevel@tonic-gate exit(1); 1773*7c478bd9Sstevel@tonic-gate } 1774*7c478bd9Sstevel@tonic-gate } else if (optind != argc) { 1775*7c478bd9Sstevel@tonic-gate usage(); 1776*7c478bd9Sstevel@tonic-gate } 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate if (s_arg) { 1779*7c478bd9Sstevel@tonic-gate aggr_stats(key, interval); 1780*7c478bd9Sstevel@tonic-gate return; 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate state.gs_key = key; 1784*7c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 1785*7c478bd9Sstevel@tonic-gate 1786*7c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate if (key != 0 && !state.gs_found) { 1789*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1790*7c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 1791*7c478bd9Sstevel@tonic-gate progname, key); 1792*7c478bd9Sstevel@tonic-gate exit(1); 1793*7c478bd9Sstevel@tonic-gate } 1794*7c478bd9Sstevel@tonic-gate } 1795*7c478bd9Sstevel@tonic-gate 1796*7c478bd9Sstevel@tonic-gate static void 1797*7c478bd9Sstevel@tonic-gate do_show_dev(int argc, char *argv[]) 1798*7c478bd9Sstevel@tonic-gate { 1799*7c478bd9Sstevel@tonic-gate int option; 1800*7c478bd9Sstevel@tonic-gate char *dev = NULL; 1801*7c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 1802*7c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 1803*7c478bd9Sstevel@tonic-gate uint32_t interval = 0; 1804*7c478bd9Sstevel@tonic-gate show_mac_state_t state; 1805*7c478bd9Sstevel@tonic-gate char *endp = NULL; 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate state.ms_parseable = B_FALSE; 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate opterr = 0; 1810*7c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 1811*7c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 1812*7c478bd9Sstevel@tonic-gate switch (option) { 1813*7c478bd9Sstevel@tonic-gate case 'p': 1814*7c478bd9Sstevel@tonic-gate state.ms_parseable = B_TRUE; 1815*7c478bd9Sstevel@tonic-gate break; 1816*7c478bd9Sstevel@tonic-gate case 's': 1817*7c478bd9Sstevel@tonic-gate if (s_arg) { 1818*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1819*7c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 1820*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1821*7c478bd9Sstevel@tonic-gate usage(); 1822*7c478bd9Sstevel@tonic-gate } 1823*7c478bd9Sstevel@tonic-gate 1824*7c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 1825*7c478bd9Sstevel@tonic-gate break; 1826*7c478bd9Sstevel@tonic-gate case 'i': 1827*7c478bd9Sstevel@tonic-gate if (i_arg) { 1828*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1829*7c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 1830*7c478bd9Sstevel@tonic-gate "more than once\n"), progname); 1831*7c478bd9Sstevel@tonic-gate usage(); 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate 1834*7c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 1835*7c478bd9Sstevel@tonic-gate 1836*7c478bd9Sstevel@tonic-gate errno = 0; 1837*7c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 1838*7c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 1839*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1840*7c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 1841*7c478bd9Sstevel@tonic-gate " '%d'\n"), 1842*7c478bd9Sstevel@tonic-gate progname, interval); 1843*7c478bd9Sstevel@tonic-gate exit(1); 1844*7c478bd9Sstevel@tonic-gate } 1845*7c478bd9Sstevel@tonic-gate break; 1846*7c478bd9Sstevel@tonic-gate case ':': 1847*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1848*7c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 1849*7c478bd9Sstevel@tonic-gate progname, optopt); 1850*7c478bd9Sstevel@tonic-gate exit(1); 1851*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1852*7c478bd9Sstevel@tonic-gate case '?': 1853*7c478bd9Sstevel@tonic-gate default: 1854*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1855*7c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 1856*7c478bd9Sstevel@tonic-gate progname, optopt); 1857*7c478bd9Sstevel@tonic-gate exit(1); 1858*7c478bd9Sstevel@tonic-gate } 1859*7c478bd9Sstevel@tonic-gate } 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 1862*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 1863*7c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 1864*7c478bd9Sstevel@tonic-gate usage(); 1865*7c478bd9Sstevel@tonic-gate } 1866*7c478bd9Sstevel@tonic-gate 1867*7c478bd9Sstevel@tonic-gate /* get dev name (optional last argument) */ 1868*7c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 1869*7c478bd9Sstevel@tonic-gate dev = argv[optind]; 1870*7c478bd9Sstevel@tonic-gate else if (optind != argc) 1871*7c478bd9Sstevel@tonic-gate usage(); 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate if ((dev != NULL) && (strcmp(dev, AGGR_DEV) == 0)) { 1874*7c478bd9Sstevel@tonic-gate /* aggregations are already managed by a set of subcommands */ 1875*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1876*7c478bd9Sstevel@tonic-gate gettext("%s: non-existant device '%s'\n"), 1877*7c478bd9Sstevel@tonic-gate progname, dev); 1878*7c478bd9Sstevel@tonic-gate exit(1); 1879*7c478bd9Sstevel@tonic-gate } 1880*7c478bd9Sstevel@tonic-gate 1881*7c478bd9Sstevel@tonic-gate if (s_arg) { 1882*7c478bd9Sstevel@tonic-gate dev_stats(dev, interval); 1883*7c478bd9Sstevel@tonic-gate return; 1884*7c478bd9Sstevel@tonic-gate } 1885*7c478bd9Sstevel@tonic-gate 1886*7c478bd9Sstevel@tonic-gate if (dev == NULL) 1887*7c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev, &state, B_TRUE); 1888*7c478bd9Sstevel@tonic-gate else 1889*7c478bd9Sstevel@tonic-gate show_dev(&state, dev, 0); 1890*7c478bd9Sstevel@tonic-gate } 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1893*7c478bd9Sstevel@tonic-gate static void 1894*7c478bd9Sstevel@tonic-gate link_stats(const char *link, uint32_t interval) 1895*7c478bd9Sstevel@tonic-gate { 1896*7c478bd9Sstevel@tonic-gate show_link_state_t state; 1897*7c478bd9Sstevel@tonic-gate 1898*7c478bd9Sstevel@tonic-gate if (link != NULL) { 1899*7c478bd9Sstevel@tonic-gate dlpi_if_attr_t dia; 1900*7c478bd9Sstevel@tonic-gate int fd; 1901*7c478bd9Sstevel@tonic-gate 1902*7c478bd9Sstevel@tonic-gate if ((fd = dlpi_if_open(link, &dia, B_FALSE)) != -1) { 1903*7c478bd9Sstevel@tonic-gate (void) dlpi_close(fd); 1904*7c478bd9Sstevel@tonic-gate } else { 1905*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1906*7c478bd9Sstevel@tonic-gate gettext("%s: invalid device '%s'\n"), 1907*7c478bd9Sstevel@tonic-gate progname, link); 1908*7c478bd9Sstevel@tonic-gate exit(1); 1909*7c478bd9Sstevel@tonic-gate } 1910*7c478bd9Sstevel@tonic-gate } 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate /* 1915*7c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 1916*7c478bd9Sstevel@tonic-gate * only for the first MAC port. 1917*7c478bd9Sstevel@tonic-gate */ 1918*7c478bd9Sstevel@tonic-gate state.ls_firstonly = (interval != 0); 1919*7c478bd9Sstevel@tonic-gate 1920*7c478bd9Sstevel@tonic-gate for (;;) { 1921*7c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 1922*7c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 1923*7c478bd9Sstevel@tonic-gate 1924*7c478bd9Sstevel@tonic-gate state.ls_donefirst = B_FALSE; 1925*7c478bd9Sstevel@tonic-gate if (link == NULL) 1926*7c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link_stats, &state); 1927*7c478bd9Sstevel@tonic-gate else 1928*7c478bd9Sstevel@tonic-gate show_link_stats(&state, link); 1929*7c478bd9Sstevel@tonic-gate 1930*7c478bd9Sstevel@tonic-gate if (interval == 0) 1931*7c478bd9Sstevel@tonic-gate break; 1932*7c478bd9Sstevel@tonic-gate 1933*7c478bd9Sstevel@tonic-gate (void) sleep(interval); 1934*7c478bd9Sstevel@tonic-gate } 1935*7c478bd9Sstevel@tonic-gate 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate 1938*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1939*7c478bd9Sstevel@tonic-gate static void 1940*7c478bd9Sstevel@tonic-gate aggr_stats(uint16_t key, uint32_t interval) 1941*7c478bd9Sstevel@tonic-gate { 1942*7c478bd9Sstevel@tonic-gate show_grp_state_t state; 1943*7c478bd9Sstevel@tonic-gate 1944*7c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 1945*7c478bd9Sstevel@tonic-gate state.gs_stats = B_TRUE; 1946*7c478bd9Sstevel@tonic-gate state.gs_key = key; 1947*7c478bd9Sstevel@tonic-gate 1948*7c478bd9Sstevel@tonic-gate /* 1949*7c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 1950*7c478bd9Sstevel@tonic-gate * only for the first group. 1951*7c478bd9Sstevel@tonic-gate */ 1952*7c478bd9Sstevel@tonic-gate state.gs_firstonly = (interval != 0); 1953*7c478bd9Sstevel@tonic-gate 1954*7c478bd9Sstevel@tonic-gate for (;;) { 1955*7c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 1956*7c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 1957*7c478bd9Sstevel@tonic-gate if (state.gs_key != 0 && !state.gs_found) { 1958*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1959*7c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 1960*7c478bd9Sstevel@tonic-gate progname, key); 1961*7c478bd9Sstevel@tonic-gate exit(1); 1962*7c478bd9Sstevel@tonic-gate } 1963*7c478bd9Sstevel@tonic-gate 1964*7c478bd9Sstevel@tonic-gate if (interval == 0) 1965*7c478bd9Sstevel@tonic-gate break; 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate (void) sleep(interval); 1968*7c478bd9Sstevel@tonic-gate } 1969*7c478bd9Sstevel@tonic-gate } 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1972*7c478bd9Sstevel@tonic-gate static void 1973*7c478bd9Sstevel@tonic-gate dev_stats(const char *dev, uint32_t interval) 1974*7c478bd9Sstevel@tonic-gate { 1975*7c478bd9Sstevel@tonic-gate show_mac_state_t state; 1976*7c478bd9Sstevel@tonic-gate 1977*7c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 1978*7c478bd9Sstevel@tonic-gate 1979*7c478bd9Sstevel@tonic-gate /* 1980*7c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 1981*7c478bd9Sstevel@tonic-gate * only for the first MAC port. 1982*7c478bd9Sstevel@tonic-gate */ 1983*7c478bd9Sstevel@tonic-gate state.ms_firstonly = (interval != 0); 1984*7c478bd9Sstevel@tonic-gate 1985*7c478bd9Sstevel@tonic-gate for (;;) { 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 1988*7c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate state.ms_donefirst = B_FALSE; 1991*7c478bd9Sstevel@tonic-gate if (dev == NULL) { 1992*7c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev_stats, &state, B_TRUE); 1993*7c478bd9Sstevel@tonic-gate } else { 1994*7c478bd9Sstevel@tonic-gate show_dev_stats(&state, dev, 0); 1995*7c478bd9Sstevel@tonic-gate } 1996*7c478bd9Sstevel@tonic-gate 1997*7c478bd9Sstevel@tonic-gate if (interval == 0) 1998*7c478bd9Sstevel@tonic-gate break; 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate (void) sleep(interval); 2001*7c478bd9Sstevel@tonic-gate } 2002*7c478bd9Sstevel@tonic-gate } 2003*7c478bd9Sstevel@tonic-gate 2004*7c478bd9Sstevel@tonic-gate /* accumulate stats (s1 += (s2 - s3)) */ 2005*7c478bd9Sstevel@tonic-gate static void 2006*7c478bd9Sstevel@tonic-gate stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 2007*7c478bd9Sstevel@tonic-gate { 2008*7c478bd9Sstevel@tonic-gate s1->ipackets += (s2->ipackets - s3->ipackets); 2009*7c478bd9Sstevel@tonic-gate s1->opackets += (s2->opackets - s3->opackets); 2010*7c478bd9Sstevel@tonic-gate s1->rbytes += (s2->rbytes - s3->rbytes); 2011*7c478bd9Sstevel@tonic-gate s1->obytes += (s2->obytes - s3->obytes); 2012*7c478bd9Sstevel@tonic-gate s1->ierrors += (s2->ierrors - s3->ierrors); 2013*7c478bd9Sstevel@tonic-gate s1->oerrors += (s2->oerrors - s3->oerrors); 2014*7c478bd9Sstevel@tonic-gate } 2015*7c478bd9Sstevel@tonic-gate 2016*7c478bd9Sstevel@tonic-gate /* compute stats differences (s1 = s2 - s3) */ 2017*7c478bd9Sstevel@tonic-gate static void 2018*7c478bd9Sstevel@tonic-gate stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 2019*7c478bd9Sstevel@tonic-gate { 2020*7c478bd9Sstevel@tonic-gate s1->ipackets = s2->ipackets - s3->ipackets; 2021*7c478bd9Sstevel@tonic-gate s1->opackets = s2->opackets - s3->opackets; 2022*7c478bd9Sstevel@tonic-gate s1->rbytes = s2->rbytes - s3->rbytes; 2023*7c478bd9Sstevel@tonic-gate s1->obytes = s2->obytes - s3->obytes; 2024*7c478bd9Sstevel@tonic-gate s1->ierrors = s2->ierrors - s3->ierrors; 2025*7c478bd9Sstevel@tonic-gate s1->oerrors = s2->oerrors - s3->oerrors; 2026*7c478bd9Sstevel@tonic-gate } 2027*7c478bd9Sstevel@tonic-gate 2028*7c478bd9Sstevel@tonic-gate static void 2029*7c478bd9Sstevel@tonic-gate get_stats(char *module, int instance, char *name, pktsum_t *stats) 2030*7c478bd9Sstevel@tonic-gate { 2031*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 2032*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 2033*7c478bd9Sstevel@tonic-gate 2034*7c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 2035*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2036*7c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 2037*7c478bd9Sstevel@tonic-gate progname); 2038*7c478bd9Sstevel@tonic-gate return; 2039*7c478bd9Sstevel@tonic-gate } 2040*7c478bd9Sstevel@tonic-gate 2041*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, module, instance, name)) == NULL) { 2042*7c478bd9Sstevel@tonic-gate /* 2043*7c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 2044*7c478bd9Sstevel@tonic-gate * driver was already detached. 2045*7c478bd9Sstevel@tonic-gate */ 2046*7c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 2047*7c478bd9Sstevel@tonic-gate return; 2048*7c478bd9Sstevel@tonic-gate } 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) 2051*7c478bd9Sstevel@tonic-gate goto bail; 2052*7c478bd9Sstevel@tonic-gate 2053*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64, 2054*7c478bd9Sstevel@tonic-gate &stats->ipackets) < 0) 2055*7c478bd9Sstevel@tonic-gate goto bail; 2056*7c478bd9Sstevel@tonic-gate 2057*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64, 2058*7c478bd9Sstevel@tonic-gate &stats->opackets) < 0) 2059*7c478bd9Sstevel@tonic-gate goto bail; 2060*7c478bd9Sstevel@tonic-gate 2061*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64, 2062*7c478bd9Sstevel@tonic-gate &stats->rbytes) < 0) 2063*7c478bd9Sstevel@tonic-gate goto bail; 2064*7c478bd9Sstevel@tonic-gate 2065*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64, 2066*7c478bd9Sstevel@tonic-gate &stats->obytes) < 0) 2067*7c478bd9Sstevel@tonic-gate goto bail; 2068*7c478bd9Sstevel@tonic-gate 2069*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32, 2070*7c478bd9Sstevel@tonic-gate &stats->ierrors) < 0) 2071*7c478bd9Sstevel@tonic-gate goto bail; 2072*7c478bd9Sstevel@tonic-gate 2073*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32, 2074*7c478bd9Sstevel@tonic-gate &stats->oerrors) < 0) 2075*7c478bd9Sstevel@tonic-gate goto bail; 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 2078*7c478bd9Sstevel@tonic-gate return; 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate bail: 2081*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2082*7c478bd9Sstevel@tonic-gate gettext("%s: kstat operation failed\n"), 2083*7c478bd9Sstevel@tonic-gate progname); 2084*7c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 2085*7c478bd9Sstevel@tonic-gate } 2086*7c478bd9Sstevel@tonic-gate 2087*7c478bd9Sstevel@tonic-gate static void 2088*7c478bd9Sstevel@tonic-gate get_mac_stats(const char *dev, uint_t port, pktsum_t *stats) 2089*7c478bd9Sstevel@tonic-gate { 2090*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 2091*7c478bd9Sstevel@tonic-gate 2092*7c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 2095*7c478bd9Sstevel@tonic-gate get_stats((char *)dev, 0, name, stats); 2096*7c478bd9Sstevel@tonic-gate } 2097*7c478bd9Sstevel@tonic-gate 2098*7c478bd9Sstevel@tonic-gate static void 2099*7c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 2100*7c478bd9Sstevel@tonic-gate { 2101*7c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 2102*7c478bd9Sstevel@tonic-gate get_stats(NULL, -1, (char *)link, stats); 2103*7c478bd9Sstevel@tonic-gate } 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate static uint64_t 2106*7c478bd9Sstevel@tonic-gate mac_ifspeed(const char *dev, uint_t port) 2107*7c478bd9Sstevel@tonic-gate { 2108*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 2109*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 2110*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 2111*7c478bd9Sstevel@tonic-gate uint64_t ifspeed = 0; 2112*7c478bd9Sstevel@tonic-gate 2113*7c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 2114*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2115*7c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 2116*7c478bd9Sstevel@tonic-gate progname); 2117*7c478bd9Sstevel@tonic-gate return (0); 2118*7c478bd9Sstevel@tonic-gate } 2119*7c478bd9Sstevel@tonic-gate 2120*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 2121*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, (char *)dev, 0, name)) == NULL) { 2122*7c478bd9Sstevel@tonic-gate /* 2123*7c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 2124*7c478bd9Sstevel@tonic-gate * driver was already detached. 2125*7c478bd9Sstevel@tonic-gate */ 2126*7c478bd9Sstevel@tonic-gate goto bail; 2127*7c478bd9Sstevel@tonic-gate } 2128*7c478bd9Sstevel@tonic-gate 2129*7c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 2130*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2131*7c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 2132*7c478bd9Sstevel@tonic-gate progname); 2133*7c478bd9Sstevel@tonic-gate goto bail; 2134*7c478bd9Sstevel@tonic-gate } 2135*7c478bd9Sstevel@tonic-gate 2136*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64, &ifspeed) < 0) { 2137*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2138*7c478bd9Sstevel@tonic-gate gettext("%s: kstat value failed\n"), 2139*7c478bd9Sstevel@tonic-gate progname); 2140*7c478bd9Sstevel@tonic-gate goto bail; 2141*7c478bd9Sstevel@tonic-gate } 2142*7c478bd9Sstevel@tonic-gate 2143*7c478bd9Sstevel@tonic-gate bail: 2144*7c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 2145*7c478bd9Sstevel@tonic-gate return (ifspeed); 2146*7c478bd9Sstevel@tonic-gate } 2147*7c478bd9Sstevel@tonic-gate 2148*7c478bd9Sstevel@tonic-gate static char * 2149*7c478bd9Sstevel@tonic-gate mac_link_state(const char *dev, uint_t port) 2150*7c478bd9Sstevel@tonic-gate { 2151*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 2152*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 2153*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 2154*7c478bd9Sstevel@tonic-gate link_state_t link_state; 2155*7c478bd9Sstevel@tonic-gate char *state_str = "unknown"; 2156*7c478bd9Sstevel@tonic-gate 2157*7c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 2158*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2159*7c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 2160*7c478bd9Sstevel@tonic-gate progname); 2161*7c478bd9Sstevel@tonic-gate return (state_str); 2162*7c478bd9Sstevel@tonic-gate } 2163*7c478bd9Sstevel@tonic-gate 2164*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 2165*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, (char *)dev, 0, name)) == NULL) { 2166*7c478bd9Sstevel@tonic-gate /* 2167*7c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 2168*7c478bd9Sstevel@tonic-gate * driver was already detached. 2169*7c478bd9Sstevel@tonic-gate */ 2170*7c478bd9Sstevel@tonic-gate goto bail; 2171*7c478bd9Sstevel@tonic-gate } 2172*7c478bd9Sstevel@tonic-gate 2173*7c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 2174*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2175*7c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 2176*7c478bd9Sstevel@tonic-gate progname); 2177*7c478bd9Sstevel@tonic-gate goto bail; 2178*7c478bd9Sstevel@tonic-gate } 2179*7c478bd9Sstevel@tonic-gate 2180*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "link_state", KSTAT_DATA_UINT32, 2181*7c478bd9Sstevel@tonic-gate &link_state) < 0) { 2182*7c478bd9Sstevel@tonic-gate goto bail; 2183*7c478bd9Sstevel@tonic-gate } 2184*7c478bd9Sstevel@tonic-gate 2185*7c478bd9Sstevel@tonic-gate switch (link_state) { 2186*7c478bd9Sstevel@tonic-gate case LINK_STATE_UP: 2187*7c478bd9Sstevel@tonic-gate state_str = "up"; 2188*7c478bd9Sstevel@tonic-gate break; 2189*7c478bd9Sstevel@tonic-gate case LINK_STATE_DOWN: 2190*7c478bd9Sstevel@tonic-gate state_str = "down"; 2191*7c478bd9Sstevel@tonic-gate break; 2192*7c478bd9Sstevel@tonic-gate default: 2193*7c478bd9Sstevel@tonic-gate break; 2194*7c478bd9Sstevel@tonic-gate } 2195*7c478bd9Sstevel@tonic-gate 2196*7c478bd9Sstevel@tonic-gate bail: 2197*7c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 2198*7c478bd9Sstevel@tonic-gate return (state_str); 2199*7c478bd9Sstevel@tonic-gate } 2200*7c478bd9Sstevel@tonic-gate 2201*7c478bd9Sstevel@tonic-gate 2202*7c478bd9Sstevel@tonic-gate static char * 2203*7c478bd9Sstevel@tonic-gate mac_link_duplex(const char *dev, uint_t port) 2204*7c478bd9Sstevel@tonic-gate { 2205*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 2206*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 2207*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 2208*7c478bd9Sstevel@tonic-gate link_duplex_t link_duplex; 2209*7c478bd9Sstevel@tonic-gate char *duplex_str = "unknown"; 2210*7c478bd9Sstevel@tonic-gate 2211*7c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 2212*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2213*7c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 2214*7c478bd9Sstevel@tonic-gate progname); 2215*7c478bd9Sstevel@tonic-gate return (duplex_str); 2216*7c478bd9Sstevel@tonic-gate } 2217*7c478bd9Sstevel@tonic-gate 2218*7c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port); 2219*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kcp, (char *)dev, 0, name)) == NULL) { 2220*7c478bd9Sstevel@tonic-gate /* 2221*7c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 2222*7c478bd9Sstevel@tonic-gate * driver was already detached. 2223*7c478bd9Sstevel@tonic-gate */ 2224*7c478bd9Sstevel@tonic-gate goto bail; 2225*7c478bd9Sstevel@tonic-gate } 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 2228*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2229*7c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 2230*7c478bd9Sstevel@tonic-gate progname); 2231*7c478bd9Sstevel@tonic-gate goto bail; 2232*7c478bd9Sstevel@tonic-gate } 2233*7c478bd9Sstevel@tonic-gate 2234*7c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "link_duplex", KSTAT_DATA_UINT32, 2235*7c478bd9Sstevel@tonic-gate &link_duplex) < 0) { 2236*7c478bd9Sstevel@tonic-gate goto bail; 2237*7c478bd9Sstevel@tonic-gate } 2238*7c478bd9Sstevel@tonic-gate switch (link_duplex) { 2239*7c478bd9Sstevel@tonic-gate case LINK_DUPLEX_FULL: 2240*7c478bd9Sstevel@tonic-gate duplex_str = "full"; 2241*7c478bd9Sstevel@tonic-gate break; 2242*7c478bd9Sstevel@tonic-gate case LINK_DUPLEX_HALF: 2243*7c478bd9Sstevel@tonic-gate duplex_str = "half"; 2244*7c478bd9Sstevel@tonic-gate break; 2245*7c478bd9Sstevel@tonic-gate default: 2246*7c478bd9Sstevel@tonic-gate break; 2247*7c478bd9Sstevel@tonic-gate } 2248*7c478bd9Sstevel@tonic-gate 2249*7c478bd9Sstevel@tonic-gate bail: 2250*7c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 2251*7c478bd9Sstevel@tonic-gate return (duplex_str); 2252*7c478bd9Sstevel@tonic-gate } 2253