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