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_DEFAULT
) ) < 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
,