00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 FILE_LICENCE ( BSD2 );
00032
00033 #include <stdlib.h>
00034 #include <errno.h>
00035 #include <gpxe/srp.h>
00036 #include <gpxe/infiniband.h>
00037 #include <gpxe/ib_cmrc.h>
00038 #include <gpxe/ib_srp.h>
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define EINVAL_BYTE_STRING_LEN ( EINVAL | EUNIQ_01 )
00049 #define EINVAL_BYTE_STRING ( EINVAL | EUNIQ_02 )
00050 #define EINVAL_INTEGER ( EINVAL | EUNIQ_03 )
00051 #define EINVAL_RP_TOO_SHORT ( EINVAL | EUNIQ_04 )
00052
00053
00054 enum ib_srp_parse_flags {
00055 IB_SRP_PARSE_REQUIRED = 0x0000,
00056 IB_SRP_PARSE_OPTIONAL = 0x8000,
00057 IB_SRP_PARSE_FLAG_MASK = 0xf000,
00058 };
00059
00060
00061 struct ib_srp_root_path {
00062
00063 struct scsi_lun *lun;
00064
00065 struct srp_port_ids *port_ids;
00066
00067 struct ib_srp_parameters *ib;
00068 };
00069
00070
00071
00072
00073
00074
00075
00076
00077 static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
00078 unsigned int size_flags ) {
00079 size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
00080 size_t rp_comp_len = strlen ( rp_comp );
00081 char buf[3];
00082 char *buf_end;
00083
00084
00085 if ( ( rp_comp_len == 0 ) &&
00086 ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
00087 return 0;
00088
00089
00090 if ( rp_comp_len != ( 2 * size ) )
00091 return -EINVAL_BYTE_STRING_LEN;
00092
00093
00094 for ( ; size ; size--, rp_comp += 2, bytes++ ) {
00095 memcpy ( buf, rp_comp, 2 );
00096 buf[2] = '\0';
00097 *bytes = strtoul ( buf, &buf_end, 16 );
00098 if ( buf_end != &buf[2] )
00099 return -EINVAL_BYTE_STRING;
00100 }
00101 return 0;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111 static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
00112 int value;
00113 char *end;
00114
00115 value = strtoul ( rp_comp, &end, 16 );
00116 if ( *end )
00117 return -EINVAL_INTEGER;
00118
00119 if ( end == rp_comp )
00120 return default_value;
00121
00122 return value;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132 static int ib_srp_parse_literal ( const char *rp_comp __unused,
00133 struct ib_srp_root_path *rp __unused ) {
00134
00135 return 0;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145 static int ib_srp_parse_sgid ( const char *rp_comp,
00146 struct ib_srp_root_path *rp ) {
00147 struct ib_device *ibdev;
00148
00149
00150 if ( ( ibdev = last_opened_ibdev() ) != NULL )
00151 memcpy ( &rp->ib->sgid, &ibdev->gid, sizeof ( rp->ib->sgid ) );
00152
00153 return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
00154 ( sizeof ( rp->ib->sgid ) |
00155 IB_SRP_PARSE_OPTIONAL ) );
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165 static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
00166 struct ib_srp_root_path *rp ) {
00167 struct ib_srp_initiator_port_id *port_id =
00168 ib_srp_initiator_port_id ( rp->port_ids );
00169
00170 return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
00171 ( sizeof ( port_id->id_ext ) |
00172 IB_SRP_PARSE_OPTIONAL ) );
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182 static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
00183 struct ib_srp_root_path *rp ) {
00184 struct ib_srp_initiator_port_id *port_id =
00185 ib_srp_initiator_port_id ( rp->port_ids );
00186
00187
00188 memcpy ( &port_id->hca_guid, &rp->ib->sgid.u.half[1],
00189 sizeof ( port_id->hca_guid ) );
00190
00191 return ib_srp_parse_byte_string ( rp_comp, port_id->hca_guid.u.bytes,
00192 ( sizeof ( port_id->hca_guid ) |
00193 IB_SRP_PARSE_OPTIONAL ) );
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203 static int ib_srp_parse_dgid ( const char *rp_comp,
00204 struct ib_srp_root_path *rp ) {
00205 return ib_srp_parse_byte_string ( rp_comp, rp->ib->dgid.u.bytes,
00206 ( sizeof ( rp->ib->dgid ) |
00207 IB_SRP_PARSE_REQUIRED ) );
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217 static int ib_srp_parse_pkey ( const char *rp_comp,
00218 struct ib_srp_root_path *rp ) {
00219 int pkey;
00220
00221 if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
00222 return pkey;
00223 rp->ib->pkey = pkey;
00224 return 0;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 static int ib_srp_parse_service_id ( const char *rp_comp,
00235 struct ib_srp_root_path *rp ) {
00236 return ib_srp_parse_byte_string ( rp_comp, rp->ib->service_id.u.bytes,
00237 ( sizeof ( rp->ib->service_id ) |
00238 IB_SRP_PARSE_REQUIRED ) );
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 static int ib_srp_parse_lun ( const char *rp_comp,
00249 struct ib_srp_root_path *rp ) {
00250 return scsi_parse_lun ( rp_comp, rp->lun );
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 static int ib_srp_parse_target_id_ext ( const char *rp_comp,
00261 struct ib_srp_root_path *rp ) {
00262 struct ib_srp_target_port_id *port_id =
00263 ib_srp_target_port_id ( rp->port_ids );
00264
00265 return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
00266 ( sizeof ( port_id->id_ext ) |
00267 IB_SRP_PARSE_REQUIRED ) );
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
00278 struct ib_srp_root_path *rp ) {
00279 struct ib_srp_target_port_id *port_id =
00280 ib_srp_target_port_id ( rp->port_ids );
00281
00282 return ib_srp_parse_byte_string ( rp_comp, port_id->ioc_guid.u.bytes,
00283 ( sizeof ( port_id->ioc_guid ) |
00284 IB_SRP_PARSE_REQUIRED ) );
00285 }
00286
00287
00288 struct ib_srp_root_path_parser {
00289
00290
00291
00292
00293
00294
00295
00296 int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
00297 };
00298
00299
00300 static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
00301 { ib_srp_parse_literal },
00302 { ib_srp_parse_sgid },
00303 { ib_srp_parse_initiator_id_ext },
00304 { ib_srp_parse_initiator_hca_guid },
00305 { ib_srp_parse_dgid },
00306 { ib_srp_parse_pkey },
00307 { ib_srp_parse_service_id },
00308 { ib_srp_parse_lun },
00309 { ib_srp_parse_target_id_ext },
00310 { ib_srp_parse_target_ioc_guid },
00311 };
00312
00313
00314 #define IB_SRP_NUM_RP_COMPONENTS \
00315 ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
00316
00317
00318
00319
00320
00321
00322
00323
00324 static int ib_srp_parse_root_path ( struct srp_device *srp,
00325 const char *rp_string ) {
00326 struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
00327 struct ib_srp_root_path rp = {
00328 .lun = &srp->lun,
00329 .port_ids = &srp->port_ids,
00330 .ib = ib_params,
00331 };
00332 char rp_string_copy[ strlen ( rp_string ) + 1 ];
00333 char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
00334 char *rp_string_tmp = rp_string_copy;
00335 unsigned int i = 0;
00336 int rc;
00337
00338
00339 strcpy ( rp_string_copy, rp_string );
00340 while ( 1 ) {
00341 rp_comp[i++] = rp_string_tmp;
00342 if ( i == IB_SRP_NUM_RP_COMPONENTS )
00343 break;
00344 for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
00345 if ( ! *rp_string_tmp ) {
00346 DBGC ( srp, "SRP %p root path \"%s\" too "
00347 "short\n", srp, rp_string );
00348 return -EINVAL_RP_TOO_SHORT;
00349 }
00350 }
00351 *(rp_string_tmp++) = '\0';
00352 }
00353
00354
00355 for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
00356 if ( ( rc = ib_srp_rp_parser[i].parse ( rp_comp[i],
00357 &rp ) ) != 0 ) {
00358 DBGC ( srp, "SRP %p could not parse \"%s\" in root "
00359 "path \"%s\": %s\n", srp, rp_comp[i],
00360 rp_string, strerror ( rc ) );
00361 return rc;
00362 }
00363 }
00364
00365 return 0;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 static int ib_srp_connect ( struct srp_device *srp ) {
00375 struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
00376 struct ib_device *ibdev;
00377 int rc;
00378
00379
00380 ibdev = find_ibdev ( &ib_params->sgid );
00381 if ( ! ibdev ) {
00382 DBGC ( srp, "SRP %p could not identify Infiniband device\n",
00383 srp );
00384 return -ENODEV;
00385 }
00386
00387
00388 srp->memory_handle = ibdev->rdma_key;
00389
00390
00391 if ( ( rc = ib_cmrc_open ( &srp->socket, ibdev, &ib_params->dgid,
00392 &ib_params->service_id ) ) != 0 ) {
00393 DBGC ( srp, "SRP %p could not open CMRC socket: %s\n",
00394 srp, strerror ( rc ) );
00395 return rc;
00396 }
00397
00398 return 0;
00399 }
00400
00401
00402 struct srp_transport_type ib_srp_transport = {
00403 .priv_len = sizeof ( struct ib_srp_parameters ),
00404 .parse_root_path = ib_srp_parse_root_path,
00405 .connect = ib_srp_connect,
00406 };