2
* Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
12
* Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in
14
* the documentation and/or other materials provided with the
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
* OF THE POSSIBILITY OF SUCH DAMAGE.
31
FILE_LICENCE ( BSD2 );
36
#include <gpxe/infiniband.h>
37
#include <gpxe/ib_cmrc.h>
38
#include <gpxe/ib_srp.h>
43
* SCSI RDMA Protocol over Infiniband
47
/* Disambiguate the various possible EINVALs */
48
#define EINVAL_BYTE_STRING_LEN ( EINVAL | EUNIQ_01 )
49
#define EINVAL_BYTE_STRING ( EINVAL | EUNIQ_02 )
50
#define EINVAL_INTEGER ( EINVAL | EUNIQ_03 )
51
#define EINVAL_RP_TOO_SHORT ( EINVAL | EUNIQ_04 )
53
/** IB SRP parse flags */
54
enum ib_srp_parse_flags {
55
IB_SRP_PARSE_REQUIRED = 0x0000,
56
IB_SRP_PARSE_OPTIONAL = 0x8000,
57
IB_SRP_PARSE_FLAG_MASK = 0xf000,
60
/** IB SRP root path parameters */
61
struct ib_srp_root_path {
65
struct srp_port_ids *port_ids;
66
/** IB SRP parameters */
67
struct ib_srp_parameters *ib;
71
* Parse IB SRP root path byte-string value
73
* @v rp_comp Root path component string
74
* @v default_value Default value to use if component string is empty
77
static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
78
unsigned int size_flags ) {
79
size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
80
size_t rp_comp_len = strlen ( rp_comp );
84
/* Allow optional components to be empty */
85
if ( ( rp_comp_len == 0 ) &&
86
( size_flags & IB_SRP_PARSE_OPTIONAL ) )
89
/* Check string length */
90
if ( rp_comp_len != ( 2 * size ) )
91
return -EINVAL_BYTE_STRING_LEN;
93
/* Parse byte string */
94
for ( ; size ; size--, rp_comp += 2, bytes++ ) {
95
memcpy ( buf, rp_comp, 2 );
97
*bytes = strtoul ( buf, &buf_end, 16 );
98
if ( buf_end != &buf[2] )
99
return -EINVAL_BYTE_STRING;
105
* Parse IB SRP root path integer value
107
* @v rp_comp Root path component string
108
* @v default_value Default value to use if component string is empty
111
static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
115
value = strtoul ( rp_comp, &end, 16 );
117
return -EINVAL_INTEGER;
119
if ( end == rp_comp )
120
return default_value;
126
* Parse IB SRP root path literal component
128
* @v rp_comp Root path component string
129
* @v rp IB SRP root path
130
* @ret rc Return status code
132
static int ib_srp_parse_literal ( const char *rp_comp __unused,
133
struct ib_srp_root_path *rp __unused ) {
139
* Parse IB SRP root path source GID
141
* @v rp_comp Root path component string
142
* @v rp IB SRP root path
143
* @ret rc Return status code
145
static int ib_srp_parse_sgid ( const char *rp_comp,
146
struct ib_srp_root_path *rp ) {
147
struct ib_device *ibdev;
149
/* Default to the GID of the last opened Infiniband device */
150
if ( ( ibdev = last_opened_ibdev() ) != NULL )
151
memcpy ( &rp->ib->sgid, &ibdev->gid, sizeof ( rp->ib->sgid ) );
153
return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
154
( sizeof ( rp->ib->sgid ) |
155
IB_SRP_PARSE_OPTIONAL ) );
159
* Parse IB SRP root path initiator identifier extension
161
* @v rp_comp Root path component string
162
* @v rp IB SRP root path
163
* @ret rc Return status code
165
static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
166
struct ib_srp_root_path *rp ) {
167
struct ib_srp_initiator_port_id *port_id =
168
ib_srp_initiator_port_id ( rp->port_ids );
170
return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
171
( sizeof ( port_id->id_ext ) |
172
IB_SRP_PARSE_OPTIONAL ) );
176
* Parse IB SRP root path initiator HCA GUID
178
* @v rp_comp Root path component string
179
* @v rp IB SRP root path
180
* @ret rc Return status code
182
static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
183
struct ib_srp_root_path *rp ) {
184
struct ib_srp_initiator_port_id *port_id =
185
ib_srp_initiator_port_id ( rp->port_ids );
187
/* Default to the GUID portion of the source GID */
188
memcpy ( &port_id->hca_guid, &rp->ib->sgid.u.half[1],
189
sizeof ( port_id->hca_guid ) );
191
return ib_srp_parse_byte_string ( rp_comp, port_id->hca_guid.u.bytes,
192
( sizeof ( port_id->hca_guid ) |
193
IB_SRP_PARSE_OPTIONAL ) );
197
* Parse IB SRP root path destination GID
199
* @v rp_comp Root path component string
200
* @v rp IB SRP root path
201
* @ret rc Return status code
203
static int ib_srp_parse_dgid ( const char *rp_comp,
204
struct ib_srp_root_path *rp ) {
205
return ib_srp_parse_byte_string ( rp_comp, rp->ib->dgid.u.bytes,
206
( sizeof ( rp->ib->dgid ) |
207
IB_SRP_PARSE_REQUIRED ) );
211
* Parse IB SRP root path partition key
213
* @v rp_comp Root path component string
214
* @v rp IB SRP root path
215
* @ret rc Return status code
217
static int ib_srp_parse_pkey ( const char *rp_comp,
218
struct ib_srp_root_path *rp ) {
221
if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_NONE ) ) < 0 )
228
* Parse IB SRP root path service ID
230
* @v rp_comp Root path component string
231
* @v rp IB SRP root path
232
* @ret rc Return status code
234
static int ib_srp_parse_service_id ( const char *rp_comp,
235
struct ib_srp_root_path *rp ) {
236
return ib_srp_parse_byte_string ( rp_comp, rp->ib->service_id.u.bytes,
237
( sizeof ( rp->ib->service_id ) |
238
IB_SRP_PARSE_REQUIRED ) );
242
* Parse IB SRP root path LUN
244
* @v rp_comp Root path component string
245
* @v rp IB SRP root path
246
* @ret rc Return status code
248
static int ib_srp_parse_lun ( const char *rp_comp,
249
struct ib_srp_root_path *rp ) {
250
return scsi_parse_lun ( rp_comp, rp->lun );
254
* Parse IB SRP root path target identifier extension
256
* @v rp_comp Root path component string
257
* @v rp IB SRP root path
258
* @ret rc Return status code
260
static int ib_srp_parse_target_id_ext ( const char *rp_comp,
261
struct ib_srp_root_path *rp ) {
262
struct ib_srp_target_port_id *port_id =
263
ib_srp_target_port_id ( rp->port_ids );
265
return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
266
( sizeof ( port_id->id_ext ) |
267
IB_SRP_PARSE_REQUIRED ) );
271
* Parse IB SRP root path target I/O controller GUID
273
* @v rp_comp Root path component string
274
* @v rp IB SRP root path
275
* @ret rc Return status code
277
static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
278
struct ib_srp_root_path *rp ) {
279
struct ib_srp_target_port_id *port_id =
280
ib_srp_target_port_id ( rp->port_ids );
282
return ib_srp_parse_byte_string ( rp_comp, port_id->ioc_guid.u.bytes,
283
( sizeof ( port_id->ioc_guid ) |
284
IB_SRP_PARSE_REQUIRED ) );
287
/** IB SRP root path component parser */
288
struct ib_srp_root_path_parser {
290
* Parse IB SRP root path component
292
* @v rp_comp Root path component string
293
* @v rp IB SRP root path
294
* @ret rc Return status code
296
int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
299
/** IB SRP root path components */
300
static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
301
{ ib_srp_parse_literal },
302
{ ib_srp_parse_sgid },
303
{ ib_srp_parse_initiator_id_ext },
304
{ ib_srp_parse_initiator_hca_guid },
305
{ ib_srp_parse_dgid },
306
{ ib_srp_parse_pkey },
307
{ ib_srp_parse_service_id },
308
{ ib_srp_parse_lun },
309
{ ib_srp_parse_target_id_ext },
310
{ ib_srp_parse_target_ioc_guid },
313
/** Number of IB SRP root path components */
314
#define IB_SRP_NUM_RP_COMPONENTS \
315
( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
318
* Parse IB SRP root path
321
* @v rp_string Root path
322
* @ret rc Return status code
324
static int ib_srp_parse_root_path ( struct srp_device *srp,
325
const char *rp_string ) {
326
struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
327
struct ib_srp_root_path rp = {
329
.port_ids = &srp->port_ids,
332
char rp_string_copy[ strlen ( rp_string ) + 1 ];
333
char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
334
char *rp_string_tmp = rp_string_copy;
338
/* Split root path into component parts */
339
strcpy ( rp_string_copy, rp_string );
341
rp_comp[i++] = rp_string_tmp;
342
if ( i == IB_SRP_NUM_RP_COMPONENTS )
344
for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
345
if ( ! *rp_string_tmp ) {
346
DBGC ( srp, "SRP %p root path \"%s\" too "
347
"short\n", srp, rp_string );
348
return -EINVAL_RP_TOO_SHORT;
351
*(rp_string_tmp++) = '\0';
354
/* Parse root path components */
355
for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
356
if ( ( rc = ib_srp_rp_parser[i].parse ( rp_comp[i],
358
DBGC ( srp, "SRP %p could not parse \"%s\" in root "
359
"path \"%s\": %s\n", srp, rp_comp[i],
360
rp_string, strerror ( rc ) );
369
* Connect IB SRP session
372
* @ret rc Return status code
374
static int ib_srp_connect ( struct srp_device *srp ) {
375
struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
376
struct ib_device *ibdev;
379
/* Identify Infiniband device */
380
ibdev = find_ibdev ( &ib_params->sgid );
382
DBGC ( srp, "SRP %p could not identify Infiniband device\n",
387
/* Configure remaining SRP parameters */
388
srp->memory_handle = ibdev->rdma_key;
390
/* Open CMRC socket */
391
if ( ( rc = ib_cmrc_open ( &srp->socket, ibdev, &ib_params->dgid,
392
&ib_params->service_id ) ) != 0 ) {
393
DBGC ( srp, "SRP %p could not open CMRC socket: %s\n",
394
srp, strerror ( rc ) );
401
/** IB SRP transport type */
402
struct srp_transport_type ib_srp_transport = {
403
.priv_len = sizeof ( struct ib_srp_parameters ),
404
.parse_root_path = ib_srp_parse_root_path,
405
.connect = ib_srp_connect,