[infiniband] Rename IB_PKEY_NONE to IB_PKEY_DEFAULT
[people/peper/gpxe.git] / src / net / infiniband / ib_srp.c
1 /*
2  * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
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
15  *   distribution.
16  *
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.
29  */
30
31 FILE_LICENCE ( BSD2 );
32
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <gpxe/srp.h>
36 #include <gpxe/infiniband.h>
37 #include <gpxe/ib_cmrc.h>
38 #include <gpxe/ib_srp.h>
39
40 /**
41  * @file
42  *
43  * SCSI RDMA Protocol over Infiniband
44  *
45  */
46
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 )
52
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,
58 };
59
60 /** IB SRP root path parameters */
61 struct ib_srp_root_path {
62         /** SCSI LUN */
63         struct scsi_lun *lun;
64         /** SRP port IDs */
65         struct srp_port_ids *port_ids;
66         /** IB SRP parameters */
67         struct ib_srp_parameters *ib;
68 };
69
70 /**
71  * Parse IB SRP root path byte-string value
72  *
73  * @v rp_comp           Root path component string
74  * @v default_value     Default value to use if component string is empty
75  * @ret value           Value
76  */
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 );
81         char buf[3];
82         char *buf_end;
83
84         /* Allow optional components to be empty */
85         if ( ( rp_comp_len == 0 ) &&
86              ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
87                 return 0;
88
89         /* Check string length */
90         if ( rp_comp_len != ( 2 * size ) )
91                 return -EINVAL_BYTE_STRING_LEN;
92
93         /* Parse byte string */
94         for ( ; size ; size--, rp_comp += 2, bytes++ ) {
95                 memcpy ( buf, rp_comp, 2 );
96                 buf[2] = '\0';
97                 *bytes = strtoul ( buf, &buf_end, 16 );
98                 if ( buf_end != &buf[2] )
99                         return -EINVAL_BYTE_STRING;
100         }
101         return 0;
102 }
103
104 /**
105  * Parse IB SRP root path integer value
106  *
107  * @v rp_comp           Root path component string
108  * @v default_value     Default value to use if component string is empty
109  * @ret value           Value
110  */
111 static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
112         int value;
113         char *end;
114
115         value = strtoul ( rp_comp, &end, 16 );
116         if ( *end )
117                 return -EINVAL_INTEGER;
118
119         if ( end == rp_comp )
120                 return default_value;
121
122         return value;
123 }
124
125 /**
126  * Parse IB SRP root path literal component
127  *
128  * @v rp_comp           Root path component string
129  * @v rp                IB SRP root path
130  * @ret rc              Return status code
131  */
132 static int ib_srp_parse_literal ( const char *rp_comp __unused,
133                                   struct ib_srp_root_path *rp __unused ) {
134         /* Ignore */
135         return 0;
136 }
137
138 /**
139  * Parse IB SRP root path source GID
140  *
141  * @v rp_comp           Root path component string
142  * @v rp                IB SRP root path
143  * @ret rc              Return status code
144  */
145 static int ib_srp_parse_sgid ( const char *rp_comp,
146                                struct ib_srp_root_path *rp ) {
147         struct ib_device *ibdev;
148
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 ) );
152
153         return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
154                                           ( sizeof ( rp->ib->sgid ) |
155                                             IB_SRP_PARSE_OPTIONAL ) );
156 }
157
158 /**
159  * Parse IB SRP root path initiator identifier extension
160  *
161  * @v rp_comp           Root path component string
162  * @v rp                IB SRP root path
163  * @ret rc              Return status code
164  */
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 );
169
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 ) );
173 }
174
175 /**
176  * Parse IB SRP root path initiator HCA GUID
177  *
178  * @v rp_comp           Root path component string
179  * @v rp                IB SRP root path
180  * @ret rc              Return status code
181  */
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 );
186
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 ) );
190
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 ) );
194 }
195
196 /**
197  * Parse IB SRP root path destination GID
198  *
199  * @v rp_comp           Root path component string
200  * @v rp                IB SRP root path
201  * @ret rc              Return status code
202  */
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 ) );
208 }
209
210 /**
211  * Parse IB SRP root path partition key
212  *
213  * @v rp_comp           Root path component string
214  * @v rp                IB SRP root path
215  * @ret rc              Return status code
216  */
217 static int ib_srp_parse_pkey ( const char *rp_comp,
218                                struct ib_srp_root_path *rp ) {
219         int pkey;
220
221         if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
222                 return pkey;
223         rp->ib->pkey = pkey;
224         return 0;
225 }
226
227 /**
228  * Parse IB SRP root path service ID
229  *
230  * @v rp_comp           Root path component string
231  * @v rp                IB SRP root path
232  * @ret rc              Return status code
233  */
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 ) );
239 }
240
241 /**
242  * Parse IB SRP root path LUN
243  *
244  * @v rp_comp           Root path component string
245  * @v rp                IB SRP root path
246  * @ret rc              Return status code
247  */
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 );
251 }
252
253 /**
254  * Parse IB SRP root path target identifier extension
255  *
256  * @v rp_comp           Root path component string
257  * @v rp                IB SRP root path
258  * @ret rc              Return status code
259  */
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 );
264
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 ) );
268 }
269
270 /**
271  * Parse IB SRP root path target I/O controller GUID
272  *
273  * @v rp_comp           Root path component string
274  * @v rp                IB SRP root path
275  * @ret rc              Return status code
276  */
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 );
281
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 ) );
285 }
286
287 /** IB SRP root path component parser */
288 struct ib_srp_root_path_parser {
289         /**
290          * Parse IB SRP root path component
291          *
292          * @v rp_comp           Root path component string
293          * @v rp                IB SRP root path
294          * @ret rc              Return status code
295          */
296         int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
297 };
298
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 },
311 };
312
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] ) )
316
317 /**
318  * Parse IB SRP root path
319  *
320  * @v srp               SRP device
321  * @v rp_string         Root path
322  * @ret rc              Return status code
323  */
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 = {
328                 .lun = &srp->lun,
329                 .port_ids = &srp->port_ids,
330                 .ib = ib_params,
331         };
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;
335         unsigned int i = 0;
336         int rc;
337
338         /* Split root path into component parts */
339         strcpy ( rp_string_copy, rp_string );
340         while ( 1 ) {
341                 rp_comp[i++] = rp_string_tmp;
342                 if ( i == IB_SRP_NUM_RP_COMPONENTS )
343                         break;
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;
349                         }
350                 }
351                 *(rp_string_tmp++) = '\0';
352         }
353
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],
357                                                         &rp ) ) != 0 ) {
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 ) );
361                         return rc;
362                 }
363         }
364
365         return 0;
366 }
367
368 /**
369  * Connect IB SRP session
370  *
371  * @v srp               SRP device
372  * @ret rc              Return status code
373  */
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;
377         int rc;
378
379         /* Identify Infiniband device */
380         ibdev = find_ibdev ( &ib_params->sgid );
381         if ( ! ibdev ) {
382                 DBGC ( srp, "SRP %p could not identify Infiniband device\n",
383                        srp );
384                 return -ENODEV;
385         }
386
387         /* Configure remaining SRP parameters */
388         srp->memory_handle = ibdev->rdma_key;
389
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 ) );
395                 return rc;
396         }
397
398         return 0;
399 }
400
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,
406 };