You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ib_srp.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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. FILE_LICENCE ( BSD2 );
  31. #include <stdlib.h>
  32. #include <errno.h>
  33. #include <ipxe/base16.h>
  34. #include <ipxe/srp.h>
  35. #include <ipxe/infiniband.h>
  36. #include <ipxe/ib_cmrc.h>
  37. #include <ipxe/ib_srp.h>
  38. /**
  39. * @file
  40. *
  41. * SCSI RDMA Protocol over Infiniband
  42. *
  43. */
  44. /* Disambiguate the various possible EINVALs */
  45. #define EINVAL_BYTE_STRING_LEN ( EINVAL | EUNIQ_01 )
  46. #define EINVAL_BYTE_STRING ( EINVAL | EUNIQ_02 )
  47. #define EINVAL_INTEGER ( EINVAL | EUNIQ_03 )
  48. #define EINVAL_RP_TOO_SHORT ( EINVAL | EUNIQ_04 )
  49. /** IB SRP parse flags */
  50. enum ib_srp_parse_flags {
  51. IB_SRP_PARSE_REQUIRED = 0x0000,
  52. IB_SRP_PARSE_OPTIONAL = 0x8000,
  53. IB_SRP_PARSE_FLAG_MASK = 0xf000,
  54. };
  55. /** IB SRP root path parameters */
  56. struct ib_srp_root_path {
  57. /** SCSI LUN */
  58. struct scsi_lun *lun;
  59. /** SRP port IDs */
  60. struct srp_port_ids *port_ids;
  61. /** IB SRP parameters */
  62. struct ib_srp_parameters *ib;
  63. };
  64. /**
  65. * Parse IB SRP root path byte-string value
  66. *
  67. * @v rp_comp Root path component string
  68. * @v default_value Default value to use if component string is empty
  69. * @ret value Value
  70. */
  71. static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
  72. unsigned int size_flags ) {
  73. size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
  74. size_t rp_comp_len = strlen ( rp_comp );
  75. int decoded_size;
  76. /* Allow optional components to be empty */
  77. if ( ( rp_comp_len == 0 ) &&
  78. ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
  79. return 0;
  80. /* Check string length */
  81. if ( rp_comp_len != ( 2 * size ) )
  82. return -EINVAL_BYTE_STRING_LEN;
  83. /* Parse byte string */
  84. decoded_size = base16_decode ( rp_comp, bytes );
  85. if ( decoded_size < 0 )
  86. return decoded_size;
  87. assert ( decoded_size == size );
  88. return 0;
  89. }
  90. /**
  91. * Parse IB SRP root path integer value
  92. *
  93. * @v rp_comp Root path component string
  94. * @v default_value Default value to use if component string is empty
  95. * @ret value Value
  96. */
  97. static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
  98. int value;
  99. char *end;
  100. value = strtoul ( rp_comp, &end, 16 );
  101. if ( *end )
  102. return -EINVAL_INTEGER;
  103. if ( end == rp_comp )
  104. return default_value;
  105. return value;
  106. }
  107. /**
  108. * Parse IB SRP root path literal component
  109. *
  110. * @v rp_comp Root path component string
  111. * @v rp IB SRP root path
  112. * @ret rc Return status code
  113. */
  114. static int ib_srp_parse_literal ( const char *rp_comp __unused,
  115. struct ib_srp_root_path *rp __unused ) {
  116. /* Ignore */
  117. return 0;
  118. }
  119. /**
  120. * Parse IB SRP root path source GID
  121. *
  122. * @v rp_comp Root path component string
  123. * @v rp IB SRP root path
  124. * @ret rc Return status code
  125. */
  126. static int ib_srp_parse_sgid ( const char *rp_comp,
  127. struct ib_srp_root_path *rp ) {
  128. struct ib_device *ibdev;
  129. /* Default to the GID of the last opened Infiniband device */
  130. if ( ( ibdev = last_opened_ibdev() ) != NULL )
  131. memcpy ( &rp->ib->sgid, &ibdev->gid, sizeof ( rp->ib->sgid ) );
  132. return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
  133. ( sizeof ( rp->ib->sgid ) |
  134. IB_SRP_PARSE_OPTIONAL ) );
  135. }
  136. /**
  137. * Parse IB SRP root path initiator identifier extension
  138. *
  139. * @v rp_comp Root path component string
  140. * @v rp IB SRP root path
  141. * @ret rc Return status code
  142. */
  143. static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
  144. struct ib_srp_root_path *rp ) {
  145. struct ib_srp_initiator_port_id *port_id =
  146. ib_srp_initiator_port_id ( rp->port_ids );
  147. return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
  148. ( sizeof ( port_id->id_ext ) |
  149. IB_SRP_PARSE_OPTIONAL ) );
  150. }
  151. /**
  152. * Parse IB SRP root path initiator HCA GUID
  153. *
  154. * @v rp_comp Root path component string
  155. * @v rp IB SRP root path
  156. * @ret rc Return status code
  157. */
  158. static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
  159. struct ib_srp_root_path *rp ) {
  160. struct ib_srp_initiator_port_id *port_id =
  161. ib_srp_initiator_port_id ( rp->port_ids );
  162. /* Default to the GUID portion of the source GID */
  163. memcpy ( &port_id->hca_guid, &rp->ib->sgid.u.half[1],
  164. sizeof ( port_id->hca_guid ) );
  165. return ib_srp_parse_byte_string ( rp_comp, port_id->hca_guid.u.bytes,
  166. ( sizeof ( port_id->hca_guid ) |
  167. IB_SRP_PARSE_OPTIONAL ) );
  168. }
  169. /**
  170. * Parse IB SRP root path destination GID
  171. *
  172. * @v rp_comp Root path component string
  173. * @v rp IB SRP root path
  174. * @ret rc Return status code
  175. */
  176. static int ib_srp_parse_dgid ( const char *rp_comp,
  177. struct ib_srp_root_path *rp ) {
  178. return ib_srp_parse_byte_string ( rp_comp, rp->ib->dgid.u.bytes,
  179. ( sizeof ( rp->ib->dgid ) |
  180. IB_SRP_PARSE_REQUIRED ) );
  181. }
  182. /**
  183. * Parse IB SRP root path partition key
  184. *
  185. * @v rp_comp Root path component string
  186. * @v rp IB SRP root path
  187. * @ret rc Return status code
  188. */
  189. static int ib_srp_parse_pkey ( const char *rp_comp,
  190. struct ib_srp_root_path *rp ) {
  191. int pkey;
  192. if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
  193. return pkey;
  194. rp->ib->pkey = pkey;
  195. return 0;
  196. }
  197. /**
  198. * Parse IB SRP root path service ID
  199. *
  200. * @v rp_comp Root path component string
  201. * @v rp IB SRP root path
  202. * @ret rc Return status code
  203. */
  204. static int ib_srp_parse_service_id ( const char *rp_comp,
  205. struct ib_srp_root_path *rp ) {
  206. return ib_srp_parse_byte_string ( rp_comp, rp->ib->service_id.u.bytes,
  207. ( sizeof ( rp->ib->service_id ) |
  208. IB_SRP_PARSE_REQUIRED ) );
  209. }
  210. /**
  211. * Parse IB SRP root path LUN
  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_lun ( const char *rp_comp,
  218. struct ib_srp_root_path *rp ) {
  219. return scsi_parse_lun ( rp_comp, rp->lun );
  220. }
  221. /**
  222. * Parse IB SRP root path target identifier extension
  223. *
  224. * @v rp_comp Root path component string
  225. * @v rp IB SRP root path
  226. * @ret rc Return status code
  227. */
  228. static int ib_srp_parse_target_id_ext ( const char *rp_comp,
  229. struct ib_srp_root_path *rp ) {
  230. struct ib_srp_target_port_id *port_id =
  231. ib_srp_target_port_id ( rp->port_ids );
  232. return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
  233. ( sizeof ( port_id->id_ext ) |
  234. IB_SRP_PARSE_REQUIRED ) );
  235. }
  236. /**
  237. * Parse IB SRP root path target I/O controller GUID
  238. *
  239. * @v rp_comp Root path component string
  240. * @v rp IB SRP root path
  241. * @ret rc Return status code
  242. */
  243. static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
  244. struct ib_srp_root_path *rp ) {
  245. struct ib_srp_target_port_id *port_id =
  246. ib_srp_target_port_id ( rp->port_ids );
  247. return ib_srp_parse_byte_string ( rp_comp, port_id->ioc_guid.u.bytes,
  248. ( sizeof ( port_id->ioc_guid ) |
  249. IB_SRP_PARSE_REQUIRED ) );
  250. }
  251. /** IB SRP root path component parser */
  252. struct ib_srp_root_path_parser {
  253. /**
  254. * Parse IB SRP root path component
  255. *
  256. * @v rp_comp Root path component string
  257. * @v rp IB SRP root path
  258. * @ret rc Return status code
  259. */
  260. int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
  261. };
  262. /** IB SRP root path components */
  263. static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
  264. { ib_srp_parse_literal },
  265. { ib_srp_parse_sgid },
  266. { ib_srp_parse_initiator_id_ext },
  267. { ib_srp_parse_initiator_hca_guid },
  268. { ib_srp_parse_dgid },
  269. { ib_srp_parse_pkey },
  270. { ib_srp_parse_service_id },
  271. { ib_srp_parse_lun },
  272. { ib_srp_parse_target_id_ext },
  273. { ib_srp_parse_target_ioc_guid },
  274. };
  275. /** Number of IB SRP root path components */
  276. #define IB_SRP_NUM_RP_COMPONENTS \
  277. ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
  278. /**
  279. * Parse IB SRP root path
  280. *
  281. * @v srp SRP device
  282. * @v rp_string Root path
  283. * @ret rc Return status code
  284. */
  285. static int ib_srp_parse_root_path ( struct srp_device *srp,
  286. const char *rp_string ) {
  287. struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
  288. struct ib_srp_root_path rp = {
  289. .lun = &srp->lun,
  290. .port_ids = &srp->port_ids,
  291. .ib = ib_params,
  292. };
  293. char rp_string_copy[ strlen ( rp_string ) + 1 ];
  294. char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
  295. char *rp_string_tmp = rp_string_copy;
  296. unsigned int i = 0;
  297. int rc;
  298. /* Split root path into component parts */
  299. strcpy ( rp_string_copy, rp_string );
  300. while ( 1 ) {
  301. rp_comp[i++] = rp_string_tmp;
  302. if ( i == IB_SRP_NUM_RP_COMPONENTS )
  303. break;
  304. for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
  305. if ( ! *rp_string_tmp ) {
  306. DBGC ( srp, "SRP %p root path \"%s\" too "
  307. "short\n", srp, rp_string );
  308. return -EINVAL_RP_TOO_SHORT;
  309. }
  310. }
  311. *(rp_string_tmp++) = '\0';
  312. }
  313. /* Parse root path components */
  314. for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
  315. if ( ( rc = ib_srp_rp_parser[i].parse ( rp_comp[i],
  316. &rp ) ) != 0 ) {
  317. DBGC ( srp, "SRP %p could not parse \"%s\" in root "
  318. "path \"%s\": %s\n", srp, rp_comp[i],
  319. rp_string, strerror ( rc ) );
  320. return rc;
  321. }
  322. }
  323. return 0;
  324. }
  325. /**
  326. * Connect IB SRP session
  327. *
  328. * @v srp SRP device
  329. * @ret rc Return status code
  330. */
  331. static int ib_srp_connect ( struct srp_device *srp ) {
  332. struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
  333. struct ib_device *ibdev;
  334. int rc;
  335. /* Identify Infiniband device */
  336. ibdev = find_ibdev ( &ib_params->sgid );
  337. if ( ! ibdev ) {
  338. DBGC ( srp, "SRP %p could not identify Infiniband device\n",
  339. srp );
  340. return -ENODEV;
  341. }
  342. /* Configure remaining SRP parameters */
  343. srp->memory_handle = ibdev->rdma_key;
  344. /* Open CMRC socket */
  345. if ( ( rc = ib_cmrc_open ( &srp->socket, ibdev, &ib_params->dgid,
  346. &ib_params->service_id ) ) != 0 ) {
  347. DBGC ( srp, "SRP %p could not open CMRC socket: %s\n",
  348. srp, strerror ( rc ) );
  349. return rc;
  350. }
  351. return 0;
  352. }
  353. /** IB SRP transport type */
  354. struct srp_transport_type ib_srp_transport = {
  355. .priv_len = sizeof ( struct ib_srp_parameters ),
  356. .parse_root_path = ib_srp_parse_root_path,
  357. .connect = ib_srp_connect,
  358. };