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 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. FILE_LICENCE ( GPL2_OR_LATER );
  19. #include <stdint.h>
  20. #include <string.h>
  21. #include <byteswap.h>
  22. #include <errno.h>
  23. #include <gpxe/list.h>
  24. #include <gpxe/infiniband.h>
  25. #include <gpxe/ib_mi.h>
  26. #include <gpxe/ib_mcast.h>
  27. /** @file
  28. *
  29. * Infiniband multicast groups
  30. *
  31. */
  32. /**
  33. * Generate multicast membership MAD
  34. *
  35. * @v ibdev Infiniband device
  36. * @v gid Multicast GID
  37. * @v join Join (rather than leave) group
  38. * @v mad MAD to fill in
  39. */
  40. static void ib_mcast_mad ( struct ib_device *ibdev, struct ib_gid *gid,
  41. int join, union ib_mad *mad ) {
  42. struct ib_mad_sa *sa = &mad->sa;
  43. /* Construct multicast membership record request */
  44. memset ( sa, 0, sizeof ( *sa ) );
  45. sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
  46. sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
  47. sa->mad_hdr.method =
  48. ( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
  49. sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
  50. sa->sa_hdr.comp_mask[1] =
  51. htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
  52. IB_SA_MCMEMBER_REC_JOIN_STATE );
  53. sa->sa_data.mc_member_record.scope__join_state = 1;
  54. memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
  55. sizeof ( sa->sa_data.mc_member_record.mgid ) );
  56. memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
  57. sizeof ( sa->sa_data.mc_member_record.port_gid ) );
  58. }
  59. /**
  60. * Handle multicast membership record join response
  61. *
  62. * @v ibdev Infiniband device
  63. * @v mi Management interface
  64. * @v madx Management transaction
  65. * @v rc Status code
  66. * @v mad Received MAD (or NULL on error)
  67. * @v av Source address vector (or NULL on error)
  68. */
  69. static void ib_mcast_complete ( struct ib_device *ibdev,
  70. struct ib_mad_interface *mi __unused,
  71. struct ib_mad_transaction *madx,
  72. int rc, union ib_mad *mad,
  73. struct ib_address_vector *av __unused ) {
  74. struct ib_mc_membership *membership = ib_madx_get_ownerdata ( madx );
  75. struct ib_queue_pair *qp = membership->qp;
  76. struct ib_gid *gid = &membership->gid;
  77. struct ib_mc_member_record *mc_member_record =
  78. &mad->sa.sa_data.mc_member_record;
  79. int joined;
  80. unsigned long qkey;
  81. /* Report failures */
  82. if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
  83. rc = -ENOTCONN;
  84. if ( rc != 0 ) {
  85. DBGC ( ibdev, "IBDEV %p QPN %lx join failed: %s\n",
  86. ibdev, qp->qpn, strerror ( rc ) );
  87. goto out;
  88. }
  89. /* Extract values from MAD */
  90. joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
  91. qkey = ntohl ( mc_member_record->qkey );
  92. DBGC ( ibdev, "IBDEV %p QPN %lx %s %08x:%08x:%08x:%08x qkey %lx\n",
  93. ibdev, qp->qpn, ( joined ? "joined" : "left" ),
  94. ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
  95. ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ),
  96. qkey );
  97. /* Set queue key */
  98. qp->qkey = qkey;
  99. if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
  100. DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
  101. ibdev, qp->qpn, strerror ( rc ) );
  102. goto out;
  103. }
  104. out:
  105. /* Destroy the completed transaction */
  106. ib_destroy_madx ( ibdev, mi, madx );
  107. membership->madx = NULL;
  108. /* Hand off to upper completion handler */
  109. membership->complete ( ibdev, qp, membership, rc, mad );
  110. }
  111. /** Multicast membership management transaction completion operations */
  112. static struct ib_mad_transaction_operations ib_mcast_op = {
  113. .complete = ib_mcast_complete,
  114. };
  115. /**
  116. * Join multicast group
  117. *
  118. * @v ibdev Infiniband device
  119. * @v qp Queue pair
  120. * @v membership Multicast group membership
  121. * @v gid Multicast GID to join
  122. * @v joined Join completion handler
  123. * @ret rc Return status code
  124. */
  125. int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  126. struct ib_mc_membership *membership, struct ib_gid *gid,
  127. void ( * complete ) ( struct ib_device *ibdev,
  128. struct ib_queue_pair *qp,
  129. struct ib_mc_membership *membership,
  130. int rc, union ib_mad *mad ) ) {
  131. union ib_mad mad;
  132. int rc;
  133. DBGC ( ibdev, "IBDEV %p QPN %lx joining %08x:%08x:%08x:%08x\n",
  134. ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
  135. ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
  136. ntohl ( gid->u.dwords[3] ) );
  137. /* Initialise structure */
  138. membership->qp = qp;
  139. memcpy ( &membership->gid, gid, sizeof ( membership->gid ) );
  140. membership->complete = complete;
  141. /* Attach queue pair to multicast GID */
  142. if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
  143. DBGC ( ibdev, "IBDEV %p QPN %lx could not attach: %s\n",
  144. ibdev, qp->qpn, strerror ( rc ) );
  145. goto err_mcast_attach;
  146. }
  147. /* Initiate multicast membership join */
  148. ib_mcast_mad ( ibdev, gid, 1, &mad );
  149. membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
  150. &ib_mcast_op );
  151. if ( ! membership->madx ) {
  152. DBGC ( ibdev, "IBDEV %p QPN %lx could not create join "
  153. "transaction\n", ibdev, qp->qpn );
  154. rc = -ENOMEM;
  155. goto err_create_madx;
  156. }
  157. ib_madx_set_ownerdata ( membership->madx, membership );
  158. return 0;
  159. ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
  160. err_create_madx:
  161. ib_mcast_detach ( ibdev, qp, gid );
  162. err_mcast_attach:
  163. return rc;
  164. }
  165. /**
  166. * Leave multicast group
  167. *
  168. * @v ibdev Infiniband device
  169. * @v qp Queue pair
  170. * @v membership Multicast group membership
  171. */
  172. void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  173. struct ib_mc_membership *membership ) {
  174. struct ib_gid *gid = &membership->gid;
  175. union ib_mad mad;
  176. int rc;
  177. DBGC ( ibdev, "IBDEV %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
  178. ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
  179. ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
  180. ntohl ( gid->u.dwords[3] ) );
  181. /* Detach from multicast GID */
  182. ib_mcast_detach ( ibdev, qp, &membership->gid );
  183. /* Cancel multicast membership join, if applicable */
  184. if ( membership->madx ) {
  185. ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
  186. membership->madx = NULL;
  187. }
  188. /* Send a single group leave MAD */
  189. ib_mcast_mad ( ibdev, &membership->gid, 0, &mad );
  190. if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
  191. DBGC ( ibdev, "IBDEV %p QPN %lx could not send leave request: "
  192. "%s\n", ibdev, qp->qpn, strerror ( rc ) );
  193. }
  194. }