xref: /illumos-gate/usr/src/cmd/dlstat/dlstat.c (revision 3d349c31)
10dc2366fSVenugopal Iyer /*
20dc2366fSVenugopal Iyer  * CDDL HEADER START
30dc2366fSVenugopal Iyer  *
40dc2366fSVenugopal Iyer  * The contents of this file are subject to the terms of the
50dc2366fSVenugopal Iyer  * Common Development and Distribution License (the "License").
60dc2366fSVenugopal Iyer  * You may not use this file except in compliance with the License.
70dc2366fSVenugopal Iyer  *
80dc2366fSVenugopal Iyer  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90dc2366fSVenugopal Iyer  * or http://www.opensolaris.org/os/licensing.
100dc2366fSVenugopal Iyer  * See the License for the specific language governing permissions
110dc2366fSVenugopal Iyer  * and limitations under the License.
120dc2366fSVenugopal Iyer  *
130dc2366fSVenugopal Iyer  * When distributing Covered Code, include this CDDL HEADER in each
140dc2366fSVenugopal Iyer  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150dc2366fSVenugopal Iyer  * If applicable, add the following below this CDDL HEADER, with the
160dc2366fSVenugopal Iyer  * fields enclosed by brackets "[]" replaced with your own identifying
170dc2366fSVenugopal Iyer  * information: Portions Copyright [yyyy] [name of copyright owner]
180dc2366fSVenugopal Iyer  *
190dc2366fSVenugopal Iyer  * CDDL HEADER END
200dc2366fSVenugopal Iyer  */
210dc2366fSVenugopal Iyer /*
220dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230dc2366fSVenugopal Iyer  * Use is subject to license terms.
240dc2366fSVenugopal Iyer  */
250dc2366fSVenugopal Iyer 
26b2f26520SBryan Cantrill /*
27b2f26520SBryan Cantrill  * Copyright 2017 Joyent, Inc.
28b2f26520SBryan Cantrill  */
29b2f26520SBryan Cantrill 
30*3d349c31SPeter Tribble /*
31*3d349c31SPeter Tribble  * Copyright 2020 Peter Tribble.
32*3d349c31SPeter Tribble  */
33*3d349c31SPeter Tribble 
340dc2366fSVenugopal Iyer #include <stdio.h>
350dc2366fSVenugopal Iyer #include <ctype.h>
360dc2366fSVenugopal Iyer #include <locale.h>
370dc2366fSVenugopal Iyer #include <signal.h>
380dc2366fSVenugopal Iyer #include <stdarg.h>
390dc2366fSVenugopal Iyer #include <stdlib.h>
400dc2366fSVenugopal Iyer #include <fcntl.h>
410dc2366fSVenugopal Iyer #include <string.h>
420dc2366fSVenugopal Iyer #include <stropts.h>
430dc2366fSVenugopal Iyer #include <sys/stat.h>
440dc2366fSVenugopal Iyer #include <errno.h>
450dc2366fSVenugopal Iyer #include <strings.h>
460dc2366fSVenugopal Iyer #include <getopt.h>
470dc2366fSVenugopal Iyer #include <unistd.h>
480dc2366fSVenugopal Iyer #include <priv.h>
490dc2366fSVenugopal Iyer #include <termios.h>
500dc2366fSVenugopal Iyer #include <pwd.h>
510dc2366fSVenugopal Iyer #include <auth_attr.h>
520dc2366fSVenugopal Iyer #include <auth_list.h>
530dc2366fSVenugopal Iyer #include <libintl.h>
540dc2366fSVenugopal Iyer #include <libdevinfo.h>
550dc2366fSVenugopal Iyer #include <libdlpi.h>
560dc2366fSVenugopal Iyer #include <libdladm.h>
570dc2366fSVenugopal Iyer #include <libdllink.h>
580dc2366fSVenugopal Iyer #include <libdlstat.h>
590dc2366fSVenugopal Iyer #include <libdlaggr.h>
600dc2366fSVenugopal Iyer #include <libinetutil.h>
610dc2366fSVenugopal Iyer #include <bsm/adt.h>
620dc2366fSVenugopal Iyer #include <bsm/adt_event.h>
630dc2366fSVenugopal Iyer #include <stddef.h>
640dc2366fSVenugopal Iyer #include <ofmt.h>
650dc2366fSVenugopal Iyer 
660dc2366fSVenugopal Iyer typedef struct link_chain_s {
670dc2366fSVenugopal Iyer 	datalink_id_t		lc_linkid;
680dc2366fSVenugopal Iyer 	boolean_t		lc_visited;
690dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*lc_statchain[DLADM_STAT_NUM_STATS];
700dc2366fSVenugopal Iyer 	struct link_chain_s	*lc_next;
710dc2366fSVenugopal Iyer } link_chain_t;
720dc2366fSVenugopal Iyer 
730dc2366fSVenugopal Iyer typedef void *	(*stats2str_t)(const char *, void *,
740dc2366fSVenugopal Iyer 		    char, boolean_t);
750dc2366fSVenugopal Iyer 
760dc2366fSVenugopal Iyer typedef struct show_state {
770dc2366fSVenugopal Iyer 	link_chain_t	*ls_linkchain;
780dc2366fSVenugopal Iyer 	boolean_t	ls_stattype[DLADM_STAT_NUM_STATS];
790dc2366fSVenugopal Iyer 	stats2str_t	ls_stats2str[DLADM_STAT_NUM_STATS];
800dc2366fSVenugopal Iyer 	ofmt_handle_t	ls_ofmt;
810dc2366fSVenugopal Iyer 	char		ls_unit;
820dc2366fSVenugopal Iyer 	boolean_t	ls_parsable;
830dc2366fSVenugopal Iyer } show_state_t;
840dc2366fSVenugopal Iyer 
850dc2366fSVenugopal Iyer typedef struct show_history_state_s {
860dc2366fSVenugopal Iyer 	boolean_t	hs_plot;
870dc2366fSVenugopal Iyer 	boolean_t	hs_parsable;
880dc2366fSVenugopal Iyer 	boolean_t	hs_printheader;
890dc2366fSVenugopal Iyer 	boolean_t	hs_first;
900dc2366fSVenugopal Iyer 	boolean_t	hs_showall;
910dc2366fSVenugopal Iyer 	ofmt_handle_t	hs_ofmt;
920dc2366fSVenugopal Iyer } show_history_state_t;
930dc2366fSVenugopal Iyer 
940dc2366fSVenugopal Iyer /*
950dc2366fSVenugopal Iyer  * callback functions for printing output and error diagnostics.
960dc2366fSVenugopal Iyer  */
970dc2366fSVenugopal Iyer static ofmt_cb_t print_default_cb;
980dc2366fSVenugopal Iyer 
990dc2366fSVenugopal Iyer typedef void cmdfunc_t(int, char **, const char *);
1000dc2366fSVenugopal Iyer 
1010dc2366fSVenugopal Iyer static cmdfunc_t do_show, do_show_history, do_show_phys, do_show_link;
1020dc2366fSVenugopal Iyer static cmdfunc_t do_show_aggr;
1030dc2366fSVenugopal Iyer 
1040dc2366fSVenugopal Iyer static void	die(const char *, ...);
1050dc2366fSVenugopal Iyer static void	die_optdup(int);
1060dc2366fSVenugopal Iyer static void	die_opterr(int, int, const char *);
1070dc2366fSVenugopal Iyer static void	die_dlerr(dladm_status_t, const char *, ...);
1080dc2366fSVenugopal Iyer static void	warn(const char *, ...);
1090dc2366fSVenugopal Iyer 
1100dc2366fSVenugopal Iyer typedef struct	cmd {
1110dc2366fSVenugopal Iyer 	char		*c_name;
1120dc2366fSVenugopal Iyer 	cmdfunc_t	*c_fn;
1130dc2366fSVenugopal Iyer 	const char	*c_usage;
1140dc2366fSVenugopal Iyer } cmd_t;
1150dc2366fSVenugopal Iyer 
1160dc2366fSVenugopal Iyer static cmd_t	cmds[] = {
1170dc2366fSVenugopal Iyer 	{ "",		do_show,
1180dc2366fSVenugopal Iyer 	    "dlstat [-r | -t] [-i <interval>] [link]\n"
1190dc2366fSVenugopal Iyer 	    "       dlstat [-a | -A] [-i <interval>] [-p] [ -o field[,...]]\n"
1200dc2366fSVenugopal Iyer 	    "              [-u R|K|M|G|T|P] [link]"},
1210dc2366fSVenugopal Iyer 	{ "show-phys", do_show_phys,
1220dc2366fSVenugopal Iyer 	    "dlstat show-phys [-r | -t] [-i interval] [-a]\n"
1230dc2366fSVenugopal Iyer 	    "                 [-p] [ -o field[,...]] [-u R|K|M|G|T|P] "
1240dc2366fSVenugopal Iyer 	    "[link]"},
1250dc2366fSVenugopal Iyer 	{ "show-link", do_show_link,
1260dc2366fSVenugopal Iyer 	    "dlstat show-link [-r [-F] | -t] [-i interval] [-a]\n"
1270dc2366fSVenugopal Iyer 	    "                 [-p] [ -o field[,...]] [-u R|K|M|G|T|P] "
1280dc2366fSVenugopal Iyer 	    "[link]\n"
1290dc2366fSVenugopal Iyer 	    "       dlstat show-link -h [-a] [-d] [-F <format>]\n"
1300dc2366fSVenugopal Iyer 	    "                 [-s <DD/MM/YYYY,HH:MM:SS>] "
1310dc2366fSVenugopal Iyer 	    "[-e <DD/MM/YYYY,HH:MM:SS>]\n"
1320dc2366fSVenugopal Iyer 	    "                 -f <logfile> [<link>]" },
1330dc2366fSVenugopal Iyer 	{ "show-aggr", do_show_aggr,
1340dc2366fSVenugopal Iyer 	    "dlstat show-aggr [-r | -t] [-i interval] [-p]\n"
1350dc2366fSVenugopal Iyer 	    "                 [ -o field[,...]] [-u R|K|M|G|T|P] "
1360dc2366fSVenugopal Iyer 	    " [link]" }
1370dc2366fSVenugopal Iyer };
1380dc2366fSVenugopal Iyer 
1390dc2366fSVenugopal Iyer #define	MAXSTATLEN 15
1400dc2366fSVenugopal Iyer 
1410dc2366fSVenugopal Iyer /*
1420dc2366fSVenugopal Iyer  * dlstat : total stat fields
1430dc2366fSVenugopal Iyer  */
1440dc2366fSVenugopal Iyer typedef struct total_fields_buf_s {
1450dc2366fSVenugopal Iyer 	char t_linkname[MAXLINKNAMELEN];
1460dc2366fSVenugopal Iyer 	char t_ipackets[MAXSTATLEN];
1470dc2366fSVenugopal Iyer 	char t_rbytes[MAXSTATLEN];
1480dc2366fSVenugopal Iyer 	char t_opackets[MAXSTATLEN];
1490dc2366fSVenugopal Iyer 	char t_obytes[MAXSTATLEN];
1500dc2366fSVenugopal Iyer } total_fields_buf_t;
1510dc2366fSVenugopal Iyer 
1520dc2366fSVenugopal Iyer static ofmt_field_t total_s_fields[] = {
1530dc2366fSVenugopal Iyer { "LINK",	15,
1540dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_linkname),	print_default_cb},
1550dc2366fSVenugopal Iyer { "IPKTS",	8,
1560dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_ipackets),	print_default_cb},
1570dc2366fSVenugopal Iyer { "RBYTES",	8,
1580dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_rbytes),	print_default_cb},
1590dc2366fSVenugopal Iyer { "OPKTS",	8,
1600dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_opackets),	print_default_cb},
1610dc2366fSVenugopal Iyer { "OBYTES",	8,
1620dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_obytes),	print_default_cb},
1630dc2366fSVenugopal Iyer { NULL,		0,	0,		NULL}};
1640dc2366fSVenugopal Iyer 
1650dc2366fSVenugopal Iyer /*
1660dc2366fSVenugopal Iyer  * dlstat show-phys: both Rx and Tx stat fields
1670dc2366fSVenugopal Iyer  */
1680dc2366fSVenugopal Iyer typedef struct ring_fields_buf_s {
1690dc2366fSVenugopal Iyer 	char r_linkname[MAXLINKNAMELEN];
1700dc2366fSVenugopal Iyer 	char r_type[MAXSTATLEN];
1710dc2366fSVenugopal Iyer 	char r_id[MAXSTATLEN];
1720dc2366fSVenugopal Iyer 	char r_index[MAXSTATLEN];
1730dc2366fSVenugopal Iyer 	char r_packets[MAXSTATLEN];
1740dc2366fSVenugopal Iyer 	char r_bytes[MAXSTATLEN];
1750dc2366fSVenugopal Iyer } ring_fields_buf_t;
1760dc2366fSVenugopal Iyer 
1770dc2366fSVenugopal Iyer static ofmt_field_t ring_s_fields[] = {
1780dc2366fSVenugopal Iyer { "LINK",	15,
1790dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_linkname),	print_default_cb},
1800dc2366fSVenugopal Iyer { "TYPE",	5,
1810dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_type),	print_default_cb},
1820dc2366fSVenugopal Iyer { "ID",		7,
1830dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_id),		print_default_cb},
1840dc2366fSVenugopal Iyer { "INDEX",	6,
1850dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_index),	print_default_cb},
1860dc2366fSVenugopal Iyer { "PKTS",	8,
1870dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_packets),	print_default_cb},
1880dc2366fSVenugopal Iyer { "BYTES",	8,
1890dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_bytes),	print_default_cb},
1900dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
1910dc2366fSVenugopal Iyer 
1920dc2366fSVenugopal Iyer /*
1930dc2366fSVenugopal Iyer  * dlstat show-phys -r: Rx Ring stat fields
1940dc2366fSVenugopal Iyer  */
1950dc2366fSVenugopal Iyer typedef struct rx_ring_fields_buf_s {
1960dc2366fSVenugopal Iyer 	char rr_linkname[MAXLINKNAMELEN];
1970dc2366fSVenugopal Iyer 	char rr_type[MAXSTATLEN];
1980dc2366fSVenugopal Iyer 	char rr_id[MAXSTATLEN];
1990dc2366fSVenugopal Iyer 	char rr_index[MAXSTATLEN];
2000dc2366fSVenugopal Iyer 	char rr_ipackets[MAXSTATLEN];
2010dc2366fSVenugopal Iyer 	char rr_rbytes[MAXSTATLEN];
2020dc2366fSVenugopal Iyer } rx_ring_fields_buf_t;
2030dc2366fSVenugopal Iyer 
2040dc2366fSVenugopal Iyer static ofmt_field_t rx_ring_s_fields[] = {
2050dc2366fSVenugopal Iyer { "LINK",	15,
2060dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_linkname),	print_default_cb},
2070dc2366fSVenugopal Iyer { "TYPE",	5,
2080dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_type),		print_default_cb},
2090dc2366fSVenugopal Iyer { "ID",		7,
2100dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_id),		print_default_cb},
2110dc2366fSVenugopal Iyer { "INDEX",	6,
2120dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_index),		print_default_cb},
2130dc2366fSVenugopal Iyer { "IPKTS",	8,
2140dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_ipackets),	print_default_cb},
2150dc2366fSVenugopal Iyer { "RBYTES",	8,
2160dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_rbytes),		print_default_cb},
2170dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
2180dc2366fSVenugopal Iyer 
2190dc2366fSVenugopal Iyer /*
2200dc2366fSVenugopal Iyer  * dlstat show-phys -t: Tx Ring stat fields
2210dc2366fSVenugopal Iyer  */
2220dc2366fSVenugopal Iyer typedef struct tx_ring_fields_buf_s {
2230dc2366fSVenugopal Iyer 	char tr_linkname[MAXLINKNAMELEN];
2240dc2366fSVenugopal Iyer 	char tr_type[MAXSTATLEN];
2250dc2366fSVenugopal Iyer 	char tr_id[MAXSTATLEN];
2260dc2366fSVenugopal Iyer 	char tr_index[MAXSTATLEN];
2270dc2366fSVenugopal Iyer 	char tr_opackets[MAXSTATLEN];
2280dc2366fSVenugopal Iyer 	char tr_obytes[MAXSTATLEN];
2290dc2366fSVenugopal Iyer } tx_ring_fields_buf_t;
2300dc2366fSVenugopal Iyer 
2310dc2366fSVenugopal Iyer static ofmt_field_t tx_ring_s_fields[] = {
2320dc2366fSVenugopal Iyer { "LINK",	15,
2330dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_linkname),	print_default_cb},
2340dc2366fSVenugopal Iyer { "TYPE",	5,
2350dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_type),		print_default_cb},
2360dc2366fSVenugopal Iyer { "ID",		7,
2370dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_id),		print_default_cb},
2380dc2366fSVenugopal Iyer { "INDEX",	6,
2390dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_index),		print_default_cb},
2400dc2366fSVenugopal Iyer { "OPKTS",	8,
2410dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_opackets),	print_default_cb},
2420dc2366fSVenugopal Iyer { "OBYTES",	8,
2430dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_obytes),		print_default_cb},
2440dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
2450dc2366fSVenugopal Iyer 
2460dc2366fSVenugopal Iyer /*
2470dc2366fSVenugopal Iyer  * dlstat show-link: both Rx and Tx lane fields
2480dc2366fSVenugopal Iyer  */
2490dc2366fSVenugopal Iyer typedef struct lane_fields_buf_s {
2500dc2366fSVenugopal Iyer 	char l_linkname[MAXLINKNAMELEN];
2510dc2366fSVenugopal Iyer 	char l_type[MAXSTATLEN];
2520dc2366fSVenugopal Iyer 	char l_id[MAXSTATLEN];
2530dc2366fSVenugopal Iyer 	char l_index[MAXSTATLEN];
2540dc2366fSVenugopal Iyer 	char l_packets[MAXSTATLEN];
2550dc2366fSVenugopal Iyer 	char l_bytes[MAXSTATLEN];
2560dc2366fSVenugopal Iyer } lane_fields_buf_t;
2570dc2366fSVenugopal Iyer 
2580dc2366fSVenugopal Iyer static ofmt_field_t lane_s_fields[] = {
2590dc2366fSVenugopal Iyer { "LINK",	15,
2600dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_linkname),	print_default_cb},
2610dc2366fSVenugopal Iyer { "TYPE",	5,
2620dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_type),	print_default_cb},
2630dc2366fSVenugopal Iyer { "ID",		7,
2640dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_id),		print_default_cb},
2650dc2366fSVenugopal Iyer { "INDEX",	6,
2660dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_index),	print_default_cb},
2670dc2366fSVenugopal Iyer { "PKTS",	8,
2680dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_packets),	print_default_cb},
2690dc2366fSVenugopal Iyer { "BYTES",	8,
2700dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_bytes),	print_default_cb},
2710dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
2720dc2366fSVenugopal Iyer 
2730dc2366fSVenugopal Iyer /*
2740dc2366fSVenugopal Iyer  * dlstat show-link -r, dlstat -r: Rx Lane stat fields
2750dc2366fSVenugopal Iyer  */
2760dc2366fSVenugopal Iyer typedef struct rx_lane_fields_buf_s {
2770dc2366fSVenugopal Iyer 	char rl_linkname[MAXLINKNAMELEN];
2780dc2366fSVenugopal Iyer 	char rl_type[MAXSTATLEN];
2790dc2366fSVenugopal Iyer 	char rl_id[MAXSTATLEN];
2800dc2366fSVenugopal Iyer 	char rl_index[MAXSTATLEN];
2810dc2366fSVenugopal Iyer 	char rl_ipackets[MAXSTATLEN];
2820dc2366fSVenugopal Iyer 	char rl_rbytes[MAXSTATLEN];
2830dc2366fSVenugopal Iyer 	char rl_intrs[MAXSTATLEN];
2840dc2366fSVenugopal Iyer 	char rl_polls[MAXSTATLEN];
2850dc2366fSVenugopal Iyer 	char rl_sdrops[MAXSTATLEN];
2860dc2366fSVenugopal Iyer 	char rl_chl10[MAXSTATLEN];
2870dc2366fSVenugopal Iyer 	char rl_ch10_50[MAXSTATLEN];
2880dc2366fSVenugopal Iyer 	char rl_chg50[MAXSTATLEN];
2890dc2366fSVenugopal Iyer } rx_lane_fields_buf_t;
2900dc2366fSVenugopal Iyer 
2910dc2366fSVenugopal Iyer static ofmt_field_t rx_lane_s_fields[] = {
2920dc2366fSVenugopal Iyer { "LINK",	10,
2930dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_linkname),	print_default_cb},
2940dc2366fSVenugopal Iyer { "TYPE",	5,
2950dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_type),		print_default_cb},
2960dc2366fSVenugopal Iyer { "ID",		7,
2970dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_id),		print_default_cb},
2980dc2366fSVenugopal Iyer { "INDEX",	6,
2990dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_index),		print_default_cb},
3000dc2366fSVenugopal Iyer { "IPKTS",	8,
3010dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_ipackets),	print_default_cb},
3020dc2366fSVenugopal Iyer { "RBYTES",	8,
3030dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_rbytes),		print_default_cb},
3040dc2366fSVenugopal Iyer { "INTRS",	8,
3050dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_intrs),		print_default_cb},
3060dc2366fSVenugopal Iyer { "POLLS",	8,
3070dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_polls),		print_default_cb},
3080dc2366fSVenugopal Iyer { "SDROPS",	8,
3090dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_sdrops),		print_default_cb},
3100dc2366fSVenugopal Iyer { "CH<10",	8,
3110dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_chl10),		print_default_cb},
3120dc2366fSVenugopal Iyer { "CH10-50",	8,
3130dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_ch10_50),		print_default_cb},
3140dc2366fSVenugopal Iyer { "CH>50",	8,
3150dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_chg50),		print_default_cb},
3160dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
3170dc2366fSVenugopal Iyer 
3180dc2366fSVenugopal Iyer /*
3190dc2366fSVenugopal Iyer  * dlstat show-link -r -F: Rx fanout stat fields
3200dc2366fSVenugopal Iyer  */
3210dc2366fSVenugopal Iyer typedef struct rx_fanout_lane_fields_buf_s {
3220dc2366fSVenugopal Iyer 	char rfl_linkname[MAXLINKNAMELEN];
3230dc2366fSVenugopal Iyer 	char rfl_type[MAXSTATLEN];
3240dc2366fSVenugopal Iyer 	char rfl_id[MAXSTATLEN];
3250dc2366fSVenugopal Iyer 	char rfl_index[MAXSTATLEN];
3260dc2366fSVenugopal Iyer 	char rfl_fout[MAXSTATLEN];
3270dc2366fSVenugopal Iyer 	char rfl_ipackets[MAXSTATLEN];
3280dc2366fSVenugopal Iyer 	char rfl_rbytes[MAXSTATLEN];
3290dc2366fSVenugopal Iyer } rx_fanout_lane_fields_buf_t;
3300dc2366fSVenugopal Iyer 
3310dc2366fSVenugopal Iyer static ofmt_field_t rx_fanout_lane_s_fields[] = {
3320dc2366fSVenugopal Iyer { "LINK",	15,
3330dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_linkname), print_default_cb},
3340dc2366fSVenugopal Iyer { "TYPE",	5,
3350dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_type),	print_default_cb},
3360dc2366fSVenugopal Iyer { "ID",		7,
3370dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_id),	print_default_cb},
3380dc2366fSVenugopal Iyer { "INDEX",	6,
3390dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_index),	print_default_cb},
3400dc2366fSVenugopal Iyer { "FOUT",	6,
3410dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_fout),	print_default_cb},
3420dc2366fSVenugopal Iyer { "IPKTS",	8,
3430dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_ipackets), print_default_cb},
3440dc2366fSVenugopal Iyer { "RBYTES",	8,
3450dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_rbytes),	print_default_cb},
3460dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
3470dc2366fSVenugopal Iyer 
3480dc2366fSVenugopal Iyer /*
3490dc2366fSVenugopal Iyer  * dlstat show-link -t: Tx Lane stat fields
3500dc2366fSVenugopal Iyer  */
3510dc2366fSVenugopal Iyer typedef struct tx_lane_fields_buf_s {
3520dc2366fSVenugopal Iyer 	char tl_linkname[MAXLINKNAMELEN];
3530dc2366fSVenugopal Iyer 	char tl_index[MAXSTATLEN];
3540dc2366fSVenugopal Iyer 	char tl_type[MAXSTATLEN];
3550dc2366fSVenugopal Iyer 	char tl_id[MAXSTATLEN];
3560dc2366fSVenugopal Iyer 	char tl_opackets[MAXSTATLEN];
3570dc2366fSVenugopal Iyer 	char tl_obytes[MAXSTATLEN];
3580dc2366fSVenugopal Iyer 	char tl_blockcnt[MAXSTATLEN];
3590dc2366fSVenugopal Iyer 	char tl_unblockcnt[MAXSTATLEN];
3600dc2366fSVenugopal Iyer 	char tl_sdrops[MAXSTATLEN];
3610dc2366fSVenugopal Iyer } tx_lane_fields_buf_t;
3620dc2366fSVenugopal Iyer 
3630dc2366fSVenugopal Iyer static ofmt_field_t tx_lane_s_fields[] = {
3640dc2366fSVenugopal Iyer { "LINK",	15,
3650dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_linkname),	print_default_cb},
3660dc2366fSVenugopal Iyer { "TYPE",	5,
3670dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_type),		print_default_cb},
3680dc2366fSVenugopal Iyer { "ID",		7,
3690dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_id),		print_default_cb},
3700dc2366fSVenugopal Iyer { "INDEX",	6,
3710dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_index),		print_default_cb},
3720dc2366fSVenugopal Iyer { "OPKTS",	8,
3730dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_opackets),	print_default_cb},
3740dc2366fSVenugopal Iyer { "OBYTES",	8,
3750dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_obytes),		print_default_cb},
3760dc2366fSVenugopal Iyer { "BLKCNT",	8,
3770dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_blockcnt),	print_default_cb},
3780dc2366fSVenugopal Iyer { "UBLKCNT",	8,
3790dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_unblockcnt),	print_default_cb},
3800dc2366fSVenugopal Iyer { "SDROPS",	8,
3810dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_sdrops),		print_default_cb},
3820dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
3830dc2366fSVenugopal Iyer 
3840dc2366fSVenugopal Iyer /*
3850dc2366fSVenugopal Iyer  * dlstat show-aggr: aggr port stat fields
3860dc2366fSVenugopal Iyer  */
3870dc2366fSVenugopal Iyer typedef struct aggr_port_fields_buf_s {
3880dc2366fSVenugopal Iyer 	char ap_linkname[MAXLINKNAMELEN];
3890dc2366fSVenugopal Iyer 	char ap_portname[MAXLINKNAMELEN];
3900dc2366fSVenugopal Iyer 	char ap_ipackets[MAXSTATLEN];
3910dc2366fSVenugopal Iyer 	char ap_rbytes[MAXSTATLEN];
3920dc2366fSVenugopal Iyer 	char ap_opackets[MAXSTATLEN];
3930dc2366fSVenugopal Iyer 	char ap_obytes[MAXSTATLEN];
3940dc2366fSVenugopal Iyer } aggr_port_fields_buf_t;
3950dc2366fSVenugopal Iyer 
3960dc2366fSVenugopal Iyer static ofmt_field_t aggr_port_s_fields[] = {
3970dc2366fSVenugopal Iyer { "LINK",	15,
3980dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_linkname),	print_default_cb},
3990dc2366fSVenugopal Iyer { "PORT",	15,
4000dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_portname),	print_default_cb},
4010dc2366fSVenugopal Iyer { "IPKTS",	8,
4020dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_ipackets),	print_default_cb},
4030dc2366fSVenugopal Iyer { "RBYTES",	8,
4040dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_rbytes),	print_default_cb},
4050dc2366fSVenugopal Iyer { "OPKTS",	8,
4060dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_opackets),	print_default_cb},
4070dc2366fSVenugopal Iyer { "OBYTES",	8,
4080dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_obytes),	print_default_cb},
4090dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
4100dc2366fSVenugopal Iyer 
4110dc2366fSVenugopal Iyer /*
4120dc2366fSVenugopal Iyer  * structures for 'dlstat show-link -h'
4130dc2366fSVenugopal Iyer  */
4140dc2366fSVenugopal Iyer typedef struct  history_fields_buf_s {
4150dc2366fSVenugopal Iyer 	char	h_link[12];
4160dc2366fSVenugopal Iyer 	char	h_duration[10];
4170dc2366fSVenugopal Iyer 	char	h_ipackets[9];
4180dc2366fSVenugopal Iyer 	char	h_rbytes[10];
4190dc2366fSVenugopal Iyer 	char	h_opackets[9];
4200dc2366fSVenugopal Iyer 	char	h_obytes[10];
421*3d349c31SPeter Tribble 	char	h_bandwidth[15];
4220dc2366fSVenugopal Iyer } history_fields_buf_t;
4230dc2366fSVenugopal Iyer 
4240dc2366fSVenugopal Iyer static ofmt_field_t history_fields[] = {
4250dc2366fSVenugopal Iyer { "LINK",	13,
4260dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_link), print_default_cb},
4270dc2366fSVenugopal Iyer { "DURATION",	11,
4280dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_duration), print_default_cb},
4290dc2366fSVenugopal Iyer { "IPKTS",	10,
4300dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_ipackets), print_default_cb},
4310dc2366fSVenugopal Iyer { "RBYTES",	11,
4320dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_rbytes), print_default_cb},
4330dc2366fSVenugopal Iyer { "OPKTS",	10,
4340dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_opackets), print_default_cb},
4350dc2366fSVenugopal Iyer { "OBYTES",	11,
4360dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_obytes), print_default_cb},
437*3d349c31SPeter Tribble { "BANDWIDTH",	16,
4380dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_bandwidth), print_default_cb},
4390dc2366fSVenugopal Iyer { NULL,		0, 0, NULL}};
4400dc2366fSVenugopal Iyer 
4410dc2366fSVenugopal Iyer /*
4420dc2366fSVenugopal Iyer  * structures for 'dlstat show-link -h link'
4430dc2366fSVenugopal Iyer  */
4440dc2366fSVenugopal Iyer typedef struct  history_l_fields_buf_s {
4450dc2366fSVenugopal Iyer 	char	hl_link[12];
4460dc2366fSVenugopal Iyer 	char	hl_stime[13];
4470dc2366fSVenugopal Iyer 	char	hl_etime[13];
4480dc2366fSVenugopal Iyer 	char	hl_rbytes[8];
4490dc2366fSVenugopal Iyer 	char	hl_obytes[8];
450*3d349c31SPeter Tribble 	char	hl_bandwidth[15];
4510dc2366fSVenugopal Iyer } history_l_fields_buf_t;
4520dc2366fSVenugopal Iyer 
4530dc2366fSVenugopal Iyer static ofmt_field_t history_l_fields[] = {
4540dc2366fSVenugopal Iyer /* name,	field width,	offset */
4550dc2366fSVenugopal Iyer { "LINK",	13,
4560dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_link), print_default_cb},
4570dc2366fSVenugopal Iyer { "START",	14,
4580dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_stime), print_default_cb},
4590dc2366fSVenugopal Iyer { "END",	14,
4600dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_etime), print_default_cb},
4610dc2366fSVenugopal Iyer { "RBYTES",	9,
4620dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_rbytes), print_default_cb},
4630dc2366fSVenugopal Iyer { "OBYTES",	9,
4640dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_obytes), print_default_cb},
465*3d349c31SPeter Tribble { "BANDWIDTH",	16,
4660dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_bandwidth), print_default_cb},
4670dc2366fSVenugopal Iyer { NULL,		0, 0, NULL}}
4680dc2366fSVenugopal Iyer ;
4690dc2366fSVenugopal Iyer 
4700dc2366fSVenugopal Iyer static char *progname;
4710dc2366fSVenugopal Iyer 
4720dc2366fSVenugopal Iyer /*
4730dc2366fSVenugopal Iyer  * Handle to libdladm.  Opened in main() before the sub-command
4740dc2366fSVenugopal Iyer  * specific function is called.
4750dc2366fSVenugopal Iyer  */
4760dc2366fSVenugopal Iyer static dladm_handle_t handle = NULL;
4770dc2366fSVenugopal Iyer 
4780dc2366fSVenugopal Iyer static void
usage(void)4790dc2366fSVenugopal Iyer usage(void)
4800dc2366fSVenugopal Iyer {
4810dc2366fSVenugopal Iyer 	int	i;
4820dc2366fSVenugopal Iyer 	cmd_t	*cmdp;
4830dc2366fSVenugopal Iyer 
4840dc2366fSVenugopal Iyer 	(void) fprintf(stderr, gettext("usage: "));
4850dc2366fSVenugopal Iyer 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
4860dc2366fSVenugopal Iyer 		cmdp = &cmds[i];
4870dc2366fSVenugopal Iyer 		if (cmdp->c_usage != NULL)
4880dc2366fSVenugopal Iyer 			(void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
4890dc2366fSVenugopal Iyer 	}
4900dc2366fSVenugopal Iyer 
4910dc2366fSVenugopal Iyer 	/* close dladm handle if it was opened */
4920dc2366fSVenugopal Iyer 	if (handle != NULL)
4930dc2366fSVenugopal Iyer 		dladm_close(handle);
4940dc2366fSVenugopal Iyer 
4950dc2366fSVenugopal Iyer 	exit(1);
4960dc2366fSVenugopal Iyer }
4970dc2366fSVenugopal Iyer 
4980dc2366fSVenugopal Iyer int
main(int argc,char * argv[])4990dc2366fSVenugopal Iyer main(int argc, char *argv[])
5000dc2366fSVenugopal Iyer {
5010dc2366fSVenugopal Iyer 	int		i;
5020dc2366fSVenugopal Iyer 	cmd_t		*cmdp;
5030dc2366fSVenugopal Iyer 	dladm_status_t	status;
5040dc2366fSVenugopal Iyer 
5050dc2366fSVenugopal Iyer 	(void) setlocale(LC_ALL, "");
5060dc2366fSVenugopal Iyer #if !defined(TEXT_DOMAIN)
5070dc2366fSVenugopal Iyer #define	TEXT_DOMAIN "SYS_TEST"
5080dc2366fSVenugopal Iyer #endif
5090dc2366fSVenugopal Iyer 	(void) textdomain(TEXT_DOMAIN);
5100dc2366fSVenugopal Iyer 
5110dc2366fSVenugopal Iyer 	progname = argv[0];
5120dc2366fSVenugopal Iyer 
5130dc2366fSVenugopal Iyer 	/* Open the libdladm handle */
5140dc2366fSVenugopal Iyer 	if ((status = dladm_open(&handle)) != DLADM_STATUS_OK)
5150dc2366fSVenugopal Iyer 		die_dlerr(status, "could not open /dev/dld");
5160dc2366fSVenugopal Iyer 
5170dc2366fSVenugopal Iyer 	if (argc == 1) {
5180dc2366fSVenugopal Iyer 		do_show(argc - 1, NULL, cmds[0].c_usage);
5190dc2366fSVenugopal Iyer 		goto done;
5200dc2366fSVenugopal Iyer 	}
5210dc2366fSVenugopal Iyer 
5220dc2366fSVenugopal Iyer 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
5230dc2366fSVenugopal Iyer 		cmdp = &cmds[i];
5240dc2366fSVenugopal Iyer 		if (strcmp(argv[1], cmdp->c_name) == 0) {
5250dc2366fSVenugopal Iyer 			cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage);
5260dc2366fSVenugopal Iyer 			goto done;
5270dc2366fSVenugopal Iyer 		}
5280dc2366fSVenugopal Iyer 	}
5290dc2366fSVenugopal Iyer 
5300dc2366fSVenugopal Iyer 	do_show(argc, &argv[0], cmds[0].c_usage);
5310dc2366fSVenugopal Iyer 
5320dc2366fSVenugopal Iyer done:
5330dc2366fSVenugopal Iyer 	dladm_close(handle);
5340dc2366fSVenugopal Iyer 	return (0);
5350dc2366fSVenugopal Iyer }
5360dc2366fSVenugopal Iyer 
5370dc2366fSVenugopal Iyer /*ARGSUSED*/
5380dc2366fSVenugopal Iyer static int
show_history_date(dladm_usage_t * history,void * arg)5390dc2366fSVenugopal Iyer show_history_date(dladm_usage_t *history, void *arg)
5400dc2366fSVenugopal Iyer {
5410dc2366fSVenugopal Iyer 	show_history_state_t	*state = arg;
5420dc2366fSVenugopal Iyer 	time_t			stime;
5430dc2366fSVenugopal Iyer 	char			timebuf[20];
5440dc2366fSVenugopal Iyer 	dladm_status_t		status;
5450dc2366fSVenugopal Iyer 	uint32_t		flags;
5460dc2366fSVenugopal Iyer 
5470dc2366fSVenugopal Iyer 	/*
5480dc2366fSVenugopal Iyer 	 * Only show history information for existing links unless '-a'
5490dc2366fSVenugopal Iyer 	 * is specified.
5500dc2366fSVenugopal Iyer 	 */
5510dc2366fSVenugopal Iyer 	if (!state->hs_showall) {
5520dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, history->du_name,
5530dc2366fSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
5540dc2366fSVenugopal Iyer 			return (status);
5550dc2366fSVenugopal Iyer 		}
5560dc2366fSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
5570dc2366fSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
5580dc2366fSVenugopal Iyer 	}
5590dc2366fSVenugopal Iyer 
5600dc2366fSVenugopal Iyer 	stime = history->du_stime;
5610dc2366fSVenugopal Iyer 	(void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y",
5620dc2366fSVenugopal Iyer 	    localtime(&stime));
5630dc2366fSVenugopal Iyer 	(void) printf("%s\n", timebuf);
5640dc2366fSVenugopal Iyer 
5650dc2366fSVenugopal Iyer 	return (DLADM_STATUS_OK);
5660dc2366fSVenugopal Iyer }
5670dc2366fSVenugopal Iyer 
5680dc2366fSVenugopal Iyer static int
show_history_time(dladm_usage_t * history,void * arg)5690dc2366fSVenugopal Iyer show_history_time(dladm_usage_t *history, void *arg)
5700dc2366fSVenugopal Iyer {
5710dc2366fSVenugopal Iyer 	show_history_state_t	*state = arg;
5720dc2366fSVenugopal Iyer 	char			buf[DLADM_STRSIZE];
573*3d349c31SPeter Tribble 	history_l_fields_buf_t	ubuf;
5740dc2366fSVenugopal Iyer 	time_t			time;
5750dc2366fSVenugopal Iyer 	double			bw;
5760dc2366fSVenugopal Iyer 	dladm_status_t		status;
5770dc2366fSVenugopal Iyer 	uint32_t		flags;
5780dc2366fSVenugopal Iyer 
5790dc2366fSVenugopal Iyer 	/*
5800dc2366fSVenugopal Iyer 	 * Only show history information for existing links unless '-a'
5810dc2366fSVenugopal Iyer 	 * is specified.
5820dc2366fSVenugopal Iyer 	 */
5830dc2366fSVenugopal Iyer 	if (!state->hs_showall) {
5840dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, history->du_name,
5850dc2366fSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
5860dc2366fSVenugopal Iyer 			return (status);
5870dc2366fSVenugopal Iyer 		}
5880dc2366fSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
5890dc2366fSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
5900dc2366fSVenugopal Iyer 	}
5910dc2366fSVenugopal Iyer 
5920dc2366fSVenugopal Iyer 	if (state->hs_plot) {
5930dc2366fSVenugopal Iyer 		if (!state->hs_printheader) {
5940dc2366fSVenugopal Iyer 			if (state->hs_first) {
5950dc2366fSVenugopal Iyer 				(void) printf("# Time");
5960dc2366fSVenugopal Iyer 				state->hs_first = B_FALSE;
5970dc2366fSVenugopal Iyer 			}
5980dc2366fSVenugopal Iyer 			(void) printf(" %s", history->du_name);
5990dc2366fSVenugopal Iyer 			if (history->du_last) {
6000dc2366fSVenugopal Iyer 				(void) printf("\n");
6010dc2366fSVenugopal Iyer 				state->hs_first = B_TRUE;
6020dc2366fSVenugopal Iyer 				state->hs_printheader = B_TRUE;
6030dc2366fSVenugopal Iyer 			}
6040dc2366fSVenugopal Iyer 		} else {
6050dc2366fSVenugopal Iyer 			if (state->hs_first) {
6060dc2366fSVenugopal Iyer 				time = history->du_etime;
6070dc2366fSVenugopal Iyer 				(void) strftime(buf, sizeof (buf), "%T",
6080dc2366fSVenugopal Iyer 				    localtime(&time));
6090dc2366fSVenugopal Iyer 				state->hs_first = B_FALSE;
6100dc2366fSVenugopal Iyer 				(void) printf("%s", buf);
6110dc2366fSVenugopal Iyer 			}
6120dc2366fSVenugopal Iyer 			bw = (double)history->du_bandwidth/1000;
6130dc2366fSVenugopal Iyer 			(void) printf(" %.2f", bw);
6140dc2366fSVenugopal Iyer 			if (history->du_last) {
6150dc2366fSVenugopal Iyer 				(void) printf("\n");
6160dc2366fSVenugopal Iyer 				state->hs_first = B_TRUE;
6170dc2366fSVenugopal Iyer 			}
6180dc2366fSVenugopal Iyer 		}
6190dc2366fSVenugopal Iyer 		return (DLADM_STATUS_OK);
6200dc2366fSVenugopal Iyer 	}
6210dc2366fSVenugopal Iyer 
6220dc2366fSVenugopal Iyer 	bzero(&ubuf, sizeof (ubuf));
6230dc2366fSVenugopal Iyer 
6240dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_link, sizeof (ubuf.hl_link), "%s",
6250dc2366fSVenugopal Iyer 	    history->du_name);
6260dc2366fSVenugopal Iyer 	time = history->du_stime;
6270dc2366fSVenugopal Iyer 	(void) strftime(buf, sizeof (buf), "%T", localtime(&time));
6280dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_stime, sizeof (ubuf.hl_stime), "%s",
6290dc2366fSVenugopal Iyer 	    buf);
6300dc2366fSVenugopal Iyer 	time = history->du_etime;
6310dc2366fSVenugopal Iyer 	(void) strftime(buf, sizeof (buf), "%T", localtime(&time));
6320dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_etime, sizeof (ubuf.hl_etime), "%s",
6330dc2366fSVenugopal Iyer 	    buf);
6340dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_rbytes, sizeof (ubuf.hl_rbytes),
6350dc2366fSVenugopal Iyer 	    "%llu", history->du_rbytes);
6360dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_obytes, sizeof (ubuf.hl_obytes),
6370dc2366fSVenugopal Iyer 	    "%llu", history->du_obytes);
6380dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_bandwidth, sizeof (ubuf.hl_bandwidth),
6390dc2366fSVenugopal Iyer 	    "%s Mbps", dladm_bw2str(history->du_bandwidth, buf));
6400dc2366fSVenugopal Iyer 
6410dc2366fSVenugopal Iyer 	ofmt_print(state->hs_ofmt, &ubuf);
6420dc2366fSVenugopal Iyer 	return (DLADM_STATUS_OK);
6430dc2366fSVenugopal Iyer }
6440dc2366fSVenugopal Iyer 
6450dc2366fSVenugopal Iyer static int
show_history_res(dladm_usage_t * history,void * arg)6460dc2366fSVenugopal Iyer show_history_res(dladm_usage_t *history, void *arg)
6470dc2366fSVenugopal Iyer {
6480dc2366fSVenugopal Iyer 	show_history_state_t	*state = arg;
6490dc2366fSVenugopal Iyer 	char			buf[DLADM_STRSIZE];
6500dc2366fSVenugopal Iyer 	history_fields_buf_t	ubuf;
6510dc2366fSVenugopal Iyer 	dladm_status_t		status;
6520dc2366fSVenugopal Iyer 	uint32_t		flags;
6530dc2366fSVenugopal Iyer 
6540dc2366fSVenugopal Iyer 	/*
6550dc2366fSVenugopal Iyer 	 * Only show history information for existing links unless '-a'
6560dc2366fSVenugopal Iyer 	 * is specified.
6570dc2366fSVenugopal Iyer 	 */
6580dc2366fSVenugopal Iyer 	if (!state->hs_showall) {
6590dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, history->du_name,
6600dc2366fSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
6610dc2366fSVenugopal Iyer 			return (status);
6620dc2366fSVenugopal Iyer 		}
6630dc2366fSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
6640dc2366fSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
6650dc2366fSVenugopal Iyer 	}
6660dc2366fSVenugopal Iyer 
6670dc2366fSVenugopal Iyer 	bzero(&ubuf, sizeof (ubuf));
6680dc2366fSVenugopal Iyer 
6690dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_link, sizeof (ubuf.h_link), "%s",
6700dc2366fSVenugopal Iyer 	    history->du_name);
6710dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_duration, sizeof (ubuf.h_duration),
6720dc2366fSVenugopal Iyer 	    "%llu", history->du_duration);
6730dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_ipackets, sizeof (ubuf.h_ipackets),
6740dc2366fSVenugopal Iyer 	    "%llu", history->du_ipackets);
6750dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_rbytes, sizeof (ubuf.h_rbytes),
6760dc2366fSVenugopal Iyer 	    "%llu", history->du_rbytes);
6770dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_opackets, sizeof (ubuf.h_opackets),
6780dc2366fSVenugopal Iyer 	    "%llu", history->du_opackets);
6790dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_obytes, sizeof (ubuf.h_obytes),
6800dc2366fSVenugopal Iyer 	    "%llu", history->du_obytes);
6810dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_bandwidth, sizeof (ubuf.h_bandwidth),
6820dc2366fSVenugopal Iyer 	    "%s Mbps", dladm_bw2str(history->du_bandwidth, buf));
6830dc2366fSVenugopal Iyer 
6840dc2366fSVenugopal Iyer 	ofmt_print(state->hs_ofmt, &ubuf);
6850dc2366fSVenugopal Iyer 
6860dc2366fSVenugopal Iyer 	return (DLADM_STATUS_OK);
6870dc2366fSVenugopal Iyer }
6880dc2366fSVenugopal Iyer 
6890dc2366fSVenugopal Iyer static boolean_t
valid_formatspec(char * formatspec_str)6900dc2366fSVenugopal Iyer valid_formatspec(char *formatspec_str)
6910dc2366fSVenugopal Iyer {
6920dc2366fSVenugopal Iyer 	return (strcmp(formatspec_str, "gnuplot") == 0);
6930dc2366fSVenugopal Iyer }
6940dc2366fSVenugopal Iyer 
6950dc2366fSVenugopal Iyer /*ARGSUSED*/
6960dc2366fSVenugopal Iyer static void
do_show_history(int argc,char * argv[],const char * use)6970dc2366fSVenugopal Iyer do_show_history(int argc, char *argv[], const char *use)
6980dc2366fSVenugopal Iyer {
6990dc2366fSVenugopal Iyer 	char			*file = NULL;
7000dc2366fSVenugopal Iyer 	int			opt;
7010dc2366fSVenugopal Iyer 	dladm_status_t		status;
7020dc2366fSVenugopal Iyer 	boolean_t		d_arg = B_FALSE;
7030dc2366fSVenugopal Iyer 	char			*stime = NULL;
7040dc2366fSVenugopal Iyer 	char			*etime = NULL;
7050dc2366fSVenugopal Iyer 	char			*resource = NULL;
7060dc2366fSVenugopal Iyer 	show_history_state_t	state;
7070dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
7080dc2366fSVenugopal Iyer 	boolean_t		F_arg = B_FALSE;
7090dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
7100dc2366fSVenugopal Iyer 	char			*formatspec_str = NULL;
7110dc2366fSVenugopal Iyer 	char			*all_l_fields =
7120dc2366fSVenugopal Iyer 	    "link,start,end,rbytes,obytes,bandwidth";
7130dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
7140dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
7150dc2366fSVenugopal Iyer 	uint_t			ofmtflags = 0;
7160dc2366fSVenugopal Iyer 
7170dc2366fSVenugopal Iyer 	bzero(&state, sizeof (show_history_state_t));
7180dc2366fSVenugopal Iyer 	state.hs_parsable = B_FALSE;
7190dc2366fSVenugopal Iyer 	state.hs_printheader = B_FALSE;
7200dc2366fSVenugopal Iyer 	state.hs_plot = B_FALSE;
7210dc2366fSVenugopal Iyer 	state.hs_first = B_TRUE;
7220dc2366fSVenugopal Iyer 
7230dc2366fSVenugopal Iyer 	while ((opt = getopt(argc, argv, "das:e:o:f:F:")) != -1) {
7240dc2366fSVenugopal Iyer 		switch (opt) {
7250dc2366fSVenugopal Iyer 		case 'd':
7260dc2366fSVenugopal Iyer 			d_arg = B_TRUE;
7270dc2366fSVenugopal Iyer 			break;
7280dc2366fSVenugopal Iyer 		case 'a':
7290dc2366fSVenugopal Iyer 			state.hs_showall = B_TRUE;
7300dc2366fSVenugopal Iyer 			break;
7310dc2366fSVenugopal Iyer 		case 'f':
7320dc2366fSVenugopal Iyer 			file = optarg;
7330dc2366fSVenugopal Iyer 			break;
7340dc2366fSVenugopal Iyer 		case 's':
7350dc2366fSVenugopal Iyer 			stime = optarg;
7360dc2366fSVenugopal Iyer 			break;
7370dc2366fSVenugopal Iyer 		case 'e':
7380dc2366fSVenugopal Iyer 			etime = optarg;
7390dc2366fSVenugopal Iyer 			break;
7400dc2366fSVenugopal Iyer 		case 'o':
7410dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
7420dc2366fSVenugopal Iyer 			fields_str = optarg;
7430dc2366fSVenugopal Iyer 			break;
7440dc2366fSVenugopal Iyer 		case 'F':
7450dc2366fSVenugopal Iyer 			state.hs_plot = F_arg = B_TRUE;
7460dc2366fSVenugopal Iyer 			formatspec_str = optarg;
7470dc2366fSVenugopal Iyer 			break;
7480dc2366fSVenugopal Iyer 		default:
7490dc2366fSVenugopal Iyer 			die_opterr(optopt, opt, use);
7500dc2366fSVenugopal Iyer 			break;
7510dc2366fSVenugopal Iyer 		}
7520dc2366fSVenugopal Iyer 	}
7530dc2366fSVenugopal Iyer 
7540dc2366fSVenugopal Iyer 	if (file == NULL)
7550dc2366fSVenugopal Iyer 		die("show-link -h requires a file");
7560dc2366fSVenugopal Iyer 
7570dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
758*3d349c31SPeter Tribble 		uint32_t	flags;
7590dc2366fSVenugopal Iyer 
7600dc2366fSVenugopal Iyer 		resource = argv[optind];
7610dc2366fSVenugopal Iyer 		if (!state.hs_showall &&
7620dc2366fSVenugopal Iyer 		    (((status = dladm_name2info(handle, resource, NULL, &flags,
7630dc2366fSVenugopal Iyer 		    NULL, NULL)) != DLADM_STATUS_OK) ||
7640dc2366fSVenugopal Iyer 		    ((flags & DLADM_OPT_ACTIVE) == 0))) {
7650dc2366fSVenugopal Iyer 			die("invalid link: '%s'", resource);
7660dc2366fSVenugopal Iyer 		}
7670dc2366fSVenugopal Iyer 	}
7680dc2366fSVenugopal Iyer 
7690dc2366fSVenugopal Iyer 	if (F_arg && d_arg)
7700dc2366fSVenugopal Iyer 		die("incompatible -d and -F options");
7710dc2366fSVenugopal Iyer 
7720dc2366fSVenugopal Iyer 	if (F_arg && !valid_formatspec(formatspec_str))
7730dc2366fSVenugopal Iyer 		die("Format specifier %s not supported", formatspec_str);
7740dc2366fSVenugopal Iyer 
7750dc2366fSVenugopal Iyer 	if (state.hs_parsable)
7760dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
7770dc2366fSVenugopal Iyer 
7780dc2366fSVenugopal Iyer 	if (resource == NULL && stime == NULL && etime == NULL) {
7790dc2366fSVenugopal Iyer 		oferr = ofmt_open(fields_str, history_fields, ofmtflags, 0,
7800dc2366fSVenugopal Iyer 		    &ofmt);
7810dc2366fSVenugopal Iyer 	} else {
7820dc2366fSVenugopal Iyer 		if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
7830dc2366fSVenugopal Iyer 			fields_str = all_l_fields;
7840dc2366fSVenugopal Iyer 		oferr = ofmt_open(fields_str, history_l_fields, ofmtflags, 0,
7850dc2366fSVenugopal Iyer 		    &ofmt);
7860dc2366fSVenugopal Iyer 
7870dc2366fSVenugopal Iyer 	}
788b2f26520SBryan Cantrill 	ofmt_check(oferr, state.hs_parsable, ofmt, die, warn);
7890dc2366fSVenugopal Iyer 	state.hs_ofmt = ofmt;
7900dc2366fSVenugopal Iyer 
7910dc2366fSVenugopal Iyer 	if (d_arg) {
7920dc2366fSVenugopal Iyer 		/* Print log dates */
7930dc2366fSVenugopal Iyer 		status = dladm_usage_dates(show_history_date,
7940dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, resource, &state);
7950dc2366fSVenugopal Iyer 	} else if (resource == NULL && stime == NULL && etime == NULL &&
7960dc2366fSVenugopal Iyer 	    !F_arg) {
7970dc2366fSVenugopal Iyer 		/* Print summary */
7980dc2366fSVenugopal Iyer 		status = dladm_usage_summary(show_history_res,
7990dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, &state);
8000dc2366fSVenugopal Iyer 	} else if (resource != NULL) {
8010dc2366fSVenugopal Iyer 		/* Print log entries for named resource */
8020dc2366fSVenugopal Iyer 		status = dladm_walk_usage_res(show_history_time,
8030dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state);
8040dc2366fSVenugopal Iyer 	} else {
8050dc2366fSVenugopal Iyer 		/* Print time and information for each link */
8060dc2366fSVenugopal Iyer 		status = dladm_walk_usage_time(show_history_time,
8070dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, stime, etime, &state);
8080dc2366fSVenugopal Iyer 	}
8090dc2366fSVenugopal Iyer 
8100dc2366fSVenugopal Iyer 	if (status != DLADM_STATUS_OK)
8110dc2366fSVenugopal Iyer 		die_dlerr(status, "show-link -h");
8120dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
8130dc2366fSVenugopal Iyer }
8140dc2366fSVenugopal Iyer 
8150dc2366fSVenugopal Iyer boolean_t
dlstat_unit(char * oarg,char * unit)8160dc2366fSVenugopal Iyer dlstat_unit(char *oarg, char *unit)
8170dc2366fSVenugopal Iyer {
8180dc2366fSVenugopal Iyer 	if ((strcmp(oarg, "R") == 0) || (strcmp(oarg, "K") == 0) ||
8190dc2366fSVenugopal Iyer 	    (strcmp(oarg, "M") == 0) || (strcmp(oarg, "G") == 0) ||
8200dc2366fSVenugopal Iyer 	    (strcmp(oarg, "T") == 0) || (strcmp(oarg, "P") == 0)) {
8210dc2366fSVenugopal Iyer 		*unit = oarg[0];
8220dc2366fSVenugopal Iyer 		return (B_TRUE);
8230dc2366fSVenugopal Iyer 	}
8240dc2366fSVenugopal Iyer 
8250dc2366fSVenugopal Iyer 	return (B_FALSE);
8260dc2366fSVenugopal Iyer }
8270dc2366fSVenugopal Iyer 
8280dc2366fSVenugopal Iyer void
map_to_units(char * buf,uint_t bufsize,double num,char unit,boolean_t parsable)8290dc2366fSVenugopal Iyer map_to_units(char *buf, uint_t bufsize, double num, char unit,
8300dc2366fSVenugopal Iyer     boolean_t parsable)
8310dc2366fSVenugopal Iyer {
8320dc2366fSVenugopal Iyer 	if (parsable) {
8330dc2366fSVenugopal Iyer 		(void) snprintf(buf, bufsize, "%.0lf", num);
8340dc2366fSVenugopal Iyer 		return;
8350dc2366fSVenugopal Iyer 	}
8360dc2366fSVenugopal Iyer 
8370dc2366fSVenugopal Iyer 	if (unit == '\0') {
8380dc2366fSVenugopal Iyer 		int index;
8390dc2366fSVenugopal Iyer 
8400dc2366fSVenugopal Iyer 		for (index = 0; (int)(num/1000) != 0; index++, num /= 1000)
8410dc2366fSVenugopal Iyer 			;
8420dc2366fSVenugopal Iyer 
8430dc2366fSVenugopal Iyer 		switch (index) {
8440dc2366fSVenugopal Iyer 			case 0:
8450dc2366fSVenugopal Iyer 				unit = '\0';
8460dc2366fSVenugopal Iyer 				break;
8470dc2366fSVenugopal Iyer 			case 1:
8480dc2366fSVenugopal Iyer 				unit = 'K';
8490dc2366fSVenugopal Iyer 				break;
8500dc2366fSVenugopal Iyer 			case 2:
8510dc2366fSVenugopal Iyer 				unit = 'M';
8520dc2366fSVenugopal Iyer 				break;
8530dc2366fSVenugopal Iyer 			case 3:
8540dc2366fSVenugopal Iyer 				unit = 'G';
8550dc2366fSVenugopal Iyer 				break;
8560dc2366fSVenugopal Iyer 			case 4:
8570dc2366fSVenugopal Iyer 				unit = 'T';
8580dc2366fSVenugopal Iyer 				break;
8590dc2366fSVenugopal Iyer 			case 5:
8600dc2366fSVenugopal Iyer 				/* Largest unit supported */
8610dc2366fSVenugopal Iyer 			default:
8620dc2366fSVenugopal Iyer 				unit = 'P';
8630dc2366fSVenugopal Iyer 				break;
8640dc2366fSVenugopal Iyer 		}
8650dc2366fSVenugopal Iyer 	} else  {
8660dc2366fSVenugopal Iyer 		switch (unit) {
8670dc2366fSVenugopal Iyer 			case 'R':
8680dc2366fSVenugopal Iyer 				/* Already raw numbers */
8690dc2366fSVenugopal Iyer 				unit = '\0';
8700dc2366fSVenugopal Iyer 				break;
8710dc2366fSVenugopal Iyer 			case 'K':
8720dc2366fSVenugopal Iyer 				num /= 1000;
8730dc2366fSVenugopal Iyer 				break;
8740dc2366fSVenugopal Iyer 			case 'M':
8750dc2366fSVenugopal Iyer 				num /= (1000*1000);
8760dc2366fSVenugopal Iyer 				break;
8770dc2366fSVenugopal Iyer 			case 'G':
8780dc2366fSVenugopal Iyer 				num /= (1000*1000*1000);
8790dc2366fSVenugopal Iyer 				break;
8800dc2366fSVenugopal Iyer 			case 'T':
8810dc2366fSVenugopal Iyer 				num /= (1000.0*1000.0*1000.0*1000.0);
8820dc2366fSVenugopal Iyer 				break;
8830dc2366fSVenugopal Iyer 			case 'P':
8840dc2366fSVenugopal Iyer 				/* Largest unit supported */
8850dc2366fSVenugopal Iyer 			default:
8860dc2366fSVenugopal Iyer 				num /= (1000.0*1000.0*1000.0*1000.0*1000.0);
8870dc2366fSVenugopal Iyer 				break;
8880dc2366fSVenugopal Iyer 		}
8890dc2366fSVenugopal Iyer 	}
8900dc2366fSVenugopal Iyer 
8910dc2366fSVenugopal Iyer 	if (unit == '\0')
8920dc2366fSVenugopal Iyer 		(void) snprintf(buf, bufsize, " %7.0lf%c", num, unit);
8930dc2366fSVenugopal Iyer 	else
8940dc2366fSVenugopal Iyer 		(void) snprintf(buf, bufsize, " %6.2lf%c", num, unit);
8950dc2366fSVenugopal Iyer }
8960dc2366fSVenugopal Iyer 
8970dc2366fSVenugopal Iyer link_chain_t *
get_link_prev_stat(datalink_id_t linkid,void * arg)8980dc2366fSVenugopal Iyer get_link_prev_stat(datalink_id_t linkid, void *arg)
8990dc2366fSVenugopal Iyer {
9000dc2366fSVenugopal Iyer 	show_state_t	*state = (show_state_t *)arg;
9010dc2366fSVenugopal Iyer 	link_chain_t	*link_curr = NULL;
9020dc2366fSVenugopal Iyer 
9030dc2366fSVenugopal Iyer 	/* Scan prev linkid list and look for entry matching this entry */
9040dc2366fSVenugopal Iyer 	for (link_curr = state->ls_linkchain; link_curr;
9050dc2366fSVenugopal Iyer 	    link_curr = link_curr->lc_next) {
9060dc2366fSVenugopal Iyer 		if (link_curr->lc_linkid == linkid)
9070dc2366fSVenugopal Iyer 			break;
9080dc2366fSVenugopal Iyer 	}
9090dc2366fSVenugopal Iyer 				/* New link, add it */
9100dc2366fSVenugopal Iyer 	if (link_curr == NULL) {
9110dc2366fSVenugopal Iyer 		link_curr = (link_chain_t *)malloc(sizeof (link_chain_t));
9120dc2366fSVenugopal Iyer 		if (link_curr == NULL)
9130dc2366fSVenugopal Iyer 			goto done;
9140dc2366fSVenugopal Iyer 		link_curr->lc_linkid = linkid;
9150dc2366fSVenugopal Iyer 		bzero(&link_curr->lc_statchain,
9160dc2366fSVenugopal Iyer 		    sizeof (link_curr->lc_statchain));
9170dc2366fSVenugopal Iyer 		link_curr->lc_next = state->ls_linkchain;
9180dc2366fSVenugopal Iyer 		state->ls_linkchain = link_curr;
9190dc2366fSVenugopal Iyer 	}
9200dc2366fSVenugopal Iyer done:
9210dc2366fSVenugopal Iyer 	return (link_curr);
9220dc2366fSVenugopal Iyer }
9230dc2366fSVenugopal Iyer 
9240dc2366fSVenugopal Iyer /*
9250dc2366fSVenugopal Iyer  * Number of links may change while dlstat with -i is executing.
9260dc2366fSVenugopal Iyer  * Free memory allocated for links that are no longer there.
9270dc2366fSVenugopal Iyer  * Prepare for next iteration by marking visited = false for existing stat
9280dc2366fSVenugopal Iyer  * entries.
9290dc2366fSVenugopal Iyer  */
9300dc2366fSVenugopal Iyer static void
cleanup_removed_links(show_state_t * state)9310dc2366fSVenugopal Iyer cleanup_removed_links(show_state_t *state)
9320dc2366fSVenugopal Iyer {
9330dc2366fSVenugopal Iyer 	link_chain_t	*lcurr;
9340dc2366fSVenugopal Iyer 	link_chain_t	*lprev;
9350dc2366fSVenugopal Iyer 	link_chain_t	*tofree;
9360dc2366fSVenugopal Iyer 	int		i;
9370dc2366fSVenugopal Iyer 
9380dc2366fSVenugopal Iyer 	/* Delete all nodes from the list that have lc_visited marked false */
9390dc2366fSVenugopal Iyer 	lcurr = state->ls_linkchain;
9400dc2366fSVenugopal Iyer 	while (lcurr != NULL) {
9410dc2366fSVenugopal Iyer 		if (lcurr->lc_visited) {
9420dc2366fSVenugopal Iyer 			lcurr->lc_visited = B_FALSE;
9430dc2366fSVenugopal Iyer 			lprev = lcurr;
9440dc2366fSVenugopal Iyer 			lcurr = lcurr->lc_next;
9450dc2366fSVenugopal Iyer 			continue;
9460dc2366fSVenugopal Iyer 		}
9470dc2366fSVenugopal Iyer 				/* Is it head of the list? */
9480dc2366fSVenugopal Iyer 		if (lcurr == state->ls_linkchain)
9490dc2366fSVenugopal Iyer 			state->ls_linkchain = lcurr->lc_next;
9500dc2366fSVenugopal Iyer 		else
9510dc2366fSVenugopal Iyer 			lprev->lc_next = lcurr->lc_next;
9520dc2366fSVenugopal Iyer 				/* lprev remains the same */
9530dc2366fSVenugopal Iyer 		tofree = lcurr;
9540dc2366fSVenugopal Iyer 		lcurr = lcurr->lc_next;
9550dc2366fSVenugopal Iyer 
9560dc2366fSVenugopal Iyer 				/* Free stats memory for the removed link */
9570dc2366fSVenugopal Iyer 		for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
9580dc2366fSVenugopal Iyer 			if (state->ls_stattype[i])
9590dc2366fSVenugopal Iyer 				dladm_link_stat_free(tofree->lc_statchain[i]);
9600dc2366fSVenugopal Iyer 		}
9610dc2366fSVenugopal Iyer 		free(tofree);
9620dc2366fSVenugopal Iyer 	}
9630dc2366fSVenugopal Iyer }
9640dc2366fSVenugopal Iyer 
9650dc2366fSVenugopal Iyer void *
print_total_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)9660dc2366fSVenugopal Iyer print_total_stats(const char *linkname, void *statentry, char unit,
9670dc2366fSVenugopal Iyer     boolean_t parsable)
9680dc2366fSVenugopal Iyer {
9690dc2366fSVenugopal Iyer 	total_stat_entry_t	*sentry = statentry;
9700dc2366fSVenugopal Iyer 	total_stat_t		*link_stats = &sentry->tse_stats;
9710dc2366fSVenugopal Iyer 	total_fields_buf_t	*buf;
9720dc2366fSVenugopal Iyer 
9730dc2366fSVenugopal Iyer 	buf = malloc(sizeof (total_fields_buf_t));
9740dc2366fSVenugopal Iyer 	if (buf == NULL)
9750dc2366fSVenugopal Iyer 		goto done;
9760dc2366fSVenugopal Iyer 
9770dc2366fSVenugopal Iyer 	(void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s",
9780dc2366fSVenugopal Iyer 	    linkname);
9790dc2366fSVenugopal Iyer 
9800dc2366fSVenugopal Iyer 	map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets),
9810dc2366fSVenugopal Iyer 	    link_stats->ts_ipackets, unit, parsable);
9820dc2366fSVenugopal Iyer 
9830dc2366fSVenugopal Iyer 	map_to_units(buf->t_rbytes, sizeof (buf->t_rbytes),
9840dc2366fSVenugopal Iyer 	    link_stats->ts_rbytes, unit, parsable);
9850dc2366fSVenugopal Iyer 
9860dc2366fSVenugopal Iyer 	map_to_units(buf->t_opackets, sizeof (buf->t_opackets),
9870dc2366fSVenugopal Iyer 	    link_stats->ts_opackets, unit, parsable);
9880dc2366fSVenugopal Iyer 
9890dc2366fSVenugopal Iyer 	map_to_units(buf->t_obytes, sizeof (buf->t_obytes),
9900dc2366fSVenugopal Iyer 	    link_stats->ts_obytes, unit, parsable);
9910dc2366fSVenugopal Iyer 
9920dc2366fSVenugopal Iyer done:
9930dc2366fSVenugopal Iyer 	return (buf);
9940dc2366fSVenugopal Iyer }
9950dc2366fSVenugopal Iyer 
9960dc2366fSVenugopal Iyer void *
print_rx_generic_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)9970dc2366fSVenugopal Iyer print_rx_generic_ring_stats(const char *linkname, void *statentry, char unit,
9980dc2366fSVenugopal Iyer     boolean_t parsable)
9990dc2366fSVenugopal Iyer {
10000dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
10010dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
10020dc2366fSVenugopal Iyer 	ring_fields_buf_t	*buf;
10030dc2366fSVenugopal Iyer 
10040dc2366fSVenugopal Iyer 	buf = malloc(sizeof (ring_fields_buf_t));
10050dc2366fSVenugopal Iyer 	if (buf == NULL)
10060dc2366fSVenugopal Iyer 		goto done;
10070dc2366fSVenugopal Iyer 
10080dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
10090dc2366fSVenugopal Iyer 	    linkname);
10100dc2366fSVenugopal Iyer 
10110dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_type, sizeof (buf->r_type), "rx");
10120dc2366fSVenugopal Iyer 
10130dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
10140dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
10150dc2366fSVenugopal Iyer 	} else {
10160dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index),
10170dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
10180dc2366fSVenugopal Iyer 	}
10190dc2366fSVenugopal Iyer 
10200dc2366fSVenugopal Iyer 	map_to_units(buf->r_packets, sizeof (buf->r_packets),
10210dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
10220dc2366fSVenugopal Iyer 
10230dc2366fSVenugopal Iyer 	map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
10240dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
10250dc2366fSVenugopal Iyer 
10260dc2366fSVenugopal Iyer done:
10270dc2366fSVenugopal Iyer 	return (buf);
10280dc2366fSVenugopal Iyer }
10290dc2366fSVenugopal Iyer 
10300dc2366fSVenugopal Iyer void *
print_tx_generic_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)10310dc2366fSVenugopal Iyer print_tx_generic_ring_stats(const char *linkname, void *statentry, char unit,
10320dc2366fSVenugopal Iyer     boolean_t parsable)
10330dc2366fSVenugopal Iyer {
10340dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
10350dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
10360dc2366fSVenugopal Iyer 	ring_fields_buf_t	*buf;
10370dc2366fSVenugopal Iyer 
10380dc2366fSVenugopal Iyer 	buf = malloc(sizeof (ring_fields_buf_t));
10390dc2366fSVenugopal Iyer 	if (buf == NULL)
10400dc2366fSVenugopal Iyer 		goto done;
10410dc2366fSVenugopal Iyer 
10420dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
10430dc2366fSVenugopal Iyer 	    linkname);
10440dc2366fSVenugopal Iyer 
10450dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_type, sizeof (buf->r_type), "tx");
10460dc2366fSVenugopal Iyer 
10470dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
10480dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
10490dc2366fSVenugopal Iyer 	} else {
10500dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index),
10510dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
10520dc2366fSVenugopal Iyer 	}
10530dc2366fSVenugopal Iyer 
10540dc2366fSVenugopal Iyer 	map_to_units(buf->r_packets, sizeof (buf->r_packets),
10550dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
10560dc2366fSVenugopal Iyer 
10570dc2366fSVenugopal Iyer 	map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
10580dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
10590dc2366fSVenugopal Iyer 
10600dc2366fSVenugopal Iyer done:
10610dc2366fSVenugopal Iyer 	return (buf);
10620dc2366fSVenugopal Iyer }
10630dc2366fSVenugopal Iyer 
10640dc2366fSVenugopal Iyer void *
print_rx_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)10650dc2366fSVenugopal Iyer print_rx_ring_stats(const char *linkname, void *statentry, char unit,
10660dc2366fSVenugopal Iyer     boolean_t parsable)
10670dc2366fSVenugopal Iyer {
10680dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
10690dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
10700dc2366fSVenugopal Iyer 	rx_ring_fields_buf_t	*buf;
10710dc2366fSVenugopal Iyer 
10720dc2366fSVenugopal Iyer 	buf = malloc(sizeof (rx_ring_fields_buf_t));
10730dc2366fSVenugopal Iyer 	if (buf == NULL)
10740dc2366fSVenugopal Iyer 		goto done;
10750dc2366fSVenugopal Iyer 
10760dc2366fSVenugopal Iyer 	(void) snprintf(buf->rr_linkname, sizeof (buf->rr_linkname), "%s",
10770dc2366fSVenugopal Iyer 	    linkname);
10780dc2366fSVenugopal Iyer 
10790dc2366fSVenugopal Iyer 	(void) snprintf(buf->rr_type, sizeof (buf->rr_type), "rx");
10800dc2366fSVenugopal Iyer 
10810dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
10820dc2366fSVenugopal Iyer 		(void) snprintf(buf->rr_index, sizeof (buf->rr_index), "--");
10830dc2366fSVenugopal Iyer 	} else {
10840dc2366fSVenugopal Iyer 		(void) snprintf(buf->rr_index, sizeof (buf->rr_index),
10850dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
10860dc2366fSVenugopal Iyer 	}
10870dc2366fSVenugopal Iyer 
10880dc2366fSVenugopal Iyer 	map_to_units(buf->rr_ipackets, sizeof (buf->rr_ipackets),
10890dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
10900dc2366fSVenugopal Iyer 
10910dc2366fSVenugopal Iyer 	map_to_units(buf->rr_rbytes, sizeof (buf->rr_rbytes),
10920dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
10930dc2366fSVenugopal Iyer 
10940dc2366fSVenugopal Iyer done:
10950dc2366fSVenugopal Iyer 	return (buf);
10960dc2366fSVenugopal Iyer }
10970dc2366fSVenugopal Iyer 
10980dc2366fSVenugopal Iyer void *
print_tx_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)10990dc2366fSVenugopal Iyer print_tx_ring_stats(const char *linkname, void *statentry, char unit,
11000dc2366fSVenugopal Iyer     boolean_t parsable)
11010dc2366fSVenugopal Iyer {
11020dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
11030dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
11040dc2366fSVenugopal Iyer 	tx_ring_fields_buf_t	*buf;
11050dc2366fSVenugopal Iyer 
11060dc2366fSVenugopal Iyer 	buf = malloc(sizeof (tx_ring_fields_buf_t));
11070dc2366fSVenugopal Iyer 	if (buf == NULL)
11080dc2366fSVenugopal Iyer 		goto done;
11090dc2366fSVenugopal Iyer 
11100dc2366fSVenugopal Iyer 	(void) snprintf(buf->tr_linkname, sizeof (buf->tr_linkname), "%s",
11110dc2366fSVenugopal Iyer 	    linkname);
11120dc2366fSVenugopal Iyer 
11130dc2366fSVenugopal Iyer 	(void) snprintf(buf->tr_type, sizeof (buf->tr_type), "tx");
11140dc2366fSVenugopal Iyer 
11150dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
11160dc2366fSVenugopal Iyer 		(void) snprintf(buf->tr_index, sizeof (buf->tr_index), "--");
11170dc2366fSVenugopal Iyer 	} else {
11180dc2366fSVenugopal Iyer 		(void) snprintf(buf->tr_index, sizeof (buf->tr_index),
11190dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
11200dc2366fSVenugopal Iyer 	}
11210dc2366fSVenugopal Iyer 
11220dc2366fSVenugopal Iyer 	map_to_units(buf->tr_opackets, sizeof (buf->tr_opackets),
11230dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
11240dc2366fSVenugopal Iyer 
11250dc2366fSVenugopal Iyer 	map_to_units(buf->tr_obytes, sizeof (buf->tr_obytes),
11260dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
11270dc2366fSVenugopal Iyer 
11280dc2366fSVenugopal Iyer done:
11290dc2366fSVenugopal Iyer 	return (buf);
11300dc2366fSVenugopal Iyer }
11310dc2366fSVenugopal Iyer 
11320dc2366fSVenugopal Iyer void *
print_rx_generic_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)11330dc2366fSVenugopal Iyer print_rx_generic_lane_stats(const char *linkname, void *statentry, char unit,
11340dc2366fSVenugopal Iyer     boolean_t parsable)
11350dc2366fSVenugopal Iyer {
11360dc2366fSVenugopal Iyer 	rx_lane_stat_entry_t	*sentry = statentry;
11370dc2366fSVenugopal Iyer 	rx_lane_stat_t		*link_stats = &sentry->rle_stats;
11380dc2366fSVenugopal Iyer 	lane_fields_buf_t	*buf;
11390dc2366fSVenugopal Iyer 
11400dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_DFNCT)
11410dc2366fSVenugopal Iyer 		return (NULL);
11420dc2366fSVenugopal Iyer 
11430dc2366fSVenugopal Iyer 	buf = malloc(sizeof (lane_fields_buf_t));
11440dc2366fSVenugopal Iyer 	if (buf == NULL)
11450dc2366fSVenugopal Iyer 		goto done;
11460dc2366fSVenugopal Iyer 
11470dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
11480dc2366fSVenugopal Iyer 	    linkname);
11490dc2366fSVenugopal Iyer 
11500dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_type, sizeof (buf->l_type), "rx");
11510dc2366fSVenugopal Iyer 
11520dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_HWLANE)
11530dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
11540dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_SWLANE)
11550dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "sw");
11560dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_LOCAL)
11570dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "local");
11580dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_BCAST)
11590dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "bcast");
11600dc2366fSVenugopal Iyer 	else
11610dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
11620dc2366fSVenugopal Iyer 
11630dc2366fSVenugopal Iyer 	if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
11640dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
11650dc2366fSVenugopal Iyer 	} else {
11660dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index),
11670dc2366fSVenugopal Iyer 		    "%llu", sentry->rle_index);
11680dc2366fSVenugopal Iyer 	}
11690dc2366fSVenugopal Iyer 
11700dc2366fSVenugopal Iyer 	map_to_units(buf->l_packets, sizeof (buf->l_packets),
11710dc2366fSVenugopal Iyer 	    link_stats->rl_ipackets, unit, parsable);
11720dc2366fSVenugopal Iyer 
11730dc2366fSVenugopal Iyer 	map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
11740dc2366fSVenugopal Iyer 	    link_stats->rl_rbytes, unit, parsable);
11750dc2366fSVenugopal Iyer 
11760dc2366fSVenugopal Iyer done:
11770dc2366fSVenugopal Iyer 	return (buf);
11780dc2366fSVenugopal Iyer }
11790dc2366fSVenugopal Iyer 
11800dc2366fSVenugopal Iyer void *
print_tx_generic_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)11810dc2366fSVenugopal Iyer print_tx_generic_lane_stats(const char *linkname, void *statentry, char unit,
11820dc2366fSVenugopal Iyer     boolean_t parsable)
11830dc2366fSVenugopal Iyer {
11840dc2366fSVenugopal Iyer 	tx_lane_stat_entry_t	*sentry = statentry;
11850dc2366fSVenugopal Iyer 	tx_lane_stat_t		*link_stats = &sentry->tle_stats;
11860dc2366fSVenugopal Iyer 	lane_fields_buf_t	*buf;
11870dc2366fSVenugopal Iyer 
11880dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_DFNCT)
11890dc2366fSVenugopal Iyer 		return (NULL);
11900dc2366fSVenugopal Iyer 
11910dc2366fSVenugopal Iyer 	buf = malloc(sizeof (lane_fields_buf_t));
11920dc2366fSVenugopal Iyer 	if (buf == NULL)
11930dc2366fSVenugopal Iyer 		goto done;
11940dc2366fSVenugopal Iyer 
11950dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
11960dc2366fSVenugopal Iyer 	    linkname);
11970dc2366fSVenugopal Iyer 
11980dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_type, sizeof (buf->l_type), "tx");
11990dc2366fSVenugopal Iyer 
12000dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_HWLANE)
12010dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
12020dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_SWLANE)
12030dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "sw");
12040dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_BCAST)
12050dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "bcast");
12060dc2366fSVenugopal Iyer 	else
12070dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
12080dc2366fSVenugopal Iyer 
12090dc2366fSVenugopal Iyer 	if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
12100dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
12110dc2366fSVenugopal Iyer 	} else {
12120dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index),
12130dc2366fSVenugopal Iyer 		    "%llu", sentry->tle_index);
12140dc2366fSVenugopal Iyer 	}
12150dc2366fSVenugopal Iyer 	map_to_units(buf->l_packets, sizeof (buf->l_packets),
12160dc2366fSVenugopal Iyer 	    link_stats->tl_opackets, unit, parsable);
12170dc2366fSVenugopal Iyer 
12180dc2366fSVenugopal Iyer 	map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
12190dc2366fSVenugopal Iyer 	    link_stats->tl_obytes, unit, parsable);
12200dc2366fSVenugopal Iyer 
12210dc2366fSVenugopal Iyer done:
12220dc2366fSVenugopal Iyer 	return (buf);
12230dc2366fSVenugopal Iyer }
12240dc2366fSVenugopal Iyer 
12250dc2366fSVenugopal Iyer void *
print_rx_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)12260dc2366fSVenugopal Iyer print_rx_lane_stats(const char *linkname, void *statentry, char unit,
12270dc2366fSVenugopal Iyer     boolean_t parsable)
12280dc2366fSVenugopal Iyer {
12290dc2366fSVenugopal Iyer 	rx_lane_stat_entry_t	*sentry = statentry;
12300dc2366fSVenugopal Iyer 	rx_lane_stat_t		*link_stats = &sentry->rle_stats;
12310dc2366fSVenugopal Iyer 	rx_lane_fields_buf_t	*buf;
12320dc2366fSVenugopal Iyer 
12330dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_DFNCT)
12340dc2366fSVenugopal Iyer 		return (NULL);
12350dc2366fSVenugopal Iyer 
12360dc2366fSVenugopal Iyer 	buf = malloc(sizeof (rx_lane_fields_buf_t));
12370dc2366fSVenugopal Iyer 	if (buf == NULL)
12380dc2366fSVenugopal Iyer 		goto done;
12390dc2366fSVenugopal Iyer 
12400dc2366fSVenugopal Iyer 	(void) snprintf(buf->rl_linkname, sizeof (buf->rl_linkname), "%s",
12410dc2366fSVenugopal Iyer 	    linkname);
12420dc2366fSVenugopal Iyer 
12430dc2366fSVenugopal Iyer 	(void) snprintf(buf->rl_type, sizeof (buf->rl_type), "rx");
12440dc2366fSVenugopal Iyer 
12450dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_HWLANE)
12460dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "hw");
12470dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_SWLANE)
12480dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "sw");
12490dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_LOCAL)
12500dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "local");
12510dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_BCAST)
12520dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "bcast");
12530dc2366fSVenugopal Iyer 	else
12540dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "--");
12550dc2366fSVenugopal Iyer 
12560dc2366fSVenugopal Iyer 	if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
12570dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_index, sizeof (buf->rl_index), "--");
12580dc2366fSVenugopal Iyer 	} else {
12590dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_index, sizeof (buf->rl_index),
12600dc2366fSVenugopal Iyer 		    "%llu", sentry->rle_index);
12610dc2366fSVenugopal Iyer 	}
12620dc2366fSVenugopal Iyer 
12630dc2366fSVenugopal Iyer 	map_to_units(buf->rl_ipackets, sizeof (buf->rl_ipackets),
12640dc2366fSVenugopal Iyer 	    link_stats->rl_ipackets, unit, parsable);
12650dc2366fSVenugopal Iyer 
12660dc2366fSVenugopal Iyer 	map_to_units(buf->rl_rbytes, sizeof (buf->rl_rbytes),
12670dc2366fSVenugopal Iyer 	    link_stats->rl_rbytes, unit, parsable);
12680dc2366fSVenugopal Iyer 
12690dc2366fSVenugopal Iyer 	map_to_units(buf->rl_intrs, sizeof (buf->rl_intrs),
12700dc2366fSVenugopal Iyer 	    link_stats->rl_intrs, unit, parsable);
12710dc2366fSVenugopal Iyer 
12720dc2366fSVenugopal Iyer 	map_to_units(buf->rl_polls, sizeof (buf->rl_polls),
12730dc2366fSVenugopal Iyer 	    link_stats->rl_polls, unit, parsable);
12740dc2366fSVenugopal Iyer 
12750dc2366fSVenugopal Iyer 	map_to_units(buf->rl_sdrops, sizeof (buf->rl_sdrops),
12760dc2366fSVenugopal Iyer 	    link_stats->rl_sdrops, unit, parsable);
12770dc2366fSVenugopal Iyer 
12780dc2366fSVenugopal Iyer 	map_to_units(buf->rl_chl10, sizeof (buf->rl_chl10),
12790dc2366fSVenugopal Iyer 	    link_stats->rl_chl10, unit, parsable);
12800dc2366fSVenugopal Iyer 
12810dc2366fSVenugopal Iyer 	map_to_units(buf->rl_ch10_50, sizeof (buf->rl_ch10_50),
12820dc2366fSVenugopal Iyer 	    link_stats->rl_ch10_50, unit, parsable);
12830dc2366fSVenugopal Iyer 
12840dc2366fSVenugopal Iyer 	map_to_units(buf->rl_chg50, sizeof (buf->rl_chg50),
12850dc2366fSVenugopal Iyer 	    link_stats->rl_chg50, unit, parsable);
12860dc2366fSVenugopal Iyer 
12870dc2366fSVenugopal Iyer done:
12880dc2366fSVenugopal Iyer 	return (buf);
12890dc2366fSVenugopal Iyer }
12900dc2366fSVenugopal Iyer 
12910dc2366fSVenugopal Iyer void *
print_tx_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)12920dc2366fSVenugopal Iyer print_tx_lane_stats(const char *linkname, void *statentry, char unit,
12930dc2366fSVenugopal Iyer     boolean_t parsable)
12940dc2366fSVenugopal Iyer {
12950dc2366fSVenugopal Iyer 	tx_lane_stat_entry_t	*sentry = statentry;
12960dc2366fSVenugopal Iyer 	tx_lane_stat_t		*link_stats = &sentry->tle_stats;
12970dc2366fSVenugopal Iyer 	tx_lane_fields_buf_t	*buf = NULL;
12980dc2366fSVenugopal Iyer 
12990dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_DFNCT)
13000dc2366fSVenugopal Iyer 		return (NULL);
13010dc2366fSVenugopal Iyer 
13020dc2366fSVenugopal Iyer 	buf = malloc(sizeof (tx_lane_fields_buf_t));
13030dc2366fSVenugopal Iyer 	if (buf == NULL)
13040dc2366fSVenugopal Iyer 		goto done;
13050dc2366fSVenugopal Iyer 
13060dc2366fSVenugopal Iyer 	(void) snprintf(buf->tl_linkname, sizeof (buf->tl_linkname), "%s",
13070dc2366fSVenugopal Iyer 	    linkname);
13080dc2366fSVenugopal Iyer 
13090dc2366fSVenugopal Iyer 	(void) snprintf(buf->tl_type, sizeof (buf->tl_type), "tx");
13100dc2366fSVenugopal Iyer 
13110dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_HWLANE)
13120dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "hw");
13130dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_SWLANE)
13140dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "sw");
13150dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_BCAST)
13160dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "bcast");
13170dc2366fSVenugopal Iyer 	else
13180dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "--");
13190dc2366fSVenugopal Iyer 
13200dc2366fSVenugopal Iyer 	if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
13210dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_index, sizeof (buf->tl_index), "--");
13220dc2366fSVenugopal Iyer 	} else {
13230dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_index, sizeof (buf->tl_index),
13240dc2366fSVenugopal Iyer 		    "%llu", sentry->tle_index);
13250dc2366fSVenugopal Iyer 	}
13260dc2366fSVenugopal Iyer 
13270dc2366fSVenugopal Iyer 	map_to_units(buf->tl_opackets, sizeof (buf->tl_opackets),
13280dc2366fSVenugopal Iyer 	    link_stats->tl_opackets, unit, parsable);
13290dc2366fSVenugopal Iyer 
13300dc2366fSVenugopal Iyer 	map_to_units(buf->tl_obytes, sizeof (buf->tl_obytes),
13310dc2366fSVenugopal Iyer 	    link_stats->tl_obytes, unit, parsable);
13320dc2366fSVenugopal Iyer 
13330dc2366fSVenugopal Iyer 	map_to_units(buf->tl_blockcnt, sizeof (buf->tl_blockcnt),
13340dc2366fSVenugopal Iyer 	    link_stats->tl_blockcnt, unit, parsable);
13350dc2366fSVenugopal Iyer 
13360dc2366fSVenugopal Iyer 	map_to_units(buf->tl_unblockcnt, sizeof (buf->tl_unblockcnt),
13370dc2366fSVenugopal Iyer 	    link_stats->tl_unblockcnt, unit, parsable);
13380dc2366fSVenugopal Iyer 
13390dc2366fSVenugopal Iyer 	map_to_units(buf->tl_sdrops, sizeof (buf->tl_sdrops),
13400dc2366fSVenugopal Iyer 	    link_stats->tl_sdrops, unit, parsable);
13410dc2366fSVenugopal Iyer 
13420dc2366fSVenugopal Iyer done:
13430dc2366fSVenugopal Iyer 	return (buf);
13440dc2366fSVenugopal Iyer }
13450dc2366fSVenugopal Iyer 
13460dc2366fSVenugopal Iyer void *
print_fanout_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)13470dc2366fSVenugopal Iyer print_fanout_stats(const char *linkname, void *statentry, char unit,
13480dc2366fSVenugopal Iyer     boolean_t parsable)
13490dc2366fSVenugopal Iyer {
13500dc2366fSVenugopal Iyer 	fanout_stat_entry_t		*sentry = statentry;
13510dc2366fSVenugopal Iyer 	fanout_stat_t			*link_stats = &sentry->fe_stats;
13520dc2366fSVenugopal Iyer 	rx_fanout_lane_fields_buf_t	*buf;
13530dc2366fSVenugopal Iyer 
13540dc2366fSVenugopal Iyer 	buf = malloc(sizeof (rx_fanout_lane_fields_buf_t));
13550dc2366fSVenugopal Iyer 	if (buf == NULL)
13560dc2366fSVenugopal Iyer 		goto done;
13570dc2366fSVenugopal Iyer 
13580dc2366fSVenugopal Iyer 	(void) snprintf(buf->rfl_linkname, sizeof (buf->rfl_linkname), "%s",
13590dc2366fSVenugopal Iyer 	    linkname);
13600dc2366fSVenugopal Iyer 
13610dc2366fSVenugopal Iyer 	(void) snprintf(buf->rfl_type, sizeof (buf->rfl_type), "rx");
13620dc2366fSVenugopal Iyer 
13630dc2366fSVenugopal Iyer 	if (sentry->fe_id == L_HWLANE)
13640dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "hw");
13650dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_SWLANE)
13660dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "sw");
13670dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_LCLSWLANE)
13680dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "lcl/sw");
13690dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_LOCAL)
13700dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "local");
13710dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_BCAST)
13720dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "bcast");
13730dc2366fSVenugopal Iyer 	else
13740dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "--");
13750dc2366fSVenugopal Iyer 
13760dc2366fSVenugopal Iyer 	if (sentry->fe_index == DLSTAT_INVALID_ENTRY) {
13770dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_index, sizeof (buf->rfl_index), "--");
13780dc2366fSVenugopal Iyer 	} else {
13790dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_index, sizeof (buf->rfl_index),
13800dc2366fSVenugopal Iyer 		    "%llu", sentry->fe_index);
13810dc2366fSVenugopal Iyer 	}
13820dc2366fSVenugopal Iyer 
13830dc2366fSVenugopal Iyer 	if (sentry->fe_foutindex == DLSTAT_INVALID_ENTRY)
13840dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "--");
13850dc2366fSVenugopal Iyer 	else {
13860dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "%llu",
13870dc2366fSVenugopal Iyer 		    sentry->fe_foutindex);
13880dc2366fSVenugopal Iyer 	}
13890dc2366fSVenugopal Iyer 
13900dc2366fSVenugopal Iyer 	map_to_units(buf->rfl_ipackets, sizeof (buf->rfl_ipackets),
13910dc2366fSVenugopal Iyer 	    link_stats->f_ipackets, unit, parsable);
13920dc2366fSVenugopal Iyer 
13930dc2366fSVenugopal Iyer 	map_to_units(buf->rfl_rbytes, sizeof (buf->rfl_rbytes),
13940dc2366fSVenugopal Iyer 	    link_stats->f_rbytes, unit, parsable);
13950dc2366fSVenugopal Iyer 
13960dc2366fSVenugopal Iyer done:
13970dc2366fSVenugopal Iyer 	return (buf);
13980dc2366fSVenugopal Iyer }
13990dc2366fSVenugopal Iyer 
14000dc2366fSVenugopal Iyer void *
print_aggr_port_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)14010dc2366fSVenugopal Iyer print_aggr_port_stats(const char *linkname, void *statentry, char unit,
14020dc2366fSVenugopal Iyer     boolean_t parsable)
14030dc2366fSVenugopal Iyer {
14040dc2366fSVenugopal Iyer 	aggr_port_stat_entry_t	*sentry = statentry;
14050dc2366fSVenugopal Iyer 	aggr_port_stat_t	*link_stats = &sentry->ape_stats;
14060dc2366fSVenugopal Iyer 	aggr_port_fields_buf_t	*buf;
14070dc2366fSVenugopal Iyer 	char			portname[MAXLINKNAMELEN];
14080dc2366fSVenugopal Iyer 
14090dc2366fSVenugopal Iyer 	buf = malloc(sizeof (aggr_port_fields_buf_t));
14100dc2366fSVenugopal Iyer 	if (buf == NULL)
14110dc2366fSVenugopal Iyer 		goto done;
14120dc2366fSVenugopal Iyer 
14130dc2366fSVenugopal Iyer 	(void) snprintf(buf->ap_linkname, sizeof (buf->ap_linkname), "%s",
14140dc2366fSVenugopal Iyer 	    linkname);
14150dc2366fSVenugopal Iyer 
14160dc2366fSVenugopal Iyer 	if (dladm_datalink_id2info(handle, sentry->ape_portlinkid, NULL,
14170dc2366fSVenugopal Iyer 	    NULL, NULL, portname, DLPI_LINKNAME_MAX)
14180dc2366fSVenugopal Iyer 	    != DLADM_STATUS_OK) {
14190dc2366fSVenugopal Iyer 		(void) snprintf(buf->ap_portname,
14200dc2366fSVenugopal Iyer 		    sizeof (buf->ap_portname), "--");
14210dc2366fSVenugopal Iyer 	} else {
14220dc2366fSVenugopal Iyer 		(void) snprintf(buf->ap_portname,
14230dc2366fSVenugopal Iyer 		    sizeof (buf->ap_portname), "%s", portname);
14240dc2366fSVenugopal Iyer 	}
14250dc2366fSVenugopal Iyer 
14260dc2366fSVenugopal Iyer 	map_to_units(buf->ap_ipackets, sizeof (buf->ap_ipackets),
14270dc2366fSVenugopal Iyer 	    link_stats->ap_ipackets, unit, parsable);
14280dc2366fSVenugopal Iyer 
14290dc2366fSVenugopal Iyer 	map_to_units(buf->ap_rbytes, sizeof (buf->ap_rbytes),
14300dc2366fSVenugopal Iyer 	    link_stats->ap_rbytes, unit, parsable);
14310dc2366fSVenugopal Iyer 
14320dc2366fSVenugopal Iyer 	map_to_units(buf->ap_opackets, sizeof (buf->ap_opackets),
14330dc2366fSVenugopal Iyer 	    link_stats->ap_opackets, unit, parsable);
14340dc2366fSVenugopal Iyer 
14350dc2366fSVenugopal Iyer 	map_to_units(buf->ap_obytes, sizeof (buf->ap_obytes),
14360dc2366fSVenugopal Iyer 	    link_stats->ap_obytes, unit, parsable);
14370dc2366fSVenugopal Iyer 
14380dc2366fSVenugopal Iyer done:
14390dc2366fSVenugopal Iyer 	return (buf);
14400dc2366fSVenugopal Iyer }
14410dc2366fSVenugopal Iyer 
14420dc2366fSVenugopal Iyer dladm_stat_chain_t *
query_link_stats(dladm_handle_t dh,datalink_id_t linkid,void * arg,dladm_stat_type_t stattype)14430dc2366fSVenugopal Iyer query_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg,
14440dc2366fSVenugopal Iyer     dladm_stat_type_t stattype)
14450dc2366fSVenugopal Iyer {
14460dc2366fSVenugopal Iyer 	link_chain_t		*link_node;
14470dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*curr_stat;
14480dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*prev_stat = NULL;
14490dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*diff_stat = NULL;
14500dc2366fSVenugopal Iyer 
14510dc2366fSVenugopal Iyer 	/*  Get prev iteration stat for this link */
14520dc2366fSVenugopal Iyer 	link_node = get_link_prev_stat(linkid, arg);
14530dc2366fSVenugopal Iyer 	if (link_node == NULL)
14540dc2366fSVenugopal Iyer 		goto done;
14550dc2366fSVenugopal Iyer 
14560dc2366fSVenugopal Iyer 	link_node->lc_visited = B_TRUE;
14570dc2366fSVenugopal Iyer 	prev_stat = link_node->lc_statchain[stattype];
14580dc2366fSVenugopal Iyer 
14590dc2366fSVenugopal Iyer 	/* Query library for current stats */
14600dc2366fSVenugopal Iyer 	curr_stat = dladm_link_stat_query(dh, linkid, stattype);
14610dc2366fSVenugopal Iyer 	if (curr_stat == NULL)
14620dc2366fSVenugopal Iyer 		goto done;
14630dc2366fSVenugopal Iyer 
14640dc2366fSVenugopal Iyer 	/* current stats - prev iteration stats */
14650dc2366fSVenugopal Iyer 	diff_stat = dladm_link_stat_diffchain(curr_stat, prev_stat, stattype);
14660dc2366fSVenugopal Iyer 
14670dc2366fSVenugopal Iyer 	/* Free prev stats */
14680dc2366fSVenugopal Iyer 	dladm_link_stat_free(prev_stat);
14690dc2366fSVenugopal Iyer 
14700dc2366fSVenugopal Iyer 	/* Prev <- curr stats */
14710dc2366fSVenugopal Iyer 	link_node->lc_statchain[stattype] = curr_stat;
14720dc2366fSVenugopal Iyer 
14730dc2366fSVenugopal Iyer done:
14740dc2366fSVenugopal Iyer 	return (diff_stat);
14750dc2366fSVenugopal Iyer }
14760dc2366fSVenugopal Iyer 
14770dc2366fSVenugopal Iyer void
walk_dlstat_stats(show_state_t * state,const char * linkname,dladm_stat_type_t stattype,dladm_stat_chain_t * diff_stat)14780dc2366fSVenugopal Iyer walk_dlstat_stats(show_state_t *state, const char *linkname,
14790dc2366fSVenugopal Iyer     dladm_stat_type_t stattype, dladm_stat_chain_t *diff_stat)
14800dc2366fSVenugopal Iyer {
14810dc2366fSVenugopal Iyer 	dladm_stat_chain_t  *curr;
14820dc2366fSVenugopal Iyer 
14830dc2366fSVenugopal Iyer 	/* Unpack invidual stat entry and call library consumer's callback */
14840dc2366fSVenugopal Iyer 	for (curr = diff_stat; curr != NULL; curr = curr->dc_next) {
14850dc2366fSVenugopal Iyer 		void	*fields_buf;
14860dc2366fSVenugopal Iyer 
14870dc2366fSVenugopal Iyer 		/* Format the raw numbers for printing */
14880dc2366fSVenugopal Iyer 		fields_buf = state->ls_stats2str[stattype](linkname,
14890dc2366fSVenugopal Iyer 		    curr->dc_statentry, state->ls_unit, state->ls_parsable);
14900dc2366fSVenugopal Iyer 		/* Print the stats */
14910dc2366fSVenugopal Iyer 		if (fields_buf != NULL)
14920dc2366fSVenugopal Iyer 			ofmt_print(state->ls_ofmt, fields_buf);
14930dc2366fSVenugopal Iyer 		free(fields_buf);
14940dc2366fSVenugopal Iyer 	}
14950dc2366fSVenugopal Iyer }
14960dc2366fSVenugopal Iyer 
14970dc2366fSVenugopal Iyer static int
show_queried_stats(dladm_handle_t dh,datalink_id_t linkid,void * arg)14980dc2366fSVenugopal Iyer show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
14990dc2366fSVenugopal Iyer {
15000dc2366fSVenugopal Iyer 	show_state_t		*state = arg;
1501*3d349c31SPeter Tribble 	int			i;
15020dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*diff_stat;
15030dc2366fSVenugopal Iyer 	char			linkname[DLPI_LINKNAME_MAX];
15040dc2366fSVenugopal Iyer 
15050dc2366fSVenugopal Iyer 	if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
15060dc2366fSVenugopal Iyer 	    DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
15070dc2366fSVenugopal Iyer 		goto done;
15080dc2366fSVenugopal Iyer 	}
15090dc2366fSVenugopal Iyer 
15100dc2366fSVenugopal Iyer 	for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
15110dc2366fSVenugopal Iyer 		if (state->ls_stattype[i]) {
15120dc2366fSVenugopal Iyer 			/*
15130dc2366fSVenugopal Iyer 			 * Query library for stats
15140dc2366fSVenugopal Iyer 			 * Stats are returned as chain of raw numbers
15150dc2366fSVenugopal Iyer 			 */
15160dc2366fSVenugopal Iyer 			diff_stat = query_link_stats(handle, linkid, arg, i);
15170dc2366fSVenugopal Iyer 			walk_dlstat_stats(state, linkname, i, diff_stat);
15180dc2366fSVenugopal Iyer 			dladm_link_stat_free(diff_stat);
15190dc2366fSVenugopal Iyer 		}
15200dc2366fSVenugopal Iyer 	}
15210dc2366fSVenugopal Iyer done:
15220dc2366fSVenugopal Iyer 	return (DLADM_WALK_CONTINUE);
15230dc2366fSVenugopal Iyer }
15240dc2366fSVenugopal Iyer 
15250dc2366fSVenugopal Iyer void
show_link_stats(datalink_id_t linkid,show_state_t state,uint32_t interval)15260dc2366fSVenugopal Iyer show_link_stats(datalink_id_t linkid, show_state_t state, uint32_t interval)
15270dc2366fSVenugopal Iyer {
15280dc2366fSVenugopal Iyer 	for (;;) {
15290dc2366fSVenugopal Iyer 		if (linkid == DATALINK_ALL_LINKID) {
15300dc2366fSVenugopal Iyer 			(void) dladm_walk_datalink_id(show_queried_stats,
15310dc2366fSVenugopal Iyer 			    handle, &state, DATALINK_CLASS_ALL,
15320dc2366fSVenugopal Iyer 			    DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
15330dc2366fSVenugopal Iyer 		} else {
15340dc2366fSVenugopal Iyer 			(void) show_queried_stats(handle, linkid, &state);
15350dc2366fSVenugopal Iyer 		}
15360dc2366fSVenugopal Iyer 
15370dc2366fSVenugopal Iyer 		if (interval == 0)
15380dc2366fSVenugopal Iyer 			break;
15390dc2366fSVenugopal Iyer 
15400dc2366fSVenugopal Iyer 		cleanup_removed_links(&state);
15410dc2366fSVenugopal Iyer 		(void) sleep(interval);
15420dc2366fSVenugopal Iyer 	}
15430dc2366fSVenugopal Iyer }
15440dc2366fSVenugopal Iyer 
15450dc2366fSVenugopal Iyer void
print_all_stats(dladm_handle_t dh,datalink_id_t linkid,dladm_stat_chain_t * stat_chain)15460dc2366fSVenugopal Iyer print_all_stats(dladm_handle_t dh, datalink_id_t linkid,
15470dc2366fSVenugopal Iyer     dladm_stat_chain_t *stat_chain)
15480dc2366fSVenugopal Iyer {
15490dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*curr;
15500dc2366fSVenugopal Iyer 	name_value_stat_entry_t	*stat_entry;
15510dc2366fSVenugopal Iyer 	name_value_stat_t	*curr_stat;
15520dc2366fSVenugopal Iyer 	boolean_t		stat_printed = B_FALSE;
15530dc2366fSVenugopal Iyer 	char			linkname[MAXLINKNAMELEN];
15540dc2366fSVenugopal Iyer 	char			prev_linkname[MAXLINKNAMELEN];
15550dc2366fSVenugopal Iyer 
15560dc2366fSVenugopal Iyer 	if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
15570dc2366fSVenugopal Iyer 	    DLPI_LINKNAME_MAX) != DLADM_STATUS_OK)
15580dc2366fSVenugopal Iyer 		return;
15590dc2366fSVenugopal Iyer 
15600dc2366fSVenugopal Iyer 	for (curr = stat_chain; curr != NULL; curr = curr->dc_next) {
15610dc2366fSVenugopal Iyer 		stat_entry = curr->dc_statentry;
15620dc2366fSVenugopal Iyer 		/*
15630dc2366fSVenugopal Iyer 		 * Print header
15640dc2366fSVenugopal Iyer 		 * If link name is already printed in previous iteration,
15650dc2366fSVenugopal Iyer 		 * don't print again
15660dc2366fSVenugopal Iyer 		 */
15670dc2366fSVenugopal Iyer 		if (strcmp(prev_linkname, linkname) != 0)
15680dc2366fSVenugopal Iyer 			printf("%s \n", linkname);
15690dc2366fSVenugopal Iyer 		printf("  %s \n", stat_entry->nve_header);
15700dc2366fSVenugopal Iyer 
15710dc2366fSVenugopal Iyer 		/* Print stat fields */
15720dc2366fSVenugopal Iyer 		for (curr_stat = stat_entry->nve_stats; curr_stat != NULL;
15730dc2366fSVenugopal Iyer 		    curr_stat = curr_stat->nv_nextstat) {
15740dc2366fSVenugopal Iyer 			printf("\t%15s", curr_stat->nv_statname);
15750dc2366fSVenugopal Iyer 			printf("\t\t%15llu\n", curr_stat->nv_statval);
15760dc2366fSVenugopal Iyer 		}
15770dc2366fSVenugopal Iyer 
15780dc2366fSVenugopal Iyer 		strncpy(prev_linkname, linkname, MAXLINKNAMELEN);
15790dc2366fSVenugopal Iyer 		stat_printed = B_TRUE;
15800dc2366fSVenugopal Iyer 	}
15810dc2366fSVenugopal Iyer 	if (stat_printed)
15820dc2366fSVenugopal Iyer 		printf("---------------------------------------------------\n");
15830dc2366fSVenugopal Iyer }
15840dc2366fSVenugopal Iyer 
15850dc2366fSVenugopal Iyer static int
dump_queried_stats(dladm_handle_t dh,datalink_id_t linkid,void * arg)15860dc2366fSVenugopal Iyer dump_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
15870dc2366fSVenugopal Iyer {
15880dc2366fSVenugopal Iyer 	boolean_t		*stattype = arg;
15890dc2366fSVenugopal Iyer 	int			i;
15900dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*stat_chain;
15910dc2366fSVenugopal Iyer 
15920dc2366fSVenugopal Iyer 	for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
15930dc2366fSVenugopal Iyer 		if (stattype[i]) {
15940dc2366fSVenugopal Iyer 			stat_chain = dladm_link_stat_query_all(dh, linkid, i);
15950dc2366fSVenugopal Iyer 			print_all_stats(dh, linkid, stat_chain);
15960dc2366fSVenugopal Iyer 			dladm_link_stat_query_all_free(stat_chain);
15970dc2366fSVenugopal Iyer 		}
15980dc2366fSVenugopal Iyer 	}
15990dc2366fSVenugopal Iyer done:
16000dc2366fSVenugopal Iyer 	return (DLADM_WALK_CONTINUE);
16010dc2366fSVenugopal Iyer }
16020dc2366fSVenugopal Iyer 
16030dc2366fSVenugopal Iyer void
dump_all_link_stats(datalink_id_t linkid,boolean_t * stattype)16040dc2366fSVenugopal Iyer dump_all_link_stats(datalink_id_t linkid, boolean_t *stattype)
16050dc2366fSVenugopal Iyer {
16060dc2366fSVenugopal Iyer 	if (linkid == DATALINK_ALL_LINKID) {
16070dc2366fSVenugopal Iyer 		(void) dladm_walk_datalink_id(dump_queried_stats,
16080dc2366fSVenugopal Iyer 		    handle, stattype, DATALINK_CLASS_ALL,
16090dc2366fSVenugopal Iyer 		    DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
16100dc2366fSVenugopal Iyer 	} else {
16110dc2366fSVenugopal Iyer 		(void) dump_queried_stats(handle, linkid, stattype);
16120dc2366fSVenugopal Iyer 	}
16130dc2366fSVenugopal Iyer }
16140dc2366fSVenugopal Iyer 
16150dc2366fSVenugopal Iyer static void
do_show(int argc,char * argv[],const char * use)16160dc2366fSVenugopal Iyer do_show(int argc, char *argv[], const char *use)
16170dc2366fSVenugopal Iyer {
16180dc2366fSVenugopal Iyer 	int			option;
16190dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
16200dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
16210dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
16220dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
16230dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
16240dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
16250dc2366fSVenugopal Iyer 	boolean_t		a_arg = B_FALSE;
16260dc2366fSVenugopal Iyer 	boolean_t		A_arg = B_FALSE;
16270dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
16280dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
16290dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
16300dc2366fSVenugopal Iyer 	char			unit = '\0';
16310dc2366fSVenugopal Iyer 	show_state_t		state;
16320dc2366fSVenugopal Iyer 	dladm_status_t		status;
16330dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
16340dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
16350dc2366fSVenugopal Iyer 
16360dc2366fSVenugopal Iyer 	char			*total_stat_fields =
16370dc2366fSVenugopal Iyer 	    "link,ipkts,rbytes,opkts,obytes";
16380dc2366fSVenugopal Iyer 	char			*rx_total_stat_fields =
16390dc2366fSVenugopal Iyer 	    "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
16400dc2366fSVenugopal Iyer 	char			*tx_total_stat_fields =
16410dc2366fSVenugopal Iyer 	    "link,opkts,obytes,blkcnt,ublkcnt";
16420dc2366fSVenugopal Iyer 
16430dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
16440dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
16450dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
1646*3d349c31SPeter Tribble 	ofmt_field_t		*oftemplate;
16470dc2366fSVenugopal Iyer 
16480dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
16490dc2366fSVenugopal Iyer 	opterr = 0;
16500dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":rtaApi:o:u:",
16510dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
16520dc2366fSVenugopal Iyer 		switch (option) {
16530dc2366fSVenugopal Iyer 		case 'r':
16540dc2366fSVenugopal Iyer 			if (r_arg)
16550dc2366fSVenugopal Iyer 				die_optdup(option);
16560dc2366fSVenugopal Iyer 
16570dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
16580dc2366fSVenugopal Iyer 			break;
16590dc2366fSVenugopal Iyer 		case 't':
16600dc2366fSVenugopal Iyer 			if (t_arg)
16610dc2366fSVenugopal Iyer 				die_optdup(option);
16620dc2366fSVenugopal Iyer 
16630dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
16640dc2366fSVenugopal Iyer 			break;
16650dc2366fSVenugopal Iyer 		case 'a':
16660dc2366fSVenugopal Iyer 			if (a_arg)
16670dc2366fSVenugopal Iyer 				die_optdup(option);
16680dc2366fSVenugopal Iyer 
16690dc2366fSVenugopal Iyer 			a_arg = B_TRUE;
16700dc2366fSVenugopal Iyer 			break;
16710dc2366fSVenugopal Iyer 		case 'A':
16720dc2366fSVenugopal Iyer 			if (A_arg)
16730dc2366fSVenugopal Iyer 				die_optdup(option);
16740dc2366fSVenugopal Iyer 
16750dc2366fSVenugopal Iyer 			A_arg = B_TRUE;
16760dc2366fSVenugopal Iyer 			break;
16770dc2366fSVenugopal Iyer 		case 'i':
16780dc2366fSVenugopal Iyer 			if (i_arg)
16790dc2366fSVenugopal Iyer 				die_optdup(option);
16800dc2366fSVenugopal Iyer 
16810dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
16820dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
16830dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
16840dc2366fSVenugopal Iyer 			break;
16850dc2366fSVenugopal Iyer 		case 'p':
16860dc2366fSVenugopal Iyer 			if (p_arg)
16870dc2366fSVenugopal Iyer 				die_optdup(option);
16880dc2366fSVenugopal Iyer 
16890dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
16900dc2366fSVenugopal Iyer 			break;
16910dc2366fSVenugopal Iyer 		case 'o':
16920dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
16930dc2366fSVenugopal Iyer 			o_fields_str = optarg;
16940dc2366fSVenugopal Iyer 			break;
16950dc2366fSVenugopal Iyer 		case 'u':
16960dc2366fSVenugopal Iyer 			if (u_arg)
16970dc2366fSVenugopal Iyer 				die_optdup(option);
16980dc2366fSVenugopal Iyer 
16990dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
17000dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
17010dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
17020dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
17030dc2366fSVenugopal Iyer 			break;
17040dc2366fSVenugopal Iyer 		default:
17050dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
17060dc2366fSVenugopal Iyer 			break;
17070dc2366fSVenugopal Iyer 		}
17080dc2366fSVenugopal Iyer 	}
17090dc2366fSVenugopal Iyer 
17100dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
17110dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
17120dc2366fSVenugopal Iyer 
17130dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
17140dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
17150dc2366fSVenugopal Iyer 
17160dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
17170dc2366fSVenugopal Iyer 		die("-p requires -o");
17180dc2366fSVenugopal Iyer 
17190dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
17200dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
17210dc2366fSVenugopal Iyer 
17220dc2366fSVenugopal Iyer 	if (a_arg && A_arg)
17230dc2366fSVenugopal Iyer 		die("the options -a and -A are not compatible");
17240dc2366fSVenugopal Iyer 
17250dc2366fSVenugopal Iyer 	if (a_arg &&
17260dc2366fSVenugopal Iyer 	    (p_arg || o_arg || u_arg || i_arg)) {
17270dc2366fSVenugopal Iyer 		die("the option -a is not compatible with "
17280dc2366fSVenugopal Iyer 		    "-p, -o, -u, -i");
17290dc2366fSVenugopal Iyer 	}
17300dc2366fSVenugopal Iyer 
17310dc2366fSVenugopal Iyer 	if (A_arg &&
17320dc2366fSVenugopal Iyer 	    (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg)) {
17330dc2366fSVenugopal Iyer 		die("the option -A is not compatible with "
17340dc2366fSVenugopal Iyer 		    "-r, -t, -p, -o, -u, -i");
17350dc2366fSVenugopal Iyer 	}
17360dc2366fSVenugopal Iyer 
17370dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
17380dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
17390dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
17400dc2366fSVenugopal Iyer 			die("link name too long");
17410dc2366fSVenugopal Iyer 
17420dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
17430dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
17440dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
17450dc2366fSVenugopal Iyer 		}
17460dc2366fSVenugopal Iyer 	} else if (optind != argc) {
17470dc2366fSVenugopal Iyer 		if (argc != 0)
17480dc2366fSVenugopal Iyer 			usage();
17490dc2366fSVenugopal Iyer 	}
17500dc2366fSVenugopal Iyer 
17510dc2366fSVenugopal Iyer 	if (a_arg) {
17520dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
17530dc2366fSVenugopal Iyer 
17540dc2366fSVenugopal Iyer 		bzero(&stattype, sizeof (stattype));
17550dc2366fSVenugopal Iyer 		if (r_arg) {
17560dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_LANE_TOTAL] = B_TRUE;
17570dc2366fSVenugopal Iyer 		} else if (t_arg) {
17580dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_LANE_TOTAL] = B_TRUE;
17590dc2366fSVenugopal Iyer 		} else {		/* Display both Rx and Tx lanes */
17600dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TOTAL] = B_TRUE;
17610dc2366fSVenugopal Iyer 		}
17620dc2366fSVenugopal Iyer 
17630dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
17640dc2366fSVenugopal Iyer 		return;
17650dc2366fSVenugopal Iyer 	}
17660dc2366fSVenugopal Iyer 
17670dc2366fSVenugopal Iyer 	if (A_arg) {
17680dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
17690dc2366fSVenugopal Iyer 		int		i;
17700dc2366fSVenugopal Iyer 
17710dc2366fSVenugopal Iyer 		for (i = 0; i < DLADM_STAT_NUM_STATS; i++)
17720dc2366fSVenugopal Iyer 			stattype[i] = B_TRUE;
17730dc2366fSVenugopal Iyer 
17740dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
17750dc2366fSVenugopal Iyer 		return;
17760dc2366fSVenugopal Iyer 	}
17770dc2366fSVenugopal Iyer 
17780dc2366fSVenugopal Iyer 	state.ls_unit = unit;
17790dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
17800dc2366fSVenugopal Iyer 
17810dc2366fSVenugopal Iyer 	if (state.ls_parsable)
17820dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
17830dc2366fSVenugopal Iyer 
17840dc2366fSVenugopal Iyer 	if (r_arg) {
17850dc2366fSVenugopal Iyer 		fields_str = rx_total_stat_fields;
17860dc2366fSVenugopal Iyer 		oftemplate = rx_lane_s_fields;
17870dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_LANE_TOTAL] = B_TRUE;
17880dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_LANE_TOTAL] =
17890dc2366fSVenugopal Iyer 		    print_rx_lane_stats;
17900dc2366fSVenugopal Iyer 	} else if (t_arg) {
17910dc2366fSVenugopal Iyer 		fields_str = tx_total_stat_fields;
17920dc2366fSVenugopal Iyer 		oftemplate = tx_lane_s_fields;
17930dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_LANE_TOTAL] = B_TRUE;
17940dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_LANE_TOTAL] =
17950dc2366fSVenugopal Iyer 		    print_tx_lane_stats;
17960dc2366fSVenugopal Iyer 	} else {		/* Display both Rx and Tx lanes total */
17970dc2366fSVenugopal Iyer 		fields_str = total_stat_fields;
17980dc2366fSVenugopal Iyer 		oftemplate = total_s_fields;
17990dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TOTAL] = B_TRUE;
18000dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TOTAL] = print_total_stats;
18010dc2366fSVenugopal Iyer 	}
18020dc2366fSVenugopal Iyer 
18030dc2366fSVenugopal Iyer 	if (o_arg) {
18040dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
18050dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
18060dc2366fSVenugopal Iyer 	}
18070dc2366fSVenugopal Iyer 
18080dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
1809b2f26520SBryan Cantrill 	ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
18100dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
18110dc2366fSVenugopal Iyer 
18120dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
18130dc2366fSVenugopal Iyer 
18140dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
18150dc2366fSVenugopal Iyer }
18160dc2366fSVenugopal Iyer 
18170dc2366fSVenugopal Iyer static void
do_show_phys(int argc,char * argv[],const char * use)18180dc2366fSVenugopal Iyer do_show_phys(int argc, char *argv[], const char *use)
18190dc2366fSVenugopal Iyer {
18200dc2366fSVenugopal Iyer 	int			option;
18210dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
18220dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
18230dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
18240dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
18250dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
18260dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
18270dc2366fSVenugopal Iyer 	boolean_t		a_arg = B_FALSE;
18280dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
18290dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
18300dc2366fSVenugopal Iyer 	char			linkname[MAXLINKNAMELEN];
18310dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
18320dc2366fSVenugopal Iyer 	char			unit = '\0';
18330dc2366fSVenugopal Iyer 	show_state_t		state;
18340dc2366fSVenugopal Iyer 	dladm_status_t		status;
18350dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
18360dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
18370dc2366fSVenugopal Iyer 	char			*ring_stat_fields =
18380dc2366fSVenugopal Iyer 	    "link,type,index,pkts,bytes";
18390dc2366fSVenugopal Iyer 	char			*rx_ring_stat_fields =
18400dc2366fSVenugopal Iyer 	    "link,type,index,ipkts,rbytes";
18410dc2366fSVenugopal Iyer 	char			*tx_ring_stat_fields =
18420dc2366fSVenugopal Iyer 	    "link,type,index,opkts,obytes";
18430dc2366fSVenugopal Iyer 
18440dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
18450dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
18460dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
1847*3d349c31SPeter Tribble 	ofmt_field_t		*oftemplate;
18480dc2366fSVenugopal Iyer 
18490dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
18500dc2366fSVenugopal Iyer 	opterr = 0;
18510dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":rtapi:o:u:",
18520dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
18530dc2366fSVenugopal Iyer 		switch (option) {
18540dc2366fSVenugopal Iyer 		case 'r':
18550dc2366fSVenugopal Iyer 			if (r_arg)
18560dc2366fSVenugopal Iyer 				die_optdup(option);
18570dc2366fSVenugopal Iyer 
18580dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
18590dc2366fSVenugopal Iyer 			break;
18600dc2366fSVenugopal Iyer 		case 't':
18610dc2366fSVenugopal Iyer 			if (t_arg)
18620dc2366fSVenugopal Iyer 				die_optdup(option);
18630dc2366fSVenugopal Iyer 
18640dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
18650dc2366fSVenugopal Iyer 			break;
18660dc2366fSVenugopal Iyer 		case 'a':
18670dc2366fSVenugopal Iyer 			if (a_arg)
18680dc2366fSVenugopal Iyer 				die_optdup(option);
18690dc2366fSVenugopal Iyer 
18700dc2366fSVenugopal Iyer 			a_arg = B_TRUE;
18710dc2366fSVenugopal Iyer 			break;
18720dc2366fSVenugopal Iyer 		case 'i':
18730dc2366fSVenugopal Iyer 			if (i_arg)
18740dc2366fSVenugopal Iyer 				die_optdup(option);
18750dc2366fSVenugopal Iyer 
18760dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
18770dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
18780dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
18790dc2366fSVenugopal Iyer 			break;
18800dc2366fSVenugopal Iyer 		case 'p':
18810dc2366fSVenugopal Iyer 			if (p_arg)
18820dc2366fSVenugopal Iyer 				die_optdup(option);
18830dc2366fSVenugopal Iyer 
18840dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
18850dc2366fSVenugopal Iyer 			break;
18860dc2366fSVenugopal Iyer 		case 'o':
18870dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
18880dc2366fSVenugopal Iyer 			o_fields_str = optarg;
18890dc2366fSVenugopal Iyer 			break;
18900dc2366fSVenugopal Iyer 		case 'u':
18910dc2366fSVenugopal Iyer 			if (u_arg)
18920dc2366fSVenugopal Iyer 				die_optdup(option);
18930dc2366fSVenugopal Iyer 
18940dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
18950dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
18960dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
18970dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
18980dc2366fSVenugopal Iyer 			break;
18990dc2366fSVenugopal Iyer 		default:
19000dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
19010dc2366fSVenugopal Iyer 			break;
19020dc2366fSVenugopal Iyer 		}
19030dc2366fSVenugopal Iyer 	}
19040dc2366fSVenugopal Iyer 
19050dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
19060dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
19070dc2366fSVenugopal Iyer 
19080dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
19090dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
19100dc2366fSVenugopal Iyer 
19110dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
19120dc2366fSVenugopal Iyer 		die("-p requires -o");
19130dc2366fSVenugopal Iyer 
19140dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
19150dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
19160dc2366fSVenugopal Iyer 
19170dc2366fSVenugopal Iyer 	if (a_arg &&
19180dc2366fSVenugopal Iyer 	    (p_arg || o_arg || u_arg || i_arg)) {
19190dc2366fSVenugopal Iyer 		die("the option -a is not compatible with "
19200dc2366fSVenugopal Iyer 		    "-p, -o, -u, -i");
19210dc2366fSVenugopal Iyer 	}
19220dc2366fSVenugopal Iyer 
19230dc2366fSVenugopal Iyer 
19240dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
19250dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
19260dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
19270dc2366fSVenugopal Iyer 			die("link name too long");
19280dc2366fSVenugopal Iyer 
19290dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
19300dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
19310dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
19320dc2366fSVenugopal Iyer 		}
19330dc2366fSVenugopal Iyer 	} else if (optind != argc) {
19340dc2366fSVenugopal Iyer 		usage();
19350dc2366fSVenugopal Iyer 	}
19360dc2366fSVenugopal Iyer 
19370dc2366fSVenugopal Iyer 	if (a_arg) {
19380dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
19390dc2366fSVenugopal Iyer 
19400dc2366fSVenugopal Iyer 		bzero(&stattype, sizeof (stattype));
19410dc2366fSVenugopal Iyer 
19420dc2366fSVenugopal Iyer 		if (r_arg) {
19430dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_RING] = B_TRUE;
19440dc2366fSVenugopal Iyer 		} else if (t_arg) {
19450dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_RING] = B_TRUE;
19460dc2366fSVenugopal Iyer 		} else {		/* Display both Rx and Tx lanes */
19470dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_RING] = B_TRUE;
19480dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_RING] = B_TRUE;
19490dc2366fSVenugopal Iyer 		}
19500dc2366fSVenugopal Iyer 
19510dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
19520dc2366fSVenugopal Iyer 		return;
19530dc2366fSVenugopal Iyer 	}
19540dc2366fSVenugopal Iyer 
19550dc2366fSVenugopal Iyer 	state.ls_unit = unit;
19560dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
19570dc2366fSVenugopal Iyer 
19580dc2366fSVenugopal Iyer 	if (state.ls_parsable)
19590dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
19600dc2366fSVenugopal Iyer 
19610dc2366fSVenugopal Iyer 	if (r_arg) {
19620dc2366fSVenugopal Iyer 		fields_str = rx_ring_stat_fields;
19630dc2366fSVenugopal Iyer 		oftemplate = rx_ring_s_fields;
19640dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_RING] = B_TRUE;
19650dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_RING] = print_rx_ring_stats;
19660dc2366fSVenugopal Iyer 	} else if (t_arg) {
19670dc2366fSVenugopal Iyer 		fields_str = tx_ring_stat_fields;
19680dc2366fSVenugopal Iyer 		oftemplate = tx_ring_s_fields;
19690dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_RING] = B_TRUE;
19700dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_RING] = print_tx_ring_stats;
19710dc2366fSVenugopal Iyer 	} else {		/* Display both Rx and Tx lanes */
19720dc2366fSVenugopal Iyer 		fields_str = ring_stat_fields;
19730dc2366fSVenugopal Iyer 		oftemplate = ring_s_fields;
19740dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_RING] = B_TRUE;
19750dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_RING] = B_TRUE;
19760dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_RING] =
19770dc2366fSVenugopal Iyer 		    print_rx_generic_ring_stats;
19780dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_RING] =
19790dc2366fSVenugopal Iyer 		    print_tx_generic_ring_stats;
19800dc2366fSVenugopal Iyer 	}
19810dc2366fSVenugopal Iyer 
19820dc2366fSVenugopal Iyer 	if (o_arg) {
19830dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
19840dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
19850dc2366fSVenugopal Iyer 	}
19860dc2366fSVenugopal Iyer 
19870dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
1988b2f26520SBryan Cantrill 	ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
19890dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
19900dc2366fSVenugopal Iyer 
19910dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
19920dc2366fSVenugopal Iyer 
19930dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
19940dc2366fSVenugopal Iyer }
19950dc2366fSVenugopal Iyer 
19960dc2366fSVenugopal Iyer static void
do_show_link(int argc,char * argv[],const char * use)19970dc2366fSVenugopal Iyer do_show_link(int argc, char *argv[], const char *use)
19980dc2366fSVenugopal Iyer {
19990dc2366fSVenugopal Iyer 	int			option;
20000dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
20010dc2366fSVenugopal Iyer 	boolean_t		F_arg = B_FALSE;
20020dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
20030dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
20040dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
20050dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
20060dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
20070dc2366fSVenugopal Iyer 	boolean_t		a_arg = B_FALSE;
20080dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
20090dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
20100dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
20110dc2366fSVenugopal Iyer 	char			unit = '\0';
20120dc2366fSVenugopal Iyer 	show_state_t		state;
20130dc2366fSVenugopal Iyer 	dladm_status_t		status;
20140dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
20150dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
20160dc2366fSVenugopal Iyer 
20170dc2366fSVenugopal Iyer 	char			*lane_stat_fields =
20180dc2366fSVenugopal Iyer 	    "link,type,id,index,pkts,bytes";
20190dc2366fSVenugopal Iyer 	char			*rx_lane_stat_fields =
20200dc2366fSVenugopal Iyer 	    "link,type,id,index,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
20210dc2366fSVenugopal Iyer 	char			*tx_lane_stat_fields =
20220dc2366fSVenugopal Iyer 	    "link,type,id,index,opkts,obytes,blkcnt,ublkcnt";
20230dc2366fSVenugopal Iyer 	char			*rx_fanout_stat_fields =
20240dc2366fSVenugopal Iyer 	    "link,id,index,fout,ipkts,rbytes";
20250dc2366fSVenugopal Iyer 
20260dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
20270dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
20280dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
2029*3d349c31SPeter Tribble 	ofmt_field_t		*oftemplate;
20300dc2366fSVenugopal Iyer 
20310dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
20320dc2366fSVenugopal Iyer 	opterr = 0;
20330dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":hrtFapi:o:u:",
20340dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
20350dc2366fSVenugopal Iyer 		switch (option) {
20360dc2366fSVenugopal Iyer 		case 'h':
20370dc2366fSVenugopal Iyer 			if (r_arg || F_arg || t_arg || i_arg || p_arg ||
20380dc2366fSVenugopal Iyer 			    o_arg || u_arg || a_arg) {
20390dc2366fSVenugopal Iyer 				die("the option -h is not compatible with "
20400dc2366fSVenugopal Iyer 				    "-r, -F, -t, -i, -p, -o, -u, -a");
20410dc2366fSVenugopal Iyer 			}
20420dc2366fSVenugopal Iyer 			do_show_history(argc, &argv[0], use);
20430dc2366fSVenugopal Iyer 			return;
20440dc2366fSVenugopal Iyer 		case 'r':
20450dc2366fSVenugopal Iyer 			if (r_arg)
20460dc2366fSVenugopal Iyer 				die_optdup(option);
20470dc2366fSVenugopal Iyer 
20480dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
20490dc2366fSVenugopal Iyer 			break;
20500dc2366fSVenugopal Iyer 		case 'F':
20510dc2366fSVenugopal Iyer 			if (F_arg)
20520dc2366fSVenugopal Iyer 				die_optdup(option);
20530dc2366fSVenugopal Iyer 
20540dc2366fSVenugopal Iyer 			F_arg = B_TRUE;
20550dc2366fSVenugopal Iyer 			break;
20560dc2366fSVenugopal Iyer 		case 't':
20570dc2366fSVenugopal Iyer 			if (t_arg)
20580dc2366fSVenugopal Iyer 				die_optdup(option);
20590dc2366fSVenugopal Iyer 
20600dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
20610dc2366fSVenugopal Iyer 			break;
20620dc2366fSVenugopal Iyer 		case 'a':
20630dc2366fSVenugopal Iyer 			if (a_arg)
20640dc2366fSVenugopal Iyer 				die_optdup(option);
20650dc2366fSVenugopal Iyer 
20660dc2366fSVenugopal Iyer 			a_arg = B_TRUE;
20670dc2366fSVenugopal Iyer 			break;
20680dc2366fSVenugopal Iyer 		case 'i':
20690dc2366fSVenugopal Iyer 			if (i_arg)
20700dc2366fSVenugopal Iyer 				die_optdup(option);
20710dc2366fSVenugopal Iyer 
20720dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
20730dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
20740dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
20750dc2366fSVenugopal Iyer 			break;
20760dc2366fSVenugopal Iyer 		case 'p':
20770dc2366fSVenugopal Iyer 			if (p_arg)
20780dc2366fSVenugopal Iyer 				die_optdup(option);
20790dc2366fSVenugopal Iyer 
20800dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
20810dc2366fSVenugopal Iyer 			break;
20820dc2366fSVenugopal Iyer 		case 'o':
20830dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
20840dc2366fSVenugopal Iyer 			o_fields_str = optarg;
20850dc2366fSVenugopal Iyer 			break;
20860dc2366fSVenugopal Iyer 		case 'u':
20870dc2366fSVenugopal Iyer 			if (u_arg)
20880dc2366fSVenugopal Iyer 				die_optdup(option);
20890dc2366fSVenugopal Iyer 
20900dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
20910dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
20920dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
20930dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
20940dc2366fSVenugopal Iyer 			break;
20950dc2366fSVenugopal Iyer 		default:
20960dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
20970dc2366fSVenugopal Iyer 			break;
20980dc2366fSVenugopal Iyer 		}
20990dc2366fSVenugopal Iyer 	}
21000dc2366fSVenugopal Iyer 
21010dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
21020dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
21030dc2366fSVenugopal Iyer 
21040dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
21050dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
21060dc2366fSVenugopal Iyer 
21070dc2366fSVenugopal Iyer 	if (F_arg && !r_arg)
21080dc2366fSVenugopal Iyer 		die("-F must be used with -r");
21090dc2366fSVenugopal Iyer 
21100dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
21110dc2366fSVenugopal Iyer 		die("-p requires -o");
21120dc2366fSVenugopal Iyer 
21130dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
21140dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
21150dc2366fSVenugopal Iyer 
21160dc2366fSVenugopal Iyer 	if (a_arg &&
21170dc2366fSVenugopal Iyer 	    (p_arg || o_arg || u_arg || i_arg)) {
21180dc2366fSVenugopal Iyer 		die("the option -a is not compatible with "
21190dc2366fSVenugopal Iyer 		    "-p, -o, -u, -i");
21200dc2366fSVenugopal Iyer 	}
21210dc2366fSVenugopal Iyer 
21220dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
21230dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
21240dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
21250dc2366fSVenugopal Iyer 			die("link name too long");
21260dc2366fSVenugopal Iyer 
21270dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
21280dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
21290dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
21300dc2366fSVenugopal Iyer 		}
21310dc2366fSVenugopal Iyer 	} else if (optind != argc) {
21320dc2366fSVenugopal Iyer 		usage();
21330dc2366fSVenugopal Iyer 	}
21340dc2366fSVenugopal Iyer 
21350dc2366fSVenugopal Iyer 	if (a_arg) {
21360dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
21370dc2366fSVenugopal Iyer 
21380dc2366fSVenugopal Iyer 		bzero(&stattype, sizeof (stattype));
21390dc2366fSVenugopal Iyer 
21400dc2366fSVenugopal Iyer 		if (r_arg) {
21410dc2366fSVenugopal Iyer 			if (F_arg) {
21420dc2366fSVenugopal Iyer 				stattype[DLADM_STAT_RX_LANE_FOUT] = B_TRUE;
21430dc2366fSVenugopal Iyer 			} else {
21440dc2366fSVenugopal Iyer 				stattype[DLADM_STAT_RX_LANE] = B_TRUE;
21450dc2366fSVenugopal Iyer 			}
21460dc2366fSVenugopal Iyer 		} else if (t_arg) {
21470dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_LANE] = B_TRUE;
21480dc2366fSVenugopal Iyer 		} else {		/* Display both Rx and Tx lanes */
21490dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_LANE] = B_TRUE;
21500dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_LANE] = B_TRUE;
21510dc2366fSVenugopal Iyer 		}
21520dc2366fSVenugopal Iyer 
21530dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
21540dc2366fSVenugopal Iyer 		return;
21550dc2366fSVenugopal Iyer 	}
21560dc2366fSVenugopal Iyer 
21570dc2366fSVenugopal Iyer 	state.ls_unit = unit;
21580dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
21590dc2366fSVenugopal Iyer 
21600dc2366fSVenugopal Iyer 	if (state.ls_parsable)
21610dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
21620dc2366fSVenugopal Iyer 
21630dc2366fSVenugopal Iyer 	if (r_arg) {
21640dc2366fSVenugopal Iyer 		if (F_arg) {
21650dc2366fSVenugopal Iyer 			fields_str = rx_fanout_stat_fields;
21660dc2366fSVenugopal Iyer 			oftemplate = rx_fanout_lane_s_fields;
21670dc2366fSVenugopal Iyer 			state.ls_stattype[DLADM_STAT_RX_LANE_FOUT] = B_TRUE;
21680dc2366fSVenugopal Iyer 			state.ls_stats2str[DLADM_STAT_RX_LANE_FOUT] =
21690dc2366fSVenugopal Iyer 			    print_fanout_stats;
21700dc2366fSVenugopal Iyer 		} else {
21710dc2366fSVenugopal Iyer 			fields_str = rx_lane_stat_fields;
21720dc2366fSVenugopal Iyer 			oftemplate = rx_lane_s_fields;
21730dc2366fSVenugopal Iyer 			state.ls_stattype[DLADM_STAT_RX_LANE] = B_TRUE;
21740dc2366fSVenugopal Iyer 			state.ls_stats2str[DLADM_STAT_RX_LANE] =
21750dc2366fSVenugopal Iyer 			    print_rx_lane_stats;
21760dc2366fSVenugopal Iyer 		}
21770dc2366fSVenugopal Iyer 	} else if (t_arg) {
21780dc2366fSVenugopal Iyer 		fields_str = tx_lane_stat_fields;
21790dc2366fSVenugopal Iyer 		oftemplate = tx_lane_s_fields;
21800dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_LANE] = B_TRUE;
21810dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_LANE] = print_tx_lane_stats;
21820dc2366fSVenugopal Iyer 	} else {		/* Display both Rx and Tx lanes */
21830dc2366fSVenugopal Iyer 		fields_str = lane_stat_fields;
21840dc2366fSVenugopal Iyer 		oftemplate = lane_s_fields;
21850dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_LANE] = B_TRUE;
21860dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_LANE] = B_TRUE;
21870dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_LANE] =
21880dc2366fSVenugopal Iyer 		    print_rx_generic_lane_stats;
21890dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_LANE] =
21900dc2366fSVenugopal Iyer 		    print_tx_generic_lane_stats;
21910dc2366fSVenugopal Iyer 	}
21920dc2366fSVenugopal Iyer 	if (o_arg) {
21930dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
21940dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
21950dc2366fSVenugopal Iyer 	}
21960dc2366fSVenugopal Iyer 
21970dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
2198b2f26520SBryan Cantrill 	ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
21990dc2366fSVenugopal Iyer 
22000dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
22010dc2366fSVenugopal Iyer 
22020dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
22030dc2366fSVenugopal Iyer 
22040dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
22050dc2366fSVenugopal Iyer }
22060dc2366fSVenugopal Iyer 
22070dc2366fSVenugopal Iyer static void
do_show_aggr(int argc,char * argv[],const char * use)22080dc2366fSVenugopal Iyer do_show_aggr(int argc, char *argv[], const char *use)
22090dc2366fSVenugopal Iyer {
22100dc2366fSVenugopal Iyer 	int			option;
22110dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
22120dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
22130dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
22140dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
22150dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
22160dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
22170dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
22180dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
22190dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
22200dc2366fSVenugopal Iyer 	char			unit = '\0';
22210dc2366fSVenugopal Iyer 	show_state_t		state;
22220dc2366fSVenugopal Iyer 	dladm_status_t		status;
22230dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
22240dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
22250dc2366fSVenugopal Iyer 
22260dc2366fSVenugopal Iyer 	char			*aggr_stat_fields =
22270dc2366fSVenugopal Iyer 	    "link,port,ipkts,rbytes,opkts,obytes";
22280dc2366fSVenugopal Iyer 	char			*rx_aggr_stat_fields = "link,port,ipkts,rbytes";
22290dc2366fSVenugopal Iyer 	char			*tx_aggr_stat_fields = "link,port,opkts,obytes";
22300dc2366fSVenugopal Iyer 
22310dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
22320dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
22330dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
2234*3d349c31SPeter Tribble 	ofmt_field_t		*oftemplate;
22350dc2366fSVenugopal Iyer 
22360dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
22370dc2366fSVenugopal Iyer 	opterr = 0;
22380dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":rtpi:o:u:",
22390dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
22400dc2366fSVenugopal Iyer 		switch (option) {
22410dc2366fSVenugopal Iyer 		case 'r':
22420dc2366fSVenugopal Iyer 			if (r_arg)
22430dc2366fSVenugopal Iyer 				die_optdup(option);
22440dc2366fSVenugopal Iyer 
22450dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
22460dc2366fSVenugopal Iyer 			break;
22470dc2366fSVenugopal Iyer 		case 't':
22480dc2366fSVenugopal Iyer 			if (t_arg)
22490dc2366fSVenugopal Iyer 				die_optdup(option);
22500dc2366fSVenugopal Iyer 
22510dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
22520dc2366fSVenugopal Iyer 			break;
22530dc2366fSVenugopal Iyer 		case 'i':
22540dc2366fSVenugopal Iyer 			if (i_arg)
22550dc2366fSVenugopal Iyer 				die_optdup(option);
22560dc2366fSVenugopal Iyer 
22570dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
22580dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
22590dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
22600dc2366fSVenugopal Iyer 			break;
22610dc2366fSVenugopal Iyer 		case 'p':
22620dc2366fSVenugopal Iyer 			if (p_arg)
22630dc2366fSVenugopal Iyer 				die_optdup(option);
22640dc2366fSVenugopal Iyer 
22650dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
22660dc2366fSVenugopal Iyer 			break;
22670dc2366fSVenugopal Iyer 		case 'o':
22680dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
22690dc2366fSVenugopal Iyer 			o_fields_str = optarg;
22700dc2366fSVenugopal Iyer 			break;
22710dc2366fSVenugopal Iyer 		case 'u':
22720dc2366fSVenugopal Iyer 			if (u_arg)
22730dc2366fSVenugopal Iyer 				die_optdup(option);
22740dc2366fSVenugopal Iyer 
22750dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
22760dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
22770dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
22780dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
22790dc2366fSVenugopal Iyer 			break;
22800dc2366fSVenugopal Iyer 		default:
22810dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
22820dc2366fSVenugopal Iyer 			break;
22830dc2366fSVenugopal Iyer 		}
22840dc2366fSVenugopal Iyer 	}
22850dc2366fSVenugopal Iyer 
22860dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
22870dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
22880dc2366fSVenugopal Iyer 
22890dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
22900dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
22910dc2366fSVenugopal Iyer 
22920dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
22930dc2366fSVenugopal Iyer 		die("-p requires -o");
22940dc2366fSVenugopal Iyer 
22950dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
22960dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
22970dc2366fSVenugopal Iyer 
22980dc2366fSVenugopal Iyer 
22990dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
23000dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
23010dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
23020dc2366fSVenugopal Iyer 			die("link name too long");
23030dc2366fSVenugopal Iyer 
23040dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
23050dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
23060dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
23070dc2366fSVenugopal Iyer 		}
23080dc2366fSVenugopal Iyer 	} else if (optind != argc) {
23090dc2366fSVenugopal Iyer 		usage();
23100dc2366fSVenugopal Iyer 	}
23110dc2366fSVenugopal Iyer 
23120dc2366fSVenugopal Iyer 	state.ls_unit = unit;
23130dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
23140dc2366fSVenugopal Iyer 
23150dc2366fSVenugopal Iyer 	if (state.ls_parsable)
23160dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
23170dc2366fSVenugopal Iyer 
23180dc2366fSVenugopal Iyer 	oftemplate = aggr_port_s_fields;
23190dc2366fSVenugopal Iyer 	state.ls_stattype[DLADM_STAT_AGGR_PORT] = B_TRUE;
23200dc2366fSVenugopal Iyer 	state.ls_stats2str[DLADM_STAT_AGGR_PORT] = print_aggr_port_stats;
23210dc2366fSVenugopal Iyer 
23220dc2366fSVenugopal Iyer 	if (r_arg)
23230dc2366fSVenugopal Iyer 		fields_str = rx_aggr_stat_fields;
23240dc2366fSVenugopal Iyer 	else if (t_arg)
23250dc2366fSVenugopal Iyer 		fields_str = tx_aggr_stat_fields;
23260dc2366fSVenugopal Iyer 	else
23270dc2366fSVenugopal Iyer 		fields_str = aggr_stat_fields;
23280dc2366fSVenugopal Iyer 
23290dc2366fSVenugopal Iyer 	if (o_arg) {
23300dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
23310dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
23320dc2366fSVenugopal Iyer 	}
23330dc2366fSVenugopal Iyer 
23340dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
2335b2f26520SBryan Cantrill 	ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
23360dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
23370dc2366fSVenugopal Iyer 
23380dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
23390dc2366fSVenugopal Iyer 
23400dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
23410dc2366fSVenugopal Iyer }
23420dc2366fSVenugopal Iyer 
23430dc2366fSVenugopal Iyer /* PRINTFLIKE1 */
23440dc2366fSVenugopal Iyer static void
warn(const char * format,...)23450dc2366fSVenugopal Iyer warn(const char *format, ...)
23460dc2366fSVenugopal Iyer {
23470dc2366fSVenugopal Iyer 	va_list alist;
23480dc2366fSVenugopal Iyer 
23490dc2366fSVenugopal Iyer 	format = gettext(format);
23500dc2366fSVenugopal Iyer 	(void) fprintf(stderr, "%s: warning: ", progname);
23510dc2366fSVenugopal Iyer 
23520dc2366fSVenugopal Iyer 	va_start(alist, format);
23530dc2366fSVenugopal Iyer 	(void) vfprintf(stderr, format, alist);
23540dc2366fSVenugopal Iyer 	va_end(alist);
23550dc2366fSVenugopal Iyer 
23560dc2366fSVenugopal Iyer 	(void) putc('\n', stderr);
23570dc2366fSVenugopal Iyer }
23580dc2366fSVenugopal Iyer 
23590dc2366fSVenugopal Iyer /*
23600dc2366fSVenugopal Iyer  * Also closes the dladm handle if it is not NULL.
23610dc2366fSVenugopal Iyer  */
23620dc2366fSVenugopal Iyer /* PRINTFLIKE2 */
23630dc2366fSVenugopal Iyer static void
die_dlerr(dladm_status_t err,const char * format,...)23640dc2366fSVenugopal Iyer die_dlerr(dladm_status_t err, const char *format, ...)
23650dc2366fSVenugopal Iyer {
23660dc2366fSVenugopal Iyer 	va_list alist;
23670dc2366fSVenugopal Iyer 	char	errmsg[DLADM_STRSIZE];
23680dc2366fSVenugopal Iyer 
23690dc2366fSVenugopal Iyer 	format = gettext(format);
23700dc2366fSVenugopal Iyer 	(void) fprintf(stderr, "%s: ", progname);
23710dc2366fSVenugopal Iyer 
23720dc2366fSVenugopal Iyer 	va_start(alist, format);
23730dc2366fSVenugopal Iyer 	(void) vfprintf(stderr, format, alist);
23740dc2366fSVenugopal Iyer 	va_end(alist);
23750dc2366fSVenugopal Iyer 	(void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
23760dc2366fSVenugopal Iyer 
23770dc2366fSVenugopal Iyer 	/* close dladm handle if it was opened */
23780dc2366fSVenugopal Iyer 	if (handle != NULL)
23790dc2366fSVenugopal Iyer 		dladm_close(handle);
23800dc2366fSVenugopal Iyer 
23810dc2366fSVenugopal Iyer 	exit(EXIT_FAILURE);
23820dc2366fSVenugopal Iyer }
23830dc2366fSVenugopal Iyer 
23840dc2366fSVenugopal Iyer /* PRINTFLIKE1 */
23850dc2366fSVenugopal Iyer static void
die(const char * format,...)23860dc2366fSVenugopal Iyer die(const char *format, ...)
23870dc2366fSVenugopal Iyer {
23880dc2366fSVenugopal Iyer 	va_list alist;
23890dc2366fSVenugopal Iyer 
23900dc2366fSVenugopal Iyer 	format = gettext(format);
23910dc2366fSVenugopal Iyer 	(void) fprintf(stderr, "%s: ", progname);
23920dc2366fSVenugopal Iyer 
23930dc2366fSVenugopal Iyer 	va_start(alist, format);
23940dc2366fSVenugopal Iyer 	(void) vfprintf(stderr, format, alist);
23950dc2366fSVenugopal Iyer 	va_end(alist);
23960dc2366fSVenugopal Iyer 
23970dc2366fSVenugopal Iyer 	(void) putc('\n', stderr);
23980dc2366fSVenugopal Iyer 
23990dc2366fSVenugopal Iyer 	/* close dladm handle if it was opened */
24000dc2366fSVenugopal Iyer 	if (handle != NULL)
24010dc2366fSVenugopal Iyer 		dladm_close(handle);
24020dc2366fSVenugopal Iyer 
24030dc2366fSVenugopal Iyer 	exit(EXIT_FAILURE);
24040dc2366fSVenugopal Iyer }
24050dc2366fSVenugopal Iyer 
24060dc2366fSVenugopal Iyer static void
die_optdup(int opt)24070dc2366fSVenugopal Iyer die_optdup(int opt)
24080dc2366fSVenugopal Iyer {
24090dc2366fSVenugopal Iyer 	die("the option -%c cannot be specified more than once", opt);
24100dc2366fSVenugopal Iyer }
24110dc2366fSVenugopal Iyer 
24120dc2366fSVenugopal Iyer static void
die_opterr(int opt,int opterr,const char * usage)24130dc2366fSVenugopal Iyer die_opterr(int opt, int opterr, const char *usage)
24140dc2366fSVenugopal Iyer {
24150dc2366fSVenugopal Iyer 	switch (opterr) {
24160dc2366fSVenugopal Iyer 	case ':':
24170dc2366fSVenugopal Iyer 		die("option '-%c' requires a value\nusage: %s", opt,
24180dc2366fSVenugopal Iyer 		    gettext(usage));
24190dc2366fSVenugopal Iyer 		break;
24200dc2366fSVenugopal Iyer 	case '?':
24210dc2366fSVenugopal Iyer 	default:
24220dc2366fSVenugopal Iyer 		die("unrecognized option '-%c'\nusage: %s", opt,
24230dc2366fSVenugopal Iyer 		    gettext(usage));
24240dc2366fSVenugopal Iyer 		break;
24250dc2366fSVenugopal Iyer 	}
24260dc2366fSVenugopal Iyer }
24270dc2366fSVenugopal Iyer 
24280dc2366fSVenugopal Iyer /*
24290dc2366fSVenugopal Iyer  * default output callback function that, when invoked,
24300dc2366fSVenugopal Iyer  * prints string which is offset by ofmt_arg->ofmt_id within buf.
24310dc2366fSVenugopal Iyer  */
24320dc2366fSVenugopal Iyer static boolean_t
print_default_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)24330dc2366fSVenugopal Iyer print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
24340dc2366fSVenugopal Iyer {
24350dc2366fSVenugopal Iyer 	char *value;
24360dc2366fSVenugopal Iyer 
24370dc2366fSVenugopal Iyer 	value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
24380dc2366fSVenugopal Iyer 	(void) strlcpy(buf, value, bufsize);
24390dc2366fSVenugopal Iyer 	return (B_TRUE);
24400dc2366fSVenugopal Iyer }
2441