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