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

📄 cma.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct ib_qp_attr qp_attr;	int qp_attr_mask, ret;	mutex_lock(&id_priv->qp_mutex);	if (!id_priv->id.qp) {		ret = 0;		goto out;	}	qp_attr.qp_state = IB_QPS_RTS;	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);	if (ret)		goto out;	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);out:	mutex_unlock(&id_priv->qp_mutex);	return ret;}static int cma_modify_qp_err(struct rdma_id_private *id_priv){	struct ib_qp_attr qp_attr;	int ret;	mutex_lock(&id_priv->qp_mutex);	if (!id_priv->id.qp) {		ret = 0;		goto out;	}	qp_attr.qp_state = IB_QPS_ERR;	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, IB_QP_STATE);out:	mutex_unlock(&id_priv->qp_mutex);	return ret;}static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,			       struct ib_qp_attr *qp_attr, int *qp_attr_mask){	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;	int ret;	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,				  ib_addr_get_pkey(dev_addr),				  &qp_attr->pkey_index);	if (ret)		return ret;	qp_attr->port_num = id_priv->id.port_num;	*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;	if (cma_is_ud_ps(id_priv->id.ps)) {		qp_attr->qkey = id_priv->qkey;		*qp_attr_mask |= IB_QP_QKEY;	} else {		qp_attr->qp_access_flags = 0;		*qp_attr_mask |= IB_QP_ACCESS_FLAGS;	}	return 0;}int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,		       int *qp_attr_mask){	struct rdma_id_private *id_priv;	int ret = 0;	id_priv = container_of(id, struct rdma_id_private, id);	switch (rdma_node_get_transport(id_priv->id.device->node_type)) {	case RDMA_TRANSPORT_IB:		if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps))			ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);		else			ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,						 qp_attr_mask);		if (qp_attr->qp_state == IB_QPS_RTR)			qp_attr->rq_psn = id_priv->seq_num;		break;	case RDMA_TRANSPORT_IWARP:		if (!id_priv->cm_id.iw) {			qp_attr->qp_access_flags = 0;			*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;		} else			ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,						 qp_attr_mask);		break;	default:		ret = -ENOSYS;		break;	}	return ret;}EXPORT_SYMBOL(rdma_init_qp_attr);static inline int cma_zero_addr(struct sockaddr *addr){	struct in6_addr *ip6;	if (addr->sa_family == AF_INET)		return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);	else {		ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;		return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |			ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0;	}}static inline int cma_loopback_addr(struct sockaddr *addr){	return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);}static inline int cma_any_addr(struct sockaddr *addr){	return cma_zero_addr(addr) || cma_loopback_addr(addr);}static inline __be16 cma_port(struct sockaddr *addr){	if (addr->sa_family == AF_INET)		return ((struct sockaddr_in *) addr)->sin_port;	else		return ((struct sockaddr_in6 *) addr)->sin6_port;}static inline int cma_any_port(struct sockaddr *addr){	return !cma_port(addr);}static int cma_get_net_info(void *hdr, enum rdma_port_space ps,			    u8 *ip_ver, __u16 *port,			    union cma_ip_addr **src, union cma_ip_addr **dst){	switch (ps) {	case RDMA_PS_SDP:		if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) !=		    SDP_MAJ_VERSION)			return -EINVAL;		*ip_ver	= sdp_get_ip_ver(hdr);		*port	= ((struct sdp_hh *) hdr)->port;		*src	= &((struct sdp_hh *) hdr)->src_addr;		*dst	= &((struct sdp_hh *) hdr)->dst_addr;		break;	default:		if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)			return -EINVAL;		*ip_ver	= cma_get_ip_ver(hdr);		*port	= ((struct cma_hdr *) hdr)->port;		*src	= &((struct cma_hdr *) hdr)->src_addr;		*dst	= &((struct cma_hdr *) hdr)->dst_addr;		break;	}	if (*ip_ver != 4 && *ip_ver != 6)		return -EINVAL;	return 0;}static void cma_save_net_info(struct rdma_addr *addr,			      struct rdma_addr *listen_addr,			      u8 ip_ver, __u16 port,			      union cma_ip_addr *src, union cma_ip_addr *dst){	struct sockaddr_in *listen4, *ip4;	struct sockaddr_in6 *listen6, *ip6;	switch (ip_ver) {	case 4:		listen4 = (struct sockaddr_in *) &listen_addr->src_addr;		ip4 = (struct sockaddr_in *) &addr->src_addr;		ip4->sin_family = listen4->sin_family;		ip4->sin_addr.s_addr = dst->ip4.addr;		ip4->sin_port = listen4->sin_port;		ip4 = (struct sockaddr_in *) &addr->dst_addr;		ip4->sin_family = listen4->sin_family;		ip4->sin_addr.s_addr = src->ip4.addr;		ip4->sin_port = port;		break;	case 6:		listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;		ip6 = (struct sockaddr_in6 *) &addr->src_addr;		ip6->sin6_family = listen6->sin6_family;		ip6->sin6_addr = dst->ip6;		ip6->sin6_port = listen6->sin6_port;		ip6 = (struct sockaddr_in6 *) &addr->dst_addr;		ip6->sin6_family = listen6->sin6_family;		ip6->sin6_addr = src->ip6;		ip6->sin6_port = port;		break;	default:		break;	}}static inline int cma_user_data_offset(enum rdma_port_space ps){	switch (ps) {	case RDMA_PS_SDP:		return 0;	default:		return sizeof(struct cma_hdr);	}}static void cma_cancel_route(struct rdma_id_private *id_priv){	switch (rdma_node_get_transport(id_priv->id.device->node_type)) {	case RDMA_TRANSPORT_IB:		if (id_priv->query)			ib_sa_cancel_query(id_priv->query_id, id_priv->query);		break;	default:		break;	}}static void cma_cancel_listens(struct rdma_id_private *id_priv){	struct rdma_id_private *dev_id_priv;	/*	 * Remove from listen_any_list to prevent added devices from spawning	 * additional listen requests.	 */	mutex_lock(&lock);	list_del(&id_priv->list);	while (!list_empty(&id_priv->listen_list)) {		dev_id_priv = list_entry(id_priv->listen_list.next,					 struct rdma_id_private, listen_list);		/* sync with device removal to avoid duplicate destruction */		list_del_init(&dev_id_priv->list);		list_del(&dev_id_priv->listen_list);		mutex_unlock(&lock);		rdma_destroy_id(&dev_id_priv->id);		mutex_lock(&lock);	}	mutex_unlock(&lock);}static void cma_cancel_operation(struct rdma_id_private *id_priv,				 enum cma_state state){	switch (state) {	case CMA_ADDR_QUERY:		rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);		break;	case CMA_ROUTE_QUERY:		cma_cancel_route(id_priv);		break;	case CMA_LISTEN:		if (cma_any_addr(&id_priv->id.route.addr.src_addr) &&		    !id_priv->cma_dev)			cma_cancel_listens(id_priv);		break;	default:		break;	}}static void cma_release_port(struct rdma_id_private *id_priv){	struct rdma_bind_list *bind_list = id_priv->bind_list;	if (!bind_list)		return;	mutex_lock(&lock);	hlist_del(&id_priv->node);	if (hlist_empty(&bind_list->owners)) {		idr_remove(bind_list->ps, bind_list->port);		kfree(bind_list);	}	mutex_unlock(&lock);}static void cma_leave_mc_groups(struct rdma_id_private *id_priv){	struct cma_multicast *mc;	while (!list_empty(&id_priv->mc_list)) {		mc = container_of(id_priv->mc_list.next,				  struct cma_multicast, list);		list_del(&mc->list);		ib_sa_free_multicast(mc->multicast.ib);		kfree(mc);	}}void rdma_destroy_id(struct rdma_cm_id *id){	struct rdma_id_private *id_priv;	enum cma_state state;	id_priv = container_of(id, struct rdma_id_private, id);	state = cma_exch(id_priv, CMA_DESTROYING);	cma_cancel_operation(id_priv, state);	mutex_lock(&lock);	if (id_priv->cma_dev) {		mutex_unlock(&lock);		switch (rdma_node_get_transport(id->device->node_type)) {		case RDMA_TRANSPORT_IB:			if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))				ib_destroy_cm_id(id_priv->cm_id.ib);			break;		case RDMA_TRANSPORT_IWARP:			if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw))				iw_destroy_cm_id(id_priv->cm_id.iw);			break;		default:			break;		}		cma_leave_mc_groups(id_priv);		mutex_lock(&lock);		cma_detach_from_dev(id_priv);	}	mutex_unlock(&lock);	cma_release_port(id_priv);	cma_deref_id(id_priv);	wait_for_completion(&id_priv->comp);	if (id_priv->internal_id)		cma_deref_id(id_priv->id.context);	kfree(id_priv->id.route.path_rec);	kfree(id_priv);}EXPORT_SYMBOL(rdma_destroy_id);static int cma_rep_recv(struct rdma_id_private *id_priv){	int ret;	ret = cma_modify_qp_rtr(id_priv);	if (ret)		goto reject;	ret = cma_modify_qp_rts(id_priv);	if (ret)		goto reject;	ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);	if (ret)		goto reject;	return 0;reject:	cma_modify_qp_err(id_priv);	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,		       NULL, 0, NULL, 0);	return ret;}static int cma_verify_rep(struct rdma_id_private *id_priv, void *data){	if (id_priv->id.ps == RDMA_PS_SDP &&	    sdp_get_majv(((struct sdp_hah *) data)->sdp_version) !=	    SDP_MAJ_VERSION)		return -EINVAL;	return 0;}static void cma_set_rep_event_data(struct rdma_cm_event *event,				   struct ib_cm_rep_event_param *rep_data,				   void *private_data){	event->param.conn.private_data = private_data;	event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;	event->param.conn.responder_resources = rep_data->responder_resources;	event->param.conn.initiator_depth = rep_data->initiator_depth;	event->param.conn.flow_control = rep_data->flow_control;	event->param.conn.rnr_retry_count = rep_data->rnr_retry_count;	event->param.conn.srq = rep_data->srq;	event->param.conn.qp_num = rep_data->remote_qpn;}static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event){	struct rdma_id_private *id_priv = cm_id->context;	struct rdma_cm_event event;	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_REQ_ERROR:	case IB_CM_REP_ERROR:		event.event = RDMA_CM_EVENT_UNREACHABLE;		event.status = -ETIMEDOUT;		break;	case IB_CM_REP_RECEIVED:		event.status = cma_verify_rep(id_priv, ib_event->private_data);		if (event.status)			event.event = RDMA_CM_EVENT_CONNECT_ERROR;		else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {			event.status = cma_rep_recv(id_priv);			event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :						     RDMA_CM_EVENT_ESTABLISHED;		} else			event.event = RDMA_CM_EVENT_CONNECT_RESPONSE;		cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd,				       ib_event->private_data);		break;	case IB_CM_RTU_RECEIVED:	case IB_CM_USER_ESTABLISHED:		event.event = RDMA_CM_EVENT_ESTABLISHED;		break;	case IB_CM_DREQ_ERROR:		event.status = -ETIMEDOUT; /* fall through */	case IB_CM_DREQ_RECEIVED:	case IB_CM_DREP_RECEIVED:		if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))			goto out;		event.event = RDMA_CM_EVENT_DISCONNECTED;		break;	case IB_CM_TIMEWAIT_EXIT:	case IB_CM_MRA_RECEIVED:		/* ignore event */		goto out;	case IB_CM_REJ_RECEIVED:		cma_modify_qp_err(id_priv);		event.status = ib_event->param.rej_rcvd.reason;		event.event = RDMA_CM_EVENT_REJECTED;		event.param.conn.private_data = ib_event->private_data;		event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;		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 struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,					       struct ib_cm_event *ib_event){	struct rdma_id_private *id_priv;	struct rdma_cm_id *id;	struct rdma_route *rt;	union cma_ip_addr *src, *dst;	__u16 port;	u8 ip_ver;	if (cma_get_net_info(ib_event->private_data, listen_id->ps,			     &ip_ver, &port, &src, &dst))		goto err;	id = rdma_create_id(listen_id->event_handler, listen_id->context,			    listen_id->ps);	if (IS_ERR(id))		goto err;	cma_save_net_info(&id->route.addr, &listen_id->route.addr,			  ip_ver, port, src, dst);	rt = &id->route;	rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,			       GFP_KERNEL);	if (!rt->path_rec)		goto destroy_id;	rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;	if (rt->num_paths == 2)		rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;	ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);	ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);	ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));	rt->addr.dev_addr.dev_type = RDMA_NODE_IB_CA;	id_priv = container_of(id, struct rdma_id_private, id);	id_priv->state = CMA_CONNECT;	return id_priv;destroy_id:	rdma_destroy_id(id);err:	return NULL;}static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,					      struct ib_cm_event *ib_event){	struct rdma_id_private *id_priv;	struct rdma_cm_id *id;	union cma_ip_addr *src, *dst;	__u16 port;	u8 ip_ver;	int ret;	id = rdma_create_id(listen_id->event_handler, listen_id->context,			    listen_id->ps);	if (IS_ERR(id))		return NULL;

⌨️ 快捷键说明

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