xref: /titanic_44/usr/src/cmd/dlstat/dlstat.c (revision 0dc2366f7b9f9f36e10909b1e95edbf2a261c2ac)
1*0dc2366fSVenugopal Iyer /*
2*0dc2366fSVenugopal Iyer  * CDDL HEADER START
3*0dc2366fSVenugopal Iyer  *
4*0dc2366fSVenugopal Iyer  * The contents of this file are subject to the terms of the
5*0dc2366fSVenugopal Iyer  * Common Development and Distribution License (the "License").
6*0dc2366fSVenugopal Iyer  * You may not use this file except in compliance with the License.
7*0dc2366fSVenugopal Iyer  *
8*0dc2366fSVenugopal Iyer  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*0dc2366fSVenugopal Iyer  * or http://www.opensolaris.org/os/licensing.
10*0dc2366fSVenugopal Iyer  * See the License for the specific language governing permissions
11*0dc2366fSVenugopal Iyer  * and limitations under the License.
12*0dc2366fSVenugopal Iyer  *
13*0dc2366fSVenugopal Iyer  * When distributing Covered Code, include this CDDL HEADER in each
14*0dc2366fSVenugopal Iyer  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*0dc2366fSVenugopal Iyer  * If applicable, add the following below this CDDL HEADER, with the
16*0dc2366fSVenugopal Iyer  * fields enclosed by brackets "[]" replaced with your own identifying
17*0dc2366fSVenugopal Iyer  * information: Portions Copyright [yyyy] [name of copyright owner]
18*0dc2366fSVenugopal Iyer  *
19*0dc2366fSVenugopal Iyer  * CDDL HEADER END
20*0dc2366fSVenugopal Iyer  */
21*0dc2366fSVenugopal Iyer /*
22*0dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*0dc2366fSVenugopal Iyer  * Use is subject to license terms.
24*0dc2366fSVenugopal Iyer  */
25*0dc2366fSVenugopal Iyer 
26*0dc2366fSVenugopal Iyer #include <stdio.h>
27*0dc2366fSVenugopal Iyer #include <ctype.h>
28*0dc2366fSVenugopal Iyer #include <locale.h>
29*0dc2366fSVenugopal Iyer #include <signal.h>
30*0dc2366fSVenugopal Iyer #include <stdarg.h>
31*0dc2366fSVenugopal Iyer #include <stdlib.h>
32*0dc2366fSVenugopal Iyer #include <fcntl.h>
33*0dc2366fSVenugopal Iyer #include <string.h>
34*0dc2366fSVenugopal Iyer #include <stropts.h>
35*0dc2366fSVenugopal Iyer #include <sys/stat.h>
36*0dc2366fSVenugopal Iyer #include <errno.h>
37*0dc2366fSVenugopal Iyer #include <strings.h>
38*0dc2366fSVenugopal Iyer #include <getopt.h>
39*0dc2366fSVenugopal Iyer #include <unistd.h>
40*0dc2366fSVenugopal Iyer #include <priv.h>
41*0dc2366fSVenugopal Iyer #include <termios.h>
42*0dc2366fSVenugopal Iyer #include <pwd.h>
43*0dc2366fSVenugopal Iyer #include <auth_attr.h>
44*0dc2366fSVenugopal Iyer #include <auth_list.h>
45*0dc2366fSVenugopal Iyer #include <libintl.h>
46*0dc2366fSVenugopal Iyer #include <libdevinfo.h>
47*0dc2366fSVenugopal Iyer #include <libdlpi.h>
48*0dc2366fSVenugopal Iyer #include <libdladm.h>
49*0dc2366fSVenugopal Iyer #include <libdllink.h>
50*0dc2366fSVenugopal Iyer #include <libdlstat.h>
51*0dc2366fSVenugopal Iyer #include <libdlaggr.h>
52*0dc2366fSVenugopal Iyer #include <libinetutil.h>
53*0dc2366fSVenugopal Iyer #include <bsm/adt.h>
54*0dc2366fSVenugopal Iyer #include <bsm/adt_event.h>
55*0dc2366fSVenugopal Iyer #include <stddef.h>
56*0dc2366fSVenugopal Iyer #include <ofmt.h>
57*0dc2366fSVenugopal Iyer 
58*0dc2366fSVenugopal Iyer typedef struct link_chain_s {
59*0dc2366fSVenugopal Iyer 	datalink_id_t		lc_linkid;
60*0dc2366fSVenugopal Iyer 	boolean_t		lc_visited;
61*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*lc_statchain[DLADM_STAT_NUM_STATS];
62*0dc2366fSVenugopal Iyer 	struct link_chain_s	*lc_next;
63*0dc2366fSVenugopal Iyer } link_chain_t;
64*0dc2366fSVenugopal Iyer 
65*0dc2366fSVenugopal Iyer typedef void *	(*stats2str_t)(const char *, void *,
66*0dc2366fSVenugopal Iyer 		    char, boolean_t);
67*0dc2366fSVenugopal Iyer 
68*0dc2366fSVenugopal Iyer typedef struct show_state {
69*0dc2366fSVenugopal Iyer 	link_chain_t	*ls_linkchain;
70*0dc2366fSVenugopal Iyer 	boolean_t	ls_stattype[DLADM_STAT_NUM_STATS];
71*0dc2366fSVenugopal Iyer 	stats2str_t	ls_stats2str[DLADM_STAT_NUM_STATS];
72*0dc2366fSVenugopal Iyer 	ofmt_handle_t	ls_ofmt;
73*0dc2366fSVenugopal Iyer 	char		ls_unit;
74*0dc2366fSVenugopal Iyer 	boolean_t	ls_parsable;
75*0dc2366fSVenugopal Iyer } show_state_t;
76*0dc2366fSVenugopal Iyer 
77*0dc2366fSVenugopal Iyer typedef struct show_history_state_s {
78*0dc2366fSVenugopal Iyer 	boolean_t	hs_plot;
79*0dc2366fSVenugopal Iyer 	boolean_t	hs_parsable;
80*0dc2366fSVenugopal Iyer 	boolean_t	hs_printheader;
81*0dc2366fSVenugopal Iyer 	boolean_t	hs_first;
82*0dc2366fSVenugopal Iyer 	boolean_t	hs_showall;
83*0dc2366fSVenugopal Iyer 	ofmt_handle_t	hs_ofmt;
84*0dc2366fSVenugopal Iyer } show_history_state_t;
85*0dc2366fSVenugopal Iyer 
86*0dc2366fSVenugopal Iyer /*
87*0dc2366fSVenugopal Iyer  * callback functions for printing output and error diagnostics.
88*0dc2366fSVenugopal Iyer  */
89*0dc2366fSVenugopal Iyer static ofmt_cb_t print_default_cb;
90*0dc2366fSVenugopal Iyer 
91*0dc2366fSVenugopal Iyer static void dlstat_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
92*0dc2366fSVenugopal Iyer 
93*0dc2366fSVenugopal Iyer typedef void cmdfunc_t(int, char **, const char *);
94*0dc2366fSVenugopal Iyer 
95*0dc2366fSVenugopal Iyer static cmdfunc_t do_show, do_show_history, do_show_phys, do_show_link;
96*0dc2366fSVenugopal Iyer static cmdfunc_t do_show_aggr;
97*0dc2366fSVenugopal Iyer 
98*0dc2366fSVenugopal Iyer static void	die(const char *, ...);
99*0dc2366fSVenugopal Iyer static void	die_optdup(int);
100*0dc2366fSVenugopal Iyer static void	die_opterr(int, int, const char *);
101*0dc2366fSVenugopal Iyer static void	die_dlerr(dladm_status_t, const char *, ...);
102*0dc2366fSVenugopal Iyer static void	warn(const char *, ...);
103*0dc2366fSVenugopal Iyer 
104*0dc2366fSVenugopal Iyer typedef struct	cmd {
105*0dc2366fSVenugopal Iyer 	char		*c_name;
106*0dc2366fSVenugopal Iyer 	cmdfunc_t	*c_fn;
107*0dc2366fSVenugopal Iyer 	const char	*c_usage;
108*0dc2366fSVenugopal Iyer } cmd_t;
109*0dc2366fSVenugopal Iyer 
110*0dc2366fSVenugopal Iyer static cmd_t	cmds[] = {
111*0dc2366fSVenugopal Iyer 	{ "",		do_show,
112*0dc2366fSVenugopal Iyer 	    "dlstat [-r | -t] [-i <interval>] [link]\n"
113*0dc2366fSVenugopal Iyer 	    "       dlstat [-a | -A] [-i <interval>] [-p] [ -o field[,...]]\n"
114*0dc2366fSVenugopal Iyer 	    "              [-u R|K|M|G|T|P] [link]"},
115*0dc2366fSVenugopal Iyer 	{ "show-phys", do_show_phys,
116*0dc2366fSVenugopal Iyer 	    "dlstat show-phys [-r | -t] [-i interval] [-a]\n"
117*0dc2366fSVenugopal Iyer 	    "                 [-p] [ -o field[,...]] [-u R|K|M|G|T|P] "
118*0dc2366fSVenugopal Iyer 	    "[link]"},
119*0dc2366fSVenugopal Iyer 	{ "show-link", do_show_link,
120*0dc2366fSVenugopal Iyer 	    "dlstat show-link [-r [-F] | -t] [-i interval] [-a]\n"
121*0dc2366fSVenugopal Iyer 	    "                 [-p] [ -o field[,...]] [-u R|K|M|G|T|P] "
122*0dc2366fSVenugopal Iyer 	    "[link]\n"
123*0dc2366fSVenugopal Iyer 	    "       dlstat show-link -h [-a] [-d] [-F <format>]\n"
124*0dc2366fSVenugopal Iyer 	    "                 [-s <DD/MM/YYYY,HH:MM:SS>] "
125*0dc2366fSVenugopal Iyer 	    "[-e <DD/MM/YYYY,HH:MM:SS>]\n"
126*0dc2366fSVenugopal Iyer 	    "                 -f <logfile> [<link>]" },
127*0dc2366fSVenugopal Iyer 	{ "show-aggr", do_show_aggr,
128*0dc2366fSVenugopal Iyer 	    "dlstat show-aggr [-r | -t] [-i interval] [-p]\n"
129*0dc2366fSVenugopal Iyer 	    "                 [ -o field[,...]] [-u R|K|M|G|T|P] "
130*0dc2366fSVenugopal Iyer 	    " [link]" }
131*0dc2366fSVenugopal Iyer };
132*0dc2366fSVenugopal Iyer 
133*0dc2366fSVenugopal Iyer #define	MAXSTATLEN 15
134*0dc2366fSVenugopal Iyer 
135*0dc2366fSVenugopal Iyer /*
136*0dc2366fSVenugopal Iyer  * dlstat : total stat fields
137*0dc2366fSVenugopal Iyer  */
138*0dc2366fSVenugopal Iyer typedef struct total_fields_buf_s {
139*0dc2366fSVenugopal Iyer 	char t_linkname[MAXLINKNAMELEN];
140*0dc2366fSVenugopal Iyer 	char t_ipackets[MAXSTATLEN];
141*0dc2366fSVenugopal Iyer 	char t_rbytes[MAXSTATLEN];
142*0dc2366fSVenugopal Iyer 	char t_opackets[MAXSTATLEN];
143*0dc2366fSVenugopal Iyer 	char t_obytes[MAXSTATLEN];
144*0dc2366fSVenugopal Iyer } total_fields_buf_t;
145*0dc2366fSVenugopal Iyer 
146*0dc2366fSVenugopal Iyer static ofmt_field_t total_s_fields[] = {
147*0dc2366fSVenugopal Iyer { "LINK",	15,
148*0dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_linkname),	print_default_cb},
149*0dc2366fSVenugopal Iyer { "IPKTS",	8,
150*0dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_ipackets),	print_default_cb},
151*0dc2366fSVenugopal Iyer { "RBYTES",	8,
152*0dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_rbytes),	print_default_cb},
153*0dc2366fSVenugopal Iyer { "OPKTS",	8,
154*0dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_opackets),	print_default_cb},
155*0dc2366fSVenugopal Iyer { "OBYTES",	8,
156*0dc2366fSVenugopal Iyer     offsetof(total_fields_buf_t, t_obytes),	print_default_cb},
157*0dc2366fSVenugopal Iyer { NULL,		0,	0,		NULL}};
158*0dc2366fSVenugopal Iyer 
159*0dc2366fSVenugopal Iyer /*
160*0dc2366fSVenugopal Iyer  * dlstat show-phys: both Rx and Tx stat fields
161*0dc2366fSVenugopal Iyer  */
162*0dc2366fSVenugopal Iyer typedef struct ring_fields_buf_s {
163*0dc2366fSVenugopal Iyer 	char r_linkname[MAXLINKNAMELEN];
164*0dc2366fSVenugopal Iyer 	char r_type[MAXSTATLEN];
165*0dc2366fSVenugopal Iyer 	char r_id[MAXSTATLEN];
166*0dc2366fSVenugopal Iyer 	char r_index[MAXSTATLEN];
167*0dc2366fSVenugopal Iyer 	char r_packets[MAXSTATLEN];
168*0dc2366fSVenugopal Iyer 	char r_bytes[MAXSTATLEN];
169*0dc2366fSVenugopal Iyer } ring_fields_buf_t;
170*0dc2366fSVenugopal Iyer 
171*0dc2366fSVenugopal Iyer static ofmt_field_t ring_s_fields[] = {
172*0dc2366fSVenugopal Iyer { "LINK",	15,
173*0dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_linkname),	print_default_cb},
174*0dc2366fSVenugopal Iyer { "TYPE",	5,
175*0dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_type),	print_default_cb},
176*0dc2366fSVenugopal Iyer { "ID",		7,
177*0dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_id),		print_default_cb},
178*0dc2366fSVenugopal Iyer { "INDEX",	6,
179*0dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_index),	print_default_cb},
180*0dc2366fSVenugopal Iyer { "PKTS",	8,
181*0dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_packets),	print_default_cb},
182*0dc2366fSVenugopal Iyer { "BYTES",	8,
183*0dc2366fSVenugopal Iyer     offsetof(ring_fields_buf_t, r_bytes),	print_default_cb},
184*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
185*0dc2366fSVenugopal Iyer 
186*0dc2366fSVenugopal Iyer /*
187*0dc2366fSVenugopal Iyer  * dlstat show-phys -r: Rx Ring stat fields
188*0dc2366fSVenugopal Iyer  */
189*0dc2366fSVenugopal Iyer typedef struct rx_ring_fields_buf_s {
190*0dc2366fSVenugopal Iyer 	char rr_linkname[MAXLINKNAMELEN];
191*0dc2366fSVenugopal Iyer 	char rr_type[MAXSTATLEN];
192*0dc2366fSVenugopal Iyer 	char rr_id[MAXSTATLEN];
193*0dc2366fSVenugopal Iyer 	char rr_index[MAXSTATLEN];
194*0dc2366fSVenugopal Iyer 	char rr_ipackets[MAXSTATLEN];
195*0dc2366fSVenugopal Iyer 	char rr_rbytes[MAXSTATLEN];
196*0dc2366fSVenugopal Iyer } rx_ring_fields_buf_t;
197*0dc2366fSVenugopal Iyer 
198*0dc2366fSVenugopal Iyer static ofmt_field_t rx_ring_s_fields[] = {
199*0dc2366fSVenugopal Iyer { "LINK",	15,
200*0dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_linkname),	print_default_cb},
201*0dc2366fSVenugopal Iyer { "TYPE",	5,
202*0dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_type),		print_default_cb},
203*0dc2366fSVenugopal Iyer { "ID",		7,
204*0dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_id),		print_default_cb},
205*0dc2366fSVenugopal Iyer { "INDEX",	6,
206*0dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_index),		print_default_cb},
207*0dc2366fSVenugopal Iyer { "IPKTS",	8,
208*0dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_ipackets),	print_default_cb},
209*0dc2366fSVenugopal Iyer { "RBYTES",	8,
210*0dc2366fSVenugopal Iyer     offsetof(rx_ring_fields_buf_t, rr_rbytes),		print_default_cb},
211*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
212*0dc2366fSVenugopal Iyer 
213*0dc2366fSVenugopal Iyer /*
214*0dc2366fSVenugopal Iyer  * dlstat show-phys -t: Tx Ring stat fields
215*0dc2366fSVenugopal Iyer  */
216*0dc2366fSVenugopal Iyer typedef struct tx_ring_fields_buf_s {
217*0dc2366fSVenugopal Iyer 	char tr_linkname[MAXLINKNAMELEN];
218*0dc2366fSVenugopal Iyer 	char tr_type[MAXSTATLEN];
219*0dc2366fSVenugopal Iyer 	char tr_id[MAXSTATLEN];
220*0dc2366fSVenugopal Iyer 	char tr_index[MAXSTATLEN];
221*0dc2366fSVenugopal Iyer 	char tr_opackets[MAXSTATLEN];
222*0dc2366fSVenugopal Iyer 	char tr_obytes[MAXSTATLEN];
223*0dc2366fSVenugopal Iyer } tx_ring_fields_buf_t;
224*0dc2366fSVenugopal Iyer 
225*0dc2366fSVenugopal Iyer static ofmt_field_t tx_ring_s_fields[] = {
226*0dc2366fSVenugopal Iyer { "LINK",	15,
227*0dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_linkname),	print_default_cb},
228*0dc2366fSVenugopal Iyer { "TYPE",	5,
229*0dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_type),		print_default_cb},
230*0dc2366fSVenugopal Iyer { "ID",		7,
231*0dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_id),		print_default_cb},
232*0dc2366fSVenugopal Iyer { "INDEX",	6,
233*0dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_index),		print_default_cb},
234*0dc2366fSVenugopal Iyer { "OPKTS",	8,
235*0dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_opackets),	print_default_cb},
236*0dc2366fSVenugopal Iyer { "OBYTES",	8,
237*0dc2366fSVenugopal Iyer     offsetof(tx_ring_fields_buf_t, tr_obytes),		print_default_cb},
238*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
239*0dc2366fSVenugopal Iyer 
240*0dc2366fSVenugopal Iyer /*
241*0dc2366fSVenugopal Iyer  * dlstat show-link: both Rx and Tx lane fields
242*0dc2366fSVenugopal Iyer  */
243*0dc2366fSVenugopal Iyer typedef struct lane_fields_buf_s {
244*0dc2366fSVenugopal Iyer 	char l_linkname[MAXLINKNAMELEN];
245*0dc2366fSVenugopal Iyer 	char l_type[MAXSTATLEN];
246*0dc2366fSVenugopal Iyer 	char l_id[MAXSTATLEN];
247*0dc2366fSVenugopal Iyer 	char l_index[MAXSTATLEN];
248*0dc2366fSVenugopal Iyer 	char l_packets[MAXSTATLEN];
249*0dc2366fSVenugopal Iyer 	char l_bytes[MAXSTATLEN];
250*0dc2366fSVenugopal Iyer } lane_fields_buf_t;
251*0dc2366fSVenugopal Iyer 
252*0dc2366fSVenugopal Iyer static ofmt_field_t lane_s_fields[] = {
253*0dc2366fSVenugopal Iyer { "LINK",	15,
254*0dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_linkname),	print_default_cb},
255*0dc2366fSVenugopal Iyer { "TYPE",	5,
256*0dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_type),	print_default_cb},
257*0dc2366fSVenugopal Iyer { "ID",		7,
258*0dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_id),		print_default_cb},
259*0dc2366fSVenugopal Iyer { "INDEX",	6,
260*0dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_index),	print_default_cb},
261*0dc2366fSVenugopal Iyer { "PKTS",	8,
262*0dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_packets),	print_default_cb},
263*0dc2366fSVenugopal Iyer { "BYTES",	8,
264*0dc2366fSVenugopal Iyer     offsetof(lane_fields_buf_t, l_bytes),	print_default_cb},
265*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
266*0dc2366fSVenugopal Iyer 
267*0dc2366fSVenugopal Iyer /*
268*0dc2366fSVenugopal Iyer  * dlstat show-link -r, dlstat -r: Rx Lane stat fields
269*0dc2366fSVenugopal Iyer  */
270*0dc2366fSVenugopal Iyer typedef struct rx_lane_fields_buf_s {
271*0dc2366fSVenugopal Iyer 	char rl_linkname[MAXLINKNAMELEN];
272*0dc2366fSVenugopal Iyer 	char rl_type[MAXSTATLEN];
273*0dc2366fSVenugopal Iyer 	char rl_id[MAXSTATLEN];
274*0dc2366fSVenugopal Iyer 	char rl_index[MAXSTATLEN];
275*0dc2366fSVenugopal Iyer 	char rl_ipackets[MAXSTATLEN];
276*0dc2366fSVenugopal Iyer 	char rl_rbytes[MAXSTATLEN];
277*0dc2366fSVenugopal Iyer 	char rl_intrs[MAXSTATLEN];
278*0dc2366fSVenugopal Iyer 	char rl_polls[MAXSTATLEN];
279*0dc2366fSVenugopal Iyer 	char rl_sdrops[MAXSTATLEN];
280*0dc2366fSVenugopal Iyer 	char rl_chl10[MAXSTATLEN];
281*0dc2366fSVenugopal Iyer 	char rl_ch10_50[MAXSTATLEN];
282*0dc2366fSVenugopal Iyer 	char rl_chg50[MAXSTATLEN];
283*0dc2366fSVenugopal Iyer } rx_lane_fields_buf_t;
284*0dc2366fSVenugopal Iyer 
285*0dc2366fSVenugopal Iyer static ofmt_field_t rx_lane_s_fields[] = {
286*0dc2366fSVenugopal Iyer { "LINK",	10,
287*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_linkname),	print_default_cb},
288*0dc2366fSVenugopal Iyer { "TYPE",	5,
289*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_type),		print_default_cb},
290*0dc2366fSVenugopal Iyer { "ID",		7,
291*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_id),		print_default_cb},
292*0dc2366fSVenugopal Iyer { "INDEX",	6,
293*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_index),		print_default_cb},
294*0dc2366fSVenugopal Iyer { "IPKTS",	8,
295*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_ipackets),	print_default_cb},
296*0dc2366fSVenugopal Iyer { "RBYTES",	8,
297*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_rbytes),		print_default_cb},
298*0dc2366fSVenugopal Iyer { "INTRS",	8,
299*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_intrs),		print_default_cb},
300*0dc2366fSVenugopal Iyer { "POLLS",	8,
301*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_polls),		print_default_cb},
302*0dc2366fSVenugopal Iyer { "SDROPS",	8,
303*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_sdrops),		print_default_cb},
304*0dc2366fSVenugopal Iyer { "CH<10",	8,
305*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_chl10),		print_default_cb},
306*0dc2366fSVenugopal Iyer { "CH10-50",	8,
307*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_ch10_50),		print_default_cb},
308*0dc2366fSVenugopal Iyer { "CH>50",	8,
309*0dc2366fSVenugopal Iyer     offsetof(rx_lane_fields_buf_t, rl_chg50),		print_default_cb},
310*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
311*0dc2366fSVenugopal Iyer 
312*0dc2366fSVenugopal Iyer /*
313*0dc2366fSVenugopal Iyer  * dlstat show-link -r -F: Rx fanout stat fields
314*0dc2366fSVenugopal Iyer  */
315*0dc2366fSVenugopal Iyer typedef struct rx_fanout_lane_fields_buf_s {
316*0dc2366fSVenugopal Iyer 	char rfl_linkname[MAXLINKNAMELEN];
317*0dc2366fSVenugopal Iyer 	char rfl_type[MAXSTATLEN];
318*0dc2366fSVenugopal Iyer 	char rfl_id[MAXSTATLEN];
319*0dc2366fSVenugopal Iyer 	char rfl_index[MAXSTATLEN];
320*0dc2366fSVenugopal Iyer 	char rfl_fout[MAXSTATLEN];
321*0dc2366fSVenugopal Iyer 	char rfl_ipackets[MAXSTATLEN];
322*0dc2366fSVenugopal Iyer 	char rfl_rbytes[MAXSTATLEN];
323*0dc2366fSVenugopal Iyer } rx_fanout_lane_fields_buf_t;
324*0dc2366fSVenugopal Iyer 
325*0dc2366fSVenugopal Iyer static ofmt_field_t rx_fanout_lane_s_fields[] = {
326*0dc2366fSVenugopal Iyer { "LINK",	15,
327*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_linkname), print_default_cb},
328*0dc2366fSVenugopal Iyer { "TYPE",	5,
329*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_type),	print_default_cb},
330*0dc2366fSVenugopal Iyer { "ID",		7,
331*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_id),	print_default_cb},
332*0dc2366fSVenugopal Iyer { "INDEX",	6,
333*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_index),	print_default_cb},
334*0dc2366fSVenugopal Iyer { "FOUT",	6,
335*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_fout),	print_default_cb},
336*0dc2366fSVenugopal Iyer { "IPKTS",	8,
337*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_ipackets), print_default_cb},
338*0dc2366fSVenugopal Iyer { "RBYTES",	8,
339*0dc2366fSVenugopal Iyer     offsetof(rx_fanout_lane_fields_buf_t, rfl_rbytes),	print_default_cb},
340*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
341*0dc2366fSVenugopal Iyer 
342*0dc2366fSVenugopal Iyer /*
343*0dc2366fSVenugopal Iyer  * dlstat show-link -t: Tx Lane stat fields
344*0dc2366fSVenugopal Iyer  */
345*0dc2366fSVenugopal Iyer typedef struct tx_lane_fields_buf_s {
346*0dc2366fSVenugopal Iyer 	char tl_linkname[MAXLINKNAMELEN];
347*0dc2366fSVenugopal Iyer 	char tl_index[MAXSTATLEN];
348*0dc2366fSVenugopal Iyer 	char tl_type[MAXSTATLEN];
349*0dc2366fSVenugopal Iyer 	char tl_id[MAXSTATLEN];
350*0dc2366fSVenugopal Iyer 	char tl_opackets[MAXSTATLEN];
351*0dc2366fSVenugopal Iyer 	char tl_obytes[MAXSTATLEN];
352*0dc2366fSVenugopal Iyer 	char tl_blockcnt[MAXSTATLEN];
353*0dc2366fSVenugopal Iyer 	char tl_unblockcnt[MAXSTATLEN];
354*0dc2366fSVenugopal Iyer 	char tl_sdrops[MAXSTATLEN];
355*0dc2366fSVenugopal Iyer } tx_lane_fields_buf_t;
356*0dc2366fSVenugopal Iyer 
357*0dc2366fSVenugopal Iyer static ofmt_field_t tx_lane_s_fields[] = {
358*0dc2366fSVenugopal Iyer { "LINK",	15,
359*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_linkname),	print_default_cb},
360*0dc2366fSVenugopal Iyer { "TYPE",	5,
361*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_type),		print_default_cb},
362*0dc2366fSVenugopal Iyer { "ID",		7,
363*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_id),		print_default_cb},
364*0dc2366fSVenugopal Iyer { "INDEX",	6,
365*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_index),		print_default_cb},
366*0dc2366fSVenugopal Iyer { "OPKTS",	8,
367*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_opackets),	print_default_cb},
368*0dc2366fSVenugopal Iyer { "OBYTES",	8,
369*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_obytes),		print_default_cb},
370*0dc2366fSVenugopal Iyer { "BLKCNT",	8,
371*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_blockcnt),	print_default_cb},
372*0dc2366fSVenugopal Iyer { "UBLKCNT",	8,
373*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_unblockcnt),	print_default_cb},
374*0dc2366fSVenugopal Iyer { "SDROPS",	8,
375*0dc2366fSVenugopal Iyer     offsetof(tx_lane_fields_buf_t, tl_sdrops),		print_default_cb},
376*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
377*0dc2366fSVenugopal Iyer 
378*0dc2366fSVenugopal Iyer /*
379*0dc2366fSVenugopal Iyer  * dlstat show-aggr: aggr port stat fields
380*0dc2366fSVenugopal Iyer  */
381*0dc2366fSVenugopal Iyer typedef struct aggr_port_fields_buf_s {
382*0dc2366fSVenugopal Iyer 	char ap_linkname[MAXLINKNAMELEN];
383*0dc2366fSVenugopal Iyer 	char ap_portname[MAXLINKNAMELEN];
384*0dc2366fSVenugopal Iyer 	char ap_ipackets[MAXSTATLEN];
385*0dc2366fSVenugopal Iyer 	char ap_rbytes[MAXSTATLEN];
386*0dc2366fSVenugopal Iyer 	char ap_opackets[MAXSTATLEN];
387*0dc2366fSVenugopal Iyer 	char ap_obytes[MAXSTATLEN];
388*0dc2366fSVenugopal Iyer } aggr_port_fields_buf_t;
389*0dc2366fSVenugopal Iyer 
390*0dc2366fSVenugopal Iyer static ofmt_field_t aggr_port_s_fields[] = {
391*0dc2366fSVenugopal Iyer { "LINK",	15,
392*0dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_linkname),	print_default_cb},
393*0dc2366fSVenugopal Iyer { "PORT",	15,
394*0dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_portname),	print_default_cb},
395*0dc2366fSVenugopal Iyer { "IPKTS",	8,
396*0dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_ipackets),	print_default_cb},
397*0dc2366fSVenugopal Iyer { "RBYTES",	8,
398*0dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_rbytes),	print_default_cb},
399*0dc2366fSVenugopal Iyer { "OPKTS",	8,
400*0dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_opackets),	print_default_cb},
401*0dc2366fSVenugopal Iyer { "OBYTES",	8,
402*0dc2366fSVenugopal Iyer     offsetof(aggr_port_fields_buf_t, ap_obytes),	print_default_cb},
403*0dc2366fSVenugopal Iyer { NULL,		0,		0,		NULL}};
404*0dc2366fSVenugopal Iyer 
405*0dc2366fSVenugopal Iyer /*
406*0dc2366fSVenugopal Iyer  * structures for 'dlstat show-link -h'
407*0dc2366fSVenugopal Iyer  */
408*0dc2366fSVenugopal Iyer typedef struct  history_fields_buf_s {
409*0dc2366fSVenugopal Iyer 	char	h_link[12];
410*0dc2366fSVenugopal Iyer 	char	h_duration[10];
411*0dc2366fSVenugopal Iyer 	char	h_ipackets[9];
412*0dc2366fSVenugopal Iyer 	char	h_rbytes[10];
413*0dc2366fSVenugopal Iyer 	char	h_opackets[9];
414*0dc2366fSVenugopal Iyer 	char	h_obytes[10];
415*0dc2366fSVenugopal Iyer 	char	h_bandwidth[14];
416*0dc2366fSVenugopal Iyer } history_fields_buf_t;
417*0dc2366fSVenugopal Iyer 
418*0dc2366fSVenugopal Iyer static ofmt_field_t history_fields[] = {
419*0dc2366fSVenugopal Iyer { "LINK",	13,
420*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_link), print_default_cb},
421*0dc2366fSVenugopal Iyer { "DURATION",	11,
422*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_duration), print_default_cb},
423*0dc2366fSVenugopal Iyer { "IPKTS",	10,
424*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_ipackets), print_default_cb},
425*0dc2366fSVenugopal Iyer { "RBYTES",	11,
426*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_rbytes), print_default_cb},
427*0dc2366fSVenugopal Iyer { "OPKTS",	10,
428*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_opackets), print_default_cb},
429*0dc2366fSVenugopal Iyer { "OBYTES",	11,
430*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_obytes), print_default_cb},
431*0dc2366fSVenugopal Iyer { "BANDWIDTH",	15,
432*0dc2366fSVenugopal Iyer 	offsetof(history_fields_buf_t, h_bandwidth), print_default_cb},
433*0dc2366fSVenugopal Iyer { NULL,		0, 0, NULL}};
434*0dc2366fSVenugopal Iyer 
435*0dc2366fSVenugopal Iyer /*
436*0dc2366fSVenugopal Iyer  * structures for 'dlstat show-link -h link'
437*0dc2366fSVenugopal Iyer  */
438*0dc2366fSVenugopal Iyer typedef struct  history_l_fields_buf_s {
439*0dc2366fSVenugopal Iyer 	char	hl_link[12];
440*0dc2366fSVenugopal Iyer 	char	hl_stime[13];
441*0dc2366fSVenugopal Iyer 	char	hl_etime[13];
442*0dc2366fSVenugopal Iyer 	char	hl_rbytes[8];
443*0dc2366fSVenugopal Iyer 	char	hl_obytes[8];
444*0dc2366fSVenugopal Iyer 	char	hl_bandwidth[14];
445*0dc2366fSVenugopal Iyer } history_l_fields_buf_t;
446*0dc2366fSVenugopal Iyer 
447*0dc2366fSVenugopal Iyer static ofmt_field_t history_l_fields[] = {
448*0dc2366fSVenugopal Iyer /* name,	field width,	offset */
449*0dc2366fSVenugopal Iyer { "LINK",	13,
450*0dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_link), print_default_cb},
451*0dc2366fSVenugopal Iyer { "START",	14,
452*0dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_stime), print_default_cb},
453*0dc2366fSVenugopal Iyer { "END",	14,
454*0dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_etime), print_default_cb},
455*0dc2366fSVenugopal Iyer { "RBYTES",	9,
456*0dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_rbytes), print_default_cb},
457*0dc2366fSVenugopal Iyer { "OBYTES",	9,
458*0dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_obytes), print_default_cb},
459*0dc2366fSVenugopal Iyer { "BANDWIDTH",	15,
460*0dc2366fSVenugopal Iyer 	offsetof(history_l_fields_buf_t, hl_bandwidth), print_default_cb},
461*0dc2366fSVenugopal Iyer { NULL,		0, 0, NULL}}
462*0dc2366fSVenugopal Iyer ;
463*0dc2366fSVenugopal Iyer 
464*0dc2366fSVenugopal Iyer static char *progname;
465*0dc2366fSVenugopal Iyer 
466*0dc2366fSVenugopal Iyer /*
467*0dc2366fSVenugopal Iyer  * Handle to libdladm.  Opened in main() before the sub-command
468*0dc2366fSVenugopal Iyer  * specific function is called.
469*0dc2366fSVenugopal Iyer  */
470*0dc2366fSVenugopal Iyer static dladm_handle_t handle = NULL;
471*0dc2366fSVenugopal Iyer 
472*0dc2366fSVenugopal Iyer static void
usage(void)473*0dc2366fSVenugopal Iyer usage(void)
474*0dc2366fSVenugopal Iyer {
475*0dc2366fSVenugopal Iyer 	int	i;
476*0dc2366fSVenugopal Iyer 	cmd_t	*cmdp;
477*0dc2366fSVenugopal Iyer 
478*0dc2366fSVenugopal Iyer 	(void) fprintf(stderr, gettext("usage: "));
479*0dc2366fSVenugopal Iyer 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
480*0dc2366fSVenugopal Iyer 		cmdp = &cmds[i];
481*0dc2366fSVenugopal Iyer 		if (cmdp->c_usage != NULL)
482*0dc2366fSVenugopal Iyer 			(void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
483*0dc2366fSVenugopal Iyer 	}
484*0dc2366fSVenugopal Iyer 
485*0dc2366fSVenugopal Iyer 	/* close dladm handle if it was opened */
486*0dc2366fSVenugopal Iyer 	if (handle != NULL)
487*0dc2366fSVenugopal Iyer 		dladm_close(handle);
488*0dc2366fSVenugopal Iyer 
489*0dc2366fSVenugopal Iyer 	exit(1);
490*0dc2366fSVenugopal Iyer }
491*0dc2366fSVenugopal Iyer 
492*0dc2366fSVenugopal Iyer int
main(int argc,char * argv[])493*0dc2366fSVenugopal Iyer main(int argc, char *argv[])
494*0dc2366fSVenugopal Iyer {
495*0dc2366fSVenugopal Iyer 	int		i;
496*0dc2366fSVenugopal Iyer 	cmd_t		*cmdp;
497*0dc2366fSVenugopal Iyer 	dladm_status_t	status;
498*0dc2366fSVenugopal Iyer 
499*0dc2366fSVenugopal Iyer 	(void) setlocale(LC_ALL, "");
500*0dc2366fSVenugopal Iyer #if !defined(TEXT_DOMAIN)
501*0dc2366fSVenugopal Iyer #define	TEXT_DOMAIN "SYS_TEST"
502*0dc2366fSVenugopal Iyer #endif
503*0dc2366fSVenugopal Iyer 	(void) textdomain(TEXT_DOMAIN);
504*0dc2366fSVenugopal Iyer 
505*0dc2366fSVenugopal Iyer 	progname = argv[0];
506*0dc2366fSVenugopal Iyer 
507*0dc2366fSVenugopal Iyer 	/* Open the libdladm handle */
508*0dc2366fSVenugopal Iyer 	if ((status = dladm_open(&handle)) != DLADM_STATUS_OK)
509*0dc2366fSVenugopal Iyer 		die_dlerr(status, "could not open /dev/dld");
510*0dc2366fSVenugopal Iyer 
511*0dc2366fSVenugopal Iyer 	if (argc == 1) {
512*0dc2366fSVenugopal Iyer 		do_show(argc - 1, NULL, cmds[0].c_usage);
513*0dc2366fSVenugopal Iyer 		goto done;
514*0dc2366fSVenugopal Iyer 	}
515*0dc2366fSVenugopal Iyer 
516*0dc2366fSVenugopal Iyer 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
517*0dc2366fSVenugopal Iyer 		cmdp = &cmds[i];
518*0dc2366fSVenugopal Iyer 		if (strcmp(argv[1], cmdp->c_name) == 0) {
519*0dc2366fSVenugopal Iyer 			cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage);
520*0dc2366fSVenugopal Iyer 			goto done;
521*0dc2366fSVenugopal Iyer 		}
522*0dc2366fSVenugopal Iyer 	}
523*0dc2366fSVenugopal Iyer 
524*0dc2366fSVenugopal Iyer 	do_show(argc, &argv[0], cmds[0].c_usage);
525*0dc2366fSVenugopal Iyer 
526*0dc2366fSVenugopal Iyer done:
527*0dc2366fSVenugopal Iyer 	dladm_close(handle);
528*0dc2366fSVenugopal Iyer 	return (0);
529*0dc2366fSVenugopal Iyer }
530*0dc2366fSVenugopal Iyer 
531*0dc2366fSVenugopal Iyer /*ARGSUSED*/
532*0dc2366fSVenugopal Iyer static int
show_history_date(dladm_usage_t * history,void * arg)533*0dc2366fSVenugopal Iyer show_history_date(dladm_usage_t *history, void *arg)
534*0dc2366fSVenugopal Iyer {
535*0dc2366fSVenugopal Iyer 	show_history_state_t	*state = arg;
536*0dc2366fSVenugopal Iyer 	time_t			stime;
537*0dc2366fSVenugopal Iyer 	char			timebuf[20];
538*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
539*0dc2366fSVenugopal Iyer 	uint32_t		flags;
540*0dc2366fSVenugopal Iyer 
541*0dc2366fSVenugopal Iyer 	/*
542*0dc2366fSVenugopal Iyer 	 * Only show history information for existing links unless '-a'
543*0dc2366fSVenugopal Iyer 	 * is specified.
544*0dc2366fSVenugopal Iyer 	 */
545*0dc2366fSVenugopal Iyer 	if (!state->hs_showall) {
546*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, history->du_name,
547*0dc2366fSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
548*0dc2366fSVenugopal Iyer 			return (status);
549*0dc2366fSVenugopal Iyer 		}
550*0dc2366fSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
551*0dc2366fSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
552*0dc2366fSVenugopal Iyer 	}
553*0dc2366fSVenugopal Iyer 
554*0dc2366fSVenugopal Iyer 	stime = history->du_stime;
555*0dc2366fSVenugopal Iyer 	(void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y",
556*0dc2366fSVenugopal Iyer 	    localtime(&stime));
557*0dc2366fSVenugopal Iyer 	(void) printf("%s\n", timebuf);
558*0dc2366fSVenugopal Iyer 
559*0dc2366fSVenugopal Iyer 	return (DLADM_STATUS_OK);
560*0dc2366fSVenugopal Iyer }
561*0dc2366fSVenugopal Iyer 
562*0dc2366fSVenugopal Iyer static int
show_history_time(dladm_usage_t * history,void * arg)563*0dc2366fSVenugopal Iyer show_history_time(dladm_usage_t *history, void *arg)
564*0dc2366fSVenugopal Iyer {
565*0dc2366fSVenugopal Iyer 	show_history_state_t	*state = arg;
566*0dc2366fSVenugopal Iyer 	char			buf[DLADM_STRSIZE];
567*0dc2366fSVenugopal Iyer 	history_l_fields_buf_t 	ubuf;
568*0dc2366fSVenugopal Iyer 	time_t			time;
569*0dc2366fSVenugopal Iyer 	double			bw;
570*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
571*0dc2366fSVenugopal Iyer 	uint32_t		flags;
572*0dc2366fSVenugopal Iyer 
573*0dc2366fSVenugopal Iyer 	/*
574*0dc2366fSVenugopal Iyer 	 * Only show history information for existing links unless '-a'
575*0dc2366fSVenugopal Iyer 	 * is specified.
576*0dc2366fSVenugopal Iyer 	 */
577*0dc2366fSVenugopal Iyer 	if (!state->hs_showall) {
578*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, history->du_name,
579*0dc2366fSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
580*0dc2366fSVenugopal Iyer 			return (status);
581*0dc2366fSVenugopal Iyer 		}
582*0dc2366fSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
583*0dc2366fSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
584*0dc2366fSVenugopal Iyer 	}
585*0dc2366fSVenugopal Iyer 
586*0dc2366fSVenugopal Iyer 	if (state->hs_plot) {
587*0dc2366fSVenugopal Iyer 		if (!state->hs_printheader) {
588*0dc2366fSVenugopal Iyer 			if (state->hs_first) {
589*0dc2366fSVenugopal Iyer 				(void) printf("# Time");
590*0dc2366fSVenugopal Iyer 				state->hs_first = B_FALSE;
591*0dc2366fSVenugopal Iyer 			}
592*0dc2366fSVenugopal Iyer 			(void) printf(" %s", history->du_name);
593*0dc2366fSVenugopal Iyer 			if (history->du_last) {
594*0dc2366fSVenugopal Iyer 				(void) printf("\n");
595*0dc2366fSVenugopal Iyer 				state->hs_first = B_TRUE;
596*0dc2366fSVenugopal Iyer 				state->hs_printheader = B_TRUE;
597*0dc2366fSVenugopal Iyer 			}
598*0dc2366fSVenugopal Iyer 		} else {
599*0dc2366fSVenugopal Iyer 			if (state->hs_first) {
600*0dc2366fSVenugopal Iyer 				time = history->du_etime;
601*0dc2366fSVenugopal Iyer 				(void) strftime(buf, sizeof (buf), "%T",
602*0dc2366fSVenugopal Iyer 				    localtime(&time));
603*0dc2366fSVenugopal Iyer 				state->hs_first = B_FALSE;
604*0dc2366fSVenugopal Iyer 				(void) printf("%s", buf);
605*0dc2366fSVenugopal Iyer 			}
606*0dc2366fSVenugopal Iyer 			bw = (double)history->du_bandwidth/1000;
607*0dc2366fSVenugopal Iyer 			(void) printf(" %.2f", bw);
608*0dc2366fSVenugopal Iyer 			if (history->du_last) {
609*0dc2366fSVenugopal Iyer 				(void) printf("\n");
610*0dc2366fSVenugopal Iyer 				state->hs_first = B_TRUE;
611*0dc2366fSVenugopal Iyer 			}
612*0dc2366fSVenugopal Iyer 		}
613*0dc2366fSVenugopal Iyer 		return (DLADM_STATUS_OK);
614*0dc2366fSVenugopal Iyer 	}
615*0dc2366fSVenugopal Iyer 
616*0dc2366fSVenugopal Iyer 	bzero(&ubuf, sizeof (ubuf));
617*0dc2366fSVenugopal Iyer 
618*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_link, sizeof (ubuf.hl_link), "%s",
619*0dc2366fSVenugopal Iyer 	    history->du_name);
620*0dc2366fSVenugopal Iyer 	time = history->du_stime;
621*0dc2366fSVenugopal Iyer 	(void) strftime(buf, sizeof (buf), "%T", localtime(&time));
622*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_stime, sizeof (ubuf.hl_stime), "%s",
623*0dc2366fSVenugopal Iyer 	    buf);
624*0dc2366fSVenugopal Iyer 	time = history->du_etime;
625*0dc2366fSVenugopal Iyer 	(void) strftime(buf, sizeof (buf), "%T", localtime(&time));
626*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_etime, sizeof (ubuf.hl_etime), "%s",
627*0dc2366fSVenugopal Iyer 	    buf);
628*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_rbytes, sizeof (ubuf.hl_rbytes),
629*0dc2366fSVenugopal Iyer 	    "%llu", history->du_rbytes);
630*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_obytes, sizeof (ubuf.hl_obytes),
631*0dc2366fSVenugopal Iyer 	    "%llu", history->du_obytes);
632*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.hl_bandwidth, sizeof (ubuf.hl_bandwidth),
633*0dc2366fSVenugopal Iyer 	    "%s Mbps", dladm_bw2str(history->du_bandwidth, buf));
634*0dc2366fSVenugopal Iyer 
635*0dc2366fSVenugopal Iyer 	ofmt_print(state->hs_ofmt, &ubuf);
636*0dc2366fSVenugopal Iyer 	return (DLADM_STATUS_OK);
637*0dc2366fSVenugopal Iyer }
638*0dc2366fSVenugopal Iyer 
639*0dc2366fSVenugopal Iyer static int
show_history_res(dladm_usage_t * history,void * arg)640*0dc2366fSVenugopal Iyer show_history_res(dladm_usage_t *history, void *arg)
641*0dc2366fSVenugopal Iyer {
642*0dc2366fSVenugopal Iyer 	show_history_state_t	*state = arg;
643*0dc2366fSVenugopal Iyer 	char			buf[DLADM_STRSIZE];
644*0dc2366fSVenugopal Iyer 	history_fields_buf_t	ubuf;
645*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
646*0dc2366fSVenugopal Iyer 	uint32_t		flags;
647*0dc2366fSVenugopal Iyer 
648*0dc2366fSVenugopal Iyer 	/*
649*0dc2366fSVenugopal Iyer 	 * Only show history information for existing links unless '-a'
650*0dc2366fSVenugopal Iyer 	 * is specified.
651*0dc2366fSVenugopal Iyer 	 */
652*0dc2366fSVenugopal Iyer 	if (!state->hs_showall) {
653*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, history->du_name,
654*0dc2366fSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
655*0dc2366fSVenugopal Iyer 			return (status);
656*0dc2366fSVenugopal Iyer 		}
657*0dc2366fSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
658*0dc2366fSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
659*0dc2366fSVenugopal Iyer 	}
660*0dc2366fSVenugopal Iyer 
661*0dc2366fSVenugopal Iyer 	bzero(&ubuf, sizeof (ubuf));
662*0dc2366fSVenugopal Iyer 
663*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_link, sizeof (ubuf.h_link), "%s",
664*0dc2366fSVenugopal Iyer 	    history->du_name);
665*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_duration, sizeof (ubuf.h_duration),
666*0dc2366fSVenugopal Iyer 	    "%llu", history->du_duration);
667*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_ipackets, sizeof (ubuf.h_ipackets),
668*0dc2366fSVenugopal Iyer 	    "%llu", history->du_ipackets);
669*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_rbytes, sizeof (ubuf.h_rbytes),
670*0dc2366fSVenugopal Iyer 	    "%llu", history->du_rbytes);
671*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_opackets, sizeof (ubuf.h_opackets),
672*0dc2366fSVenugopal Iyer 	    "%llu", history->du_opackets);
673*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_obytes, sizeof (ubuf.h_obytes),
674*0dc2366fSVenugopal Iyer 	    "%llu", history->du_obytes);
675*0dc2366fSVenugopal Iyer 	(void) snprintf(ubuf.h_bandwidth, sizeof (ubuf.h_bandwidth),
676*0dc2366fSVenugopal Iyer 	    "%s Mbps", dladm_bw2str(history->du_bandwidth, buf));
677*0dc2366fSVenugopal Iyer 
678*0dc2366fSVenugopal Iyer 	ofmt_print(state->hs_ofmt, &ubuf);
679*0dc2366fSVenugopal Iyer 
680*0dc2366fSVenugopal Iyer 	return (DLADM_STATUS_OK);
681*0dc2366fSVenugopal Iyer }
682*0dc2366fSVenugopal Iyer 
683*0dc2366fSVenugopal Iyer static boolean_t
valid_formatspec(char * formatspec_str)684*0dc2366fSVenugopal Iyer valid_formatspec(char *formatspec_str)
685*0dc2366fSVenugopal Iyer {
686*0dc2366fSVenugopal Iyer 	return (strcmp(formatspec_str, "gnuplot") == 0);
687*0dc2366fSVenugopal Iyer }
688*0dc2366fSVenugopal Iyer 
689*0dc2366fSVenugopal Iyer /*ARGSUSED*/
690*0dc2366fSVenugopal Iyer static void
do_show_history(int argc,char * argv[],const char * use)691*0dc2366fSVenugopal Iyer do_show_history(int argc, char *argv[], const char *use)
692*0dc2366fSVenugopal Iyer {
693*0dc2366fSVenugopal Iyer 	char			*file = NULL;
694*0dc2366fSVenugopal Iyer 	int			opt;
695*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
696*0dc2366fSVenugopal Iyer 	boolean_t		d_arg = B_FALSE;
697*0dc2366fSVenugopal Iyer 	char			*stime = NULL;
698*0dc2366fSVenugopal Iyer 	char			*etime = NULL;
699*0dc2366fSVenugopal Iyer 	char			*resource = NULL;
700*0dc2366fSVenugopal Iyer 	show_history_state_t	state;
701*0dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
702*0dc2366fSVenugopal Iyer 	boolean_t		F_arg = B_FALSE;
703*0dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
704*0dc2366fSVenugopal Iyer 	char			*formatspec_str = NULL;
705*0dc2366fSVenugopal Iyer 	char			*all_l_fields =
706*0dc2366fSVenugopal Iyer 	    "link,start,end,rbytes,obytes,bandwidth";
707*0dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
708*0dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
709*0dc2366fSVenugopal Iyer 	uint_t			ofmtflags = 0;
710*0dc2366fSVenugopal Iyer 
711*0dc2366fSVenugopal Iyer 	bzero(&state, sizeof (show_history_state_t));
712*0dc2366fSVenugopal Iyer 	state.hs_parsable = B_FALSE;
713*0dc2366fSVenugopal Iyer 	state.hs_printheader = B_FALSE;
714*0dc2366fSVenugopal Iyer 	state.hs_plot = B_FALSE;
715*0dc2366fSVenugopal Iyer 	state.hs_first = B_TRUE;
716*0dc2366fSVenugopal Iyer 
717*0dc2366fSVenugopal Iyer 	while ((opt = getopt(argc, argv, "das:e:o:f:F:")) != -1) {
718*0dc2366fSVenugopal Iyer 		switch (opt) {
719*0dc2366fSVenugopal Iyer 		case 'd':
720*0dc2366fSVenugopal Iyer 			d_arg = B_TRUE;
721*0dc2366fSVenugopal Iyer 			break;
722*0dc2366fSVenugopal Iyer 		case 'a':
723*0dc2366fSVenugopal Iyer 			state.hs_showall = B_TRUE;
724*0dc2366fSVenugopal Iyer 			break;
725*0dc2366fSVenugopal Iyer 		case 'f':
726*0dc2366fSVenugopal Iyer 			file = optarg;
727*0dc2366fSVenugopal Iyer 			break;
728*0dc2366fSVenugopal Iyer 		case 's':
729*0dc2366fSVenugopal Iyer 			stime = optarg;
730*0dc2366fSVenugopal Iyer 			break;
731*0dc2366fSVenugopal Iyer 		case 'e':
732*0dc2366fSVenugopal Iyer 			etime = optarg;
733*0dc2366fSVenugopal Iyer 			break;
734*0dc2366fSVenugopal Iyer 		case 'o':
735*0dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
736*0dc2366fSVenugopal Iyer 			fields_str = optarg;
737*0dc2366fSVenugopal Iyer 			break;
738*0dc2366fSVenugopal Iyer 		case 'F':
739*0dc2366fSVenugopal Iyer 			state.hs_plot = F_arg = B_TRUE;
740*0dc2366fSVenugopal Iyer 			formatspec_str = optarg;
741*0dc2366fSVenugopal Iyer 			break;
742*0dc2366fSVenugopal Iyer 		default:
743*0dc2366fSVenugopal Iyer 			die_opterr(optopt, opt, use);
744*0dc2366fSVenugopal Iyer 			break;
745*0dc2366fSVenugopal Iyer 		}
746*0dc2366fSVenugopal Iyer 	}
747*0dc2366fSVenugopal Iyer 
748*0dc2366fSVenugopal Iyer 	if (file == NULL)
749*0dc2366fSVenugopal Iyer 		die("show-link -h requires a file");
750*0dc2366fSVenugopal Iyer 
751*0dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
752*0dc2366fSVenugopal Iyer 		uint32_t 	flags;
753*0dc2366fSVenugopal Iyer 
754*0dc2366fSVenugopal Iyer 		resource = argv[optind];
755*0dc2366fSVenugopal Iyer 		if (!state.hs_showall &&
756*0dc2366fSVenugopal Iyer 		    (((status = dladm_name2info(handle, resource, NULL, &flags,
757*0dc2366fSVenugopal Iyer 		    NULL, NULL)) != DLADM_STATUS_OK) ||
758*0dc2366fSVenugopal Iyer 		    ((flags & DLADM_OPT_ACTIVE) == 0))) {
759*0dc2366fSVenugopal Iyer 			die("invalid link: '%s'", resource);
760*0dc2366fSVenugopal Iyer 		}
761*0dc2366fSVenugopal Iyer 	}
762*0dc2366fSVenugopal Iyer 
763*0dc2366fSVenugopal Iyer 	if (F_arg && d_arg)
764*0dc2366fSVenugopal Iyer 		die("incompatible -d and -F options");
765*0dc2366fSVenugopal Iyer 
766*0dc2366fSVenugopal Iyer 	if (F_arg && !valid_formatspec(formatspec_str))
767*0dc2366fSVenugopal Iyer 		die("Format specifier %s not supported", formatspec_str);
768*0dc2366fSVenugopal Iyer 
769*0dc2366fSVenugopal Iyer 	if (state.hs_parsable)
770*0dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
771*0dc2366fSVenugopal Iyer 
772*0dc2366fSVenugopal Iyer 	if (resource == NULL && stime == NULL && etime == NULL) {
773*0dc2366fSVenugopal Iyer 		oferr = ofmt_open(fields_str, history_fields, ofmtflags, 0,
774*0dc2366fSVenugopal Iyer 		    &ofmt);
775*0dc2366fSVenugopal Iyer 	} else {
776*0dc2366fSVenugopal Iyer 		if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
777*0dc2366fSVenugopal Iyer 			fields_str = all_l_fields;
778*0dc2366fSVenugopal Iyer 		oferr = ofmt_open(fields_str, history_l_fields, ofmtflags, 0,
779*0dc2366fSVenugopal Iyer 		    &ofmt);
780*0dc2366fSVenugopal Iyer 
781*0dc2366fSVenugopal Iyer 	}
782*0dc2366fSVenugopal Iyer 	dlstat_ofmt_check(oferr, state.hs_parsable, ofmt);
783*0dc2366fSVenugopal Iyer 	state.hs_ofmt = ofmt;
784*0dc2366fSVenugopal Iyer 
785*0dc2366fSVenugopal Iyer 	if (d_arg) {
786*0dc2366fSVenugopal Iyer 		/* Print log dates */
787*0dc2366fSVenugopal Iyer 		status = dladm_usage_dates(show_history_date,
788*0dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, resource, &state);
789*0dc2366fSVenugopal Iyer 	} else if (resource == NULL && stime == NULL && etime == NULL &&
790*0dc2366fSVenugopal Iyer 	    !F_arg) {
791*0dc2366fSVenugopal Iyer 		/* Print summary */
792*0dc2366fSVenugopal Iyer 		status = dladm_usage_summary(show_history_res,
793*0dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, &state);
794*0dc2366fSVenugopal Iyer 	} else if (resource != NULL) {
795*0dc2366fSVenugopal Iyer 		/* Print log entries for named resource */
796*0dc2366fSVenugopal Iyer 		status = dladm_walk_usage_res(show_history_time,
797*0dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state);
798*0dc2366fSVenugopal Iyer 	} else {
799*0dc2366fSVenugopal Iyer 		/* Print time and information for each link */
800*0dc2366fSVenugopal Iyer 		status = dladm_walk_usage_time(show_history_time,
801*0dc2366fSVenugopal Iyer 		    DLADM_LOGTYPE_LINK, file, stime, etime, &state);
802*0dc2366fSVenugopal Iyer 	}
803*0dc2366fSVenugopal Iyer 
804*0dc2366fSVenugopal Iyer 	if (status != DLADM_STATUS_OK)
805*0dc2366fSVenugopal Iyer 		die_dlerr(status, "show-link -h");
806*0dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
807*0dc2366fSVenugopal Iyer }
808*0dc2366fSVenugopal Iyer 
809*0dc2366fSVenugopal Iyer boolean_t
dlstat_unit(char * oarg,char * unit)810*0dc2366fSVenugopal Iyer dlstat_unit(char *oarg, char *unit)
811*0dc2366fSVenugopal Iyer {
812*0dc2366fSVenugopal Iyer 	if ((strcmp(oarg, "R") == 0) || (strcmp(oarg, "K") == 0) ||
813*0dc2366fSVenugopal Iyer 	    (strcmp(oarg, "M") == 0) || (strcmp(oarg, "G") == 0) ||
814*0dc2366fSVenugopal Iyer 	    (strcmp(oarg, "T") == 0) || (strcmp(oarg, "P") == 0)) {
815*0dc2366fSVenugopal Iyer 		*unit = oarg[0];
816*0dc2366fSVenugopal Iyer 		return (B_TRUE);
817*0dc2366fSVenugopal Iyer 	}
818*0dc2366fSVenugopal Iyer 
819*0dc2366fSVenugopal Iyer 	return (B_FALSE);
820*0dc2366fSVenugopal Iyer }
821*0dc2366fSVenugopal Iyer 
822*0dc2366fSVenugopal Iyer void
map_to_units(char * buf,uint_t bufsize,double num,char unit,boolean_t parsable)823*0dc2366fSVenugopal Iyer map_to_units(char *buf, uint_t bufsize, double num, char unit,
824*0dc2366fSVenugopal Iyer     boolean_t parsable)
825*0dc2366fSVenugopal Iyer {
826*0dc2366fSVenugopal Iyer 	if (parsable) {
827*0dc2366fSVenugopal Iyer 		(void) snprintf(buf, bufsize, "%.0lf", num);
828*0dc2366fSVenugopal Iyer 		return;
829*0dc2366fSVenugopal Iyer 	}
830*0dc2366fSVenugopal Iyer 
831*0dc2366fSVenugopal Iyer 	if (unit == '\0') {
832*0dc2366fSVenugopal Iyer 		int index;
833*0dc2366fSVenugopal Iyer 
834*0dc2366fSVenugopal Iyer 		for (index = 0; (int)(num/1000) != 0; index++, num /= 1000)
835*0dc2366fSVenugopal Iyer 			;
836*0dc2366fSVenugopal Iyer 
837*0dc2366fSVenugopal Iyer 		switch (index) {
838*0dc2366fSVenugopal Iyer 			case 0:
839*0dc2366fSVenugopal Iyer 				unit = '\0';
840*0dc2366fSVenugopal Iyer 				break;
841*0dc2366fSVenugopal Iyer 			case 1:
842*0dc2366fSVenugopal Iyer 				unit = 'K';
843*0dc2366fSVenugopal Iyer 				break;
844*0dc2366fSVenugopal Iyer 			case 2:
845*0dc2366fSVenugopal Iyer 				unit = 'M';
846*0dc2366fSVenugopal Iyer 				break;
847*0dc2366fSVenugopal Iyer 			case 3:
848*0dc2366fSVenugopal Iyer 				unit = 'G';
849*0dc2366fSVenugopal Iyer 				break;
850*0dc2366fSVenugopal Iyer 			case 4:
851*0dc2366fSVenugopal Iyer 				unit = 'T';
852*0dc2366fSVenugopal Iyer 				break;
853*0dc2366fSVenugopal Iyer 			case 5:
854*0dc2366fSVenugopal Iyer 				/* Largest unit supported */
855*0dc2366fSVenugopal Iyer 			default:
856*0dc2366fSVenugopal Iyer 				unit = 'P';
857*0dc2366fSVenugopal Iyer 				break;
858*0dc2366fSVenugopal Iyer 		}
859*0dc2366fSVenugopal Iyer 	} else  {
860*0dc2366fSVenugopal Iyer 		switch (unit) {
861*0dc2366fSVenugopal Iyer 			case 'R':
862*0dc2366fSVenugopal Iyer 				/* Already raw numbers */
863*0dc2366fSVenugopal Iyer 				unit = '\0';
864*0dc2366fSVenugopal Iyer 				break;
865*0dc2366fSVenugopal Iyer 			case 'K':
866*0dc2366fSVenugopal Iyer 				num /= 1000;
867*0dc2366fSVenugopal Iyer 				break;
868*0dc2366fSVenugopal Iyer 			case 'M':
869*0dc2366fSVenugopal Iyer 				num /= (1000*1000);
870*0dc2366fSVenugopal Iyer 				break;
871*0dc2366fSVenugopal Iyer 			case 'G':
872*0dc2366fSVenugopal Iyer 				num /= (1000*1000*1000);
873*0dc2366fSVenugopal Iyer 				break;
874*0dc2366fSVenugopal Iyer 			case 'T':
875*0dc2366fSVenugopal Iyer 				num /= (1000.0*1000.0*1000.0*1000.0);
876*0dc2366fSVenugopal Iyer 				break;
877*0dc2366fSVenugopal Iyer 			case 'P':
878*0dc2366fSVenugopal Iyer 				/* Largest unit supported */
879*0dc2366fSVenugopal Iyer 			default:
880*0dc2366fSVenugopal Iyer 				num /= (1000.0*1000.0*1000.0*1000.0*1000.0);
881*0dc2366fSVenugopal Iyer 				break;
882*0dc2366fSVenugopal Iyer 		}
883*0dc2366fSVenugopal Iyer 	}
884*0dc2366fSVenugopal Iyer 
885*0dc2366fSVenugopal Iyer 	if (unit == '\0')
886*0dc2366fSVenugopal Iyer 		(void) snprintf(buf, bufsize, " %7.0lf%c", num, unit);
887*0dc2366fSVenugopal Iyer 	else
888*0dc2366fSVenugopal Iyer 		(void) snprintf(buf, bufsize, " %6.2lf%c", num, unit);
889*0dc2366fSVenugopal Iyer }
890*0dc2366fSVenugopal Iyer 
891*0dc2366fSVenugopal Iyer link_chain_t *
get_link_prev_stat(datalink_id_t linkid,void * arg)892*0dc2366fSVenugopal Iyer get_link_prev_stat(datalink_id_t linkid, void *arg)
893*0dc2366fSVenugopal Iyer {
894*0dc2366fSVenugopal Iyer 	show_state_t	*state = (show_state_t *)arg;
895*0dc2366fSVenugopal Iyer 	link_chain_t	*link_curr = NULL;
896*0dc2366fSVenugopal Iyer 
897*0dc2366fSVenugopal Iyer 	/* Scan prev linkid list and look for entry matching this entry */
898*0dc2366fSVenugopal Iyer 	for (link_curr = state->ls_linkchain; link_curr;
899*0dc2366fSVenugopal Iyer 	    link_curr = link_curr->lc_next) {
900*0dc2366fSVenugopal Iyer 		if (link_curr->lc_linkid == linkid)
901*0dc2366fSVenugopal Iyer 			break;
902*0dc2366fSVenugopal Iyer 	}
903*0dc2366fSVenugopal Iyer 				/* New link, add it */
904*0dc2366fSVenugopal Iyer 	if (link_curr == NULL) {
905*0dc2366fSVenugopal Iyer 		link_curr = (link_chain_t *)malloc(sizeof (link_chain_t));
906*0dc2366fSVenugopal Iyer 		if (link_curr == NULL)
907*0dc2366fSVenugopal Iyer 			goto done;
908*0dc2366fSVenugopal Iyer 		link_curr->lc_linkid = linkid;
909*0dc2366fSVenugopal Iyer 		bzero(&link_curr->lc_statchain,
910*0dc2366fSVenugopal Iyer 		    sizeof (link_curr->lc_statchain));
911*0dc2366fSVenugopal Iyer 		link_curr->lc_next = state->ls_linkchain;
912*0dc2366fSVenugopal Iyer 		state->ls_linkchain = link_curr;
913*0dc2366fSVenugopal Iyer 	}
914*0dc2366fSVenugopal Iyer done:
915*0dc2366fSVenugopal Iyer 	return (link_curr);
916*0dc2366fSVenugopal Iyer }
917*0dc2366fSVenugopal Iyer 
918*0dc2366fSVenugopal Iyer /*
919*0dc2366fSVenugopal Iyer  * Number of links may change while dlstat with -i is executing.
920*0dc2366fSVenugopal Iyer  * Free memory allocated for links that are no longer there.
921*0dc2366fSVenugopal Iyer  * Prepare for next iteration by marking visited = false for existing stat
922*0dc2366fSVenugopal Iyer  * entries.
923*0dc2366fSVenugopal Iyer  */
924*0dc2366fSVenugopal Iyer static void
cleanup_removed_links(show_state_t * state)925*0dc2366fSVenugopal Iyer cleanup_removed_links(show_state_t *state)
926*0dc2366fSVenugopal Iyer {
927*0dc2366fSVenugopal Iyer 	link_chain_t	*lcurr;
928*0dc2366fSVenugopal Iyer 	link_chain_t	*lprev;
929*0dc2366fSVenugopal Iyer 	link_chain_t	*tofree;
930*0dc2366fSVenugopal Iyer 	int		i;
931*0dc2366fSVenugopal Iyer 
932*0dc2366fSVenugopal Iyer 	/* Delete all nodes from the list that have lc_visited marked false */
933*0dc2366fSVenugopal Iyer 	lcurr = state->ls_linkchain;
934*0dc2366fSVenugopal Iyer 	while (lcurr != NULL) {
935*0dc2366fSVenugopal Iyer 		if (lcurr->lc_visited) {
936*0dc2366fSVenugopal Iyer 			lcurr->lc_visited = B_FALSE;
937*0dc2366fSVenugopal Iyer 			lprev = lcurr;
938*0dc2366fSVenugopal Iyer 			lcurr = lcurr->lc_next;
939*0dc2366fSVenugopal Iyer 			continue;
940*0dc2366fSVenugopal Iyer 		}
941*0dc2366fSVenugopal Iyer 				/* Is it head of the list? */
942*0dc2366fSVenugopal Iyer 		if (lcurr == state->ls_linkchain)
943*0dc2366fSVenugopal Iyer 			state->ls_linkchain = lcurr->lc_next;
944*0dc2366fSVenugopal Iyer 		else
945*0dc2366fSVenugopal Iyer 			lprev->lc_next = lcurr->lc_next;
946*0dc2366fSVenugopal Iyer 				/* lprev remains the same */
947*0dc2366fSVenugopal Iyer 		tofree = lcurr;
948*0dc2366fSVenugopal Iyer 		lcurr = lcurr->lc_next;
949*0dc2366fSVenugopal Iyer 
950*0dc2366fSVenugopal Iyer 				/* Free stats memory for the removed link */
951*0dc2366fSVenugopal Iyer 		for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
952*0dc2366fSVenugopal Iyer 			if (state->ls_stattype[i])
953*0dc2366fSVenugopal Iyer 				dladm_link_stat_free(tofree->lc_statchain[i]);
954*0dc2366fSVenugopal Iyer 		}
955*0dc2366fSVenugopal Iyer 		free(tofree);
956*0dc2366fSVenugopal Iyer 	}
957*0dc2366fSVenugopal Iyer }
958*0dc2366fSVenugopal Iyer 
959*0dc2366fSVenugopal Iyer void *
print_total_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)960*0dc2366fSVenugopal Iyer print_total_stats(const char *linkname, void *statentry, char unit,
961*0dc2366fSVenugopal Iyer     boolean_t parsable)
962*0dc2366fSVenugopal Iyer {
963*0dc2366fSVenugopal Iyer 	total_stat_entry_t	*sentry = statentry;
964*0dc2366fSVenugopal Iyer 	total_stat_t		*link_stats = &sentry->tse_stats;
965*0dc2366fSVenugopal Iyer 	total_fields_buf_t	*buf;
966*0dc2366fSVenugopal Iyer 
967*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (total_fields_buf_t));
968*0dc2366fSVenugopal Iyer 	if (buf == NULL)
969*0dc2366fSVenugopal Iyer 		goto done;
970*0dc2366fSVenugopal Iyer 
971*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s",
972*0dc2366fSVenugopal Iyer 	    linkname);
973*0dc2366fSVenugopal Iyer 
974*0dc2366fSVenugopal Iyer 	map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets),
975*0dc2366fSVenugopal Iyer 	    link_stats->ts_ipackets, unit, parsable);
976*0dc2366fSVenugopal Iyer 
977*0dc2366fSVenugopal Iyer 	map_to_units(buf->t_rbytes, sizeof (buf->t_rbytes),
978*0dc2366fSVenugopal Iyer 	    link_stats->ts_rbytes, unit, parsable);
979*0dc2366fSVenugopal Iyer 
980*0dc2366fSVenugopal Iyer 	map_to_units(buf->t_opackets, sizeof (buf->t_opackets),
981*0dc2366fSVenugopal Iyer 	    link_stats->ts_opackets, unit, parsable);
982*0dc2366fSVenugopal Iyer 
983*0dc2366fSVenugopal Iyer 	map_to_units(buf->t_obytes, sizeof (buf->t_obytes),
984*0dc2366fSVenugopal Iyer 	    link_stats->ts_obytes, unit, parsable);
985*0dc2366fSVenugopal Iyer 
986*0dc2366fSVenugopal Iyer done:
987*0dc2366fSVenugopal Iyer 	return (buf);
988*0dc2366fSVenugopal Iyer }
989*0dc2366fSVenugopal Iyer 
990*0dc2366fSVenugopal Iyer void *
print_rx_generic_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)991*0dc2366fSVenugopal Iyer print_rx_generic_ring_stats(const char *linkname, void *statentry, char unit,
992*0dc2366fSVenugopal Iyer     boolean_t parsable)
993*0dc2366fSVenugopal Iyer {
994*0dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
995*0dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
996*0dc2366fSVenugopal Iyer 	ring_fields_buf_t	*buf;
997*0dc2366fSVenugopal Iyer 
998*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (ring_fields_buf_t));
999*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1000*0dc2366fSVenugopal Iyer 		goto done;
1001*0dc2366fSVenugopal Iyer 
1002*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1003*0dc2366fSVenugopal Iyer 	    linkname);
1004*0dc2366fSVenugopal Iyer 
1005*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_type, sizeof (buf->r_type), "rx");
1006*0dc2366fSVenugopal Iyer 
1007*0dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1008*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1009*0dc2366fSVenugopal Iyer 	} else {
1010*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index),
1011*0dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
1012*0dc2366fSVenugopal Iyer 	}
1013*0dc2366fSVenugopal Iyer 
1014*0dc2366fSVenugopal Iyer 	map_to_units(buf->r_packets, sizeof (buf->r_packets),
1015*0dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
1016*0dc2366fSVenugopal Iyer 
1017*0dc2366fSVenugopal Iyer 	map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1018*0dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
1019*0dc2366fSVenugopal Iyer 
1020*0dc2366fSVenugopal Iyer done:
1021*0dc2366fSVenugopal Iyer 	return (buf);
1022*0dc2366fSVenugopal Iyer }
1023*0dc2366fSVenugopal Iyer 
1024*0dc2366fSVenugopal Iyer void *
print_tx_generic_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1025*0dc2366fSVenugopal Iyer print_tx_generic_ring_stats(const char *linkname, void *statentry, char unit,
1026*0dc2366fSVenugopal Iyer     boolean_t parsable)
1027*0dc2366fSVenugopal Iyer {
1028*0dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
1029*0dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
1030*0dc2366fSVenugopal Iyer 	ring_fields_buf_t	*buf;
1031*0dc2366fSVenugopal Iyer 
1032*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (ring_fields_buf_t));
1033*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1034*0dc2366fSVenugopal Iyer 		goto done;
1035*0dc2366fSVenugopal Iyer 
1036*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1037*0dc2366fSVenugopal Iyer 	    linkname);
1038*0dc2366fSVenugopal Iyer 
1039*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->r_type, sizeof (buf->r_type), "tx");
1040*0dc2366fSVenugopal Iyer 
1041*0dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1042*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1043*0dc2366fSVenugopal Iyer 	} else {
1044*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->r_index, sizeof (buf->r_index),
1045*0dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
1046*0dc2366fSVenugopal Iyer 	}
1047*0dc2366fSVenugopal Iyer 
1048*0dc2366fSVenugopal Iyer 	map_to_units(buf->r_packets, sizeof (buf->r_packets),
1049*0dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
1050*0dc2366fSVenugopal Iyer 
1051*0dc2366fSVenugopal Iyer 	map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1052*0dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
1053*0dc2366fSVenugopal Iyer 
1054*0dc2366fSVenugopal Iyer done:
1055*0dc2366fSVenugopal Iyer 	return (buf);
1056*0dc2366fSVenugopal Iyer }
1057*0dc2366fSVenugopal Iyer 
1058*0dc2366fSVenugopal Iyer void *
print_rx_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1059*0dc2366fSVenugopal Iyer print_rx_ring_stats(const char *linkname, void *statentry, char unit,
1060*0dc2366fSVenugopal Iyer     boolean_t parsable)
1061*0dc2366fSVenugopal Iyer {
1062*0dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
1063*0dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
1064*0dc2366fSVenugopal Iyer 	rx_ring_fields_buf_t	*buf;
1065*0dc2366fSVenugopal Iyer 
1066*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (rx_ring_fields_buf_t));
1067*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1068*0dc2366fSVenugopal Iyer 		goto done;
1069*0dc2366fSVenugopal Iyer 
1070*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->rr_linkname, sizeof (buf->rr_linkname), "%s",
1071*0dc2366fSVenugopal Iyer 	    linkname);
1072*0dc2366fSVenugopal Iyer 
1073*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->rr_type, sizeof (buf->rr_type), "rx");
1074*0dc2366fSVenugopal Iyer 
1075*0dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1076*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rr_index, sizeof (buf->rr_index), "--");
1077*0dc2366fSVenugopal Iyer 	} else {
1078*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rr_index, sizeof (buf->rr_index),
1079*0dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
1080*0dc2366fSVenugopal Iyer 	}
1081*0dc2366fSVenugopal Iyer 
1082*0dc2366fSVenugopal Iyer 	map_to_units(buf->rr_ipackets, sizeof (buf->rr_ipackets),
1083*0dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
1084*0dc2366fSVenugopal Iyer 
1085*0dc2366fSVenugopal Iyer 	map_to_units(buf->rr_rbytes, sizeof (buf->rr_rbytes),
1086*0dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
1087*0dc2366fSVenugopal Iyer 
1088*0dc2366fSVenugopal Iyer done:
1089*0dc2366fSVenugopal Iyer 	return (buf);
1090*0dc2366fSVenugopal Iyer }
1091*0dc2366fSVenugopal Iyer 
1092*0dc2366fSVenugopal Iyer void *
print_tx_ring_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1093*0dc2366fSVenugopal Iyer print_tx_ring_stats(const char *linkname, void *statentry, char unit,
1094*0dc2366fSVenugopal Iyer     boolean_t parsable)
1095*0dc2366fSVenugopal Iyer {
1096*0dc2366fSVenugopal Iyer 	ring_stat_entry_t	*sentry = statentry;
1097*0dc2366fSVenugopal Iyer 	ring_stat_t		*link_stats = &sentry->re_stats;
1098*0dc2366fSVenugopal Iyer 	tx_ring_fields_buf_t	*buf;
1099*0dc2366fSVenugopal Iyer 
1100*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (tx_ring_fields_buf_t));
1101*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1102*0dc2366fSVenugopal Iyer 		goto done;
1103*0dc2366fSVenugopal Iyer 
1104*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->tr_linkname, sizeof (buf->tr_linkname), "%s",
1105*0dc2366fSVenugopal Iyer 	    linkname);
1106*0dc2366fSVenugopal Iyer 
1107*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->tr_type, sizeof (buf->tr_type), "tx");
1108*0dc2366fSVenugopal Iyer 
1109*0dc2366fSVenugopal Iyer 	if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1110*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tr_index, sizeof (buf->tr_index), "--");
1111*0dc2366fSVenugopal Iyer 	} else {
1112*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tr_index, sizeof (buf->tr_index),
1113*0dc2366fSVenugopal Iyer 		    "%llu", sentry->re_index);
1114*0dc2366fSVenugopal Iyer 	}
1115*0dc2366fSVenugopal Iyer 
1116*0dc2366fSVenugopal Iyer 	map_to_units(buf->tr_opackets, sizeof (buf->tr_opackets),
1117*0dc2366fSVenugopal Iyer 	    link_stats->r_packets, unit, parsable);
1118*0dc2366fSVenugopal Iyer 
1119*0dc2366fSVenugopal Iyer 	map_to_units(buf->tr_obytes, sizeof (buf->tr_obytes),
1120*0dc2366fSVenugopal Iyer 	    link_stats->r_bytes, unit, parsable);
1121*0dc2366fSVenugopal Iyer 
1122*0dc2366fSVenugopal Iyer done:
1123*0dc2366fSVenugopal Iyer 	return (buf);
1124*0dc2366fSVenugopal Iyer }
1125*0dc2366fSVenugopal Iyer 
1126*0dc2366fSVenugopal Iyer void *
print_rx_generic_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1127*0dc2366fSVenugopal Iyer print_rx_generic_lane_stats(const char *linkname, void *statentry, char unit,
1128*0dc2366fSVenugopal Iyer     boolean_t parsable)
1129*0dc2366fSVenugopal Iyer {
1130*0dc2366fSVenugopal Iyer 	rx_lane_stat_entry_t	*sentry = statentry;
1131*0dc2366fSVenugopal Iyer 	rx_lane_stat_t		*link_stats = &sentry->rle_stats;
1132*0dc2366fSVenugopal Iyer 	lane_fields_buf_t	*buf;
1133*0dc2366fSVenugopal Iyer 
1134*0dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_DFNCT)
1135*0dc2366fSVenugopal Iyer 		return (NULL);
1136*0dc2366fSVenugopal Iyer 
1137*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (lane_fields_buf_t));
1138*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1139*0dc2366fSVenugopal Iyer 		goto done;
1140*0dc2366fSVenugopal Iyer 
1141*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1142*0dc2366fSVenugopal Iyer 	    linkname);
1143*0dc2366fSVenugopal Iyer 
1144*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_type, sizeof (buf->l_type), "rx");
1145*0dc2366fSVenugopal Iyer 
1146*0dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_HWLANE)
1147*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1148*0dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_SWLANE)
1149*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "sw");
1150*0dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_LOCAL)
1151*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "local");
1152*0dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_BCAST)
1153*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "bcast");
1154*0dc2366fSVenugopal Iyer 	else
1155*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1156*0dc2366fSVenugopal Iyer 
1157*0dc2366fSVenugopal Iyer 	if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
1158*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1159*0dc2366fSVenugopal Iyer 	} else {
1160*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index),
1161*0dc2366fSVenugopal Iyer 		    "%llu", sentry->rle_index);
1162*0dc2366fSVenugopal Iyer 	}
1163*0dc2366fSVenugopal Iyer 
1164*0dc2366fSVenugopal Iyer 	map_to_units(buf->l_packets, sizeof (buf->l_packets),
1165*0dc2366fSVenugopal Iyer 	    link_stats->rl_ipackets, unit, parsable);
1166*0dc2366fSVenugopal Iyer 
1167*0dc2366fSVenugopal Iyer 	map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1168*0dc2366fSVenugopal Iyer 	    link_stats->rl_rbytes, unit, parsable);
1169*0dc2366fSVenugopal Iyer 
1170*0dc2366fSVenugopal Iyer done:
1171*0dc2366fSVenugopal Iyer 	return (buf);
1172*0dc2366fSVenugopal Iyer }
1173*0dc2366fSVenugopal Iyer 
1174*0dc2366fSVenugopal Iyer void *
print_tx_generic_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1175*0dc2366fSVenugopal Iyer print_tx_generic_lane_stats(const char *linkname, void *statentry, char unit,
1176*0dc2366fSVenugopal Iyer     boolean_t parsable)
1177*0dc2366fSVenugopal Iyer {
1178*0dc2366fSVenugopal Iyer 	tx_lane_stat_entry_t	*sentry = statentry;
1179*0dc2366fSVenugopal Iyer 	tx_lane_stat_t		*link_stats = &sentry->tle_stats;
1180*0dc2366fSVenugopal Iyer 	lane_fields_buf_t	*buf;
1181*0dc2366fSVenugopal Iyer 
1182*0dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_DFNCT)
1183*0dc2366fSVenugopal Iyer 		return (NULL);
1184*0dc2366fSVenugopal Iyer 
1185*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (lane_fields_buf_t));
1186*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1187*0dc2366fSVenugopal Iyer 		goto done;
1188*0dc2366fSVenugopal Iyer 
1189*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1190*0dc2366fSVenugopal Iyer 	    linkname);
1191*0dc2366fSVenugopal Iyer 
1192*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->l_type, sizeof (buf->l_type), "tx");
1193*0dc2366fSVenugopal Iyer 
1194*0dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_HWLANE)
1195*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1196*0dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_SWLANE)
1197*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "sw");
1198*0dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_BCAST)
1199*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "bcast");
1200*0dc2366fSVenugopal Iyer 	else
1201*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1202*0dc2366fSVenugopal Iyer 
1203*0dc2366fSVenugopal Iyer 	if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
1204*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1205*0dc2366fSVenugopal Iyer 	} else {
1206*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->l_index, sizeof (buf->l_index),
1207*0dc2366fSVenugopal Iyer 		    "%llu", sentry->tle_index);
1208*0dc2366fSVenugopal Iyer 	}
1209*0dc2366fSVenugopal Iyer 	map_to_units(buf->l_packets, sizeof (buf->l_packets),
1210*0dc2366fSVenugopal Iyer 	    link_stats->tl_opackets, unit, parsable);
1211*0dc2366fSVenugopal Iyer 
1212*0dc2366fSVenugopal Iyer 	map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1213*0dc2366fSVenugopal Iyer 	    link_stats->tl_obytes, unit, parsable);
1214*0dc2366fSVenugopal Iyer 
1215*0dc2366fSVenugopal Iyer done:
1216*0dc2366fSVenugopal Iyer 	return (buf);
1217*0dc2366fSVenugopal Iyer }
1218*0dc2366fSVenugopal Iyer 
1219*0dc2366fSVenugopal Iyer void *
print_rx_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1220*0dc2366fSVenugopal Iyer print_rx_lane_stats(const char *linkname, void *statentry, char unit,
1221*0dc2366fSVenugopal Iyer     boolean_t parsable)
1222*0dc2366fSVenugopal Iyer {
1223*0dc2366fSVenugopal Iyer 	rx_lane_stat_entry_t	*sentry = statentry;
1224*0dc2366fSVenugopal Iyer 	rx_lane_stat_t		*link_stats = &sentry->rle_stats;
1225*0dc2366fSVenugopal Iyer 	rx_lane_fields_buf_t	*buf;
1226*0dc2366fSVenugopal Iyer 
1227*0dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_DFNCT)
1228*0dc2366fSVenugopal Iyer 		return (NULL);
1229*0dc2366fSVenugopal Iyer 
1230*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (rx_lane_fields_buf_t));
1231*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1232*0dc2366fSVenugopal Iyer 		goto done;
1233*0dc2366fSVenugopal Iyer 
1234*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->rl_linkname, sizeof (buf->rl_linkname), "%s",
1235*0dc2366fSVenugopal Iyer 	    linkname);
1236*0dc2366fSVenugopal Iyer 
1237*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->rl_type, sizeof (buf->rl_type), "rx");
1238*0dc2366fSVenugopal Iyer 
1239*0dc2366fSVenugopal Iyer 	if (sentry->rle_id == L_HWLANE)
1240*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "hw");
1241*0dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_SWLANE)
1242*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "sw");
1243*0dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_LOCAL)
1244*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "local");
1245*0dc2366fSVenugopal Iyer 	else if (sentry->rle_id == L_BCAST)
1246*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "bcast");
1247*0dc2366fSVenugopal Iyer 	else
1248*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_id, sizeof (buf->rl_id), "--");
1249*0dc2366fSVenugopal Iyer 
1250*0dc2366fSVenugopal Iyer 	if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
1251*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_index, sizeof (buf->rl_index), "--");
1252*0dc2366fSVenugopal Iyer 	} else {
1253*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rl_index, sizeof (buf->rl_index),
1254*0dc2366fSVenugopal Iyer 		    "%llu", sentry->rle_index);
1255*0dc2366fSVenugopal Iyer 	}
1256*0dc2366fSVenugopal Iyer 
1257*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_ipackets, sizeof (buf->rl_ipackets),
1258*0dc2366fSVenugopal Iyer 	    link_stats->rl_ipackets, unit, parsable);
1259*0dc2366fSVenugopal Iyer 
1260*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_rbytes, sizeof (buf->rl_rbytes),
1261*0dc2366fSVenugopal Iyer 	    link_stats->rl_rbytes, unit, parsable);
1262*0dc2366fSVenugopal Iyer 
1263*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_intrs, sizeof (buf->rl_intrs),
1264*0dc2366fSVenugopal Iyer 	    link_stats->rl_intrs, unit, parsable);
1265*0dc2366fSVenugopal Iyer 
1266*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_polls, sizeof (buf->rl_polls),
1267*0dc2366fSVenugopal Iyer 	    link_stats->rl_polls, unit, parsable);
1268*0dc2366fSVenugopal Iyer 
1269*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_sdrops, sizeof (buf->rl_sdrops),
1270*0dc2366fSVenugopal Iyer 	    link_stats->rl_sdrops, unit, parsable);
1271*0dc2366fSVenugopal Iyer 
1272*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_chl10, sizeof (buf->rl_chl10),
1273*0dc2366fSVenugopal Iyer 	    link_stats->rl_chl10, unit, parsable);
1274*0dc2366fSVenugopal Iyer 
1275*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_ch10_50, sizeof (buf->rl_ch10_50),
1276*0dc2366fSVenugopal Iyer 	    link_stats->rl_ch10_50, unit, parsable);
1277*0dc2366fSVenugopal Iyer 
1278*0dc2366fSVenugopal Iyer 	map_to_units(buf->rl_chg50, sizeof (buf->rl_chg50),
1279*0dc2366fSVenugopal Iyer 	    link_stats->rl_chg50, unit, parsable);
1280*0dc2366fSVenugopal Iyer 
1281*0dc2366fSVenugopal Iyer done:
1282*0dc2366fSVenugopal Iyer 	return (buf);
1283*0dc2366fSVenugopal Iyer }
1284*0dc2366fSVenugopal Iyer 
1285*0dc2366fSVenugopal Iyer void *
print_tx_lane_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1286*0dc2366fSVenugopal Iyer print_tx_lane_stats(const char *linkname, void *statentry, char unit,
1287*0dc2366fSVenugopal Iyer     boolean_t parsable)
1288*0dc2366fSVenugopal Iyer {
1289*0dc2366fSVenugopal Iyer 	tx_lane_stat_entry_t	*sentry = statentry;
1290*0dc2366fSVenugopal Iyer 	tx_lane_stat_t		*link_stats = &sentry->tle_stats;
1291*0dc2366fSVenugopal Iyer 	tx_lane_fields_buf_t	*buf = NULL;
1292*0dc2366fSVenugopal Iyer 
1293*0dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_DFNCT)
1294*0dc2366fSVenugopal Iyer 		return (NULL);
1295*0dc2366fSVenugopal Iyer 
1296*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (tx_lane_fields_buf_t));
1297*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1298*0dc2366fSVenugopal Iyer 		goto done;
1299*0dc2366fSVenugopal Iyer 
1300*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->tl_linkname, sizeof (buf->tl_linkname), "%s",
1301*0dc2366fSVenugopal Iyer 	    linkname);
1302*0dc2366fSVenugopal Iyer 
1303*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->tl_type, sizeof (buf->tl_type), "tx");
1304*0dc2366fSVenugopal Iyer 
1305*0dc2366fSVenugopal Iyer 	if (sentry->tle_id == L_HWLANE)
1306*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "hw");
1307*0dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_SWLANE)
1308*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "sw");
1309*0dc2366fSVenugopal Iyer 	else if (sentry->tle_id == L_BCAST)
1310*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "bcast");
1311*0dc2366fSVenugopal Iyer 	else
1312*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_id, sizeof (buf->tl_id), "--");
1313*0dc2366fSVenugopal Iyer 
1314*0dc2366fSVenugopal Iyer 	if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
1315*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_index, sizeof (buf->tl_index), "--");
1316*0dc2366fSVenugopal Iyer 	} else {
1317*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->tl_index, sizeof (buf->tl_index),
1318*0dc2366fSVenugopal Iyer 		    "%llu", sentry->tle_index);
1319*0dc2366fSVenugopal Iyer 	}
1320*0dc2366fSVenugopal Iyer 
1321*0dc2366fSVenugopal Iyer 	map_to_units(buf->tl_opackets, sizeof (buf->tl_opackets),
1322*0dc2366fSVenugopal Iyer 	    link_stats->tl_opackets, unit, parsable);
1323*0dc2366fSVenugopal Iyer 
1324*0dc2366fSVenugopal Iyer 	map_to_units(buf->tl_obytes, sizeof (buf->tl_obytes),
1325*0dc2366fSVenugopal Iyer 	    link_stats->tl_obytes, unit, parsable);
1326*0dc2366fSVenugopal Iyer 
1327*0dc2366fSVenugopal Iyer 	map_to_units(buf->tl_blockcnt, sizeof (buf->tl_blockcnt),
1328*0dc2366fSVenugopal Iyer 	    link_stats->tl_blockcnt, unit, parsable);
1329*0dc2366fSVenugopal Iyer 
1330*0dc2366fSVenugopal Iyer 	map_to_units(buf->tl_unblockcnt, sizeof (buf->tl_unblockcnt),
1331*0dc2366fSVenugopal Iyer 	    link_stats->tl_unblockcnt, unit, parsable);
1332*0dc2366fSVenugopal Iyer 
1333*0dc2366fSVenugopal Iyer 	map_to_units(buf->tl_sdrops, sizeof (buf->tl_sdrops),
1334*0dc2366fSVenugopal Iyer 	    link_stats->tl_sdrops, unit, parsable);
1335*0dc2366fSVenugopal Iyer 
1336*0dc2366fSVenugopal Iyer done:
1337*0dc2366fSVenugopal Iyer 	return (buf);
1338*0dc2366fSVenugopal Iyer }
1339*0dc2366fSVenugopal Iyer 
1340*0dc2366fSVenugopal Iyer void *
print_fanout_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1341*0dc2366fSVenugopal Iyer print_fanout_stats(const char *linkname, void *statentry, char unit,
1342*0dc2366fSVenugopal Iyer     boolean_t parsable)
1343*0dc2366fSVenugopal Iyer {
1344*0dc2366fSVenugopal Iyer 	fanout_stat_entry_t		*sentry = statentry;
1345*0dc2366fSVenugopal Iyer 	fanout_stat_t			*link_stats = &sentry->fe_stats;
1346*0dc2366fSVenugopal Iyer 	rx_fanout_lane_fields_buf_t	*buf;
1347*0dc2366fSVenugopal Iyer 
1348*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (rx_fanout_lane_fields_buf_t));
1349*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1350*0dc2366fSVenugopal Iyer 		goto done;
1351*0dc2366fSVenugopal Iyer 
1352*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->rfl_linkname, sizeof (buf->rfl_linkname), "%s",
1353*0dc2366fSVenugopal Iyer 	    linkname);
1354*0dc2366fSVenugopal Iyer 
1355*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->rfl_type, sizeof (buf->rfl_type), "rx");
1356*0dc2366fSVenugopal Iyer 
1357*0dc2366fSVenugopal Iyer 	if (sentry->fe_id == L_HWLANE)
1358*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "hw");
1359*0dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_SWLANE)
1360*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "sw");
1361*0dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_LCLSWLANE)
1362*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "lcl/sw");
1363*0dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_LOCAL)
1364*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "local");
1365*0dc2366fSVenugopal Iyer 	else if (sentry->fe_id == L_BCAST)
1366*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "bcast");
1367*0dc2366fSVenugopal Iyer 	else
1368*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "--");
1369*0dc2366fSVenugopal Iyer 
1370*0dc2366fSVenugopal Iyer 	if (sentry->fe_index == DLSTAT_INVALID_ENTRY) {
1371*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_index, sizeof (buf->rfl_index), "--");
1372*0dc2366fSVenugopal Iyer 	} else {
1373*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_index, sizeof (buf->rfl_index),
1374*0dc2366fSVenugopal Iyer 		    "%llu", sentry->fe_index);
1375*0dc2366fSVenugopal Iyer 	}
1376*0dc2366fSVenugopal Iyer 
1377*0dc2366fSVenugopal Iyer 	if (sentry->fe_foutindex == DLSTAT_INVALID_ENTRY)
1378*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "--");
1379*0dc2366fSVenugopal Iyer 	else {
1380*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "%llu",
1381*0dc2366fSVenugopal Iyer 		    sentry->fe_foutindex);
1382*0dc2366fSVenugopal Iyer 	}
1383*0dc2366fSVenugopal Iyer 
1384*0dc2366fSVenugopal Iyer 	map_to_units(buf->rfl_ipackets, sizeof (buf->rfl_ipackets),
1385*0dc2366fSVenugopal Iyer 	    link_stats->f_ipackets, unit, parsable);
1386*0dc2366fSVenugopal Iyer 
1387*0dc2366fSVenugopal Iyer 	map_to_units(buf->rfl_rbytes, sizeof (buf->rfl_rbytes),
1388*0dc2366fSVenugopal Iyer 	    link_stats->f_rbytes, unit, parsable);
1389*0dc2366fSVenugopal Iyer 
1390*0dc2366fSVenugopal Iyer done:
1391*0dc2366fSVenugopal Iyer 	return (buf);
1392*0dc2366fSVenugopal Iyer }
1393*0dc2366fSVenugopal Iyer 
1394*0dc2366fSVenugopal Iyer void *
print_aggr_port_stats(const char * linkname,void * statentry,char unit,boolean_t parsable)1395*0dc2366fSVenugopal Iyer print_aggr_port_stats(const char *linkname, void *statentry, char unit,
1396*0dc2366fSVenugopal Iyer     boolean_t parsable)
1397*0dc2366fSVenugopal Iyer {
1398*0dc2366fSVenugopal Iyer 	aggr_port_stat_entry_t	*sentry = statentry;
1399*0dc2366fSVenugopal Iyer 	aggr_port_stat_t	*link_stats = &sentry->ape_stats;
1400*0dc2366fSVenugopal Iyer 	aggr_port_fields_buf_t	*buf;
1401*0dc2366fSVenugopal Iyer 	char			portname[MAXLINKNAMELEN];
1402*0dc2366fSVenugopal Iyer 
1403*0dc2366fSVenugopal Iyer 	buf = malloc(sizeof (aggr_port_fields_buf_t));
1404*0dc2366fSVenugopal Iyer 	if (buf == NULL)
1405*0dc2366fSVenugopal Iyer 		goto done;
1406*0dc2366fSVenugopal Iyer 
1407*0dc2366fSVenugopal Iyer 	(void) snprintf(buf->ap_linkname, sizeof (buf->ap_linkname), "%s",
1408*0dc2366fSVenugopal Iyer 	    linkname);
1409*0dc2366fSVenugopal Iyer 
1410*0dc2366fSVenugopal Iyer 	if (dladm_datalink_id2info(handle, sentry->ape_portlinkid, NULL,
1411*0dc2366fSVenugopal Iyer 	    NULL, NULL, portname, DLPI_LINKNAME_MAX)
1412*0dc2366fSVenugopal Iyer 	    != DLADM_STATUS_OK) {
1413*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->ap_portname,
1414*0dc2366fSVenugopal Iyer 		    sizeof (buf->ap_portname), "--");
1415*0dc2366fSVenugopal Iyer 	} else {
1416*0dc2366fSVenugopal Iyer 		(void) snprintf(buf->ap_portname,
1417*0dc2366fSVenugopal Iyer 		    sizeof (buf->ap_portname), "%s", portname);
1418*0dc2366fSVenugopal Iyer 	}
1419*0dc2366fSVenugopal Iyer 
1420*0dc2366fSVenugopal Iyer 	map_to_units(buf->ap_ipackets, sizeof (buf->ap_ipackets),
1421*0dc2366fSVenugopal Iyer 	    link_stats->ap_ipackets, unit, parsable);
1422*0dc2366fSVenugopal Iyer 
1423*0dc2366fSVenugopal Iyer 	map_to_units(buf->ap_rbytes, sizeof (buf->ap_rbytes),
1424*0dc2366fSVenugopal Iyer 	    link_stats->ap_rbytes, unit, parsable);
1425*0dc2366fSVenugopal Iyer 
1426*0dc2366fSVenugopal Iyer 	map_to_units(buf->ap_opackets, sizeof (buf->ap_opackets),
1427*0dc2366fSVenugopal Iyer 	    link_stats->ap_opackets, unit, parsable);
1428*0dc2366fSVenugopal Iyer 
1429*0dc2366fSVenugopal Iyer 	map_to_units(buf->ap_obytes, sizeof (buf->ap_obytes),
1430*0dc2366fSVenugopal Iyer 	    link_stats->ap_obytes, unit, parsable);
1431*0dc2366fSVenugopal Iyer 
1432*0dc2366fSVenugopal Iyer done:
1433*0dc2366fSVenugopal Iyer 	return (buf);
1434*0dc2366fSVenugopal Iyer }
1435*0dc2366fSVenugopal Iyer 
1436*0dc2366fSVenugopal Iyer dladm_stat_chain_t *
query_link_stats(dladm_handle_t dh,datalink_id_t linkid,void * arg,dladm_stat_type_t stattype)1437*0dc2366fSVenugopal Iyer query_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg,
1438*0dc2366fSVenugopal Iyer     dladm_stat_type_t stattype)
1439*0dc2366fSVenugopal Iyer {
1440*0dc2366fSVenugopal Iyer 	link_chain_t		*link_node;
1441*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*curr_stat;
1442*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*prev_stat = NULL;
1443*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*diff_stat = NULL;
1444*0dc2366fSVenugopal Iyer 
1445*0dc2366fSVenugopal Iyer 	/*  Get prev iteration stat for this link */
1446*0dc2366fSVenugopal Iyer 	link_node = get_link_prev_stat(linkid, arg);
1447*0dc2366fSVenugopal Iyer 	if (link_node == NULL)
1448*0dc2366fSVenugopal Iyer 		goto done;
1449*0dc2366fSVenugopal Iyer 
1450*0dc2366fSVenugopal Iyer 	link_node->lc_visited = B_TRUE;
1451*0dc2366fSVenugopal Iyer 	prev_stat = link_node->lc_statchain[stattype];
1452*0dc2366fSVenugopal Iyer 
1453*0dc2366fSVenugopal Iyer 	/* Query library for current stats */
1454*0dc2366fSVenugopal Iyer 	curr_stat = dladm_link_stat_query(dh, linkid, stattype);
1455*0dc2366fSVenugopal Iyer 	if (curr_stat == NULL)
1456*0dc2366fSVenugopal Iyer 		goto done;
1457*0dc2366fSVenugopal Iyer 
1458*0dc2366fSVenugopal Iyer 	/* current stats - prev iteration stats */
1459*0dc2366fSVenugopal Iyer 	diff_stat = dladm_link_stat_diffchain(curr_stat, prev_stat, stattype);
1460*0dc2366fSVenugopal Iyer 
1461*0dc2366fSVenugopal Iyer 	/* Free prev stats */
1462*0dc2366fSVenugopal Iyer 	dladm_link_stat_free(prev_stat);
1463*0dc2366fSVenugopal Iyer 
1464*0dc2366fSVenugopal Iyer 	/* Prev <- curr stats */
1465*0dc2366fSVenugopal Iyer 	link_node->lc_statchain[stattype] = curr_stat;
1466*0dc2366fSVenugopal Iyer 
1467*0dc2366fSVenugopal Iyer done:
1468*0dc2366fSVenugopal Iyer 	return (diff_stat);
1469*0dc2366fSVenugopal Iyer }
1470*0dc2366fSVenugopal Iyer 
1471*0dc2366fSVenugopal Iyer void
walk_dlstat_stats(show_state_t * state,const char * linkname,dladm_stat_type_t stattype,dladm_stat_chain_t * diff_stat)1472*0dc2366fSVenugopal Iyer walk_dlstat_stats(show_state_t *state, const char *linkname,
1473*0dc2366fSVenugopal Iyer     dladm_stat_type_t stattype, dladm_stat_chain_t *diff_stat)
1474*0dc2366fSVenugopal Iyer {
1475*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t  *curr;
1476*0dc2366fSVenugopal Iyer 
1477*0dc2366fSVenugopal Iyer 	/* Unpack invidual stat entry and call library consumer's callback */
1478*0dc2366fSVenugopal Iyer 	for (curr = diff_stat; curr != NULL; curr = curr->dc_next) {
1479*0dc2366fSVenugopal Iyer 		void	*fields_buf;
1480*0dc2366fSVenugopal Iyer 
1481*0dc2366fSVenugopal Iyer 		/* Format the raw numbers for printing */
1482*0dc2366fSVenugopal Iyer 		fields_buf = state->ls_stats2str[stattype](linkname,
1483*0dc2366fSVenugopal Iyer 		    curr->dc_statentry, state->ls_unit, state->ls_parsable);
1484*0dc2366fSVenugopal Iyer 		/* Print the stats */
1485*0dc2366fSVenugopal Iyer 		if (fields_buf != NULL)
1486*0dc2366fSVenugopal Iyer 			ofmt_print(state->ls_ofmt, fields_buf);
1487*0dc2366fSVenugopal Iyer 		free(fields_buf);
1488*0dc2366fSVenugopal Iyer 	}
1489*0dc2366fSVenugopal Iyer }
1490*0dc2366fSVenugopal Iyer 
1491*0dc2366fSVenugopal Iyer static int
show_queried_stats(dladm_handle_t dh,datalink_id_t linkid,void * arg)1492*0dc2366fSVenugopal Iyer show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1493*0dc2366fSVenugopal Iyer {
1494*0dc2366fSVenugopal Iyer 	show_state_t		*state = arg;
1495*0dc2366fSVenugopal Iyer 	int 			i;
1496*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*diff_stat;
1497*0dc2366fSVenugopal Iyer 	char			linkname[DLPI_LINKNAME_MAX];
1498*0dc2366fSVenugopal Iyer 
1499*0dc2366fSVenugopal Iyer 	if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1500*0dc2366fSVenugopal Iyer 	    DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
1501*0dc2366fSVenugopal Iyer 		goto done;
1502*0dc2366fSVenugopal Iyer 	}
1503*0dc2366fSVenugopal Iyer 
1504*0dc2366fSVenugopal Iyer 	for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
1505*0dc2366fSVenugopal Iyer 		if (state->ls_stattype[i]) {
1506*0dc2366fSVenugopal Iyer 			/*
1507*0dc2366fSVenugopal Iyer 			 * Query library for stats
1508*0dc2366fSVenugopal Iyer 			 * Stats are returned as chain of raw numbers
1509*0dc2366fSVenugopal Iyer 			 */
1510*0dc2366fSVenugopal Iyer 			diff_stat = query_link_stats(handle, linkid, arg, i);
1511*0dc2366fSVenugopal Iyer 			walk_dlstat_stats(state, linkname, i, diff_stat);
1512*0dc2366fSVenugopal Iyer 			dladm_link_stat_free(diff_stat);
1513*0dc2366fSVenugopal Iyer 		}
1514*0dc2366fSVenugopal Iyer 	}
1515*0dc2366fSVenugopal Iyer done:
1516*0dc2366fSVenugopal Iyer 	return (DLADM_WALK_CONTINUE);
1517*0dc2366fSVenugopal Iyer }
1518*0dc2366fSVenugopal Iyer 
1519*0dc2366fSVenugopal Iyer void
show_link_stats(datalink_id_t linkid,show_state_t state,uint32_t interval)1520*0dc2366fSVenugopal Iyer show_link_stats(datalink_id_t linkid, show_state_t state, uint32_t interval)
1521*0dc2366fSVenugopal Iyer {
1522*0dc2366fSVenugopal Iyer 	for (;;) {
1523*0dc2366fSVenugopal Iyer 		if (linkid == DATALINK_ALL_LINKID) {
1524*0dc2366fSVenugopal Iyer 			(void) dladm_walk_datalink_id(show_queried_stats,
1525*0dc2366fSVenugopal Iyer 			    handle, &state, DATALINK_CLASS_ALL,
1526*0dc2366fSVenugopal Iyer 			    DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1527*0dc2366fSVenugopal Iyer 		} else {
1528*0dc2366fSVenugopal Iyer 			(void) show_queried_stats(handle, linkid, &state);
1529*0dc2366fSVenugopal Iyer 		}
1530*0dc2366fSVenugopal Iyer 
1531*0dc2366fSVenugopal Iyer 		if (interval == 0)
1532*0dc2366fSVenugopal Iyer 			break;
1533*0dc2366fSVenugopal Iyer 
1534*0dc2366fSVenugopal Iyer 		cleanup_removed_links(&state);
1535*0dc2366fSVenugopal Iyer 		(void) sleep(interval);
1536*0dc2366fSVenugopal Iyer 	}
1537*0dc2366fSVenugopal Iyer }
1538*0dc2366fSVenugopal Iyer 
1539*0dc2366fSVenugopal Iyer void
print_all_stats(dladm_handle_t dh,datalink_id_t linkid,dladm_stat_chain_t * stat_chain)1540*0dc2366fSVenugopal Iyer print_all_stats(dladm_handle_t dh, datalink_id_t linkid,
1541*0dc2366fSVenugopal Iyer     dladm_stat_chain_t *stat_chain)
1542*0dc2366fSVenugopal Iyer {
1543*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*curr;
1544*0dc2366fSVenugopal Iyer 	name_value_stat_entry_t	*stat_entry;
1545*0dc2366fSVenugopal Iyer 	name_value_stat_t	*curr_stat;
1546*0dc2366fSVenugopal Iyer 	boolean_t		stat_printed = B_FALSE;
1547*0dc2366fSVenugopal Iyer 	char			linkname[MAXLINKNAMELEN];
1548*0dc2366fSVenugopal Iyer 	char			prev_linkname[MAXLINKNAMELEN];
1549*0dc2366fSVenugopal Iyer 
1550*0dc2366fSVenugopal Iyer 	if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1551*0dc2366fSVenugopal Iyer 	    DLPI_LINKNAME_MAX) != DLADM_STATUS_OK)
1552*0dc2366fSVenugopal Iyer 		return;
1553*0dc2366fSVenugopal Iyer 
1554*0dc2366fSVenugopal Iyer 	for (curr = stat_chain; curr != NULL; curr = curr->dc_next) {
1555*0dc2366fSVenugopal Iyer 		stat_entry = curr->dc_statentry;
1556*0dc2366fSVenugopal Iyer 		/*
1557*0dc2366fSVenugopal Iyer 		 * Print header
1558*0dc2366fSVenugopal Iyer 		 * If link name is already printed in previous iteration,
1559*0dc2366fSVenugopal Iyer 		 * don't print again
1560*0dc2366fSVenugopal Iyer 		 */
1561*0dc2366fSVenugopal Iyer 		if (strcmp(prev_linkname, linkname) != 0)
1562*0dc2366fSVenugopal Iyer 			printf("%s \n", linkname);
1563*0dc2366fSVenugopal Iyer 		printf("  %s \n", stat_entry->nve_header);
1564*0dc2366fSVenugopal Iyer 
1565*0dc2366fSVenugopal Iyer 		/* Print stat fields */
1566*0dc2366fSVenugopal Iyer 		for (curr_stat = stat_entry->nve_stats; curr_stat != NULL;
1567*0dc2366fSVenugopal Iyer 		    curr_stat = curr_stat->nv_nextstat) {
1568*0dc2366fSVenugopal Iyer 			printf("\t%15s", curr_stat->nv_statname);
1569*0dc2366fSVenugopal Iyer 			printf("\t\t%15llu\n", curr_stat->nv_statval);
1570*0dc2366fSVenugopal Iyer 		}
1571*0dc2366fSVenugopal Iyer 
1572*0dc2366fSVenugopal Iyer 		strncpy(prev_linkname, linkname, MAXLINKNAMELEN);
1573*0dc2366fSVenugopal Iyer 		stat_printed = B_TRUE;
1574*0dc2366fSVenugopal Iyer 	}
1575*0dc2366fSVenugopal Iyer 	if (stat_printed)
1576*0dc2366fSVenugopal Iyer 		printf("---------------------------------------------------\n");
1577*0dc2366fSVenugopal Iyer }
1578*0dc2366fSVenugopal Iyer 
1579*0dc2366fSVenugopal Iyer static int
dump_queried_stats(dladm_handle_t dh,datalink_id_t linkid,void * arg)1580*0dc2366fSVenugopal Iyer dump_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1581*0dc2366fSVenugopal Iyer {
1582*0dc2366fSVenugopal Iyer 	boolean_t		*stattype = arg;
1583*0dc2366fSVenugopal Iyer 	int			i;
1584*0dc2366fSVenugopal Iyer 	dladm_stat_chain_t	*stat_chain;
1585*0dc2366fSVenugopal Iyer 
1586*0dc2366fSVenugopal Iyer 	for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
1587*0dc2366fSVenugopal Iyer 		if (stattype[i]) {
1588*0dc2366fSVenugopal Iyer 			stat_chain = dladm_link_stat_query_all(dh, linkid, i);
1589*0dc2366fSVenugopal Iyer 			print_all_stats(dh, linkid, stat_chain);
1590*0dc2366fSVenugopal Iyer 			dladm_link_stat_query_all_free(stat_chain);
1591*0dc2366fSVenugopal Iyer 		}
1592*0dc2366fSVenugopal Iyer 	}
1593*0dc2366fSVenugopal Iyer done:
1594*0dc2366fSVenugopal Iyer 	return (DLADM_WALK_CONTINUE);
1595*0dc2366fSVenugopal Iyer }
1596*0dc2366fSVenugopal Iyer 
1597*0dc2366fSVenugopal Iyer void
dump_all_link_stats(datalink_id_t linkid,boolean_t * stattype)1598*0dc2366fSVenugopal Iyer dump_all_link_stats(datalink_id_t linkid, boolean_t *stattype)
1599*0dc2366fSVenugopal Iyer {
1600*0dc2366fSVenugopal Iyer 	if (linkid == DATALINK_ALL_LINKID) {
1601*0dc2366fSVenugopal Iyer 		(void) dladm_walk_datalink_id(dump_queried_stats,
1602*0dc2366fSVenugopal Iyer 		    handle, stattype, DATALINK_CLASS_ALL,
1603*0dc2366fSVenugopal Iyer 		    DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1604*0dc2366fSVenugopal Iyer 	} else {
1605*0dc2366fSVenugopal Iyer 		(void) dump_queried_stats(handle, linkid, stattype);
1606*0dc2366fSVenugopal Iyer 	}
1607*0dc2366fSVenugopal Iyer }
1608*0dc2366fSVenugopal Iyer 
1609*0dc2366fSVenugopal Iyer static void
do_show(int argc,char * argv[],const char * use)1610*0dc2366fSVenugopal Iyer do_show(int argc, char *argv[], const char *use)
1611*0dc2366fSVenugopal Iyer {
1612*0dc2366fSVenugopal Iyer 	int			option;
1613*0dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
1614*0dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
1615*0dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
1616*0dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
1617*0dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
1618*0dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
1619*0dc2366fSVenugopal Iyer 	boolean_t		a_arg = B_FALSE;
1620*0dc2366fSVenugopal Iyer 	boolean_t		A_arg = B_FALSE;
1621*0dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
1622*0dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
1623*0dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
1624*0dc2366fSVenugopal Iyer 	char			unit = '\0';
1625*0dc2366fSVenugopal Iyer 	show_state_t		state;
1626*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
1627*0dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
1628*0dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
1629*0dc2366fSVenugopal Iyer 
1630*0dc2366fSVenugopal Iyer 	char			*total_stat_fields =
1631*0dc2366fSVenugopal Iyer 	    "link,ipkts,rbytes,opkts,obytes";
1632*0dc2366fSVenugopal Iyer 	char			*rx_total_stat_fields =
1633*0dc2366fSVenugopal Iyer 	    "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
1634*0dc2366fSVenugopal Iyer 	char			*tx_total_stat_fields =
1635*0dc2366fSVenugopal Iyer 	    "link,opkts,obytes,blkcnt,ublkcnt";
1636*0dc2366fSVenugopal Iyer 
1637*0dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
1638*0dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
1639*0dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
1640*0dc2366fSVenugopal Iyer 	ofmt_field_t 		*oftemplate;
1641*0dc2366fSVenugopal Iyer 
1642*0dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
1643*0dc2366fSVenugopal Iyer 	opterr = 0;
1644*0dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":rtaApi:o:u:",
1645*0dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
1646*0dc2366fSVenugopal Iyer 		switch (option) {
1647*0dc2366fSVenugopal Iyer 		case 'r':
1648*0dc2366fSVenugopal Iyer 			if (r_arg)
1649*0dc2366fSVenugopal Iyer 				die_optdup(option);
1650*0dc2366fSVenugopal Iyer 
1651*0dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
1652*0dc2366fSVenugopal Iyer 			break;
1653*0dc2366fSVenugopal Iyer 		case 't':
1654*0dc2366fSVenugopal Iyer 			if (t_arg)
1655*0dc2366fSVenugopal Iyer 				die_optdup(option);
1656*0dc2366fSVenugopal Iyer 
1657*0dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
1658*0dc2366fSVenugopal Iyer 			break;
1659*0dc2366fSVenugopal Iyer 		case 'a':
1660*0dc2366fSVenugopal Iyer 			if (a_arg)
1661*0dc2366fSVenugopal Iyer 				die_optdup(option);
1662*0dc2366fSVenugopal Iyer 
1663*0dc2366fSVenugopal Iyer 			a_arg = B_TRUE;
1664*0dc2366fSVenugopal Iyer 			break;
1665*0dc2366fSVenugopal Iyer 		case 'A':
1666*0dc2366fSVenugopal Iyer 			if (A_arg)
1667*0dc2366fSVenugopal Iyer 				die_optdup(option);
1668*0dc2366fSVenugopal Iyer 
1669*0dc2366fSVenugopal Iyer 			A_arg = B_TRUE;
1670*0dc2366fSVenugopal Iyer 			break;
1671*0dc2366fSVenugopal Iyer 		case 'i':
1672*0dc2366fSVenugopal Iyer 			if (i_arg)
1673*0dc2366fSVenugopal Iyer 				die_optdup(option);
1674*0dc2366fSVenugopal Iyer 
1675*0dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
1676*0dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
1677*0dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
1678*0dc2366fSVenugopal Iyer 			break;
1679*0dc2366fSVenugopal Iyer 		case 'p':
1680*0dc2366fSVenugopal Iyer 			if (p_arg)
1681*0dc2366fSVenugopal Iyer 				die_optdup(option);
1682*0dc2366fSVenugopal Iyer 
1683*0dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
1684*0dc2366fSVenugopal Iyer 			break;
1685*0dc2366fSVenugopal Iyer 		case 'o':
1686*0dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
1687*0dc2366fSVenugopal Iyer 			o_fields_str = optarg;
1688*0dc2366fSVenugopal Iyer 			break;
1689*0dc2366fSVenugopal Iyer 		case 'u':
1690*0dc2366fSVenugopal Iyer 			if (u_arg)
1691*0dc2366fSVenugopal Iyer 				die_optdup(option);
1692*0dc2366fSVenugopal Iyer 
1693*0dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
1694*0dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
1695*0dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
1696*0dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
1697*0dc2366fSVenugopal Iyer 			break;
1698*0dc2366fSVenugopal Iyer 		default:
1699*0dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
1700*0dc2366fSVenugopal Iyer 			break;
1701*0dc2366fSVenugopal Iyer 		}
1702*0dc2366fSVenugopal Iyer 	}
1703*0dc2366fSVenugopal Iyer 
1704*0dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
1705*0dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
1706*0dc2366fSVenugopal Iyer 
1707*0dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
1708*0dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
1709*0dc2366fSVenugopal Iyer 
1710*0dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
1711*0dc2366fSVenugopal Iyer 		die("-p requires -o");
1712*0dc2366fSVenugopal Iyer 
1713*0dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
1714*0dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
1715*0dc2366fSVenugopal Iyer 
1716*0dc2366fSVenugopal Iyer 	if (a_arg && A_arg)
1717*0dc2366fSVenugopal Iyer 		die("the options -a and -A are not compatible");
1718*0dc2366fSVenugopal Iyer 
1719*0dc2366fSVenugopal Iyer 	if (a_arg &&
1720*0dc2366fSVenugopal Iyer 	    (p_arg || o_arg || u_arg || i_arg)) {
1721*0dc2366fSVenugopal Iyer 		die("the option -a is not compatible with "
1722*0dc2366fSVenugopal Iyer 		    "-p, -o, -u, -i");
1723*0dc2366fSVenugopal Iyer 	}
1724*0dc2366fSVenugopal Iyer 
1725*0dc2366fSVenugopal Iyer 	if (A_arg &&
1726*0dc2366fSVenugopal Iyer 	    (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg)) {
1727*0dc2366fSVenugopal Iyer 		die("the option -A is not compatible with "
1728*0dc2366fSVenugopal Iyer 		    "-r, -t, -p, -o, -u, -i");
1729*0dc2366fSVenugopal Iyer 	}
1730*0dc2366fSVenugopal Iyer 
1731*0dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
1732*0dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
1733*0dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
1734*0dc2366fSVenugopal Iyer 			die("link name too long");
1735*0dc2366fSVenugopal Iyer 
1736*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
1737*0dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
1738*0dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
1739*0dc2366fSVenugopal Iyer 		}
1740*0dc2366fSVenugopal Iyer 	} else if (optind != argc) {
1741*0dc2366fSVenugopal Iyer 		if (argc != 0)
1742*0dc2366fSVenugopal Iyer 			usage();
1743*0dc2366fSVenugopal Iyer 	}
1744*0dc2366fSVenugopal Iyer 
1745*0dc2366fSVenugopal Iyer 	if (a_arg) {
1746*0dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
1747*0dc2366fSVenugopal Iyer 
1748*0dc2366fSVenugopal Iyer 		bzero(&stattype, sizeof (stattype));
1749*0dc2366fSVenugopal Iyer 		if (r_arg) {
1750*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_LANE_TOTAL] = B_TRUE;
1751*0dc2366fSVenugopal Iyer 		} else if (t_arg) {
1752*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_LANE_TOTAL] = B_TRUE;
1753*0dc2366fSVenugopal Iyer 		} else {		/* Display both Rx and Tx lanes */
1754*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TOTAL] = B_TRUE;
1755*0dc2366fSVenugopal Iyer 		}
1756*0dc2366fSVenugopal Iyer 
1757*0dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
1758*0dc2366fSVenugopal Iyer 		return;
1759*0dc2366fSVenugopal Iyer 	}
1760*0dc2366fSVenugopal Iyer 
1761*0dc2366fSVenugopal Iyer 	if (A_arg) {
1762*0dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
1763*0dc2366fSVenugopal Iyer 		int		i;
1764*0dc2366fSVenugopal Iyer 
1765*0dc2366fSVenugopal Iyer 		for (i = 0; i < DLADM_STAT_NUM_STATS; i++)
1766*0dc2366fSVenugopal Iyer 			stattype[i] = B_TRUE;
1767*0dc2366fSVenugopal Iyer 
1768*0dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
1769*0dc2366fSVenugopal Iyer 		return;
1770*0dc2366fSVenugopal Iyer 	}
1771*0dc2366fSVenugopal Iyer 
1772*0dc2366fSVenugopal Iyer 	state.ls_unit = unit;
1773*0dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
1774*0dc2366fSVenugopal Iyer 
1775*0dc2366fSVenugopal Iyer 	if (state.ls_parsable)
1776*0dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
1777*0dc2366fSVenugopal Iyer 
1778*0dc2366fSVenugopal Iyer 	if (r_arg) {
1779*0dc2366fSVenugopal Iyer 		fields_str = rx_total_stat_fields;
1780*0dc2366fSVenugopal Iyer 		oftemplate = rx_lane_s_fields;
1781*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_LANE_TOTAL] = B_TRUE;
1782*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_LANE_TOTAL] =
1783*0dc2366fSVenugopal Iyer 		    print_rx_lane_stats;
1784*0dc2366fSVenugopal Iyer 	} else if (t_arg) {
1785*0dc2366fSVenugopal Iyer 		fields_str = tx_total_stat_fields;
1786*0dc2366fSVenugopal Iyer 		oftemplate = tx_lane_s_fields;
1787*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_LANE_TOTAL] = B_TRUE;
1788*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_LANE_TOTAL] =
1789*0dc2366fSVenugopal Iyer 		    print_tx_lane_stats;
1790*0dc2366fSVenugopal Iyer 	} else {		/* Display both Rx and Tx lanes total */
1791*0dc2366fSVenugopal Iyer 		fields_str = total_stat_fields;
1792*0dc2366fSVenugopal Iyer 		oftemplate = total_s_fields;
1793*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TOTAL] = B_TRUE;
1794*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TOTAL] = print_total_stats;
1795*0dc2366fSVenugopal Iyer 	}
1796*0dc2366fSVenugopal Iyer 
1797*0dc2366fSVenugopal Iyer 	if (o_arg) {
1798*0dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
1799*0dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
1800*0dc2366fSVenugopal Iyer 	}
1801*0dc2366fSVenugopal Iyer 
1802*0dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
1803*0dc2366fSVenugopal Iyer 	dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
1804*0dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
1805*0dc2366fSVenugopal Iyer 
1806*0dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
1807*0dc2366fSVenugopal Iyer 
1808*0dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
1809*0dc2366fSVenugopal Iyer }
1810*0dc2366fSVenugopal Iyer 
1811*0dc2366fSVenugopal Iyer static void
do_show_phys(int argc,char * argv[],const char * use)1812*0dc2366fSVenugopal Iyer do_show_phys(int argc, char *argv[], const char *use)
1813*0dc2366fSVenugopal Iyer {
1814*0dc2366fSVenugopal Iyer 	int			option;
1815*0dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
1816*0dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
1817*0dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
1818*0dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
1819*0dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
1820*0dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
1821*0dc2366fSVenugopal Iyer 	boolean_t		a_arg = B_FALSE;
1822*0dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
1823*0dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
1824*0dc2366fSVenugopal Iyer 	char			linkname[MAXLINKNAMELEN];
1825*0dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
1826*0dc2366fSVenugopal Iyer 	char			unit = '\0';
1827*0dc2366fSVenugopal Iyer 	show_state_t		state;
1828*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
1829*0dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
1830*0dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
1831*0dc2366fSVenugopal Iyer 	char			*ring_stat_fields =
1832*0dc2366fSVenugopal Iyer 	    "link,type,index,pkts,bytes";
1833*0dc2366fSVenugopal Iyer 	char			*rx_ring_stat_fields =
1834*0dc2366fSVenugopal Iyer 	    "link,type,index,ipkts,rbytes";
1835*0dc2366fSVenugopal Iyer 	char			*tx_ring_stat_fields =
1836*0dc2366fSVenugopal Iyer 	    "link,type,index,opkts,obytes";
1837*0dc2366fSVenugopal Iyer 
1838*0dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
1839*0dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
1840*0dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
1841*0dc2366fSVenugopal Iyer 	ofmt_field_t 		*oftemplate;
1842*0dc2366fSVenugopal Iyer 
1843*0dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
1844*0dc2366fSVenugopal Iyer 	opterr = 0;
1845*0dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":rtapi:o:u:",
1846*0dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
1847*0dc2366fSVenugopal Iyer 		switch (option) {
1848*0dc2366fSVenugopal Iyer 		case 'r':
1849*0dc2366fSVenugopal Iyer 			if (r_arg)
1850*0dc2366fSVenugopal Iyer 				die_optdup(option);
1851*0dc2366fSVenugopal Iyer 
1852*0dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
1853*0dc2366fSVenugopal Iyer 			break;
1854*0dc2366fSVenugopal Iyer 		case 't':
1855*0dc2366fSVenugopal Iyer 			if (t_arg)
1856*0dc2366fSVenugopal Iyer 				die_optdup(option);
1857*0dc2366fSVenugopal Iyer 
1858*0dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
1859*0dc2366fSVenugopal Iyer 			break;
1860*0dc2366fSVenugopal Iyer 		case 'a':
1861*0dc2366fSVenugopal Iyer 			if (a_arg)
1862*0dc2366fSVenugopal Iyer 				die_optdup(option);
1863*0dc2366fSVenugopal Iyer 
1864*0dc2366fSVenugopal Iyer 			a_arg = B_TRUE;
1865*0dc2366fSVenugopal Iyer 			break;
1866*0dc2366fSVenugopal Iyer 		case 'i':
1867*0dc2366fSVenugopal Iyer 			if (i_arg)
1868*0dc2366fSVenugopal Iyer 				die_optdup(option);
1869*0dc2366fSVenugopal Iyer 
1870*0dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
1871*0dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
1872*0dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
1873*0dc2366fSVenugopal Iyer 			break;
1874*0dc2366fSVenugopal Iyer 		case 'p':
1875*0dc2366fSVenugopal Iyer 			if (p_arg)
1876*0dc2366fSVenugopal Iyer 				die_optdup(option);
1877*0dc2366fSVenugopal Iyer 
1878*0dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
1879*0dc2366fSVenugopal Iyer 			break;
1880*0dc2366fSVenugopal Iyer 		case 'o':
1881*0dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
1882*0dc2366fSVenugopal Iyer 			o_fields_str = optarg;
1883*0dc2366fSVenugopal Iyer 			break;
1884*0dc2366fSVenugopal Iyer 		case 'u':
1885*0dc2366fSVenugopal Iyer 			if (u_arg)
1886*0dc2366fSVenugopal Iyer 				die_optdup(option);
1887*0dc2366fSVenugopal Iyer 
1888*0dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
1889*0dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
1890*0dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
1891*0dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
1892*0dc2366fSVenugopal Iyer 			break;
1893*0dc2366fSVenugopal Iyer 		default:
1894*0dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
1895*0dc2366fSVenugopal Iyer 			break;
1896*0dc2366fSVenugopal Iyer 		}
1897*0dc2366fSVenugopal Iyer 	}
1898*0dc2366fSVenugopal Iyer 
1899*0dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
1900*0dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
1901*0dc2366fSVenugopal Iyer 
1902*0dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
1903*0dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
1904*0dc2366fSVenugopal Iyer 
1905*0dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
1906*0dc2366fSVenugopal Iyer 		die("-p requires -o");
1907*0dc2366fSVenugopal Iyer 
1908*0dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
1909*0dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
1910*0dc2366fSVenugopal Iyer 
1911*0dc2366fSVenugopal Iyer 	if (a_arg &&
1912*0dc2366fSVenugopal Iyer 	    (p_arg || o_arg || u_arg || i_arg)) {
1913*0dc2366fSVenugopal Iyer 		die("the option -a is not compatible with "
1914*0dc2366fSVenugopal Iyer 		    "-p, -o, -u, -i");
1915*0dc2366fSVenugopal Iyer 	}
1916*0dc2366fSVenugopal Iyer 
1917*0dc2366fSVenugopal Iyer 
1918*0dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
1919*0dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
1920*0dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
1921*0dc2366fSVenugopal Iyer 			die("link name too long");
1922*0dc2366fSVenugopal Iyer 
1923*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
1924*0dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
1925*0dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
1926*0dc2366fSVenugopal Iyer 		}
1927*0dc2366fSVenugopal Iyer 	} else if (optind != argc) {
1928*0dc2366fSVenugopal Iyer 		usage();
1929*0dc2366fSVenugopal Iyer 	}
1930*0dc2366fSVenugopal Iyer 
1931*0dc2366fSVenugopal Iyer 	if (a_arg) {
1932*0dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
1933*0dc2366fSVenugopal Iyer 
1934*0dc2366fSVenugopal Iyer 		bzero(&stattype, sizeof (stattype));
1935*0dc2366fSVenugopal Iyer 
1936*0dc2366fSVenugopal Iyer 		if (r_arg) {
1937*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_RING] = B_TRUE;
1938*0dc2366fSVenugopal Iyer 		} else if (t_arg) {
1939*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_RING] = B_TRUE;
1940*0dc2366fSVenugopal Iyer 		} else {		/* Display both Rx and Tx lanes */
1941*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_RING] = B_TRUE;
1942*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_RING] = B_TRUE;
1943*0dc2366fSVenugopal Iyer 		}
1944*0dc2366fSVenugopal Iyer 
1945*0dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
1946*0dc2366fSVenugopal Iyer 		return;
1947*0dc2366fSVenugopal Iyer 	}
1948*0dc2366fSVenugopal Iyer 
1949*0dc2366fSVenugopal Iyer 	state.ls_unit = unit;
1950*0dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
1951*0dc2366fSVenugopal Iyer 
1952*0dc2366fSVenugopal Iyer 	if (state.ls_parsable)
1953*0dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
1954*0dc2366fSVenugopal Iyer 
1955*0dc2366fSVenugopal Iyer 	if (r_arg) {
1956*0dc2366fSVenugopal Iyer 		fields_str = rx_ring_stat_fields;
1957*0dc2366fSVenugopal Iyer 		oftemplate = rx_ring_s_fields;
1958*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_RING] = B_TRUE;
1959*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_RING] = print_rx_ring_stats;
1960*0dc2366fSVenugopal Iyer 	} else if (t_arg) {
1961*0dc2366fSVenugopal Iyer 		fields_str = tx_ring_stat_fields;
1962*0dc2366fSVenugopal Iyer 		oftemplate = tx_ring_s_fields;
1963*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_RING] = B_TRUE;
1964*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_RING] = print_tx_ring_stats;
1965*0dc2366fSVenugopal Iyer 	} else {		/* Display both Rx and Tx lanes */
1966*0dc2366fSVenugopal Iyer 		fields_str = ring_stat_fields;
1967*0dc2366fSVenugopal Iyer 		oftemplate = ring_s_fields;
1968*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_RING] = B_TRUE;
1969*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_RING] = B_TRUE;
1970*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_RING] =
1971*0dc2366fSVenugopal Iyer 		    print_rx_generic_ring_stats;
1972*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_RING] =
1973*0dc2366fSVenugopal Iyer 		    print_tx_generic_ring_stats;
1974*0dc2366fSVenugopal Iyer 	}
1975*0dc2366fSVenugopal Iyer 
1976*0dc2366fSVenugopal Iyer 	if (o_arg) {
1977*0dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
1978*0dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
1979*0dc2366fSVenugopal Iyer 	}
1980*0dc2366fSVenugopal Iyer 
1981*0dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
1982*0dc2366fSVenugopal Iyer 	dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
1983*0dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
1984*0dc2366fSVenugopal Iyer 
1985*0dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
1986*0dc2366fSVenugopal Iyer 
1987*0dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
1988*0dc2366fSVenugopal Iyer }
1989*0dc2366fSVenugopal Iyer 
1990*0dc2366fSVenugopal Iyer static void
do_show_link(int argc,char * argv[],const char * use)1991*0dc2366fSVenugopal Iyer do_show_link(int argc, char *argv[], const char *use)
1992*0dc2366fSVenugopal Iyer {
1993*0dc2366fSVenugopal Iyer 	int			option;
1994*0dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
1995*0dc2366fSVenugopal Iyer 	boolean_t		F_arg = B_FALSE;
1996*0dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
1997*0dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
1998*0dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
1999*0dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
2000*0dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
2001*0dc2366fSVenugopal Iyer 	boolean_t		a_arg = B_FALSE;
2002*0dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
2003*0dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
2004*0dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
2005*0dc2366fSVenugopal Iyer 	char			unit = '\0';
2006*0dc2366fSVenugopal Iyer 	show_state_t		state;
2007*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
2008*0dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
2009*0dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
2010*0dc2366fSVenugopal Iyer 
2011*0dc2366fSVenugopal Iyer 	char			*lane_stat_fields =
2012*0dc2366fSVenugopal Iyer 	    "link,type,id,index,pkts,bytes";
2013*0dc2366fSVenugopal Iyer 	char			*rx_lane_stat_fields =
2014*0dc2366fSVenugopal Iyer 	    "link,type,id,index,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
2015*0dc2366fSVenugopal Iyer 	char			*tx_lane_stat_fields =
2016*0dc2366fSVenugopal Iyer 	    "link,type,id,index,opkts,obytes,blkcnt,ublkcnt";
2017*0dc2366fSVenugopal Iyer 	char			*rx_fanout_stat_fields =
2018*0dc2366fSVenugopal Iyer 	    "link,id,index,fout,ipkts,rbytes";
2019*0dc2366fSVenugopal Iyer 
2020*0dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
2021*0dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
2022*0dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
2023*0dc2366fSVenugopal Iyer 	ofmt_field_t 		*oftemplate;
2024*0dc2366fSVenugopal Iyer 
2025*0dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
2026*0dc2366fSVenugopal Iyer 	opterr = 0;
2027*0dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":hrtFapi:o:u:",
2028*0dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
2029*0dc2366fSVenugopal Iyer 		switch (option) {
2030*0dc2366fSVenugopal Iyer 		case 'h':
2031*0dc2366fSVenugopal Iyer 			if (r_arg || F_arg || t_arg || i_arg || p_arg ||
2032*0dc2366fSVenugopal Iyer 			    o_arg || u_arg || a_arg) {
2033*0dc2366fSVenugopal Iyer 				die("the option -h is not compatible with "
2034*0dc2366fSVenugopal Iyer 				    "-r, -F, -t, -i, -p, -o, -u, -a");
2035*0dc2366fSVenugopal Iyer 			}
2036*0dc2366fSVenugopal Iyer 			do_show_history(argc, &argv[0], use);
2037*0dc2366fSVenugopal Iyer 			return;
2038*0dc2366fSVenugopal Iyer 		case 'r':
2039*0dc2366fSVenugopal Iyer 			if (r_arg)
2040*0dc2366fSVenugopal Iyer 				die_optdup(option);
2041*0dc2366fSVenugopal Iyer 
2042*0dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
2043*0dc2366fSVenugopal Iyer 			break;
2044*0dc2366fSVenugopal Iyer 		case 'F':
2045*0dc2366fSVenugopal Iyer 			if (F_arg)
2046*0dc2366fSVenugopal Iyer 				die_optdup(option);
2047*0dc2366fSVenugopal Iyer 
2048*0dc2366fSVenugopal Iyer 			F_arg = B_TRUE;
2049*0dc2366fSVenugopal Iyer 			break;
2050*0dc2366fSVenugopal Iyer 		case 't':
2051*0dc2366fSVenugopal Iyer 			if (t_arg)
2052*0dc2366fSVenugopal Iyer 				die_optdup(option);
2053*0dc2366fSVenugopal Iyer 
2054*0dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
2055*0dc2366fSVenugopal Iyer 			break;
2056*0dc2366fSVenugopal Iyer 		case 'a':
2057*0dc2366fSVenugopal Iyer 			if (a_arg)
2058*0dc2366fSVenugopal Iyer 				die_optdup(option);
2059*0dc2366fSVenugopal Iyer 
2060*0dc2366fSVenugopal Iyer 			a_arg = B_TRUE;
2061*0dc2366fSVenugopal Iyer 			break;
2062*0dc2366fSVenugopal Iyer 		case 'i':
2063*0dc2366fSVenugopal Iyer 			if (i_arg)
2064*0dc2366fSVenugopal Iyer 				die_optdup(option);
2065*0dc2366fSVenugopal Iyer 
2066*0dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
2067*0dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
2068*0dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
2069*0dc2366fSVenugopal Iyer 			break;
2070*0dc2366fSVenugopal Iyer 		case 'p':
2071*0dc2366fSVenugopal Iyer 			if (p_arg)
2072*0dc2366fSVenugopal Iyer 				die_optdup(option);
2073*0dc2366fSVenugopal Iyer 
2074*0dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
2075*0dc2366fSVenugopal Iyer 			break;
2076*0dc2366fSVenugopal Iyer 		case 'o':
2077*0dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
2078*0dc2366fSVenugopal Iyer 			o_fields_str = optarg;
2079*0dc2366fSVenugopal Iyer 			break;
2080*0dc2366fSVenugopal Iyer 		case 'u':
2081*0dc2366fSVenugopal Iyer 			if (u_arg)
2082*0dc2366fSVenugopal Iyer 				die_optdup(option);
2083*0dc2366fSVenugopal Iyer 
2084*0dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
2085*0dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
2086*0dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
2087*0dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
2088*0dc2366fSVenugopal Iyer 			break;
2089*0dc2366fSVenugopal Iyer 		default:
2090*0dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
2091*0dc2366fSVenugopal Iyer 			break;
2092*0dc2366fSVenugopal Iyer 		}
2093*0dc2366fSVenugopal Iyer 	}
2094*0dc2366fSVenugopal Iyer 
2095*0dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
2096*0dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
2097*0dc2366fSVenugopal Iyer 
2098*0dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
2099*0dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
2100*0dc2366fSVenugopal Iyer 
2101*0dc2366fSVenugopal Iyer 	if (F_arg && !r_arg)
2102*0dc2366fSVenugopal Iyer 		die("-F must be used with -r");
2103*0dc2366fSVenugopal Iyer 
2104*0dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
2105*0dc2366fSVenugopal Iyer 		die("-p requires -o");
2106*0dc2366fSVenugopal Iyer 
2107*0dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
2108*0dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
2109*0dc2366fSVenugopal Iyer 
2110*0dc2366fSVenugopal Iyer 	if (a_arg &&
2111*0dc2366fSVenugopal Iyer 	    (p_arg || o_arg || u_arg || i_arg)) {
2112*0dc2366fSVenugopal Iyer 		die("the option -a is not compatible with "
2113*0dc2366fSVenugopal Iyer 		    "-p, -o, -u, -i");
2114*0dc2366fSVenugopal Iyer 	}
2115*0dc2366fSVenugopal Iyer 
2116*0dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
2117*0dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
2118*0dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
2119*0dc2366fSVenugopal Iyer 			die("link name too long");
2120*0dc2366fSVenugopal Iyer 
2121*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
2122*0dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
2123*0dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
2124*0dc2366fSVenugopal Iyer 		}
2125*0dc2366fSVenugopal Iyer 	} else if (optind != argc) {
2126*0dc2366fSVenugopal Iyer 		usage();
2127*0dc2366fSVenugopal Iyer 	}
2128*0dc2366fSVenugopal Iyer 
2129*0dc2366fSVenugopal Iyer 	if (a_arg) {
2130*0dc2366fSVenugopal Iyer 		boolean_t	stattype[DLADM_STAT_NUM_STATS];
2131*0dc2366fSVenugopal Iyer 
2132*0dc2366fSVenugopal Iyer 		bzero(&stattype, sizeof (stattype));
2133*0dc2366fSVenugopal Iyer 
2134*0dc2366fSVenugopal Iyer 		if (r_arg) {
2135*0dc2366fSVenugopal Iyer 			if (F_arg) {
2136*0dc2366fSVenugopal Iyer 				stattype[DLADM_STAT_RX_LANE_FOUT] = B_TRUE;
2137*0dc2366fSVenugopal Iyer 			} else {
2138*0dc2366fSVenugopal Iyer 				stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2139*0dc2366fSVenugopal Iyer 			}
2140*0dc2366fSVenugopal Iyer 		} else if (t_arg) {
2141*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2142*0dc2366fSVenugopal Iyer 		} else {		/* Display both Rx and Tx lanes */
2143*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2144*0dc2366fSVenugopal Iyer 			stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2145*0dc2366fSVenugopal Iyer 		}
2146*0dc2366fSVenugopal Iyer 
2147*0dc2366fSVenugopal Iyer 		dump_all_link_stats(linkid, stattype);
2148*0dc2366fSVenugopal Iyer 		return;
2149*0dc2366fSVenugopal Iyer 	}
2150*0dc2366fSVenugopal Iyer 
2151*0dc2366fSVenugopal Iyer 	state.ls_unit = unit;
2152*0dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
2153*0dc2366fSVenugopal Iyer 
2154*0dc2366fSVenugopal Iyer 	if (state.ls_parsable)
2155*0dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
2156*0dc2366fSVenugopal Iyer 
2157*0dc2366fSVenugopal Iyer 	if (r_arg) {
2158*0dc2366fSVenugopal Iyer 		if (F_arg) {
2159*0dc2366fSVenugopal Iyer 			fields_str = rx_fanout_stat_fields;
2160*0dc2366fSVenugopal Iyer 			oftemplate = rx_fanout_lane_s_fields;
2161*0dc2366fSVenugopal Iyer 			state.ls_stattype[DLADM_STAT_RX_LANE_FOUT] = B_TRUE;
2162*0dc2366fSVenugopal Iyer 			state.ls_stats2str[DLADM_STAT_RX_LANE_FOUT] =
2163*0dc2366fSVenugopal Iyer 			    print_fanout_stats;
2164*0dc2366fSVenugopal Iyer 		} else {
2165*0dc2366fSVenugopal Iyer 			fields_str = rx_lane_stat_fields;
2166*0dc2366fSVenugopal Iyer 			oftemplate = rx_lane_s_fields;
2167*0dc2366fSVenugopal Iyer 			state.ls_stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2168*0dc2366fSVenugopal Iyer 			state.ls_stats2str[DLADM_STAT_RX_LANE] =
2169*0dc2366fSVenugopal Iyer 			    print_rx_lane_stats;
2170*0dc2366fSVenugopal Iyer 		}
2171*0dc2366fSVenugopal Iyer 	} else if (t_arg) {
2172*0dc2366fSVenugopal Iyer 		fields_str = tx_lane_stat_fields;
2173*0dc2366fSVenugopal Iyer 		oftemplate = tx_lane_s_fields;
2174*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2175*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_LANE] = print_tx_lane_stats;
2176*0dc2366fSVenugopal Iyer 	} else {		/* Display both Rx and Tx lanes */
2177*0dc2366fSVenugopal Iyer 		fields_str = lane_stat_fields;
2178*0dc2366fSVenugopal Iyer 		oftemplate = lane_s_fields;
2179*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2180*0dc2366fSVenugopal Iyer 		state.ls_stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2181*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_RX_LANE] =
2182*0dc2366fSVenugopal Iyer 		    print_rx_generic_lane_stats;
2183*0dc2366fSVenugopal Iyer 		state.ls_stats2str[DLADM_STAT_TX_LANE] =
2184*0dc2366fSVenugopal Iyer 		    print_tx_generic_lane_stats;
2185*0dc2366fSVenugopal Iyer 	}
2186*0dc2366fSVenugopal Iyer 	if (o_arg) {
2187*0dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
2188*0dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
2189*0dc2366fSVenugopal Iyer 	}
2190*0dc2366fSVenugopal Iyer 
2191*0dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
2192*0dc2366fSVenugopal Iyer 	dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
2193*0dc2366fSVenugopal Iyer 
2194*0dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
2195*0dc2366fSVenugopal Iyer 
2196*0dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
2197*0dc2366fSVenugopal Iyer 
2198*0dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
2199*0dc2366fSVenugopal Iyer }
2200*0dc2366fSVenugopal Iyer 
2201*0dc2366fSVenugopal Iyer static void
do_show_aggr(int argc,char * argv[],const char * use)2202*0dc2366fSVenugopal Iyer do_show_aggr(int argc, char *argv[], const char *use)
2203*0dc2366fSVenugopal Iyer {
2204*0dc2366fSVenugopal Iyer 	int			option;
2205*0dc2366fSVenugopal Iyer 	boolean_t		r_arg = B_FALSE;
2206*0dc2366fSVenugopal Iyer 	boolean_t		t_arg = B_FALSE;
2207*0dc2366fSVenugopal Iyer 	boolean_t		i_arg = B_FALSE;
2208*0dc2366fSVenugopal Iyer 	boolean_t		p_arg = B_FALSE;
2209*0dc2366fSVenugopal Iyer 	boolean_t		o_arg = B_FALSE;
2210*0dc2366fSVenugopal Iyer 	boolean_t		u_arg = B_FALSE;
2211*0dc2366fSVenugopal Iyer 	uint32_t		flags = DLADM_OPT_ACTIVE;
2212*0dc2366fSVenugopal Iyer 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
2213*0dc2366fSVenugopal Iyer 	uint32_t		interval = 0;
2214*0dc2366fSVenugopal Iyer 	char			unit = '\0';
2215*0dc2366fSVenugopal Iyer 	show_state_t		state;
2216*0dc2366fSVenugopal Iyer 	dladm_status_t		status;
2217*0dc2366fSVenugopal Iyer 	char			*fields_str = NULL;
2218*0dc2366fSVenugopal Iyer 	char			*o_fields_str = NULL;
2219*0dc2366fSVenugopal Iyer 
2220*0dc2366fSVenugopal Iyer 	char			*aggr_stat_fields =
2221*0dc2366fSVenugopal Iyer 	    "link,port,ipkts,rbytes,opkts,obytes";
2222*0dc2366fSVenugopal Iyer 	char			*rx_aggr_stat_fields = "link,port,ipkts,rbytes";
2223*0dc2366fSVenugopal Iyer 	char			*tx_aggr_stat_fields = "link,port,opkts,obytes";
2224*0dc2366fSVenugopal Iyer 
2225*0dc2366fSVenugopal Iyer 	ofmt_handle_t		ofmt;
2226*0dc2366fSVenugopal Iyer 	ofmt_status_t		oferr;
2227*0dc2366fSVenugopal Iyer 	uint_t			ofmtflags = OFMT_RIGHTJUST;
2228*0dc2366fSVenugopal Iyer 	ofmt_field_t 		*oftemplate;
2229*0dc2366fSVenugopal Iyer 
2230*0dc2366fSVenugopal Iyer 	bzero(&state, sizeof (state));
2231*0dc2366fSVenugopal Iyer 	opterr = 0;
2232*0dc2366fSVenugopal Iyer 	while ((option = getopt_long(argc, argv, ":rtpi:o:u:",
2233*0dc2366fSVenugopal Iyer 	    NULL, NULL)) != -1) {
2234*0dc2366fSVenugopal Iyer 		switch (option) {
2235*0dc2366fSVenugopal Iyer 		case 'r':
2236*0dc2366fSVenugopal Iyer 			if (r_arg)
2237*0dc2366fSVenugopal Iyer 				die_optdup(option);
2238*0dc2366fSVenugopal Iyer 
2239*0dc2366fSVenugopal Iyer 			r_arg = B_TRUE;
2240*0dc2366fSVenugopal Iyer 			break;
2241*0dc2366fSVenugopal Iyer 		case 't':
2242*0dc2366fSVenugopal Iyer 			if (t_arg)
2243*0dc2366fSVenugopal Iyer 				die_optdup(option);
2244*0dc2366fSVenugopal Iyer 
2245*0dc2366fSVenugopal Iyer 			t_arg = B_TRUE;
2246*0dc2366fSVenugopal Iyer 			break;
2247*0dc2366fSVenugopal Iyer 		case 'i':
2248*0dc2366fSVenugopal Iyer 			if (i_arg)
2249*0dc2366fSVenugopal Iyer 				die_optdup(option);
2250*0dc2366fSVenugopal Iyer 
2251*0dc2366fSVenugopal Iyer 			i_arg = B_TRUE;
2252*0dc2366fSVenugopal Iyer 			if (!dladm_str2interval(optarg, &interval))
2253*0dc2366fSVenugopal Iyer 				die("invalid interval value '%s'", optarg);
2254*0dc2366fSVenugopal Iyer 			break;
2255*0dc2366fSVenugopal Iyer 		case 'p':
2256*0dc2366fSVenugopal Iyer 			if (p_arg)
2257*0dc2366fSVenugopal Iyer 				die_optdup(option);
2258*0dc2366fSVenugopal Iyer 
2259*0dc2366fSVenugopal Iyer 			p_arg = B_TRUE;
2260*0dc2366fSVenugopal Iyer 			break;
2261*0dc2366fSVenugopal Iyer 		case 'o':
2262*0dc2366fSVenugopal Iyer 			o_arg = B_TRUE;
2263*0dc2366fSVenugopal Iyer 			o_fields_str = optarg;
2264*0dc2366fSVenugopal Iyer 			break;
2265*0dc2366fSVenugopal Iyer 		case 'u':
2266*0dc2366fSVenugopal Iyer 			if (u_arg)
2267*0dc2366fSVenugopal Iyer 				die_optdup(option);
2268*0dc2366fSVenugopal Iyer 
2269*0dc2366fSVenugopal Iyer 			u_arg = B_TRUE;
2270*0dc2366fSVenugopal Iyer 			if (!dlstat_unit(optarg, &unit))
2271*0dc2366fSVenugopal Iyer 				die("invalid unit value '%s',"
2272*0dc2366fSVenugopal Iyer 				    "unit must be R|K|M|G|T|P", optarg);
2273*0dc2366fSVenugopal Iyer 			break;
2274*0dc2366fSVenugopal Iyer 		default:
2275*0dc2366fSVenugopal Iyer 			die_opterr(optopt, option, use);
2276*0dc2366fSVenugopal Iyer 			break;
2277*0dc2366fSVenugopal Iyer 		}
2278*0dc2366fSVenugopal Iyer 	}
2279*0dc2366fSVenugopal Iyer 
2280*0dc2366fSVenugopal Iyer 	if (r_arg && t_arg)
2281*0dc2366fSVenugopal Iyer 		die("the options -t and -r are not compatible");
2282*0dc2366fSVenugopal Iyer 
2283*0dc2366fSVenugopal Iyer 	if (u_arg && p_arg)
2284*0dc2366fSVenugopal Iyer 		die("the options -u and -p are not compatible");
2285*0dc2366fSVenugopal Iyer 
2286*0dc2366fSVenugopal Iyer 	if (p_arg && !o_arg)
2287*0dc2366fSVenugopal Iyer 		die("-p requires -o");
2288*0dc2366fSVenugopal Iyer 
2289*0dc2366fSVenugopal Iyer 	if (p_arg && strcasecmp(o_fields_str, "all") == 0)
2290*0dc2366fSVenugopal Iyer 		die("\"-o all\" is invalid with -p");
2291*0dc2366fSVenugopal Iyer 
2292*0dc2366fSVenugopal Iyer 
2293*0dc2366fSVenugopal Iyer 	/* get link name (optional last argument) */
2294*0dc2366fSVenugopal Iyer 	if (optind == (argc-1)) {
2295*0dc2366fSVenugopal Iyer 		if (strlen(argv[optind]) >= MAXLINKNAMELEN)
2296*0dc2366fSVenugopal Iyer 			die("link name too long");
2297*0dc2366fSVenugopal Iyer 
2298*0dc2366fSVenugopal Iyer 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
2299*0dc2366fSVenugopal Iyer 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
2300*0dc2366fSVenugopal Iyer 			die_dlerr(status, "link %s is not valid", argv[optind]);
2301*0dc2366fSVenugopal Iyer 		}
2302*0dc2366fSVenugopal Iyer 	} else if (optind != argc) {
2303*0dc2366fSVenugopal Iyer 		usage();
2304*0dc2366fSVenugopal Iyer 	}
2305*0dc2366fSVenugopal Iyer 
2306*0dc2366fSVenugopal Iyer 	state.ls_unit = unit;
2307*0dc2366fSVenugopal Iyer 	state.ls_parsable = p_arg;
2308*0dc2366fSVenugopal Iyer 
2309*0dc2366fSVenugopal Iyer 	if (state.ls_parsable)
2310*0dc2366fSVenugopal Iyer 		ofmtflags |= OFMT_PARSABLE;
2311*0dc2366fSVenugopal Iyer 
2312*0dc2366fSVenugopal Iyer 	oftemplate = aggr_port_s_fields;
2313*0dc2366fSVenugopal Iyer 	state.ls_stattype[DLADM_STAT_AGGR_PORT] = B_TRUE;
2314*0dc2366fSVenugopal Iyer 	state.ls_stats2str[DLADM_STAT_AGGR_PORT] = print_aggr_port_stats;
2315*0dc2366fSVenugopal Iyer 
2316*0dc2366fSVenugopal Iyer 	if (r_arg)
2317*0dc2366fSVenugopal Iyer 		fields_str = rx_aggr_stat_fields;
2318*0dc2366fSVenugopal Iyer 	else if (t_arg)
2319*0dc2366fSVenugopal Iyer 		fields_str = tx_aggr_stat_fields;
2320*0dc2366fSVenugopal Iyer 	else
2321*0dc2366fSVenugopal Iyer 		fields_str = aggr_stat_fields;
2322*0dc2366fSVenugopal Iyer 
2323*0dc2366fSVenugopal Iyer 	if (o_arg) {
2324*0dc2366fSVenugopal Iyer 		fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
2325*0dc2366fSVenugopal Iyer 		    fields_str : o_fields_str;
2326*0dc2366fSVenugopal Iyer 	}
2327*0dc2366fSVenugopal Iyer 
2328*0dc2366fSVenugopal Iyer 	oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
2329*0dc2366fSVenugopal Iyer 	dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
2330*0dc2366fSVenugopal Iyer 	state.ls_ofmt = ofmt;
2331*0dc2366fSVenugopal Iyer 
2332*0dc2366fSVenugopal Iyer 	show_link_stats(linkid, state, interval);
2333*0dc2366fSVenugopal Iyer 
2334*0dc2366fSVenugopal Iyer 	ofmt_close(ofmt);
2335*0dc2366fSVenugopal Iyer }
2336*0dc2366fSVenugopal Iyer 
2337*0dc2366fSVenugopal Iyer /* PRINTFLIKE1 */
2338*0dc2366fSVenugopal Iyer static void
warn(const char * format,...)2339*0dc2366fSVenugopal Iyer warn(const char *format, ...)
2340*0dc2366fSVenugopal Iyer {
2341*0dc2366fSVenugopal Iyer 	va_list alist;
2342*0dc2366fSVenugopal Iyer 
2343*0dc2366fSVenugopal Iyer 	format = gettext(format);
2344*0dc2366fSVenugopal Iyer 	(void) fprintf(stderr, "%s: warning: ", progname);
2345*0dc2366fSVenugopal Iyer 
2346*0dc2366fSVenugopal Iyer 	va_start(alist, format);
2347*0dc2366fSVenugopal Iyer 	(void) vfprintf(stderr, format, alist);
2348*0dc2366fSVenugopal Iyer 	va_end(alist);
2349*0dc2366fSVenugopal Iyer 
2350*0dc2366fSVenugopal Iyer 	(void) putc('\n', stderr);
2351*0dc2366fSVenugopal Iyer }
2352*0dc2366fSVenugopal Iyer 
2353*0dc2366fSVenugopal Iyer /*
2354*0dc2366fSVenugopal Iyer  * Also closes the dladm handle if it is not NULL.
2355*0dc2366fSVenugopal Iyer  */
2356*0dc2366fSVenugopal Iyer /* PRINTFLIKE2 */
2357*0dc2366fSVenugopal Iyer static void
die_dlerr(dladm_status_t err,const char * format,...)2358*0dc2366fSVenugopal Iyer die_dlerr(dladm_status_t err, const char *format, ...)
2359*0dc2366fSVenugopal Iyer {
2360*0dc2366fSVenugopal Iyer 	va_list alist;
2361*0dc2366fSVenugopal Iyer 	char	errmsg[DLADM_STRSIZE];
2362*0dc2366fSVenugopal Iyer 
2363*0dc2366fSVenugopal Iyer 	format = gettext(format);
2364*0dc2366fSVenugopal Iyer 	(void) fprintf(stderr, "%s: ", progname);
2365*0dc2366fSVenugopal Iyer 
2366*0dc2366fSVenugopal Iyer 	va_start(alist, format);
2367*0dc2366fSVenugopal Iyer 	(void) vfprintf(stderr, format, alist);
2368*0dc2366fSVenugopal Iyer 	va_end(alist);
2369*0dc2366fSVenugopal Iyer 	(void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
2370*0dc2366fSVenugopal Iyer 
2371*0dc2366fSVenugopal Iyer 	/* close dladm handle if it was opened */
2372*0dc2366fSVenugopal Iyer 	if (handle != NULL)
2373*0dc2366fSVenugopal Iyer 		dladm_close(handle);
2374*0dc2366fSVenugopal Iyer 
2375*0dc2366fSVenugopal Iyer 	exit(EXIT_FAILURE);
2376*0dc2366fSVenugopal Iyer }
2377*0dc2366fSVenugopal Iyer 
2378*0dc2366fSVenugopal Iyer /* PRINTFLIKE1 */
2379*0dc2366fSVenugopal Iyer static void
die(const char * format,...)2380*0dc2366fSVenugopal Iyer die(const char *format, ...)
2381*0dc2366fSVenugopal Iyer {
2382*0dc2366fSVenugopal Iyer 	va_list alist;
2383*0dc2366fSVenugopal Iyer 
2384*0dc2366fSVenugopal Iyer 	format = gettext(format);
2385*0dc2366fSVenugopal Iyer 	(void) fprintf(stderr, "%s: ", progname);
2386*0dc2366fSVenugopal Iyer 
2387*0dc2366fSVenugopal Iyer 	va_start(alist, format);
2388*0dc2366fSVenugopal Iyer 	(void) vfprintf(stderr, format, alist);
2389*0dc2366fSVenugopal Iyer 	va_end(alist);
2390*0dc2366fSVenugopal Iyer 
2391*0dc2366fSVenugopal Iyer 	(void) putc('\n', stderr);
2392*0dc2366fSVenugopal Iyer 
2393*0dc2366fSVenugopal Iyer 	/* close dladm handle if it was opened */
2394*0dc2366fSVenugopal Iyer 	if (handle != NULL)
2395*0dc2366fSVenugopal Iyer 		dladm_close(handle);
2396*0dc2366fSVenugopal Iyer 
2397*0dc2366fSVenugopal Iyer 	exit(EXIT_FAILURE);
2398*0dc2366fSVenugopal Iyer }
2399*0dc2366fSVenugopal Iyer 
2400*0dc2366fSVenugopal Iyer static void
die_optdup(int opt)2401*0dc2366fSVenugopal Iyer die_optdup(int opt)
2402*0dc2366fSVenugopal Iyer {
2403*0dc2366fSVenugopal Iyer 	die("the option -%c cannot be specified more than once", opt);
2404*0dc2366fSVenugopal Iyer }
2405*0dc2366fSVenugopal Iyer 
2406*0dc2366fSVenugopal Iyer static void
die_opterr(int opt,int opterr,const char * usage)2407*0dc2366fSVenugopal Iyer die_opterr(int opt, int opterr, const char *usage)
2408*0dc2366fSVenugopal Iyer {
2409*0dc2366fSVenugopal Iyer 	switch (opterr) {
2410*0dc2366fSVenugopal Iyer 	case ':':
2411*0dc2366fSVenugopal Iyer 		die("option '-%c' requires a value\nusage: %s", opt,
2412*0dc2366fSVenugopal Iyer 		    gettext(usage));
2413*0dc2366fSVenugopal Iyer 		break;
2414*0dc2366fSVenugopal Iyer 	case '?':
2415*0dc2366fSVenugopal Iyer 	default:
2416*0dc2366fSVenugopal Iyer 		die("unrecognized option '-%c'\nusage: %s", opt,
2417*0dc2366fSVenugopal Iyer 		    gettext(usage));
2418*0dc2366fSVenugopal Iyer 		break;
2419*0dc2366fSVenugopal Iyer 	}
2420*0dc2366fSVenugopal Iyer }
2421*0dc2366fSVenugopal Iyer 
2422*0dc2366fSVenugopal Iyer /*
2423*0dc2366fSVenugopal Iyer  * default output callback function that, when invoked,
2424*0dc2366fSVenugopal Iyer  * prints string which is offset by ofmt_arg->ofmt_id within buf.
2425*0dc2366fSVenugopal Iyer  */
2426*0dc2366fSVenugopal Iyer static boolean_t
print_default_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)2427*0dc2366fSVenugopal Iyer print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2428*0dc2366fSVenugopal Iyer {
2429*0dc2366fSVenugopal Iyer 	char *value;
2430*0dc2366fSVenugopal Iyer 
2431*0dc2366fSVenugopal Iyer 	value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
2432*0dc2366fSVenugopal Iyer 	(void) strlcpy(buf, value, bufsize);
2433*0dc2366fSVenugopal Iyer 	return (B_TRUE);
2434*0dc2366fSVenugopal Iyer }
2435*0dc2366fSVenugopal Iyer 
2436*0dc2366fSVenugopal Iyer static void
dlstat_ofmt_check(ofmt_status_t oferr,boolean_t parsable,ofmt_handle_t ofmt)2437*0dc2366fSVenugopal Iyer dlstat_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
2438*0dc2366fSVenugopal Iyer     ofmt_handle_t ofmt)
2439*0dc2366fSVenugopal Iyer {
2440*0dc2366fSVenugopal Iyer 	char buf[OFMT_BUFSIZE];
2441*0dc2366fSVenugopal Iyer 
2442*0dc2366fSVenugopal Iyer 	if (oferr == OFMT_SUCCESS)
2443*0dc2366fSVenugopal Iyer 		return;
2444*0dc2366fSVenugopal Iyer 	(void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
2445*0dc2366fSVenugopal Iyer 	/*
2446*0dc2366fSVenugopal Iyer 	 * All errors are considered fatal in parsable mode.
2447*0dc2366fSVenugopal Iyer 	 * NOMEM errors are always fatal, regardless of mode.
2448*0dc2366fSVenugopal Iyer 	 * For other errors, we print diagnostics in human-readable
2449*0dc2366fSVenugopal Iyer 	 * mode and processs what we can.
2450*0dc2366fSVenugopal Iyer 	 */
2451*0dc2366fSVenugopal Iyer 	if (parsable || oferr == OFMT_ENOFIELDS) {
2452*0dc2366fSVenugopal Iyer 		ofmt_close(ofmt);
2453*0dc2366fSVenugopal Iyer 		die(buf);
2454*0dc2366fSVenugopal Iyer 	} else {
2455*0dc2366fSVenugopal Iyer 		warn(buf);
2456*0dc2366fSVenugopal Iyer 	}
2457*0dc2366fSVenugopal Iyer }
2458