Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

ib_srp.c 11KB

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