Skip to content

Commit a1b1b61

Browse files
Sean HeftyRoland Dreier
authored andcommitted
RDMA/cma: Report connect info with connect events
Connection information was never given to the recipient of a connection request or reply message. Only the event was delivered. Report the connection data with the event to allows user to reject the connection based on the requested parameters, or adjust their resources to match the request. Signed-off-by: Sean Hefty <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent 9b2e9c0 commit a1b1b61

File tree

2 files changed

+101
-72
lines changed

2 files changed

+101
-72
lines changed

drivers/infiniband/core/cma.c

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -592,20 +592,6 @@ static inline int cma_user_data_offset(enum rdma_port_space ps)
592592
}
593593
}
594594

595-
static int cma_notify_user(struct rdma_id_private *id_priv,
596-
enum rdma_cm_event_type type, int status,
597-
void *data, u8 data_len)
598-
{
599-
struct rdma_cm_event event;
600-
601-
event.event = type;
602-
event.status = status;
603-
event.private_data = data;
604-
event.private_data_len = data_len;
605-
606-
return id_priv->id.event_handler(&id_priv->id, &event);
607-
}
608-
609595
static void cma_cancel_route(struct rdma_id_private *id_priv)
610596
{
611597
switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
@@ -790,66 +776,81 @@ static int cma_rtu_recv(struct rdma_id_private *id_priv)
790776
return ret;
791777
}
792778

779+
static void cma_set_rep_event_data(struct rdma_cm_event *event,
780+
struct ib_cm_rep_event_param *rep_data,
781+
void *private_data)
782+
{
783+
event->param.conn.private_data = private_data;
784+
event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
785+
event->param.conn.responder_resources = rep_data->responder_resources;
786+
event->param.conn.initiator_depth = rep_data->initiator_depth;
787+
event->param.conn.flow_control = rep_data->flow_control;
788+
event->param.conn.rnr_retry_count = rep_data->rnr_retry_count;
789+
event->param.conn.srq = rep_data->srq;
790+
event->param.conn.qp_num = rep_data->remote_qpn;
791+
}
792+
793793
static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
794794
{
795795
struct rdma_id_private *id_priv = cm_id->context;
796-
enum rdma_cm_event_type event;
797-
u8 private_data_len = 0;
798-
int ret = 0, status = 0;
796+
struct rdma_cm_event event;
797+
int ret = 0;
799798

800799
atomic_inc(&id_priv->dev_remove);
801800
if (!cma_comp(id_priv, CMA_CONNECT))
802801
goto out;
803802

803+
memset(&event, 0, sizeof event);
804804
switch (ib_event->event) {
805805
case IB_CM_REQ_ERROR:
806806
case IB_CM_REP_ERROR:
807-
event = RDMA_CM_EVENT_UNREACHABLE;
808-
status = -ETIMEDOUT;
807+
event.event = RDMA_CM_EVENT_UNREACHABLE;
808+
event.status = -ETIMEDOUT;
809809
break;
810810
case IB_CM_REP_RECEIVED:
811-
status = cma_verify_rep(id_priv, ib_event->private_data);
812-
if (status)
813-
event = RDMA_CM_EVENT_CONNECT_ERROR;
811+
event.status = cma_verify_rep(id_priv, ib_event->private_data);
812+
if (event.status)
813+
event.event = RDMA_CM_EVENT_CONNECT_ERROR;
814814
else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
815-
status = cma_rep_recv(id_priv);
816-
event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
817-
RDMA_CM_EVENT_ESTABLISHED;
815+
event.status = cma_rep_recv(id_priv);
816+
event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :
817+
RDMA_CM_EVENT_ESTABLISHED;
818818
} else
819-
event = RDMA_CM_EVENT_CONNECT_RESPONSE;
820-
private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
819+
event.event = RDMA_CM_EVENT_CONNECT_RESPONSE;
820+
cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd,
821+
ib_event->private_data);
821822
break;
822823
case IB_CM_RTU_RECEIVED:
823-
status = cma_rtu_recv(id_priv);
824-
event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
825-
RDMA_CM_EVENT_ESTABLISHED;
824+
event.status = cma_rtu_recv(id_priv);
825+
event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :
826+
RDMA_CM_EVENT_ESTABLISHED;
826827
break;
827828
case IB_CM_DREQ_ERROR:
828-
status = -ETIMEDOUT; /* fall through */
829+
event.status = -ETIMEDOUT; /* fall through */
829830
case IB_CM_DREQ_RECEIVED:
830831
case IB_CM_DREP_RECEIVED:
831832
if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
832833
goto out;
833-
event = RDMA_CM_EVENT_DISCONNECTED;
834+
event.event = RDMA_CM_EVENT_DISCONNECTED;
834835
break;
835836
case IB_CM_TIMEWAIT_EXIT:
836837
case IB_CM_MRA_RECEIVED:
837838
/* ignore event */
838839
goto out;
839840
case IB_CM_REJ_RECEIVED:
840841
cma_modify_qp_err(&id_priv->id);
841-
status = ib_event->param.rej_rcvd.reason;
842-
event = RDMA_CM_EVENT_REJECTED;
843-
private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
842+
event.status = ib_event->param.rej_rcvd.reason;
843+
event.event = RDMA_CM_EVENT_REJECTED;
844+
event.param.conn.private_data = ib_event->private_data;
845+
event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
844846
break;
845847
default:
846848
printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
847849
ib_event->event);
848850
goto out;
849851
}
850852

851-
ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
852-
private_data_len);
853+
ret = id_priv->id.event_handler(&id_priv->id, &event);
853854
if (ret) {
854855
/* Destroy the CM ID by returning a non-zero value. */
855856
id_priv->cm_id.ib = NULL;
@@ -911,9 +912,25 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
911912
return NULL;
912913
}
913914

915+
static void cma_set_req_event_data(struct rdma_cm_event *event,
916+
struct ib_cm_req_event_param *req_data,
917+
void *private_data, int offset)
918+
{
919+
event->param.conn.private_data = private_data + offset;
920+
event->param.conn.private_data_len = IB_CM_REQ_PRIVATE_DATA_SIZE - offset;
921+
event->param.conn.responder_resources = req_data->responder_resources;
922+
event->param.conn.initiator_depth = req_data->initiator_depth;
923+
event->param.conn.flow_control = req_data->flow_control;
924+
event->param.conn.retry_count = req_data->retry_count;
925+
event->param.conn.rnr_retry_count = req_data->rnr_retry_count;
926+
event->param.conn.srq = req_data->srq;
927+
event->param.conn.qp_num = req_data->remote_qpn;
928+
}
929+
914930
static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
915931
{
916932
struct rdma_id_private *listen_id, *conn_id;
933+
struct rdma_cm_event event;
917934
int offset, ret;
918935

919936
listen_id = cm_id->context;
@@ -941,9 +958,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
941958
cm_id->cm_handler = cma_ib_handler;
942959

943960
offset = cma_user_data_offset(listen_id->id.ps);
944-
ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
945-
ib_event->private_data + offset,
946-
IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
961+
memset(&event, 0, sizeof event);
962+
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
963+
cma_set_req_event_data(&event, &ib_event->param.req_rcvd,
964+
ib_event->private_data, offset);
965+
ret = conn_id->id.event_handler(&conn_id->id, &event);
947966
if (!ret)
948967
goto out;
949968

@@ -1019,36 +1038,38 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
10191038
static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
10201039
{
10211040
struct rdma_id_private *id_priv = iw_id->context;
1022-
enum rdma_cm_event_type event = 0;
1041+
struct rdma_cm_event event;
10231042
struct sockaddr_in *sin;
10241043
int ret = 0;
10251044

1045+
memset(&event, 0, sizeof event);
10261046
atomic_inc(&id_priv->dev_remove);
10271047

10281048
switch (iw_event->event) {
10291049
case IW_CM_EVENT_CLOSE:
1030-
event = RDMA_CM_EVENT_DISCONNECTED;
1050+
event.event = RDMA_CM_EVENT_DISCONNECTED;
10311051
break;
10321052
case IW_CM_EVENT_CONNECT_REPLY:
10331053
sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
10341054
*sin = iw_event->local_addr;
10351055
sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr;
10361056
*sin = iw_event->remote_addr;
10371057
if (iw_event->status)
1038-
event = RDMA_CM_EVENT_REJECTED;
1058+
event.event = RDMA_CM_EVENT_REJECTED;
10391059
else
1040-
event = RDMA_CM_EVENT_ESTABLISHED;
1060+
event.event = RDMA_CM_EVENT_ESTABLISHED;
10411061
break;
10421062
case IW_CM_EVENT_ESTABLISHED:
1043-
event = RDMA_CM_EVENT_ESTABLISHED;
1063+
event.event = RDMA_CM_EVENT_ESTABLISHED;
10441064
break;
10451065
default:
10461066
BUG_ON(1);
10471067
}
10481068

1049-
ret = cma_notify_user(id_priv, event, iw_event->status,
1050-
iw_event->private_data,
1051-
iw_event->private_data_len);
1069+
event.status = iw_event->status;
1070+
event.param.conn.private_data = iw_event->private_data;
1071+
event.param.conn.private_data_len = iw_event->private_data_len;
1072+
ret = id_priv->id.event_handler(&id_priv->id, &event);
10521073
if (ret) {
10531074
/* Destroy the CM ID by returning a non-zero value. */
10541075
id_priv->cm_id.iw = NULL;
@@ -1069,6 +1090,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
10691090
struct rdma_id_private *listen_id, *conn_id;
10701091
struct sockaddr_in *sin;
10711092
struct net_device *dev = NULL;
1093+
struct rdma_cm_event event;
10721094
int ret;
10731095

10741096
listen_id = cm_id->context;
@@ -1122,9 +1144,11 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
11221144
sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
11231145
*sin = iw_event->remote_addr;
11241146

1125-
ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
1126-
iw_event->private_data,
1127-
iw_event->private_data_len);
1147+
memset(&event, 0, sizeof event);
1148+
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
1149+
event.param.conn.private_data = iw_event->private_data;
1150+
event.param.conn.private_data_len = iw_event->private_data_len;
1151+
ret = conn_id->id.event_handler(&conn_id->id, &event);
11281152
if (ret) {
11291153
/* User wants to destroy the CM ID */
11301154
conn_id->cm_id.iw = NULL;
@@ -1513,8 +1537,9 @@ static void addr_handler(int status, struct sockaddr *src_addr,
15131537
struct rdma_dev_addr *dev_addr, void *context)
15141538
{
15151539
struct rdma_id_private *id_priv = context;
1516-
enum rdma_cm_event_type event;
1540+
struct rdma_cm_event event;
15171541

1542+
memset(&event, 0, sizeof event);
15181543
atomic_inc(&id_priv->dev_remove);
15191544

15201545
/*
@@ -1534,14 +1559,15 @@ static void addr_handler(int status, struct sockaddr *src_addr,
15341559
if (status) {
15351560
if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
15361561
goto out;
1537-
event = RDMA_CM_EVENT_ADDR_ERROR;
1562+
event.event = RDMA_CM_EVENT_ADDR_ERROR;
1563+
event.status = status;
15381564
} else {
15391565
memcpy(&id_priv->id.route.addr.src_addr, src_addr,
15401566
ip_addr_size(src_addr));
1541-
event = RDMA_CM_EVENT_ADDR_RESOLVED;
1567+
event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
15421568
}
15431569

1544-
if (cma_notify_user(id_priv, event, status, NULL, 0)) {
1570+
if (id_priv->id.event_handler(&id_priv->id, &event)) {
15451571
cma_exch(id_priv, CMA_DESTROYING);
15461572
cma_release_remove(id_priv);
15471573
cma_deref_id(id_priv);
@@ -2132,6 +2158,7 @@ static void cma_add_one(struct ib_device *device)
21322158

21332159
static int cma_remove_id_dev(struct rdma_id_private *id_priv)
21342160
{
2161+
struct rdma_cm_event event;
21352162
enum cma_state state;
21362163

21372164
/* Record that we want to remove the device */
@@ -2146,8 +2173,9 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
21462173
if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
21472174
return 0;
21482175

2149-
return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
2150-
0, NULL, 0);
2176+
memset(&event, 0, sizeof event);
2177+
event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
2178+
return id_priv->id.event_handler(&id_priv->id, &event);
21512179
}
21522180

21532181
static void cma_process_remove(struct cma_device *cma_dev)

include/rdma/rdma_cm.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,25 @@ struct rdma_route {
7777
int num_paths;
7878
};
7979

80+
struct rdma_conn_param {
81+
const void *private_data;
82+
u8 private_data_len;
83+
u8 responder_resources;
84+
u8 initiator_depth;
85+
u8 flow_control;
86+
u8 retry_count; /* ignored when accepting */
87+
u8 rnr_retry_count;
88+
/* Fields below ignored if a QP is created on the rdma_cm_id. */
89+
u8 srq;
90+
u32 qp_num;
91+
};
92+
8093
struct rdma_cm_event {
8194
enum rdma_cm_event_type event;
8295
int status;
83-
void *private_data;
84-
u8 private_data_len;
96+
union {
97+
struct rdma_conn_param conn;
98+
} param;
8599
};
86100

87101
struct rdma_cm_id;
@@ -204,19 +218,6 @@ void rdma_destroy_qp(struct rdma_cm_id *id);
204218
int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
205219
int *qp_attr_mask);
206220

207-
struct rdma_conn_param {
208-
const void *private_data;
209-
u8 private_data_len;
210-
u8 responder_resources;
211-
u8 initiator_depth;
212-
u8 flow_control;
213-
u8 retry_count; /* ignored when accepting */
214-
u8 rnr_retry_count;
215-
/* Fields below ignored if a QP is created on the rdma_cm_id. */
216-
u8 srq;
217-
u32 qp_num;
218-
};
219-
220221
/**
221222
* rdma_connect - Initiate an active connection request.
222223
*

0 commit comments

Comments
 (0)