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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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_gma.h>
  26. #include <gpxe/ib_mcast.h>
  27. /** @file
  28. *
  29. * Infiniband multicast groups
  30. *
  31. */
  32. /**
  33. * Transmit multicast group membership request
  34. *
  35. * @v ibdev Infiniband device
  36. * @v gid Multicast GID
  37. * @v join Join (rather than leave) group
  38. * @ret rc Return status code
  39. */
  40. static int ib_mc_member_request ( struct ib_device *ibdev, struct ib_gid *gid,
  41. int join ) {
  42. union ib_mad mad;
  43. struct ib_mad_sa *sa = &mad.sa;
  44. int rc;
  45. /* Construct multicast membership record request */
  46. memset ( sa, 0, sizeof ( *sa ) );
  47. sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
  48. sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
  49. sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
  50. sa->mad_hdr.method =
  51. ( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
  52. sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
  53. sa->sa_hdr.comp_mask[1] =
  54. htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
  55. IB_SA_MCMEMBER_REC_JOIN_STATE );
  56. sa->sa_data.mc_member_record.scope__join_state = 1;
  57. memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
  58. sizeof ( sa->sa_data.mc_member_record.mgid ) );
  59. memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
  60. sizeof ( sa->sa_data.mc_member_record.port_gid ) );
  61. /* Issue multicast membership record request */
  62. if ( ( rc = ib_gma_request ( &ibdev->gma, &mad, NULL,
  63. join ) ) != 0 ) {
  64. DBGC ( ibdev, "IBDEV %p could not join group: %s\n",
  65. ibdev, strerror ( rc ) );
  66. return rc;
  67. }
  68. return 0;
  69. }
  70. /**
  71. * Join multicast group
  72. *
  73. * @v ibdev Infiniband device
  74. * @v qp Queue pair
  75. * @v gid Multicast GID
  76. * @ret rc Return status code
  77. */
  78. int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  79. struct ib_gid *gid ) {
  80. int rc;
  81. DBGC ( ibdev, "IBDEV %p QPN %lx joining %08x:%08x:%08x:%08x\n",
  82. ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
  83. ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
  84. ntohl ( gid->u.dwords[3] ) );
  85. /* Attach queue pair to multicast GID */
  86. if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
  87. DBGC ( ibdev, "IBDEV %p could not attach: %s\n",
  88. ibdev, strerror ( rc ) );
  89. goto err_mcast_attach;
  90. }
  91. /* Initiate multicast membership join */
  92. if ( ( rc = ib_mc_member_request ( ibdev, gid, 1 ) ) != 0 )
  93. goto err_mc_member_record;
  94. return 0;
  95. err_mc_member_record:
  96. ib_mcast_detach ( ibdev, qp, gid );
  97. err_mcast_attach:
  98. return rc;
  99. }
  100. /**
  101. * Leave multicast group
  102. *
  103. * @v ibdev Infiniband device
  104. * @v qp Queue pair
  105. * @v gid Multicast GID
  106. */
  107. void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
  108. struct ib_gid *gid ) {
  109. DBGC ( ibdev, "IBDEV %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
  110. ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
  111. ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
  112. ntohl ( gid->u.dwords[3] ) );
  113. /* Detach queue pair from multicast GID */
  114. ib_mcast_detach ( ibdev, qp, gid );
  115. /* Initiate multicast membership leave */
  116. ib_mc_member_request ( ibdev, gid, 0 );
  117. }
  118. /**
  119. * Handle multicast membership record join response
  120. *
  121. * @v ibdev Infiniband device
  122. * @v mad MAD
  123. * @ret rc Return status code
  124. */
  125. static int ib_handle_mc_member_join ( struct ib_device *ibdev,
  126. union ib_mad *mad ) {
  127. struct ib_mc_member_record *mc_member_record =
  128. &mad->sa.sa_data.mc_member_record;
  129. struct ib_queue_pair *qp;
  130. struct ib_gid *gid;
  131. unsigned long qkey;
  132. int rc;
  133. /* Ignore if not a success */
  134. if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
  135. DBGC ( ibdev, "IBDEV %p join failed with status %04x\n",
  136. ibdev, ntohs ( mad->hdr.status ) );
  137. return -EINVAL;
  138. }
  139. /* Extract MAD parameters */
  140. gid = &mc_member_record->mgid;
  141. qkey = ntohl ( mc_member_record->qkey );
  142. /* Locate matching queue pair */
  143. qp = ib_find_qp_mgid ( ibdev, gid );
  144. if ( ! qp ) {
  145. DBGC ( ibdev, "IBDEV %p has no QP to join "
  146. "%08x:%08x:%08x:%08x\n", ibdev,
  147. ntohl ( gid->u.dwords[0] ),
  148. ntohl ( gid->u.dwords[1] ),
  149. ntohl ( gid->u.dwords[2] ),
  150. ntohl ( gid->u.dwords[3] ) );
  151. return -ENOENT;
  152. }
  153. DBGC ( ibdev, "IBDEV %p QPN %lx joined %08x:%08x:%08x:%08x qkey "
  154. "%lx\n", ibdev, qp->qpn,
  155. ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
  156. ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ),
  157. qkey );
  158. /* Set queue key */
  159. if ( ( rc = ib_modify_qp ( ibdev, qp, IB_MODIFY_QKEY, qkey ) ) != 0 ) {
  160. DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
  161. ibdev, qp->qpn, strerror ( rc ) );
  162. return rc;
  163. }
  164. return 0;
  165. }
  166. /**
  167. * Handle multicast membership record leave response
  168. *
  169. * @v ibdev Infiniband device
  170. * @v mad MAD
  171. * @ret rc Return status code
  172. */
  173. static int ib_handle_mc_member_leave ( struct ib_device *ibdev,
  174. union ib_mad *mad ) {
  175. struct ib_mc_member_record *mc_member_record =
  176. &mad->sa.sa_data.mc_member_record;
  177. struct ib_gid *gid;
  178. /* Ignore if not a success */
  179. if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
  180. DBGC ( ibdev, "IBDEV %p leave failed with status %04x\n",
  181. ibdev, ntohs ( mad->hdr.status ) );
  182. return -EINVAL;
  183. }
  184. /* Extract MAD parameters */
  185. gid = &mc_member_record->mgid;
  186. DBGC ( ibdev, "IBDEV %p left %08x:%08x:%08x:%08x\n", ibdev,
  187. ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
  188. ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ) );
  189. return 0;
  190. }
  191. /** Multicast membership record response handler */
  192. struct ib_mad_handler ib_mc_member_record_handlers[] __ib_mad_handler = {
  193. {
  194. .mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
  195. .class_version = IB_SA_CLASS_VERSION,
  196. .method = IB_MGMT_METHOD_GET_RESP,
  197. .attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC ),
  198. .handle = ib_handle_mc_member_join,
  199. },
  200. {
  201. .mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
  202. .class_version = IB_SA_CLASS_VERSION,
  203. .method = IB_SA_METHOD_DELETE_RESP,
  204. .attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC ),
  205. .handle = ib_handle_mc_member_leave,
  206. },
  207. };