Esempio n. 1
0
/*
 * iser_conn_disconnect()
 * Shutdown this iSER connection
 */
static void
iser_conn_disconnect(idm_conn_t *ic)
{
    iser_conn_t	*iser_conn;

    iser_conn = (iser_conn_t *)ic->ic_transport_private;

    mutex_enter(&iser_conn->ic_lock);
    iser_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
    mutex_exit(&iser_conn->ic_lock);

    /* Close the channel */
    iser_channel_close(iser_conn->ic_chan);

    /* Free our reference held on the IDM conn handle, and set CLOSED */
    mutex_enter(&iser_conn->ic_lock);
    idm_conn_rele(iser_conn->ic_idmc);
    iser_conn->ic_stage = ISER_CONN_STAGE_CLOSED;
    mutex_exit(&iser_conn->ic_lock);
}
Esempio n. 2
0
static void
idm_conn_event_handler(void *event_ctx_opaque)
{
	idm_conn_event_ctx_t *event_ctx = event_ctx_opaque;
	idm_conn_t *ic = event_ctx->iec_ic;
	idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info;
	idm_pdu_event_action_t action;

	IDM_SM_LOG(CE_NOTE, "idm_conn_event_handler: conn %p event %s(%d)",
	    (void *)ic, idm_ce_name[event_ctx->iec_event],
	    event_ctx->iec_event);
	DTRACE_PROBE2(conn__event,
	    idm_conn_t *, ic, idm_conn_event_ctx_t *, event_ctx);

	/*
	 * Validate event
	 */
	ASSERT(event_ctx->iec_event != CE_UNDEFINED);
	ASSERT3U(event_ctx->iec_event, <, CE_MAX_EVENT);

	/*
	 * Validate current state
	 */
	ASSERT(ic->ic_state != CS_S0_UNDEFINED);
	ASSERT3U(ic->ic_state, <, CS_MAX_STATE);

	/*
	 * Validate PDU-related events against the current state.  If a PDU
	 * is not allowed in the current state we change the event to a
	 * protocol error.  This simplifies the state-specific event handlers.
	 * For example the CS_S2_XPT_WAIT state only needs to handle the
	 * CE_TX_PROTOCOL_ERROR and CE_RX_PROTOCOL_ERROR events since
	 * no PDU's can be transmitted or received in that state.
	 */
	event_ctx->iec_pdu_forwarded = B_FALSE;
	if (event_ctx->iec_pdu_event_type != CT_NONE) {
		ASSERT(pdu != NULL);
		action = idm_conn_sm_validate_pdu(ic, event_ctx, pdu);

		switch (action) {
		case CA_TX_PROTOCOL_ERROR:
			/*
			 * Change event and forward the PDU
			 */
			event_ctx->iec_event = CE_TX_PROTOCOL_ERROR;
			break;
		case CA_RX_PROTOCOL_ERROR:
			/*
			 * Change event and forward the PDU.
			 */
			event_ctx->iec_event = CE_RX_PROTOCOL_ERROR;
			break;
		case CA_FORWARD:
			/*
			 * Let the state-specific event handlers take
			 * care of it.
			 */
			break;
		case CA_DROP:
			/*
			 * It never even happened
			 */
			IDM_SM_LOG(CE_NOTE, "*** drop PDU %p", (void *) pdu);
			idm_pdu_complete(pdu, IDM_STATUS_FAIL);
			break;
		default:
			ASSERT(0);
			break;
		}
	}

	switch (ic->ic_state) {
	case CS_S1_FREE:
		idm_state_s1_free(ic, event_ctx);
		break;
	case CS_S2_XPT_WAIT:
		idm_state_s2_xpt_wait(ic, event_ctx);
		break;
	case CS_S3_XPT_UP:
		idm_state_s3_xpt_up(ic, event_ctx);
		break;
	case CS_S4_IN_LOGIN:
		idm_state_s4_in_login(ic, event_ctx);
		break;
	case CS_S5_LOGGED_IN:
		idm_state_s5_logged_in(ic, event_ctx);
		break;
	case CS_S6_IN_LOGOUT:
		idm_state_s6_in_logout(ic, event_ctx);
		break;
	case CS_S7_LOGOUT_REQ:
		idm_state_s7_logout_req(ic, event_ctx);
		break;
	case CS_S8_CLEANUP:
		idm_state_s8_cleanup(ic, event_ctx);
		break;
	case CS_S9A_REJECTED:
		idm_state_s9a_rejected(ic, event_ctx);
		break;
	case CS_S9B_WAIT_SND_DONE:
		idm_state_s9b_wait_snd_done(ic, event_ctx);
		break;
	case CS_S9_INIT_ERROR:
		idm_state_s9_init_error(ic, event_ctx);
		break;
	case CS_S10_IN_CLEANUP:
		idm_state_s10_in_cleanup(ic, event_ctx);
		break;
	case CS_S11_COMPLETE:
		idm_state_s11_complete(ic, event_ctx);
		break;
	case CS_S12_ENABLE_DM:
		idm_state_s12_enable_dm(ic, event_ctx);
		break;
	default:
		ASSERT(0);
		break;
	}

	/*
	 * Now that we've updated the state machine, if this was
	 * a PDU-related event take the appropriate action on the PDU
	 * (transmit it, forward it to the clients RX callback, drop
	 * it, etc).
	 */
	if (event_ctx->iec_pdu_event_type != CT_NONE) {
		switch (action) {
		case CA_TX_PROTOCOL_ERROR:
			idm_pdu_tx_protocol_error(ic, pdu);
			break;
		case CA_RX_PROTOCOL_ERROR:
			idm_pdu_rx_protocol_error(ic, pdu);
			break;
		case CA_FORWARD:
			if (!event_ctx->iec_pdu_forwarded) {
				if (event_ctx->iec_pdu_event_type ==
				    CT_RX_PDU) {
					idm_pdu_rx_forward(ic, pdu);
				} else {
					idm_pdu_tx_forward(ic, pdu);
				}
			}
			break;
		default:
			ASSERT(0);
			break;
		}
	}

	/*
	 * Update outstanding PDU event count (see idm_pdu_tx for
	 * how this is used)
	 */
	if ((event_ctx->iec_pdu_event_type == CT_TX_PDU) ||
	    (event_ctx->iec_pdu_event_type == CT_RX_PDU)) {
		mutex_enter(&ic->ic_state_mutex);
		ic->ic_pdu_events--;
		mutex_exit(&ic->ic_state_mutex);
	}

	idm_conn_rele(ic);
	kmem_free(event_ctx, sizeof (*event_ctx));
}