1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  * Copyright (c) 2009,2010 HNR Consulting. All rights reserved.
6  *
7  * This software is available to you under a choice of one of two
8  * licenses.  You may choose to be licensed under the terms of the GNU
9  * General Public License (GPL) Version 2, available from the file
10  * COPYING in the main directory of this source tree, or the
11  * OpenIB.org BSD license below:
12  *
13  *     Redistribution and use in source and binary forms, with or
14  *     without modification, are permitted provided that the following
15  *     conditions are met:
16  *
17  *      - Redistributions of source code must retain the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer.
20  *
21  *      - Redistributions in binary form must reproduce the above
22  *        copyright notice, this list of conditions and the following
23  *        disclaimer in the documentation and/or other materials
24  *        provided with the distribution.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33  * SOFTWARE.
34  *
35  */
36 
37 #if HAVE_CONFIG_H
38 #  include <config.h>
39 #endif				/* HAVE_CONFIG_H */
40 
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/time.h>
44 #include <vendor/osm_vendor_api.h>
45 #include <vendor/osm_vendor_sa_api.h>
46 #include <complib/cl_event.h>
47 
48 /* this struct is the internal rep of the bind handle */
49 typedef struct _osmv_sa_bind_info {
50 	osm_bind_handle_t h_bind;
51 	osm_log_t *p_log;
52 	osm_vendor_t *p_vendor;
53 	osm_mad_pool_t *p_mad_pool;
54 	cl_event_t sync_event;
55 	time_t last_lids_update_sec;
56 } osmv_sa_bind_info_t;
57 
58 /*
59   Call back on new mad received:
60 
61   We basically only need to set the context of the query.
62   Or report an error.
63 
64   A pointer to the actual context of the request (a copy of the oriignal
65   request structure) is attached as the p_madw->context.ni_context.node_guid
66 */
67 static void
68 __osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
69 		     IN void *bind_context, IN osm_madw_t * p_req_madw)
70 {
71 	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
72 	osmv_query_req_t *p_query_req_copy = NULL;
73 	osmv_query_res_t query_res;
74 	ib_sa_mad_t *p_sa_mad;
75 	ib_net16_t mad_status;
76 
77 	OSM_LOG_ENTER(p_bind->p_log);
78 
79 	if (!p_req_madw) {
80 		OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
81 			"Ignoring a non-response mad\n");
82 		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
83 		goto Exit;
84 	}
85 
86 	/* obtain the sent context since we store it during send in the ni_ctx */
87 	p_query_req_copy = (osmv_query_req_t *)
88             (uintptr_t)(osm_madw_get_ni_context_ptr(p_req_madw)->node_guid);
89 
90 	/* provide the context of the original request in the result */
91 	query_res.query_context = p_query_req_copy->query_context;
92 
93 	/* provide the resulting madw */
94 	query_res.p_result_madw = p_madw;
95 
96 	/* update the req fields */
97 	p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;
98 
99 	/* if we got a remote error track it in the status */
100 	mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
101 	if (mad_status != IB_SUCCESS) {
102 		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5501: "
103 			"Remote error: 0x%04X\n", cl_ntoh16(mad_status));
104 		query_res.status = IB_REMOTE_ERROR;
105 	} else
106 		query_res.status = IB_SUCCESS;
107 
108 	/* what if we have got back an empty mad ? */
109 	if (!p_madw->mad_size) {
110 		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5502: "
111 			"Got an empty mad\n");
112 		query_res.status = IB_ERROR;
113 	}
114 
115 	if (IB_SUCCESS == mad_status) {
116 
117 		/* if we are in not in a method response of an rmpp nature we must get only 1 */
118 		/* HACK: in the future we might need to be smarter for other methods... */
119 		if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
120 			query_res.result_cnt = 1;
121 		} else {
122 #ifndef VENDOR_RMPP_SUPPORT
123 			if (mad_status != IB_SUCCESS)
124 				query_res.result_cnt = 0;
125 			else
126 				query_res.result_cnt = 1;
127 #else
128 			if (ib_get_attr_size(p_sa_mad->attr_offset)) {
129 				/* we used the offset value to calculate the
130 				   number of records in here */
131 				query_res.result_cnt =
132 				    (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) /
133 				    ib_get_attr_size(p_sa_mad->attr_offset);
134 				OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
135 					"Count = %u = %zu / %u (%zu)\n",
136 					query_res.result_cnt,
137 					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
138 					ib_get_attr_size(p_sa_mad->attr_offset),
139 					(p_madw->mad_size -
140 					 IB_SA_MAD_HDR_SIZE) %
141 					ib_get_attr_size(p_sa_mad->attr_offset));
142 			} else
143 				query_res.result_cnt = 0;
144 #endif
145 		}
146 	}
147 
148 	query_res.query_type = p_query_req_copy->query_type;
149 
150 	p_query_req_copy->pfn_query_cb(&query_res);
151 
152 	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
153 		cl_event_signal(&p_bind->sync_event);
154 
155 Exit:
156 
157 	/* free the copied query request if found */
158 	if (p_query_req_copy)
159 		free(p_query_req_copy);
160 
161 	/* put back the request madw */
162 	if (p_req_madw)
163 		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
164 
165 	OSM_LOG_EXIT(p_bind->p_log);
166 }
167 
168 /*
169   Send Error Callback:
170 
171   Only report the error and get rid of the mad wrapper
172 */
173 static void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
174 {
175 	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
176 	osmv_query_req_t *p_query_req_copy = NULL;
177 	osmv_query_res_t query_res;
178 
179 	OSM_LOG_ENTER(p_bind->p_log);
180 
181 	/* Obtain the sent context etc */
182 	p_query_req_copy = (osmv_query_req_t *)
183             (uintptr_t)(osm_madw_get_ni_context_ptr(p_madw)->node_guid);
184 
185 	/* provide the context of the original request in the result */
186 	query_res.query_context = p_query_req_copy->query_context;
187 
188 	query_res.p_result_madw = p_madw;
189 
190 	query_res.status = IB_TIMEOUT;
191 	query_res.result_cnt = 0;
192 
193 	query_res.query_type = p_query_req_copy->query_type;
194 
195 	p_query_req_copy->pfn_query_cb(&query_res);
196 
197 	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
198 		cl_event_signal(&p_bind->sync_event);
199 
200 	free(p_query_req_copy);
201 	OSM_LOG_EXIT(p_bind->p_log);
202 }
203 
204 /*****************************************************************************
205  Update lids of vendor umad_port.
206  *****************************************************************************/
207 static ib_api_status_t update_umad_port(osm_vendor_t * p_vend)
208 {
209 	umad_port_t port;
210 	if (umad_get_port(p_vend->umad_port.ca_name,
211 			  p_vend->umad_port.portnum, &port) < 0)
212 		return IB_ERROR;
213 	p_vend->umad_port.base_lid = port.base_lid;
214 	p_vend->umad_port.sm_lid = port.sm_lid;
215 	umad_release_port(&port);
216 	return IB_SUCCESS;
217 }
218 
219 osm_bind_handle_t
220 osmv_bind_sa(IN osm_vendor_t * const p_vend,
221 	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
222 {
223 	osm_bind_info_t bind_info;
224 	osm_log_t *p_log = p_vend->p_log;
225 	osmv_sa_bind_info_t *p_sa_bind_info;
226 	cl_status_t cl_status;
227 
228 	OSM_LOG_ENTER(p_log);
229 
230 	OSM_LOG(p_log, OSM_LOG_DEBUG,
231 		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
232 
233 	bind_info.port_guid = port_guid;
234 	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
235 	bind_info.class_version = 2;
236 	bind_info.is_responder = FALSE;
237 	bind_info.is_trap_processor = FALSE;
238 	bind_info.is_report_processor = FALSE;
239 	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
240 	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
241 	bind_info.timeout = p_vend->timeout;
242 	bind_info.retries = OSM_DEFAULT_RETRY_COUNT;
243 
244 	/* allocate the new sa bind info */
245 	p_sa_bind_info =
246 	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
247 	if (!p_sa_bind_info) {
248 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5505: "
249 			"Failed to allocate new bind structure\n");
250 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
251 		goto Exit;
252 	}
253 
254 	/* store some important context */
255 	p_sa_bind_info->p_log = p_log;
256 	p_sa_bind_info->p_mad_pool = p_mad_pool;
257 	p_sa_bind_info->p_vendor = p_vend;
258 
259 	/* Bind to the lower level */
260 	p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info);	/* context provided to CBs */
261 
262 	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
263 		free(p_sa_bind_info);
264 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
265 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5506: "
266 			"Failed to bind to vendor GSI\n");
267 		goto Exit;
268 	}
269 
270 	/* update time umad_port is initialized now */
271 	p_sa_bind_info->last_lids_update_sec = time(NULL);
272 
273 	/* initialize the sync_event */
274 	cl_event_construct(&p_sa_bind_info->sync_event);
275 	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
276 	if (cl_status != CL_SUCCESS) {
277 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5508: "
278 			"cl_init_event failed: %s\n", ib_get_err_str(cl_status));
279 		free(p_sa_bind_info);
280 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
281 	}
282 
283 Exit:
284 	OSM_LOG_EXIT(p_log);
285 	return (p_sa_bind_info);
286 }
287 
288 /****t* OSM Vendor SA Client/osmv_sa_mad_data
289  * NAME
290  *    osmv_sa_mad_data
291  *
292  * DESCRIPTION
293  * Extra fields required to perform a mad query
294  *  This struct is passed to the actual send method
295  *
296  * SYNOPSIS
297  */
298 typedef struct _osmv_sa_mad_data {
299 	/* MAD data. */
300 	uint8_t method;
301 	ib_net16_t attr_id;
302 	ib_net16_t attr_offset;
303 	ib_net32_t attr_mod;
304 	ib_net64_t comp_mask;
305 	void *p_attr;
306 } osmv_sa_mad_data_t;
307 /*
308  * method
309  *    The method of the mad to be sent
310  *
311  *  attr_id
312  *     Attribute ID
313  *
314  *  attr_offset
315  *     Offset as defined by RMPP
316  *
317  *  attr_mod
318  *     Attribute modifier
319  *
320  *  comp_mask
321  *     The component mask of the query
322  *
323  *  p_attr
324  *     A pointer to the record of the attribute to be sent.
325  *
326  *****/
327 
328 /* Send a MAD out on the GSI interface */
329 static ib_api_status_t
330 __osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
331 		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
332 		   IN const osmv_query_req_t * const p_query_req)
333 {
334 	ib_api_status_t status;
335 	ib_mad_t *p_mad_hdr;
336 	ib_sa_mad_t *p_sa_mad;
337 	osm_madw_t *p_madw;
338 	osm_log_t *p_log = p_bind->p_log;
339 	static atomic32_t trans_id;
340 	boolean_t sync;
341 	osmv_query_req_t *p_query_req_copy;
342 	uint32_t sa_size;
343 
344 	OSM_LOG_ENTER(p_log);
345 
346 	/*
347 	   since the sm_lid might change we obtain it every send
348 	   (actually it is cached in the bind object and refreshed
349 	   every 30sec by this proc)
350 	 */
351 	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
352 		status = update_umad_port(p_bind->p_vendor);
353 		if (status != IB_SUCCESS) {
354 			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
355 				"Failed to obtain the SM lid\n");
356 			goto Exit;
357 		}
358 		p_bind->last_lids_update_sec = time(NULL);
359 	}
360 
361 	/* Get a MAD wrapper for the send */
362 	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
363 				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);
364 
365 	if (p_madw == NULL) {
366 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
367 			"Unable to acquire MAD\n");
368 		status = IB_INSUFFICIENT_RESOURCES;
369 		goto Exit;
370 	}
371 
372 	/* Initialize the Sent MAD: */
373 
374 	/* Initialize the MAD buffer for the send operation. */
375 	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
376 	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
377 
378 	/* Get a new transaction Id */
379 	cl_atomic_inc(&trans_id);
380 
381 	/* Cleanup the MAD from any residue */
382 	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
383 
384 	/* Initialize the standard MAD header. */
385 	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
386 			IB_MCLASS_SUBN_ADM,	/* class */
387 			(uint8_t) 2,	/* version */
388 			p_sa_mad_data->method,	/* method */
389 			cl_hton64((uint64_t) trans_id),	/* tid */
390 			p_sa_mad_data->attr_id,	/* attr id */
391 			p_sa_mad_data->attr_mod	/* attr mod */);
392 
393 	/* Set the query information. */
394 	p_sa_mad->sm_key = p_query_req->sm_key;
395 	p_sa_mad->attr_offset = 0;
396 	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
397 #ifdef DUAL_SIDED_RMPP
398 	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
399 		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
400 #endif
401 	if (p_sa_mad->comp_mask) {
402 		p_sa_mad_data->attr_offset ? (sa_size = ib_get_attr_size(p_sa_mad_data->attr_offset)) : (sa_size = IB_SA_DATA_SIZE);
403 		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr, sa_size);
404 	}
405 
406 	/*
407 	   Provide the address to send to
408 	 */
409 	p_madw->mad_addr.dest_lid =
410 	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
411 	p_madw->mad_addr.addr_type.smi.source_lid =
412 	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
413 	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
414 	p_madw->resp_expected = TRUE;
415 	p_madw->fail_msg = CL_DISP_MSGID_NONE;
416 
417 	/*
418 	   add grh
419 	 */
420 	if (p_query_req->with_grh) {
421 		OSM_LOG(p_log, OSM_LOG_DEBUG, "sending sa query with GRH "
422 			"GID 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
423 			cl_ntoh64(p_query_req->gid.unicast.prefix),
424 			cl_ntoh64(p_query_req->gid.unicast.interface_id));
425 		p_madw->mad_addr.addr_type.gsi.global_route = 1;
426 		memset(&p_madw->mad_addr.addr_type.gsi.grh_info, 0,
427 		       sizeof(p_madw->mad_addr.addr_type.gsi.grh_info));
428 		memcpy(&p_madw->mad_addr.addr_type.gsi.grh_info.dest_gid, &(p_query_req->gid), 16);
429 	}
430 
431 	/*
432 	   Provide MAD context such that the call back will know what to do.
433 	   We have to keep the entire request structure so we know the CB.
434 	   Since we can not rely on the client to keep it around until
435 	   the response - we duplicate it and will later dispose it (in CB).
436 	   To store on the MADW we cast it into what opensm has:
437 	   p_madw->context.ni_context.node_guid
438 	 */
439 	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
440 	if (!p_query_req_copy) {
441 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5511: "
442 			"Unable to acquire memory for query copy\n");
443 		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
444 		status = IB_INSUFFICIENT_RESOURCES;
445 		goto Exit;
446 	}
447 	*p_query_req_copy = *p_query_req;
448 	osm_madw_get_ni_context_ptr(p_madw)->node_guid =
449 	    (ib_net64_t) (uintptr_t)p_query_req_copy;
450 
451 	/* we can support async as well as sync calls */
452 	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
453 
454 	/* send the mad asynchronously */
455 	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
456 				 p_madw, p_madw->resp_expected);
457 
458 	/* if synchronous - wait on the event */
459 	if (sync) {
460 		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
461 		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
462 		cl_event_reset(&p_bind->sync_event);
463 		status = p_madw->status;
464 	}
465 
466 Exit:
467 	OSM_LOG_EXIT(p_log);
468 	return status;
469 }
470 
471 /*
472  * Query the SA based on the user's request.
473  */
474 ib_api_status_t
475 osmv_query_sa(IN osm_bind_handle_t h_bind,
476 	      IN const osmv_query_req_t * const p_query_req)
477 {
478 	union {
479 		ib_service_record_t svc_rec;
480 		ib_node_record_t node_rec;
481 		ib_portinfo_record_t port_info;
482 		ib_path_rec_t path_rec;
483 #ifdef DUAL_SIDED_RMPP
484 		ib_multipath_rec_t multipath_rec;
485 #endif
486 		ib_class_port_info_t class_port_info;
487 	} u;
488 	osmv_sa_mad_data_t sa_mad_data;
489 	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind;
490 	osmv_user_query_t *p_user_query;
491 #ifdef DUAL_SIDED_RMPP
492 	osmv_multipath_req_t *p_mpr_req;
493 	int i, j;
494 #endif
495 	osm_log_t *p_log = p_bind->p_log;
496 	ib_api_status_t status;
497 
498 	OSM_LOG_ENTER(p_log);
499 
500 	/* Set the request information. */
501 	sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
502 	sa_mad_data.attr_mod = 0;
503 	sa_mad_data.attr_offset = 0;
504 
505 	/* Set the MAD attributes and component mask correctly. */
506 	switch (p_query_req->query_type) {
507 
508 	case OSMV_QUERY_USER_DEFINED:
509 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 USER_DEFINED\n");
510 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
511 		if (p_user_query->method)
512 			sa_mad_data.method = p_user_query->method;
513 #ifdef DUAL_SIDED_RMPP
514 		if (sa_mad_data.method == IB_MAD_METHOD_GETMULTI ||
515 		    sa_mad_data.method == IB_MAD_METHOD_GETTRACETABLE)
516 			sa_mad_data.attr_offset = p_user_query->attr_offset;
517 #endif
518 		sa_mad_data.attr_id = p_user_query->attr_id;
519 		sa_mad_data.attr_mod = p_user_query->attr_mod;
520 		sa_mad_data.comp_mask = p_user_query->comp_mask;
521 		sa_mad_data.p_attr = p_user_query->p_attr;
522 		break;
523 
524 	case OSMV_QUERY_ALL_SVC_RECS:
525 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
526 		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
527 		sa_mad_data.comp_mask = 0;
528 		sa_mad_data.p_attr = &u.svc_rec;
529 		break;
530 
531 	case OSMV_QUERY_SVC_REC_BY_NAME:
532 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
533 		sa_mad_data.method = IB_MAD_METHOD_GET;
534 		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
535 		sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
536 		sa_mad_data.p_attr = &u.svc_rec;
537 		memcpy(u.svc_rec.service_name, p_query_req->p_query_input,
538 		       sizeof(ib_svc_name_t));
539 		break;
540 
541 	case OSMV_QUERY_SVC_REC_BY_ID:
542 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_ID\n");
543 		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
544 		sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
545 		sa_mad_data.p_attr = &u.svc_rec;
546 		u.svc_rec.service_id =
547 		    *(ib_net64_t *) (p_query_req->p_query_input);
548 		break;
549 
550 	case OSMV_QUERY_CLASS_PORT_INFO:
551 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 CLASS_PORT_INFO\n");
552 		sa_mad_data.method = IB_MAD_METHOD_GET;
553 		sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
554 		sa_mad_data.comp_mask = 0;
555 		sa_mad_data.p_attr = &u.class_port_info;
556 		break;
557 
558 	case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
559 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 NODE_REC_BY_NODE_GUID\n");
560 		sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
561 		sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
562 		sa_mad_data.p_attr = &u.node_rec;
563 		u.node_rec.node_info.node_guid =
564 		    *(ib_net64_t *) (p_query_req->p_query_input);
565 		break;
566 
567 	case OSMV_QUERY_PORT_REC_BY_LID:
568 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID\n");
569 		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
570 		sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
571 		sa_mad_data.p_attr = &u.port_info;
572 		u.port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input);
573 		break;
574 
575 	case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
576 		sa_mad_data.method = IB_MAD_METHOD_GET;
577 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
578 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID_AND_NUM\n");
579 		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
580 		sa_mad_data.comp_mask =
581 		    IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
582 		sa_mad_data.p_attr = p_user_query->p_attr;
583 		break;
584 
585 	case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
586 		sa_mad_data.method = IB_MAD_METHOD_GET;
587 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
588 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
589 		sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
590 		sa_mad_data.comp_mask =
591 		    IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT |
592 		    IB_VLA_COMPMASK_BLOCK;
593 		sa_mad_data.p_attr = p_user_query->p_attr;
594 		break;
595 
596 	case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
597 		sa_mad_data.method = IB_MAD_METHOD_GET;
598 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
599 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
600 		sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
601 		sa_mad_data.comp_mask =
602 		    IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT |
603 		    IB_SLVL_COMPMASK_IN_PORT;
604 		sa_mad_data.p_attr = p_user_query->p_attr;
605 		break;
606 
607 	case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
608 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_PORT_GUIDS\n");
609 		memset(&u.path_rec, 0, sizeof(ib_path_rec_t));
610 		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
611 		sa_mad_data.comp_mask =
612 		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH);
613 		u.path_rec.num_path = 0x7f;
614 		sa_mad_data.p_attr = &u.path_rec;
615 		ib_gid_set_default(&u.path_rec.dgid,
616 				   ((osmv_guid_pair_t *) (p_query_req->
617 							  p_query_input))->
618 							  dest_guid);
619 		ib_gid_set_default(&u.path_rec.sgid,
620 				   ((osmv_guid_pair_t *) (p_query_req->
621 							  p_query_input))->
622 							  src_guid);
623 		break;
624 
625 	case OSMV_QUERY_PATH_REC_BY_GIDS:
626 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_GIDS\n");
627 		memset(&u.path_rec, 0, sizeof(ib_path_rec_t));
628 		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
629 		sa_mad_data.comp_mask =
630 		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH);
631 		u.path_rec.num_path = 0x7f;
632 		sa_mad_data.p_attr = &u.path_rec;
633 		memcpy(&u.path_rec.dgid,
634 		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
635 					      dest_gid,
636 		       sizeof(ib_gid_t));
637 		memcpy(&u.path_rec.sgid,
638 		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
639 					      src_gid,
640 		       sizeof(ib_gid_t));
641 		break;
642 
643 	case OSMV_QUERY_PATH_REC_BY_LIDS:
644 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_LIDS\n");
645 		memset(&u.path_rec, 0, sizeof(ib_path_rec_t));
646 		sa_mad_data.method = IB_MAD_METHOD_GET;
647 		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
648 		sa_mad_data.comp_mask =
649 		    (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID);
650 		sa_mad_data.p_attr = &u.path_rec;
651 		u.path_rec.dlid =
652 		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->dest_lid;
653 		u.path_rec.slid =
654 		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid;
655 		break;
656 
657 	case OSMV_QUERY_UD_MULTICAST_SET:
658 		sa_mad_data.method = IB_MAD_METHOD_SET;
659 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
660 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_SET\n");
661 		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
662 		sa_mad_data.comp_mask = p_user_query->comp_mask;
663 		sa_mad_data.p_attr = p_user_query->p_attr;
664 		break;
665 
666 	case OSMV_QUERY_UD_MULTICAST_DELETE:
667 		sa_mad_data.method = IB_MAD_METHOD_DELETE;
668 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
669 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_DELETE\n");
670 		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
671 		sa_mad_data.comp_mask = p_user_query->comp_mask;
672 		sa_mad_data.p_attr = p_user_query->p_attr;
673 		break;
674 
675 #ifdef DUAL_SIDED_RMPP
676 	case OSMV_QUERY_MULTIPATH_REC:
677 		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 MULTIPATH_REC\n");
678 		/* Validate sgid/dgid counts against SA client limit */
679 		p_mpr_req = (osmv_multipath_req_t *) p_query_req->p_query_input;
680 		if (p_mpr_req->sgid_count + p_mpr_req->dgid_count >
681 		    IB_MULTIPATH_MAX_GIDS) {
682 			OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 MULTIPATH_REC "
683 				"SGID count %d DGID count %d max count %d\n",
684 				p_mpr_req->sgid_count, p_mpr_req->dgid_count,
685 				IB_MULTIPATH_MAX_GIDS);
686 			CL_ASSERT(0);
687 			return IB_ERROR;
688 		}
689 		memset(&u.multipath_rec, 0, sizeof(ib_multipath_rec_t));
690 		sa_mad_data.method = IB_MAD_METHOD_GETMULTI;
691 		sa_mad_data.attr_id = IB_MAD_ATTR_MULTIPATH_RECORD;
692 		sa_mad_data.attr_offset =
693 		    ib_get_attr_offset(sizeof(ib_multipath_rec_t));
694 		sa_mad_data.p_attr = &u.multipath_rec;
695 		sa_mad_data.comp_mask = p_mpr_req->comp_mask;
696 		u.multipath_rec.num_path = p_mpr_req->num_path;
697 		if (p_mpr_req->reversible)
698 			u.multipath_rec.num_path |= 0x80;
699 		else
700 			u.multipath_rec.num_path &= ~0x80;
701 		u.multipath_rec.pkey = p_mpr_req->pkey;
702 		ib_multipath_rec_set_sl(&u.multipath_rec, p_mpr_req->sl);
703 		ib_multipath_rec_set_qos_class(&u.multipath_rec, 0);
704 		u.multipath_rec.independence = p_mpr_req->independence;
705 		u.multipath_rec.sgid_count = p_mpr_req->sgid_count;
706 		u.multipath_rec.dgid_count = p_mpr_req->dgid_count;
707 		j = 0;
708 		for (i = 0; i < p_mpr_req->sgid_count; i++, j++)
709 			u.multipath_rec.gids[j] = p_mpr_req->gids[j];
710 		for (i = 0; i < p_mpr_req->dgid_count; i++, j++)
711 			u.multipath_rec.gids[j] = p_mpr_req->gids[j];
712 		break;
713 #endif
714 
715 	default:
716 		OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 UNKNOWN\n");
717 		CL_ASSERT(0);
718 		return IB_ERROR;
719 	}
720 
721 	status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req);
722 
723 	OSM_LOG_EXIT(p_log);
724 	return status;
725 }
726