@@ -263,6 +263,15 @@ struct cma_hdr {
263
263
264
264
#define CMA_VERSION 0x00
265
265
266
+ struct cma_req_info {
267
+ struct ib_device * device ;
268
+ int port ;
269
+ union ib_gid local_gid ;
270
+ __be64 service_id ;
271
+ u16 pkey ;
272
+ bool has_gid :1 ;
273
+ };
274
+
266
275
static int cma_comp (struct rdma_id_private * id_priv , enum rdma_cm_state comp )
267
276
{
268
277
unsigned long flags ;
@@ -300,7 +309,7 @@ static enum rdma_cm_state cma_exch(struct rdma_id_private *id_priv,
300
309
return old ;
301
310
}
302
311
303
- static inline u8 cma_get_ip_ver (struct cma_hdr * hdr )
312
+ static inline u8 cma_get_ip_ver (const struct cma_hdr * hdr )
304
313
{
305
314
return hdr -> ip_version >> 4 ;
306
315
}
@@ -1016,7 +1025,7 @@ static int cma_save_ip_info(struct sockaddr *src_addr,
1016
1025
cma_save_ip6_info (src_addr , dst_addr , hdr , port );
1017
1026
break ;
1018
1027
default :
1019
- return - EINVAL ;
1028
+ return - EAFNOSUPPORT ;
1020
1029
}
1021
1030
1022
1031
return 0 ;
@@ -1040,6 +1049,176 @@ static int cma_save_net_info(struct sockaddr *src_addr,
1040
1049
return cma_save_ip_info (src_addr , dst_addr , ib_event , service_id );
1041
1050
}
1042
1051
1052
+ static int cma_save_req_info (const struct ib_cm_event * ib_event ,
1053
+ struct cma_req_info * req )
1054
+ {
1055
+ const struct ib_cm_req_event_param * req_param =
1056
+ & ib_event -> param .req_rcvd ;
1057
+ const struct ib_cm_sidr_req_event_param * sidr_param =
1058
+ & ib_event -> param .sidr_req_rcvd ;
1059
+
1060
+ switch (ib_event -> event ) {
1061
+ case IB_CM_REQ_RECEIVED :
1062
+ req -> device = req_param -> listen_id -> device ;
1063
+ req -> port = req_param -> port ;
1064
+ memcpy (& req -> local_gid , & req_param -> primary_path -> sgid ,
1065
+ sizeof (req -> local_gid ));
1066
+ req -> has_gid = true;
1067
+ req -> service_id = req_param -> primary_path -> service_id ;
1068
+ req -> pkey = req_param -> bth_pkey ;
1069
+ break ;
1070
+ case IB_CM_SIDR_REQ_RECEIVED :
1071
+ req -> device = sidr_param -> listen_id -> device ;
1072
+ req -> port = sidr_param -> port ;
1073
+ req -> has_gid = false;
1074
+ req -> service_id = sidr_param -> service_id ;
1075
+ req -> pkey = sidr_param -> bth_pkey ;
1076
+ break ;
1077
+ default :
1078
+ return - EINVAL ;
1079
+ }
1080
+
1081
+ return 0 ;
1082
+ }
1083
+
1084
+ static struct net_device * cma_get_net_dev (struct ib_cm_event * ib_event ,
1085
+ const struct cma_req_info * req )
1086
+ {
1087
+ struct sockaddr_storage listen_addr_storage ;
1088
+ struct sockaddr * listen_addr = (struct sockaddr * )& listen_addr_storage ;
1089
+ struct net_device * net_dev ;
1090
+ const union ib_gid * gid = req -> has_gid ? & req -> local_gid : NULL ;
1091
+ int err ;
1092
+
1093
+ err = cma_save_ip_info (listen_addr , NULL , ib_event , req -> service_id );
1094
+ if (err )
1095
+ return ERR_PTR (err );
1096
+
1097
+ net_dev = ib_get_net_dev_by_params (req -> device , req -> port , req -> pkey ,
1098
+ gid , listen_addr );
1099
+ if (!net_dev )
1100
+ return ERR_PTR (- ENODEV );
1101
+
1102
+ return net_dev ;
1103
+ }
1104
+
1105
+ static enum rdma_port_space rdma_ps_from_service_id (__be64 service_id )
1106
+ {
1107
+ return (be64_to_cpu (service_id ) >> 16 ) & 0xffff ;
1108
+ }
1109
+
1110
+ static bool cma_match_private_data (struct rdma_id_private * id_priv ,
1111
+ const struct cma_hdr * hdr )
1112
+ {
1113
+ struct sockaddr * addr = cma_src_addr (id_priv );
1114
+ __be32 ip4_addr ;
1115
+ struct in6_addr ip6_addr ;
1116
+
1117
+ if (cma_any_addr (addr ) && !id_priv -> afonly )
1118
+ return true;
1119
+
1120
+ switch (addr -> sa_family ) {
1121
+ case AF_INET :
1122
+ ip4_addr = ((struct sockaddr_in * )addr )-> sin_addr .s_addr ;
1123
+ if (cma_get_ip_ver (hdr ) != 4 )
1124
+ return false;
1125
+ if (!cma_any_addr (addr ) &&
1126
+ hdr -> dst_addr .ip4 .addr != ip4_addr )
1127
+ return false;
1128
+ break ;
1129
+ case AF_INET6 :
1130
+ ip6_addr = ((struct sockaddr_in6 * )addr )-> sin6_addr ;
1131
+ if (cma_get_ip_ver (hdr ) != 6 )
1132
+ return false;
1133
+ if (!cma_any_addr (addr ) &&
1134
+ memcmp (& hdr -> dst_addr .ip6 , & ip6_addr , sizeof (ip6_addr )))
1135
+ return false;
1136
+ break ;
1137
+ case AF_IB :
1138
+ return true;
1139
+ default :
1140
+ return false;
1141
+ }
1142
+
1143
+ return true;
1144
+ }
1145
+
1146
+ static bool cma_match_net_dev (const struct rdma_id_private * id_priv ,
1147
+ const struct net_device * net_dev )
1148
+ {
1149
+ const struct rdma_addr * addr = & id_priv -> id .route .addr ;
1150
+
1151
+ if (!net_dev )
1152
+ /* This request is an AF_IB request */
1153
+ return addr -> src_addr .ss_family == AF_IB ;
1154
+
1155
+ return !addr -> dev_addr .bound_dev_if ||
1156
+ (net_eq (dev_net (net_dev ), & init_net ) &&
1157
+ addr -> dev_addr .bound_dev_if == net_dev -> ifindex );
1158
+ }
1159
+
1160
+ static struct rdma_id_private * cma_find_listener (
1161
+ const struct rdma_bind_list * bind_list ,
1162
+ const struct ib_cm_id * cm_id ,
1163
+ const struct ib_cm_event * ib_event ,
1164
+ const struct cma_req_info * req ,
1165
+ const struct net_device * net_dev )
1166
+ {
1167
+ struct rdma_id_private * id_priv , * id_priv_dev ;
1168
+
1169
+ if (!bind_list )
1170
+ return ERR_PTR (- EINVAL );
1171
+
1172
+ hlist_for_each_entry (id_priv , & bind_list -> owners , node ) {
1173
+ if (cma_match_private_data (id_priv , ib_event -> private_data )) {
1174
+ if (id_priv -> id .device == cm_id -> device &&
1175
+ cma_match_net_dev (id_priv , net_dev ))
1176
+ return id_priv ;
1177
+ list_for_each_entry (id_priv_dev ,
1178
+ & id_priv -> listen_list ,
1179
+ listen_list ) {
1180
+ if (id_priv_dev -> id .device == cm_id -> device &&
1181
+ cma_match_net_dev (id_priv_dev , net_dev ))
1182
+ return id_priv_dev ;
1183
+ }
1184
+ }
1185
+ }
1186
+
1187
+ return ERR_PTR (- EINVAL );
1188
+ }
1189
+
1190
+ static struct rdma_id_private * cma_id_from_event (struct ib_cm_id * cm_id ,
1191
+ struct ib_cm_event * ib_event )
1192
+ {
1193
+ struct cma_req_info req ;
1194
+ struct rdma_bind_list * bind_list ;
1195
+ struct rdma_id_private * id_priv ;
1196
+ struct net_device * net_dev ;
1197
+ int err ;
1198
+
1199
+ err = cma_save_req_info (ib_event , & req );
1200
+ if (err )
1201
+ return ERR_PTR (err );
1202
+
1203
+ net_dev = cma_get_net_dev (ib_event , & req );
1204
+ if (IS_ERR (net_dev )) {
1205
+ if (PTR_ERR (net_dev ) == - EAFNOSUPPORT ) {
1206
+ /* Assuming the protocol is AF_IB */
1207
+ net_dev = NULL ;
1208
+ } else {
1209
+ return ERR_CAST (net_dev );
1210
+ }
1211
+ }
1212
+
1213
+ bind_list = cma_ps_find (rdma_ps_from_service_id (req .service_id ),
1214
+ cma_port_from_service_id (req .service_id ));
1215
+ id_priv = cma_find_listener (bind_list , cm_id , ib_event , & req , net_dev );
1216
+
1217
+ dev_put (net_dev );
1218
+
1219
+ return id_priv ;
1220
+ }
1221
+
1043
1222
static inline int cma_user_data_offset (struct rdma_id_private * id_priv )
1044
1223
{
1045
1224
return cma_family (id_priv ) == AF_IB ? 0 : sizeof (struct cma_hdr );
@@ -1399,7 +1578,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
1399
1578
struct rdma_cm_event event ;
1400
1579
int offset , ret ;
1401
1580
1402
- listen_id = cm_id -> context ;
1581
+ listen_id = cma_id_from_event (cm_id , ib_event );
1582
+ if (IS_ERR (listen_id ))
1583
+ return PTR_ERR (listen_id );
1584
+
1403
1585
if (!cma_check_req_qp_type (& listen_id -> id , ib_event ))
1404
1586
return - EINVAL ;
1405
1587
0 commit comments