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.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 ) {
  83. DBGC ( ibdev, "IBDEV %p QPN %lx join failed: %s\n",
  84. ibdev, qp->qpn, strerror ( rc ) );
  85. goto out;
  86. }
  87. /* Extract values from MAD */
  88. joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
  89. qkey = ntohl ( mc_member_record->qkey );
  90. DBGC ( ibdev, "IBDEV %p QPN %lx %s %08x:%08x:%08x:%08x qkey %lx\n",
  91. ibdev, qp->qpn, ( joined ? "joined" : "left" ),
  92. ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
  93. ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ),
  94. qkey );
  95. /* Set queue key */
  96. qp->qkey = qkey;
  97. if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
  98. DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
  99. ibdev, qp->qpn, strerror ( rc ) );
  100. goto out;
  101. }
  102. out:
  103. /* Destroy the completed transaction */
  104. ib_destroy_madx ( ibdev, mi, madx );
  105. membership->madx = NULL;
  106. /* Hand off to upper completion handler */
  107. membership->complete ( ibdev, qp, membership, rc, mad );
  108. }
  109. /** Multicast membership management transaction completion operations */
  110. static struct ib_mad_transaction_operations ib_mcast_op = {
  111. .complete = ib_mcast_complete,
  112. };
  113. /**
  114. * Join multicast group
  115. *
  116. * @v ibdev Infiniband device
  117. * @v qp Queue pair
  118. * @v membership Multicast group membership
  119. * @v gid Multicast GID to join
  120. * @v joined Join completion handler
  121. * @ret rc Return status code
  122. */
  123. int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  124. struct ib_mc_membership *membership, struct ib_gid *gid,
  125. void ( * complete ) ( struct ib_device *ibdev,
  126. struct ib_queue_pair *qp,
  127. struct ib_mc_membership *membership,
  128. int rc, union ib_mad *mad ) ) {
  129. union ib_mad mad;
  130. int rc;
  131. DBGC ( ibdev, "IBDEV %p QPN %lx joining %08x:%08x:%08x:%08x\n",
  132. ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
  133. ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
  134. ntohl ( gid->u.dwords[3] ) );
  135. /* Initialise structure */
  136. membership->qp = qp;
  137. memcpy ( &membership->gid, gid, sizeof ( membership->gid ) );
  138. membership->complete = complete;
  139. /* Attach queue pair to multicast GID */
  140. if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
  141. DBGC ( ibdev, "IBDEV %p QPN %lx could not attach: %s\n",
  142. ibdev, qp->qpn, strerror ( rc ) );
  143. goto err_mcast_attach;
  144. }
  145. /* Initiate multicast membership join */
  146. ib_mcast_mad ( ibdev, gid, 1, &mad );
  147. membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
  148. &ib_mcast_op );
  149. if ( ! membership->madx ) {
  150. DBGC ( ibdev, "IBDEV %p QPN %lx could not create join "
  151. "transaction\n", ibdev, qp->qpn );
  152. rc = -ENOMEM;
  153. goto err_create_madx;
  154. }
  155. ib_madx_set_ownerdata ( membership->madx, membership );
  156. return 0;
  157. ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
  158. err_create_madx:
  159. ib_mcast_detach ( ibdev, qp, gid );
  160. err_mcast_attach:
  161. return rc;
  162. }
  163. /**
  164. * Leave multicast group
  165. *
  166. * @v ibdev Infiniband device
  167. * @v qp Queue pair
  168. * @v membership Multicast group membership
  169. */
  170. void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  171. struct ib_mc_membership *membership ) {
  172. struct ib_gid *gid = &membership->gid;
  173. union ib_mad mad;
  174. int rc;
  175. DBGC ( ibdev, "IBDEV %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
  176. ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
  177. ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
  178. ntohl ( gid->u.dwords[3] ) );
  179. /* Detach from multicast GID */
  180. ib_mcast_detach ( ibdev, qp, &membership->gid );
  181. /* Cancel multicast membership join, if applicable */
  182. if ( membership->madx ) {
  183. ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
  184. membership->madx = NULL;
  185. }
  186. /* Send a single group leave MAD */
  187. ib_mcast_mad ( ibdev, &membership->gid, 0, &mad );
  188. if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
  189. DBGC ( ibdev, "IBDEV %p QPN %lx could not send leave request: "
  190. "%s\n", ibdev, qp->qpn, strerror ( rc ) );
  191. }
  192. }