1 /* 2 * Copyright (c) 2004-2009 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 * Copyright (c) 2013 Oracle and/or its affiliates. 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 /* 38 * Abstract: 39 * Implementation of osm_sminfo_rcv_t. 40 * This object represents the SMInfo Receiver object. 41 * This object is part of the opensm family of objects. 42 */ 43 44 #if HAVE_CONFIG_H 45 # include <config.h> 46 #endif /* HAVE_CONFIG_H */ 47 48 #include <stdlib.h> 49 #include <string.h> 50 #include <iba/ib_types.h> 51 #include <complib/cl_qmap.h> 52 #include <complib/cl_passivelock.h> 53 #include <complib/cl_debug.h> 54 #include <opensm/osm_file_ids.h> 55 #define FILE_ID OSM_FILE_SMINFO_RCV_C 56 #include <opensm/osm_madw.h> 57 #include <opensm/osm_log.h> 58 #include <opensm/osm_node.h> 59 #include <opensm/osm_helper.h> 60 #include <opensm/osm_subnet.h> 61 #include <opensm/osm_sm.h> 62 #include <opensm/osm_opensm.h> 63 64 /********************************************************************** 65 Return TRUE if the remote sm given (by ib_sm_info_t) is higher, 66 return FALSE otherwise. 67 By higher - we mean: SM with higher priority or with same priority 68 and lower GUID. 69 **********************************************************************/ 70 static boolean_t smi_rcv_remote_sm_is_higher(IN osm_sm_t * sm, 71 IN const ib_sm_info_t * p_rem_smi) 72 { 73 return osm_sm_is_greater_than(ib_sminfo_get_priority(p_rem_smi), 74 p_rem_smi->guid, 75 sm->p_subn->opt.sm_priority, 76 sm->p_subn->sm_port_guid); 77 78 } 79 80 static void smi_rcv_process_get_request(IN osm_sm_t * sm, 81 IN const osm_madw_t * p_madw, 82 IN boolean_t fill_sm_key) 83 { 84 uint8_t payload[IB_SMP_DATA_SIZE]; 85 ib_sm_info_t *p_smi = (ib_sm_info_t *) payload; 86 ib_api_status_t status; 87 88 OSM_LOG_ENTER(sm->p_log); 89 90 CL_ASSERT(p_madw); 91 92 /* No real need to grab the lock for this function. */ 93 memset(payload, 0, sizeof(payload)); 94 95 CL_ASSERT(osm_madw_get_smp_ptr(p_madw)->method == IB_MAD_METHOD_GET); 96 97 p_smi->guid = sm->p_subn->sm_port_guid; 98 p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent); 99 p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state | 100 sm->p_subn->opt.sm_priority << 4); 101 p_smi->sm_key = fill_sm_key ? sm->p_subn->opt.sm_key : 0; 102 103 status = osm_resp_send(sm, p_madw, 0, payload); 104 if (status != IB_SUCCESS) { 105 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F02: " 106 "Error sending SMInfo response (%s)\n", 107 ib_get_err_str(status)); 108 goto Exit; 109 } 110 111 Exit: 112 OSM_LOG_EXIT(sm->p_log); 113 } 114 115 /********************************************************************** 116 * Check if the p_smp received is legal. 117 * Current checks: 118 * MADHeader:AttributeModifier of ACKNOWLEDGE that was not sent by a 119 * Standby SM. 120 * MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER 121 * that was not sent by a Master SM. 122 * FUTURE - TO DO: 123 * Check that the SM_Key matches. 124 **********************************************************************/ 125 static ib_api_status_t smi_rcv_check_set_req_legality(IN const ib_smp_t * p_smp) 126 { 127 ib_sm_info_t *p_smi; 128 129 p_smi = ib_smp_get_payload_ptr(p_smp); 130 131 if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_ACKNOWLEDGE) { 132 if (ib_sminfo_get_state(p_smi) == IB_SMINFO_STATE_STANDBY) 133 return IB_SUCCESS; 134 } else if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_HANDOVER || 135 p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISABLE || 136 p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY || 137 p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISCOVER) { 138 if (ib_sminfo_get_state(p_smi) == IB_SMINFO_STATE_MASTER) 139 return IB_SUCCESS; 140 } 141 142 return IB_INVALID_PARAMETER; 143 } 144 145 static void smi_rcv_process_set_request(IN osm_sm_t * sm, 146 IN const osm_madw_t * p_madw) 147 { 148 uint8_t payload[IB_SMP_DATA_SIZE]; 149 ib_smp_t *p_smp; 150 ib_sm_info_t *p_smi = (ib_sm_info_t *) payload; 151 ib_sm_info_t *sm_smi; 152 ib_api_status_t status; 153 osm_sm_signal_t sm_signal; 154 155 OSM_LOG_ENTER(sm->p_log); 156 157 CL_ASSERT(p_madw); 158 159 memset(payload, 0, sizeof(payload)); 160 161 p_smp = osm_madw_get_smp_ptr(p_madw); 162 sm_smi = ib_smp_get_payload_ptr(p_smp); 163 164 if (p_smp->method != IB_MAD_METHOD_SET) { 165 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F03: " 166 "Unsupported set method 0x%X\n", p_smp->method); 167 goto Exit; 168 } 169 170 CL_PLOCK_ACQUIRE(sm->p_lock); 171 172 p_smi->guid = sm->p_subn->sm_port_guid; 173 p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent); 174 p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state | 175 sm->p_subn->opt.sm_priority << 4); 176 p_smi->sm_key = sm->p_subn->opt.sm_key; 177 178 /* Check the legality of the packet */ 179 status = smi_rcv_check_set_req_legality(p_smp); 180 if (status != IB_SUCCESS) { 181 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F04: " 182 "Check legality failed. AttributeModifier:0x%X RemoteState:%s\n", 183 p_smp->attr_mod, 184 osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi))); 185 status = osm_resp_send(sm, p_madw, 7, payload); 186 if (status != IB_SUCCESS) 187 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F05: " 188 "Error sending SMInfo response (%s)\n", 189 ib_get_err_str(status)); 190 CL_PLOCK_RELEASE(sm->p_lock); 191 goto Exit; 192 } 193 194 /* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */ 195 switch (p_smp->attr_mod) { 196 case IB_SMINFO_ATTR_MOD_HANDOVER: 197 sm_signal = OSM_SM_SIGNAL_HANDOVER; 198 break; 199 case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE: 200 sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE; 201 break; 202 case IB_SMINFO_ATTR_MOD_DISABLE: 203 sm_signal = OSM_SM_SIGNAL_DISABLE; 204 break; 205 case IB_SMINFO_ATTR_MOD_STANDBY: 206 sm_signal = OSM_SM_SIGNAL_STANDBY; 207 break; 208 case IB_SMINFO_ATTR_MOD_DISCOVER: 209 sm_signal = OSM_SM_SIGNAL_DISCOVER; 210 break; 211 default: 212 /* 213 This code shouldn't be reached - checked in the 214 check legality 215 */ 216 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F06: " 217 "THIS CODE SHOULD NOT BE REACHED!!\n"); 218 CL_PLOCK_RELEASE(sm->p_lock); 219 goto Exit; 220 } 221 222 CL_PLOCK_RELEASE(sm->p_lock); 223 224 /* check legality of the needed transition in the SM state machine */ 225 status = osm_sm_state_mgr_check_legality(sm, sm_signal); 226 if (status != IB_SUCCESS) { 227 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F07: " 228 "Failed check of legality of needed SM transition. " 229 "AttributeModifier:0x%X RemoteState:%s\n", 230 p_smp->attr_mod, 231 osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi))); 232 status = osm_resp_send(sm, p_madw, 7, payload); 233 if (status != IB_SUCCESS) 234 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F08: " 235 "Error sending SMInfo response (%s)\n", 236 ib_get_err_str(status)); 237 goto Exit; 238 } 239 240 /* the SubnSet(SMInfo) command is ok. Send a response. */ 241 status = osm_resp_send(sm, p_madw, 0, payload); 242 if (status != IB_SUCCESS) 243 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F09: " 244 "Error sending SMInfo response (%s)\n", 245 ib_get_err_str(status)); 246 247 /* it is a legal packet - act according to it */ 248 249 /* if the AttributeModifier is STANDBY - need to save on the sm in */ 250 /* the master_sm_guid variable - the guid of the current master. */ 251 if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY) { 252 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 253 "Received a STANDBY signal. Updating " 254 "sm_state_mgr master_guid: 0x%016" PRIx64 "\n", 255 cl_ntoh64(sm_smi->guid)); 256 CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); 257 sm->master_sm_guid = sm_smi->guid; 258 CL_PLOCK_RELEASE(sm->p_lock); 259 } 260 261 status = osm_sm_state_mgr_process(sm, sm_signal); 262 263 if (status != IB_SUCCESS) 264 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F10: " 265 "Error in SM state transition (%s)\n", 266 ib_get_err_str(status)); 267 268 Exit: 269 OSM_LOG_EXIT(sm->p_log); 270 } 271 272 static void smi_rcv_process_get_sm(IN osm_sm_t * sm, 273 IN const osm_remote_sm_t * p_sm, 274 boolean_t light_sweep) 275 { 276 const ib_sm_info_t *p_smi; 277 278 OSM_LOG_ENTER(sm->p_log); 279 280 p_smi = &p_sm->smi; 281 282 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 283 "Detected SM 0x%016" PRIx64 " in state %u (%s)\n", 284 cl_ntoh64(p_smi->guid), ib_sminfo_get_state(p_smi), 285 osm_get_sm_mgr_state_str(ib_sminfo_get_state(p_smi))); 286 287 /* Check the state of this SM vs. our own. */ 288 switch (sm->p_subn->sm_state) { 289 case IB_SMINFO_STATE_NOTACTIVE: 290 break; 291 292 case IB_SMINFO_STATE_DISCOVERING: 293 switch (ib_sminfo_get_state(p_smi)) { 294 case IB_SMINFO_STATE_NOTACTIVE: 295 break; 296 case IB_SMINFO_STATE_MASTER: 297 sm->master_sm_found = 1; 298 /* save on the sm the guid of the current master. */ 299 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 300 "Found master SM. Updating sm_state_mgr master_guid: 0x%016" 301 PRIx64 "\n", cl_ntoh64(p_smi->guid)); 302 sm->master_sm_guid = p_smi->guid; 303 break; 304 case IB_SMINFO_STATE_DISCOVERING: 305 case IB_SMINFO_STATE_STANDBY: 306 if (smi_rcv_remote_sm_is_higher(sm, p_smi)) { 307 /* the remote is a higher sm - need to stop sweeping */ 308 sm->master_sm_found = 1; 309 /* save on the sm the guid of the higher SM we found - */ 310 /* we will poll it - as long as it lives - we should be in Standby. */ 311 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 312 "Found higher SM. Updating sm_state_mgr master_guid:" 313 " 0x%016" PRIx64 "\n", 314 cl_ntoh64(p_smi->guid)); 315 sm->master_sm_guid = p_smi->guid; 316 } 317 break; 318 default: 319 break; 320 } 321 break; 322 323 case IB_SMINFO_STATE_STANDBY: 324 /* if the guid of the SM that sent us this response is equal to the */ 325 /* p_sm_mgr->master_guid - then this is a signal that the polling */ 326 switch (ib_sminfo_get_state(p_smi)) { 327 case IB_SMINFO_STATE_MASTER: 328 /* This means the master is alive */ 329 /* Signal that to the SM state mgr */ 330 osm_sm_state_mgr_signal_master_is_alive(sm); 331 332 if (!smi_rcv_remote_sm_is_higher(sm, p_smi)) 333 osm_send_trap144(sm, 334 TRAP_144_MASK_SM_PRIORITY_CHANGE); 335 break; 336 case IB_SMINFO_STATE_STANDBY: 337 /* This should be the response from the sm we are polling. */ 338 /* If it is - then signal master is alive */ 339 if (sm->master_sm_guid == p_sm->smi.guid) { 340 /* Make sure that it is an SM with higher priority than us. 341 If we started polling it when it was master, and it moved 342 to standby - then it might be with a lower priority than 343 us - and then we don't want to continue polling it. */ 344 if (smi_rcv_remote_sm_is_higher(sm, p_smi)) 345 osm_sm_state_mgr_signal_master_is_alive 346 (sm); 347 } 348 break; 349 default: 350 /* any other state - do nothing */ 351 break; 352 } 353 break; 354 355 case IB_SMINFO_STATE_MASTER: 356 switch (ib_sminfo_get_state(p_smi)) { 357 case IB_SMINFO_STATE_MASTER: 358 /* If this is a response due to our polling, this means that we are 359 * waiting for a handover from this SM, and it is still alive - 360 * signal that. If we detected the remote SM with higher priority 361 * we should init a heavy sweep in order to go STANDBY. If we 362 * detected a remote SM with lower priority, we should resend trap144 363 * as it might not get it and we don't want to wait for a HANDOVER 364 * forever. 365 */ 366 if (sm->polling_sm_guid) { 367 if (smi_rcv_remote_sm_is_higher(sm, p_smi)) 368 sm->p_subn->force_heavy_sweep = TRUE; 369 else { 370 /* Update master_sm_guid to the GUID of the newly 371 * found MASTER SM and send trap 144 to it. 372 */ 373 sm->master_sm_guid = sm->polling_sm_guid; 374 osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE); 375 } 376 osm_sm_state_mgr_signal_master_is_alive(sm); 377 } else { 378 /* This is a response we got while sweeping the subnet. 379 * 380 * If this is during a heavy sweep, we will handle a case of 381 * handover needed later on, when the sweep is done and all 382 * SMs are recognized. 383 * 384 * If this is during a light sweep, initiate a heavy sweep 385 * to initiate handover scenarios. 386 * 387 * Note that it does not matter if the remote SM is lower 388 * or higher priority. If it is lower priority, we must 389 * wait for it HANDOVER. If it is higher priority, we need 390 * to HANDOVER to it. Both cases are handled after doing 391 * a heavy sweep. 392 */ 393 if (light_sweep) 394 sm->p_subn->force_heavy_sweep = TRUE; 395 } 396 break; 397 case IB_SMINFO_STATE_STANDBY: 398 if (light_sweep && 399 smi_rcv_remote_sm_is_higher(sm, p_smi)) 400 sm->p_subn->force_heavy_sweep = TRUE; 401 break; 402 default: 403 /* any other state - do nothing */ 404 break; 405 } 406 break; 407 408 default: 409 break; 410 } 411 412 OSM_LOG_EXIT(sm->p_log); 413 } 414 415 static void smi_rcv_process_get_response(IN osm_sm_t * sm, 416 IN const osm_madw_t * p_madw) 417 { 418 const ib_smp_t *p_smp; 419 const ib_sm_info_t *p_smi; 420 cl_qmap_t *p_sm_tbl; 421 osm_port_t *p_port; 422 ib_net64_t port_guid; 423 osm_remote_sm_t *p_sm; 424 char buf[256]; 425 426 OSM_LOG_ENTER(sm->p_log); 427 428 CL_ASSERT(p_madw); 429 430 p_smp = osm_madw_get_smp_ptr(p_madw); 431 432 if (p_smp->method != IB_MAD_METHOD_GET_RESP) { 433 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F11: " 434 "Unsupported response method 0x%X\n", p_smp->method); 435 goto Exit; 436 } 437 438 p_smi = ib_smp_get_payload_ptr(p_smp); 439 p_sm_tbl = &sm->p_subn->sm_guid_tbl; 440 port_guid = p_smi->guid; 441 442 osm_dump_sm_info_v2(sm->p_log, p_smi, FILE_ID, OSM_LOG_DEBUG); 443 444 /* Check that the sm_key of the found SM is the same as ours, 445 or is zero. If not - OpenSM should ignore this SM */ 446 if (sm->p_subn->opt.sm_key != 0 && p_smi->sm_key != sm->p_subn->opt.sm_key) { 447 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) 448 sprint_uint8_arr(buf, sizeof(buf), 449 p_smp->initial_path, p_smp->hop_count + 1); 450 else 451 sprintf(buf, "LID %u", 452 cl_ntoh16(p_madw->mad_addr.addr_type.smi.source_lid)); 453 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F18: " 454 "Got SM (%s) with sm_key 0x%016" PRIx64 " that doesn't match our " 455 "local sm_key. Ignoring SMInfo\n", buf, cl_ntoh64(p_smi->sm_key)); 456 osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, 457 "Found remote SM (%s) with non-matching sm_key\n", buf); 458 goto Exit; 459 } 460 461 /* Determine if we already have another SM object for this SM. */ 462 CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); 463 464 p_port = osm_get_port_by_guid(sm->p_subn, port_guid); 465 if (!p_port) { 466 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F12: " 467 "No port object for this SM\n"); 468 goto _unlock_and_exit; 469 } 470 471 if (osm_port_get_guid(p_port) != p_smi->guid) { 472 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F13: " 473 "Bogus SM port GUID, Expected 0x%016" PRIx64 474 ", Received 0x%016" PRIx64 "\n", 475 cl_ntoh64(osm_port_get_guid(p_port)), 476 cl_ntoh64(p_smi->guid)); 477 goto _unlock_and_exit; 478 } 479 480 if (port_guid == sm->p_subn->sm_port_guid) { 481 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 482 "Self query response received - SM port 0x%016" PRIx64 483 "\n", cl_ntoh64(port_guid)); 484 goto _unlock_and_exit; 485 } 486 487 p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid); 488 if (p_sm == (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl)) { 489 p_sm = malloc(sizeof(*p_sm)); 490 if (p_sm == NULL) { 491 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F14: " 492 "Unable to allocate SM object\n"); 493 goto _unlock_and_exit; 494 } 495 496 osm_remote_sm_init(p_sm, p_smi); 497 498 cl_qmap_insert(p_sm_tbl, port_guid, &p_sm->map_item); 499 } else 500 /* We already know this SM. Update the SMInfo attribute. */ 501 p_sm->smi = *p_smi; 502 503 smi_rcv_process_get_sm(sm, p_sm, 504 osm_madw_get_smi_context_ptr(p_madw)-> 505 light_sweep); 506 507 _unlock_and_exit: 508 CL_PLOCK_RELEASE(sm->p_lock); 509 510 Exit: 511 OSM_LOG_EXIT(sm->p_log); 512 } 513 514 static void smi_rcv_process_set_response(IN osm_sm_t * sm, 515 IN const osm_madw_t * p_madw) 516 { 517 const ib_smp_t *p_smp; 518 const ib_sm_info_t *p_smi; 519 520 OSM_LOG_ENTER(sm->p_log); 521 522 CL_ASSERT(p_madw); 523 524 p_smp = osm_madw_get_smp_ptr(p_madw); 525 if (ib_smp_get_status(p_smp)) { 526 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 527 "MAD status 0x%x received\n", 528 cl_ntoh16(ib_smp_get_status(p_smp))); 529 goto Exit; 530 } 531 532 if (p_smp->method != IB_MAD_METHOD_GET_RESP) { 533 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F16: " 534 "Unsupported response method 0x%X\n", p_smp->method); 535 goto Exit; 536 } 537 538 p_smi = ib_smp_get_payload_ptr(p_smp); 539 osm_dump_sm_info_v2(sm->p_log, p_smi, FILE_ID, OSM_LOG_DEBUG); 540 541 /* Check the AttributeModifier */ 542 if (p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER) { 543 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F17: " 544 "Unsupported attribute modifier 0x%X, " 545 "expected ATTR_MOD_HANDOVER\n", 546 p_smp->attr_mod); 547 goto Exit; 548 } 549 550 /* This is a response on a HANDOVER request - Nothing to do. */ 551 552 Exit: 553 OSM_LOG_EXIT(sm->p_log); 554 } 555 556 void osm_sminfo_rcv_process(IN void *context, IN void *data) 557 { 558 osm_sm_t *sm = context; 559 osm_madw_t *p_madw = data; 560 ib_smp_t *p_smp; 561 osm_smi_context_t *p_smi_context; 562 563 OSM_LOG_ENTER(sm->p_log); 564 565 CL_ASSERT(p_madw); 566 567 p_smp = osm_madw_get_smp_ptr(p_madw); 568 if (ib_smp_get_status(p_smp)) { 569 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 570 "MAD status 0x%x received\n", 571 cl_ntoh16(ib_smp_get_status(p_smp))); 572 goto Exit; 573 } 574 575 /* Determine if this is a request for our own SMInfo or if 576 this is a response to our request for another SM's SMInfo. */ 577 if (ib_smp_is_response(p_smp)) { 578 const ib_sm_info_t *p_smi = ib_smp_get_payload_ptr(p_smp); 579 580 /* Get the context - to see if this is a response to a Get or Set method */ 581 p_smi_context = osm_madw_get_smi_context_ptr(p_madw); 582 583 /* Verify that response is from expected port and there is 584 no port moving issue. */ 585 if (p_smi_context->port_guid != p_smi->guid) { 586 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F19: " 587 "Unexpected SM port GUID in response" 588 ", Expected 0x%016" PRIx64 589 ", Received 0x%016" PRIx64 "\n", 590 cl_ntoh64(p_smi_context->port_guid), 591 cl_ntoh64(p_smi->guid)); 592 goto Exit; 593 } 594 595 if (p_smi_context->set_method == FALSE) 596 /* this is a response to a Get method */ 597 smi_rcv_process_get_response(sm, p_madw); 598 else 599 /* this is a response to a Set method */ 600 smi_rcv_process_set_response(sm, p_madw); 601 } else { 602 osm_port_t * p_port; 603 ib_net64_t my_mkey; 604 uint8_t mpb; 605 char buf[256]; 606 607 if(!(p_port = osm_get_port_by_guid(sm->p_subn, 608 sm->p_subn->sm_port_guid))) 609 goto Exit; 610 611 if (!p_port->p_physp) 612 goto Exit; 613 614 my_mkey = ib_port_info_get_m_key(&p_port->p_physp->port_info); 615 mpb = my_mkey ? ib_port_info_get_mpb(&p_port->p_physp->port_info) : 0; 616 617 if (p_smp->method == IB_MAD_METHOD_GET) { 618 /* M-Key Authentication */ 619 if (my_mkey && mpb > 1 && my_mkey != p_smp->m_key) { 620 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) 621 sprint_uint8_arr(buf, sizeof(buf), 622 p_smp->return_path, p_smp->hop_count + 1); 623 else 624 sprintf(buf, "LID %u", 625 cl_ntoh16(p_madw->mad_addr.addr_type.smi.source_lid)); 626 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F1A: " 627 "SMInfo(GET) sender (%s) authentication failure." 628 "Ignoring SMInfo\n", buf); 629 goto Exit; 630 } 631 /* If protection bits == 1 but MKEY mismatch, return SM-KEY = 0 */ 632 if (my_mkey && mpb == 1 && my_mkey != p_smp->m_key) 633 smi_rcv_process_get_request(sm, p_madw, FALSE); 634 else 635 smi_rcv_process_get_request(sm, p_madw, TRUE); 636 } else { 637 /* M-Key Authentication */ 638 if (my_mkey && my_mkey != p_smp->m_key) { 639 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) 640 sprint_uint8_arr(buf, sizeof(buf), 641 p_smp->return_path, p_smp->hop_count + 1); 642 else 643 sprintf(buf, "LID %u", 644 cl_ntoh16(p_madw->mad_addr.addr_type.smi.source_lid)); 645 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F1B: " 646 "SMInfo(SET) sender (%s) authentication failure." 647 "Ignoring SMInfo\n", buf); 648 goto Exit; 649 } 650 /* This should be a SubnSet request */ 651 smi_rcv_process_set_request(sm, p_madw); 652 } 653 } 654 655 Exit: 656 OSM_LOG_EXIT(sm->p_log); 657 } 658