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 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 */ 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 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 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 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 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