#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. | |
Definition in file srp.c.
| FILE_LICENCE | ( | BSD2 | ) |
| FEATURE | ( | FEATURE_PROTOCOL | , | |
| "SRP" | , | |||
| DHCP_EB_FEATURE_SRP | , | |||
| 1 | ||||
| ) |
| static void srp_login | ( | struct srp_device * | srp | ) | [static] |
Initiate SRP login.
| 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.
| 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.
| 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().
| static void srp_fail | ( | struct srp_device * | srp, | |
| int | rc | |||
| ) | [static] |
Handle SRP session failure.
| 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.
| srp | SRP device | |
| iobuf | I/O buffer |
| 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.
| srp | SRP device | |
| iobuf | I/O buffer |
| 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.
| srp | SRP device | |
| iobuf | I/O buffer |
| 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.
| srp | SRP device | |
| iobuf | I/O buffer |
| 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.
| xfer | Data transfer interface | |
| iobuf | Datagram I/O buffer | |
| meta | Data transfer metadata |
| 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.
| 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.
| 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.
| 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.
| 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 }
unsigned int srp_tag = 0 [static] |
struct xfer_interface_operations srp_xfer_operations [static] |
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,
}
1.5.7.1