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 <complib/cl_debug.h>
43 #include <complib/cl_timer.h>
44 #include <complib/cl_event.h>
45 #include <vendor/osm_vendor_api.h>
46 #include <vendor/osm_vendor_sa_api.h>
47
48 /*****************************************************************************
49 *****************************************************************************/
50
51 /* this struct is the internal rep of the bind handle */
52 typedef struct _osmv_sa_bind_info {
53 osm_bind_handle_t h_bind;
54 osm_log_t *p_log;
55 osm_vendor_t *p_vendor;
56 osm_mad_pool_t *p_mad_pool;
57 uint64_t port_guid;
58 cl_event_t sync_event;
59 uint64_t last_lids_update_sec;
60 uint16_t lid;
61 uint16_t sm_lid;
62 } osmv_sa_bind_info_t;
63
64 /*****************************************************************************
65 *****************************************************************************/
66
67 /*
68 Call back on new mad received:
69
70 We basically only need to set the context of the query.
71 Or report an error.
72
73 A pointer to the actual context of the request (a copy of the oriignal
74 request structure) is attached as the p_madw->context.ni_context.node_guid
75 */
76 void
__osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,IN void * bind_context,IN osm_madw_t * p_req_madw)77 __osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
78 IN void *bind_context, IN osm_madw_t * p_req_madw)
79 {
80 osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
81 osmv_query_req_t *p_query_req_copy = NULL;
82 osmv_query_res_t query_res;
83 ib_sa_mad_t *p_sa_mad;
84 ib_net16_t mad_status;
85
86 OSM_LOG_ENTER(p_bind->p_log);
87
88 if (!p_req_madw) {
89 osm_log(p_bind->p_log, OSM_LOG_DEBUG,
90 "__osmv_sa_mad_rcv_cb: "
91 "Ignoring a non-response mad\n");
92 osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
93 goto Exit;
94 }
95
96 /* obtain the sent context */
97 p_query_req_copy =
98 (osmv_query_req_t *) (p_req_madw->context.arb_context.context1);
99
100 /* provide the context of the original request in the result */
101 query_res.query_context = p_query_req_copy->query_context;
102
103 /* provide the resulting madw */
104 query_res.p_result_madw = p_madw;
105
106 /* update the req fields */
107 p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;
108
109 /* if we got a remote error track it in the status */
110 mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
111 if (mad_status != IB_SUCCESS) {
112 osm_log(p_bind->p_log, OSM_LOG_ERROR,
113 "__osmv_sa_mad_rcv_cb: ERR 0501: "
114 "Remote error:0x%04X .\n", mad_status);
115 query_res.status = IB_REMOTE_ERROR;
116 } else {
117 query_res.status = IB_SUCCESS;
118 }
119
120 /* what if we have got back an empty mad ? */
121 if (!p_madw->mad_size) {
122 osm_log(p_bind->p_log, OSM_LOG_ERROR,
123 "__osmv_sa_mad_rcv_cb: ERR 0502: "
124 "Got an empty mad.\n");
125 query_res.status = IB_ERROR;
126 }
127
128 if (IB_SUCCESS == mad_status) {
129
130 /* if we are in not in a method response of an rmpp nature we must get only 1 */
131 /* HACK: in the future we might need to be smarter for other methods... */
132 if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
133 query_res.result_cnt = 1;
134 } else {
135 #ifndef VENDOR_RMPP_SUPPORT
136 if (mad_status != IB_SUCCESS)
137 query_res.result_cnt = 0;
138 else
139 query_res.result_cnt = 1;
140 #else
141 /* we used the offset value to calculate the number of
142 records in here */
143 if (ib_get_attr_size(p_sa_mad->attr_offset) == 0) {
144 query_res.result_cnt = 0;
145 osm_log(p_bind->p_log, OSM_LOG_DEBUG,
146 "__osmv_sa_mad_rcv_cb: Count = 0\n");
147 }
148 else {
149 query_res.result_cnt = (uintn_t)
150 ((p_madw->mad_size - IB_SA_MAD_HDR_SIZE) /
151 ib_get_attr_size(p_sa_mad->attr_offset));
152 osm_log(p_bind->p_log, OSM_LOG_DEBUG,
153 "__osmv_sa_mad_rcv_cb: "
154 "Count = %u = %zu / %u (%zu)\n",
155 query_res.result_cnt,
156 p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
157 ib_get_attr_size(p_sa_mad->attr_offset),
158 (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) %
159 ib_get_attr_size(p_sa_mad->attr_offset));
160 }
161 #endif
162 }
163 }
164
165 query_res.query_type = p_query_req_copy->query_type;
166
167 p_query_req_copy->pfn_query_cb(&query_res);
168
169 if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
170 cl_event_signal(&p_bind->sync_event);
171
172 Exit:
173
174 /* free the copied query request if found */
175 if (p_query_req_copy)
176 free(p_query_req_copy);
177
178 /* put back the request madw */
179 if (p_req_madw)
180 osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
181
182 OSM_LOG_EXIT(p_bind->p_log);
183 }
184
185 /*****************************************************************************
186 ****************************************************************************/
187 /*
188 Send Error Callback:
189
190 Only report the error and get rid of the mad wrapper
191 */
__osmv_sa_mad_err_cb(IN void * bind_context,IN osm_madw_t * p_madw)192 void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
193 {
194 osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
195 osmv_query_req_t *p_query_req_copy = NULL;
196 osmv_query_res_t query_res;
197
198 OSM_LOG_ENTER(p_bind->p_log);
199
200 /* Obtain the sent context etc */
201 p_query_req_copy =
202 (osmv_query_req_t *) (p_madw->context.arb_context.context1);
203
204 /* provide the context of the original request in the result */
205 query_res.query_context = p_query_req_copy->query_context;
206
207 query_res.p_result_madw = p_madw;
208
209 query_res.status = IB_TIMEOUT;
210 query_res.result_cnt = 0;
211 query_res.p_result_madw->status = IB_TIMEOUT;
212 p_madw->status = IB_TIMEOUT;
213 query_res.query_type = p_query_req_copy->query_type;
214
215 p_query_req_copy->pfn_query_cb(&query_res);
216
217 if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
218 cl_event_signal(&p_bind->sync_event);
219
220 if (p_query_req_copy)
221 free(p_query_req_copy);
222 OSM_LOG_EXIT(p_bind->p_log);
223 }
224
225 /*****************************************************************************
226 This routine needs to be invoked on every send - since the SM LID and Local
227 lid might change. To do that without any major perfoermance impact we cache
228 the results and time they were obtained. Refresh only twice a minute.
229 To avoid the need to use statics and risk a race - we require the refresh time
230 to be stored in the context of the results. Also this coveres cases were
231 we query for multiple guids.
232 *****************************************************************************/
233 ib_api_status_t
__osmv_get_lid_and_sm_lid_by_port_guid(IN osm_vendor_t * const p_vend,IN ib_net64_t port_guid,IN OUT uint64_t * p_lids_update_time_sec,OUT uint16_t * lid,OUT uint16_t * sm_lid)234 __osmv_get_lid_and_sm_lid_by_port_guid(IN osm_vendor_t * const p_vend,
235 IN ib_net64_t port_guid,
236 IN OUT uint64_t * p_lids_update_time_sec,
237 OUT uint16_t * lid,
238 OUT uint16_t * sm_lid)
239 {
240
241 ib_api_status_t status;
242 ib_port_attr_t *p_attr_array;
243 uint32_t num_ports;
244 uint32_t port_num;
245
246 OSM_LOG_ENTER(p_vend->p_log);
247
248 /* use prevous values if current time is close enough to previous query */
249 if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30) {
250 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
251 "__osmv_get_lid_and_sm_lid_by_port_guid: "
252 "Using previously stored lid:0x%04x sm_lid:0x%04x\n",
253 *lid, *sm_lid);
254 status = IB_SUCCESS;
255 goto Exit;
256 }
257
258 /* obtain the number of available ports */
259 num_ports = 0;
260 status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports);
261 if (status != IB_INSUFFICIENT_MEMORY) {
262 osm_log(p_vend->p_log, OSM_LOG_ERROR,
263 "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: "
264 "expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n",
265 ib_get_err_str(status)
266 );
267 status = IB_ERROR;
268 goto Exit;
269 }
270
271 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
272 "__osmv_get_lid_and_sm_lid_by_port_guid: "
273 "Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n",
274 num_ports, cl_ntoh64(port_guid)
275 );
276
277 /* allocate the attributes */
278 p_attr_array =
279 (ib_port_attr_t *) malloc(sizeof(ib_port_attr_t) * num_ports);
280
281 /* obtain the attributes */
282 status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports);
283 if (status != IB_SUCCESS) {
284 osm_log(p_vend->p_log, OSM_LOG_ERROR,
285 "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
286 "Fail to get port attributes (error: %s)\n",
287 ib_get_err_str(status)
288 );
289 free(p_attr_array);
290 goto Exit;
291 }
292
293 status = IB_ERROR;
294 /* find the port requested in the list */
295 for (port_num = 0; (port_num < num_ports) && (status == IB_ERROR);
296 port_num++) {
297 if (p_attr_array[port_num].port_guid == port_guid) {
298 *lid = p_attr_array[port_num].lid;
299 *sm_lid = p_attr_array[port_num].sm_lid;
300 *p_lids_update_time_sec = cl_get_time_stamp_sec();
301 status = IB_SUCCESS;
302 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
303 "__osmv_get_lid_and_sm_lid_by_port_guid: "
304 "Found guid:0x%016" PRIx64 " with idx:%d\n",
305 cl_ntoh64(port_guid), port_num);
306 }
307 }
308
309 free(p_attr_array);
310
311 Exit:
312 OSM_LOG_EXIT(p_vend->p_log);
313 return (status);
314 }
315
316 /*****************************************************************************
317 *****************************************************************************/
318 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)319 osmv_bind_sa(IN osm_vendor_t * const p_vend,
320 IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
321 {
322 osm_bind_info_t bind_info;
323 osm_log_t *p_log = p_vend->p_log;
324 ib_api_status_t status = IB_SUCCESS;
325 osmv_sa_bind_info_t *p_sa_bind_info;
326 cl_status_t cl_status;
327
328 OSM_LOG_ENTER(p_log);
329
330 osm_log(p_log, OSM_LOG_DEBUG,
331 "osmv_bind_sa: "
332 "Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));
333
334 bind_info.port_guid = port_guid;
335 bind_info.mad_class = IB_MCLASS_SUBN_ADM;
336 bind_info.class_version = 2;
337 bind_info.is_responder = TRUE;
338 bind_info.is_trap_processor = FALSE;
339 bind_info.is_report_processor = TRUE;
340 bind_info.send_q_size = 256;
341 bind_info.recv_q_size = 256;
342
343 /* allocate the new sa bind info */
344 p_sa_bind_info =
345 (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
346 if (!p_sa_bind_info) {
347 osm_log(p_log, OSM_LOG_ERROR,
348 "osmv_bind_sa: ERR 0505: "
349 "Fail to allocate new bidn structure\n");
350 p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
351 goto Exit;
352 }
353
354 /* store some important context */
355 p_sa_bind_info->p_log = p_log;
356 p_sa_bind_info->port_guid = port_guid;
357 p_sa_bind_info->p_mad_pool = p_mad_pool;
358 p_sa_bind_info->p_vendor = p_vend;
359 p_sa_bind_info->last_lids_update_sec = 0;
360
361 /* Bind to the lower level */
362 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 */
363
364 if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
365 free(p_sa_bind_info);
366 p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
367 osm_log(p_log, OSM_LOG_ERROR,
368 "osmv_bind_sa: ERR 0506: "
369 "Fail to bind to vendor SMI.\n");
370 goto Exit;
371 }
372
373 /* obtain the sm_lid from the vendor */
374 status =
375 __osmv_get_lid_and_sm_lid_by_port_guid(p_vend, port_guid,
376 &p_sa_bind_info->
377 last_lids_update_sec,
378 &p_sa_bind_info->lid,
379 &p_sa_bind_info->sm_lid);
380 if (status != IB_SUCCESS) {
381 free(p_sa_bind_info);
382 p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
383 osm_log(p_log, OSM_LOG_ERROR,
384 "osmv_bind_sa: ERR 0507: "
385 "Fail to obtain the sm lid.\n");
386 goto Exit;
387 }
388
389 /* initialize the sync_event */
390 cl_event_construct(&p_sa_bind_info->sync_event);
391 cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
392 if (cl_status != CL_SUCCESS) {
393 osm_log(p_log, OSM_LOG_ERROR,
394 "osmv_bind_sa: ERR 0508: "
395 "cl_init_event failed: %s\n", ib_get_err_str(cl_status)
396 );
397 free(p_sa_bind_info);
398 p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
399 }
400
401 Exit:
402 OSM_LOG_EXIT(p_log);
403 return (p_sa_bind_info);
404 }
405
406 /*****************************************************************************
407 *****************************************************************************/
408
409 /****t* OSM Vendor SA Client/osmv_sa_mad_data
410 * NAME
411 * osmv_sa_mad_data
412 *
413 * DESCRIPTION
414 * Extra fields required to perform a mad query
415 * This struct is passed to the actual send method
416 *
417 * SYNOPSIS
418 */
419 typedef struct _osmv_sa_mad_data {
420 /* MAD data. */
421 uint8_t method;
422 ib_net16_t attr_id;
423 ib_net16_t attr_offset;
424 ib_net32_t attr_mod;
425 ib_net64_t comp_mask;
426 void *p_attr;
427 } osmv_sa_mad_data_t;
428 /*
429 * method
430 * The method of the mad to be sent
431 *
432 * attr_id
433 * Attribute ID
434 *
435 * attr_offset
436 * Offset as defined by RMPP
437 *
438 * attr_mod
439 * Attribute modifier
440 *
441 * comp_mask
442 * The component mask of the query
443 *
444 * p_attr
445 * A pointer to the record of the attribute to be sent.
446 *
447 *****/
448
449 /*****************************************************************************
450 *****************************************************************************/
451 /* Send a MAD out on the GSI interface */
452 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)453 __osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
454 IN const osmv_sa_mad_data_t * const p_sa_mad_data,
455 IN const osmv_query_req_t * const p_query_req)
456 {
457 ib_api_status_t status;
458 ib_mad_t *p_mad_hdr;
459 ib_sa_mad_t *p_sa_mad;
460 osm_madw_t *p_madw;
461 osm_log_t *p_log = p_bind->p_log;
462 static atomic32_t trans_id;
463 boolean_t sync;
464 osmv_query_req_t *p_query_req_copy;
465
466 OSM_LOG_ENTER(p_log);
467
468 /*
469 since the sm_lid might change we obtain it every send
470 (actually it is cached in the bind object and refreshed
471 every 30sec by this proc )
472 */
473 status =
474 __osmv_get_lid_and_sm_lid_by_port_guid(p_bind->p_vendor,
475 p_bind->port_guid,
476 &p_bind->
477 last_lids_update_sec,
478 &p_bind->lid,
479 &p_bind->sm_lid);
480 if (status != IB_SUCCESS) {
481 osm_log(p_log, OSM_LOG_ERROR,
482 "__osmv_send_sa_req: ERR 0509: "
483 "Fail to obtain the sm lid.\n");
484 goto Exit;
485 }
486
487 /* Get a MAD wrapper for the send */
488 p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
489 p_bind->h_bind, MAD_BLOCK_SIZE, NULL);
490
491 if (p_madw == NULL) {
492 osm_log(p_log, OSM_LOG_ERROR,
493 "__osmv_send_sa_req: ERR 0510: "
494 "Unable to acquire MAD.\n");
495 status = IB_INSUFFICIENT_RESOURCES;
496 goto Exit;
497 }
498
499 /* Initialize the Sent MAD: */
500
501 /* Initialize the MAD buffer for the send operation. */
502 p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
503 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
504
505 /* Get a new transaction Id */
506 cl_atomic_inc(&trans_id);
507
508 /* Cleanup the MAD from any residue */
509 memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
510
511 /* Initialize the standard MAD header. */
512 ib_mad_init_new(p_mad_hdr, /* mad pointer */
513 IB_MCLASS_SUBN_ADM, /* class */
514 (uint8_t) 2, /* version */
515 p_sa_mad_data->method, /* method */
516 cl_hton64((uint64_t) trans_id), /* tid */
517 p_sa_mad_data->attr_id, /* attr id */
518 p_sa_mad_data->attr_mod /* attr mod */
519 );
520
521 /* Set the query information. */
522 p_sa_mad->sm_key = p_query_req->sm_key;
523 p_sa_mad->attr_offset = 0;
524 p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
525 if (p_sa_mad->comp_mask) {
526 memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
527 ib_get_attr_size(p_sa_mad_data->attr_offset));
528 }
529
530 /*
531 Provide the address to send to
532 */
533 /* Patch to handle IBAL - host order , where it should take destination lid in network order */
534 #ifdef OSM_VENDOR_INTF_AL
535 p_madw->mad_addr.dest_lid = p_bind->sm_lid;
536 #else
537 p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
538 #endif
539 p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->lid);
540 p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
541 p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
542 p_madw->mad_addr.addr_type.gsi.pkey_ix = 0;
543 p_madw->resp_expected = TRUE;
544 p_madw->fail_msg = CL_DISP_MSGID_NONE;
545
546 /*
547 Provide MAD context such that the call back will know what to do.
548 We have to keep the entire request structure so we know the CB.
549 Since we can not rely on the client to keep it arroud until
550 the response - we duplicate it and will later dispose it (in CB).
551 To store on the MADW we cast it into what opensm has:
552 p_madw->context.arb_context.context1
553 */
554 p_query_req_copy = malloc(sizeof(*p_query_req_copy));
555 *p_query_req_copy = *p_query_req;
556 p_madw->context.arb_context.context1 = p_query_req_copy;
557
558 /* we can support async as well as sync calls */
559 sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
560
561 /* send the mad asynchronously */
562 status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
563 p_madw, p_madw->resp_expected);
564
565 /* if synchronous - wait on the event */
566 if (sync) {
567 osm_log(p_log, OSM_LOG_DEBUG,
568 "__osmv_send_sa_req: " "Waiting for async event.\n");
569 cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
570 cl_event_reset(&p_bind->sync_event);
571 status = p_madw->status;
572 }
573
574 Exit:
575 OSM_LOG_EXIT(p_log);
576 return status;
577 }
578
579 /*****************************************************************************
580 *****************************************************************************/
581 /*
582 * Query the SA based on the user's request.
583 */
584 ib_api_status_t
osmv_query_sa(IN osm_bind_handle_t h_bind,IN const osmv_query_req_t * const p_query_req)585 osmv_query_sa(IN osm_bind_handle_t h_bind,
586 IN const osmv_query_req_t * const p_query_req)
587 {
588 osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind;
589 osmv_sa_mad_data_t sa_mad_data;
590 osmv_user_query_t *p_user_query;
591 ib_service_record_t svc_rec;
592 ib_node_record_t node_rec;
593 ib_portinfo_record_t port_info;
594 ib_path_rec_t path_rec;
595 ib_class_port_info_t class_port_info;
596 osm_log_t *p_log = p_bind->p_log;
597 ib_api_status_t status;
598
599 OSM_LOG_ENTER(p_log);
600
601 /* Set the request information. */
602 sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
603 sa_mad_data.attr_mod = 0;
604
605 /* Set the MAD attributes and component mask correctly. */
606 switch (p_query_req->query_type) {
607
608 case OSMV_QUERY_USER_DEFINED:
609 osm_log(p_log, OSM_LOG_DEBUG,
610 "osmv_query_sa DBG:001 %s", "USER_DEFINED\n");
611 p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
612 if (p_user_query->method)
613 sa_mad_data.method = p_user_query->method;
614 sa_mad_data.attr_offset = p_user_query->attr_offset;
615 sa_mad_data.attr_id = p_user_query->attr_id;
616 sa_mad_data.attr_mod = p_user_query->attr_mod;
617 sa_mad_data.comp_mask = p_user_query->comp_mask;
618 sa_mad_data.p_attr = p_user_query->p_attr;
619 break;
620
621 case OSMV_QUERY_ALL_SVC_RECS:
622 osm_log(p_log, OSM_LOG_DEBUG,
623 "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n");
624 sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
625 sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
626 sa_mad_data.attr_offset =
627 ib_get_attr_offset(sizeof(ib_service_record_t));
628 sa_mad_data.comp_mask = 0;
629 sa_mad_data.p_attr = &svc_rec;
630 break;
631
632 case OSMV_QUERY_SVC_REC_BY_NAME:
633 osm_log(p_log, OSM_LOG_DEBUG,
634 "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n");
635 sa_mad_data.method = IB_MAD_METHOD_GET;
636 sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
637 sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
638 sa_mad_data.attr_offset =
639 ib_get_attr_offset(sizeof(ib_service_record_t));
640 sa_mad_data.p_attr = &svc_rec;
641 memcpy(svc_rec.service_name, p_query_req->p_query_input,
642 sizeof(ib_svc_name_t));
643 break;
644
645 case OSMV_QUERY_SVC_REC_BY_ID:
646 osm_log(p_log, OSM_LOG_DEBUG,
647 "osmv_query_sa DBG:001 %s", "SVC_REC_BY_ID\n");
648 sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
649 sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
650 sa_mad_data.attr_offset =
651 ib_get_attr_offset(sizeof(ib_service_record_t));
652 sa_mad_data.p_attr = &svc_rec;
653 svc_rec.service_id =
654 *(ib_net64_t *) (p_query_req->p_query_input);
655 break;
656
657 case OSMV_QUERY_CLASS_PORT_INFO:
658 osm_log(p_log, OSM_LOG_DEBUG,
659 "osmv_query_sa DBG:001 %s", "CLASS_PORT_INFO\n");
660 sa_mad_data.method = IB_MAD_METHOD_GET;
661 sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
662 sa_mad_data.attr_offset =
663 ib_get_attr_offset(sizeof(ib_class_port_info_t));
664 sa_mad_data.comp_mask = 0;
665 sa_mad_data.p_attr = &class_port_info;
666
667 break;
668
669 case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
670 osm_log(p_log, OSM_LOG_DEBUG,
671 "osmv_query_sa DBG:001 %s", "NODE_REC_BY_NODE_GUID\n");
672 sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
673 sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
674 sa_mad_data.attr_offset =
675 ib_get_attr_offset(sizeof(ib_node_record_t));
676 sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
677 sa_mad_data.p_attr = &node_rec;
678 node_rec.node_info.node_guid =
679 *(ib_net64_t *) (p_query_req->p_query_input);
680
681 break;
682
683 case OSMV_QUERY_PORT_REC_BY_LID:
684 osm_log(p_log, OSM_LOG_DEBUG,
685 "osmv_query_sa DBG:001 %s", "PORT_REC_BY_LID\n");
686 sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
687 sa_mad_data.attr_offset =
688 ib_get_attr_offset(sizeof(ib_portinfo_record_t));
689 sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
690 sa_mad_data.p_attr = &port_info;
691 port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input);
692 break;
693
694 case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
695 sa_mad_data.method = IB_MAD_METHOD_GET;
696 p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
697 osm_log(p_log, OSM_LOG_DEBUG,
698 "osmv_query_sa DBG:001 %s",
699 "PORT_REC_BY_LID_AND_NUM\n");
700 sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
701 sa_mad_data.attr_offset =
702 ib_get_attr_offset(sizeof(ib_portinfo_record_t));
703 sa_mad_data.comp_mask =
704 IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
705 sa_mad_data.p_attr = p_user_query->p_attr;
706 break;
707
708 case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
709 sa_mad_data.method = IB_MAD_METHOD_GET;
710 p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
711 osm_log(p_log, OSM_LOG_DEBUG,
712 "osmv_query_sa DBG:001 %s",
713 "OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
714 sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
715 sa_mad_data.attr_offset =
716 ib_get_attr_offset(sizeof(ib_vl_arb_table_record_t));
717 sa_mad_data.comp_mask =
718 IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT |
719 IB_VLA_COMPMASK_BLOCK;
720 sa_mad_data.p_attr = p_user_query->p_attr;
721 break;
722
723 case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
724 sa_mad_data.method = IB_MAD_METHOD_GET;
725 p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
726 osm_log(p_log, OSM_LOG_DEBUG,
727 "osmv_query_sa DBG:001 %s",
728 "OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
729 sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
730 sa_mad_data.attr_offset =
731 ib_get_attr_offset(sizeof(ib_slvl_table_record_t));
732 sa_mad_data.comp_mask =
733 IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT |
734 IB_SLVL_COMPMASK_IN_PORT;
735 sa_mad_data.p_attr = p_user_query->p_attr;
736 break;
737
738 case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
739 osm_log(p_log, OSM_LOG_DEBUG,
740 "osmv_query_sa DBG:001 %s", "PATH_REC_BY_PORT_GUIDS\n");
741 memset(&path_rec, 0, sizeof(ib_path_rec_t));
742 sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
743 sa_mad_data.attr_offset =
744 ib_get_attr_offset(sizeof(ib_path_rec_t));
745 sa_mad_data.comp_mask =
746 (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID);
747 sa_mad_data.p_attr = &path_rec;
748 ib_gid_set_default(&path_rec.dgid,
749 ((osmv_guid_pair_t *) (p_query_req->
750 p_query_input))->
751 dest_guid);
752 ib_gid_set_default(&path_rec.sgid,
753 ((osmv_guid_pair_t *) (p_query_req->
754 p_query_input))->
755 src_guid);
756 break;
757
758 case OSMV_QUERY_PATH_REC_BY_GIDS:
759 osm_log(p_log, OSM_LOG_DEBUG,
760 "osmv_query_sa DBG:001 %s", "PATH_REC_BY_GIDS\n");
761 memset(&path_rec, 0, sizeof(ib_path_rec_t));
762 sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
763 sa_mad_data.attr_offset =
764 ib_get_attr_offset(sizeof(ib_path_rec_t));
765 sa_mad_data.comp_mask =
766 (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID);
767 sa_mad_data.p_attr = &path_rec;
768 memcpy(&path_rec.dgid,
769 &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
770 dest_gid, sizeof(ib_gid_t));
771 memcpy(&path_rec.sgid,
772 &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
773 src_gid, sizeof(ib_gid_t));
774 break;
775
776 case OSMV_QUERY_PATH_REC_BY_LIDS:
777 osm_log(p_log, OSM_LOG_DEBUG,
778 "osmv_query_sa DBG:001 %s", "PATH_REC_BY_LIDS\n");
779 memset(&path_rec, 0, sizeof(ib_path_rec_t));
780 sa_mad_data.method = IB_MAD_METHOD_GET;
781 sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
782 sa_mad_data.attr_offset =
783 ib_get_attr_offset(sizeof(ib_path_rec_t));
784 sa_mad_data.comp_mask =
785 (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID);
786 sa_mad_data.p_attr = &path_rec;
787 path_rec.dlid =
788 ((osmv_lid_pair_t *) (p_query_req->p_query_input))->
789 dest_lid;
790 path_rec.slid =
791 ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid;
792 break;
793
794 case OSMV_QUERY_UD_MULTICAST_SET:
795 sa_mad_data.method = IB_MAD_METHOD_SET;
796 p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
797 osm_log(p_log, OSM_LOG_DEBUG,
798 "osmv_query_sa DBG:001 %s",
799 "OSMV_QUERY_UD_MULTICAST_SET\n");
800 sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
801 sa_mad_data.attr_offset =
802 ib_get_attr_offset(sizeof(ib_member_rec_t));
803 sa_mad_data.comp_mask = p_user_query->comp_mask;
804 sa_mad_data.p_attr = p_user_query->p_attr;
805 break;
806
807 case OSMV_QUERY_UD_MULTICAST_DELETE:
808 sa_mad_data.method = IB_MAD_METHOD_DELETE;
809 p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
810 osm_log(p_log, OSM_LOG_DEBUG,
811 "osmv_query_sa DBG:001 %s",
812 "OSMV_QUERY_UD_MULTICAST_DELETE\n");
813 sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
814 sa_mad_data.attr_offset =
815 ib_get_attr_offset(sizeof(ib_member_rec_t));
816 sa_mad_data.comp_mask = p_user_query->comp_mask;
817 sa_mad_data.p_attr = p_user_query->p_attr;
818 break;
819
820 default:
821 osm_log(p_log, OSM_LOG_ERROR,
822 "osmv_query_sa DBG:001 %s", "UNKNOWN\n");
823 CL_ASSERT(0);
824 return IB_ERROR;
825 }
826
827 status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req);
828
829 OSM_LOG_EXIT(p_log);
830 return status;
831 }
832
833 /*****************************************************************************
834 *****************************************************************************/
835