ib_srp.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  *   Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  *
00012  *   Redistributions in binary form must reproduce the above copyright
00013  *   notice, this list of conditions and the following disclaimer in
00014  *   the documentation and/or other materials provided with the
00015  *   distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00022  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00024  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00026  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00028  * OF THE POSSIBILITY OF SUCH DAMAGE.
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  * @file
00042  *
00043  * SCSI RDMA Protocol over Infiniband
00044  *
00045  */
00046 
00047 /* Disambiguate the various possible EINVALs */
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 /** IB SRP parse flags */
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 /** IB SRP root path parameters */
00061 struct ib_srp_root_path {
00062         /** SCSI LUN */
00063         struct scsi_lun *lun;
00064         /** SRP port IDs */
00065         struct srp_port_ids *port_ids;
00066         /** IB SRP parameters */
00067         struct ib_srp_parameters *ib;
00068 };
00069 
00070 /**
00071  * Parse IB SRP root path byte-string value
00072  *
00073  * @v rp_comp           Root path component string
00074  * @v default_value     Default value to use if component string is empty
00075  * @ret value           Value
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         /* Allow optional components to be empty */
00085         if ( ( rp_comp_len == 0 ) &&
00086              ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
00087                 return 0;
00088 
00089         /* Check string length */
00090         if ( rp_comp_len != ( 2 * size ) )
00091                 return -EINVAL_BYTE_STRING_LEN;
00092 
00093         /* Parse byte string */
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  * Parse IB SRP root path integer value
00106  *
00107  * @v rp_comp           Root path component string
00108  * @v default_value     Default value to use if component string is empty
00109  * @ret value           Value
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  * Parse IB SRP root path literal component
00127  *
00128  * @v rp_comp           Root path component string
00129  * @v rp                IB SRP root path
00130  * @ret rc              Return status code
00131  */
00132 static int ib_srp_parse_literal ( const char *rp_comp __unused,
00133                                   struct ib_srp_root_path *rp __unused ) {
00134         /* Ignore */
00135         return 0;
00136 }
00137 
00138 /**
00139  * Parse IB SRP root path source GID
00140  *
00141  * @v rp_comp           Root path component string
00142  * @v rp                IB SRP root path
00143  * @ret rc              Return status code
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         /* Default to the GID of the last opened Infiniband device */
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  * Parse IB SRP root path initiator identifier extension
00160  *
00161  * @v rp_comp           Root path component string
00162  * @v rp                IB SRP root path
00163  * @ret rc              Return status code
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  * Parse IB SRP root path initiator HCA GUID
00177  *
00178  * @v rp_comp           Root path component string
00179  * @v rp                IB SRP root path
00180  * @ret rc              Return status code
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         /* Default to the GUID portion of the source GID */
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  * Parse IB SRP root path destination GID
00198  *
00199  * @v rp_comp           Root path component string
00200  * @v rp                IB SRP root path
00201  * @ret rc              Return status code
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  * Parse IB SRP root path partition key
00212  *
00213  * @v rp_comp           Root path component string
00214  * @v rp                IB SRP root path
00215  * @ret rc              Return status code
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  * Parse IB SRP root path service ID
00229  *
00230  * @v rp_comp           Root path component string
00231  * @v rp                IB SRP root path
00232  * @ret rc              Return status code
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  * Parse IB SRP root path LUN
00243  *
00244  * @v rp_comp           Root path component string
00245  * @v rp                IB SRP root path
00246  * @ret rc              Return status code
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  * Parse IB SRP root path target identifier extension
00255  *
00256  * @v rp_comp           Root path component string
00257  * @v rp                IB SRP root path
00258  * @ret rc              Return status code
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  * Parse IB SRP root path target I/O controller GUID
00272  *
00273  * @v rp_comp           Root path component string
00274  * @v rp                IB SRP root path
00275  * @ret rc              Return status code
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 /** IB SRP root path component parser */
00288 struct ib_srp_root_path_parser {
00289         /**
00290          * Parse IB SRP root path component
00291          *
00292          * @v rp_comp           Root path component string
00293          * @v rp                IB SRP root path
00294          * @ret rc              Return status code
00295          */
00296         int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
00297 };
00298 
00299 /** IB SRP root path components */
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 /** Number of IB SRP root path components */
00314 #define IB_SRP_NUM_RP_COMPONENTS \
00315         ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
00316 
00317 /**
00318  * Parse IB SRP root path
00319  *
00320  * @v srp               SRP device
00321  * @v rp_string         Root path
00322  * @ret rc              Return status code
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         /* Split root path into component parts */
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         /* Parse root path components */
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  * Connect IB SRP session
00370  *
00371  * @v srp               SRP device
00372  * @ret rc              Return status code
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         /* Identify Infiniband device */
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         /* Configure remaining SRP parameters */
00388         srp->memory_handle = ibdev->rdma_key;
00389 
00390         /* Open CMRC socket */
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 /** IB SRP transport type */
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 };

Generated on Tue Apr 6 20:01:10 2010 for gPXE by  doxygen 1.5.7.1