Ejemplo n.º 1
0
/*
 * dapls_ib_reject_connection
 *
 * Perform necessary steps to reject a connection
 *
 * Input:
 *        cr_handle
 *
 * Output:
 *        none
 *
 * Returns:
 *        DAT_SUCCESS
 *        DAT_INSUFFICIENT_RESOURCES
 *        DAT_INVALID_PARAMETER
 *
 */
DAT_RETURN
dapls_ib_reject_connection(IN ib_cm_handle_t cm_handle,
                           IN int reject_reason, IN DAPL_SP *sp_ptr)
{
    dapl_cr_reject_t args;
    int retval;

    args.crr_reason = reject_reason;
    args.crr_bkl_cookie = (uint64_t)cm_handle;
    args.crr_sp_hkey = sp_ptr->cm_srvc_handle->sv_sp_hkey;

    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_reject: fd %d, sp_hkey %016llx, bkl_index 0x%llx\n",
                 sp_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                 args.crr_sp_hkey, args.crr_bkl_cookie);

    retval = ioctl(sp_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                   DAPL_CR_REJECT, &args);
    if (retval != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_reject: reject failed %s\n",
                     strerror(errno));
        return (dapls_convert_error(errno, retval));
    }
    return (DAT_SUCCESS);
}
Ejemplo n.º 2
0
/* ARGSUSED */
DAT_RETURN
dapls_ib_disconnect(IN DAPL_EP *ep_ptr,
                    IN DAT_CLOSE_FLAGS close_flags)
{
    dapl_ep_disconnect_t args;
    struct sockaddr *s;
    char addr_buf[64];
    int retval;

    if (ep_ptr->qp_handle == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_disconnect: qp_handle == NULL\n");
        return (DAT_INVALID_PARAMETER);
    }
    args.epd_hkey = ep_ptr->qp_handle->ep_hkey;

    retval = ioctl(ep_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                   DAPL_EP_DISCONNECT, &args);
    /* no reason for disconnect to fail so transition the state */
    ep_ptr->qp_state = IBT_STATE_ERROR;

    if (retval != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_disconnect: disconnect failed %s\n",
                     strerror(errno));
        return (dapls_convert_error(errno, retval));
    }
    s = (struct sockaddr *)ep_ptr->param.remote_ia_address_ptr;
    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_disconnect: disconnected from %s, conn_qual %016llu\n",
                 dapls_inet_ntop(s, addr_buf, 64), ep_ptr->param.remote_port_qual);
    return (DAT_SUCCESS);
}
Ejemplo n.º 3
0
/*
 * dapls_ib_handoff_connection
 *
 * handoff connection to a different qualifier
 *
 * Input:
 *        cr_ptr
 *        cr_handoff
 *
 * Output:
 *        none
 *
 * Returns:
 *        DAT_SUCCESS
 *        DAT_INSUFFICIENT_RESOURCES
 *        DAT_INVALID_PARAMETER
 *
 */
DAT_RETURN
dapls_ib_handoff_connection(IN DAPL_CR *cr_ptr, IN DAT_CONN_QUAL cr_handoff)
{
    dapl_cr_handoff_t args;
    int retval;

    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_handoff: fd %d, sp_hkey %016llx, "
                 "bkl_index 0x%llx conn_qual %llu\n",
                 cr_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                 cr_ptr->sp_ptr->cm_srvc_handle->sv_sp_hkey,
                 (uint64_t)cr_ptr->ib_cm_handle, cr_handoff);

    args.crh_bkl_cookie = (uint64_t)cr_ptr->ib_cm_handle;
    args.crh_sp_hkey = cr_ptr->sp_ptr->cm_srvc_handle->sv_sp_hkey;
    args.crh_conn_qual = cr_handoff;

    retval = ioctl(cr_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                   DAPL_CR_HANDOFF, &args);
    if (retval != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_handoff: failed %s\n", strerror(errno));
        return (dapls_convert_error(errno, retval));
    }
    return (DAT_SUCCESS);
}
Ejemplo n.º 4
0
/*
 * dapls_create_gid_map()
 *
 * Read /usr/local/etc/ibhosts to obtain host names and GIDs.
 * Create a table containing IP addresses and GIDs which can
 * be used for lookups.
 *
 * This implementation is a simple method providing name services
 * when more advanced mechanisms do not exist. The proper way
 * to obtain these mappings is to use a name service such as is
 * provided by IPoIB on InfiniBand.
 *
 * Input:
 *	device_name		Name of device as reported by the provider
 *
 * Output:
 * 	none
 *
 * Returns:
 * 	char * to string number
 */
DAT_RETURN
dapli_ns_create_gid_map(void)
{
	FILE			*f;
	ib_gid_t		gid;
	char			hostname[128];
	int			rc;
	struct addrinfo		*addr;
	struct sockaddr_in	*si;
	DAPL_GID_MAP		gmt;

	f = fopen(MAP_FILE, "r");
	if (f == NULL) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR, "ERROR: Must have file <%s> "
		    "for IP/GID mappings\n", MAP_FILE);
		return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
	}

	rc = fscanf(f, "%s " F64x " " F64x, hostname,
	    &gid.gid_prefix, &gid.gid_guid);
	while (rc != EOF) {
		rc = dapls_osd_getaddrinfo(hostname, &addr);

		if (rc != 0) {
			/*
			 * hostname not registered in DNS,
			 * provide a dummy value
			 */
			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
			    "WARNING: <%s> not registered in "
			    "DNS, using dummy IP value\n", hostname);
			gmt.ip_address = 0x01020304;
		} else {
			/*
			 * Load into the ip/gid mapping table
			 */
			si = (struct sockaddr_in *)addr->ai_addr;
			if (AF_INET == addr->ai_addr->sa_family) {
				gmt.ip_address = si->sin_addr.s_addr;
			} else {
				dapl_dbg_log(DAPL_DBG_TYPE_ERR,
				    "WARNING: <%s> Address family "
				    "not supported, using dummy "
				    "IP value\n", hostname);
				gmt.ip_address = 0x01020304;
			}
			dapls_osd_freeaddrinfo(addr);
		}
		gmt.gid.gid_prefix = gid.gid_prefix;
		gmt.gid.gid_guid = gid.gid_guid;

		dapli_ns_add_address(&gmt);
		rc = fscanf(f, "%s " F64x " " F64x, hostname,
		    &gid.gid_prefix, &gid.gid_guid);
	}
	(void) fclose(f);
	return (DAT_SUCCESS);
}
Ejemplo n.º 5
0
/*
 * dapl_ib_setup_conn_listener
 *
 * Have the CM set up a connection listener.
 *
 * Input:
 *        ibm_hca_handle           HCA handle
 *        qp_handle                QP handle
 *
 * Output:
 *        none
 *
 * Returns:
 *        DAT_SUCCESS
 *        DAT_INSUFFICIENT_RESOURCES
 *        DAT_INVALID_PARAMETER
 *
 */
DAT_RETURN
dapls_ib_setup_conn_listener(IN DAPL_IA *ia_ptr,
                             IN DAT_UINT64 ServiceID, IN DAPL_SP *sp_ptr)
{
    ib_hca_handle_t hca_hdl = ia_ptr->hca_ptr->ib_hca_handle;
    struct dapls_ib_cm_srvc_handle *srvc_hdl;
    dapl_service_register_t args;
    struct sockaddr *s;
    char addr_buf[64];
    DAPL_EVD *evd_p = (DAPL_EVD *)sp_ptr->evd_handle;
    int retval;

    if (hca_hdl == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "setup_conn_listener: hca_handle == NULL\n");
        return (DAT_INVALID_PARAMETER);
    }
    if (evd_p == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "setup_conn_listener: evd_p == NULL\n");
        return (DAT_INVALID_PARAMETER);
    }
    srvc_hdl = (struct dapls_ib_cm_srvc_handle *)
               dapl_os_alloc(sizeof (*srvc_hdl));
    if (srvc_hdl == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "setup_conn_listener: srvc_handle == NULL\n");
        return (DAT_INSUFFICIENT_RESOURCES);
    }

    args.sr_sid = ServiceID;
    args.sr_evd_hkey = evd_p->ib_cq_handle->evd_hkey;
    args.sr_sp_cookie = (uintptr_t)sp_ptr;

    retval = ioctl(hca_hdl->ia_fd, DAPL_SERVICE_REGISTER, &args);
    if (retval != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "setup_conn_listener: register failed %s\n",
                     strerror(errno));
        dapl_os_free(srvc_hdl, sizeof (*srvc_hdl));
        return (dapls_convert_error(errno, retval));
    }
    srvc_hdl->sv_sp_hkey = args.sr_sp_hkey;
    sp_ptr->cm_srvc_handle = srvc_hdl;
    sp_ptr->conn_qual = args.sr_retsid;

    s = (struct sockaddr *)&ia_ptr->hca_ptr->hca_address;
    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "setup_conn_listener: listening on ia_address %s, "
                 "conn_qual %016llu\n\n", dapls_inet_ntop(s, addr_buf, 64),
                 sp_ptr->conn_qual);
    return (DAT_SUCCESS);
}
Ejemplo n.º 6
0
/*
 * dapl_ep_recv_query
 *
 * uDAPL Version 1.2, 6.6.11
 *
 * Destroy an instance of the Endpoint
 *
 * Input:
 *	ep_handle
 *
 * Output:
 *	none
 *
 * Returns:
 *	DAT_SUCCESS
 *	DAT_INVALID_PARAMETER
 *	DAT_INVALID_HANDLE
 *	DAT_MODEL_NOT_SUPPORTED
 */
DAT_RETURN DAT_API
dapl_ep_recv_query(IN DAT_EP_HANDLE ep_handle,
		   OUT DAT_COUNT * nbufs_allocate,
		   OUT DAT_COUNT * bufs_alloc_span)
{
	DAPL_EP *ep_ptr;
	DAT_RETURN dat_status;

	dat_status = DAT_SUCCESS;

	dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_ep_recv_query (%p, %p, %p)\n",
		     ep_handle, nbufs_allocate, bufs_alloc_span);

	ep_ptr = (DAPL_EP *) ep_handle;

	/*
	 * Verify parameter & state
	 */
	if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) {
		dat_status =
		    DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);
		goto bail;
	}

	dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);

      bail:
	return dat_status;

}
Ejemplo n.º 7
0
DAT_RETURN
dapl_cr_query(
	IN DAT_CR_HANDLE cr_handle,
	IN DAT_CR_PARAM_MASK cr_param_mask,
	OUT DAT_CR_PARAM *cr_param)
{
	DAPL_CR	*cr_ptr;
	DAT_RETURN dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_cr_query (%p, %x, %p)\n",
	    cr_handle, cr_param_mask, cr_param);

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

	if (NULL == cr_param) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER,
		    DAT_INVALID_ARG3);
		goto bail;
	}

	cr_ptr = (DAPL_CR *) cr_handle;

	/* since the arguments are easily accessible, ignore the mask */
	(void) dapl_os_memcpy(cr_param, &cr_ptr->param, sizeof (DAT_CR_PARAM));

bail:
	return (dat_status);
}
Ejemplo n.º 8
0
static int
dapls_ns_subnet_match_v6(int s, DAPL_IA *ia_ptr, struct sockaddr_in6 *addr)
{
	struct lifreq		lifreq;
	struct sockaddr_in6	netmask_sock;
	uchar_t			*netmask, *local_addr, *dest_addr;
	int			i, retval;

	(void) dapl_os_strcpy(lifreq.lifr_name, ia_ptr->hca_ptr->name);

	retval = ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifreq);
	if (retval < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_subnet_match_v6: cannot get netmask: %s\n",
		    strerror(errno));
		return (-1);
	}
	(void) dapl_os_memcpy(&netmask_sock, &lifreq.lifr_addr,
	    sizeof (netmask_sock));

	/*
	 * we need to get the interface address here because the
	 * address in ia_ptr->hca_ptr->hca_address might not
	 * necessarily be an IPv6 address.
	 */
	retval = ioctl(s, SIOCGLIFADDR, (caddr_t)&lifreq);
	if (retval < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_subnet_match_v6: cannot get local addr: %s\n",
		    strerror(errno));
		return (-1);
	}
	netmask = (uchar_t *)&netmask_sock.sin6_addr;
	local_addr = (uchar_t *)&((struct sockaddr_in6 *)&lifreq.lifr_addr)->
	    sin6_addr;
	dest_addr = (uchar_t *)&addr->sin6_addr;

	for (i = 0; i < sizeof (addr->sin6_addr); i++) {
		if (((local_addr[i] ^ dest_addr[i]) & netmask[i]) != 0) {
			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
			    "ns_subnet_match_v6: subnets do not match\n");
			return (-1);
		}
	}
	return (0);
}
Ejemplo n.º 9
0
static int
dapls_ns_subnet_match_v4(int s, DAPL_IA *ia_ptr, struct sockaddr_in *addr)
{
	struct lifreq		lifreq;
	int			retval;
	uint32_t		netmask, netaddr, netaddr_dest;

	(void) dapl_os_strcpy(lifreq.lifr_name, ia_ptr->hca_ptr->name);

	retval = ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifreq);
	if (retval < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_subnet_match_v4: cannot get netmask: %s\n",
		    strerror(errno));
		return (-1);
	}
	netmask = ((struct sockaddr_in *)&lifreq.lifr_addr)->
	    sin_addr.s_addr;

	/*
	 * we need to get the interface address here because the
	 * address in ia_ptr->hca_ptr->hca_address might not
	 * necessarily be an IPv4 address.
	 */
	retval = ioctl(s, SIOCGLIFADDR, (caddr_t)&lifreq);
	if (retval < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_subnet_match_v4: cannot get local addr: %s\n",
		    strerror(errno));
		return (-1);
	}
	netaddr = ((struct sockaddr_in *)&lifreq.lifr_addr)->
	    sin_addr.s_addr & netmask;
	netaddr_dest = addr->sin_addr.s_addr & netmask;

	if (netaddr != netaddr_dest) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_subnet_match_v4: netaddrs don't match: "
		    "local %x, remote %x\n", netaddr, netaddr_dest);
		return (-1);
	}
	return (0);
}
Ejemplo n.º 10
0
/*
 * dapl_ep_query
 *
 * DAPL Requirements Version xxx, 6.5.5
 *
 * Provide the consumer parameters, including attributes and status of
 * the Endpoint.
 *
 * Input:
 *	ep_handle
 *	ep_param_mask
 *
 * Output:
 *	ep_param
 *
 * Returns:
 *	DAT_SUCCESS
 *	DAT_INVALID_PARAMETER
 */
DAT_RETURN DAT_API
dapl_ep_query(IN DAT_EP_HANDLE ep_handle,
	      IN DAT_EP_PARAM_MASK ep_param_mask, OUT DAT_EP_PARAM * ep_param)
{
	DAPL_EP *ep_ptr;
	DAT_RETURN dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_API,
		     "dapl_ep_query (%p, %x, %p)\n",
		     ep_handle, ep_param_mask, ep_param);

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

	/*
	 * Verify parameter & state
	 */
	if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) {
		dat_status =
		    DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);
		goto bail;
	}

	if (ep_param == NULL) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
		goto bail;
	}

	/*
	 * Fill in according to user request
	 *
	 * N.B. Just slam all values into the user structure, there
	 *      is nothing to be gained by checking for each bit.
	 */
	if (ep_param_mask & DAT_EP_FIELD_ALL) {
		/* only attempt to get remote IA address if consumer requested it */
		if (ep_param_mask & DAT_EP_FIELD_REMOTE_IA_ADDRESS_PTR) {
			if (ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED) {
				/* obtain the remote IP address */
				dat_status =
				    dapls_ib_cm_remote_addr((DAT_HANDLE)
							    ep_handle,
							    &ep_ptr->
							    remote_ia_address);
			}
			ep_ptr->param.remote_ia_address_ptr =
			    (DAT_IA_ADDRESS_PTR) & ep_ptr->remote_ia_address;
		}
		*ep_param = ep_ptr->param;
		dats_get_ia_handle(ep_ptr->param.ia_handle, &ep_param->ia_handle);
	}

      bail:
	return dat_status;
}
Ejemplo n.º 11
0
static int
dapls_ns_send_packet_v6(int s, struct sockaddr_in6 *addr)
{
	if (sendto(s, NULL, 0, MSG_DONTROUTE, (struct sockaddr *)addr,
	    sizeof (*addr)) < 0) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "ns_send_packet_v6: failed: %s\n", strerror(errno));
		return (-1);
	}
	return (0);
}
Ejemplo n.º 12
0
/*
 * dapls_ib_accept_connection
 *
 * Perform necessary steps to accept a connection
 *
 * Input:
 *        cr_handle
 *        ep_handle
 *        private_data_size
 *        private_data
 *
 * Output:
 *        none
 *
 * Returns:
 *        DAT_SUCCESS
 *        DAT_INSUFFICIENT_RESOURCES
 *        DAT_INVALID_PARAMETER
 *
 */
DAT_RETURN
dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,
                           IN DAT_EP_HANDLE ep_handle, IN DAPL_PRIVATE *prd_ptr)
{
    DAPL_EP		*ep_p = (DAPL_EP *)ep_handle;
    DAPL_CR		*cr_p = (DAPL_CR *)cr_handle;
    dapl_cr_accept_t	args;
    int			retval;

    /* check if ep is valid */
    if (ep_p->qp_handle == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_accept: qp_handle == NULL\n");
        return (DAT_INVALID_PARAMETER);
    }

    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_accept: fd %d, sp_hkey %016llx, "
                 "bkl_index 0x%llx, ep_hkey %016llx\n",
                 cr_p->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                 cr_p->sp_ptr->cm_srvc_handle->sv_sp_hkey,
                 (uint64_t)cr_p->ib_cm_handle, ep_p->qp_handle->ep_hkey);

    args.cra_bkl_cookie = (uint64_t)cr_p->ib_cm_handle;
    args.cra_sp_hkey = cr_p->sp_ptr->cm_srvc_handle->sv_sp_hkey;
    args.cra_ep_hkey = ep_p->qp_handle->ep_hkey;

    args.cra_priv_sz = IB_MAX_REP_PDATA_SIZE;
    bcopy(prd_ptr, args.cra_priv, IB_MAX_REP_PDATA_SIZE);

    retval = ioctl(cr_p->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
                   DAPL_CR_ACCEPT, &args);
    if (retval != 0) {
        ep_p->qp_state = IBT_STATE_ERROR;
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_accept: accept failed %s\n",
                     strerror(errno));
        return (dapls_convert_error(errno, retval));
    }
    return (DAT_SUCCESS);
}
Ejemplo n.º 13
0
/*
 * dapli_stup_dummy_addr
 *
 * Set up a dummy local address for the HCA. Things are not going
 * to work too well if this happens.
 * We call this routine if:
 *  - remote host adapter name is not in DNS
 *  - IPoIB implementation is not correctly set up
 *  - Similar nonsense.
 *
 * Input:
 *      hca_ptr
 *	rhost_name		Name of remote adapter
 *
 * Output:
 * 	none
 *
 * Returns:
 * 	none
 */
void dapli_setup_dummy_addr(IN DAPL_HCA * hca_ptr, IN char *rhost_name)
{
	struct sockaddr_in *si;

	/* Not registered in DNS, provide a dummy value */
	dapl_dbg_log(DAPL_DBG_TYPE_WARN,
		     "WARNING: <%s> not registered in DNS, using dummy IP value\n",
		     rhost_name);
	si = (struct sockaddr_in *)&hca_ptr->hca_address;
	hca_ptr->hca_address.sin6_family = AF_INET;
	si->sin_addr.s_addr = 0x01020304;
}
Ejemplo n.º 14
0
/*
 * dapl_ib_remove_conn_listener
 *
 * Have the CM remove a connection listener.
 *
 * Input:
 *      ia_handle               IA handle
 *      ServiceID               IB Channel Service ID
 *
 * Output:
 *      none
 *
 * Returns:
 *      DAT_SUCCESS
 *      DAT_INVALID_PARAMETER
 *
 */
DAT_RETURN
dapls_ib_remove_conn_listener(IN DAPL_IA *ia_ptr, IN DAPL_SP *sp_ptr)
{
    ib_hca_handle_t hca_hdl = ia_ptr->hca_ptr->ib_hca_handle;
    struct dapls_ib_cm_srvc_handle *srvc_hdl;
    dapl_service_deregister_t args;
    struct sockaddr *s;
    char addr_buf[64];
    int retval;

    if (hca_hdl == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "remove_conn_listener: hca_handle == NULL\n");
        return (DAT_INVALID_PARAMETER);
    }
    srvc_hdl = (struct dapls_ib_cm_srvc_handle *)sp_ptr->
               cm_srvc_handle;

    args.sdr_sp_hkey = srvc_hdl->sv_sp_hkey;
    retval = ioctl(hca_hdl->ia_fd, DAPL_SERVICE_DEREGISTER, &args);
    if (retval != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "remove_conn_listener: deregister failed %s\n",
                     strerror(errno));
        return (dapls_convert_error(errno, retval));
    }
    dapl_os_free(srvc_hdl, sizeof (*srvc_hdl));
    sp_ptr->cm_srvc_handle = NULL;

    s = (struct sockaddr *)&ia_ptr->hca_ptr->hca_address;
    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "remove_conn_listener: successful, ia_address %s, "
                 "conn_qual %016llu\n\n", dapls_inet_ntop(s, addr_buf, 64),
                 sp_ptr->conn_qual);
    return (DAT_SUCCESS);
}
Ejemplo n.º 15
0
/*
 * dapl_cno_free
 *
 * DAPL Requirements Version xxx, 6.3.2.2
 *
 * Destroy a consumer notification object instance
 *
 * Input:
 *	cno_handle
 *
 * Output:
 *	none
 *
 * Returns:
 *	DAT_SUCCESS
 *	DAT_INVALID_HANDLE
 *	DAT_INVALID_STATE
 */
DAT_RETURN
dapl_cno_free(
	IN	DAT_CNO_HANDLE		cno_handle)	/* cno_handle */
{
	DAPL_CNO    *cno_ptr;
	DAT_RETURN  dat_status;

	dat_status = DAT_SUCCESS;
	cno_ptr = (DAPL_CNO *)cno_handle;

	if (DAPL_BAD_HANDLE(cno_handle, DAPL_MAGIC_CNO)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_CNO);
		goto bail;
	}

	if (cno_ptr->cno_ref_count != 0 || cno_ptr->cno_waiters != 0) {
		dat_status = DAT_ERROR(DAT_INVALID_STATE,
		    DAT_INVALID_STATE_CNO_IN_USE);
		goto bail;
	}

	dapl_os_lock(&cno_ptr->header.lock);
	if (!dapl_llist_is_empty(&cno_ptr->evd_list_head)) {
		dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
		    "cno_free: evd list not empty!\n");
		dapl_os_unlock(&cno_ptr->header.lock);
		dat_status =  DAT_ERROR(DAT_INVALID_STATE,
		    DAT_INVALID_STATE_CNO_IN_USE);
		goto bail;
	}
	dapl_os_unlock(&cno_ptr->header.lock);

	dat_status = dapls_ib_cno_free(cno_ptr);
	if (dat_status != DAT_SUCCESS) {
		goto bail;
	}

	dapl_ia_unlink_cno(cno_ptr->header.owner_ia, cno_ptr);
	dapl_cno_dealloc(cno_ptr);

bail:
	return (dat_status);
}
Ejemplo n.º 16
0
/*
 * dapl_sp_remove_cr
 *
 * Remove the CR from the PSP. Done prior to freeing the CR resource.
 *
 * Input:
 *	sp_ptr
 *	cr_ptr
 *
 * Output:
 * 	none
 *
 * Returns:
 * 	void
 *
 */
void
dapl_sp_remove_cr(
	IN  DAPL_SP *sp_ptr,
	IN  DAPL_CR *cr_ptr)
{
	dapl_os_lock(&sp_ptr->header.lock);

	if (dapl_llist_is_empty(&sp_ptr->cr_list_head)) {
		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
		    "***dapl_sp_remove_cr: removing from empty queue! sp %p\n",
		    sp_ptr);
		dapl_os_unlock(&sp_ptr->header.lock);
		return;
	}

	(void) dapl_llist_remove_entry(&sp_ptr->cr_list_head,
	    &cr_ptr->header.ia_list_entry);
	sp_ptr->cr_list_count--;

	dapl_os_unlock(&sp_ptr->header.lock);
}
Ejemplo n.º 17
0
/*
 * dapl_pz_query
 *
 * DAPL Requirements Version xxx, 6.6.2.1
 *
 * Return the ia associated with the protection zone pz
 *
 * Input:
 * 	pz_handle
 *      pz_param_mask
 *
 * Output:
 * 	pz_param
 *
 * Returns:
 * 	DAT_SUCCESS
 *      DAT_INVALID_HANDLE
 * 	DAT_INVALID_PARAMETER
 */
DAT_RETURN
dapl_pz_query(
	IN	DAT_PZ_HANDLE		pz_handle,
	IN	DAT_PZ_PARAM_MASK	pz_param_mask,
	OUT	DAT_PZ_PARAM		*pz_param)
{
	DAPL_PZ		*pz;
	DAT_RETURN	dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_API,
	    "dapl_pz_query (%p, %x, %p)\n",
	    pz_handle,
	    pz_param_mask,
	    pz_param);

	dat_status = DAT_SUCCESS;

	if (DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_PZ);
		goto bail;
	}
	if (NULL == pz_param) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
		goto bail;
	}
	if (pz_param_mask & ~DAT_PZ_FIELD_ALL) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
		goto bail;
	}

	pz = (DAPL_PZ *) pz_handle;

	/* Since the DAT_PZ_ARGS values are easily accessible, */
	/* don't bother checking the DAT_PZ_ARGS_MASK value    */
	pz_param->ia_handle = (DAT_IA_HANDLE) pz->header.owner_ia;

bail:
	return (dat_status);
}
Ejemplo n.º 18
0
/*
 * dapl_srq_query
 *
 * DAPL Requirements Version 1.2, 6.5.6
 *
 * Return SRQ parameters to the consumer
 *
 * Input:
 * 	srq_handle
 *      srq_param_mask
 *
 * Output:
 * 	srq_param
 *
 * Returns:
 * 	DAT_SUCCESS
 *      DAT_INVALID_HANDLE
 * 	DAT_INVALID_PARAMETER
 */
DAT_RETURN DAT_API
dapl_srq_query(IN DAT_SRQ_HANDLE srq_handle,
	       IN DAT_SRQ_PARAM_MASK srq_param_mask,
	       OUT DAT_SRQ_PARAM * srq_param)
{
	DAPL_SRQ *srq_ptr;
	DAT_RETURN dat_status;

	dat_status = DAT_SUCCESS;

	dapl_dbg_log(DAPL_DBG_TYPE_API,
		     "dapl_srq_query (%p, %x, %p)\n",
		     srq_handle, srq_param_mask, srq_param);

	if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) {
		dat_status =
		    DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_SRQ);
		goto bail;
	}
	if (srq_param == NULL) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
		goto bail;
	}

	srq_ptr = (DAPL_SRQ *) srq_handle;

	/*
	 * XXX Need to calculate available_dto_count and outstanding_dto_count
	 */
	srq_ptr->param.available_dto_count = DAT_VALUE_UNKNOWN;
	srq_ptr->param.outstanding_dto_count = DAT_VALUE_UNKNOWN;

	*srq_param = srq_ptr->param;
	dats_get_ia_handle(srq_ptr->header.owner_ia, &srq_param->ia_handle);

      bail:
	return dat_status;
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
DAT_RETURN DAT_API dapl_evd_create(IN DAT_IA_HANDLE ia_handle,
                                   IN DAT_COUNT evd_min_qlen,
                                   IN DAT_CNO_HANDLE cno_handle,
                                   IN DAT_EVD_FLAGS evd_flags,
                                   OUT DAT_EVD_HANDLE * evd_handle)
{
    DAPL_IA *ia_ptr;
    DAPL_EVD *evd_ptr;
    DAPL_CNO *cno_ptr;
    DAT_RETURN dat_status;
    DAT_PROVIDER_ATTR provider_attr;
    int i;
    int j;
    int flag_mask[6];

    dapl_dbg_log(DAPL_DBG_TYPE_API,
                 "dapl_evd_create (%p, %d, %p, 0x%x, %p)\n",
                 ia_handle,
                 evd_min_qlen, cno_handle, evd_flags, evd_handle);

    ia_ptr = (DAPL_IA *) ia_handle;
    cno_ptr = (DAPL_CNO *) cno_handle;
    evd_ptr = NULL;
    *evd_handle = NULL;
    dat_status = DAT_SUCCESS;

    if (DAPL_BAD_HANDLE(ia_handle, DAPL_MAGIC_IA)) {
        dat_status =
            DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA);
        goto bail;
    }

    DAPL_CNTR(ia_ptr, DCNT_IA_EVD_CREATE);

    if (evd_min_qlen <= 0) {
        dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
        goto bail;
    }
    if (evd_min_qlen > ia_ptr->hca_ptr->ia_attr.max_evd_qlen) {
        dat_status =
            DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_TEVD);
        goto bail;
    }

    if (cno_handle != DAT_HANDLE_NULL
            && DAPL_BAD_HANDLE(cno_handle, DAPL_MAGIC_CNO)) {
        dat_status =
            DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CNO);
        goto bail;
    }

    /*
     * Check the merging attributes to ensure the combination of
     * flags requested is supported.
     */
    dapl_ia_query(ia_handle, NULL,
                  0, NULL, DAT_PROVIDER_FIELD_ALL, &provider_attr);

    /* Set up an array of flags to compare against; the EVD bits are
     * a sparse array that need to be mapped to the merging flags
     */
    flag_mask[0] = DAT_EVD_SOFTWARE_FLAG;
    flag_mask[1] = DAT_EVD_CR_FLAG;
    flag_mask[2] = DAT_EVD_DTO_FLAG;
    flag_mask[3] = DAT_EVD_CONNECTION_FLAG;
    flag_mask[4] = DAT_EVD_RMR_BIND_FLAG;
    flag_mask[5] = DAT_EVD_ASYNC_FLAG;

    for (i = 0; i < 6; i++) {
        if (flag_mask[i] & evd_flags) {
            for (j = 0; j < 6; j++) {
                if (flag_mask[j] & evd_flags) {
                    if (provider_attr.
                            evd_stream_merging_supported[i][j]
                            == DAT_FALSE) {
                        dat_status =
                            DAT_ERROR
                            (DAT_INVALID_PARAMETER,
                             DAT_INVALID_ARG4);
                        goto bail;
                    }
                }
            }	/* end for j */
        }
    }			/* end for i */

    dat_status = dapls_evd_internal_create(ia_ptr,
                                           cno_ptr,
                                           evd_min_qlen,
                                           evd_flags, &evd_ptr);
    if (dat_status != DAT_SUCCESS) {
        goto bail;
    }

    evd_ptr->evd_state = DAPL_EVD_STATE_OPEN;

    *evd_handle = (DAT_EVD_HANDLE) evd_ptr;

bail:
    if (dat_status != DAT_SUCCESS) {
        if (evd_ptr) {
            dapl_evd_free(evd_ptr);
        }
    }

    dapl_dbg_log(DAPL_DBG_TYPE_RTN,
                 "dapl_evd_create () returns 0x%x\n", dat_status);

    return dat_status;
}
Ejemplo n.º 21
0
DAT_RETURN DAT_API dapl_evd_resize(IN DAT_EVD_HANDLE evd_handle,
				   IN DAT_COUNT evd_qlen)
{
	DAPL_IA *ia_ptr;
	DAPL_EVD *evd_ptr;
	DAT_COUNT pend_cnt;
	DAT_RETURN dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_evd_resize (%p, %d)\n",
		     evd_handle, evd_qlen);

	if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE1);
		goto bail;
	}

	evd_ptr = (DAPL_EVD *) evd_handle;
	ia_ptr = evd_ptr->header.owner_ia;

	if (evd_qlen == evd_ptr->qlen) {
		dat_status = DAT_SUCCESS;
		goto bail;
	}

	if (evd_qlen > ia_ptr->hca_ptr->ia_attr.max_evd_qlen) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
		goto bail;
	}

	dapl_os_lock(&evd_ptr->header.lock);

	/* Don't try to resize if we are actively waiting */
	if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED) {
		dapl_os_unlock(&evd_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);
		goto bail;
	}

	pend_cnt = dapls_rbuf_count(&evd_ptr->pending_event_queue);
	if (pend_cnt > evd_qlen) {
		dapl_os_unlock(&evd_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);
		goto bail;
	}

	if (evd_ptr->ib_cq_handle) {

		dat_status = dapls_ib_cq_resize(evd_ptr->header.owner_ia,
						evd_ptr, &evd_qlen);
		if (dat_status != DAT_SUCCESS) {
			dapl_os_unlock(&evd_ptr->header.lock);
			goto bail;
		}
	}

	dat_status = dapls_evd_event_realloc(evd_ptr, evd_qlen);
	if (dat_status != DAT_SUCCESS) {
		dapl_os_unlock(&evd_ptr->header.lock);
		goto bail;
	}

	dapl_os_unlock(&evd_ptr->header.lock);

      bail:
	return dat_status;
}
void
dapl_evd_connection_callback(
    IN    ib_cm_handle_t	ib_cm_handle,
    IN    const ib_cm_events_t  ib_cm_event,
    IN	  const void 		*private_data_ptr,
    IN    const void		*context)
{
	DAPL_EP		*ep_ptr;
	DAPL_EVD	*evd_ptr;
	DAPL_PRIVATE	*prd_ptr;
	DAT_EVENT_NUMBER event_type;

	dapl_dbg_log(
	    DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
	    "--> dapl_evd_connection_callback: ctxt: %p event: %x"
	    " cm_handle %p\n",
	    context,
	    ib_cm_event,
	    ib_cm_handle);

	/*
	 * Determine the type of handle passed back to us in the context
	 * and sort out key parameters.
	 */
	dapl_os_assert(((DAPL_HEADER *)context)->magic == DAPL_MAGIC_EP ||
	    ((DAPL_HEADER *)context)->magic == DAPL_MAGIC_EP_EXIT);
	/*
	 * Active side of the connection, context is an EP and
	 * PSP is irrelevant.
	 */
	ep_ptr  = (DAPL_EP *)context;
	evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;

	prd_ptr = (DAPL_PRIVATE *)private_data_ptr;

	switch (ib_cm_event) {
	case IB_CME_CONNECTED:
	{
		/*
		 * If we don't have an EP at this point we are very screwed
		 * up
		 */
		DAT_RETURN dat_status;

		if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) {
			/*
			 * If someone pulled the plug on the connection, just
			 * exit
			 */
			break;
		}
		dapls_ib_connected(ep_ptr);
		ep_ptr->param.ep_state	= DAT_EP_STATE_CONNECTED;
		ep_ptr->cm_handle	= ib_cm_handle;
		/* copy in the private data */
		(void) dapl_os_memcpy(ep_ptr->private_data,
		    prd_ptr->private_data,
		    IB_MAX_REQ_PDATA_SIZE);

		dat_status = dapls_evd_post_connection_event(
		    evd_ptr,
		    DAT_CONNECTION_EVENT_ESTABLISHED,
		    (DAT_HANDLE) ep_ptr,
		    IB_MAX_REQ_PDATA_SIZE,
		    ep_ptr->private_data);

		if (dat_status != DAT_SUCCESS) {
			(void) dapls_ib_disconnect(ep_ptr,
			    DAT_CLOSE_ABRUPT_FLAG);
			ep_ptr->param.ep_state =
			    DAT_EP_STATE_DISCONNECT_PENDING;
		}

		/*
		 * If we received any premature DTO completions and
		 * post them to the recv evd now.
		 * there is a race here - if events arrive after we change
		 * the ep state to connected and before we process premature
		 * events
		 */
		dapls_evd_post_premature_events(ep_ptr);

		break;
	}
	case IB_CME_DISCONNECTED:
	case IB_CME_DISCONNECTED_ON_LINK_DOWN:
	{
		/*
		 * EP is now fully disconnected; initiate any post processing
		 * to reset the underlying QP and get the EP ready for
		 * another connection
		 */
		if (ep_ptr->param.ep_state  == DAT_EP_STATE_DISCONNECTED) {
			/* DTO error caused this */
			event_type = DAT_CONNECTION_EVENT_BROKEN;
		} else {
			ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
			dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE,
			    ib_cm_event);
			event_type = DAT_CONNECTION_EVENT_DISCONNECTED;
		}

		/* If the EP has been freed, the evd_ptr will be NULL */
		if (evd_ptr != NULL) {
			(void) dapls_evd_post_connection_event(
			    evd_ptr, event_type, (DAT_HANDLE) ep_ptr, 0, 0);
		}

		/*
		 * If the user has done an ep_free of the EP, we have been
		 * waiting for the disconnect event; just clean it up now.
		 */
		if (ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT) {
			(void) dapl_ep_free(ep_ptr);
		}
		break;
	}
	case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:
	{
		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
		(void) dapls_evd_post_connection_event(
		    evd_ptr,
		    DAT_CONNECTION_EVENT_PEER_REJECTED,
		    (DAT_HANDLE) ep_ptr,
		    0,
		    0);
		break;
	}
	case IB_CME_DESTINATION_UNREACHABLE:
	{
		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
		(void) dapls_evd_post_connection_event(
		    evd_ptr,
		    DAT_CONNECTION_EVENT_UNREACHABLE,
		    (DAT_HANDLE) ep_ptr,
		    0,
		    0);
		break;
	}
	case IB_CME_DESTINATION_REJECT:
	case IB_CME_TOO_MANY_CONNECTION_REQUESTS:
	case IB_CME_LOCAL_FAILURE:
	{
		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
		(void) dapls_evd_post_connection_event(
		    evd_ptr,
		    DAT_CONNECTION_EVENT_NON_PEER_REJECTED,
		    (DAT_HANDLE) ep_ptr,
		    0,
		    0);
		break;
	}
	case IB_CME_TIMED_OUT:
	{
		ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;
		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
		(void) dapls_evd_post_connection_event(
		    evd_ptr,
		    DAT_CONNECTION_EVENT_TIMED_OUT,
		    (DAT_HANDLE) ep_ptr,
		    0,
		    0);
		break;
	}
	case IB_CME_CONNECTION_REQUEST_PENDING:
	case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:
	default:
	{
		dapl_os_assert(0);		/* shouldn't happen */
		break;
	}
	}

	dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
	    "dapl_evd_connection_callback () returns\n");

}
Ejemplo n.º 23
0
/*
 * dapl_psp_create
 *
 * uDAPL: User Direct Access Program Library Version 1.1, 6.4.1.1
 *
 * Create a persistent Public Service Point that can recieve multiple
 * requests for connections and generate multiple connection request
 * instances that wil be delivered to the specified Event Dispatcher
 * in a notification event.
 *
 * Input:
 * 	ia_handle
 * 	conn_qual
 * 	evd_handle
 * 	psp_flags
 *
 * Output:
 * 	psp_handle
 *
 * Returns:
 * 	DAT_SUCCESS
 * 	DAT_INSUFFICIENT_RESOURCES
 * 	DAT_INVALID_PARAMETER
 * 	DAT_CONN_QUAL_IN_USE
 * 	DAT_MODEL_NOT_SUPPORTED
 */
DAT_RETURN
dapl_psp_create(
	IN DAT_IA_HANDLE	   ia_handle,
	IN DAT_CONN_QUAL	   conn_qual,
	IN DAT_EVD_HANDLE	   evd_handle,
	IN DAT_PSP_FLAGS	   psp_flags,
	OUT DAT_PSP_HANDLE	   *psp_handle)
{
	DAPL_IA	*ia_ptr;
	DAPL_SP	*sp_ptr;
	DAPL_EVD *evd_ptr;
	DAT_BOOLEAN sp_found;
	DAT_RETURN dat_status;

	ia_ptr = (DAPL_IA *)ia_handle;
	dat_status = DAT_SUCCESS;

	if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_IA);
		goto bail;
	}

	if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EVD_CR);
		goto bail;
	}

	if (psp_handle == NULL) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5);
		goto bail;
	}

	/* check for invalid psp flags */
	if ((psp_flags != DAT_PSP_CONSUMER_FLAG) &&
	    (psp_flags != DAT_PSP_PROVIDER_FLAG)) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
		goto bail;
	}

	evd_ptr = (DAPL_EVD *)evd_handle;
	if (!(evd_ptr->evd_flags & DAT_EVD_CR_FLAG)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EVD_CR);
		goto bail;
	}

	/*
	 * check for connection qualifier eq 0
	 * in IB this is called Null Service ID, use of it in CM is invalid.
	 * in tcp/udp, port number 0 is reserved.
	 */
	if (!conn_qual) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
		goto bail;
	}

	/*
	 * See if we have a quiescent listener to use for this PSP, else
	 * create one and set it listening
	 */
	sp_ptr = dapls_ia_sp_search(ia_ptr, conn_qual, DAT_TRUE);
	sp_found = DAT_TRUE;
	if (sp_ptr == NULL) {
		/* Allocate PSP */
		sp_found = DAT_FALSE;
		sp_ptr   = dapls_sp_alloc(ia_ptr, DAT_TRUE);

		if (sp_ptr == NULL) {
			dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
			    DAT_RESOURCE_MEMORY);
			goto bail;
		}
	} else if (sp_ptr->listening == DAT_TRUE) {
		dat_status = DAT_ERROR(DAT_CONN_QUAL_IN_USE, 0);
		goto bail;
	}

	/*
	 * Fill out the args for a PSP
	 */
	sp_ptr->ia_handle  = ia_handle;
	sp_ptr->conn_qual  = conn_qual;
	sp_ptr->evd_handle = evd_handle;
	sp_ptr->psp_flags  = psp_flags;
	sp_ptr->ep_handle  = NULL;

	/*
	 * Take a reference on the EVD handle
	 */
	(void) dapl_os_atomic_inc(&((DAPL_EVD *)evd_handle)->evd_ref_count);

	/*
	 * Set up a listener for a connection. Connections can arrive
	 * even before this call returns!
	 */
	sp_ptr->state = DAPL_SP_STATE_PSP_LISTENING;
	sp_ptr->listening = DAT_TRUE;

	/*
	 * If this is a new sp we need to add it to the IA queue, and set up
	 * a conn_listener.
	 */
	if (sp_found == DAT_FALSE) {

		/* Link it onto the IA */
		dapl_ia_link_psp(ia_ptr, sp_ptr);

		dat_status = dapls_ib_setup_conn_listener(ia_ptr, conn_qual,
		    sp_ptr);

		if (dat_status != DAT_SUCCESS) {
			/*
			 * Have a problem setting up the connection, something
			 * wrong!  The psp_free decrements the EVD refcount for
			 * us; we don't * need to do that.
			 * But we want to set the listener bits to false,
			 * as we know that call failed.
			 */
			sp_ptr->state = DAPL_SP_STATE_FREE;
			sp_ptr->listening = DAT_FALSE;
			(void) dapl_psp_free((DAT_PSP_HANDLE) sp_ptr);

			dapl_dbg_log(DAPL_DBG_TYPE_CM,
			    "--> dapl_psp_create setup_conn_listener failed: "
			    "%x\n",
			    dat_status);

			goto bail;
		}
	}

	/*
	 * Return handle to the user
	 */
	*psp_handle = (DAT_PSP_HANDLE)sp_ptr;

bail:
	return (dat_status);
}
Ejemplo n.º 24
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);
}
Ejemplo n.º 25
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);
}
Ejemplo n.º 26
0
DAT_RETURN dapl_evd_dequeue(
    IN    DAT_EVD_HANDLE	evd_handle,
    OUT   DAT_EVENT		*event)
{
	DAPL_EVD	*evd_ptr;
	DAT_EVENT	*local_event;
	DAT_RETURN	dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_API,
	    "dapl_evd_dequeue (%p, %p)\n",
	    evd_handle,
	    event);

	evd_ptr = (DAPL_EVD *)evd_handle;
	dat_status = DAT_SUCCESS;

	if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0);
		goto bail;
	}

	if (event == NULL) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
		goto bail;
	}

	/*
	 * We need to dequeue under lock, as the IB OS Access API
	 * restricts us from having multiple threads in CQ poll, and the
	 * DAPL 1.1 API allows multiple threads in dat_evd_dequeue()
	 */
	dapl_os_lock(&evd_ptr->header.lock);

	/*
	 * Make sure there are no other waiters and the evd is active.
	 * Currently this means only the OPEN state is allowed.
	 */
	if (evd_ptr->evd_state != DAPL_EVD_STATE_OPEN ||
	    evd_ptr->catastrophic_overflow) {
		dapl_os_unlock(&evd_ptr->header.lock);
		dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);
		goto bail;
	}

	/*
	 * Try the EVD rbuf first; poll from the CQ only if that's empty.
	 * This keeps events in order if dat_evd_wait() has copied events
	 * from CQ to EVD.
	 */
	if (evd_ptr->pending_event_queue.head !=
	    evd_ptr->pending_event_queue.tail) {
		local_event = (DAT_EVENT *)
		    dapls_rbuf_remove(&evd_ptr->pending_event_queue);
		if (local_event != NULL) {
			*event = *local_event;
			dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue,
			    local_event);
		} else { /* should never happen */
			dat_status = DAT_ERROR(DAT_INTERNAL_ERROR, 0);
		}
	} else if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE) {
		dat_status =  DAT_ERROR(DAT_QUEUE_EMPTY, 0);
	} else if ((evd_ptr->evd_flags & (DAT_EVD_CONNECTION_FLAG |
	    DAT_EVD_CR_FLAG | DAT_EVD_ASYNC_FLAG)) == 0) {
		/*
		 * No need to drop into kernel, just check the CQ.
		 */
		dat_status = dapls_evd_cq_poll_to_event(evd_ptr, event);
	} else {
		/* poll for events with threshold and timeout both 0 */
		evd_ptr->threshold = 0;

		dapl_os_unlock(&evd_ptr->header.lock);
		dat_status = dapls_evd_copy_events(evd_ptr, 0);
		if (dat_status != DAT_SUCCESS) {
			dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0);
			goto bail;
		}

		dapl_os_lock(&evd_ptr->header.lock);

		local_event = (DAT_EVENT *)dapls_rbuf_remove(
		    &evd_ptr->pending_event_queue);
		if (local_event != NULL) {
			*event = *local_event;
			dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue,
			    local_event);
		} else { /* still didn't find anything */
			dat_status =  DAT_ERROR(DAT_QUEUE_EMPTY, 0);
		}
	}

	dapl_os_unlock(&evd_ptr->header.lock);
bail:
	dapl_dbg_log(DAPL_DBG_TYPE_RTN,
	    "dapl_evd_dequeue () returns 0x%x\n",
	    dat_status);

	return (dat_status);
}
Ejemplo n.º 27
0
/*
 * dapls_ib_reinit_ep
 *
 * Move the QP to INIT state again.
 *
 * Input:
 *	ep_ptr		DAPL_EP
 *
 * Output:
 * 	none
 *
 * Returns:
 * 	void
 *
 */
void
dapls_ib_reinit_ep(IN DAPL_EP *ep_ptr)
{
    dapl_ep_reinit_t	reinit_args;
    ib_hca_handle_t		hca_hndl;
    ib_qp_handle_t		qp_p;
    char			addr_buf[64];
    int			retval;

    hca_hndl = ep_ptr->header.owner_ia->hca_ptr->ib_hca_handle;
    qp_p = ep_ptr->qp_handle;

    if (qp_p == NULL) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_reinit: qp_handle == NULL\n");
        return;
    }
    /*
     * Do all the work request cleanup processing right away
     * no one should really be doing any operation on this
     * qp (we are not threadsafe)...
     */
    dapls_tavor_wrid_cleanup(ep_ptr, qp_p);

    reinit_args.epri_hkey = qp_p->ep_hkey;
    if (ioctl(hca_hndl->ia_fd, DAPL_EP_REINIT, &reinit_args) != 0) {
        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                     "dapls_ib_reinit: reinit failed %s\n",
                     strerror(errno));
        return;
    }

    qp_p->qp_sq_lastwqeaddr = NULL;
    qp_p->qp_rq_lastwqeaddr = NULL;

    /*
     * Setup data structure for work request processing
     */
    retval = dapls_tavor_wrid_init(qp_p);
    if (retval != DAT_SUCCESS) {
        /*
         * we failed to create data structures for work request
         * processing. Lets unmap and leave, the qp will get
         * cleaned when ep gets destroyed - the ep is unusable
         * in this state.
         */
        if (munmap((void *)qp_p->qp_addr, qp_p->qp_map_len) < 0) {
            dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                         "qp_free: munmap failed(%d)\n", errno);
        }
        qp_p->qp_addr = NULL;
        dapl_dbg_log(DAPL_DBG_TYPE_CM,
                     "dapls_ib_reinit: wrid_init failed %d\n", retval);
        return;
    }

    /* we have a new ep and it is in the init state */
    ep_ptr->qp_state = IBT_STATE_INIT;

    dapl_dbg_log(DAPL_DBG_TYPE_CM,
                 "dapls_ib_reinit: successful, ia_address %s, conn_qual %016llu\n",
                 dapls_inet_ntop((struct sockaddr *)ep_ptr->param.
                                 remote_ia_address_ptr, addr_buf, 64),
                 ep_ptr->param.remote_port_qual);
}
Ejemplo n.º 28
0
/*
 * dapli_get_sp_ep
 *
 * Passive side of a connection is now fully established. Clean
 * up resources and obtain the EP pointer associated with a CR in
 * the SP
 *
 * Input:
 * 	ib_cm_handle,
 * 	sp_ptr
 *	connection_event
 *
 * Output:
 *	none
 *
 * Returns
 * 	ep_ptr
 *
 */
DAPL_EP *dapli_get_sp_ep(IN dp_ib_cm_handle_t ib_cm_handle,
			 IN DAPL_SP * sp_ptr, IN DAT_EVENT_NUMBER dat_event_num)
{
	DAPL_CR *cr_ptr;
	DAPL_EP *ep_ptr;

	/*
	 * acquire the lock, we may be racing with other threads here
	 */
	dapl_os_lock(&sp_ptr->header.lock);

	/* Verify under lock that the SP is still valid */
	if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) {
		dapl_os_unlock(&sp_ptr->header.lock);
		return NULL;
	}
	/*
	 * There are potentially multiple connections in progress. Need to
	 * go through the list and find the one we are interested
	 * in. There is no guarantee of order. dapl_sp_search_cr
	 * leaves the CR on the SP queue.
	 */
	cr_ptr = dapl_sp_search_cr(sp_ptr, ib_cm_handle);
	if (cr_ptr == NULL) {
		dapl_os_unlock(&sp_ptr->header.lock);
		return NULL;
	}

	ep_ptr = (DAPL_EP *) cr_ptr->param.local_ep_handle;

	/* Quick check to ensure our EP is still valid */
	if ((DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP))) {
		ep_ptr = NULL;
	}

	/* The CR record is discarded in all except for the CONNECTED case,
	 * as it will have no further relevance.
	 */
	if (dat_event_num != DAT_CONNECTION_EVENT_ESTABLISHED) {
		/* Remove the CR from the queue */
		dapl_sp_remove_cr(sp_ptr, cr_ptr);

		if (ep_ptr != NULL) {
			ep_ptr->cr_ptr = NULL;
		}

		/*
		 * If this SP has been removed from service, free it
		 * up after the last CR is removed
		 */
		if (sp_ptr->listening != DAT_TRUE && sp_ptr->cr_list_count == 0
		    && sp_ptr->state != DAPL_SP_STATE_FREE
		    && sp_ptr->state != DAPL_SP_STATE_RSP_LISTENING) {
			dapl_dbg_log(DAPL_DBG_TYPE_CM,
				     "--> dapli_get_sp_ep! disconnect dump sp: %p \n",
				     sp_ptr);
			/* Decrement the ref count on the EVD */
			if (sp_ptr->evd_handle) {
				dapl_os_atomic_dec(&
						   ((DAPL_EVD *) sp_ptr->
						    evd_handle)->evd_ref_count);
				sp_ptr->evd_handle = NULL;
			}
			sp_ptr->state = DAPL_SP_STATE_FREE;
			dapl_os_unlock(&sp_ptr->header.lock);
			(void)dapls_ib_remove_conn_listener(sp_ptr->header.
							    owner_ia, sp_ptr);
			dapls_ia_unlink_sp((DAPL_IA *) sp_ptr->header.owner_ia,
					   sp_ptr);
			dapls_sp_free_sp(sp_ptr);
			dapls_cr_free(cr_ptr);
			goto skip_unlock;
		}

		dapl_os_unlock(&sp_ptr->header.lock);
		/* free memory outside of the lock */
		dapls_cr_free(cr_ptr);
	} else {
		dapl_os_unlock(&sp_ptr->header.lock);
	}

      skip_unlock:
	return ep_ptr;
}
Ejemplo n.º 29
0
/*
 * dapls_cr_callback
 *
 * The callback function registered with verbs for passive side of
 * connection requests. The interface is specified by cm_api.h
 *
 *
 * Input:
 * 	ib_cm_handle,		Handle to CM
 * 	ib_cm_event		Specific CM event
 *	instant_data		Private data with DAT ADDRESS header
 * 	context			SP pointer
 *
 * Output:
 * 	None
 *
 */
void dapls_cr_callback(IN dp_ib_cm_handle_t ib_cm_handle, IN const ib_cm_events_t ib_cm_event,
                       IN const void *private_data_ptr, IN const int private_data_size,
                       IN const void *context)
{
	DAPL_EP *ep_ptr;
	DAPL_EVD *evd_ptr;
	DAPL_SP *sp_ptr;
	DAPL_PRIVATE *prd_ptr;
	DAT_EVENT_NUMBER dat_event_num;
	DAT_RETURN dat_status;

	dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
		     "--> dapl_cr_callback! context: %p event: %x cm_handle %p\n",
		     context, ib_cm_event, (void *)ib_cm_handle);

	/*
	 * Passive side of the connection, context is a SP and
	 * we need to look up the EP.
	 */
	sp_ptr = (DAPL_SP *) context;
	/*
	 * The context pointer could have been cleaned up in a racing
	 * CM callback, check to see if we should just exit here
	 */
	if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) {
		return;
	}
	dapl_os_assert(sp_ptr->header.magic == DAPL_MAGIC_PSP ||
		       sp_ptr->header.magic == DAPL_MAGIC_RSP);

	/* Obtain the event number from the provider layer */
	dat_event_num = dapls_ib_get_dat_event(ib_cm_event, DAT_FALSE);

	/*
	 * CONNECT_REQUEST events create an event on the PSP
	 * EVD, which will trigger connection processing. The
	 * sequence is:
	 *    CONNECT_REQUEST         Event to SP
	 *    CONNECTED               Event to EP
	 *    DISCONNECT              Event to EP
	 *
	 * Obtain the EP if required and set an event up on the correct
	 * EVD.
	 */
	if (dat_event_num == DAT_CONNECTION_REQUEST_EVENT) {
		ep_ptr = NULL;
		evd_ptr = sp_ptr->evd_handle;
	} else {
		/* see if there is an EP connected with this CM handle */
		ep_ptr = dapli_get_sp_ep(ib_cm_handle, sp_ptr, dat_event_num);

		/* if we lost a race with the CM just exit. */
		if (ep_ptr == NULL) {
			return;
		}

		evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;
		/* if something has happened to our EVD, bail. */
		if (evd_ptr == NULL) {
			return;
		}
	}

	prd_ptr = (DAPL_PRIVATE *) private_data_ptr;

	dat_status = DAT_INTERNAL_ERROR;	/* init to ERR */

	switch (dat_event_num) {
	case DAT_CONNECTION_REQUEST_EVENT:
		{
			/*
			 * Requests arriving on a disabled SP are immediatly rejected
			 */

			dapl_os_lock(&sp_ptr->header.lock);
			if (sp_ptr->listening == DAT_FALSE) {
				dapl_os_unlock(&sp_ptr->header.lock);
				dapl_log(DAPL_DBG_TYPE_CM_WARN,
					 " cr_callback: CR event on non-listening SP\n");
				(void)dapls_ib_reject_connection(ib_cm_handle,
								 DAT_CONNECTION_EVENT_UNREACHABLE,
								 0, NULL);

				return;
			}

			if (sp_ptr->header.handle_type == DAT_HANDLE_TYPE_RSP) {
				/*
				 * RSP connections only allow a single connection. Close
				 * it down NOW so we reject any further connections.
				 */
				sp_ptr->listening = DAT_FALSE;
			}
			dapl_os_unlock(&sp_ptr->header.lock);

			/*
			 * Only occurs on the passive side of a connection
			 * dapli_connection_request will post the connection
			 * event if appropriate.
			 */
			dat_status = dapli_connection_request(ib_cm_handle,
							      sp_ptr, prd_ptr, private_data_size, evd_ptr);
			/* Set evd_ptr = NULL so we don't generate an event below */
			evd_ptr = NULL;

			break;
		}
	case DAT_CONNECTION_EVENT_ESTABLISHED:
		{
			/* This is just a notification the connection is now
			 * established, there isn't any private data to deal with.
			 *
			 * Update the EP state and cache a copy of the cm handle,
			 * then let the user know we are ready to go.
			 */
			dapl_os_lock(&ep_ptr->header.lock);
			if (ep_ptr->header.magic != DAPL_MAGIC_EP ||
			    ep_ptr->param.ep_state !=
			    DAT_EP_STATE_COMPLETION_PENDING) {
				/* If someone pulled the plug on the EP or connection,
				 * just exit
				 */
				dapl_os_unlock(&ep_ptr->header.lock);
				dat_status = DAT_SUCCESS;
				/* Set evd_ptr = NULL so we don't generate an event below */
				evd_ptr = NULL;

				break;
			}

			ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;
			dapl_os_unlock(&ep_ptr->header.lock);

			break;
		}
	case DAT_CONNECTION_EVENT_DISCONNECTED:
		{
			/*
			 * EP is now fully disconnected; initiate any post processing
			 * to reset the underlying QP and get the EP ready for
			 * another connection
			 */
			dapl_os_lock(&ep_ptr->header.lock);
			if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED) {
				/* The disconnect has already occurred, we are now
				 * cleaned up and ready to exit
				 */
				dapl_os_unlock(&ep_ptr->header.lock);
				return;
			}
			ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
			dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
						  ib_cm_event);
			dapl_os_unlock(&ep_ptr->header.lock);

			break;
		}
	case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:
	case DAT_CONNECTION_EVENT_PEER_REJECTED:
	case DAT_CONNECTION_EVENT_UNREACHABLE:
		{
			/*
			 * After posting an accept the requesting node has
			 * stopped talking.
			 */
			dapl_os_lock(&ep_ptr->header.lock);
			ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
			dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
						  ib_cm_event);
			dapl_os_unlock(&ep_ptr->header.lock);

			break;
		}
	case DAT_CONNECTION_EVENT_BROKEN:
		{
			dapl_os_lock(&ep_ptr->header.lock);
			ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
			dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
						  ib_cm_event);
			dapl_os_unlock(&ep_ptr->header.lock);

			break;
		}
	default:
		{
			evd_ptr = NULL;
			dapl_os_assert(0);	/* shouldn't happen */
			break;
		}
	}

	if (evd_ptr != NULL) {
		dat_status = dapls_evd_post_connection_event(evd_ptr,
							     dat_event_num,
							     (DAT_HANDLE)
							     ep_ptr, 0, NULL);
	}

	if (dat_status != DAT_SUCCESS) {
		/* The event post failed; take appropriate action.  */
		(void)dapls_ib_reject_connection(ib_cm_handle,
						 DAT_CONNECTION_EVENT_BROKEN,
						 0, NULL);

		return;
	}
}
Ejemplo n.º 30
0
/*
 * dapl_rsp_create
 *
 * uDAPL: User Direct Access Program Library Version 1.1, 6.4.3.4.1
 *
 * Create a Resereved Service Point with the specified Endpoint
 * that generates at most one Connection Request that is
 * delivered to the specified Event Dispatcher in a notification
 * event
 *
 * Input:
 *	ia_handle
 *	conn_qual
 *	ep_handle
 *	evd_handle
 *
 * Output:
 *	rsp_handle
 *
 * Returns:
 *	DAT_SUCCESS
 *	DAT_INSUFFICIENT_RESOURCES
 *	DAT_INVALID_PARAMETER
 *	DAT_INVALID_STATE
 *	DAT_CONN_QUAL_IN_USE
 */
DAT_RETURN
dapl_rsp_create(
	IN DAT_IA_HANDLE ia_handle,
	IN DAT_CONN_QUAL conn_qual,
	IN DAT_EP_HANDLE ep_handle,
	IN DAT_EVD_HANDLE evd_handle,
	OUT DAT_RSP_HANDLE *rsp_handle)
{
	DAPL_IA	*ia_ptr;
	DAPL_SP	*sp_ptr;
	DAPL_EVD *evd_ptr;
	DAPL_EP	*ep_ptr;
	DAT_BOOLEAN sp_found;
	DAT_RETURN dat_status;

	dat_status = DAT_SUCCESS;
	ia_ptr = (DAPL_IA *)ia_handle;

	dapl_dbg_log(DAPL_DBG_TYPE_CM,
	    ">>> dapl_rsp_free conn_qual: %x EP: %p\n",
	    conn_qual, ep_handle);

	if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_IA);
		goto bail;
	}
	if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EP);
		goto bail;
	}
	if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EVD_CR);
		goto bail;
	}

	if (rsp_handle == NULL) {
		dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5);
		goto bail;
	}

	ep_ptr = (DAPL_EP *) ep_handle;
	if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED) {
		dat_status = DAT_ERROR(DAT_INVALID_STATE,
		    dapls_ep_state_subtype(ep_ptr));
		goto bail;
	}

	evd_ptr = (DAPL_EVD *)evd_handle;
	if (!(evd_ptr->evd_flags & DAT_EVD_CR_FLAG)) {
		dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
		    DAT_INVALID_HANDLE_EVD_CR);
		goto bail;
	}

	sp_ptr = dapls_ia_sp_search(ia_ptr, conn_qual, DAT_FALSE);
	sp_found = DAT_TRUE;
	if (sp_ptr == NULL) {
		sp_found = DAT_FALSE;

		/* Allocate RSP */
		sp_ptr = dapls_sp_alloc(ia_ptr, DAT_FALSE);
		if (sp_ptr == NULL) {
			dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
			    DAT_RESOURCE_MEMORY);
			goto bail;
		}
	}

	/*
	 * Fill out the RSP args
	 */
	sp_ptr->ia_handle  = ia_handle;
	sp_ptr->conn_qual  = conn_qual;
	sp_ptr->evd_handle = evd_handle;
	sp_ptr->psp_flags  = 0;
	sp_ptr->ep_handle  = ep_handle;

	/*
	 * Take a reference on the EVD handle
	 */
	(void) dapl_os_atomic_inc(&((DAPL_EVD *)evd_handle)->evd_ref_count);

	/*
	 * Update the EP state indicating the provider now owns it
	 */
	ep_ptr->param.ep_state = DAT_EP_STATE_RESERVED;

	/*
	 * Set up a listener for a connection. Connections can arrive
	 * even before this call returns!
	 */
	sp_ptr->state = DAPL_SP_STATE_RSP_LISTENING;
	sp_ptr->listening = DAT_TRUE;

	if (sp_found == DAT_FALSE) {
	/* Link it onto the IA */
		dapl_ia_link_rsp(ia_ptr, sp_ptr);

		dat_status = dapls_ib_setup_conn_listener(ia_ptr, conn_qual,
		    sp_ptr);

		if (dat_status != DAT_SUCCESS) {
			/*
			 * Have a problem setting up the connection, something
			 * wrong!
			 * rsp_free will decrement the EVD refcount. Set
			 * listening to * false to avoid tearing down the
			 * conn_listener which didn't * get set up.
			 */
			sp_ptr->listening = DAT_FALSE;
			(void) dapl_rsp_free((DAT_RSP_HANDLE) sp_ptr);

			dapl_dbg_log(DAPL_DBG_TYPE_CM,
			    "--> dapl_rsp_create setup_conn_listener failed: "
			    "%x\n",
			    dat_status);

			goto bail;
		}
	}

	/*
	 * Return handle to the user
	 */
	*rsp_handle = (DAT_RSP_HANDLE)sp_ptr;

bail:
	return (dat_status);
}