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_mcast.c 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <string.h>
  26. #include <byteswap.h>
  27. #include <errno.h>
  28. #include <ipxe/list.h>
  29. #include <ipxe/infiniband.h>
  30. #include <ipxe/ib_mi.h>
  31. #include <ipxe/ib_mcast.h>
  32. /** @file
  33. *
  34. * Infiniband multicast groups
  35. *
  36. */
  37. /**
  38. * Generate multicast membership MAD
  39. *
  40. * @v ibdev Infiniband device
  41. * @v av Address vector
  42. * @v method Method (IB_MGMT_METHOD_SET or IB_MGMT_METHOD_DELETE)
  43. * @v mask Additional component mask
  44. * @v mad MAD to fill in
  45. */
  46. static void ib_mcast_mad ( struct ib_device *ibdev,
  47. struct ib_address_vector *av,
  48. unsigned int method, unsigned int mask,
  49. union ib_mad *mad ) {
  50. struct ib_mad_sa *sa = &mad->sa;
  51. /* Construct multicast membership record request */
  52. memset ( sa, 0, sizeof ( *sa ) );
  53. sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
  54. sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
  55. sa->mad_hdr.method = method;
  56. sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
  57. sa->sa_hdr.comp_mask[1] =
  58. htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
  59. IB_SA_MCMEMBER_REC_JOIN_STATE | mask );
  60. sa->sa_data.mc_member_record.qkey = htonl ( av->qkey );
  61. sa->sa_data.mc_member_record.pkey =
  62. htons ( ibdev->pkey | IB_PKEY_FULL );
  63. sa->sa_data.mc_member_record.rate_selector__rate = av->rate;
  64. sa->sa_data.mc_member_record.sl__flow_label__hop_limit =
  65. htonl ( av->sl << 28 );
  66. sa->sa_data.mc_member_record.scope__join_state = 0x01;
  67. memcpy ( &sa->sa_data.mc_member_record.mgid, &av->gid,
  68. sizeof ( sa->sa_data.mc_member_record.mgid ) );
  69. memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
  70. sizeof ( sa->sa_data.mc_member_record.port_gid ) );
  71. }
  72. /**
  73. * Handle multicast membership record join response
  74. *
  75. * @v ibdev Infiniband device
  76. * @v mi Management interface
  77. * @v madx Management transaction
  78. * @v rc Status code
  79. * @v mad Received MAD (or NULL on error)
  80. * @v src Source address vector (or NULL on error)
  81. */
  82. static void ib_mcast_complete ( struct ib_device *ibdev,
  83. struct ib_mad_interface *mi __unused,
  84. struct ib_mad_transaction *madx,
  85. int rc, union ib_mad *mad,
  86. struct ib_address_vector *src __unused ) {
  87. struct ib_mc_membership *membership = ib_madx_get_ownerdata ( madx );
  88. struct ib_queue_pair *qp = membership->qp;
  89. struct ib_address_vector *av = membership->av;
  90. struct ib_mc_member_record *mc_member_record =
  91. &mad->sa.sa_data.mc_member_record;
  92. int joined;
  93. /* Report failures */
  94. if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
  95. rc = -ENOTCONN;
  96. if ( rc != 0 ) {
  97. DBGC ( ibdev, "IBDEV %s QPN %#lx join failed: %s\n",
  98. ibdev->name, qp->qpn, strerror ( rc ) );
  99. goto out;
  100. }
  101. /* Extract values from MAD */
  102. joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
  103. av->qkey = ntohl ( mc_member_record->qkey );
  104. av->lid = ntohs ( mc_member_record->mlid );
  105. av->rate = ( mc_member_record->rate_selector__rate & 0x3f );
  106. av->sl = ( ( ntohl ( mc_member_record->sl__flow_label__hop_limit )
  107. >> 28 ) & 0x0f );
  108. DBGC ( ibdev, "IBDEV %s QPN %#lx %s " IB_GID_FMT " qkey %#lx\n",
  109. ibdev->name, qp->qpn, ( joined ? "joined" : "left" ),
  110. IB_GID_ARGS ( &av->gid ), av->qkey );
  111. /* Set queue key */
  112. qp->qkey = av->qkey;
  113. if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
  114. DBGC ( ibdev, "IBDEV %s QPN %#lx could not modify qkey: %s\n",
  115. ibdev->name, qp->qpn, strerror ( rc ) );
  116. goto out;
  117. }
  118. out:
  119. /* Destroy the completed transaction */
  120. ib_destroy_madx ( ibdev, mi, madx );
  121. membership->madx = NULL;
  122. /* Hand off to upper completion handler */
  123. membership->complete ( membership, rc );
  124. }
  125. /** Multicast membership management transaction completion operations */
  126. static struct ib_mad_transaction_operations ib_mcast_op = {
  127. .complete = ib_mcast_complete,
  128. };
  129. /**
  130. * Join multicast group
  131. *
  132. * @v ibdev Infiniband device
  133. * @v qp Queue pair
  134. * @v membership Multicast group membership
  135. * @v av Address vector to fill in
  136. * @v joined Join completion handler
  137. * @ret rc Return status code
  138. */
  139. int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  140. struct ib_mc_membership *membership,
  141. struct ib_address_vector *av, unsigned int mask,
  142. void ( * complete ) ( struct ib_mc_membership *membership,
  143. int rc ) ) {
  144. union ib_mad mad;
  145. int rc;
  146. DBGC ( ibdev, "IBDEV %s QPN %#lx joining " IB_GID_FMT "\n",
  147. ibdev->name, qp->qpn, IB_GID_ARGS ( &av->gid ) );
  148. /* Sanity checks */
  149. assert ( qp != NULL );
  150. assert ( ! membership->attached );
  151. /* Initialise structure */
  152. membership->qp = qp;
  153. membership->av = av;
  154. membership->complete = complete;
  155. /* Attach queue pair to multicast GID */
  156. if ( ( rc = ib_mcast_attach ( ibdev, qp, &av->gid ) ) != 0 ) {
  157. DBGC ( ibdev, "IBDEV %s QPN %#lx could not attach: %s\n",
  158. ibdev->name, qp->qpn, strerror ( rc ) );
  159. goto err_mcast_attach;
  160. }
  161. membership->attached = 1;
  162. /* Initiate multicast membership join */
  163. ib_mcast_mad ( ibdev, av, IB_MGMT_METHOD_SET, mask, &mad );
  164. membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
  165. &ib_mcast_op );
  166. if ( ! membership->madx ) {
  167. DBGC ( ibdev, "IBDEV %s QPN %#lx could not create join "
  168. "transaction\n", ibdev->name, qp->qpn );
  169. rc = -ENOMEM;
  170. goto err_create_madx;
  171. }
  172. ib_madx_set_ownerdata ( membership->madx, membership );
  173. return 0;
  174. ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
  175. err_create_madx:
  176. ib_mcast_detach ( ibdev, qp, &av->gid );
  177. membership->attached = 0;
  178. err_mcast_attach:
  179. return rc;
  180. }
  181. /**
  182. * Leave multicast group
  183. *
  184. * @v ibdev Infiniband device
  185. * @v qp Queue pair
  186. * @v membership Multicast group membership
  187. */
  188. void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  189. struct ib_mc_membership *membership ) {
  190. struct ib_address_vector *av = membership->av;
  191. union ib_mad mad;
  192. int rc;
  193. /* Do nothing if we are already detached from the multicast GID */
  194. if ( ! membership->attached )
  195. return;
  196. DBGC ( ibdev, "IBDEV %s QPN %#lx leaving " IB_GID_FMT "\n",
  197. ibdev->name, qp->qpn, IB_GID_ARGS ( &av->gid ) );
  198. /* Sanity check */
  199. assert ( qp != NULL );
  200. /* Detach from multicast GID */
  201. ib_mcast_detach ( ibdev, qp, &av->gid );
  202. membership->attached = 0;
  203. /* Cancel multicast membership join, if applicable */
  204. if ( membership->madx ) {
  205. ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
  206. membership->madx = NULL;
  207. }
  208. /* Send a single group leave MAD */
  209. ib_mcast_mad ( ibdev, av, IB_MGMT_METHOD_DELETE, 0, &mad );
  210. if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
  211. DBGC ( ibdev, "IBDEV %s QPN %#lx could not send leave request: "
  212. "%s\n", ibdev->name, qp->qpn, strerror ( rc ) );
  213. }
  214. }