Esempio n. 1
0
/*
 * dapl_hca_alloc
 *
 * alloc and initialize an HCA struct
 *
 * Input:
 * 	name
 *      port
 *
 * Output:
 * 	hca_ptr
 *
 * Returns:
 * 	none
 *
 */
DAPL_HCA *dapl_hca_alloc(char *name, char *port)
{
	DAPL_HCA *hca_ptr;

	hca_ptr = dapl_os_alloc(sizeof(DAPL_HCA));
	if (NULL == hca_ptr) {
		goto bail;
	}

	dapl_os_memzero(hca_ptr, sizeof(DAPL_HCA));
	dapl_os_lock_init(&hca_ptr->lock);
	dapl_llist_init_head(&hca_ptr->ia_list_head);

	hca_ptr->name = dapl_os_strdup(name);
	if (NULL == hca_ptr->name) {
		goto bail;
	}

	hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;
	hca_ptr->port_num = dapl_os_strtol(port, NULL, 0);

	return (hca_ptr);

      bail:
	if (NULL != hca_ptr) 
		dapl_os_free(hca_ptr, sizeof(DAPL_HCA));

	return NULL;
}
Esempio n. 2
0
DAPL_LMR *dapl_lmr_alloc(IN DAPL_IA * ia,
			 IN DAT_MEM_TYPE mem_type,
			 IN DAT_REGION_DESCRIPTION region_desc,
			 IN DAT_VLEN length,
			 IN DAT_PZ_HANDLE pz_handle,
			 IN DAT_MEM_PRIV_FLAGS mem_priv)
{
	DAPL_LMR *lmr;

	/* Allocate LMR */
	lmr = (DAPL_LMR *) dapl_os_alloc(sizeof(DAPL_LMR));
	if (NULL == lmr) {
		return (NULL);
	}

	/* zero the structure */
	dapl_os_memzero(lmr, sizeof(DAPL_LMR));

	/*
	 * initialize the header
	 */
	lmr->header.provider = ia->header.provider;
	lmr->header.magic = DAPL_MAGIC_LMR;
	lmr->header.handle_type = DAT_HANDLE_TYPE_LMR;
	lmr->header.owner_ia = ia;
	lmr->header.user_context.as_64 = 0;
	lmr->header.user_context.as_ptr = NULL;
	dapl_llist_init_entry(&lmr->header.ia_list_entry);
	dapl_ia_link_lmr(ia, lmr);
	dapl_os_lock_init(&lmr->header.lock);

	/* 
	 * initialize the body 
	 */
	lmr->param.ia_handle = (DAT_IA_HANDLE) ia;
	lmr->param.mem_type = mem_type;
	lmr->param.region_desc = region_desc;
	lmr->param.length = length;
	lmr->param.pz_handle = pz_handle;
	lmr->param.mem_priv = mem_priv;
	dapl_os_atomic_set(&lmr->lmr_ref_count, 0);

	return (lmr);
}
Esempio n. 3
0
/*
 * dapl_cno_alloc
 *
 * alloc and initialize an EVD struct
 *
 * Input:
 *	ia
 *
 * Returns:
 *	cno_ptr, or null on failure.
 */
DAPL_CNO *
dapl_cno_alloc(
    IN DAPL_IA				*ia_ptr,
    IN DAT_OS_WAIT_PROXY_AGENT		wait_agent)
{
	DAPL_CNO *cno_ptr;

	cno_ptr = (DAPL_CNO *) dapl_os_alloc(sizeof (DAPL_CNO));
	if (!cno_ptr) {
		return (NULL);
	}

	/* zero the structure */
	(void) dapl_os_memzero(cno_ptr, sizeof (DAPL_CNO));

	/*
	 * Initialize the header.
	 */
	cno_ptr->header.provider	= ia_ptr->header.provider;
	cno_ptr->header.magic		= DAPL_MAGIC_CNO;
	cno_ptr->header.handle_type	= DAT_HANDLE_TYPE_CNO;
	cno_ptr->header.owner_ia	= ia_ptr;
	cno_ptr->header.user_context.as_64  = 0;
	cno_ptr->header.user_context.as_ptr = NULL;
	dapl_llist_init_entry(&cno_ptr->header.ia_list_entry);
	dapl_llist_init_head(&cno_ptr->evd_list_head);
	dapl_os_lock_init(&cno_ptr->header.lock);

	/*
	 * Initialize the body
	 */
	cno_ptr->cno_waiters = 0;
	cno_ptr->cno_ref_count = 0;
	cno_ptr->cno_state = DAPL_CNO_STATE_UNTRIGGERED;
	cno_ptr->cno_evd_triggered = NULL;
	cno_ptr->cno_wait_agent = wait_agent;
	(void) dapl_os_wait_object_init(&cno_ptr->cno_wait_object);

	return (cno_ptr);
}
Esempio n. 4
0
/*
 * dapl_sp_alloc
 *
 * alloc and initialize a PSP INFO struct
 *
 * Input:
 * 	IA INFO struct ptr
 *
 * Output:
 * 	sp_ptr
 *
 * Returns:
 * 	NULL
 *	pointer to sp info struct
 *
 */
DAPL_SP *
dapls_sp_alloc(
	IN DAPL_IA *ia_ptr,
	IN DAT_BOOLEAN is_psp)
{
	DAPL_SP *sp_ptr;

	/* Allocate EP */
	sp_ptr = (DAPL_SP *)dapl_os_alloc(sizeof (DAPL_SP));
	if (sp_ptr == NULL) {
		return (NULL);
	}

	/* zero the structure */
	(void) dapl_os_memzero(sp_ptr, sizeof (DAPL_SP));

	/*
	 * initialize the header
	 */
	sp_ptr->header.provider = ia_ptr->header.provider;
	if (is_psp) {
		sp_ptr->header.magic = DAPL_MAGIC_PSP;
		sp_ptr->header.handle_type = DAT_HANDLE_TYPE_PSP;
	} else {
		sp_ptr->header.magic = DAPL_MAGIC_RSP;
		sp_ptr->header.handle_type = DAT_HANDLE_TYPE_RSP;
	}
	sp_ptr->header.owner_ia = ia_ptr;
	sp_ptr->header.user_context.as_64 = 0;
	sp_ptr->header.user_context.as_ptr = NULL;
	dapl_llist_init_entry(&sp_ptr->header.ia_list_entry);
	dapl_os_lock_init(&sp_ptr->header.lock);

	/*
	 * Initialize the Body (set to NULL above)
	 */
	dapl_llist_init_head(&sp_ptr->cr_list_head);

	return (sp_ptr);
}
Esempio n. 5
0
/*
 * dapl_ep_connect
 *
 * DAPL Requirements Version xxx, 6.5.7
 *
 * Request a connection be established between the local Endpoint
 * and a remote Endpoint. This operation is used by the active/client
 * side of a connection
 *
 * Input:
 *	ep_handle
 *	remote_ia_address
 *	remote_conn_qual
 *	timeout
 *	private_data_size
 *	privaet_data
 *	qos
 *	connect_flags
 *
 * Output:
 *	None
 *
 * Returns:
 *	DAT_SUCCESS
 *	DAT_INSUFFICIENT_RESOUCRES
 *	DAT_INVALID_PARAMETER
 *	DAT_MODLE_NOT_SUPPORTED
 */
DAT_RETURN
dapl_ep_connect(
	IN DAT_EP_HANDLE ep_handle,
	IN DAT_IA_ADDRESS_PTR remote_ia_address,
	IN DAT_CONN_QUAL remote_conn_qual,
	IN DAT_TIMEOUT timeout,
	IN DAT_COUNT private_data_size,
	IN const DAT_PVOID private_data,
	IN DAT_QOS qos,
	IN DAT_CONNECT_FLAGS connect_flags)
{
	DAPL_EP *ep_ptr;
	DAPL_PRIVATE prd;
	DAPL_EP	alloc_ep;
	DAT_RETURN dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,
	    "dapl_ep_connect (%p, {%u.%u.%u.%u}, %X, %d, %d, %p, %x, %x)\n",
	    ep_handle,
	    remote_ia_address->sa_data[2],
	    remote_ia_address->sa_data[3],
	    remote_ia_address->sa_data[4],
	    remote_ia_address->sa_data[5],
	    remote_conn_qual,
	    timeout,
	    private_data_size,
	    private_data,
	    qos,
	    connect_flags);

	dat_status = DAT_SUCCESS;
	ep_ptr = (DAPL_EP *) ep_handle;

	/*
	 * Verify parameter & state. The connection handle must be good
	 * at this point.
	 */
	if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EP);
		goto bail;
	}

	if (DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EVD_CONN);
		goto bail;
	}

	/*
	 * If the endpoint needs a QP, associated the QP with it.
	 * This needs to be done carefully, in order to:
	 *	* Avoid allocating under a lock.
	 *  * Not step on data structures being altered by
	 *    routines with which we are racing.
	 * So we:
	 *  * Confirm that a new QP is needed and is not forbidden by the
	 *    current state.
	 *  * Allocate it into a separate EP.
	 *  * Take the EP lock.
	 *  * Reconfirm that the EP is in a state where it needs a QP.
	 *  * Assign the QP and release the lock.
	 */
	if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
		if (ep_ptr->param.pz_handle == NULL ||
		    DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ)) {
			dat_status = DAT_ERROR(DAT_INVALID_STATE,
			    DAT_INVALID_STATE_EP_NOTREADY);
			goto bail;
		}
		alloc_ep = *ep_ptr;

		dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
		    &alloc_ep, ep_ptr);
		if (dat_status != DAT_SUCCESS) {
			dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
			    DAT_RESOURCE_MEMORY);
			goto bail;
		}

		dapl_os_lock(&ep_ptr->header.lock);
		/*
		 * PZ shouldn't have changed since we're only racing with
		 * dapl_cr_accept()
		 */
		if (ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED) {
			/* Bail, cleaning up.  */
			dapl_os_unlock(&ep_ptr->header.lock);
			dat_status = dapls_ib_qp_free(ep_ptr->header.owner_ia,
			    &alloc_ep);
			if (dat_status != DAT_SUCCESS) {
				dapl_dbg_log(DAPL_DBG_TYPE_WARN,
				    "ep_connect: ib_qp_free failed with %x\n",
				    dat_status);
			}
			dat_status = DAT_ERROR(DAT_INVALID_STATE,
			    dapls_ep_state_subtype(ep_ptr));
			goto bail;
		}
		ep_ptr->qp_handle = alloc_ep.qp_handle;
		ep_ptr->qpn = alloc_ep.qpn;
		ep_ptr->qp_state = alloc_ep.qp_state;

		dapl_os_unlock(&ep_ptr->header.lock);
	}

	/*
	 * We do state checks and transitions under lock.
	 * The only code we're racing against is dapl_cr_accept.
	 */
	dapl_os_lock(&ep_ptr->header.lock);

	/*
	 * Verify the attributes of the EP handle before we connect it. Test
	 * all of the handles to make sure they are currently valid.
	 * Specifically:
	 *   pz_handle		required
	 *   recv_evd_handle	optional, but must be valid
	 *   request_evd_handle	optional, but must be valid
	 *   connect_evd_handle	required
	 */
	if (ep_ptr->param.pz_handle == NULL ||
	    DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) ||
	    ep_ptr->param.connect_evd_handle == NULL ||
	    DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle,
	    DAPL_MAGIC_EVD) ||
	    !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags &
	    DAT_EVD_CONNECTION_FLAG) ||
	    (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL &&
	    (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle,
	    DAPL_MAGIC_EVD))) ||
	    (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL &&
	    (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle,
	    DAPL_MAGIC_EVD)))) {
		dapl_os_unlock(&ep_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_STATE,
		    DAT_INVALID_STATE_EP_NOTREADY);
		goto bail;
	}

	/*
	 * Check both the EP state and the QP state: if we don't have a QP
	 *  we need to attach one now.
	 */
	if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
		dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
		    ep_ptr, ep_ptr);

		if (dat_status != DAT_SUCCESS) {
			dapl_os_unlock(&ep_ptr->header.lock);
			dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
			    DAT_RESOURCE_TEP);
			goto bail;
		}
	}

	if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED) {
		dapl_os_unlock(&ep_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_STATE,
		    dapls_ep_state_subtype(ep_ptr));
		goto bail;
	}

	if (qos != DAT_QOS_BEST_EFFORT ||
	    connect_flags != DAT_CONNECT_DEFAULT_FLAG) {
		/*
		 * At this point we only support one QOS level
		 */
		dapl_os_unlock(&ep_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_MODEL_NOT_SUPPORTED, 0);
		goto bail;
	}

	/*
	 * Verify the private data size doesn't exceed the max
	 */
	if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) {
		dapl_os_unlock(&ep_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5);
		goto bail;
	}

	/*
	 * transition the state before requesting a connection to avoid
	 * race conditions
	 */
	ep_ptr->param.ep_state = DAT_EP_STATE_ACTIVE_CONNECTION_PENDING;

	/*
	 * At this point we're committed, and done with the endpoint
	 * except for the connect, so we can drop the lock.
	 */
	dapl_os_unlock(&ep_ptr->header.lock);

	/*
	 * fill in the private data
	 */
	(void) dapl_os_memzero(&prd, sizeof (DAPL_PRIVATE));
	if (private_data_size > 0)
		(void) dapl_os_memcpy(prd.private_data, private_data,
		    private_data_size);

	/* Copy the connection qualifiers */
	(void) dapl_os_memcpy(ep_ptr->param.remote_ia_address_ptr,
	    remote_ia_address, sizeof (DAT_SOCK_ADDR6));
	ep_ptr->param.remote_port_qual = remote_conn_qual;

	dat_status = dapls_ib_connect(ep_handle,
	    remote_ia_address, remote_conn_qual,
	    private_data_size, &prd, timeout);

	if (dat_status != DAT_SUCCESS) {
		DAPL_EVD	*evd_ptr;

		if (dat_status == DAT_ERROR(DAT_INVALID_ADDRESS,
		    DAT_INVALID_ADDRESS_UNREACHABLE)) {
			/* Unreachable IP address */
			evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
			if (evd_ptr != NULL) {
				(void) dapls_evd_post_connection_event(evd_ptr,
				    DAT_CONNECTION_EVENT_UNREACHABLE,
				    (DAT_HANDLE) ep_ptr, 0, 0);
			}
			ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
			dat_status = DAT_SUCCESS;
		} else if (dat_status == DAT_ERROR(DAT_INVALID_PARAMETER,
		    DAT_INVALID_ADDRESS_UNREACHABLE)) {
			/* Non-existant connection qualifier */
			evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
			if (evd_ptr != NULL) {
				(void) dapls_evd_post_connection_event(evd_ptr,
				    DAT_CONNECTION_EVENT_NON_PEER_REJECTED,
				    (DAT_HANDLE) ep_ptr, 0, 0);
			}
			ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
			dat_status = DAT_SUCCESS;
		} else {
			ep_ptr->param.ep_state = DAT_EP_STATE_UNCONNECTED;
		}
	}

bail:
	dapl_dbg_log(DAPL_DBG_TYPE_RTN | DAPL_DBG_TYPE_CM,
	    "dapl_ep_connect () returns 0x%x\n", dat_status);

	return (dat_status);
}
Esempio n. 6
0
/*
 * dapl_cr_accept
 *
 * DAPL Requirements Version xxx, 6.4.2.1
 *
 * Establish a connection between active remote side requesting Endpoint
 * and passic side local Endpoint.
 *
 * Input:
 *	cr_handle
 *	ep_handle
 *	private_data_size
 *	private_data
 *
 * Output:
 *	none
 *
 * Returns:
 *	DAT_SUCCESS
 *	DAT_INVALID_PARAMETER
 *	DAT_INVALID_ATTRIBUTE
 */
DAT_RETURN
dapl_cr_accept(
	IN	DAT_CR_HANDLE		cr_handle,
	IN	DAT_EP_HANDLE		ep_handle,
	IN	DAT_COUNT		private_data_size,
	IN	const DAT_PVOID		private_data)
{
	DAPL_EP		*ep_ptr;
	DAT_RETURN	dat_status;
	DAPL_PRIVATE	prd;
	DAPL_CR		*cr_ptr;
	DAT_EP_STATE	entry_ep_state;
	DAT_EP_HANDLE	entry_ep_handle;

	dapl_dbg_log(DAPL_DBG_TYPE_API,
	    "dapl_cr_accept(%p, %p, %d, %p)\n",
	    cr_handle, ep_handle, private_data_size, private_data);

	if (DAPL_BAD_HANDLE(cr_handle, DAPL_MAGIC_CR)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_CR);
		goto bail;
	}

	cr_ptr = (DAPL_CR *) cr_handle;

	/*
	 * Return an error if we have an ep_handle and the CR already has an
	 * EP, indicating this is an RSP connection or PSP_PROVIDER_FLAG was
	 * specified.
	 */
	if (ep_handle != NULL &&
	    (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP) ||
	    cr_ptr->param.local_ep_handle != NULL)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EP);
		goto bail;
	}

	if ((0 != private_data_size) && (NULL == private_data)) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
		goto bail;
	}

	/*
	 * Verify the private data size doesn't exceed the max
	 */
	if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
		goto bail;
	}

	/*
	 * ep_handle is NULL if the user specified DAT_PSP_PROVIDER_FLAG
	 * OR this is an RSP connection; retrieve it from the cr.
	 */
	if (ep_handle == NULL) {
		ep_handle = cr_ptr->param.local_ep_handle;
		if ((((DAPL_EP *) ep_handle)->param.ep_state !=
		    DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING) &&
		    (((DAPL_EP *)ep_handle)->param.ep_state !=
		    DAT_EP_STATE_PASSIVE_CONNECTION_PENDING)) {
			return (DAT_INVALID_STATE);
		}
	} else {
		/* ensure this EP isn't connected or in use */
		if (((DAPL_EP *)ep_handle)->param.ep_state !=
		    DAT_EP_STATE_UNCONNECTED) {
			return (DAT_INVALID_STATE);
		}
	}

	ep_ptr = (DAPL_EP *) ep_handle;

	/*
	 * Verify the attributes of the EP handle before we connect it. Test
	 * all of the handles to make sure they are currently valid.
	 * Specifically:
	 *   pz_handle		required
	 *   recv_evd_handle	optional, but must be valid
	 *   request_evd_handle	optional, but must be valid
	 *   connect_evd_handle	required
	 * We do all verification and state change under lock, at which
	 * point the EP state should protect us from most races.
	 */
	dapl_os_lock(&ep_ptr->header.lock);
	if ((ep_ptr->param.pz_handle == NULL) ||
	    DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) ||
	    (ep_ptr->param.connect_evd_handle == NULL) ||
	    DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD) ||
	    !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags &
	    DAT_EVD_CONNECTION_FLAG) ||
	    (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL &&
	    (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD))) ||
	    (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL &&
	    (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle,
	    DAPL_MAGIC_EVD)))) {
		dapl_os_unlock(&ep_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EP);
		goto bail;
	}

	if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
		/*
		 * If we are lazy attaching the QP then we may need to
		 * hook it up here. Typically, we run this code only for
		 * DAT_PSP_PROVIDER_FLAG
		 */
		dat_status = dapls_ib_qp_alloc(cr_ptr->header.owner_ia, ep_ptr,
		    ep_ptr);

		if (dat_status != DAT_SUCCESS) {
			/* This is not a great error code, but spec allows */
			dapl_os_unlock(&ep_ptr->header.lock);
			dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
			    DAT_INVALID_HANDLE_EP);
			goto bail;
		}
	}

	entry_ep_state = ep_ptr->param.ep_state;
	entry_ep_handle = cr_ptr->param.local_ep_handle;
	ep_ptr->param.ep_state = DAT_EP_STATE_COMPLETION_PENDING;
	ep_ptr->cm_handle = cr_ptr->ib_cm_handle;
	ep_ptr->cr_ptr = cr_ptr;
	ep_ptr->param.remote_ia_address_ptr = cr_ptr->param.
	    remote_ia_address_ptr;
	cr_ptr->param.local_ep_handle = ep_handle;

	/*
	 * private data
	 */
	(void) dapl_os_memcpy(prd.private_data, private_data,
	    private_data_size);
	(void) dapl_os_memzero(prd.private_data + private_data_size,
	    sizeof (DAPL_PRIVATE) - private_data_size);

	dapl_os_unlock(&ep_ptr->header.lock);

	dat_status = dapls_ib_accept_connection(cr_handle, ep_handle, &prd);

	/*
	 * If the provider failed, unwind the damage so we are back at
	 * the initial state.
	 */
	if (dat_status != DAT_SUCCESS) {
		ep_ptr->param.ep_state = entry_ep_state;
		cr_ptr->param.local_ep_handle = entry_ep_handle;
	} else {
		/*
		 * Make this CR invalid. We need to hang on to it until
		 * the connection terminates, but it's destroyed from
		 * the app point of view.
		 */
		cr_ptr->header.magic = DAPL_MAGIC_CR_DESTROYED;
	}

bail:
	return (dat_status);
}
Esempio n. 7
0
DAT_RETURN
dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,
                 IN DAT_IA_ADDRESS_PTR remote_ia_address, IN DAT_CONN_QUAL remote_conn_qual,
                 IN DAT_COUNT prd_size, IN DAPL_PRIVATE *prd_ptr, IN DAT_TIMEOUT timeout)
{
    dapl_ep_connect_t args;
    DAPL_EP *ep_p = (DAPL_EP *)ep_handle;
    struct sockaddr *s;
    char addr_buf[64];
    ib_gid_t dgid;
    int retval;
    struct sockaddr_in6 *v6addr;
    struct sockaddr_in *v4addr;
    dapl_ia_addr_t *sap;

    s = (struct sockaddr *)remote_ia_address;
    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_connect: ep 0x%p\n"
                 "                  addr %s, conn_qual %016llu, ep_hkey %016llx\n"
                 "                  prd_size %d, timeout 0x%x\n",
                 ep_p, dapls_inet_ntop(s, addr_buf, 64), remote_conn_qual,
                 ep_p->qp_handle->ep_hkey, prd_size, timeout);
    if (ep_p->qp_handle == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_connect: ep 0x%p, addr %s, conn_qual %016llu, "
                     "qp_handle == NULL\n", ep_p, dapls_inet_ntop(s,
                             addr_buf, 64), remote_conn_qual);
        return (DAT_INVALID_PARAMETER);
    }
    if (timeout == DAT_TIMEOUT_INFINITE) {
        args.epc_timeout = 0;
    } else {
        args.epc_timeout = timeout;
    }
    /* resolve remote address to dgid */
    retval = dapls_ns_lookup_address(ep_p->header.owner_ia,
                                     remote_ia_address, timeout, &dgid);
    if (retval == DAT_SUCCESS) {
        args.epc_dgid = dgid;
    } else if ((retval & DAT_SUBTYPE_MASK) ==
               DAT_INVALID_ADDRESS_UNREACHABLE) {
        /* let the kernel driver look up the dgid from ATS */
        args.epc_dgid.gid_guid = 0ULL;
        args.epc_dgid.gid_prefix = 0ULL;
    } else {
        return (retval);
    }
    args.epc_sid = remote_conn_qual;
    args.epc_hkey = ep_p->qp_handle->ep_hkey;
    sap = (dapl_ia_addr_t *)&args.epc_raddr_sadata;
    /*
     * filled in the remote_ia_address for consistent though
     * not necessary when dapls_ns_lookup_address has resolved the dgid
     */
    switch (s->sa_family) {
    case AF_INET:
        /* LINTED: E_BAD_PTR_CAST_ALIGN */
        v4addr = (struct sockaddr_in *)s;
        sap->iad_v4pad[0] = 0;
        sap->iad_v4pad[1] = 0;
        sap->iad_v4pad[2] = 0;
        sap->iad_v4 = v4addr->sin_addr;
        break;
    case AF_INET6:
        /* LINTED: E_BAD_PTR_CAST_ALIGN */
        v6addr = (struct sockaddr_in6 *)s;
        sap->iad_v6 = v6addr->sin6_addr;
        break;
    }

    /* establish the hello message */
    (void) dapl_os_memzero((void *)&prd_ptr->hello_msg,
                           sizeof (DAPL_HELLO_MSG));
    /* on ATS leave the msg blank to avoid confusion to 3rd parties */
    if ((args.epc_dgid.gid_guid | args.epc_dgid.gid_prefix)) {
        prd_ptr->hello_msg.hi_checksum = DAPL_CHECKSUM;
        prd_ptr->hello_msg.hi_clen = prd_size;
        prd_ptr->hello_msg.hi_mid = 0;
        prd_ptr->hello_msg.hi_vers = DAPL_HELLO_MSG_VERS;

        /* fill in local address */
        s = (struct sockaddr *)
            &ep_p->header.owner_ia->hca_ptr->hca_address;
        prd_ptr->hello_msg.hi_ipv = (uint8_t)s->sa_family;
        switch (s->sa_family) {
        case AF_INET:
            /* LINTED: E_BAD_PTR_CAST_ALIGN */
            v4addr = (struct sockaddr_in *)s;
            prd_ptr->hello_msg.hi_port = v4addr->sin_port;
            prd_ptr->hello_msg.hi_v4ipaddr = v4addr->sin_addr;
            break;
        case AF_INET6:
            /* LINTED: E_BAD_PTR_CAST_ALIGN */
            v6addr = (struct sockaddr_in6 *)s;
            prd_ptr->hello_msg.hi_port = v6addr->sin6_port;
            prd_ptr->hello_msg.hi_v6ipaddr = v6addr->sin6_addr;
            break;
        default:
            break; /* fall through */
        }
    }
    if (prd_size > 0) {
        (void) dapl_os_memcpy((void *)&args.epc_priv[0],
                              (void *)prd_ptr, sizeof (DAPL_PRIVATE));
    } else {
        (void) dapl_os_memcpy((void *)
                              &args.epc_priv[DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE],
                              (void *)&prd_ptr->hello_msg, sizeof (DAPL_HELLO_MSG));
    }
    args.epc_priv_sz = sizeof (DAPL_PRIVATE);

    retval = ioctl(ep_p->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                   DAPL_EP_CONNECT, &args);
    if (retval != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_connect: connect failed %s, retval %d\n\n",
                     strerror(errno), retval);
        return (dapls_convert_error(errno, retval));
    }

    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_connect: connected to %s\n\n",
                 dapls_inet_ntop(s, addr_buf, 64));
    return (DAT_SUCCESS);
}
Esempio n. 8
0
static int
dapls_ns_resolve_addr(int af, struct sockaddr *addr, DAT_TIMEOUT timeout)
{
	struct sockaddr_storage	sock;
	struct sockaddr_in	*v4dest;
	struct sockaddr_in6	*v6dest;
	struct pollfd		pollfd;
	int			fd, retval;
	int			tmo;
	int			ip_version;

	if (af == AF_INET) {
		ip_version = 4;
	} else if (af == AF_INET6) {
		ip_version = 6;
	} else {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_resolve_addr: invalid af %d\n", af);
		return (-1);
	}
	fd = socket(af, SOCK_STREAM, 0);
	if (fd < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_resolve_addr: ipv%d, cannot create socket %s\n",
		    ip_version, strerror(errno));
		return (-1);
	}

	/*
	 * set socket to non-blocking mode
	 */
	retval = fcntl(fd, F_SETFL, O_NONBLOCK);
	if (retval < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_resolve_addr: ipv%d, fcntl failed: %s\n",
		    ip_version, strerror(errno));
		(void) close(fd);
		return (-1);
	}

	/*
	 * connect to the discard port (9) at the dest IP
	 */
	(void) dapl_os_memzero(&sock, sizeof (sock));
	if (af == AF_INET) {
		v4dest = (struct sockaddr_in *)&sock;
		v4dest->sin_family = AF_INET;
		v4dest->sin_addr.s_addr =
		    /* LINTED: E_BAD_PTR_CAST_ALIGN */
		    ((struct sockaddr_in *)addr)->sin_addr.s_addr;
		v4dest->sin_port = htons(9);

		retval = connect(fd, (struct sockaddr *)v4dest,
		    sizeof (struct sockaddr_in));
	} else {
		v6dest = (struct sockaddr_in6 *)&sock;
		v6dest->sin6_family = AF_INET6;
		/* LINTED: E_BAD_PTR_CAST_ALIGN */
		(void) dapl_os_memcpy(&v6dest->sin6_addr,
		    &((struct sockaddr_in6 *)addr)->sin6_addr,
		    sizeof (struct sockaddr_in6));
		v6dest->sin6_port = htons(9);

		retval = connect(fd, (struct sockaddr *)v6dest,
		    sizeof (struct sockaddr_in6));
	}

	/*
	 * we can return immediately if connect succeeds
	 */
	if (retval == 0) {
		(void) close(fd);
		return (0);
	}
	/*
	 * receiving a RST means that the arp/nd entry should
	 * already be resolved
	 */
	if (retval < 0 && errno == ECONNREFUSED) {
		errno = 0;
		(void) close(fd);
		return (0);
	}

	/*
	 * for all other cases, we poll on the fd
	 */
	pollfd.fd = fd;
	pollfd.events = POLLIN | POLLOUT;
	pollfd.revents = 0;

	if (timeout == DAT_TIMEOUT_INFINITE ||
	    timeout == 0) {
		/*
		 * -1 means infinite
		 */
		tmo = -1;
	} else {
		/*
		 * convert timeout from usecs to msecs
		 */
		tmo = timeout/1000;
	}
	retval = poll(&pollfd, 1, tmo);
	if (retval > 0) {
		int	so_error = 0, len = sizeof (so_error);

		retval = getsockopt(fd, SOL_SOCKET, SO_ERROR,
		    &so_error, &len);
		if (retval == 0) {
			/*
			 * we only return 0 if so_error == 0 or
			 * so_error == ECONNREFUSED. for all other
			 * cases retval is non-zero.
			 */
			if (so_error != 0 && so_error != ECONNREFUSED) {
				retval = -1;
				errno = so_error;
				dapl_dbg_log(DAPL_DBG_TYPE_ERR,
				    "ns_resolve_addr: ipv%d, so_error: %s\n",
				    ip_version, strerror(errno));
			}
		} else {
			/*
			 * if retval != 0, it must be -1. and errno must
			 * have been set by getsockopt.
			 */
			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
			    "ns_resolve_addr: ipv%d, getsockopt: %s\n",
			    ip_version, strerror(errno));
		}
	} else {
		if (retval == 0) {
			errno = ETIMEDOUT;
		}
		retval = -1;
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_resolve_addr: ipv%d, poll: %s\n",
		    ip_version, strerror(errno));
	}
	(void) close(fd);
	return (retval);
}
Esempio n. 9
0
DAT_RETURN
dapls_ns_lookup_v6(
	IN  DAPL_IA			*ia_ptr,
	IN  struct sockaddr_in6		*addr,
	IN  DAT_TIMEOUT			timeout,
	OUT ib_gid_t			*gid)
{
	struct lifreq		lifr;
	uchar_t			*mac;
	int			s, retries = 0;

	s = socket(AF_INET6, SOCK_DGRAM, 0);
	if (s < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_lookup_v6: socket: %s\n", strerror(errno));
		return (DAT_INTERNAL_ERROR);
	}
	if (dapls_ns_subnet_match_v6(s, ia_ptr, addr) != 0) {
		(void) close(s);
		return (DAT_INVALID_ADDRESS);
	}
	(void) dapl_os_memzero(&lifr, sizeof (lifr));
	(void) dapl_os_memcpy(&lifr.lifr_nd.lnr_addr, addr, sizeof (*addr));
	(void) dapl_os_strcpy(lifr.lifr_name, ia_ptr->hca_ptr->name);

again:;
	if (ioctl(s, SIOCLIFGETND, (caddr_t)&lifr) < 0)  {
		/*
		 * if SIOCLIFGETND failed, we force the ND
		 * cache to be filled by connecting to the
		 * destination IP address.
		 */
		if (retries < NS_MAX_RETRIES &&
		    dapls_ns_send_packet_v6(s, addr) == 0 &&
		    dapls_ns_resolve_addr(AF_INET6, (struct sockaddr *)addr,
		    timeout) == 0) {
			retries++;
			goto again;
		}
		dapl_dbg_log(DAPL_DBG_TYPE_ERR, "ns_lookup_v6: giving up\n");
		(void) close(s);
		return (DAT_ERROR(DAT_INVALID_ADDRESS,
		    DAT_INVALID_ADDRESS_UNREACHABLE));
	}
	if (lifr.lifr_nd.lnr_hdw_len == 0 && retries <= NS_MAX_RETRIES) {
		/*
		 * lnr_hdw_len == 0 means that the ND entry
		 * is still incomplete. we need to retry the ioctl.
		 */
		retries++;
		(void) sleep(1);
		goto again;
	}
	(void) close(s);

	mac = (uchar_t *)lifr.lifr_nd.lnr_hdw_addr;
	if (lifr.lifr_nd.lnr_hdw_len >= sizeof (ipoib_mac_t)) {
		ib_gid_t tmp_gid;
		/* LINTED: E_BAD_PTR_CAST_ALIGN */
		(void) dapl_os_memcpy(&tmp_gid,
		    &((ipoib_mac_t *)mac)->ipoib_gidpref, sizeof (ib_gid_t));
		/*
		 * gids from the ND table are in network order, convert
		 * the gids from network order to host byte order
		 */
		gid->gid_prefix = BETOH_64(tmp_gid.gid_prefix);
		gid->gid_guid = BETOH_64(tmp_gid.gid_guid);
	} else {
		int i, len;

		len = lifr.lifr_nd.lnr_hdw_len;
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_lookup_v6: failed, non IB address: "
		    "len = %d, addr = 0x", len);
		if (len > 0) {
			for (i = 0; i < len; i++) {
				dapl_dbg_log(DAPL_DBG_TYPE_ERR,
				    "%02x", (int)mac[i] & 0xff);
			}
		} else {
			dapl_dbg_log(DAPL_DBG_TYPE_ERR, "0");
		}
		dapl_dbg_log(DAPL_DBG_TYPE_ERR, "\n");
		return (DAT_INVALID_ADDRESS);
	}
	return (DAT_SUCCESS);
}
Esempio n. 10
0
DAT_RETURN
dapls_ns_lookup_v4(
	IN  DAPL_IA			*ia_ptr,
	IN  struct sockaddr_in		*addr,
	IN  DAT_TIMEOUT			timeout,
	OUT ib_gid_t			*gid)
{
	struct xarpreq		ar;
	struct sockaddr_in	*sin;
	uchar_t			*mac;
	int			s, retries = 0;

	(void) dapl_os_memzero(&ar, sizeof (ar));
	sin = (struct sockaddr_in *)&ar.xarp_pa;
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = addr->sin_addr.s_addr;
	ar.xarp_ha.sdl_family = AF_LINK;

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_lookup_v4: socket: %s\n", strerror(errno));
		return (DAT_INTERNAL_ERROR);
	}
	if (dapls_ns_subnet_match_v4(s, ia_ptr, addr) != 0) {
		(void) close(s);
		return (DAT_INVALID_ADDRESS);
	}
again:;
	if (ioctl(s, SIOCGXARP, (caddr_t)&ar) < 0) {
		/*
		 * if SIOCGXARP failed, we force the ARP
		 * cache to be filled by connecting to the
		 * destination IP address.
		 */
		if (retries <= NS_MAX_RETRIES &&
		    dapls_ns_resolve_addr(AF_INET, (struct sockaddr *)addr,
		    timeout) == 0) {
			retries++;
			goto again;
		}
		dapl_dbg_log(DAPL_DBG_TYPE_ERR, "ns_lookup_v4: giving up\n");
		(void) close(s);
		return (DAT_ERROR(DAT_INVALID_ADDRESS,
		    DAT_INVALID_ADDRESS_UNREACHABLE));
	}
	if ((ar.xarp_flags & ATF_COM) == 0 &&
	    ar.xarp_ha.sdl_type == IFT_IB && retries <= NS_MAX_RETRIES) {
		/*
		 * we get here if arp resolution is still incomplete
		 */
		retries++;
		(void) sleep(1);
		goto again;
	}
	(void) close(s);

	mac = (uchar_t *)LLADDR(&ar.xarp_ha);
	if (ar.xarp_flags & ATF_COM &&
	    ar.xarp_ha.sdl_type == IFT_IB &&
	    ar.xarp_ha.sdl_alen >= sizeof (ipoib_mac_t)) {
		ib_gid_t tmp_gid;

		/* LINTED: E_BAD_PTR_CAST_ALIGN */
		(void) dapl_os_memcpy(&tmp_gid,
		    &((ipoib_mac_t *)mac)->ipoib_gidpref, sizeof (ib_gid_t));
		/*
		 * gids from the ARP table are in network order, convert
		 * the gids from network order to host byte order
		 */
		gid->gid_prefix = BETOH_64(tmp_gid.gid_prefix);
		gid->gid_guid = BETOH_64(tmp_gid.gid_guid);
	} else {
		int i, len;

		len = ar.xarp_ha.sdl_alen;
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_lookup_v4: failed, non IB address: "
		    "len = %d, addr = 0x", len);
		if (len > 0) {
			for (i = 0; i < len; i++) {
				dapl_dbg_log(DAPL_DBG_TYPE_ERR,
				    "%02x", (int)mac[i] & 0xff);
			}
		} else {
			dapl_dbg_log(DAPL_DBG_TYPE_ERR, "0");
		}
		dapl_dbg_log(DAPL_DBG_TYPE_ERR, "\n");
		return (DAT_INVALID_ADDRESS);
	}
	return (DAT_SUCCESS);
}