iPXE
ib_mcast.c
Go to the documentation of this file.
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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdint.h>
27#include <string.h>
28#include <byteswap.h>
29#include <errno.h>
30#include <ipxe/list.h>
31#include <ipxe/infiniband.h>
32#include <ipxe/ib_mi.h>
33#include <ipxe/ib_mcast.h>
34
35/** @file
36 *
37 * Infiniband multicast groups
38 *
39 */
40
41/**
42 * Generate multicast membership MAD
43 *
44 * @v ibdev Infiniband device
45 * @v av Address vector
46 * @v method Method (IB_MGMT_METHOD_SET or IB_MGMT_METHOD_DELETE)
47 * @v mask Additional component mask
48 * @v mad MAD to fill in
49 */
50static void ib_mcast_mad ( struct ib_device *ibdev,
51 struct ib_address_vector *av,
52 unsigned int method, unsigned int mask,
53 union ib_mad *mad ) {
54 struct ib_mad_sa *sa = &mad->sa;
55
56 /* Construct multicast membership record request */
57 memset ( sa, 0, sizeof ( *sa ) );
58 sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
59 sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
60 sa->mad_hdr.method = method;
61 sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
62 sa->sa_hdr.comp_mask[1] =
65 sa->sa_data.mc_member_record.qkey = htonl ( av->qkey );
66 sa->sa_data.mc_member_record.pkey =
67 htons ( ibdev->pkey | IB_PKEY_FULL );
68 sa->sa_data.mc_member_record.rate_selector__rate = av->rate;
69 sa->sa_data.mc_member_record.sl__flow_label__hop_limit =
70 htonl ( av->sl << 28 );
71 sa->sa_data.mc_member_record.scope__join_state = 0x01;
72 memcpy ( &sa->sa_data.mc_member_record.mgid, &av->gid,
73 sizeof ( sa->sa_data.mc_member_record.mgid ) );
74 memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
75 sizeof ( sa->sa_data.mc_member_record.port_gid ) );
76}
77
78/**
79 * Handle multicast membership record join response
80 *
81 * @v ibdev Infiniband device
82 * @v mi Management interface
83 * @v madx Management transaction
84 * @v rc Status code
85 * @v mad Received MAD (or NULL on error)
86 * @v src Source address vector (or NULL on error)
87 */
88static void ib_mcast_complete ( struct ib_device *ibdev,
89 struct ib_mad_interface *mi __unused,
90 struct ib_mad_transaction *madx,
91 int rc, union ib_mad *mad,
93 struct ib_mc_membership *membership = ib_madx_get_ownerdata ( madx );
94 struct ib_queue_pair *qp = membership->qp;
95 struct ib_address_vector *av = membership->av;
97 &mad->sa.sa_data.mc_member_record;
98 int joined;
99
100 /* Report failures */
101 if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
102 rc = -ENOTCONN;
103 if ( rc != 0 ) {
104 DBGC ( ibdev, "IBDEV %s QPN %#lx join failed: %s\n",
105 ibdev->name, qp->qpn, strerror ( rc ) );
106 goto out;
107 }
108
109 /* Extract values from MAD */
110 joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
111 av->qkey = ntohl ( mc_member_record->qkey );
112 av->lid = ntohs ( mc_member_record->mlid );
113 av->rate = ( mc_member_record->rate_selector__rate & 0x3f );
114 av->sl = ( ( ntohl ( mc_member_record->sl__flow_label__hop_limit )
115 >> 28 ) & 0x0f );
116 DBGC ( ibdev, "IBDEV %s QPN %#lx %s " IB_GID_FMT " qkey %#lx\n",
117 ibdev->name, qp->qpn, ( joined ? "joined" : "left" ),
118 IB_GID_ARGS ( &av->gid ), av->qkey );
119
120 /* Set queue key */
121 qp->qkey = av->qkey;
122 if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
123 DBGC ( ibdev, "IBDEV %s QPN %#lx could not modify qkey: %s\n",
124 ibdev->name, qp->qpn, strerror ( rc ) );
125 goto out;
126 }
127
128 out:
129 /* Destroy the completed transaction */
130 ib_destroy_madx ( ibdev, mi, madx );
131 membership->madx = NULL;
132
133 /* Hand off to upper completion handler */
134 membership->complete ( membership, rc );
135}
136
137/** Multicast membership management transaction completion operations */
139 .complete = ib_mcast_complete,
140};
141
142/**
143 * Join multicast group
144 *
145 * @v ibdev Infiniband device
146 * @v qp Queue pair
147 * @v membership Multicast group membership
148 * @v av Address vector to fill in
149 * @v joined Join completion handler
150 * @ret rc Return status code
151 */
152int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
153 struct ib_mc_membership *membership,
154 struct ib_address_vector *av, unsigned int mask,
155 void ( * complete ) ( struct ib_mc_membership *membership,
156 int rc ) ) {
157 union ib_mad mad;
158 int rc;
159
160 DBGC ( ibdev, "IBDEV %s QPN %#lx joining " IB_GID_FMT "\n",
161 ibdev->name, qp->qpn, IB_GID_ARGS ( &av->gid ) );
162
163 /* Sanity checks */
164 assert ( qp != NULL );
165 assert ( ! membership->attached );
166
167 /* Initialise structure */
168 membership->qp = qp;
169 membership->av = av;
170 membership->complete = complete;
171
172 /* Attach queue pair to multicast GID */
173 if ( ( rc = ib_mcast_attach ( ibdev, qp, &av->gid ) ) != 0 ) {
174 DBGC ( ibdev, "IBDEV %s QPN %#lx could not attach: %s\n",
175 ibdev->name, qp->qpn, strerror ( rc ) );
176 goto err_mcast_attach;
177 }
178 membership->attached = 1;
179
180 /* Initiate multicast membership join */
181 ib_mcast_mad ( ibdev, av, IB_MGMT_METHOD_SET, mask, &mad );
182 membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
183 &ib_mcast_op );
184 if ( ! membership->madx ) {
185 DBGC ( ibdev, "IBDEV %s QPN %#lx could not create join "
186 "transaction\n", ibdev->name, qp->qpn );
187 rc = -ENOMEM;
188 goto err_create_madx;
189 }
190 ib_madx_set_ownerdata ( membership->madx, membership );
191
192 return 0;
193
194 ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
195 err_create_madx:
196 ib_mcast_detach ( ibdev, qp, &av->gid );
197 membership->attached = 0;
198 err_mcast_attach:
199 return rc;
200}
201
202/**
203 * Leave multicast group
204 *
205 * @v ibdev Infiniband device
206 * @v qp Queue pair
207 * @v membership Multicast group membership
208 */
209void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
210 struct ib_mc_membership *membership ) {
211 struct ib_address_vector *av = membership->av;
212 union ib_mad mad;
213 int rc;
214
215 /* Do nothing if we are already detached from the multicast GID */
216 if ( ! membership->attached )
217 return;
218
219 DBGC ( ibdev, "IBDEV %s QPN %#lx leaving " IB_GID_FMT "\n",
220 ibdev->name, qp->qpn, IB_GID_ARGS ( &av->gid ) );
221
222 /* Sanity check */
223 assert ( qp != NULL );
224
225 /* Detach from multicast GID */
226 ib_mcast_detach ( ibdev, qp, &av->gid );
227 membership->attached = 0;
228
229 /* Cancel multicast membership join, if applicable */
230 if ( membership->madx ) {
231 ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
232 membership->madx = NULL;
233 }
234
235 /* Send a single group leave MAD */
236 ib_mcast_mad ( ibdev, av, IB_MGMT_METHOD_DELETE, 0, &mad );
237 if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
238 DBGC ( ibdev, "IBDEV %s QPN %#lx could not send leave request: "
239 "%s\n", ibdev->name, qp->qpn, strerror ( rc ) );
240 }
241}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__be32 out[4]
Definition CIB_PRM.h:8
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
union ib_mad mad
Definition arbel.h:1
struct arbelprm_qp_db_record qp
Definition arbel.h:2
static const void * src
Definition string.h:48
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTCONN
The socket is not connected.
Definition errno.h:570
#define IB_SA_ATTR_MC_MEMBER_REC
Definition ib_mad.h:225
#define IB_MGMT_METHOD_GET_RESP
Definition ib_mad.h:572
struct ib_mc_member_record mc_member_record
Definition ib_mad.h:2
#define IB_SA_MCMEMBER_REC_MGID
Definition ib_mad.h:279
#define IB_MGMT_STATUS_OK
Definition ib_mad.h:581
#define IB_SA_CLASS_VERSION
Definition ib_mad.h:208
uint8_t method
Definition ib_mad.h:3
#define IB_MGMT_CLASS_SUBN_ADM
Definition ib_mad.h:558
#define IB_SA_MCMEMBER_REC_JOIN_STATE
Definition ib_mad.h:295
#define IB_MGMT_METHOD_SET
Definition ib_mad.h:571
#define IB_MGMT_METHOD_DELETE
Definition ib_mad.h:578
#define IB_SA_MCMEMBER_REC_PORT_GID
Definition ib_mad.h:280
static struct ib_mad_transaction_operations ib_mcast_op
Multicast membership management transaction completion operations.
Definition ib_mcast.c:138
int ib_mcast_join(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_mc_membership *membership, struct ib_address_vector *av, unsigned int mask, void(*complete)(struct ib_mc_membership *membership, int rc))
Join multicast group.
Definition ib_mcast.c:152
void ib_mcast_leave(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_mc_membership *membership)
Leave multicast group.
Definition ib_mcast.c:209
static void ib_mcast_complete(struct ib_device *ibdev, struct ib_mad_interface *mi __unused, struct ib_mad_transaction *madx, int rc, union ib_mad *mad, struct ib_address_vector *src __unused)
Handle multicast membership record join response.
Definition ib_mcast.c:88
static void ib_mcast_mad(struct ib_device *ibdev, struct ib_address_vector *av, unsigned int method, unsigned int mask, union ib_mad *mad)
Generate multicast membership MAD.
Definition ib_mcast.c:50
Infiniband multicast groups.
int ib_mi_send(struct ib_device *ibdev, struct ib_mad_interface *mi, union ib_mad *mad, struct ib_address_vector *av)
Transmit MAD.
Definition ib_mi.c:187
struct ib_mad_transaction * ib_create_madx(struct ib_device *ibdev, struct ib_mad_interface *mi, union ib_mad *mad, struct ib_address_vector *av, struct ib_mad_transaction_operations *op)
Create management transaction.
Definition ib_mi.c:287
void ib_destroy_madx(struct ib_device *ibdev __unused, struct ib_mad_interface *mi __unused, struct ib_mad_transaction *madx)
Destroy management transaction.
Definition ib_mi.c:327
Infiniband management interfaces.
static __always_inline void ib_madx_set_ownerdata(struct ib_mad_transaction *madx, void *priv)
Set Infiniband management transaction owner-private data.
Definition ib_mi.h:106
static __always_inline void * ib_madx_get_ownerdata(struct ib_mad_transaction *madx)
Get Infiniband management transaction owner-private data.
Definition ib_mi.h:117
#define IB_GID_ARGS(gid)
Infiniband Global Identifier debug message arguments.
Definition ib_packet.h:49
#define IB_GID_FMT
Infiniband Global Identifier debug message format.
Definition ib_packet.h:46
#define ntohl(value)
Definition byteswap.h:135
#define htonl(value)
Definition byteswap.h:134
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
int ib_mcast_attach(struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
Attach to multicast group.
Definition infiniband.c:752
int ib_modify_qp(struct ib_device *ibdev, struct ib_queue_pair *qp)
Modify queue pair.
Definition infiniband.c:294
void ib_mcast_detach(struct ib_device *ibdev, struct ib_queue_pair *qp, union ib_gid *gid)
Detach from multicast group.
Definition infiniband.c:789
Infiniband protocol.
#define IB_PKEY_FULL
Infiniband partition key full membership flag.
Definition infiniband.h:43
Linked lists.
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An Infiniband Address Vector.
Definition infiniband.h:73
unsigned int sl
Service level.
Definition infiniband.h:89
unsigned long qkey
Queue key.
Definition infiniband.h:80
unsigned int lid
Local ID.
Definition infiniband.h:82
enum ib_rate rate
Rate.
Definition infiniband.h:87
union ib_gid gid
GID, if present.
Definition infiniband.h:93
An Infiniband device.
Definition infiniband.h:399
struct ib_mad_interface * gsi
General services interface.
Definition infiniband.h:462
char name[IBDEV_NAME_LEN]
Name of this Infiniband device.
Definition infiniband.h:409
uint16_t pkey
Partition key.
Definition infiniband.h:450
union ib_gid gid
Port GID (comprising GID prefix and port GUID)
Definition infiniband.h:442
An Infiniband management interface.
Definition ib_mi.h:88
A subnet administration MAD.
Definition ib_mad.h:597
Infiniband management transaction operations.
Definition ib_mi.h:49
void(* complete)(struct ib_device *ibdev, struct ib_mad_interface *mi, struct ib_mad_transaction *madx, int rc, union ib_mad *mad, struct ib_address_vector *av)
Handle transaction completion.
Definition ib_mi.h:62
An Infiniband management transaction.
Definition ib_mi.h:70
An Infiniband multicast group membership.
Definition ib_mcast.h:17
void(* complete)(struct ib_mc_membership *membership, int rc)
Handle join success/failure.
Definition ib_mcast.h:31
struct ib_address_vector * av
Address vector.
Definition ib_mcast.h:21
struct ib_queue_pair * qp
Queue pair.
Definition ib_mcast.h:19
int attached
Attached to multicast GID.
Definition ib_mcast.h:23
struct ib_mad_transaction * madx
Multicast group join transaction.
Definition ib_mcast.h:25
An Infiniband Queue Pair.
Definition infiniband.h:158
struct sockaddr sa
Definition syslog.c:57
A management datagram.
Definition ib_mad.h:611