1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Copyright 2012 David Hoeppner.  All rights reserved.
  24  */
  25 
  26 #ifndef _STAT_KSTAT_H
  27 #define _STAT_KSTAT_H
  28 
  29 /*
  30  * Structures needed by the kstat reader functions.
  31  */
  32 #include <sys/var.h>
  33 #include <sys/utsname.h>
  34 #include <sys/sysinfo.h>
  35 #include <sys/flock.h>
  36 #include <sys/dnlc.h>
  37 #include <nfs/nfs.h>
  38 #include <nfs/nfs_clnt.h>
  39 
  40 #ifdef __sparc
  41 #include <vm/hat_sfmmu.h>
  42 #include <sys/simmstat.h>
  43 #include <sys/sysctrl.h>
  44 #include <sys/fhc.h>
  45 #endif
  46 
  47 #define KSTAT_DATA_HRTIME       (KSTAT_DATA_STRING + 1)
  48 
  49 typedef union ks_value {
  50         char            c[16];
  51         int32_t         i32;
  52         uint32_t        ui32;
  53         struct {
  54                 union {
  55                         char    *ptr;
  56                         char    __pad[8];
  57                 } addr;
  58                 uint32_t        len;
  59         } str;
  60 
  61         int64_t         i64;
  62         uint64_t        ui64;
  63 } ks_value_t;
  64 
  65 #define SAVE_HRTIME(I, S, N)                            \
  66 {                                                       \
  67         ks_value_t v;                                   \
  68         v.ui64 = S->N;                                       \
  69         nvpair_insert(I, #N, &v, KSTAT_DATA_UINT64);        \
  70 }
  71 
  72 #define SAVE_INT32(I, S, N)                             \
  73 {                                                       \
  74         ks_value_t v;                                   \
  75         v.i32 = S->N;                                        \
  76         nvpair_insert(I, #N, &v, KSTAT_DATA_INT32); \
  77 }
  78 
  79 #define SAVE_UINT32(I, S, N)                            \
  80 {                                                       \
  81         ks_value_t v;                                   \
  82         v.ui32 = S->N;                                       \
  83         nvpair_insert(I, #N, &v, KSTAT_DATA_UINT32);        \
  84 }
  85 
  86 #define SAVE_INT64(I, S, N)                             \
  87 {                                                       \
  88         ks_value_t v;                                   \
  89         v.i64 = S->N;                                        \
  90         nvpair_insert(I, #N, &v, KSTAT_DATA_INT64); \
  91 }
  92 
  93 #define SAVE_UINT64(I, S, N)                            \
  94 {                                                       \
  95         ks_value_t v;                                   \
  96         v.ui64 = S->N;                                       \
  97         nvpair_insert(I, #N, &v, KSTAT_DATA_UINT64);        \
  98 }
  99 
 100 /*
 101  * We dont want const "strings" because we free
 102  * the instances later.
 103  */
 104 #define SAVE_STRING(I, S, N)                            \
 105 {                                                       \
 106         ks_value_t v;                                   \
 107         v.str.addr.ptr = safe_strdup(S->N);          \
 108         v.str.len = strlen(S->N);                    \
 109         nvpair_insert(I, #N, &v, KSTAT_DATA_STRING);        \
 110 }
 111 
 112 #define SAVE_HRTIME_X(I, N, V)                          \
 113 {                                                       \
 114         ks_value_t v;                                   \
 115         v.ui64 = V;                                     \
 116         nvpair_insert(I, N, &v, KSTAT_DATA_HRTIME); \
 117 }
 118 
 119 #define SAVE_INT32_X(I, N, V)                           \
 120 {                                                       \
 121         ks_value_t v;                                   \
 122         v.i32 = V;                                      \
 123         nvpair_insert(I, N, &v, KSTAT_DATA_INT32);  \
 124 }
 125 
 126 #define SAVE_UINT32_X(I, N, V)                          \
 127 {                                                       \
 128         ks_value_t v;                                   \
 129         v.ui32 = V;                                     \
 130         nvpair_insert(I, N, &v, KSTAT_DATA_UINT32); \
 131 }
 132 
 133 #define SAVE_UINT64_X(I, N, V)                          \
 134 {                                                       \
 135         ks_value_t v;                                   \
 136         v.ui64 = V;                                     \
 137         nvpair_insert(I, N, &v, KSTAT_DATA_UINT64); \
 138 }
 139 
 140 #define SAVE_STRING_X(I, N, V)                          \
 141 {                                                       \
 142         ks_value_t v;                                   \
 143         v.str.addr.ptr = safe_strdup(V);                \
 144         v.str.len = strlen(V);                          \
 145         nvpair_insert(I, N, &v, KSTAT_DATA_STRING); \
 146 }
 147 
 148 #define SAVE_CHAR_X(I, N, V)                            \
 149 {                                                       \
 150         ks_value_t v;                                   \
 151         asprintf(&v.str.addr.ptr, "%c", V);         \
 152         v.str.len = 1;                                  \
 153         nvpair_insert(I, N, &v, KSTAT_DATA_STRING); \
 154 }
 155 
 156 #define DFLT_FMT                                        \
 157         "module: %-30.30s  instance: %-6d\n"            \
 158         "name:   %-30.30s  class:    %-.30s\n"
 159 
 160 #define JSON_FMT                                        \
 161         "{\n\t\"module\": \"%s\",\n"                    \
 162         "\t\"instance\": %d,\n"                         \
 163         "\t\"name\": \"%s\",\n"                         \
 164         "\t\"class\": \"%s\",\n"                        \
 165         "\t\"type\": %d,\n"
 166 
 167 #define KS_DFMT "\t%-30s  "
 168 #define KS_JFMT "\t\t\"%s\": "
 169 #define KS_PFMT "%s:%d:%s:%s"
 170 
 171 typedef struct ks_instance {
 172         list_node_t     ks_next;
 173         char            ks_name[KSTAT_STRLEN];
 174         char            ks_module[KSTAT_STRLEN];
 175         char            ks_class[KSTAT_STRLEN];
 176         int             ks_instance;
 177         uchar_t         ks_type;
 178         hrtime_t        ks_snaptime;
 179         list_t          ks_nvlist;
 180 } ks_instance_t;
 181 
 182 typedef struct ks_nvpair {
 183         list_node_t     nv_next;
 184         char            name[KSTAT_STRLEN];
 185         uchar_t         data_type;
 186         ks_value_t      value;
 187 } ks_nvpair_t;
 188 
 189 typedef struct ks_selector {
 190         list_node_t ks_next;
 191         char    *ks_module;
 192         char    *ks_instance;
 193         char    *ks_name;
 194         char    *ks_statistic;
 195 } ks_selector_t;
 196 
 197 static void     usage(void);
 198 static int      compare_instances(ks_instance_t *, ks_instance_t *);
 199 static void     nvpair_insert(ks_instance_t *, char *, ks_value_t *, uchar_t);
 200 static ks_selector_t    *new_selector(void);
 201 static void     ks_instances_read(kstat_ctl_t *);
 202 static void     ks_value_print(ks_nvpair_t *);
 203 static void     ks_instance_print(ks_instance_t *, ks_nvpair_t *);
 204 static void     ks_instances_print(void);
 205 static char     *ks_safe_strdup(char *);
 206 static void     ks_sleep_until(hrtime_t *, hrtime_t, int, int *);
 207 
 208 /* Raw kstat readers */
 209 static void     save_cpu_stat(kstat_t *, ks_instance_t *);
 210 static void     save_var(kstat_t *, ks_instance_t *);
 211 static void     save_ncstats(kstat_t *, ks_instance_t *);
 212 static void     save_sysinfo(kstat_t *, ks_instance_t *);
 213 static void     save_vminfo(kstat_t *, ks_instance_t *);
 214 static void     save_nfs(kstat_t *, ks_instance_t *);
 215 #ifdef __sparc
 216 static void     save_sfmmu_global_stat(kstat_t *, ks_instance_t *);
 217 static void     save_sfmmu_tsbsize_stat(kstat_t *, ks_instance_t *);
 218 static void     save_simmstat(kstat_t *, ks_instance_t *);
 219 /* Helper function for save_temperature() */
 220 static char     *short_array_to_string(short *, int);
 221 static void     save_temperature(kstat_t *, ks_instance_t *);
 222 static void     save_temp_over(kstat_t *, ks_instance_t *);
 223 static void     save_ps_shadow(kstat_t *, ks_instance_t *);
 224 static void     save_fault_list(kstat_t *, ks_instance_t *);
 225 #endif
 226 
 227 /* Named kstat readers */
 228 static void     save_named(kstat_t *, ks_instance_t *);
 229 static void     save_intr(kstat_t *, ks_instance_t *);
 230 static void     save_io(kstat_t *, ks_instance_t *);
 231 static void     save_timer(kstat_t *, ks_instance_t *);
 232 
 233 /* Typedef for raw kstat reader functions */
 234 typedef void    (*kstat_raw_reader_t)(kstat_t *, ks_instance_t *);
 235 
 236 static struct {
 237         kstat_raw_reader_t fn;
 238         char *name;
 239 } ks_raw_lookup[] = {
 240         /* Function name                kstat name              */
 241         {save_cpu_stat,                 "cpu_stat:cpu_stat"},
 242         {save_var,                      "unix:var"},
 243         {save_ncstats,                  "unix:ncstats"},
 244         {save_sysinfo,                  "unix:sysinfo"},
 245         {save_vminfo,                   "unix:vminfo"},
 246         {save_nfs,                      "nfs:mntinfo"},
 247 #ifdef __sparc
 248         {save_sfmmu_global_stat,        "unix:sfmmu_global_stat"},
 249         {save_sfmmu_tsbsize_stat,       "unix:sfmmu_tsbsize_stat"},
 250         {save_simmstat,                 "unix:simm-status"},
 251         {save_temperature,              "unix:temperature"},
 252         {save_temp_over,                "unix:temperature override"},
 253         {save_ps_shadow,                "unix:ps_shadow"},
 254         {save_fault_list,               "unix:fault_list"},
 255 #endif
 256         {NULL, NULL},
 257 };
 258 
 259 static kstat_raw_reader_t       lookup_raw_kstat_fn(char *, char *);
 260 
 261 #endif /* _STAT_KSTAT_H */