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 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 26 */ 27 #ifndef _IDM_CONN_SM_H_ 28 #define _IDM_CONN_SM_H_ 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 35 /* 36 * IDM connection state machine events. Most events get generated internally 37 * either by the state machine or by the IDM TX/RX code. For example when IDM 38 * receives a login request for a target connectionit will generate a 39 * CE_LOGIN_RCV event. Similarly when the target sends a successful login 40 * response IDM generate a "CE_LOGIN_SUCCESS_SND" event. The following 41 * events are not detected on the TX/RX path and must be generated explicitly 42 * by the client when appropriate: 43 * 44 * CE_LOGOUT_OTHER_CONN_RCV 45 * CE_ASYNC_DROP_CONN_RCV (Only because the message may be received on 46 * a different connection from the connection being dropped) 47 * CE_ASYNC_DROP_ALL_CONN_RCV 48 * CE_LOGOUT_OTHER_CONN_SND 49 * CE_ASYNC_DROP_ALL_CONN_SND 50 * 51 * The following events might occur in any state since they are driven 52 * by the PDU's that IDM receives: 53 * 54 * CE_LOGIN_RCV 55 * CE_LOGIN_SUCCESS_RCV 56 * CE_LOGIN_FAIL_RCV 57 * CE_LOGOUT_SUCCESS_RCV 58 * CE_LOGOUT_FAIL_RCV 59 * CE_ASYNC_LOGOUT_RCV 60 * CE_MISC_RCV 61 * CE_RX_PROTOCOL_ERROR 62 */ 63 64 #define IDM_LOGIN_SECONDS 20 65 #define IDM_LOGOUT_SECONDS 20 66 #define IDM_CLEANUP_SECONDS 0 67 68 /* Update idm_ce_name table whenever connection events are modified */ 69 typedef enum { 70 CE_UNDEFINED = 0, 71 72 /* Initiator events */ 73 CE_CONNECT_REQ, 74 CE_CONNECT_FAIL, 75 CE_CONNECT_SUCCESS, 76 CE_LOGIN_SND, 77 CE_LOGIN_SUCCESS_RCV, 78 CE_LOGIN_FAIL_RCV, 79 CE_LOGOUT_THIS_CONN_SND, 80 CE_LOGOUT_OTHER_CONN_SND, 81 CE_LOGOUT_SESSION_SND, 82 CE_LOGOUT_SUCCESS_RCV, 83 CE_LOGOUT_FAIL_RCV, 84 CE_ASYNC_LOGOUT_RCV, 85 CE_ASYNC_DROP_CONN_RCV, 86 CE_ASYNC_DROP_ALL_CONN_RCV, 87 88 /* Target events */ 89 CE_CONNECT_ACCEPT, 90 CE_CONNECT_REJECT, 91 CE_LOGIN_RCV, 92 CE_LOGIN_TIMEOUT, 93 CE_LOGIN_SUCCESS_SND, 94 CE_LOGIN_FAIL_SND, 95 CE_LOGIN_FAIL_SND_DONE, 96 CE_LOGOUT_THIS_CONN_RCV, 97 CE_LOGOUT_OTHER_CONN_RCV, 98 CE_LOGOUT_SESSION_RCV, 99 CE_LOGOUT_SUCCESS_SND, 100 CE_LOGOUT_SUCCESS_SND_DONE, 101 CE_LOGOUT_FAIL_SND, 102 CE_LOGOUT_FAIL_SND_DONE, 103 CE_CLEANUP_TIMEOUT, 104 CE_ASYNC_LOGOUT_SND, 105 CE_ASYNC_DROP_CONN_SND, 106 CE_ASYNC_DROP_ALL_CONN_SND, 107 CE_LOGOUT_TIMEOUT, 108 109 /* Common events */ 110 CE_TRANSPORT_FAIL, 111 CE_MISC_TX, 112 CE_TX_PROTOCOL_ERROR, 113 CE_MISC_RX, 114 CE_RX_PROTOCOL_ERROR, 115 CE_LOGOUT_SESSION_SUCCESS, 116 CE_CONN_REINSTATE, 117 CE_CONN_REINSTATE_SUCCESS, 118 CE_CONN_REINSTATE_FAIL, 119 CE_ENABLE_DM_SUCCESS, 120 CE_ENABLE_DM_FAIL, 121 122 /* Add new events above CE_MAX_EVENT */ 123 CE_MAX_EVENT 124 } idm_conn_event_t; 125 126 #ifdef IDM_CONN_SM_STRINGS 127 /* An array of event text values, for use in logging events */ 128 static const char *idm_ce_name[CE_MAX_EVENT+1] = { 129 "CE_UNDEFINED", 130 "CE_CONNECT_REQ", 131 "CE_CONNECT_FAIL", 132 "CE_CONNECT_SUCCESS", 133 "CE_LOGIN_SND", 134 "CE_LOGIN_SUCCESS_RCV", 135 "CE_LOGIN_FAIL_RCV", 136 "CE_LOGOUT_THIS_CONN_SND", 137 "CE_LOGOUT_OTHER_CONN_SND", 138 "CE_LOGOUT_SESSION_SND", 139 "CE_LOGOUT_SUCCESS_RCV", 140 "CE_LOGOUT_FAIL_RCV", 141 "CE_ASYNC_LOGOUT_RCV", 142 "CE_ASYNC_DROP_CONN_RCV", 143 "CE_ASYNC_DROP_ALL_CONN_RCV", 144 "CE_CONNECT_ACCEPT", 145 "CE_CONNECT_REJECT", 146 "CE_LOGIN_RCV", 147 "CE_LOGIN_TIMEOUT", 148 "CE_LOGIN_SUCCESS_SND", 149 "CE_LOGIN_FAIL_SND", 150 "CE_LOGIN_FAIL_SND_DONE", 151 "CE_LOGOUT_THIS_CONN_RCV", 152 "CE_LOGOUT_OTHER_CONN_RCV", 153 "CE_LOGOUT_SESSION_RCV", 154 "CE_LOGOUT_SUCCESS_SND", 155 "CE_LOGOUT_SUCCESS_SND_DONE", 156 "CE_LOGOUT_FAIL_SND", 157 "CE_LOGOUT_FAIL_SND_DONE", 158 "CE_CLEANUP_TIMEOUT", 159 "CE_ASYNC_LOGOUT_SND", 160 "CE_ASYNC_DROP_CONN_SND", 161 "CE_ASYNC_DROP_ALL_CONN_SND", 162 "CE_LOGOUT_TIMEOUT", 163 "CE_TRANSPORT_FAIL", 164 "CE_MISC_TX", 165 "CE_TX_PROTOCOL_ERROR", 166 "CE_MISC_RX", 167 "CE_RX_PROTOCOL_ERROR", 168 "CE_LOGOUT_SESSION_SUCCESS", 169 "CE_CONN_REINSTATE", 170 "CE_CONN_REINSTATE_SUCCESS", 171 "CE_CONN_REINSTATE_FAIL", 172 "CE_ENABLE_DM_SUCCESS", 173 "CE_ENABLE_DM_FAIL", 174 "CE_MAX_EVENT" 175 }; 176 #endif 177 178 /* Update idm_cs_name table whenever connection states are modified */ 179 typedef enum { 180 CS_S0_UNDEFINED = 0, 181 182 CS_S1_FREE, 183 CS_S2_XPT_WAIT, 184 CS_S3_XPT_UP, 185 CS_S4_IN_LOGIN, 186 CS_S5_LOGGED_IN, 187 CS_S6_IN_LOGOUT, 188 CS_S7_LOGOUT_REQ, 189 CS_S8_CLEANUP, 190 CS_S9_INIT_ERROR, 191 CS_S10_IN_CLEANUP, 192 CS_S11_COMPLETE, 193 CS_S12_ENABLE_DM, 194 CS_S9A_REJECTED, 195 CS_S9B_WAIT_SND_DONE, 196 197 /* Add new connection states above CS_MAX_STATE */ 198 CS_MAX_STATE 199 } idm_conn_state_t; 200 201 #ifdef IDM_CONN_SM_STRINGS 202 /* An array of state text values, for use in logging state transitions */ 203 static const char *idm_cs_name[CS_MAX_STATE+1] = { 204 "CS_S0_UNDEFINED", 205 "CS_S1_FREE", 206 "CS_S2_XPT_WAIT", 207 "CS_S3_XPT_UP", 208 "CS_S4_IN_LOGIN", 209 "CS_S5_LOGGED_IN", 210 "CS_S6_IN_LOGOUT", 211 "CS_S7_LOGOUT_REQ", 212 "CS_S8_CLEANUP", 213 "CS_S9_INIT_ERROR", 214 "CS_S10_IN_CLEANUP", 215 "CS_S11_COMPLETE", 216 "CS_S12_ENABLE_DM", 217 "CS_S9A_REJECTED", 218 "CS_S9B_WAIT_SND_DONE", 219 "CS_MAX_STATE" 220 }; 221 #endif 222 223 /* 224 * Currently the state machine has a condition where idm_login_timeout() is 225 * left active after the connection has been closed. This causes the system 226 * to panic when idm_login_timeout() modifies the freed memory. In an attempt 227 * to isolate and find this issue special attention is being placed on 228 * the ic_state_timeout value. After each untimeout call the value will now 229 * be cleared. Just before the value is set the code will check for 0 and 230 * display an error. One final change is being done in idm_conn_sm_fini() which 231 * if ic_state_machine is not 0, an error message will be displayed and 232 * untimeout() called. That should prevent customer sites from seeing the 233 * panic. The code also calls ASSERT(0) which should cause a panic during 234 * system test. 235 */ 236 #define IDM_SM_TIMER_CHECK(ic) \ 237 if (ic->ic_state_timeout) { \ 238 cmn_err(CE_WARN, "%s: existing timeout still set. " \ 239 "state: %s, last: %s\n", __func__, \ 240 idm_cs_name[ic->ic_state], \ 241 idm_cs_name[ic->ic_last_state]); \ 242 ASSERT(0); \ 243 } 244 245 #define IDM_SM_TIMER_CLEAR(ic) \ 246 (void) untimeout(ic->ic_state_timeout); \ 247 ic->ic_state_timeout = 0; 248 249 typedef enum { 250 CT_NONE = 0, 251 CT_RX_PDU, 252 CT_TX_PDU 253 } idm_pdu_event_type_t; 254 255 typedef enum { 256 CA_TX_PROTOCOL_ERROR, /* Send "protocol error" to state machine */ 257 CA_RX_PROTOCOL_ERROR, /* Send "protocol error" to state machine */ 258 CA_FORWARD, /* State machine event and forward to client */ 259 CA_DROP /* Drop PDU */ 260 } idm_pdu_event_action_t; 261 262 typedef struct { 263 struct idm_conn_s *iec_ic; 264 idm_conn_event_t iec_event; 265 uintptr_t iec_info; 266 idm_pdu_event_type_t iec_pdu_event_type; 267 boolean_t iec_pdu_forwarded; 268 } idm_conn_event_ctx_t; 269 270 idm_status_t 271 idm_conn_sm_init(struct idm_conn_s *ic); 272 273 void 274 idm_conn_sm_fini(struct idm_conn_s *ic); 275 276 idm_status_t 277 idm_notify_client(struct idm_conn_s *ic, idm_client_notify_t cn, 278 uintptr_t data); 279 280 void 281 idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data); 282 283 void 284 idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data); 285 286 void 287 idm_conn_event_locked(struct idm_conn_s *ic, idm_conn_event_t event, 288 uintptr_t event_info, idm_pdu_event_type_t pdu_event_type); 289 290 idm_status_t 291 idm_conn_reinstate_event(struct idm_conn_s *old_ic, struct idm_conn_s *new_ic); 292 293 void 294 idm_conn_tx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event, 295 uintptr_t data); 296 297 void 298 idm_conn_rx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event, 299 uintptr_t data); 300 301 char * 302 idm_conn_state_str(struct idm_conn_s *ic); 303 304 #ifdef __cplusplus 305 } 306 #endif 307 308 #endif /* _IDM_CONN_SM_H_ */ 309