xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/ilbadm/ilbadm_stats.c (revision 10946:324bab2b3370)
1*10946SSangeeta.Misra@Sun.COM /*
2*10946SSangeeta.Misra@Sun.COM  * CDDL HEADER START
3*10946SSangeeta.Misra@Sun.COM  *
4*10946SSangeeta.Misra@Sun.COM  * The contents of this file are subject to the terms of the
5*10946SSangeeta.Misra@Sun.COM  * Common Development and Distribution License (the "License").
6*10946SSangeeta.Misra@Sun.COM  * You may not use this file except in compliance with the License.
7*10946SSangeeta.Misra@Sun.COM  *
8*10946SSangeeta.Misra@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10946SSangeeta.Misra@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10946SSangeeta.Misra@Sun.COM  * See the License for the specific language governing permissions
11*10946SSangeeta.Misra@Sun.COM  * and limitations under the License.
12*10946SSangeeta.Misra@Sun.COM  *
13*10946SSangeeta.Misra@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10946SSangeeta.Misra@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10946SSangeeta.Misra@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10946SSangeeta.Misra@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10946SSangeeta.Misra@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10946SSangeeta.Misra@Sun.COM  *
19*10946SSangeeta.Misra@Sun.COM  * CDDL HEADER END
20*10946SSangeeta.Misra@Sun.COM  */
21*10946SSangeeta.Misra@Sun.COM 
22*10946SSangeeta.Misra@Sun.COM /*
23*10946SSangeeta.Misra@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*10946SSangeeta.Misra@Sun.COM  * Use is subject to license terms.
25*10946SSangeeta.Misra@Sun.COM  */
26*10946SSangeeta.Misra@Sun.COM 
27*10946SSangeeta.Misra@Sun.COM #include <stdio.h>
28*10946SSangeeta.Misra@Sun.COM #include <unistd.h>
29*10946SSangeeta.Misra@Sun.COM #include <stdlib.h>
30*10946SSangeeta.Misra@Sun.COM #include <strings.h>
31*10946SSangeeta.Misra@Sun.COM #include <sys/types.h>
32*10946SSangeeta.Misra@Sun.COM #include <sys/socket.h>
33*10946SSangeeta.Misra@Sun.COM #include <sys/sysmacros.h>
34*10946SSangeeta.Misra@Sun.COM #include <sys/note.h>
35*10946SSangeeta.Misra@Sun.COM #include <fcntl.h>
36*10946SSangeeta.Misra@Sun.COM #include <errno.h>
37*10946SSangeeta.Misra@Sun.COM #include <assert.h>
38*10946SSangeeta.Misra@Sun.COM #include <libgen.h>
39*10946SSangeeta.Misra@Sun.COM #include <kstat.h>
40*10946SSangeeta.Misra@Sun.COM #include <ofmt.h>
41*10946SSangeeta.Misra@Sun.COM #include <libilb.h>
42*10946SSangeeta.Misra@Sun.COM #include "ilbadm.h"
43*10946SSangeeta.Misra@Sun.COM 
44*10946SSangeeta.Misra@Sun.COM #define	ILBST_TIMESTAMP_HEADER	0x01	/* a timestamp w. every header */
45*10946SSangeeta.Misra@Sun.COM #define	ILBST_DELTA_INTERVAL	0x02	/* delta over specified interval */
46*10946SSangeeta.Misra@Sun.COM #define	ILBST_ABS_NUMBERS	0x04	/* print absolute numbers, no d's */
47*10946SSangeeta.Misra@Sun.COM #define	ILBST_ITEMIZE		0x08	/* itemize */
48*10946SSangeeta.Misra@Sun.COM #define	ILBST_VERBOSE		0x10	/* verbose error info */
49*10946SSangeeta.Misra@Sun.COM 
50*10946SSangeeta.Misra@Sun.COM #define	ILBST_OLD_VALUES	0x20	/* for internal processing */
51*10946SSangeeta.Misra@Sun.COM #define	ILBST_RULES_CHANGED	0x40
52*10946SSangeeta.Misra@Sun.COM 
53*10946SSangeeta.Misra@Sun.COM typedef struct {
54*10946SSangeeta.Misra@Sun.COM 	char		is_name[KSTAT_STRLEN];
55*10946SSangeeta.Misra@Sun.COM 	uint64_t	is_value;
56*10946SSangeeta.Misra@Sun.COM } ilbst_stat_t;
57*10946SSangeeta.Misra@Sun.COM 
58*10946SSangeeta.Misra@Sun.COM static ilbst_stat_t rulestats[] = {
59*10946SSangeeta.Misra@Sun.COM 	{"num_servers", 0},
60*10946SSangeeta.Misra@Sun.COM 	{"bytes_not_processed", 0},
61*10946SSangeeta.Misra@Sun.COM 	{"pkt_not_processed", 0},
62*10946SSangeeta.Misra@Sun.COM 	{"bytes_dropped", 0},
63*10946SSangeeta.Misra@Sun.COM 	{"pkt_dropped", 0},
64*10946SSangeeta.Misra@Sun.COM 	{"nomem_bytes_dropped", 0},
65*10946SSangeeta.Misra@Sun.COM 	{"nomem_pkt_dropped", 0},
66*10946SSangeeta.Misra@Sun.COM 	{"noport_bytes_dropped", 0},
67*10946SSangeeta.Misra@Sun.COM 	{"noport_pkt_dropped", 0},
68*10946SSangeeta.Misra@Sun.COM 	{"icmp_echo_processed", 0},
69*10946SSangeeta.Misra@Sun.COM 	{"icmp_dropped", 0},
70*10946SSangeeta.Misra@Sun.COM 	{"icmp_too_big_processed", 0},
71*10946SSangeeta.Misra@Sun.COM 	{"icmp_too_big_dropped", 0}
72*10946SSangeeta.Misra@Sun.COM };
73*10946SSangeeta.Misra@Sun.COM 
74*10946SSangeeta.Misra@Sun.COM /* indices into array above, to avoid searching */
75*10946SSangeeta.Misra@Sun.COM #define	RLSTA_NUM_SRV		0
76*10946SSangeeta.Misra@Sun.COM #define	RLSTA_BYTES_U		1
77*10946SSangeeta.Misra@Sun.COM #define	RLSTA_PKT_U		2
78*10946SSangeeta.Misra@Sun.COM #define	RLSTA_BYTES_D		3
79*10946SSangeeta.Misra@Sun.COM #define	RLSTA_PKT_D		4
80*10946SSangeeta.Misra@Sun.COM #define	RLSTA_NOMEMBYTES_D	5
81*10946SSangeeta.Misra@Sun.COM #define	RLSTA_NOMEMPKT_D	6
82*10946SSangeeta.Misra@Sun.COM #define	RLSTA_NOPORTBYTES_D	7
83*10946SSangeeta.Misra@Sun.COM #define	RLSTA_NOPORTPKT_D	8
84*10946SSangeeta.Misra@Sun.COM #define	RLSTA_ICMP_P		9
85*10946SSangeeta.Misra@Sun.COM #define	RLSTA_ICMP_D		10
86*10946SSangeeta.Misra@Sun.COM #define	RLSTA_ICMP2BIG_P	11
87*10946SSangeeta.Misra@Sun.COM #define	RLSTA_ICMP2BIG_D	12
88*10946SSangeeta.Misra@Sun.COM 
89*10946SSangeeta.Misra@Sun.COM static ilbst_stat_t servstats[] = {
90*10946SSangeeta.Misra@Sun.COM 	{"bytes_processed", 0},
91*10946SSangeeta.Misra@Sun.COM 	{"pkt_processed", 0}
92*10946SSangeeta.Misra@Sun.COM };
93*10946SSangeeta.Misra@Sun.COM /* indices into array above, to avoid searching */
94*10946SSangeeta.Misra@Sun.COM #define	SRVST_BYTES_P	0
95*10946SSangeeta.Misra@Sun.COM #define	SRVST_PKT_P	1
96*10946SSangeeta.Misra@Sun.COM 
97*10946SSangeeta.Misra@Sun.COM /* values used for of_* commands as id */
98*10946SSangeeta.Misra@Sun.COM #define	ILBST_PKT_P		0
99*10946SSangeeta.Misra@Sun.COM #define	ILBST_BYTES_P		1
100*10946SSangeeta.Misra@Sun.COM #define	ILBST_PKT_U		2
101*10946SSangeeta.Misra@Sun.COM #define	ILBST_BYTES_U		3
102*10946SSangeeta.Misra@Sun.COM #define	ILBST_PKT_D		4
103*10946SSangeeta.Misra@Sun.COM #define	ILBST_BYTES_D		5
104*10946SSangeeta.Misra@Sun.COM #define	ILBST_ICMP_P		6
105*10946SSangeeta.Misra@Sun.COM #define	ILBST_ICMP_D		7
106*10946SSangeeta.Misra@Sun.COM #define	ILBST_ICMP2BIG_P	8
107*10946SSangeeta.Misra@Sun.COM #define	ILBST_ICMP2BIG_D	9
108*10946SSangeeta.Misra@Sun.COM #define	ILBST_NOMEMP_D		10
109*10946SSangeeta.Misra@Sun.COM #define	ILBST_NOPORTP_D		11
110*10946SSangeeta.Misra@Sun.COM #define	ILBST_NOMEMB_D		12
111*10946SSangeeta.Misra@Sun.COM #define	ILBST_NOPORTB_D		13
112*10946SSangeeta.Misra@Sun.COM 
113*10946SSangeeta.Misra@Sun.COM #define	ILBST_ITEMIZE_SNAME	97
114*10946SSangeeta.Misra@Sun.COM #define	ILBST_ITEMIZE_RNAME	98
115*10946SSangeeta.Misra@Sun.COM #define	ILBST_TIMESTAMP		99
116*10946SSangeeta.Misra@Sun.COM 
117*10946SSangeeta.Misra@Sun.COM /* approx field widths */
118*10946SSangeeta.Misra@Sun.COM #define	ILBST_PKTCTR_W		8
119*10946SSangeeta.Misra@Sun.COM #define	ILBST_BYTECTR_W		10
120*10946SSangeeta.Misra@Sun.COM #define	ILBST_TIME_W		15
121*10946SSangeeta.Misra@Sun.COM 
122*10946SSangeeta.Misra@Sun.COM static boolean_t of_rule_stats(ofmt_arg_t *, char *, uint_t);
123*10946SSangeeta.Misra@Sun.COM static boolean_t of_server_stats(ofmt_arg_t *, char *, uint_t);
124*10946SSangeeta.Misra@Sun.COM static boolean_t of_itemize_stats(ofmt_arg_t *, char *, uint_t);
125*10946SSangeeta.Misra@Sun.COM static boolean_t of_timestamp(ofmt_arg_t *, char *, uint_t);
126*10946SSangeeta.Misra@Sun.COM 
127*10946SSangeeta.Misra@Sun.COM static ofmt_field_t stat_itemize_fields[] = {
128*10946SSangeeta.Misra@Sun.COM 	{"RULENAME", ILB_NAMESZ,	ILBST_ITEMIZE_RNAME, of_itemize_stats},
129*10946SSangeeta.Misra@Sun.COM 	{"SERVERNAME", ILB_NAMESZ,	ILBST_ITEMIZE_SNAME, of_itemize_stats},
130*10946SSangeeta.Misra@Sun.COM 	{"PKT_P",   ILBST_PKTCTR_W,	ILBST_PKT_P, of_itemize_stats},
131*10946SSangeeta.Misra@Sun.COM 	{"BYTES_P", ILBST_BYTECTR_W,	ILBST_BYTES_P, of_itemize_stats},
132*10946SSangeeta.Misra@Sun.COM 	{"TIME",    ILBST_TIME_W,	ILBST_TIMESTAMP, of_timestamp},
133*10946SSangeeta.Misra@Sun.COM 	{NULL,	    0, 0, NULL}
134*10946SSangeeta.Misra@Sun.COM };
135*10946SSangeeta.Misra@Sun.COM static ofmt_field_t stat_stdfields[] = {
136*10946SSangeeta.Misra@Sun.COM 	{"PKT_P",   ILBST_PKTCTR_W,	ILBST_PKT_P, of_server_stats},
137*10946SSangeeta.Misra@Sun.COM 	{"BYTES_P", ILBST_BYTECTR_W,	ILBST_BYTES_P, of_server_stats},
138*10946SSangeeta.Misra@Sun.COM 	{"PKT_U",   ILBST_PKTCTR_W,	ILBST_PKT_U, of_rule_stats},
139*10946SSangeeta.Misra@Sun.COM 	{"BYTES_U", ILBST_BYTECTR_W,	ILBST_BYTES_U, of_rule_stats},
140*10946SSangeeta.Misra@Sun.COM 	{"PKT_D",   ILBST_PKTCTR_W,	ILBST_PKT_D, of_rule_stats},
141*10946SSangeeta.Misra@Sun.COM 	{"BYTES_D", ILBST_BYTECTR_W,	ILBST_BYTES_D, of_rule_stats},
142*10946SSangeeta.Misra@Sun.COM 	{"ICMP_P",  ILBST_PKTCTR_W,	ILBST_ICMP_P, of_rule_stats},
143*10946SSangeeta.Misra@Sun.COM 	{"ICMP_D",  ILBST_PKTCTR_W,	ILBST_ICMP_D, of_rule_stats},
144*10946SSangeeta.Misra@Sun.COM 	{"ICMP2BIG_P", 11,		ILBST_ICMP2BIG_P, of_rule_stats},
145*10946SSangeeta.Misra@Sun.COM 	{"ICMP2BIG_D", 11,		ILBST_ICMP2BIG_D, of_rule_stats},
146*10946SSangeeta.Misra@Sun.COM 	{"NOMEMP_D", ILBST_PKTCTR_W,	ILBST_NOMEMP_D, of_rule_stats},
147*10946SSangeeta.Misra@Sun.COM 	{"NOPORTP_D", ILBST_PKTCTR_W,	ILBST_NOPORTP_D, of_rule_stats},
148*10946SSangeeta.Misra@Sun.COM 	{"NOMEMB_D", ILBST_PKTCTR_W,	ILBST_NOMEMB_D, of_rule_stats},
149*10946SSangeeta.Misra@Sun.COM 	{"NOPORTB_D", ILBST_PKTCTR_W,	ILBST_NOPORTB_D, of_rule_stats},
150*10946SSangeeta.Misra@Sun.COM 	{"TIME",    ILBST_TIME_W,	ILBST_TIMESTAMP, of_timestamp},
151*10946SSangeeta.Misra@Sun.COM 	{NULL,	    0, 0, NULL}
152*10946SSangeeta.Misra@Sun.COM };
153*10946SSangeeta.Misra@Sun.COM 
154*10946SSangeeta.Misra@Sun.COM static char stat_stdhdrs[] = "PKT_P,BYTES_P,PKT_U,BYTES_U,PKT_D,BYTES_D";
155*10946SSangeeta.Misra@Sun.COM static char stat_stdv_hdrs[] = "PKT_P,BYTES_P,PKT_U,BYTES_U,PKT_D,BYTES_D,"
156*10946SSangeeta.Misra@Sun.COM 	"ICMP_P,ICMP_D,ICMP2BIG_P,ICMP2BIG_D,NOMEMP_D,NOPORTP_D";
157*10946SSangeeta.Misra@Sun.COM static char stat_itemize_rule_hdrs[] = "SERVERNAME,PKT_P,BYTES_P";
158*10946SSangeeta.Misra@Sun.COM static char stat_itemize_server_hdrs[] = "RULENAME,PKT_P,BYTES_P";
159*10946SSangeeta.Misra@Sun.COM 
160*10946SSangeeta.Misra@Sun.COM #define	RSTAT_SZ	(sizeof (rulestats)/sizeof (rulestats[0]))
161*10946SSangeeta.Misra@Sun.COM #define	SSTAT_SZ	(sizeof (servstats)/sizeof (servstats[0]))
162*10946SSangeeta.Misra@Sun.COM 
163*10946SSangeeta.Misra@Sun.COM typedef struct {
164*10946SSangeeta.Misra@Sun.COM 	char		isd_servername[KSTAT_STRLEN]; /* serverID */
165*10946SSangeeta.Misra@Sun.COM 	ilbst_stat_t	isd_serverstats[SSTAT_SZ];
166*10946SSangeeta.Misra@Sun.COM 	hrtime_t	isd_crtime;	/* save for comparison purpose */
167*10946SSangeeta.Misra@Sun.COM } ilbst_srv_desc_t;
168*10946SSangeeta.Misra@Sun.COM 
169*10946SSangeeta.Misra@Sun.COM /*
170*10946SSangeeta.Misra@Sun.COM  * this data structure stores statistics for a rule - both an old set
171*10946SSangeeta.Misra@Sun.COM  * and a current/new set. we use pointers to the actual stores and switch
172*10946SSangeeta.Misra@Sun.COM  * the pointers for every round. old_is_old in ilbst_arg_t indicates
173*10946SSangeeta.Misra@Sun.COM  * which pointer points to the "old" data struct (ie, if true, _o pointer
174*10946SSangeeta.Misra@Sun.COM  * points to old)
175*10946SSangeeta.Misra@Sun.COM  */
176*10946SSangeeta.Misra@Sun.COM typedef struct {
177*10946SSangeeta.Misra@Sun.COM 	char			ird_rulename[KSTAT_STRLEN];
178*10946SSangeeta.Misra@Sun.COM 	int			ird_num_servers;
179*10946SSangeeta.Misra@Sun.COM 	int			ird_num_servers_o;
180*10946SSangeeta.Misra@Sun.COM 	int			ird_srv_ind;
181*10946SSangeeta.Misra@Sun.COM 	hrtime_t		ird_crtime;	/* save for comparison */
182*10946SSangeeta.Misra@Sun.COM 	hrtime_t		ird_crtime_o;	/* save for comparison */
183*10946SSangeeta.Misra@Sun.COM 	ilbst_srv_desc_t	*ird_srvlist;
184*10946SSangeeta.Misra@Sun.COM 	ilbst_srv_desc_t	*ird_srvlist_o;
185*10946SSangeeta.Misra@Sun.COM 	ilbst_stat_t		ird_rstats[RSTAT_SZ];
186*10946SSangeeta.Misra@Sun.COM 	ilbst_stat_t		ird_rstats_o[RSTAT_SZ];
187*10946SSangeeta.Misra@Sun.COM 	ilbst_stat_t		*ird_rulestats;
188*10946SSangeeta.Misra@Sun.COM 	ilbst_stat_t		*ird_rulestats_o;
189*10946SSangeeta.Misra@Sun.COM } ilbst_rule_desc_t;
190*10946SSangeeta.Misra@Sun.COM 
191*10946SSangeeta.Misra@Sun.COM /*
192*10946SSangeeta.Misra@Sun.COM  * overall "container" for information pertaining to statistics, and
193*10946SSangeeta.Misra@Sun.COM  * how to display them.
194*10946SSangeeta.Misra@Sun.COM  */
195*10946SSangeeta.Misra@Sun.COM typedef struct {
196*10946SSangeeta.Misra@Sun.COM 	int			ilbst_flags;
197*10946SSangeeta.Misra@Sun.COM 	/* fields representing user input */
198*10946SSangeeta.Misra@Sun.COM 	char			*ilbst_rulename;	/* optional */
199*10946SSangeeta.Misra@Sun.COM 	char 			*ilbst_server;	/* optional */
200*10946SSangeeta.Misra@Sun.COM 	int			ilbst_interval;
201*10946SSangeeta.Misra@Sun.COM 	int			ilbst_count;
202*10946SSangeeta.Misra@Sun.COM 	/* "internal" fields for data and data presentation */
203*10946SSangeeta.Misra@Sun.COM 	ofmt_handle_t		ilbst_oh;
204*10946SSangeeta.Misra@Sun.COM 	boolean_t		ilbst_old_is_old;
205*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*ilbst_rlist;
206*10946SSangeeta.Misra@Sun.COM 	int			ilbst_rcount;	  /* current list count */
207*10946SSangeeta.Misra@Sun.COM 	int			ilbst_rcount_prev; /* prev (different) count */
208*10946SSangeeta.Misra@Sun.COM 	int			ilbst_rlist_sz; /* number of alloc'ed rules */
209*10946SSangeeta.Misra@Sun.COM 	int			ilbst_rule_index; /* for itemizes display */
210*10946SSangeeta.Misra@Sun.COM } ilbst_arg_t;
211*10946SSangeeta.Misra@Sun.COM 
212*10946SSangeeta.Misra@Sun.COM /* ARGSUSED */
213*10946SSangeeta.Misra@Sun.COM static boolean_t
of_timestamp(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)214*10946SSangeeta.Misra@Sun.COM of_timestamp(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
215*10946SSangeeta.Misra@Sun.COM {
216*10946SSangeeta.Misra@Sun.COM 	time_t		now;
217*10946SSangeeta.Misra@Sun.COM 	struct tm	*now_tm;
218*10946SSangeeta.Misra@Sun.COM 
219*10946SSangeeta.Misra@Sun.COM 	now = time(NULL);
220*10946SSangeeta.Misra@Sun.COM 	now_tm = localtime(&now);
221*10946SSangeeta.Misra@Sun.COM 
222*10946SSangeeta.Misra@Sun.COM 	(void) strftime(buf, bufsize, "%F:%H.%M.%S", now_tm);
223*10946SSangeeta.Misra@Sun.COM 	return (B_TRUE);
224*10946SSangeeta.Misra@Sun.COM }
225*10946SSangeeta.Misra@Sun.COM 
226*10946SSangeeta.Misra@Sun.COM static boolean_t
i_sum_per_rule_processed(ilbst_rule_desc_t * rp,uint64_t * resp,int index,int flags)227*10946SSangeeta.Misra@Sun.COM i_sum_per_rule_processed(ilbst_rule_desc_t *rp, uint64_t *resp, int index,
228*10946SSangeeta.Misra@Sun.COM     int flags)
229*10946SSangeeta.Misra@Sun.COM {
230*10946SSangeeta.Misra@Sun.COM 	int			i, num_servers;
231*10946SSangeeta.Misra@Sun.COM 	ilbst_srv_desc_t	*srv, *o_srv, *n_srv;
232*10946SSangeeta.Misra@Sun.COM 	uint64_t		res = 0;
233*10946SSangeeta.Misra@Sun.COM 	boolean_t		valid = B_TRUE;
234*10946SSangeeta.Misra@Sun.COM 	boolean_t		old = flags & ILBST_OLD_VALUES;
235*10946SSangeeta.Misra@Sun.COM 	boolean_t		check_valid;
236*10946SSangeeta.Misra@Sun.COM 
237*10946SSangeeta.Misra@Sun.COM 	/* if we do abs. numbers, we never look at the _o fields */
238*10946SSangeeta.Misra@Sun.COM 	assert((old && (flags & ILBST_ABS_NUMBERS)) == B_FALSE);
239*10946SSangeeta.Misra@Sun.COM 
240*10946SSangeeta.Misra@Sun.COM 	/* we only check for validity under certain conditions */
241*10946SSangeeta.Misra@Sun.COM 	check_valid = !(old || (flags & ILBST_ABS_NUMBERS));
242*10946SSangeeta.Misra@Sun.COM 
243*10946SSangeeta.Misra@Sun.COM 	if (check_valid && rp->ird_num_servers != rp->ird_num_servers_o)
244*10946SSangeeta.Misra@Sun.COM 		valid = B_FALSE;
245*10946SSangeeta.Misra@Sun.COM 
246*10946SSangeeta.Misra@Sun.COM 	num_servers = old ? rp->ird_num_servers_o : rp->ird_num_servers;
247*10946SSangeeta.Misra@Sun.COM 
248*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < num_servers; i++) {
249*10946SSangeeta.Misra@Sun.COM 		n_srv = &rp->ird_srvlist[i];
250*10946SSangeeta.Misra@Sun.COM 		o_srv = &rp->ird_srvlist_o[i];
251*10946SSangeeta.Misra@Sun.COM 
252*10946SSangeeta.Misra@Sun.COM 		if (old)
253*10946SSangeeta.Misra@Sun.COM 			srv = o_srv;
254*10946SSangeeta.Misra@Sun.COM 		else
255*10946SSangeeta.Misra@Sun.COM 			srv = n_srv;
256*10946SSangeeta.Misra@Sun.COM 
257*10946SSangeeta.Misra@Sun.COM 		res += srv->isd_serverstats[index].is_value;
258*10946SSangeeta.Misra@Sun.COM 		/*
259*10946SSangeeta.Misra@Sun.COM 		 * if creation times don't match, comparison is wrong; if
260*10946SSangeeta.Misra@Sun.COM 		 * if we already know something is invalid, we don't
261*10946SSangeeta.Misra@Sun.COM 		 * need to compare again.
262*10946SSangeeta.Misra@Sun.COM 		 */
263*10946SSangeeta.Misra@Sun.COM 		if (check_valid && valid == B_TRUE &&
264*10946SSangeeta.Misra@Sun.COM 		    o_srv->isd_crtime != n_srv->isd_crtime) {
265*10946SSangeeta.Misra@Sun.COM 			valid = B_FALSE;
266*10946SSangeeta.Misra@Sun.COM 			break;
267*10946SSangeeta.Misra@Sun.COM 		}
268*10946SSangeeta.Misra@Sun.COM 	}
269*10946SSangeeta.Misra@Sun.COM 	/*
270*10946SSangeeta.Misra@Sun.COM 	 * save the result even though it may be imprecise  - let the
271*10946SSangeeta.Misra@Sun.COM 	 * caller decide what to do
272*10946SSangeeta.Misra@Sun.COM 	 */
273*10946SSangeeta.Misra@Sun.COM 	*resp = res;
274*10946SSangeeta.Misra@Sun.COM 
275*10946SSangeeta.Misra@Sun.COM 	return (valid);
276*10946SSangeeta.Misra@Sun.COM }
277*10946SSangeeta.Misra@Sun.COM 
278*10946SSangeeta.Misra@Sun.COM typedef boolean_t (*sumfunc_t)(ilbst_rule_desc_t *, uint64_t *, int);
279*10946SSangeeta.Misra@Sun.COM 
280*10946SSangeeta.Misra@Sun.COM static boolean_t
i_sum_per_rule_pkt_p(ilbst_rule_desc_t * rp,uint64_t * resp,int flags)281*10946SSangeeta.Misra@Sun.COM i_sum_per_rule_pkt_p(ilbst_rule_desc_t *rp, uint64_t *resp, int flags)
282*10946SSangeeta.Misra@Sun.COM {
283*10946SSangeeta.Misra@Sun.COM 	return (i_sum_per_rule_processed(rp, resp, SRVST_PKT_P, flags));
284*10946SSangeeta.Misra@Sun.COM }
285*10946SSangeeta.Misra@Sun.COM 
286*10946SSangeeta.Misra@Sun.COM static boolean_t
i_sum_per_rule_bytes_p(ilbst_rule_desc_t * rp,uint64_t * resp,int flags)287*10946SSangeeta.Misra@Sun.COM i_sum_per_rule_bytes_p(ilbst_rule_desc_t *rp, uint64_t *resp, int flags)
288*10946SSangeeta.Misra@Sun.COM {
289*10946SSangeeta.Misra@Sun.COM 	return (i_sum_per_rule_processed(rp, resp, SRVST_BYTES_P, flags));
290*10946SSangeeta.Misra@Sun.COM }
291*10946SSangeeta.Misra@Sun.COM 
292*10946SSangeeta.Misra@Sun.COM static boolean_t
of_server_stats(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)293*10946SSangeeta.Misra@Sun.COM of_server_stats(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
294*10946SSangeeta.Misra@Sun.COM {
295*10946SSangeeta.Misra@Sun.COM 	ilbst_arg_t	*sta = (ilbst_arg_t *)of_arg->ofmt_cbarg;
296*10946SSangeeta.Misra@Sun.COM 	uint64_t	count = 0, val;
297*10946SSangeeta.Misra@Sun.COM 	int		i;
298*10946SSangeeta.Misra@Sun.COM 	boolean_t	valid = B_TRUE;
299*10946SSangeeta.Misra@Sun.COM 	sumfunc_t	sumfunc;
300*10946SSangeeta.Misra@Sun.COM 
301*10946SSangeeta.Misra@Sun.COM 	switch (of_arg->ofmt_id) {
302*10946SSangeeta.Misra@Sun.COM 	case ILBST_PKT_P: sumfunc = i_sum_per_rule_pkt_p;
303*10946SSangeeta.Misra@Sun.COM 		break;
304*10946SSangeeta.Misra@Sun.COM 	case ILBST_BYTES_P: sumfunc = i_sum_per_rule_bytes_p;
305*10946SSangeeta.Misra@Sun.COM 		break;
306*10946SSangeeta.Misra@Sun.COM 	}
307*10946SSangeeta.Misra@Sun.COM 
308*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < sta->ilbst_rcount; i++) {
309*10946SSangeeta.Misra@Sun.COM 		valid = sumfunc(&sta->ilbst_rlist[i], &val, sta->ilbst_flags);
310*10946SSangeeta.Misra@Sun.COM 		if (!valid)
311*10946SSangeeta.Misra@Sun.COM 			return (valid);
312*10946SSangeeta.Misra@Sun.COM 		count += val;
313*10946SSangeeta.Misra@Sun.COM 	}
314*10946SSangeeta.Misra@Sun.COM 
315*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & ILBST_ABS_NUMBERS) != 0)
316*10946SSangeeta.Misra@Sun.COM 		goto out;
317*10946SSangeeta.Misra@Sun.COM 
318*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < sta->ilbst_rcount; i++) {
319*10946SSangeeta.Misra@Sun.COM 		(void) sumfunc(&sta->ilbst_rlist[i], &val,
320*10946SSangeeta.Misra@Sun.COM 		    sta->ilbst_flags | ILBST_OLD_VALUES);
321*10946SSangeeta.Misra@Sun.COM 		count -= val;
322*10946SSangeeta.Misra@Sun.COM 	}
323*10946SSangeeta.Misra@Sun.COM 
324*10946SSangeeta.Misra@Sun.COM out:
325*10946SSangeeta.Misra@Sun.COM 	/*
326*10946SSangeeta.Misra@Sun.COM 	 * normally, we print "change per second", which we calculate
327*10946SSangeeta.Misra@Sun.COM 	 * here. otherwise, we print "change over interval"
328*10946SSangeeta.Misra@Sun.COM 	 */
329*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & (ILBST_DELTA_INTERVAL|ILBST_ABS_NUMBERS)) == 0)
330*10946SSangeeta.Misra@Sun.COM 		count /= sta->ilbst_interval;
331*10946SSangeeta.Misra@Sun.COM 
332*10946SSangeeta.Misra@Sun.COM 	(void) snprintf(buf, bufsize, "%llu", count);
333*10946SSangeeta.Misra@Sun.COM 	return (B_TRUE);
334*10946SSangeeta.Misra@Sun.COM }
335*10946SSangeeta.Misra@Sun.COM 
336*10946SSangeeta.Misra@Sun.COM /*
337*10946SSangeeta.Misra@Sun.COM  * this function is called when user wants itemized stats of every
338*10946SSangeeta.Misra@Sun.COM  * server for a named rule, or vice vera.
339*10946SSangeeta.Misra@Sun.COM  * i_do_print sets sta->rule_index and the proper ird_srv_ind so
340*10946SSangeeta.Misra@Sun.COM  * we don't have to differentiate between these two cases here.
341*10946SSangeeta.Misra@Sun.COM  */
342*10946SSangeeta.Misra@Sun.COM static boolean_t
of_itemize_stats(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)343*10946SSangeeta.Misra@Sun.COM of_itemize_stats(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
344*10946SSangeeta.Misra@Sun.COM {
345*10946SSangeeta.Misra@Sun.COM 	ilbst_arg_t	*sta = (ilbst_arg_t *)of_arg->ofmt_cbarg;
346*10946SSangeeta.Misra@Sun.COM 	int		stat_ind;
347*10946SSangeeta.Misra@Sun.COM 	uint64_t	count;
348*10946SSangeeta.Misra@Sun.COM 	int		rule_index = sta->ilbst_rule_index;
349*10946SSangeeta.Misra@Sun.COM 	int		srv_ind = sta->ilbst_rlist[rule_index].ird_srv_ind;
350*10946SSangeeta.Misra@Sun.COM 	boolean_t	ret = B_TRUE;
351*10946SSangeeta.Misra@Sun.COM 	ilbst_srv_desc_t *srv, *osrv;
352*10946SSangeeta.Misra@Sun.COM 
353*10946SSangeeta.Misra@Sun.COM 	srv = &sta->ilbst_rlist[rule_index].ird_srvlist[srv_ind];
354*10946SSangeeta.Misra@Sun.COM 
355*10946SSangeeta.Misra@Sun.COM 	switch (of_arg->ofmt_id) {
356*10946SSangeeta.Misra@Sun.COM 	case ILBST_PKT_P: stat_ind = SRVST_PKT_P;
357*10946SSangeeta.Misra@Sun.COM 		break;
358*10946SSangeeta.Misra@Sun.COM 	case ILBST_BYTES_P: stat_ind = SRVST_BYTES_P;
359*10946SSangeeta.Misra@Sun.COM 		break;
360*10946SSangeeta.Misra@Sun.COM 	case ILBST_ITEMIZE_RNAME:
361*10946SSangeeta.Misra@Sun.COM 		(void) snprintf(buf, bufsize, "%s",
362*10946SSangeeta.Misra@Sun.COM 		    sta->ilbst_rlist[rule_index].ird_rulename);
363*10946SSangeeta.Misra@Sun.COM 		return (B_TRUE);
364*10946SSangeeta.Misra@Sun.COM 		/* not reached */
365*10946SSangeeta.Misra@Sun.COM 		break;
366*10946SSangeeta.Misra@Sun.COM 	case ILBST_ITEMIZE_SNAME:
367*10946SSangeeta.Misra@Sun.COM 		(void) snprintf(buf, bufsize, "%s", srv->isd_servername);
368*10946SSangeeta.Misra@Sun.COM 		return (B_TRUE);
369*10946SSangeeta.Misra@Sun.COM 		/* not reached */
370*10946SSangeeta.Misra@Sun.COM 		break;
371*10946SSangeeta.Misra@Sun.COM 	}
372*10946SSangeeta.Misra@Sun.COM 
373*10946SSangeeta.Misra@Sun.COM 	count = srv->isd_serverstats[stat_ind].is_value;
374*10946SSangeeta.Misra@Sun.COM 
375*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & ILBST_ABS_NUMBERS) != 0)
376*10946SSangeeta.Misra@Sun.COM 		goto out;
377*10946SSangeeta.Misra@Sun.COM 
378*10946SSangeeta.Misra@Sun.COM 	osrv = &sta->ilbst_rlist[rule_index].ird_srvlist_o[srv_ind];
379*10946SSangeeta.Misra@Sun.COM 	if (srv->isd_crtime != osrv->isd_crtime)
380*10946SSangeeta.Misra@Sun.COM 		ret = B_FALSE;
381*10946SSangeeta.Misra@Sun.COM 
382*10946SSangeeta.Misra@Sun.COM 	count -= osrv->isd_serverstats[stat_ind].is_value;
383*10946SSangeeta.Misra@Sun.COM out:
384*10946SSangeeta.Misra@Sun.COM 	/*
385*10946SSangeeta.Misra@Sun.COM 	 * normally, we print "change per second", which we calculate
386*10946SSangeeta.Misra@Sun.COM 	 * here. otherwise, we print "change over interval" or absolute
387*10946SSangeeta.Misra@Sun.COM 	 * values.
388*10946SSangeeta.Misra@Sun.COM 	 */
389*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & (ILBST_DELTA_INTERVAL|ILBST_ABS_NUMBERS)) == 0)
390*10946SSangeeta.Misra@Sun.COM 		count /= sta->ilbst_interval;
391*10946SSangeeta.Misra@Sun.COM 
392*10946SSangeeta.Misra@Sun.COM 	(void) snprintf(buf, bufsize, "%llu", count);
393*10946SSangeeta.Misra@Sun.COM 	return (ret);
394*10946SSangeeta.Misra@Sun.COM 
395*10946SSangeeta.Misra@Sun.COM }
396*10946SSangeeta.Misra@Sun.COM 
397*10946SSangeeta.Misra@Sun.COM static boolean_t
of_rule_stats(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)398*10946SSangeeta.Misra@Sun.COM of_rule_stats(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
399*10946SSangeeta.Misra@Sun.COM {
400*10946SSangeeta.Misra@Sun.COM 	ilbst_arg_t	*sta = (ilbst_arg_t *)of_arg->ofmt_cbarg;
401*10946SSangeeta.Misra@Sun.COM 	int		i, ind;
402*10946SSangeeta.Misra@Sun.COM 	uint64_t	count = 0;
403*10946SSangeeta.Misra@Sun.COM 
404*10946SSangeeta.Misra@Sun.COM 	switch (of_arg->ofmt_id) {
405*10946SSangeeta.Misra@Sun.COM 	case ILBST_PKT_U: ind = RLSTA_PKT_U;
406*10946SSangeeta.Misra@Sun.COM 		break;
407*10946SSangeeta.Misra@Sun.COM 	case ILBST_BYTES_U: ind = RLSTA_BYTES_U;
408*10946SSangeeta.Misra@Sun.COM 		break;
409*10946SSangeeta.Misra@Sun.COM 	case ILBST_PKT_D: ind = RLSTA_PKT_D;
410*10946SSangeeta.Misra@Sun.COM 		break;
411*10946SSangeeta.Misra@Sun.COM 	case ILBST_BYTES_D: ind = RLSTA_BYTES_D;
412*10946SSangeeta.Misra@Sun.COM 		break;
413*10946SSangeeta.Misra@Sun.COM 	case ILBST_ICMP_P: ind = RLSTA_ICMP_P;
414*10946SSangeeta.Misra@Sun.COM 		break;
415*10946SSangeeta.Misra@Sun.COM 	case ILBST_ICMP_D: ind = RLSTA_ICMP_D;
416*10946SSangeeta.Misra@Sun.COM 		break;
417*10946SSangeeta.Misra@Sun.COM 	case ILBST_ICMP2BIG_P: ind = RLSTA_ICMP2BIG_P;
418*10946SSangeeta.Misra@Sun.COM 		break;
419*10946SSangeeta.Misra@Sun.COM 	case ILBST_ICMP2BIG_D: ind = RLSTA_ICMP2BIG_D;
420*10946SSangeeta.Misra@Sun.COM 		break;
421*10946SSangeeta.Misra@Sun.COM 	case ILBST_NOMEMP_D: ind  = RLSTA_NOMEMPKT_D;
422*10946SSangeeta.Misra@Sun.COM 		break;
423*10946SSangeeta.Misra@Sun.COM 	case ILBST_NOPORTP_D: ind = RLSTA_NOPORTPKT_D;
424*10946SSangeeta.Misra@Sun.COM 		break;
425*10946SSangeeta.Misra@Sun.COM 	case ILBST_NOMEMB_D: ind = RLSTA_NOMEMBYTES_D;
426*10946SSangeeta.Misra@Sun.COM 		break;
427*10946SSangeeta.Misra@Sun.COM 	case ILBST_NOPORTB_D: ind = RLSTA_NOPORTBYTES_D;
428*10946SSangeeta.Misra@Sun.COM 		break;
429*10946SSangeeta.Misra@Sun.COM 	}
430*10946SSangeeta.Misra@Sun.COM 
431*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < sta->ilbst_rcount; i++)
432*10946SSangeeta.Misra@Sun.COM 		count += sta->ilbst_rlist[i].ird_rulestats[ind].is_value;
433*10946SSangeeta.Misra@Sun.COM 
434*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & ILBST_ABS_NUMBERS) != 0)
435*10946SSangeeta.Misra@Sun.COM 		goto out;
436*10946SSangeeta.Misra@Sun.COM 
437*10946SSangeeta.Misra@Sun.COM 	/*
438*10946SSangeeta.Misra@Sun.COM 	 * the purist approach: if we can't say 100% that what we
439*10946SSangeeta.Misra@Sun.COM 	 * calculate is correct, don't.
440*10946SSangeeta.Misra@Sun.COM 	 */
441*10946SSangeeta.Misra@Sun.COM 	if (sta->ilbst_flags & ILBST_RULES_CHANGED)
442*10946SSangeeta.Misra@Sun.COM 		return (B_FALSE);
443*10946SSangeeta.Misra@Sun.COM 
444*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < sta->ilbst_rcount; i++) {
445*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_rlist[i].ird_crtime_o != 0 &&
446*10946SSangeeta.Misra@Sun.COM 		    sta->ilbst_rlist[i].ird_crtime !=
447*10946SSangeeta.Misra@Sun.COM 		    sta->ilbst_rlist[i].ird_crtime_o)
448*10946SSangeeta.Misra@Sun.COM 			return (B_FALSE);
449*10946SSangeeta.Misra@Sun.COM 
450*10946SSangeeta.Misra@Sun.COM 		count -= sta->ilbst_rlist[i].ird_rulestats_o[ind].is_value;
451*10946SSangeeta.Misra@Sun.COM 	}
452*10946SSangeeta.Misra@Sun.COM out:
453*10946SSangeeta.Misra@Sun.COM 	/*
454*10946SSangeeta.Misra@Sun.COM 	 * normally, we print "change per second", which we calculate
455*10946SSangeeta.Misra@Sun.COM 	 * here. otherwise, we print "change over interval"
456*10946SSangeeta.Misra@Sun.COM 	 */
457*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & (ILBST_DELTA_INTERVAL|ILBST_ABS_NUMBERS)) == 0)
458*10946SSangeeta.Misra@Sun.COM 		count /= sta->ilbst_interval;
459*10946SSangeeta.Misra@Sun.COM 
460*10946SSangeeta.Misra@Sun.COM 	(void) snprintf(buf, bufsize, "%llu", count);
461*10946SSangeeta.Misra@Sun.COM 	return (B_TRUE);
462*10946SSangeeta.Misra@Sun.COM }
463*10946SSangeeta.Misra@Sun.COM 
464*10946SSangeeta.Misra@Sun.COM /*
465*10946SSangeeta.Misra@Sun.COM  * Get the number of kstat instances. Note that when rules are being
466*10946SSangeeta.Misra@Sun.COM  * drained the number of kstats instances may be different than the
467*10946SSangeeta.Misra@Sun.COM  * kstat counter num_rules (ilb:0:global:num_rules").
468*10946SSangeeta.Misra@Sun.COM  *
469*10946SSangeeta.Misra@Sun.COM  * Also there can be multiple instances of a rule in the following
470*10946SSangeeta.Misra@Sun.COM  * scenario:
471*10946SSangeeta.Misra@Sun.COM  *
472*10946SSangeeta.Misra@Sun.COM  * A rule named rule A has been deleted but remains in kstats because
473*10946SSangeeta.Misra@Sun.COM  * its undergoing connection draining. During this time, the user adds
474*10946SSangeeta.Misra@Sun.COM  * a new rule with the same name(rule A). In this case, there would
475*10946SSangeeta.Misra@Sun.COM  * be two kstats instances for rule A. Currently ilbadm's aggregate
476*10946SSangeeta.Misra@Sun.COM  * results will include data from both instances of rule A. In,
477*10946SSangeeta.Misra@Sun.COM  * future we should have ilbadm stats only consider the latest instance
478*10946SSangeeta.Misra@Sun.COM  * of the rule (ie only consider the the instance that corresponds
479*10946SSangeeta.Misra@Sun.COM  * to the rule that was just added).
480*10946SSangeeta.Misra@Sun.COM  *
481*10946SSangeeta.Misra@Sun.COM  */
482*10946SSangeeta.Misra@Sun.COM static int
i_get_num_kinstances(kstat_ctl_t * kctl)483*10946SSangeeta.Misra@Sun.COM i_get_num_kinstances(kstat_ctl_t *kctl)
484*10946SSangeeta.Misra@Sun.COM {
485*10946SSangeeta.Misra@Sun.COM 	kstat_t		*kp;
486*10946SSangeeta.Misra@Sun.COM 	int		num_instances = 0; /* nothing found, 0 rules */
487*10946SSangeeta.Misra@Sun.COM 
488*10946SSangeeta.Misra@Sun.COM 	for (kp = kctl->kc_chain; kp != NULL; kp = kp->ks_next) {
489*10946SSangeeta.Misra@Sun.COM 		if (strncmp("rulestat", kp->ks_class, 8) == 0 &&
490*10946SSangeeta.Misra@Sun.COM 		    strncmp("ilb", kp->ks_module, 3) == 0) {
491*10946SSangeeta.Misra@Sun.COM 			num_instances++;
492*10946SSangeeta.Misra@Sun.COM 		}
493*10946SSangeeta.Misra@Sun.COM 	}
494*10946SSangeeta.Misra@Sun.COM 
495*10946SSangeeta.Misra@Sun.COM 	return (num_instances);
496*10946SSangeeta.Misra@Sun.COM }
497*10946SSangeeta.Misra@Sun.COM 
498*10946SSangeeta.Misra@Sun.COM 
499*10946SSangeeta.Misra@Sun.COM /*
500*10946SSangeeta.Misra@Sun.COM  * since server stat's classname is made up of <rulename>-sstat,
501*10946SSangeeta.Misra@Sun.COM  * we walk the rule list to construct the comparison
502*10946SSangeeta.Misra@Sun.COM  * Return:	pointer to rule whose name matches the class
503*10946SSangeeta.Misra@Sun.COM  *		NULL if no match
504*10946SSangeeta.Misra@Sun.COM  */
505*10946SSangeeta.Misra@Sun.COM static ilbst_rule_desc_t *
match_2_rnames(char * class,ilbst_rule_desc_t * rlist,int rcount)506*10946SSangeeta.Misra@Sun.COM match_2_rnames(char *class, ilbst_rule_desc_t *rlist, int rcount)
507*10946SSangeeta.Misra@Sun.COM {
508*10946SSangeeta.Misra@Sun.COM 	int i;
509*10946SSangeeta.Misra@Sun.COM 	char	classname[KSTAT_STRLEN];
510*10946SSangeeta.Misra@Sun.COM 
511*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < rcount; i++) {
512*10946SSangeeta.Misra@Sun.COM 		(void) snprintf(classname, sizeof (classname), "%s-sstat",
513*10946SSangeeta.Misra@Sun.COM 		    rlist[i].ird_rulename);
514*10946SSangeeta.Misra@Sun.COM 		if (strncmp(classname, class, sizeof (classname)) == 0)
515*10946SSangeeta.Misra@Sun.COM 			return (&rlist[i]);
516*10946SSangeeta.Misra@Sun.COM 	}
517*10946SSangeeta.Misra@Sun.COM 	return (NULL);
518*10946SSangeeta.Misra@Sun.COM }
519*10946SSangeeta.Misra@Sun.COM 
520*10946SSangeeta.Misra@Sun.COM static int
i_stat_index(kstat_named_t * knp,ilbst_stat_t * stats,int count)521*10946SSangeeta.Misra@Sun.COM i_stat_index(kstat_named_t *knp, ilbst_stat_t *stats, int count)
522*10946SSangeeta.Misra@Sun.COM {
523*10946SSangeeta.Misra@Sun.COM 	int	i;
524*10946SSangeeta.Misra@Sun.COM 
525*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < count; i++) {
526*10946SSangeeta.Misra@Sun.COM 		if (strcasecmp(stats[i].is_name, knp->name) == 0)
527*10946SSangeeta.Misra@Sun.COM 			return (i);
528*10946SSangeeta.Misra@Sun.COM 	}
529*10946SSangeeta.Misra@Sun.COM 
530*10946SSangeeta.Misra@Sun.COM 	return (-1);
531*10946SSangeeta.Misra@Sun.COM }
532*10946SSangeeta.Misra@Sun.COM 
533*10946SSangeeta.Misra@Sun.COM static void
i_copy_sstats(ilbst_srv_desc_t * sp,kstat_t * kp)534*10946SSangeeta.Misra@Sun.COM i_copy_sstats(ilbst_srv_desc_t *sp, kstat_t *kp)
535*10946SSangeeta.Misra@Sun.COM {
536*10946SSangeeta.Misra@Sun.COM 	kstat_named_t	*knp;
537*10946SSangeeta.Misra@Sun.COM 	int		i, ind;
538*10946SSangeeta.Misra@Sun.COM 
539*10946SSangeeta.Misra@Sun.COM 	knp = KSTAT_NAMED_PTR(kp);
540*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < kp->ks_ndata; i++, knp++) {
541*10946SSangeeta.Misra@Sun.COM 		ind = i_stat_index(knp, servstats, SSTAT_SZ);
542*10946SSangeeta.Misra@Sun.COM 		if (ind == -1)
543*10946SSangeeta.Misra@Sun.COM 			continue;
544*10946SSangeeta.Misra@Sun.COM 		(void) strlcpy(sp->isd_serverstats[ind].is_name, knp->name,
545*10946SSangeeta.Misra@Sun.COM 		    sizeof (sp->isd_serverstats[ind].is_name));
546*10946SSangeeta.Misra@Sun.COM 		sp->isd_serverstats[ind].is_value = knp->value.ui64;
547*10946SSangeeta.Misra@Sun.COM 		sp->isd_crtime = kp->ks_crtime;
548*10946SSangeeta.Misra@Sun.COM 	}
549*10946SSangeeta.Misra@Sun.COM }
550*10946SSangeeta.Misra@Sun.COM 
551*10946SSangeeta.Misra@Sun.COM 
552*10946SSangeeta.Misra@Sun.COM static ilbadm_status_t
i_get_server_descs(ilbst_arg_t * sta,kstat_ctl_t * kctl)553*10946SSangeeta.Misra@Sun.COM i_get_server_descs(ilbst_arg_t *sta, kstat_ctl_t *kctl)
554*10946SSangeeta.Misra@Sun.COM {
555*10946SSangeeta.Misra@Sun.COM 	ilbadm_status_t	rc = ILBADM_OK;
556*10946SSangeeta.Misra@Sun.COM 	kstat_t		*kp;
557*10946SSangeeta.Misra@Sun.COM 	int		i = -1;
558*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*rp;
559*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*rlist = sta->ilbst_rlist;
560*10946SSangeeta.Misra@Sun.COM 	int			rcount = sta->ilbst_rcount;
561*10946SSangeeta.Misra@Sun.COM 
562*10946SSangeeta.Misra@Sun.COM 	/*
563*10946SSangeeta.Misra@Sun.COM 	 * find all "server" kstats, or the one specified in
564*10946SSangeeta.Misra@Sun.COM 	 * sta->server
565*10946SSangeeta.Misra@Sun.COM 	 */
566*10946SSangeeta.Misra@Sun.COM 	for (kp = kctl->kc_chain; kp != NULL; kp = kp->ks_next) {
567*10946SSangeeta.Misra@Sun.COM 		if (strncmp("ilb", kp->ks_module, 3) != 0)
568*10946SSangeeta.Misra@Sun.COM 			continue;
569*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_server != NULL &&
570*10946SSangeeta.Misra@Sun.COM 		    strcasecmp(sta->ilbst_server, kp->ks_name) != 0)
571*10946SSangeeta.Misra@Sun.COM 			continue;
572*10946SSangeeta.Misra@Sun.COM 		rp = match_2_rnames(kp->ks_class, rlist, rcount);
573*10946SSangeeta.Misra@Sun.COM 		if (rp == NULL)
574*10946SSangeeta.Misra@Sun.COM 			continue;
575*10946SSangeeta.Misra@Sun.COM 
576*10946SSangeeta.Misra@Sun.COM 		(void) kstat_read(kctl, kp, NULL);
577*10946SSangeeta.Misra@Sun.COM 		i = rp->ird_srv_ind++;
578*10946SSangeeta.Misra@Sun.COM 
579*10946SSangeeta.Misra@Sun.COM 		rc = ILBADM_OK;
580*10946SSangeeta.Misra@Sun.COM 		/*
581*10946SSangeeta.Misra@Sun.COM 		 * This means that a server is added after we check last
582*10946SSangeeta.Misra@Sun.COM 		 * time...  Just make the array bigger.
583*10946SSangeeta.Misra@Sun.COM 		 */
584*10946SSangeeta.Misra@Sun.COM 		if (i+1 > rp->ird_num_servers) {
585*10946SSangeeta.Misra@Sun.COM 			ilbst_srv_desc_t  *srvlist;
586*10946SSangeeta.Misra@Sun.COM 
587*10946SSangeeta.Misra@Sun.COM 			if ((srvlist = realloc(rp->ird_srvlist, (i+1) *
588*10946SSangeeta.Misra@Sun.COM 			    sizeof (*srvlist))) == NULL) {
589*10946SSangeeta.Misra@Sun.COM 				rc = ILBADM_ENOMEM;
590*10946SSangeeta.Misra@Sun.COM 				break;
591*10946SSangeeta.Misra@Sun.COM 			}
592*10946SSangeeta.Misra@Sun.COM 			rp->ird_srvlist = srvlist;
593*10946SSangeeta.Misra@Sun.COM 			rp->ird_num_servers = i;
594*10946SSangeeta.Misra@Sun.COM 		}
595*10946SSangeeta.Misra@Sun.COM 
596*10946SSangeeta.Misra@Sun.COM 		(void) strlcpy(rp->ird_srvlist[i].isd_servername, kp->ks_name,
597*10946SSangeeta.Misra@Sun.COM 		    sizeof (rp->ird_srvlist[i].isd_servername));
598*10946SSangeeta.Misra@Sun.COM 		i_copy_sstats(&rp->ird_srvlist[i], kp);
599*10946SSangeeta.Misra@Sun.COM 	}
600*10946SSangeeta.Misra@Sun.COM 
601*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < rcount; i++)
602*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_srv_ind = 0;
603*10946SSangeeta.Misra@Sun.COM 
604*10946SSangeeta.Misra@Sun.COM 	if (sta->ilbst_server != NULL && i == -1)
605*10946SSangeeta.Misra@Sun.COM 		rc = ILBADM_ENOSERVER;
606*10946SSangeeta.Misra@Sun.COM 	return (rc);
607*10946SSangeeta.Misra@Sun.COM }
608*10946SSangeeta.Misra@Sun.COM 
609*10946SSangeeta.Misra@Sun.COM static void
i_copy_rstats(ilbst_rule_desc_t * rp,kstat_t * kp)610*10946SSangeeta.Misra@Sun.COM i_copy_rstats(ilbst_rule_desc_t *rp, kstat_t *kp)
611*10946SSangeeta.Misra@Sun.COM {
612*10946SSangeeta.Misra@Sun.COM 	kstat_named_t	*knp;
613*10946SSangeeta.Misra@Sun.COM 	int		i, ind;
614*10946SSangeeta.Misra@Sun.COM 
615*10946SSangeeta.Misra@Sun.COM 	knp = KSTAT_NAMED_PTR(kp);
616*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < kp->ks_ndata; i++, knp++) {
617*10946SSangeeta.Misra@Sun.COM 		ind = i_stat_index(knp, rulestats, RSTAT_SZ);
618*10946SSangeeta.Misra@Sun.COM 		if (ind == -1)
619*10946SSangeeta.Misra@Sun.COM 			continue;
620*10946SSangeeta.Misra@Sun.COM 
621*10946SSangeeta.Misra@Sun.COM 		(void) strlcpy(rp->ird_rulestats[ind].is_name, knp->name,
622*10946SSangeeta.Misra@Sun.COM 		    sizeof (rp->ird_rulestats[ind].is_name));
623*10946SSangeeta.Misra@Sun.COM 		rp->ird_rulestats[ind].is_value = knp->value.ui64;
624*10946SSangeeta.Misra@Sun.COM 	}
625*10946SSangeeta.Misra@Sun.COM }
626*10946SSangeeta.Misra@Sun.COM 
627*10946SSangeeta.Misra@Sun.COM static void
i_set_rlstats_ptr(ilbst_rule_desc_t * rp,boolean_t old_is_old)628*10946SSangeeta.Misra@Sun.COM i_set_rlstats_ptr(ilbst_rule_desc_t *rp, boolean_t old_is_old)
629*10946SSangeeta.Misra@Sun.COM {
630*10946SSangeeta.Misra@Sun.COM 	if (old_is_old) {
631*10946SSangeeta.Misra@Sun.COM 		rp->ird_rulestats = rp->ird_rstats;
632*10946SSangeeta.Misra@Sun.COM 		rp->ird_rulestats_o = rp->ird_rstats_o;
633*10946SSangeeta.Misra@Sun.COM 	} else {
634*10946SSangeeta.Misra@Sun.COM 		rp->ird_rulestats = rp->ird_rstats_o;
635*10946SSangeeta.Misra@Sun.COM 		rp->ird_rulestats_o = rp->ird_rstats;
636*10946SSangeeta.Misra@Sun.COM 	}
637*10946SSangeeta.Misra@Sun.COM }
638*10946SSangeeta.Misra@Sun.COM /*
639*10946SSangeeta.Misra@Sun.COM  * this function walks the array of rules and switches pointer to old
640*10946SSangeeta.Misra@Sun.COM  * and new stats as well as serverlists.
641*10946SSangeeta.Misra@Sun.COM  */
642*10946SSangeeta.Misra@Sun.COM static void
i_swap_rl_pointers(ilbst_arg_t * sta,int rcount)643*10946SSangeeta.Misra@Sun.COM i_swap_rl_pointers(ilbst_arg_t *sta, int rcount)
644*10946SSangeeta.Misra@Sun.COM {
645*10946SSangeeta.Misra@Sun.COM 	int			i, tmp_num;
646*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*rlist = sta->ilbst_rlist;
647*10946SSangeeta.Misra@Sun.COM 	ilbst_srv_desc_t	*tmp_srv;
648*10946SSangeeta.Misra@Sun.COM 
649*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < rcount; i++) {
650*10946SSangeeta.Misra@Sun.COM 		/* swap srvlist pointers */
651*10946SSangeeta.Misra@Sun.COM 		tmp_srv = rlist[i].ird_srvlist;
652*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_srvlist = rlist[i].ird_srvlist_o;
653*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_srvlist_o = tmp_srv;
654*10946SSangeeta.Misra@Sun.COM 
655*10946SSangeeta.Misra@Sun.COM 		/*
656*10946SSangeeta.Misra@Sun.COM 		 * swap server counts - we need the old one to
657*10946SSangeeta.Misra@Sun.COM 		 * save reallocation calls
658*10946SSangeeta.Misra@Sun.COM 		 */
659*10946SSangeeta.Misra@Sun.COM 		tmp_num = rlist[i].ird_num_servers_o;
660*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_num_servers_o = rlist[i].ird_num_servers;
661*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_num_servers = tmp_num;
662*10946SSangeeta.Misra@Sun.COM 
663*10946SSangeeta.Misra@Sun.COM 		/* preserve creation time */
664*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_crtime_o = rlist[i].ird_crtime;
665*10946SSangeeta.Misra@Sun.COM 
666*10946SSangeeta.Misra@Sun.COM 		i_set_rlstats_ptr(&rlist[i], sta->ilbst_old_is_old);
667*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_srv_ind = 0;
668*10946SSangeeta.Misra@Sun.COM 	}
669*10946SSangeeta.Misra@Sun.COM }
670*10946SSangeeta.Misra@Sun.COM 
671*10946SSangeeta.Misra@Sun.COM static void
i_init_rulelist(ilbst_arg_t * sta,int rcount)672*10946SSangeeta.Misra@Sun.COM i_init_rulelist(ilbst_arg_t *sta, int rcount)
673*10946SSangeeta.Misra@Sun.COM {
674*10946SSangeeta.Misra@Sun.COM 	int			 i;
675*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*rlist = sta->ilbst_rlist;
676*10946SSangeeta.Misra@Sun.COM 
677*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < rcount; i++) {
678*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_rulestats = rlist[i].ird_rstats;
679*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_rulestats_o = rlist[i].ird_rstats_o;
680*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_srv_ind = 0;
681*10946SSangeeta.Misra@Sun.COM 	}
682*10946SSangeeta.Misra@Sun.COM }
683*10946SSangeeta.Misra@Sun.COM 
684*10946SSangeeta.Misra@Sun.COM 
685*10946SSangeeta.Misra@Sun.COM /*
686*10946SSangeeta.Misra@Sun.COM  * this function searches for kstats describing individual rules and
687*10946SSangeeta.Misra@Sun.COM  * saves name, # of servers, and the kstat_t * describing them (this is
688*10946SSangeeta.Misra@Sun.COM  * for sta->rulename == NULL);
689*10946SSangeeta.Misra@Sun.COM  * if sta->rulename != NULL, it names the rule we're looking for
690*10946SSangeeta.Misra@Sun.COM  * and this function will fill in the other data (like the all_rules case)
691*10946SSangeeta.Misra@Sun.COM  * Returns:	ILBADM_ENORULE	named rule not found
692*10946SSangeeta.Misra@Sun.COM  *		ILBADM_ENOMEM	no mem. available
693*10946SSangeeta.Misra@Sun.COM  */
694*10946SSangeeta.Misra@Sun.COM static ilbadm_status_t
i_get_rule_descs(ilbst_arg_t * sta,kstat_ctl_t * kctl)695*10946SSangeeta.Misra@Sun.COM i_get_rule_descs(ilbst_arg_t *sta, kstat_ctl_t *kctl)
696*10946SSangeeta.Misra@Sun.COM {
697*10946SSangeeta.Misra@Sun.COM 	ilbadm_status_t	rc = ILBADM_OK;
698*10946SSangeeta.Misra@Sun.COM 	kstat_t		*kp;
699*10946SSangeeta.Misra@Sun.COM 	kstat_named_t	*knp;
700*10946SSangeeta.Misra@Sun.COM 	int		i;
701*10946SSangeeta.Misra@Sun.COM 	int		num_servers;
702*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*rlist = sta->ilbst_rlist;
703*10946SSangeeta.Misra@Sun.COM 	int		rcount = sta->ilbst_rcount;
704*10946SSangeeta.Misra@Sun.COM 
705*10946SSangeeta.Misra@Sun.COM 	/*
706*10946SSangeeta.Misra@Sun.COM 	 * find all "rule" kstats, or the one specified in
707*10946SSangeeta.Misra@Sun.COM 	 * sta->ilbst_rulename.
708*10946SSangeeta.Misra@Sun.COM 	 */
709*10946SSangeeta.Misra@Sun.COM 	for (i = 0, kp = kctl->kc_chain; i < rcount && kp != NULL;
710*10946SSangeeta.Misra@Sun.COM 	    kp = kp->ks_next) {
711*10946SSangeeta.Misra@Sun.COM 		if (strncmp("rulestat", kp->ks_class, 8) != 0 ||
712*10946SSangeeta.Misra@Sun.COM 		    strncmp("ilb", kp->ks_module, 3) != 0)
713*10946SSangeeta.Misra@Sun.COM 			continue;
714*10946SSangeeta.Misra@Sun.COM 
715*10946SSangeeta.Misra@Sun.COM 		(void) kstat_read(kctl, kp, NULL);
716*10946SSangeeta.Misra@Sun.COM 
717*10946SSangeeta.Misra@Sun.COM 		knp = kstat_data_lookup(kp, "num_servers");
718*10946SSangeeta.Misra@Sun.COM 		if (knp == NULL) {
719*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("kstat_data_lookup() failed: %s"),
720*10946SSangeeta.Misra@Sun.COM 			    strerror(errno));
721*10946SSangeeta.Misra@Sun.COM 			rc = ILBADM_LIBERR;
722*10946SSangeeta.Misra@Sun.COM 			break;
723*10946SSangeeta.Misra@Sun.COM 		}
724*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_rulename != NULL) {
725*10946SSangeeta.Misra@Sun.COM 			if (strcasecmp(kp->ks_name, sta->ilbst_rulename)
726*10946SSangeeta.Misra@Sun.COM 			    != 0)
727*10946SSangeeta.Misra@Sun.COM 				continue;
728*10946SSangeeta.Misra@Sun.COM 		}
729*10946SSangeeta.Misra@Sun.COM 		(void) strlcpy(rlist[i].ird_rulename, kp->ks_name,
730*10946SSangeeta.Misra@Sun.COM 		    sizeof (rlist[i].ird_rulename));
731*10946SSangeeta.Misra@Sun.COM 
732*10946SSangeeta.Misra@Sun.COM 		/* only alloc the space we need, set counter here ... */
733*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_server != NULL)
734*10946SSangeeta.Misra@Sun.COM 			num_servers = 1;
735*10946SSangeeta.Misra@Sun.COM 		else
736*10946SSangeeta.Misra@Sun.COM 			num_servers = (int)knp->value.ui64;
737*10946SSangeeta.Misra@Sun.COM 
738*10946SSangeeta.Misra@Sun.COM 		/* ... furthermore, only reallocate if necessary */
739*10946SSangeeta.Misra@Sun.COM 		if (num_servers != rlist[i].ird_num_servers) {
740*10946SSangeeta.Misra@Sun.COM 			ilbst_srv_desc_t  *srvlist;
741*10946SSangeeta.Misra@Sun.COM 
742*10946SSangeeta.Misra@Sun.COM 			rlist[i].ird_num_servers = num_servers;
743*10946SSangeeta.Misra@Sun.COM 
744*10946SSangeeta.Misra@Sun.COM 			if (rlist[i].ird_srvlist == NULL)
745*10946SSangeeta.Misra@Sun.COM 				srvlist = calloc(num_servers,
746*10946SSangeeta.Misra@Sun.COM 				    sizeof (*srvlist));
747*10946SSangeeta.Misra@Sun.COM 			else
748*10946SSangeeta.Misra@Sun.COM 				srvlist = realloc(rlist[i].ird_srvlist,
749*10946SSangeeta.Misra@Sun.COM 				    sizeof (*srvlist) * num_servers);
750*10946SSangeeta.Misra@Sun.COM 			if (srvlist == NULL) {
751*10946SSangeeta.Misra@Sun.COM 				rc = ILBADM_ENOMEM;
752*10946SSangeeta.Misra@Sun.COM 				break;
753*10946SSangeeta.Misra@Sun.COM 			}
754*10946SSangeeta.Misra@Sun.COM 			rlist[i].ird_srvlist = srvlist;
755*10946SSangeeta.Misra@Sun.COM 		}
756*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_srv_ind = 0;
757*10946SSangeeta.Misra@Sun.COM 		rlist[i].ird_crtime = kp->ks_crtime;
758*10946SSangeeta.Misra@Sun.COM 
759*10946SSangeeta.Misra@Sun.COM 		i_copy_rstats(&rlist[i], kp);
760*10946SSangeeta.Misra@Sun.COM 		i++;
761*10946SSangeeta.Misra@Sun.COM 
762*10946SSangeeta.Misra@Sun.COM 		/* if we know we're done, return */
763*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_rulename != NULL || i == rcount) {
764*10946SSangeeta.Misra@Sun.COM 			rc = ILBADM_OK;
765*10946SSangeeta.Misra@Sun.COM 			break;
766*10946SSangeeta.Misra@Sun.COM 		}
767*10946SSangeeta.Misra@Sun.COM 	}
768*10946SSangeeta.Misra@Sun.COM 
769*10946SSangeeta.Misra@Sun.COM 	if (sta->ilbst_rulename != NULL && i == 0)
770*10946SSangeeta.Misra@Sun.COM 		rc = ILBADM_ENORULE;
771*10946SSangeeta.Misra@Sun.COM 	return (rc);
772*10946SSangeeta.Misra@Sun.COM }
773*10946SSangeeta.Misra@Sun.COM 
774*10946SSangeeta.Misra@Sun.COM static void
i_do_print(ilbst_arg_t * sta)775*10946SSangeeta.Misra@Sun.COM i_do_print(ilbst_arg_t *sta)
776*10946SSangeeta.Misra@Sun.COM {
777*10946SSangeeta.Misra@Sun.COM 	int	i;
778*10946SSangeeta.Misra@Sun.COM 
779*10946SSangeeta.Misra@Sun.COM 	/* non-itemized display can go right ahead */
780*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & ILBST_ITEMIZE) == 0) {
781*10946SSangeeta.Misra@Sun.COM 		ofmt_print(sta->ilbst_oh, sta);
782*10946SSangeeta.Misra@Sun.COM 		return;
783*10946SSangeeta.Misra@Sun.COM 	}
784*10946SSangeeta.Misra@Sun.COM 
785*10946SSangeeta.Misra@Sun.COM 	/*
786*10946SSangeeta.Misra@Sun.COM 	 * rulename is given, list a line per server
787*10946SSangeeta.Misra@Sun.COM 	 * here's how we do it:
788*10946SSangeeta.Misra@Sun.COM 	 *	the _ITEMIZE flag indicates to the print function (called
789*10946SSangeeta.Misra@Sun.COM 	 *	from ofmt_print()) to look at server [ird_srv_ind] only.
790*10946SSangeeta.Misra@Sun.COM 	 */
791*10946SSangeeta.Misra@Sun.COM 	if (sta->ilbst_rulename != NULL) {
792*10946SSangeeta.Misra@Sun.COM 		sta->ilbst_rule_index = 0;
793*10946SSangeeta.Misra@Sun.COM 		for (i = 0; i < sta->ilbst_rlist->ird_num_servers; i++) {
794*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_rlist->ird_srv_ind = i;
795*10946SSangeeta.Misra@Sun.COM 			ofmt_print(sta->ilbst_oh, sta);
796*10946SSangeeta.Misra@Sun.COM 		}
797*10946SSangeeta.Misra@Sun.COM 		sta->ilbst_rlist->ird_srv_ind = 0;
798*10946SSangeeta.Misra@Sun.COM 		return;
799*10946SSangeeta.Misra@Sun.COM 	}
800*10946SSangeeta.Misra@Sun.COM 
801*10946SSangeeta.Misra@Sun.COM 	/* list one line for every rule for a given server */
802*10946SSangeeta.Misra@Sun.COM 	for (i = 0; i < sta->ilbst_rcount; i++) {
803*10946SSangeeta.Misra@Sun.COM 		/*
804*10946SSangeeta.Misra@Sun.COM 		 * if a rule doesn't contain a given server, there's no
805*10946SSangeeta.Misra@Sun.COM 		 * need to print it. Luckily, we can check that
806*10946SSangeeta.Misra@Sun.COM 		 * fairly easily
807*10946SSangeeta.Misra@Sun.COM 		 */
808*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_rlist[i].ird_srvlist[0].isd_servername[0] ==
809*10946SSangeeta.Misra@Sun.COM 		    '\0')
810*10946SSangeeta.Misra@Sun.COM 			continue;
811*10946SSangeeta.Misra@Sun.COM 
812*10946SSangeeta.Misra@Sun.COM 		sta->ilbst_rule_index = i;
813*10946SSangeeta.Misra@Sun.COM 		sta->ilbst_rlist[i].ird_srv_ind = 0;
814*10946SSangeeta.Misra@Sun.COM 		ofmt_print(sta->ilbst_oh, sta);
815*10946SSangeeta.Misra@Sun.COM 	}
816*10946SSangeeta.Misra@Sun.COM 	sta->ilbst_rule_index = 0;
817*10946SSangeeta.Misra@Sun.COM }
818*10946SSangeeta.Misra@Sun.COM 
819*10946SSangeeta.Misra@Sun.COM static ilbadm_status_t
i_do_show_stats(ilbst_arg_t * sta)820*10946SSangeeta.Misra@Sun.COM i_do_show_stats(ilbst_arg_t *sta)
821*10946SSangeeta.Misra@Sun.COM {
822*10946SSangeeta.Misra@Sun.COM 	kstat_ctl_t	*kctl;
823*10946SSangeeta.Misra@Sun.COM 	kid_t		nkid;
824*10946SSangeeta.Misra@Sun.COM 	int		rcount = 1, i;
825*10946SSangeeta.Misra@Sun.COM 	ilbadm_status_t	rc = ILBADM_OK;
826*10946SSangeeta.Misra@Sun.COM 	ilbst_rule_desc_t	*rlist, *rp;
827*10946SSangeeta.Misra@Sun.COM 	boolean_t	pseudo_abs = B_FALSE; /* for first pass */
828*10946SSangeeta.Misra@Sun.COM 
829*10946SSangeeta.Misra@Sun.COM 	if ((kctl = kstat_open()) == NULL) {
830*10946SSangeeta.Misra@Sun.COM 		ilbadm_err(gettext("kstat_open() failed: %s"), strerror(errno));
831*10946SSangeeta.Misra@Sun.COM 		return (ILBADM_LIBERR);
832*10946SSangeeta.Misra@Sun.COM 	}
833*10946SSangeeta.Misra@Sun.COM 
834*10946SSangeeta.Misra@Sun.COM 
835*10946SSangeeta.Misra@Sun.COM 	if (sta->ilbst_rulename == NULL)
836*10946SSangeeta.Misra@Sun.COM 		rcount = i_get_num_kinstances(kctl);
837*10946SSangeeta.Misra@Sun.COM 
838*10946SSangeeta.Misra@Sun.COM 	rlist = calloc(sizeof (*rlist), rcount);
839*10946SSangeeta.Misra@Sun.COM 	if (rlist == NULL) {
840*10946SSangeeta.Misra@Sun.COM 		rc = ILBADM_ENOMEM;
841*10946SSangeeta.Misra@Sun.COM 		goto out;
842*10946SSangeeta.Misra@Sun.COM 	}
843*10946SSangeeta.Misra@Sun.COM 
844*10946SSangeeta.Misra@Sun.COM 	sta->ilbst_old_is_old = B_TRUE;
845*10946SSangeeta.Misra@Sun.COM 	sta->ilbst_rlist = rlist;
846*10946SSangeeta.Misra@Sun.COM 	sta->ilbst_rcount = sta->ilbst_rcount_prev = rcount;
847*10946SSangeeta.Misra@Sun.COM 	sta->ilbst_rlist_sz = rcount;
848*10946SSangeeta.Misra@Sun.COM 
849*10946SSangeeta.Misra@Sun.COM 	/*
850*10946SSangeeta.Misra@Sun.COM 	 * in the first pass, we always print absolute numbers. We
851*10946SSangeeta.Misra@Sun.COM 	 * need to remember whether we wanted abs. numbers for
852*10946SSangeeta.Misra@Sun.COM 	 * other samples as well
853*10946SSangeeta.Misra@Sun.COM 	 */
854*10946SSangeeta.Misra@Sun.COM 	if ((sta->ilbst_flags & ILBST_ABS_NUMBERS) == 0) {
855*10946SSangeeta.Misra@Sun.COM 		sta->ilbst_flags |= ILBST_ABS_NUMBERS;
856*10946SSangeeta.Misra@Sun.COM 		pseudo_abs = B_TRUE;
857*10946SSangeeta.Misra@Sun.COM 	}
858*10946SSangeeta.Misra@Sun.COM 
859*10946SSangeeta.Misra@Sun.COM 	i_init_rulelist(sta, rcount);
860*10946SSangeeta.Misra@Sun.COM 	do {
861*10946SSangeeta.Misra@Sun.COM 		rc = i_get_rule_descs(sta, kctl);
862*10946SSangeeta.Misra@Sun.COM 		if (rc != ILBADM_OK)
863*10946SSangeeta.Misra@Sun.COM 			goto out;
864*10946SSangeeta.Misra@Sun.COM 
865*10946SSangeeta.Misra@Sun.COM 		rc = i_get_server_descs(sta, kctl);
866*10946SSangeeta.Misra@Sun.COM 		if (rc != ILBADM_OK)
867*10946SSangeeta.Misra@Sun.COM 			goto out;
868*10946SSangeeta.Misra@Sun.COM 
869*10946SSangeeta.Misra@Sun.COM 		i_do_print(sta);
870*10946SSangeeta.Misra@Sun.COM 
871*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_count == -1 || --(sta->ilbst_count) > 0)
872*10946SSangeeta.Misra@Sun.COM 			(void) sleep(sta->ilbst_interval);
873*10946SSangeeta.Misra@Sun.COM 		else
874*10946SSangeeta.Misra@Sun.COM 			break;
875*10946SSangeeta.Misra@Sun.COM 
876*10946SSangeeta.Misra@Sun.COM 		nkid = kstat_chain_update(kctl);
877*10946SSangeeta.Misra@Sun.COM 		sta->ilbst_flags &= ~ILBST_RULES_CHANGED;
878*10946SSangeeta.Misra@Sun.COM 		/*
879*10946SSangeeta.Misra@Sun.COM 		 * we only need to continue with most of the rest of this if
880*10946SSangeeta.Misra@Sun.COM 		 * the kstat chain id has changed
881*10946SSangeeta.Misra@Sun.COM 		 */
882*10946SSangeeta.Misra@Sun.COM 		if (nkid == 0)
883*10946SSangeeta.Misra@Sun.COM 			goto swap_old_new;
884*10946SSangeeta.Misra@Sun.COM 		if (nkid == -1) {
885*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("kstat_chain_update() failed: %s"),
886*10946SSangeeta.Misra@Sun.COM 			    strerror(errno));
887*10946SSangeeta.Misra@Sun.COM 			rc = ILBADM_LIBERR;
888*10946SSangeeta.Misra@Sun.COM 			break;
889*10946SSangeeta.Misra@Sun.COM 		}
890*10946SSangeeta.Misra@Sun.COM 
891*10946SSangeeta.Misra@Sun.COM 		/*
892*10946SSangeeta.Misra@Sun.COM 		 * find out whether the number of rules has changed.
893*10946SSangeeta.Misra@Sun.COM 		 * if so, adjust rcount and _o; if number has increased,
894*10946SSangeeta.Misra@Sun.COM 		 * expand array to hold all rules.
895*10946SSangeeta.Misra@Sun.COM 		 * we only shrink if rlist_sz is larger than both rcount and
896*10946SSangeeta.Misra@Sun.COM 		 * rcount_prev;
897*10946SSangeeta.Misra@Sun.COM 		 */
898*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_rulename == NULL)
899*10946SSangeeta.Misra@Sun.COM 			rcount = i_get_num_kinstances(kctl);
900*10946SSangeeta.Misra@Sun.COM 		if (rcount != sta->ilbst_rcount) {
901*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_flags |= ILBST_RULES_CHANGED;
902*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_rcount_prev = sta->ilbst_rcount;
903*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_rcount = rcount;
904*10946SSangeeta.Misra@Sun.COM 
905*10946SSangeeta.Misra@Sun.COM 			if (rcount > sta->ilbst_rcount_prev) {
906*10946SSangeeta.Misra@Sun.COM 				rlist = realloc(sta->ilbst_rlist,
907*10946SSangeeta.Misra@Sun.COM 				    sizeof (*sta->ilbst_rlist) * rcount);
908*10946SSangeeta.Misra@Sun.COM 				if (rlist == NULL) {
909*10946SSangeeta.Misra@Sun.COM 					rc = ILBADM_ENOMEM;
910*10946SSangeeta.Misra@Sun.COM 					break;
911*10946SSangeeta.Misra@Sun.COM 				}
912*10946SSangeeta.Misra@Sun.COM 				sta->ilbst_rlist = rlist;
913*10946SSangeeta.Misra@Sun.COM 				/* realloc doesn't zero out memory */
914*10946SSangeeta.Misra@Sun.COM 				for (i = sta->ilbst_rcount_prev;
915*10946SSangeeta.Misra@Sun.COM 				    i < rcount; i++) {
916*10946SSangeeta.Misra@Sun.COM 					rp = &sta->ilbst_rlist[i];
917*10946SSangeeta.Misra@Sun.COM 					bzero(rp, sizeof (*rp));
918*10946SSangeeta.Misra@Sun.COM 					i_set_rlstats_ptr(rp,
919*10946SSangeeta.Misra@Sun.COM 					    sta->ilbst_old_is_old);
920*10946SSangeeta.Misra@Sun.COM 				}
921*10946SSangeeta.Misra@Sun.COM 				/*
922*10946SSangeeta.Misra@Sun.COM 				 * even if rlist_sz was > rcount, it's now
923*10946SSangeeta.Misra@Sun.COM 				 * shrunk to rcount
924*10946SSangeeta.Misra@Sun.COM 				 */
925*10946SSangeeta.Misra@Sun.COM 				sta->ilbst_rlist_sz = sta->ilbst_rcount;
926*10946SSangeeta.Misra@Sun.COM 			}
927*10946SSangeeta.Misra@Sun.COM 		}
928*10946SSangeeta.Misra@Sun.COM 
929*10946SSangeeta.Misra@Sun.COM 		/*
930*10946SSangeeta.Misra@Sun.COM 		 * we may need to shrink the allocated slots down to the
931*10946SSangeeta.Misra@Sun.COM 		 * actually required number - we need to make sure we
932*10946SSangeeta.Misra@Sun.COM 		 * don't delete old or new stats.
933*10946SSangeeta.Misra@Sun.COM 		 */
934*10946SSangeeta.Misra@Sun.COM 		if (sta->ilbst_rlist_sz > MAX(sta->ilbst_rcount,
935*10946SSangeeta.Misra@Sun.COM 		    sta->ilbst_rcount_prev)) {
936*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_rlist_sz =
937*10946SSangeeta.Misra@Sun.COM 			    MAX(sta->ilbst_rcount, sta->ilbst_rcount_prev);
938*10946SSangeeta.Misra@Sun.COM 			rlist = realloc(sta->ilbst_rlist,
939*10946SSangeeta.Misra@Sun.COM 			    sizeof (*sta->ilbst_rlist) * sta->ilbst_rlist_sz);
940*10946SSangeeta.Misra@Sun.COM 			if (rlist == NULL) {
941*10946SSangeeta.Misra@Sun.COM 				rc = ILBADM_ENOMEM;
942*10946SSangeeta.Misra@Sun.COM 				break;
943*10946SSangeeta.Misra@Sun.COM 			}
944*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_rlist = rlist;
945*10946SSangeeta.Misra@Sun.COM 		}
946*10946SSangeeta.Misra@Sun.COM 
947*10946SSangeeta.Misra@Sun.COM 		/*
948*10946SSangeeta.Misra@Sun.COM 		 * move pointers around so what used to point to "old"
949*10946SSangeeta.Misra@Sun.COM 		 * stats now points to new, and vice versa
950*10946SSangeeta.Misra@Sun.COM 		 * if we're printing absolute numbers, this rigmarole is
951*10946SSangeeta.Misra@Sun.COM 		 * not necessary.
952*10946SSangeeta.Misra@Sun.COM 		 */
953*10946SSangeeta.Misra@Sun.COM swap_old_new:
954*10946SSangeeta.Misra@Sun.COM 		if (pseudo_abs)
955*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_flags &= ~ILBST_ABS_NUMBERS;
956*10946SSangeeta.Misra@Sun.COM 
957*10946SSangeeta.Misra@Sun.COM 		if ((sta->ilbst_flags & ILBST_ABS_NUMBERS) == 0) {
958*10946SSangeeta.Misra@Sun.COM 			sta->ilbst_old_is_old = !sta->ilbst_old_is_old;
959*10946SSangeeta.Misra@Sun.COM 			i_swap_rl_pointers(sta, rcount);
960*10946SSangeeta.Misra@Sun.COM 		}
961*10946SSangeeta.Misra@Sun.COM 		_NOTE(CONSTCOND)
962*10946SSangeeta.Misra@Sun.COM 	} while (B_TRUE);
963*10946SSangeeta.Misra@Sun.COM 
964*10946SSangeeta.Misra@Sun.COM out:
965*10946SSangeeta.Misra@Sun.COM 	(void) kstat_close(kctl);
966*10946SSangeeta.Misra@Sun.COM 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
967*10946SSangeeta.Misra@Sun.COM 		ilbadm_err(ilbadm_errstr(rc));
968*10946SSangeeta.Misra@Sun.COM 
969*10946SSangeeta.Misra@Sun.COM 	if (sta->ilbst_rlist != NULL)
970*10946SSangeeta.Misra@Sun.COM 		free(sta->ilbst_rlist);
971*10946SSangeeta.Misra@Sun.COM 
972*10946SSangeeta.Misra@Sun.COM 	return (rc);
973*10946SSangeeta.Misra@Sun.COM }
974*10946SSangeeta.Misra@Sun.COM 
975*10946SSangeeta.Misra@Sun.COM /*
976*10946SSangeeta.Misra@Sun.COM  * read ilb's kernel statistics and (periodically) display
977*10946SSangeeta.Misra@Sun.COM  * them.
978*10946SSangeeta.Misra@Sun.COM  */
979*10946SSangeeta.Misra@Sun.COM /* ARGSUSED */
980*10946SSangeeta.Misra@Sun.COM ilbadm_status_t
ilbadm_show_stats(int argc,char * argv[])981*10946SSangeeta.Misra@Sun.COM ilbadm_show_stats(int argc, char *argv[])
982*10946SSangeeta.Misra@Sun.COM {
983*10946SSangeeta.Misra@Sun.COM 	ilbadm_status_t	rc;
984*10946SSangeeta.Misra@Sun.COM 	int		c;
985*10946SSangeeta.Misra@Sun.COM 	ilbst_arg_t	sta;
986*10946SSangeeta.Misra@Sun.COM 	int		oflags = 0;
987*10946SSangeeta.Misra@Sun.COM 	char		*fieldnames = stat_stdhdrs;
988*10946SSangeeta.Misra@Sun.COM 	ofmt_field_t	*fields = stat_stdfields;
989*10946SSangeeta.Misra@Sun.COM 	boolean_t	r_opt = B_FALSE, s_opt = B_FALSE, i_opt = B_FALSE;
990*10946SSangeeta.Misra@Sun.COM 	boolean_t	o_opt = B_FALSE, p_opt = B_FALSE, t_opt = B_FALSE;
991*10946SSangeeta.Misra@Sun.COM 	boolean_t	v_opt = B_FALSE, A_opt = B_FALSE, d_opt = B_FALSE;
992*10946SSangeeta.Misra@Sun.COM 	ofmt_status_t	oerr;
993*10946SSangeeta.Misra@Sun.COM 	ofmt_handle_t	oh = NULL;
994*10946SSangeeta.Misra@Sun.COM 
995*10946SSangeeta.Misra@Sun.COM 	bzero(&sta, sizeof (sta));
996*10946SSangeeta.Misra@Sun.COM 	sta.ilbst_interval = 1;
997*10946SSangeeta.Misra@Sun.COM 	sta.ilbst_count = 1;
998*10946SSangeeta.Misra@Sun.COM 
999*10946SSangeeta.Misra@Sun.COM 	while ((c = getopt(argc, argv, ":tdAr:s:ivo:p")) != -1) {
1000*10946SSangeeta.Misra@Sun.COM 		switch ((char)c) {
1001*10946SSangeeta.Misra@Sun.COM 		case 't': sta.ilbst_flags |= ILBST_TIMESTAMP_HEADER;
1002*10946SSangeeta.Misra@Sun.COM 			t_opt = B_TRUE;
1003*10946SSangeeta.Misra@Sun.COM 			break;
1004*10946SSangeeta.Misra@Sun.COM 		case 'd': sta.ilbst_flags |= ILBST_DELTA_INTERVAL;
1005*10946SSangeeta.Misra@Sun.COM 			d_opt = B_TRUE;
1006*10946SSangeeta.Misra@Sun.COM 			break;
1007*10946SSangeeta.Misra@Sun.COM 		case 'A': sta.ilbst_flags |= ILBST_ABS_NUMBERS;
1008*10946SSangeeta.Misra@Sun.COM 			A_opt = B_TRUE;
1009*10946SSangeeta.Misra@Sun.COM 			break;
1010*10946SSangeeta.Misra@Sun.COM 		case 'r': sta.ilbst_rulename = optarg;
1011*10946SSangeeta.Misra@Sun.COM 			r_opt = B_TRUE;
1012*10946SSangeeta.Misra@Sun.COM 			break;
1013*10946SSangeeta.Misra@Sun.COM 		case 's': sta.ilbst_server = optarg;
1014*10946SSangeeta.Misra@Sun.COM 			s_opt = B_TRUE;
1015*10946SSangeeta.Misra@Sun.COM 			break;
1016*10946SSangeeta.Misra@Sun.COM 		case 'i': sta.ilbst_flags |= ILBST_ITEMIZE;
1017*10946SSangeeta.Misra@Sun.COM 			i_opt = B_TRUE;
1018*10946SSangeeta.Misra@Sun.COM 			break;
1019*10946SSangeeta.Misra@Sun.COM 		case 'o': fieldnames = optarg;
1020*10946SSangeeta.Misra@Sun.COM 			o_opt = B_TRUE;
1021*10946SSangeeta.Misra@Sun.COM 			break;
1022*10946SSangeeta.Misra@Sun.COM 		case 'p': oflags |= OFMT_PARSABLE;
1023*10946SSangeeta.Misra@Sun.COM 			p_opt = B_TRUE;
1024*10946SSangeeta.Misra@Sun.COM 			break;
1025*10946SSangeeta.Misra@Sun.COM 		case 'v': sta.ilbst_flags |= ILBST_VERBOSE;
1026*10946SSangeeta.Misra@Sun.COM 			v_opt = B_TRUE;
1027*10946SSangeeta.Misra@Sun.COM 			fieldnames = stat_stdv_hdrs;
1028*10946SSangeeta.Misra@Sun.COM 			break;
1029*10946SSangeeta.Misra@Sun.COM 		case ':': ilbadm_err(gettext("missing option-argument"
1030*10946SSangeeta.Misra@Sun.COM 			    " detected for %c"), (char)optopt);
1031*10946SSangeeta.Misra@Sun.COM 			exit(1);
1032*10946SSangeeta.Misra@Sun.COM 			/* not reached */
1033*10946SSangeeta.Misra@Sun.COM 			break;
1034*10946SSangeeta.Misra@Sun.COM 		case '?': /* fallthrough */
1035*10946SSangeeta.Misra@Sun.COM 		default:
1036*10946SSangeeta.Misra@Sun.COM 			unknown_opt(argv, optind-1);
1037*10946SSangeeta.Misra@Sun.COM 			/* not reached */
1038*10946SSangeeta.Misra@Sun.COM 			break;
1039*10946SSangeeta.Misra@Sun.COM 		}
1040*10946SSangeeta.Misra@Sun.COM 	}
1041*10946SSangeeta.Misra@Sun.COM 
1042*10946SSangeeta.Misra@Sun.COM 	if (s_opt && r_opt) {
1043*10946SSangeeta.Misra@Sun.COM 		ilbadm_err(gettext("options -s and -r are mutually exclusive"));
1044*10946SSangeeta.Misra@Sun.COM 		exit(1);
1045*10946SSangeeta.Misra@Sun.COM 	}
1046*10946SSangeeta.Misra@Sun.COM 
1047*10946SSangeeta.Misra@Sun.COM 	if (i_opt) {
1048*10946SSangeeta.Misra@Sun.COM 		if (!(s_opt || r_opt)) {
1049*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("option -i requires"
1050*10946SSangeeta.Misra@Sun.COM 			    " either -r or -s"));
1051*10946SSangeeta.Misra@Sun.COM 			exit(1);
1052*10946SSangeeta.Misra@Sun.COM 		}
1053*10946SSangeeta.Misra@Sun.COM 		if (v_opt) {
1054*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("option -i and -v are mutually"
1055*10946SSangeeta.Misra@Sun.COM 			    " exclusive"));
1056*10946SSangeeta.Misra@Sun.COM 			exit(1);
1057*10946SSangeeta.Misra@Sun.COM 		}
1058*10946SSangeeta.Misra@Sun.COM 		/* only use "std" headers if none are specified */
1059*10946SSangeeta.Misra@Sun.COM 		if (!o_opt)
1060*10946SSangeeta.Misra@Sun.COM 			if (r_opt)
1061*10946SSangeeta.Misra@Sun.COM 				fieldnames = stat_itemize_rule_hdrs;
1062*10946SSangeeta.Misra@Sun.COM 			else /* must be s_opt */
1063*10946SSangeeta.Misra@Sun.COM 				fieldnames = stat_itemize_server_hdrs;
1064*10946SSangeeta.Misra@Sun.COM 		fields = stat_itemize_fields;
1065*10946SSangeeta.Misra@Sun.COM 	}
1066*10946SSangeeta.Misra@Sun.COM 
1067*10946SSangeeta.Misra@Sun.COM 	if (p_opt) {
1068*10946SSangeeta.Misra@Sun.COM 		if (!o_opt) {
1069*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("option -p requires -o"));
1070*10946SSangeeta.Misra@Sun.COM 			exit(1);
1071*10946SSangeeta.Misra@Sun.COM 		}
1072*10946SSangeeta.Misra@Sun.COM 		if (v_opt) {
1073*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("option -o and -v are mutually"
1074*10946SSangeeta.Misra@Sun.COM 			    " exclusive"));
1075*10946SSangeeta.Misra@Sun.COM 			exit(1);
1076*10946SSangeeta.Misra@Sun.COM 		}
1077*10946SSangeeta.Misra@Sun.COM 		if (strcasecmp(fieldnames, "all") == 0) {
1078*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("option -p requires"
1079*10946SSangeeta.Misra@Sun.COM 			    " explicit field names"));
1080*10946SSangeeta.Misra@Sun.COM 			exit(1);
1081*10946SSangeeta.Misra@Sun.COM 		}
1082*10946SSangeeta.Misra@Sun.COM 	}
1083*10946SSangeeta.Misra@Sun.COM 
1084*10946SSangeeta.Misra@Sun.COM 	if (t_opt) {
1085*10946SSangeeta.Misra@Sun.COM 		if (v_opt) {
1086*10946SSangeeta.Misra@Sun.COM 			fieldnames = "all";
1087*10946SSangeeta.Misra@Sun.COM 		} else {
1088*10946SSangeeta.Misra@Sun.COM 			int  len = strlen(fieldnames) + 6;
1089*10946SSangeeta.Misra@Sun.COM 			char *fnames;
1090*10946SSangeeta.Misra@Sun.COM 
1091*10946SSangeeta.Misra@Sun.COM 			fnames = malloc(len);
1092*10946SSangeeta.Misra@Sun.COM 			if (fnames == NULL) {
1093*10946SSangeeta.Misra@Sun.COM 				rc = ILBADM_ENOMEM;
1094*10946SSangeeta.Misra@Sun.COM 				return (rc);
1095*10946SSangeeta.Misra@Sun.COM 			}
1096*10946SSangeeta.Misra@Sun.COM 			(void) snprintf(fnames, len, "%s,TIME", fieldnames);
1097*10946SSangeeta.Misra@Sun.COM 			fieldnames = fnames;
1098*10946SSangeeta.Misra@Sun.COM 		}
1099*10946SSangeeta.Misra@Sun.COM 	}
1100*10946SSangeeta.Misra@Sun.COM 
1101*10946SSangeeta.Misra@Sun.COM 	if (A_opt && d_opt) {
1102*10946SSangeeta.Misra@Sun.COM 		ilbadm_err(gettext("options -d and -A are mutually exclusive"));
1103*10946SSangeeta.Misra@Sun.COM 		exit(1);
1104*10946SSangeeta.Misra@Sun.COM 	}
1105*10946SSangeeta.Misra@Sun.COM 
1106*10946SSangeeta.Misra@Sun.COM 	/* find and parse interval and count arguments if present */
1107*10946SSangeeta.Misra@Sun.COM 	if (optind < argc) {
1108*10946SSangeeta.Misra@Sun.COM 		sta.ilbst_interval = atoi(argv[optind]);
1109*10946SSangeeta.Misra@Sun.COM 		if (sta.ilbst_interval < 1) {
1110*10946SSangeeta.Misra@Sun.COM 			ilbadm_err(gettext("illegal interval spec %s"),
1111*10946SSangeeta.Misra@Sun.COM 			    argv[optind]);
1112*10946SSangeeta.Misra@Sun.COM 			exit(1);
1113*10946SSangeeta.Misra@Sun.COM 		}
1114*10946SSangeeta.Misra@Sun.COM 		sta.ilbst_count = -1;
1115*10946SSangeeta.Misra@Sun.COM 		if (++optind < argc) {
1116*10946SSangeeta.Misra@Sun.COM 			sta.ilbst_count = atoi(argv[optind]);
1117*10946SSangeeta.Misra@Sun.COM 			if (sta.ilbst_count < 1) {
1118*10946SSangeeta.Misra@Sun.COM 				ilbadm_err(gettext("illegal count spec %s"),
1119*10946SSangeeta.Misra@Sun.COM 				    argv[optind]);
1120*10946SSangeeta.Misra@Sun.COM 				exit(1);
1121*10946SSangeeta.Misra@Sun.COM 			}
1122*10946SSangeeta.Misra@Sun.COM 		}
1123*10946SSangeeta.Misra@Sun.COM 	}
1124*10946SSangeeta.Misra@Sun.COM 
1125*10946SSangeeta.Misra@Sun.COM 	oerr = ofmt_open(fieldnames, fields, oflags, 80, &oh);
1126*10946SSangeeta.Misra@Sun.COM 	if (oerr != OFMT_SUCCESS) {
1127*10946SSangeeta.Misra@Sun.COM 		char	e[80];
1128*10946SSangeeta.Misra@Sun.COM 
1129*10946SSangeeta.Misra@Sun.COM 		ilbadm_err(gettext("ofmt_open failed: %s"),
1130*10946SSangeeta.Misra@Sun.COM 		    ofmt_strerror(oh, oerr, e, sizeof (e)));
1131*10946SSangeeta.Misra@Sun.COM 		return (ILBADM_LIBERR);
1132*10946SSangeeta.Misra@Sun.COM 	}
1133*10946SSangeeta.Misra@Sun.COM 
1134*10946SSangeeta.Misra@Sun.COM 	sta.ilbst_oh = oh;
1135*10946SSangeeta.Misra@Sun.COM 
1136*10946SSangeeta.Misra@Sun.COM 	rc = i_do_show_stats(&sta);
1137*10946SSangeeta.Misra@Sun.COM 
1138*10946SSangeeta.Misra@Sun.COM 	ofmt_close(oh);
1139*10946SSangeeta.Misra@Sun.COM 	return (rc);
1140*10946SSangeeta.Misra@Sun.COM }
1141