xref: /illumos-gate/usr/src/uts/common/sys/idm/idm_conn_sm.h (revision 61dfa5098dc8576d9a5e277deba6df647bb70c06)
1a6d42e7dSPeter Dunlap /*
2a6d42e7dSPeter Dunlap  * CDDL HEADER START
3a6d42e7dSPeter Dunlap  *
4a6d42e7dSPeter Dunlap  * The contents of this file are subject to the terms of the
5a6d42e7dSPeter Dunlap  * Common Development and Distribution License (the "License").
6a6d42e7dSPeter Dunlap  * You may not use this file except in compliance with the License.
7a6d42e7dSPeter Dunlap  *
8a6d42e7dSPeter Dunlap  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a6d42e7dSPeter Dunlap  * or http://www.opensolaris.org/os/licensing.
10a6d42e7dSPeter Dunlap  * See the License for the specific language governing permissions
11a6d42e7dSPeter Dunlap  * and limitations under the License.
12a6d42e7dSPeter Dunlap  *
13a6d42e7dSPeter Dunlap  * When distributing Covered Code, include this CDDL HEADER in each
14a6d42e7dSPeter Dunlap  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a6d42e7dSPeter Dunlap  * If applicable, add the following below this CDDL HEADER, with the
16a6d42e7dSPeter Dunlap  * fields enclosed by brackets "[]" replaced with your own identifying
17a6d42e7dSPeter Dunlap  * information: Portions Copyright [yyyy] [name of copyright owner]
18a6d42e7dSPeter Dunlap  *
19a6d42e7dSPeter Dunlap  * CDDL HEADER END
20a6d42e7dSPeter Dunlap  */
21a6d42e7dSPeter Dunlap 
22a6d42e7dSPeter Dunlap /*
23e97fb153SPeter Cudhea - Sun Microsystems - Burlington, MA United States  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24a6d42e7dSPeter Dunlap  * Use is subject to license terms.
25ff9de394SRick McNeal  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
26a6d42e7dSPeter Dunlap  */
27a6d42e7dSPeter Dunlap #ifndef	_IDM_CONN_SM_H_
28a6d42e7dSPeter Dunlap #define	_IDM_CONN_SM_H_
29a6d42e7dSPeter Dunlap 
30a6d42e7dSPeter Dunlap #ifdef	__cplusplus
31a6d42e7dSPeter Dunlap extern "C" {
32a6d42e7dSPeter Dunlap #endif
33a6d42e7dSPeter Dunlap 
34a6d42e7dSPeter Dunlap 
35a6d42e7dSPeter Dunlap /*
36a6d42e7dSPeter Dunlap  * IDM connection state machine events.  Most events get generated internally
37a6d42e7dSPeter Dunlap  * either by the state machine or by the IDM TX/RX code.  For example when IDM
38a6d42e7dSPeter Dunlap  * receives a login request for a target connectionit will generate a
39a6d42e7dSPeter Dunlap  * CE_LOGIN_RCV event.  Similarly when the target sends a successful login
40a6d42e7dSPeter Dunlap  * response IDM generate a "CE_LOGIN_SUCCESS_SND" event.  The following
41a6d42e7dSPeter Dunlap  * events are not detected on the TX/RX path and must be generated explicitly
42a6d42e7dSPeter Dunlap  * by the client when appropriate:
43a6d42e7dSPeter Dunlap  *
44a6d42e7dSPeter Dunlap  * CE_LOGOUT_OTHER_CONN_RCV
45a6d42e7dSPeter Dunlap  * CE_ASYNC_DROP_CONN_RCV   (Only because the message may be received on
46a6d42e7dSPeter Dunlap  * a different connection from the connection being dropped)
47a6d42e7dSPeter Dunlap  * CE_ASYNC_DROP_ALL_CONN_RCV
48a6d42e7dSPeter Dunlap  * CE_LOGOUT_OTHER_CONN_SND
49a6d42e7dSPeter Dunlap  * CE_ASYNC_DROP_ALL_CONN_SND
50a6d42e7dSPeter Dunlap  *
51a6d42e7dSPeter Dunlap  * The following events might occur in any state since they are driven
52a6d42e7dSPeter Dunlap  * by the PDU's that IDM receives:
53a6d42e7dSPeter Dunlap  *
54a6d42e7dSPeter Dunlap  * CE_LOGIN_RCV
55a6d42e7dSPeter Dunlap  * CE_LOGIN_SUCCESS_RCV
56a6d42e7dSPeter Dunlap  * CE_LOGIN_FAIL_RCV
57a6d42e7dSPeter Dunlap  * CE_LOGOUT_SUCCESS_RCV
58a6d42e7dSPeter Dunlap  * CE_LOGOUT_FAIL_RCV
59a6d42e7dSPeter Dunlap  * CE_ASYNC_LOGOUT_RCV
60a6d42e7dSPeter Dunlap  * CE_MISC_RCV
61a6d42e7dSPeter Dunlap  * CE_RX_PROTOCOL_ERROR
62a6d42e7dSPeter Dunlap  */
63a6d42e7dSPeter Dunlap 
64a6d42e7dSPeter Dunlap #define	IDM_LOGIN_SECONDS	20
65a6d42e7dSPeter Dunlap #define	IDM_LOGOUT_SECONDS	20
66a6d42e7dSPeter Dunlap #define	IDM_CLEANUP_SECONDS	0
67a6d42e7dSPeter Dunlap 
68*61dfa509SRick McNeal #define	IDM_CONN_EVENT_LIST() \
69*61dfa509SRick McNeal 	item(CE_UNDEFINED) \
70*61dfa509SRick McNeal 	/* Initiator events */ \
71*61dfa509SRick McNeal 	item(CE_CONNECT_REQ) \
72*61dfa509SRick McNeal 	item(CE_CONNECT_FAIL) \
73*61dfa509SRick McNeal 	item(CE_CONNECT_SUCCESS) \
74*61dfa509SRick McNeal 	item(CE_LOGIN_SND) \
75*61dfa509SRick McNeal 	item(CE_LOGIN_SUCCESS_RCV) \
76*61dfa509SRick McNeal 	item(CE_LOGIN_FAIL_RCV) \
77*61dfa509SRick McNeal 	item(CE_LOGOUT_THIS_CONN_SND) \
78*61dfa509SRick McNeal 	item(CE_LOGOUT_OTHER_CONN_SND) \
79*61dfa509SRick McNeal 	item(CE_LOGOUT_SESSION_SND) \
80*61dfa509SRick McNeal 	item(CE_LOGOUT_SUCCESS_RCV) \
81*61dfa509SRick McNeal 	item(CE_LOGOUT_FAIL_RCV) \
82*61dfa509SRick McNeal 	item(CE_ASYNC_LOGOUT_RCV) \
83*61dfa509SRick McNeal 	item(CE_ASYNC_DROP_CONN_RCV) \
84*61dfa509SRick McNeal 	item(CE_ASYNC_DROP_ALL_CONN_RCV) \
85*61dfa509SRick McNeal 	/* Target events */ \
86*61dfa509SRick McNeal 	item(CE_CONNECT_ACCEPT) \
87*61dfa509SRick McNeal 	item(CE_CONNECT_REJECT) \
88*61dfa509SRick McNeal 	item(CE_LOGIN_RCV) \
89*61dfa509SRick McNeal 	item(CE_LOGIN_TIMEOUT) \
90*61dfa509SRick McNeal 	item(CE_LOGIN_SUCCESS_SND) \
91*61dfa509SRick McNeal 	item(CE_LOGIN_FAIL_SND) \
92*61dfa509SRick McNeal 	item(CE_LOGIN_FAIL_SND_DONE) \
93*61dfa509SRick McNeal 	item(CE_LOGOUT_THIS_CONN_RCV) \
94*61dfa509SRick McNeal 	item(CE_LOGOUT_OTHER_CONN_RCV) \
95*61dfa509SRick McNeal 	item(CE_LOGOUT_SESSION_RCV) \
96*61dfa509SRick McNeal 	item(CE_LOGOUT_SUCCESS_SND) \
97*61dfa509SRick McNeal 	item(CE_LOGOUT_SUCCESS_SND_DONE) \
98*61dfa509SRick McNeal 	item(CE_LOGOUT_FAIL_SND) \
99*61dfa509SRick McNeal 	item(CE_LOGOUT_FAIL_SND_DONE) \
100*61dfa509SRick McNeal 	item(CE_CLEANUP_TIMEOUT) \
101*61dfa509SRick McNeal 	item(CE_ASYNC_LOGOUT_SND) \
102*61dfa509SRick McNeal 	item(CE_ASYNC_DROP_CONN_SND) \
103*61dfa509SRick McNeal 	item(CE_ASYNC_DROP_ALL_CONN_SND) \
104*61dfa509SRick McNeal 	item(CE_LOGOUT_TIMEOUT) \
105*61dfa509SRick McNeal 	/* Common events */ \
106*61dfa509SRick McNeal 	item(CE_TRANSPORT_FAIL) \
107*61dfa509SRick McNeal 	item(CE_MISC_TX) \
108*61dfa509SRick McNeal 	item(CE_TX_PROTOCOL_ERROR) \
109*61dfa509SRick McNeal 	item(CE_MISC_RX) \
110*61dfa509SRick McNeal 	item(CE_RX_PROTOCOL_ERROR) \
111*61dfa509SRick McNeal 	item(CE_LOGOUT_SESSION_SUCCESS) \
112*61dfa509SRick McNeal 	item(CE_CONN_REINSTATE) \
113*61dfa509SRick McNeal 	item(CE_CONN_REINSTATE_SUCCESS) \
114*61dfa509SRick McNeal 	item(CE_CONN_REINSTATE_FAIL) \
115*61dfa509SRick McNeal 	item(CE_ENABLE_DM_SUCCESS) \
116*61dfa509SRick McNeal 	item(CE_ENABLE_DM_FAIL) \
117*61dfa509SRick McNeal 	/* Add new events above CE_MAX_EVENT */ \
118*61dfa509SRick McNeal 	item(CE_MAX_EVENT)
119*61dfa509SRick McNeal 
120a6d42e7dSPeter Dunlap /* Update idm_ce_name table whenever connection events are modified */
121a6d42e7dSPeter Dunlap typedef enum {
122*61dfa509SRick McNeal #define	item(a) a,
123*61dfa509SRick McNeal 	IDM_CONN_EVENT_LIST()
124*61dfa509SRick McNeal #undef	item
125a6d42e7dSPeter Dunlap } idm_conn_event_t;
126a6d42e7dSPeter Dunlap 
127a6d42e7dSPeter Dunlap #ifdef IDM_CONN_SM_STRINGS
128a6d42e7dSPeter Dunlap /* An array of event text values, for use in logging events */
129a6d42e7dSPeter Dunlap static const char *idm_ce_name[CE_MAX_EVENT+1] = {
130*61dfa509SRick McNeal #define	item(a) #a,
131*61dfa509SRick McNeal 	IDM_CONN_EVENT_LIST()
132*61dfa509SRick McNeal #undef	item
133a6d42e7dSPeter Dunlap };
134a6d42e7dSPeter Dunlap #endif
135a6d42e7dSPeter Dunlap 
136*61dfa509SRick McNeal #define	CONN_STATE_LIST() \
137*61dfa509SRick McNeal 	item(CS_S0_UNDEFINED) \
138*61dfa509SRick McNeal 	item(CS_S1_FREE) \
139*61dfa509SRick McNeal 	item(CS_S2_XPT_WAIT) \
140*61dfa509SRick McNeal 	item(CS_S3_XPT_UP) \
141*61dfa509SRick McNeal 	item(CS_S4_IN_LOGIN) \
142*61dfa509SRick McNeal 	item(CS_S5_LOGGED_IN) \
143*61dfa509SRick McNeal 	item(CS_S6_IN_LOGOUT) \
144*61dfa509SRick McNeal 	item(CS_S7_LOGOUT_REQ) \
145*61dfa509SRick McNeal 	item(CS_S8_CLEANUP) \
146*61dfa509SRick McNeal 	item(CS_S9_INIT_ERROR) \
147*61dfa509SRick McNeal 	item(CS_S10_IN_CLEANUP) \
148*61dfa509SRick McNeal 	item(CS_S11_COMPLETE) \
149*61dfa509SRick McNeal 	item(CS_S12_ENABLE_DM) \
150*61dfa509SRick McNeal 	item(CS_S9A_REJECTED) \
151*61dfa509SRick McNeal 	item(CS_S9B_WAIT_SND_DONE) \
152*61dfa509SRick McNeal 	/* Add new connection states above CS_MAX_STATE */ \
153*61dfa509SRick McNeal 	item(CS_MAX_STATE)
154*61dfa509SRick McNeal 
155a6d42e7dSPeter Dunlap /* Update idm_cs_name table whenever connection states are modified */
156a6d42e7dSPeter Dunlap typedef enum {
157*61dfa509SRick McNeal #define	item(a) a,
158*61dfa509SRick McNeal 	CONN_STATE_LIST()
159*61dfa509SRick McNeal #undef	item
160a6d42e7dSPeter Dunlap } idm_conn_state_t;
161a6d42e7dSPeter Dunlap 
162a6d42e7dSPeter Dunlap #ifdef IDM_CONN_SM_STRINGS
163a6d42e7dSPeter Dunlap /* An array of state text values, for use in logging state transitions */
164a6d42e7dSPeter Dunlap static const char *idm_cs_name[CS_MAX_STATE+1] = {
165*61dfa509SRick McNeal #define	item(a) #a,
166*61dfa509SRick McNeal 	CONN_STATE_LIST()
167*61dfa509SRick McNeal #undef	item
168a6d42e7dSPeter Dunlap };
169a6d42e7dSPeter Dunlap #endif
170a6d42e7dSPeter Dunlap 
171ff9de394SRick McNeal /*
172ff9de394SRick McNeal  * Currently the state machine has a condition where idm_login_timeout() is
173ff9de394SRick McNeal  * left active after the connection has been closed. This causes the system
174ff9de394SRick McNeal  * to panic when idm_login_timeout() modifies the freed memory. In an attempt
175ff9de394SRick McNeal  * to isolate and find this issue special attention is being placed on
176ff9de394SRick McNeal  * the ic_state_timeout value. After each untimeout call the value will now
177ff9de394SRick McNeal  * be cleared. Just before the value is set the code will check for 0 and
178ff9de394SRick McNeal  * display an error. One final change is being done in idm_conn_sm_fini() which
179ff9de394SRick McNeal  * if ic_state_machine is not 0, an error message will be displayed and
180ff9de394SRick McNeal  * untimeout() called. That should prevent customer sites from seeing the
181ff9de394SRick McNeal  * panic. The code also calls ASSERT(0) which should cause a panic during
182ff9de394SRick McNeal  * system test.
183ff9de394SRick McNeal  */
184ff9de394SRick McNeal #define	IDM_SM_TIMER_CHECK(ic) \
185ff9de394SRick McNeal 	if (ic->ic_state_timeout) { \
186ff9de394SRick McNeal 		cmn_err(CE_WARN, "%s: existing timeout still set. " \
187ff9de394SRick McNeal 		    "state: %s, last: %s\n", __func__, \
188ff9de394SRick McNeal 		    idm_cs_name[ic->ic_state], \
189ff9de394SRick McNeal 		    idm_cs_name[ic->ic_last_state]); \
190ff9de394SRick McNeal 		ASSERT(0); \
191ff9de394SRick McNeal 	}
192ff9de394SRick McNeal 
193ff9de394SRick McNeal #define	IDM_SM_TIMER_CLEAR(ic) \
194ff9de394SRick McNeal 	(void) untimeout(ic->ic_state_timeout); \
195ff9de394SRick McNeal 	ic->ic_state_timeout = 0;
196ff9de394SRick McNeal 
197a6d42e7dSPeter Dunlap typedef enum {
198a6d42e7dSPeter Dunlap 	CT_NONE = 0,
199a6d42e7dSPeter Dunlap 	CT_RX_PDU,
200a6d42e7dSPeter Dunlap 	CT_TX_PDU
201a6d42e7dSPeter Dunlap } idm_pdu_event_type_t;
202a6d42e7dSPeter Dunlap 
203a6d42e7dSPeter Dunlap typedef enum {
204a6d42e7dSPeter Dunlap 	CA_TX_PROTOCOL_ERROR,	/* Send "protocol error" to state machine */
205a6d42e7dSPeter Dunlap 	CA_RX_PROTOCOL_ERROR,	/* Send "protocol error" to state machine */
20630e7468fSPeter Dunlap 	CA_FORWARD,		/* State machine event and forward to client */
207a6d42e7dSPeter Dunlap 	CA_DROP			/* Drop PDU */
208a6d42e7dSPeter Dunlap } idm_pdu_event_action_t;
209a6d42e7dSPeter Dunlap 
210a6d42e7dSPeter Dunlap typedef struct {
211a6d42e7dSPeter Dunlap 	struct idm_conn_s	*iec_ic;
212a6d42e7dSPeter Dunlap 	idm_conn_event_t	iec_event;
213a6d42e7dSPeter Dunlap 	uintptr_t		iec_info;
214a6d42e7dSPeter Dunlap 	idm_pdu_event_type_t	iec_pdu_event_type;
21530e7468fSPeter Dunlap 	boolean_t		iec_pdu_forwarded;
216a6d42e7dSPeter Dunlap } idm_conn_event_ctx_t;
217a6d42e7dSPeter Dunlap 
218a6d42e7dSPeter Dunlap idm_status_t
219a6d42e7dSPeter Dunlap idm_conn_sm_init(struct idm_conn_s *ic);
220a6d42e7dSPeter Dunlap 
221a6d42e7dSPeter Dunlap void
222a6d42e7dSPeter Dunlap idm_conn_sm_fini(struct idm_conn_s *ic);
223a6d42e7dSPeter Dunlap 
224a6d42e7dSPeter Dunlap idm_status_t
225a6d42e7dSPeter Dunlap idm_notify_client(struct idm_conn_s *ic, idm_client_notify_t cn,
226a6d42e7dSPeter Dunlap     uintptr_t data);
227a6d42e7dSPeter Dunlap 
228a6d42e7dSPeter Dunlap void
229a6d42e7dSPeter Dunlap idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data);
230a6d42e7dSPeter Dunlap 
23130e7468fSPeter Dunlap void
23230e7468fSPeter Dunlap idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data);
23330e7468fSPeter Dunlap 
23430e7468fSPeter Dunlap void
23530e7468fSPeter Dunlap idm_conn_event_locked(struct idm_conn_s *ic, idm_conn_event_t event,
23630e7468fSPeter Dunlap     uintptr_t event_info, idm_pdu_event_type_t pdu_event_type);
23730e7468fSPeter Dunlap 
238a6d42e7dSPeter Dunlap idm_status_t
239a6d42e7dSPeter Dunlap idm_conn_reinstate_event(struct idm_conn_s *old_ic, struct idm_conn_s *new_ic);
240a6d42e7dSPeter Dunlap 
241a6d42e7dSPeter Dunlap void
242a6d42e7dSPeter Dunlap idm_conn_tx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event,
243a6d42e7dSPeter Dunlap     uintptr_t data);
244a6d42e7dSPeter Dunlap 
245a6d42e7dSPeter Dunlap void
246a6d42e7dSPeter Dunlap idm_conn_rx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event,
247a6d42e7dSPeter Dunlap     uintptr_t data);
248a6d42e7dSPeter Dunlap 
249a6d42e7dSPeter Dunlap char *
250a6d42e7dSPeter Dunlap idm_conn_state_str(struct idm_conn_s *ic);
251a6d42e7dSPeter Dunlap 
252a6d42e7dSPeter Dunlap #ifdef	__cplusplus
253a6d42e7dSPeter Dunlap }
254a6d42e7dSPeter Dunlap #endif
255a6d42e7dSPeter Dunlap 
256a6d42e7dSPeter Dunlap #endif /* _IDM_CONN_SM_H_ */
257