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

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