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