예제 #1
0
/*
 * iser_ini_conn_connect()
 * Establish the connection referred to by the handle previously allocated via
 * iser_ini_conn_create().
 */
static idm_status_t
iser_ini_conn_connect(idm_conn_t *ic)
{
    iser_conn_t		*iser_conn;
    iser_status_t		status;

    iser_conn = (iser_conn_t *)ic->ic_transport_private;

    status = iser_channel_open(iser_conn->ic_chan);
    if (status != ISER_STATUS_SUCCESS) {
        ISER_LOG(CE_WARN, "iser: failed to open channel");
        return (IDM_STATUS_FAIL);
    }

    /*
     * Set the local and remote addresses in the idm conn handle.
     */
    iser_ib_conv_ibtaddr2sockaddr(&ic->ic_laddr,
                                  &iser_conn->ic_chan->ic_localip, iser_conn->ic_chan->ic_lport);
    iser_ib_conv_ibtaddr2sockaddr(&ic->ic_raddr,
                                  &iser_conn->ic_chan->ic_remoteip, iser_conn->ic_chan->ic_rport);

    mutex_enter(&iser_conn->ic_lock);
    /* Hold a reference on the IDM connection handle */
    idm_conn_hold(ic);
    iser_conn->ic_stage = ISER_CONN_STAGE_IC_CONNECTED;
    mutex_exit(&iser_conn->ic_lock);

    return (IDM_STATUS_SUCCESS);
}
예제 #2
0
static ibt_cm_status_t
iser_handle_cm_conn_est(ibt_cm_event_t *evp)
{
	iser_chan_t	*iser_chan;
	iser_conn_t	*iser_conn;
	iser_svc_t	*iser_svc;
	idm_status_t	status;
	idm_conn_t	*ic;

	iser_chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel);

	/*
	 * An ibt_open_rc_channel() comes in as a IBT_CM_EVENT_REQ_RCV on the
	 * iSER-IB target, upon which the target sends a Response, accepting
	 * the request. This comes in as a IBT_CM_EVENT_REP_RCV on the iSER-IB
	 * initiator, which then sends an RTU. Upon getting this RTU from the
	 * iSER-IB initiator, the IBT_CM_EVENT_CONN_EST event is generated on
	 * the target. Then subsequently an IBT_CM_EVENT_CONN_EST event is
	 * generated on the initiator.
	 *
	 * Our new connection has been established on the target. If we are
	 * receiving this event on the target side, the iser_channel can be
	 * used as it is already populated. On the target side, an IDM
	 * connection is then allocated and the IDM layer is notified.
	 * If we are on the initiator we needn't do anything, since we
	 * already have the IDM linkage in place for this connection.
	 */
	if (iser_chan->ic_conn->ic_type == ISER_CONN_TYPE_TGT) {

		iser_conn = iser_chan->ic_conn;
		iser_svc  = (iser_svc_t *)iser_conn->ic_idms->is_iser_svc;

		mutex_enter(&iser_conn->ic_lock);

		status = idm_svc_conn_create(iser_conn->ic_idms,
		    IDM_TRANSPORT_TYPE_ISER, &ic);
		if (status != IDM_STATUS_SUCCESS) {
			/*
			 * No IDM rsrcs or something equally Bad.
			 * Return non-SUCCESS to IBCM. He'll give
			 * us a CONN_CLOSED, which we'll handle
			 * below.
			 */
			ISER_LOG(CE_NOTE, "iser_handle_cm_conn_est: "
			    "idm_svc_conn_create_failed");
			mutex_exit(&iser_conn->ic_lock);
			return (IBT_CM_NO_RESOURCE);
		}

		/* We no longer need the hold on the iSER service handle */
		iser_tgt_svc_rele(iser_svc);

		/* Hold a reference on the IDM connection handle */
		idm_conn_hold(ic);

		/* Set the transport ops and conn on the idm_conn handle */
		ic->ic_transport_ops = &iser_transport_ops;
		ic->ic_transport_private = (void *)iser_conn;
		ic->ic_transport_hdrlen = ISER_HEADER_LENGTH;
		iser_conn->ic_idmc = ic;

		/*
		 * Set the local and remote addresses in the idm conn handle.
		 */
		iser_ib_conv_ibtaddr2sockaddr(&ic->ic_laddr,
		    &iser_conn->ic_chan->ic_localip, iser_chan->ic_lport);
		iser_ib_conv_ibtaddr2sockaddr(&ic->ic_raddr,
		    &iser_conn->ic_chan->ic_remoteip, iser_chan->ic_rport);

		/*
		 * Kick the state machine.  At CS_S3_XPT_UP the state machine
		 * will notify the client (target) about the new connection.
		 */
		idm_conn_event(ic, CE_CONNECT_ACCEPT, NULL);
		iser_conn->ic_stage = ISER_CONN_STAGE_IC_CONNECTED;
		mutex_exit(&iser_conn->ic_lock);

		/*
		 * Post work requests on the receive queue
		 */
		iser_ib_post_recv(iser_chan->ic_chanhdl);

	}

	return (IBT_CM_ACCEPT);
}