⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cma.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;	int ret = 0;	if (cma_disable_remove(id_priv, CMA_CONNECT))		return 0;	memset(&event, 0, sizeof event);	switch (ib_event->event) {	case IB_CM_SIDR_REQ_ERROR:		event.event = RDMA_CM_EVENT_UNREACHABLE;		event.status = -ETIMEDOUT;		break;	case IB_CM_SIDR_REP_RECEIVED:		event.param.ud.private_data = ib_event->private_data;		event.param.ud.private_data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;		if (rep->status != IB_SIDR_SUCCESS) {			event.event = RDMA_CM_EVENT_UNREACHABLE;			event.status = ib_event->param.sidr_rep_rcvd.status;			break;		}		if (id_priv->qkey != rep->qkey) {			event.event = RDMA_CM_EVENT_UNREACHABLE;			event.status = -EINVAL;			break;		}		ib_init_ah_from_path(id_priv->id.device, id_priv->id.port_num,				     id_priv->id.route.path_rec,				     &event.param.ud.ah_attr);		event.param.ud.qp_num = rep->qpn;		event.param.ud.qkey = rep->qkey;		event.event = RDMA_CM_EVENT_ESTABLISHED;		event.status = 0;		break;	default:		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",		       ib_event->event);		goto out;	}	ret = id_priv->id.event_handler(&id_priv->id, &event);	if (ret) {		/* Destroy the CM ID by returning a non-zero value. */		id_priv->cm_id.ib = NULL;		cma_exch(id_priv, CMA_DESTROYING);		cma_enable_remove(id_priv);		rdma_destroy_id(&id_priv->id);		return ret;	}out:	cma_enable_remove(id_priv);	return ret;}static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,			      struct rdma_conn_param *conn_param){	struct ib_cm_sidr_req_param req;	struct rdma_route *route;	int ret;	req.private_data_len = sizeof(struct cma_hdr) +			       conn_param->private_data_len;	req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);	if (!req.private_data)		return -ENOMEM;	if (conn_param->private_data && conn_param->private_data_len)		memcpy((void *) req.private_data + sizeof(struct cma_hdr),		       conn_param->private_data, conn_param->private_data_len);	route = &id_priv->id.route;	ret = cma_format_hdr((void *) req.private_data, id_priv->id.ps, route);	if (ret)		goto out;	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,					    cma_sidr_rep_handler, id_priv);	if (IS_ERR(id_priv->cm_id.ib)) {		ret = PTR_ERR(id_priv->cm_id.ib);		goto out;	}	req.path = route->path_rec;	req.service_id = cma_get_service_id(id_priv->id.ps,					    &route->addr.dst_addr);	req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8);	req.max_cm_retries = CMA_MAX_CM_RETRIES;	ret = ib_send_cm_sidr_req(id_priv->cm_id.ib, &req);	if (ret) {		ib_destroy_cm_id(id_priv->cm_id.ib);		id_priv->cm_id.ib = NULL;	}out:	kfree(req.private_data);	return ret;}static int cma_connect_ib(struct rdma_id_private *id_priv,			  struct rdma_conn_param *conn_param){	struct ib_cm_req_param req;	struct rdma_route *route;	void *private_data;	int offset, ret;	memset(&req, 0, sizeof req);	offset = cma_user_data_offset(id_priv->id.ps);	req.private_data_len = offset + conn_param->private_data_len;	private_data = kzalloc(req.private_data_len, GFP_ATOMIC);	if (!private_data)		return -ENOMEM;	if (conn_param->private_data && conn_param->private_data_len)		memcpy(private_data + offset, conn_param->private_data,		       conn_param->private_data_len);	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,					    id_priv);	if (IS_ERR(id_priv->cm_id.ib)) {		ret = PTR_ERR(id_priv->cm_id.ib);		goto out;	}	route = &id_priv->id.route;	ret = cma_format_hdr(private_data, id_priv->id.ps, route);	if (ret)		goto out;	req.private_data = private_data;	req.primary_path = &route->path_rec[0];	if (route->num_paths == 2)		req.alternate_path = &route->path_rec[1];	req.service_id = cma_get_service_id(id_priv->id.ps,					    &route->addr.dst_addr);	req.qp_num = id_priv->qp_num;	req.qp_type = IB_QPT_RC;	req.starting_psn = id_priv->seq_num;	req.responder_resources = conn_param->responder_resources;	req.initiator_depth = conn_param->initiator_depth;	req.flow_control = conn_param->flow_control;	req.retry_count = conn_param->retry_count;	req.rnr_retry_count = conn_param->rnr_retry_count;	req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;	req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;	req.max_cm_retries = CMA_MAX_CM_RETRIES;	req.srq = id_priv->srq ? 1 : 0;	ret = ib_send_cm_req(id_priv->cm_id.ib, &req);out:	if (ret && !IS_ERR(id_priv->cm_id.ib)) {		ib_destroy_cm_id(id_priv->cm_id.ib);		id_priv->cm_id.ib = NULL;	}	kfree(private_data);	return ret;}static int cma_connect_iw(struct rdma_id_private *id_priv,			  struct rdma_conn_param *conn_param){	struct iw_cm_id *cm_id;	struct sockaddr_in* sin;	int ret;	struct iw_cm_conn_param iw_param;	cm_id = iw_create_cm_id(id_priv->id.device, cma_iw_handler, id_priv);	if (IS_ERR(cm_id)) {		ret = PTR_ERR(cm_id);		goto out;	}	id_priv->cm_id.iw = cm_id;	sin = (struct sockaddr_in*) &id_priv->id.route.addr.src_addr;	cm_id->local_addr = *sin;	sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr;	cm_id->remote_addr = *sin;	ret = cma_modify_qp_rtr(id_priv);	if (ret)		goto out;	iw_param.ord = conn_param->initiator_depth;	iw_param.ird = conn_param->responder_resources;	iw_param.private_data = conn_param->private_data;	iw_param.private_data_len = conn_param->private_data_len;	if (id_priv->id.qp)		iw_param.qpn = id_priv->qp_num;	else		iw_param.qpn = conn_param->qp_num;	ret = iw_cm_connect(cm_id, &iw_param);out:	if (ret && !IS_ERR(cm_id)) {		iw_destroy_cm_id(cm_id);		id_priv->cm_id.iw = NULL;	}	return ret;}int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param){	struct rdma_id_private *id_priv;	int ret;	id_priv = container_of(id, struct rdma_id_private, id);	if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))		return -EINVAL;	if (!id->qp) {		id_priv->qp_num = conn_param->qp_num;		id_priv->srq = conn_param->srq;	}	switch (rdma_node_get_transport(id->device->node_type)) {	case RDMA_TRANSPORT_IB:		if (cma_is_ud_ps(id->ps))			ret = cma_resolve_ib_udp(id_priv, conn_param);		else			ret = cma_connect_ib(id_priv, conn_param);		break;	case RDMA_TRANSPORT_IWARP:		ret = cma_connect_iw(id_priv, conn_param);		break;	default:		ret = -ENOSYS;		break;	}	if (ret)		goto err;	return 0;err:	cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED);	return ret;}EXPORT_SYMBOL(rdma_connect);static int cma_accept_ib(struct rdma_id_private *id_priv,			 struct rdma_conn_param *conn_param){	struct ib_cm_rep_param rep;	struct ib_qp_attr qp_attr;	int qp_attr_mask, ret;	if (id_priv->id.qp) {		ret = cma_modify_qp_rtr(id_priv);		if (ret)			goto out;		qp_attr.qp_state = IB_QPS_RTS;		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,					 &qp_attr_mask);		if (ret)			goto out;		qp_attr.max_rd_atomic = conn_param->initiator_depth;		ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);		if (ret)			goto out;	}	memset(&rep, 0, sizeof rep);	rep.qp_num = id_priv->qp_num;	rep.starting_psn = id_priv->seq_num;	rep.private_data = conn_param->private_data;	rep.private_data_len = conn_param->private_data_len;	rep.responder_resources = conn_param->responder_resources;	rep.initiator_depth = conn_param->initiator_depth;	rep.failover_accepted = 0;	rep.flow_control = conn_param->flow_control;	rep.rnr_retry_count = conn_param->rnr_retry_count;	rep.srq = id_priv->srq ? 1 : 0;	ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);out:	return ret;}static int cma_accept_iw(struct rdma_id_private *id_priv,		  struct rdma_conn_param *conn_param){	struct iw_cm_conn_param iw_param;	int ret;	ret = cma_modify_qp_rtr(id_priv);	if (ret)		return ret;	iw_param.ord = conn_param->initiator_depth;	iw_param.ird = conn_param->responder_resources;	iw_param.private_data = conn_param->private_data;	iw_param.private_data_len = conn_param->private_data_len;	if (id_priv->id.qp) {		iw_param.qpn = id_priv->qp_num;	} else		iw_param.qpn = conn_param->qp_num;	return iw_cm_accept(id_priv->cm_id.iw, &iw_param);}static int cma_send_sidr_rep(struct rdma_id_private *id_priv,			     enum ib_cm_sidr_status status,			     const void *private_data, int private_data_len){	struct ib_cm_sidr_rep_param rep;	memset(&rep, 0, sizeof rep);	rep.status = status;	if (status == IB_SIDR_SUCCESS) {		rep.qp_num = id_priv->qp_num;		rep.qkey = id_priv->qkey;	}	rep.private_data = private_data;	rep.private_data_len = private_data_len;	return ib_send_cm_sidr_rep(id_priv->cm_id.ib, &rep);}int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param){	struct rdma_id_private *id_priv;	int ret;	id_priv = container_of(id, struct rdma_id_private, id);	if (!cma_comp(id_priv, CMA_CONNECT))		return -EINVAL;	if (!id->qp && conn_param) {		id_priv->qp_num = conn_param->qp_num;		id_priv->srq = conn_param->srq;	}	switch (rdma_node_get_transport(id->device->node_type)) {	case RDMA_TRANSPORT_IB:		if (cma_is_ud_ps(id->ps))			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,						conn_param->private_data,						conn_param->private_data_len);		else if (conn_param)			ret = cma_accept_ib(id_priv, conn_param);		else			ret = cma_rep_recv(id_priv);		break;	case RDMA_TRANSPORT_IWARP:		ret = cma_accept_iw(id_priv, conn_param);		break;	default:		ret = -ENOSYS;		break;	}	if (ret)		goto reject;	return 0;reject:	cma_modify_qp_err(id_priv);	rdma_reject(id, NULL, 0);	return ret;}EXPORT_SYMBOL(rdma_accept);int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event){	struct rdma_id_private *id_priv;	int ret;	id_priv = container_of(id, struct rdma_id_private, id);	if (!cma_has_cm_dev(id_priv))		return -EINVAL;	switch (id->device->node_type) {	case RDMA_NODE_IB_CA:		ret = ib_cm_notify(id_priv->cm_id.ib, event);		break;	default:		ret = 0;		break;	}	return ret;}EXPORT_SYMBOL(rdma_notify);int rdma_reject(struct rdma_cm_id *id, const void *private_data,		u8 private_data_len){	struct rdma_id_private *id_priv;	int ret;	id_priv = container_of(id, struct rdma_id_private, id);	if (!cma_has_cm_dev(id_priv))		return -EINVAL;	switch (rdma_node_get_transport(id->device->node_type)) {	case RDMA_TRANSPORT_IB:		if (cma_is_ud_ps(id->ps))			ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,						private_data, private_data_len);		else			ret = ib_send_cm_rej(id_priv->cm_id.ib,					     IB_CM_REJ_CONSUMER_DEFINED, NULL,					     0, private_data, private_data_len);		break;	case RDMA_TRANSPORT_IWARP:		ret = iw_cm_reject(id_priv->cm_id.iw,				   private_data, private_data_len);		break;	default:		ret = -ENOSYS;		break;	}	return ret;}EXPORT_SYMBOL(rdma_reject);int rdma_disconnect(struct rdma_cm_id *id){	struct rdma_id_private *id_priv;	int ret;	id_priv = container_of(id, struct rdma_id_private, id);	if (!cma_has_cm_dev(id_priv))		return -EINVAL;	switch (rdma_node_get_transport(id->device->node_type)) {	case RDMA_TRANSPORT_IB:		ret = cma_modify_qp_err(id_priv);		if (ret)			goto out;		/* Initiate or respond to a disconnect. */		if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))			ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);		break;	case RDMA_TRANSPORT_IWARP:		ret = iw_cm_disconnect(id_priv->cm_id.iw, 0);		break;	default:		ret = -EINVAL;		break;	}out:	return ret;}EXPORT_SYMBOL(rdma_disconnect);static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast){	struct rdma_id_private *id_priv;	struct cma_multicast *mc = multicast->context;	struct rdma_cm_event event;	int ret;	id_priv = mc->id_priv;	if (cma_disable_remove(id_priv, CMA_ADDR_BOUND) &&	    cma_disable_remove(id_priv, CMA_ADDR_RESOLVED))		return 0;	mutex_lock(&id_priv->qp_mutex);	if (!status && id_priv->id.qp)		status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,					 multicast->rec.mlid);	mutex_unlock(&id_priv->qp_mutex);	memset(&event, 0, sizeof event);	event.status = status;	event.param.ud.private_data = mc->context;	if (!status) {		event.event = RDMA_CM_EVENT_MULTICAST_JOIN;		ib_init_ah_from_mcmember(id_priv->id.device,					 id_priv->id.port_num, &multicast->rec,					 &event.param.ud.ah_attr);		event.param.ud.qp_num = 0xFFFFFF;		event.param.ud.qkey = be32_to_cpu(multicast->rec.qkey);	} else		event.event = RDMA_CM_EVENT_MULTICAST_ERROR;	ret = id_priv->id.event_handler(&id_priv->id, &event);	if (ret) {		cma_exch(id_priv, CMA_DESTROYING);		cma_enable_remove(id_priv);		rdma_destroy_id(&id_priv->id);		return 0;	}	cma_enable_remove(id_priv);	return 0;}static void cma_set_mgid(struct rdma_id_private *id_priv,			 struct sockaddr *addr, union ib_gid *mgid){	unsigned char mc_map[MAX_ADDR_LEN];	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;	struct sockaddr_in *sin = (struct sockaddr_in *) addr;	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;	if (cma_any_addr(addr)) {		memset(mgid, 0, sizeof *mgid);	} else if ((addr->sa_family == AF_INET6) &&		   ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==								 0xFF10A01B)) {		/* IPv6 address is an SA assigned MGID. */		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);	} else {		ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);		if (id_priv->id.ps == RDMA_PS_UDP)			mc_map[7] = 0x01;	/* Use RDMA CM signature */		mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;		mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);		*mgid = *(union ib_gid *) (mc_map + 4);	}}static int cma_join_ib_multicast(struct rdma_id_private *id_priv,				 struct cma_multicast *mc){	struct ib_sa_mcmember_rec rec;	struct rdma_dev_addr *dev_addr = &id_pri

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -