srp.c File Reference

SCSI RDMA Protocol. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <gpxe/scsi.h>
#include <gpxe/xfer.h>
#include <gpxe/features.h>
#include <gpxe/ib_srp.h>
#include <gpxe/srp.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (BSD2)
 FEATURE (FEATURE_PROTOCOL,"SRP", DHCP_EB_FEATURE_SRP, 1)
static void srp_login (struct srp_device *srp)
 Initiate SRP login.
static void srp_cmd (struct srp_device *srp)
 Transmit SRP SCSI command.
static void srp_scsi_done (struct srp_device *srp, int rc)
 Mark SRP SCSI command as complete.
static void srp_fail (struct srp_device *srp, int rc)
 Handle SRP session failure.
static int srp_login_rsp (struct srp_device *srp, struct io_buffer *iobuf)
 Handle SRP login response.
static int srp_login_rej (struct srp_device *srp, struct io_buffer *iobuf)
 Handle SRP login rejection.
static int srp_rsp (struct srp_device *srp, struct io_buffer *iobuf)
 Handle SRP SCSI response.
static int srp_unrecognised (struct srp_device *srp, struct io_buffer *iobuf)
 Handle SRP unrecognised response.
static int srp_xfer_deliver_iob (struct xfer_interface *xfer, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Receive data from underlying socket.
static void srp_xfer_close (struct xfer_interface *xfer, int rc)
 Underlying socket closed.
static int srp_command (struct scsi_device *scsi, struct scsi_command *command)
 Issue SCSI command via SRP.
int srp_attach (struct scsi_device *scsi, const char *root_path)
 Attach SRP device.
void srp_detach (struct scsi_device *scsi)
 Detach SRP device.

Variables

static unsigned int srp_tag = 0
 Tag to be used for next SRP IU.
static struct
xfer_interface_operations 
srp_xfer_operations
 SRP data transfer interface operations.


Detailed Description

SCSI RDMA Protocol.

Definition in file srp.c.


Function Documentation

FILE_LICENCE ( BSD2   ) 

FEATURE ( FEATURE_PROTOCOL  ,
"SRP"  ,
DHCP_EB_FEATURE_SRP  ,
 
)

static void srp_login ( struct srp_device srp  )  [static]

Initiate SRP login.

Parameters:
srp SRP device

Definition at line 101 of file srp.c.

References assert, srp_transport_type::connect, io_buffer::data, DBGC, DBGC2, DBGC2_HDA, srp_tag::dwords, ENOMEM, htonl, iob_len(), iob_put, srp_login_req::max_i_t_iu_len, memcpy, memset(), ntohl, srp_device::port_ids, srp_login_req::port_ids, srp_login_req::required_buffer_formats, srp_device::socket, srp_fail(), SRP_LOGIN_REQ, SRP_LOGIN_REQ_FMT_DDBD, SRP_MAX_I_T_IU_LEN, SRP_STATE_SOCKET_OPEN, srp_device::state, strerror(), srp_login_req::tag, srp_device::transport, srp_login_req::type, xfer_alloc_iob(), and xfer_deliver_iob().

Referenced by srp_command(), and srp_fail().

00101                                                  {
00102         struct io_buffer *iobuf;
00103         struct srp_login_req *login_req;
00104         int rc;
00105 
00106         assert ( ! ( srp->state & SRP_STATE_SOCKET_OPEN ) );
00107 
00108         /* Open underlying socket */
00109         if ( ( rc = srp->transport->connect ( srp ) ) != 0 ) {
00110                 DBGC ( srp, "SRP %p could not open socket: %s\n",
00111                        srp, strerror ( rc ) );
00112                 goto err;
00113         }
00114         srp->state |= SRP_STATE_SOCKET_OPEN;
00115 
00116         /* Allocate I/O buffer */
00117         iobuf = xfer_alloc_iob ( &srp->socket, sizeof ( *login_req ) );
00118         if ( ! iobuf ) {
00119                 rc = -ENOMEM;
00120                 goto err;
00121         }
00122 
00123         /* Construct login request IU */
00124         login_req = iob_put ( iobuf, sizeof ( *login_req ) );
00125         memset ( login_req, 0, sizeof ( *login_req ) );
00126         login_req->type = SRP_LOGIN_REQ;
00127         login_req->tag.dwords[1] = htonl ( ++srp_tag );
00128         login_req->max_i_t_iu_len = htonl ( SRP_MAX_I_T_IU_LEN );
00129         login_req->required_buffer_formats = SRP_LOGIN_REQ_FMT_DDBD;
00130         memcpy ( &login_req->port_ids, &srp->port_ids,
00131                  sizeof ( login_req->port_ids ) );
00132 
00133         DBGC2 ( srp, "SRP %p TX login request tag %08x%08x\n",
00134                 srp, ntohl ( login_req->tag.dwords[0] ),
00135                 ntohl ( login_req->tag.dwords[1] ) );
00136         DBGC2_HDA ( srp, 0, iobuf->data, iob_len ( iobuf ) );
00137 
00138         /* Send login request IU */
00139         if ( ( rc = xfer_deliver_iob ( &srp->socket, iobuf ) ) != 0 ) {
00140                 DBGC ( srp, "SRP %p could not send login request: %s\n",
00141                        srp, strerror ( rc ) );
00142                 goto err;
00143         }
00144 
00145         return;
00146 
00147  err:
00148         srp_fail ( srp, rc );
00149 }

static void srp_cmd ( struct srp_device srp  )  [static]

Transmit SRP SCSI command.

Parameters:
srp SRP device

Definition at line 229 of file srp.c.

References srp_memory_descriptor::address, assert, scsi_command::cdb, srp_cmd::cdb, srp_device::command, cpu_to_be64, io_buffer::data, srp_cmd::data_buffer_formats, scsi_command::data_in, scsi_command::data_in_len, scsi_command::data_out, scsi_command::data_out_len, DBGC, DBGC2, DBGC2_HDA, srp_tag::dwords, ENOMEM, srp_memory_descriptor::handle, htonl, iob_len(), iob_put, srp_memory_descriptor::len, srp_device::lun, srp_cmd::lun, memcpy, srp_device::memory_handle, memset(), ntohl, srp_device::socket, SRP_CMD, SRP_CMD_DI_FMT_DIRECT, SRP_CMD_DO_FMT_DIRECT, srp_fail(), SRP_MAX_I_T_IU_LEN, SRP_STATE_LOGGED_IN, srp_device::state, strerror(), srp_cmd::tag, srp_cmd::type, user_to_phys(), xfer_alloc_iob(), and xfer_deliver_iob().

Referenced by srp_command(), and srp_login_rsp().

00229                                                {
00230         struct io_buffer *iobuf;
00231         struct srp_cmd *cmd;
00232         struct srp_memory_descriptor *data_out;
00233         struct srp_memory_descriptor *data_in;
00234         int rc;
00235 
00236         assert ( srp->state & SRP_STATE_LOGGED_IN );
00237 
00238         /* Allocate I/O buffer */
00239         iobuf = xfer_alloc_iob ( &srp->socket, SRP_MAX_I_T_IU_LEN );
00240         if ( ! iobuf ) {
00241                 rc = -ENOMEM;
00242                 goto err;
00243         }
00244 
00245         /* Construct base portion */
00246         cmd = iob_put ( iobuf, sizeof ( *cmd ) );
00247         memset ( cmd, 0, sizeof ( *cmd ) );
00248         cmd->type = SRP_CMD;
00249         cmd->tag.dwords[1] = htonl ( ++srp_tag );
00250         cmd->lun = srp->lun;
00251         memcpy ( &cmd->cdb, &srp->command->cdb, sizeof ( cmd->cdb ) );
00252 
00253         /* Construct data-out descriptor, if present */
00254         if ( srp->command->data_out ) {
00255                 cmd->data_buffer_formats |= SRP_CMD_DO_FMT_DIRECT;
00256                 data_out = iob_put ( iobuf, sizeof ( *data_out ) );
00257                 data_out->address =
00258                     cpu_to_be64 ( user_to_phys ( srp->command->data_out, 0 ) );
00259                 data_out->handle = ntohl ( srp->memory_handle );
00260                 data_out->len = ntohl ( srp->command->data_out_len );
00261         }
00262 
00263         /* Construct data-in descriptor, if present */
00264         if ( srp->command->data_in ) {
00265                 cmd->data_buffer_formats |= SRP_CMD_DI_FMT_DIRECT;
00266                 data_in = iob_put ( iobuf, sizeof ( *data_in ) );
00267                 data_in->address =
00268                      cpu_to_be64 ( user_to_phys ( srp->command->data_in, 0 ) );
00269                 data_in->handle = ntohl ( srp->memory_handle );
00270                 data_in->len = ntohl ( srp->command->data_in_len );
00271         }
00272 
00273         DBGC2 ( srp, "SRP %p TX SCSI command tag %08x%08x\n", srp,
00274                 ntohl ( cmd->tag.dwords[0] ), ntohl ( cmd->tag.dwords[1] ) );
00275         DBGC2_HDA ( srp, 0, iobuf->data, iob_len ( iobuf ) );
00276 
00277         /* Send IU */
00278         if ( ( rc = xfer_deliver_iob ( &srp->socket, iobuf ) ) != 0 ) {
00279                 DBGC ( srp, "SRP %p could not send command: %s\n",
00280                        srp, strerror ( rc ) );
00281                 goto err;
00282         }
00283 
00284         return;
00285 
00286  err:
00287         srp_fail ( srp, rc );
00288 }

static void srp_scsi_done ( struct srp_device srp,
int  rc 
) [static]

Mark SRP SCSI command as complete.

Parameters:
srp SRP device
rc Status code

Definition at line 63 of file srp.c.

References srp_device::command, NULL, and scsi_command::rc.

Referenced by srp_fail(), and srp_rsp().

00063                                                              {
00064         if ( srp->command )
00065                 srp->command->rc = rc;
00066         srp->command = NULL;
00067 }

static void srp_fail ( struct srp_device srp,
int  rc 
) [static]

Handle SRP session failure.

Parameters:
srp SRP device
rc Reason for failure

Definition at line 75 of file srp.c.

References srp_device::retry_count, srp_device::socket, srp_login(), SRP_MAX_RETRIES, srp_scsi_done(), srp_device::state, and xfer_close().

Referenced by srp_cmd(), srp_login(), srp_xfer_close(), and srp_xfer_deliver_iob().

00075                                                         {
00076 
00077         /* Close underlying socket */
00078         xfer_close ( &srp->socket, rc );
00079 
00080         /* Clear session state */
00081         srp->state = 0;
00082 
00083         /* If we have reached the retry limit, report the failure */
00084         if ( srp->retry_count >= SRP_MAX_RETRIES ) {
00085                 srp_scsi_done ( srp, rc );
00086                 return;
00087         }
00088 
00089         /* Otherwise, increment the retry count and try to reopen the
00090          * connection
00091          */
00092         srp->retry_count++;
00093         srp_login ( srp );
00094 }

static int srp_login_rsp ( struct srp_device srp,
struct io_buffer iobuf 
) [static]

Handle SRP login response.

Parameters:
srp SRP device
iobuf I/O buffer
Return values:
rc Return status code

Definition at line 158 of file srp.c.

References io_buffer::data, DBGC, DBGC2, srp_tag::dwords, EINVAL, free_iob(), iob_len(), ntohl, srp_device::retry_count, srp_cmd(), SRP_STATE_LOGGED_IN, srp_device::state, and srp_login_rsp::tag.

00158                                                                              {
00159         struct srp_login_rsp *login_rsp = iobuf->data;
00160         int rc;
00161 
00162         DBGC2 ( srp, "SRP %p RX login response tag %08x%08x\n",
00163                 srp, ntohl ( login_rsp->tag.dwords[0] ),
00164                 ntohl ( login_rsp->tag.dwords[1] ) );
00165 
00166         /* Sanity check */
00167         if ( iob_len ( iobuf ) < sizeof ( *login_rsp ) ) {
00168                 DBGC ( srp, "SRP %p RX login response too short (%zd bytes)\n",
00169                        srp, iob_len ( iobuf ) );
00170                 rc = -EINVAL;
00171                 goto out;
00172         }
00173 
00174         DBGC ( srp, "SRP %p logged in\n", srp );
00175 
00176         /* Mark as logged in */
00177         srp->state |= SRP_STATE_LOGGED_IN;
00178 
00179         /* Reset error counter */
00180         srp->retry_count = 0;
00181 
00182         /* Issue pending command */
00183         srp_cmd ( srp );
00184 
00185         rc = 0;
00186  out:
00187         free_iob ( iobuf );
00188         return rc;
00189 }

static int srp_login_rej ( struct srp_device srp,
struct io_buffer iobuf 
) [static]

Handle SRP login rejection.

Parameters:
srp SRP device
iobuf I/O buffer
Return values:
rc Return status code

Definition at line 198 of file srp.c.

References io_buffer::data, DBGC, DBGC2, srp_tag::dwords, EINVAL, EPERM, free_iob(), iob_len(), ntohl, srp_login_rej::reason, and srp_login_rej::tag.

00198                                                                              {
00199         struct srp_login_rej *login_rej = iobuf->data;
00200         int rc;
00201 
00202         DBGC2 ( srp, "SRP %p RX login rejection tag %08x%08x\n",
00203                 srp, ntohl ( login_rej->tag.dwords[0] ),
00204                 ntohl ( login_rej->tag.dwords[1] ) );
00205 
00206         /* Sanity check */
00207         if ( iob_len ( iobuf ) < sizeof ( *login_rej ) ) {
00208                 DBGC ( srp, "SRP %p RX login rejection too short (%zd "
00209                        "bytes)\n", srp, iob_len ( iobuf ) );
00210                 rc = -EINVAL;
00211                 goto out;
00212         }
00213 
00214         /* Login rejection always indicates an error */
00215         DBGC ( srp, "SRP %p login rejected (reason %08x)\n",
00216                srp, ntohl ( login_rej->reason ) );
00217         rc = -EPERM;
00218 
00219  out:
00220         free_iob ( iobuf );
00221         return rc;
00222 }

static int srp_rsp ( struct srp_device srp,
struct io_buffer iobuf 
) [static]

Handle SRP SCSI response.

Parameters:
srp SRP device
iobuf I/O buffer
Return values:
rc Returns status code

Definition at line 297 of file srp.c.

References srp_device::command, io_buffer::data, srp_rsp::data_in_residual_count, srp_rsp::data_out_residual_count, DBGC, DBGC2, DBGC_HDA, srp_tag::dwords, EINVAL, free_iob(), iob_len(), ntohl, srp_rsp_sense_data(), srp_rsp_sense_data_len(), SRP_RSP_VALID_DIOVER, SRP_RSP_VALID_DIUNDER, SRP_RSP_VALID_DOOVER, SRP_RSP_VALID_DOUNDER, srp_scsi_done(), scsi_command::status, srp_rsp::status, srp_rsp::tag, and srp_rsp::valid.

00297                                                                        {
00298         struct srp_rsp *rsp = iobuf->data;
00299         int rc;
00300 
00301         DBGC2 ( srp, "SRP %p RX SCSI response tag %08x%08x\n", srp,
00302                 ntohl ( rsp->tag.dwords[0] ), ntohl ( rsp->tag.dwords[1] ) );
00303 
00304         /* Sanity check */
00305         if ( iob_len ( iobuf ) < sizeof ( *rsp ) ) {
00306                 DBGC ( srp, "SRP %p RX SCSI response too short (%zd bytes)\n",
00307                        srp, iob_len ( iobuf ) );
00308                 rc = -EINVAL;
00309                 goto out;
00310         }
00311 
00312         /* Report SCSI errors */
00313         if ( rsp->status != 0 ) {
00314                 DBGC ( srp, "SRP %p response status %02x\n",
00315                        srp, rsp->status );
00316                 if ( srp_rsp_sense_data ( rsp ) ) {
00317                         DBGC ( srp, "SRP %p sense data:\n", srp );
00318                         DBGC_HDA ( srp, 0, srp_rsp_sense_data ( rsp ),
00319                                    srp_rsp_sense_data_len ( rsp ) );
00320                 }
00321         }
00322         if ( rsp->valid & ( SRP_RSP_VALID_DOUNDER | SRP_RSP_VALID_DOOVER ) ) {
00323                 DBGC ( srp, "SRP %p response data-out %srun by %#x bytes\n",
00324                        srp, ( ( rsp->valid & SRP_RSP_VALID_DOUNDER )
00325                               ? "under" : "over" ),
00326                        ntohl ( rsp->data_out_residual_count ) );
00327         }
00328         if ( rsp->valid & ( SRP_RSP_VALID_DIUNDER | SRP_RSP_VALID_DIOVER ) ) {
00329                 DBGC ( srp, "SRP %p response data-in %srun by %#x bytes\n",
00330                        srp, ( ( rsp->valid & SRP_RSP_VALID_DIUNDER )
00331                               ? "under" : "over" ),
00332                        ntohl ( rsp->data_in_residual_count ) );
00333         }
00334         srp->command->status = rsp->status;
00335 
00336         /* Mark SCSI command as complete */
00337         srp_scsi_done ( srp, 0 );
00338 
00339         rc = 0;
00340  out:
00341         free_iob ( iobuf );
00342         return rc;
00343 }

static int srp_unrecognised ( struct srp_device srp,
struct io_buffer iobuf 
) [static]

Handle SRP unrecognised response.

Parameters:
srp SRP device
iobuf I/O buffer
Return values:
rc Returns status code

Definition at line 352 of file srp.c.

References io_buffer::data, DBGC, srp_tag::dwords, ENOTSUP, free_iob(), ntohl, srp_common::tag, and srp_common::type.

Referenced by srp_xfer_deliver_iob().

00353                                                         {
00354         struct srp_common *common = iobuf->data;
00355 
00356         DBGC ( srp, "SRP %p RX unrecognised IU tag %08x%08x type %02x\n",
00357                srp, ntohl ( common->tag.dwords[0] ),
00358                ntohl ( common->tag.dwords[1] ), common->type );
00359 
00360         free_iob ( iobuf );
00361         return -ENOTSUP;
00362 }

static int srp_xfer_deliver_iob ( struct xfer_interface xfer,
struct io_buffer iobuf,
struct xfer_metadata *meta  __unused 
) [static]

Receive data from underlying socket.

Parameters:
xfer Data transfer interface
iobuf Datagram I/O buffer
meta Data transfer metadata
Return values:
rc Return status code

Definition at line 372 of file srp.c.

References container_of, io_buffer::data, srp_device::socket, srp_fail(), SRP_LOGIN_REJ, SRP_LOGIN_RSP, SRP_RSP, srp_unrecognised(), and srp_common::type.

00374                                                                         {
00375         struct srp_device *srp =
00376                 container_of ( xfer, struct srp_device, socket );
00377         struct srp_common *common = iobuf->data;
00378         int ( * type ) ( struct srp_device *srp, struct io_buffer *iobuf );
00379         int rc;
00380 
00381         /* Determine IU type */
00382         switch ( common->type ) {
00383         case SRP_LOGIN_RSP:
00384                 type = srp_login_rsp;
00385                 break;
00386         case SRP_LOGIN_REJ:
00387                 type = srp_login_rej;
00388                 break;
00389         case SRP_RSP:
00390                 type = srp_rsp;
00391                 break;
00392         default:
00393                 type = srp_unrecognised;
00394                 break;
00395         }
00396 
00397         /* Handle IU */
00398         if ( ( rc = type ( srp, iobuf ) ) != 0 )
00399                 goto err;
00400 
00401         return 0;
00402 
00403  err:
00404         srp_fail ( srp, rc );
00405         return rc;
00406 }

static void srp_xfer_close ( struct xfer_interface xfer,
int  rc 
) [static]

Underlying socket closed.

Parameters:
xfer Data transfer interface
rc Reason for close

Definition at line 414 of file srp.c.

References container_of, DBGC, srp_device::socket, srp_fail(), and strerror().

00414                                                                    {
00415         struct srp_device *srp =
00416                 container_of ( xfer, struct srp_device, socket );
00417 
00418         DBGC ( srp, "SRP %p socket closed: %s\n", srp, strerror ( rc ) );
00419 
00420         srp_fail ( srp, rc );
00421 }

static int srp_command ( struct scsi_device scsi,
struct scsi_command command 
) [static]

Issue SCSI command via SRP.

Parameters:
scsi SCSI device
command SCSI command
Return values:
rc Return status code

Definition at line 440 of file srp.c.

References scsi_device::backend, srp_device::command, container_of, DBGC, EBUSY, srp_cmd(), srp_login(), SRP_STATE_LOGGED_IN, SRP_STATE_SOCKET_OPEN, and srp_device::state.

Referenced by srp_attach().

00441                                                         {
00442         struct srp_device *srp =
00443                 container_of ( scsi->backend, struct srp_device, refcnt );
00444 
00445         /* Store SCSI command */
00446         if ( srp->command ) {
00447                 DBGC ( srp, "SRP %p cannot handle concurrent SCSI commands\n",
00448                        srp );
00449                 return -EBUSY;
00450         }
00451         srp->command = command;
00452 
00453         /* Log in or issue command as appropriate */
00454         if ( ! ( srp->state & SRP_STATE_SOCKET_OPEN ) ) {
00455                 srp_login ( srp );
00456         } else if ( srp->state & SRP_STATE_LOGGED_IN ) {
00457                 srp_cmd ( srp );
00458         } else {
00459                 /* Still waiting for login; do nothing */
00460         }
00461 
00462         return 0;
00463 }

int srp_attach ( struct scsi_device scsi,
const char *  root_path 
)

Attach SRP device.

Parameters:
scsi SCSI device
root_path Root path

Definition at line 471 of file srp.c.

References scsi_device::backend, scsi_device::command, DBGC, ENOMEM, ib_srp_transport, srp_transport_type::parse_root_path, srp_transport_type::priv_len, ref_get(), ref_put(), srp_device::refcnt, srp_device::socket, srp_command(), strerror(), srp_device::transport, xfer_init(), and zalloc().

Referenced by ib_srpboot().

00471                                                                    {
00472         struct srp_transport_type *transport;
00473         struct srp_device *srp;
00474         int rc;
00475 
00476         /* Hard-code an IB SRP back-end for now */
00477         transport = &ib_srp_transport;
00478 
00479         /* Allocate and initialise structure */
00480         srp = zalloc ( sizeof ( *srp ) + transport->priv_len );
00481         if ( ! srp ) {
00482                 rc = -ENOMEM;
00483                 goto err_alloc;
00484         }
00485         xfer_init ( &srp->socket, &srp_xfer_operations, &srp->refcnt );
00486         srp->transport = transport;
00487         DBGC ( srp, "SRP %p using %s\n", srp, root_path );
00488 
00489         /* Parse root path */
00490         if ( ( rc = transport->parse_root_path ( srp, root_path ) ) != 0 ) {
00491                 DBGC ( srp, "SRP %p could not parse root path: %s\n",
00492                        srp, strerror ( rc ) );
00493                 goto err_parse_root_path;
00494         }
00495 
00496         /* Attach parent interface, mortalise self, and return */
00497         scsi->backend = ref_get ( &srp->refcnt );
00498         scsi->command = srp_command;
00499         ref_put ( &srp->refcnt );
00500         return 0;
00501 
00502  err_parse_root_path:
00503         ref_put ( &srp->refcnt );
00504  err_alloc:
00505         return rc;
00506 }

void srp_detach ( struct scsi_device scsi  ) 

Detach SRP device.

Parameters:
scsi SCSI device

Definition at line 513 of file srp.c.

References scsi_device::backend, scsi_device::command, container_of, NULL, ref_put(), scsi_detached_command(), srp_device::socket, and xfer_close().

Referenced by ib_srpboot().

00513                                              {
00514         struct srp_device *srp =
00515                 container_of ( scsi->backend, struct srp_device, refcnt );
00516 
00517         /* Close socket */
00518         xfer_nullify ( &srp->socket );
00519         xfer_close ( &srp->socket, 0 );
00520         scsi->command = scsi_detached_command;
00521         ref_put ( scsi->backend );
00522         scsi->backend = NULL;
00523 }


Variable Documentation

unsigned int srp_tag = 0 [static]

Tag to be used for next SRP IU.

Definition at line 52 of file srp.c.

Initial value:

 {
        .close          = srp_xfer_close,
        .vredirect      = ignore_xfer_vredirect,
        .window         = unlimited_xfer_window,
        .alloc_iob      = default_xfer_alloc_iob,
        .deliver_iob    = srp_xfer_deliver_iob,
        .deliver_raw    = xfer_deliver_as_iob,
}
SRP data transfer interface operations.

Definition at line 424 of file srp.c.


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