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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _ISCSI_STATS_H
27 #define	_ISCSI_STATS_H
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /*
34  * This file contains all the definitions and prototypes relevant to KSTAT.
35  * It also contains the declaration and initialization of data.  When including
36  * this file, if _INIT_KSTAT_DATA_ is defined, the data is declared AND
37  * initialized. As a consequence, this file should be included only once with
38  * _INIT_KSTAT_DATA_ defined.  Failure to do so will lead to a link error.
39  * Today, iscsi_stats.c is the only file defining _INIT_KSTAT_DATA_.
40  *
41  * Four types of KSTAT structures are created for iSCSI.
42  *
43  *   sun_iscsi_hba
44  *   -------------
45  *
46  *	This structure gathers statistics relevant to an HBA. Each HBA or
47  *	software state structure is given one.  It contains the following
48  *	fieds:
49  *
50  *	  _name			iSCSI name of the HBA
51  *	  _alias		iSCSI alias of the HBA
52  *	  _cntr_sess		Numbers of sessions created
53  *
54  *   sun_iscsi_sess
55  *   --------------
56  *
57  *	This structure gathers statistics relevant to a session.  Each session
58  *	is given one.  It contains the following fields:
59  *
60  *	  _state		State of the session
61  *	  _oid			OID of the session
62  *	  _hba			HBA the session belongs to.  It is the name
63  *				of the sun_iscsi_hba structure of the HBA
64  *	  _cntr_conn		Number of connections
65  *	  _cntr_pkt_pending	Number of scsi_pkt in the pending queue
66  *	  _cmd_sn		CmdSN
67  *	  _cmd_sn_exp		CmdSNExp,
68  *	  _cmd_sn_max		CmdSNMax
69  *
70  *   sun_iscsi_sess_io
71  *   -----------------
72  *
73  *	This structure is completely defined by the KSTAT frame work of Solaris.
74  *	It contains accumulated time and queue length statistics.  It assumes
75  *	the driver has a pending queue and an active.  In our implementation,
76  *	the pending queue is the pending queue defined in the session context.
77  *	The active queue is any queue defined in the connection context.
78  *	If you want more information about the meaning of the fields of this
79  *	structure you can read the nice explanation contained in the file:
80  *	/usr/src/uts/common/sys/kstat.h.
81  *	At any rate, all the sessions are given a sun_iscsi_sess_io structure.
82  *	The fields are:
83  *
84  *	  nread			number of bytes read without iSCSI overhead.
85  *	  nwritten		number of bytes written without iSCSI overhead.
86  *	  reads			number of read operations
87  *	  writes		number of write operations
88  *	  wtime			cumulative wait (pre-service) time
89  *	  wlentime		cumulative wait length*time product
90  *	  wlastupdate		last time wait queue changed
91  *	  rtime			cumulative run (service) time
92  *	  rlentime		cumulative run length*time product
93  *	  rlastupdate		last time run queue changed
94  *	  wcnt			count of elements in wait state
95  *	  rcnt			count of elements in run state
96  *
97  *	The time is expressed in nanoseconds.
98  *
99  *   sun_iscsi_conn
100  *   --------------
101  *
102  *	This structure gathers statistics relevant to a connection.  Each
103  *      connection is given one.  It contains the following fields:
104  *
105  *	  _state		State of the connection
106  *	  _cid			iSCSI CID
107  *	  _oid			OID of the connection
108  *	  _session		Session the connection belongs to.  It is the
109  *				name of the sun_iscsi_sess structure of the
110  *				session.
111  *	  _err_header_digest	Number of header digest errors
112  *	  _err_data_digest	Number of data digest errors
113  *	  _err_connection_reset	Number of reset
114  *	  _err_protocol_error	Number of protocol errors
115  *	  _cntr_tx_bytes	Number of bytes transmitted with iSCSI overhead.
116  *	  _cntr_rx_bytes	Number of bytes received with iSCSI overhead.
117  *	  _cntr_qactive		Number of requests in the active queue.
118  *	  _stat_sn_exp		ExpStatusSN
119  *	  _stat_sn_last		LastStatusSN (Last one sent to the target)
120  *
121  *
122  *
123  * The KSTAT frame work of Solaris associates a module name, a instance number
124  * a class and a name to every kstat structure.  All the kstat structures of
125  * iSCSI have the same module name. It is define farther down in this file to
126  * "iscsi".  Regarding the class, three classes are defined here. Those classes
127  * are:
128  *
129  *   - issci_hba
130  *   - iscsi_sess
131  *   - iscsi_conn
132  *
133  * The instance number is the number returned by ddi_get_instance.  Today the
134  * the driver creates one HBA only.  Therefore, all the structures will have
135  * zero as instance number.
136  *
137  *
138  * Each kstat structure can be named.  The naming convention is the following:
139  *
140  *	KSTAT Struct	   Class	Name
141  *
142  *	sun_iscsi_hba	   iscsi_hba	"sun_iscsi_hba" + instance number
143  *	sun_iscsi_sess	   iscsi_sess	"sun_iscsi_sess" + session oid
144  *	sun_iscsi_sess_io  iscsi_sess	"sun_iscsi_sess_io" + session oid
145  *	sun_iscsi_conn	   iscsi_conn	"sun_iscsi_conn" + connection oid
146  */
147 
148 /*
149  * strings used by kstat (Module name and Class name).
150  */
151 #define	iSCSI_MODULE_NAME	"iscsi"
152 
153 typedef struct _kstat_item {
154 	char		*_name;
155 	uchar_t		_data_type;
156 } kstat_item_t;
157 
158 /*
159  * ========================= Connection Class Section ======================
160  */
161 
162 #define	iSCSI_CLASS_CONN			"iscsi_conn"
163 #define	iSCSI_CONN_BASE_NAME			"iscsi_conn_%d_%d_%d"
164 
165 #define	ISCSI_CONN_STATE_FREE_STR		"free"
166 #define	ISCSI_CONN_STATE_IN_LOGIN_STR		"in_login"
167 #define	ISCSI_CONN_STATE_LOGGED_IN_STR		"logged_in"
168 #define	ISCSI_CONN_STATE_IN_LOGOUT_STR		"in_logout"
169 #define	ISCSI_CONN_STATE_CLEANUP_WAIT_STR	"cleanup_wait"
170 
171 /*
172  * WARNING: The order of this enum important.  If you change it you have to
173  *          reorder the table kstat_items_conn (in the file iscsi_stats.c)
174  *	    accordingly.
175  */
176 typedef enum _kn_conn_idx {
177 	KN_CONN_IDX_STATE = 0,
178 	KN_CONN_IDX_CID,
179 	KN_CONN_IDX_OID,
180 	KN_CONN_IDX_SESS,
181 	KN_CONN_IDX_ERR_HDR_DIGEST,
182 	KN_CONN_IDX_ERR_DATA_DIGEST,
183 	KN_CONN_IDX_ERR_CONN_RESET,
184 	KN_CONN_IDX_ERR_PROTOCOL,
185 	KN_CONN_IDX_CNTR_TX_BYTES,
186 	KN_CONN_IDX_CNTR_RX_BYTES,
187 	KN_CONN_IDX_CNTR_QACTIVE,
188 	KN_CONN_IDX_EXPSTATSN,
189 	KN_CONN_IDX_LASTSTATSN,
190 	KN_CONN_IDX_MAX
191 } kn_conn_idx_t;
192 
193 typedef struct _iscsi_conn_kstats {
194 	kstat_named_t	kn[KN_CONN_IDX_MAX];
195 	char 		sess_str[KSTAT_STRLEN];
196 	char 		state_str[KSTAT_STRLEN];
197 } iscsi_conn_stats_t;
198 
199 #define	KSTAT_INC_CONN_ERR_HEADER_DIGEST(_icp_) \
200 	(_icp_->stats.ks_data.kn[KN_CONN_IDX_ERR_HDR_DIGEST].value.ul++)
201 
202 #define	KSTAT_INC_CONN_ERR_DATA_DIGEST(_icp_) \
203 	(_icp_->stats.ks_data.kn[KN_CONN_IDX_ERR_DATA_DIGEST].value.ul++)
204 
205 #define	KSTAT_INC_CONN_ERR_PROTOCOL(_icp_) \
206 	(_icp_->stats.ks_data.kn[KN_CONN_IDX_ERR_PROTOCOL].value.ul++)
207 
208 #define	KSTAT_INC_CONN_ERR_RESET(_icp_) \
209 	(_icp_->stats.ks_data.kn[KN_CONN_IDX_ERR_CONN_RESET].value.ul++)
210 
211 #define	KSTAT_ADD_CONN_TX_BYTES(_icp_, _v_) \
212 	(_icp_->stats.ks_data.kn[KN_CONN_IDX_CNTR_TX_BYTES].value.ui64 += \
213 	_v_)
214 
215 #define	KSTAT_ADD_CONN_RX_BYTES(_icp_, _v_) \
216 	(_icp_->stats.ks_data.kn[KN_CONN_IDX_CNTR_RX_BYTES].value.ui64 += \
217 	_v_)
218 
219 /*
220  * ========================== Session Class Section ========================
221  */
222 
223 /* Session Class */
224 #define	iSCSI_CLASS_SESS			"iscsi_sess"
225 #define	iSCSI_SESS_BASE_NAME			"iscsi_sess_%d_%d"
226 #define	iSCSI_SESS_IO_BASE_NAME			"iscsi_sess_io_%d_%d"
227 
228 #define	ISCSI_SESS_STATE_FREE_STR		"free"
229 #define	ISCSI_SESS_STATE_LOGGED_IN_STR		"logged_in"
230 #define	ISCSI_SESS_STATE_FAILED_STR		"failed"
231 
232 /*
233  * WARNING: The order of this enum important.  If you change it you have to
234  *          reorder the table kstat_items_sess (in the file iscsi_stats.c)
235  *	    accordingly.
236  */
237 typedef enum _kn_sess_idx {
238 	KN_SESS_IDX_STATE = 0,
239 	KN_SESS_IDX_OID,
240 	KN_SESS_IDX_HBA,
241 	KN_SESS_IDX_CNTR_CONN,
242 	KN_SESS_IDX_CNTR_RESET,
243 	KN_SESS_IDX_CNTR_PKT_PENDING,
244 	KN_SESS_IDX_CMDSN,
245 	KN_SESS_IDX_EXPCMDSN,
246 	KN_SESS_IDX_MAXCMDSN,
247 	KN_SESS_IDX_TARGET_NAME,
248 	KN_SESS_IDX_TARGET_ALIAS,
249 	KN_SESS_IDX_TPGT,
250 	KN_SESS_IDX_MAX
251 } kn_sess_idx_t;
252 
253 typedef struct _iscsi_sess_stats {
254 	kstat_named_t	kn[KN_SESS_IDX_MAX];
255 	char 		hba_str[KSTAT_STRLEN];
256 	char 		state_str[KSTAT_STRLEN];
257 	char 		target_name[ISCSI_MAX_NAME_LEN];
258 	char 		target_alias[ISCSI_MAX_NAME_LEN];
259 } iscsi_sess_stats_t;
260 
261 #define	KSTAT_INC_SESS_CNTR_RESET(_isp_) \
262 	(_isp_->stats.ks_data.kn[KN_SESS_IDX_CNTR_RESET].value.ul++)
263 
264 #define	KSTAT_INC_SESS_CNTR_CONN(_isp_) \
265 	(_isp_->stats.ks_data.kn[KN_SESS_IDX_CNTR_CONN].value.ul++)
266 
267 #define	KSTAT_DEC_SESS_CNTR_CONN(_isp_) \
268 	(_isp_->stats.ks_data.kn[KN_SESS_IDX_CNTR_CONN].value.ul--)
269 
270 #define	KSTAT_ADD_SESS_CNTR_TX_BYTES(_isp_, _v_) \
271 	mutex_enter(&_isp_->stats.ks_io_lock); \
272 	(_isp_->stats.ks_io_data.nwritten += _v_); \
273 	mutex_exit(&_isp_->stats.ks_io_lock);
274 
275 #define	KSTAT_ADD_SESS_CNTR_RX_BYTES(_isp_, _v_) \
276 	mutex_enter(&_isp_->stats.ks_io_lock); \
277 	(_isp_->stats.ks_io_data.nread += _v_); \
278 	mutex_exit(&_isp_->stats.ks_io_lock);
279 
280 #define	KSTAT_INC_SESS_CNTR_NWRITES(_isp_) \
281 	mutex_enter(&_isp_->stats.ks_io_lock); \
282 	(_isp_->stats.ks_io_data.writes++); \
283 	mutex_exit(&_isp_->stats.ks_io_lock);
284 
285 #define	KSTAT_INC_SESS_CNTR_NREADS(_isp_) \
286 	mutex_enter(&_isp_->stats.ks_io_lock); \
287 	(_isp_->stats.ks_io_data.reads++); \
288 	mutex_exit(&_isp_->stats.ks_io_lock);
289 
290 #define	KSTAT_WAITQ_ENTER(_isp_) \
291 	mutex_enter(&_isp_->stats.ks_io_lock); \
292 	(kstat_waitq_enter(&_isp_->stats.ks_io_data)); \
293 	mutex_exit(&_isp_->stats.ks_io_lock);
294 
295 #define	KSTAT_WAITQ_EXIT(_isp_) \
296 	mutex_enter(&_isp_->stats.ks_io_lock); \
297 	(kstat_waitq_exit(&_isp_->stats.ks_io_data)); \
298 	mutex_exit(&_isp_->stats.ks_io_lock);
299 
300 #define	KSTAT_RUNQ_ENTER(_isp_) \
301 	mutex_enter(&_isp_->stats.ks_io_lock); \
302 	(kstat_runq_enter(&_isp_->stats.ks_io_data)); \
303 	mutex_exit(&_isp_->stats.ks_io_lock);
304 
305 #define	KSTAT_RUNQ_EXIT(_isp_) \
306 	mutex_enter(&_isp_->stats.ks_io_lock); \
307 	(kstat_runq_exit(&_isp_->stats.ks_io_data)); \
308 	mutex_exit(&_isp_->stats.ks_io_lock);
309 
310 #define	KSTAT_SESS_TX_IO_DONE(_isp_, _v_) \
311 	mutex_enter(&_isp_->stats.ks_io_lock); \
312 	(_isp_->stats.ks_io_data.nwritten += _v_); \
313 	(_isp_->stats.ks_io_data.writes++); \
314 	mutex_exit(&_isp_->stats.ks_io_lock);
315 
316 #define	KSTAT_SESS_RX_IO_DONE(_isp_, _v_) \
317 	mutex_enter(&_isp_->stats.ks_io_lock); \
318 	(_isp_->stats.ks_io_data.nread += _v_); \
319 	(_isp_->stats.ks_io_data.reads++); \
320 	mutex_exit(&_isp_->stats.ks_io_lock);
321 
322 /*
323  * ============================ HBA Class Section ==========================
324  */
325 
326 #define	iSCSI_CLASS_HBA		"iscsi_hba"
327 #define	iSCSI_HBA_BASE_NAME	"iscsi_hba_%d"
328 
329 /*
330  * WARNING: The order of this enum important.  If you change it you have to
331  *          reorder the table kstat_items_hba (in iscsi_stats.c) accordingly.
332  */
333 typedef enum _kn_hba_idx {
334 	KN_HBA_IDX_NAME = 0,
335 	KN_HBA_IDX_ALIAS,
336 	KN_HBA_IDX_CNTR_SESS,
337 	KN_HBA_IDX_MAX
338 } kn_hba_idx_t;
339 
340 typedef struct _iscsi_hba_stats {
341 	kstat_named_t	kn[KN_HBA_IDX_MAX];
342 	char 		name[ISCSI_MAX_NAME_LEN];
343 	char 		alias[ISCSI_MAX_NAME_LEN];
344 } iscsi_hba_stats_t;
345 
346 #define	KSTAT_INC_HBA_CNTR_SESS(_ihp_) \
347 	(_ihp_->stats.ks_data.kn[KN_HBA_IDX_CNTR_SESS].value.ul++)
348 
349 #define	KSTAT_DEC_HBA_CNTR_SESS(_ihp_) \
350 	(_ihp_->stats.ks_data.kn[KN_HBA_IDX_CNTR_SESS].value.ul--)
351 
352 #ifdef __cplusplus
353 }
354 #endif
355 
356 #endif	/* _ISCSI_STATS_H */
357