source: bootcd/isolinux/syslinux-6.03/gpxe/src/net/infiniband/ib_srp.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 10.9 KB
Line 
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
31FILE_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 */
54enum 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 */
61struct 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 */
77static 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 */
111static 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 */
132static 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 */
145static 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 */
165static 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 */
182static 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 */
203static 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 */
217static 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 */
234static 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 */
248static 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 */
260static 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 */
277static 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 */
288struct 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 */
300static 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 */
324static 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 */
374static 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 */
402struct 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};
Note: See TracBrowser for help on using the repository browser.