1 /* 2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. 6 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. 7 * 8 * This software is available to you under a choice of one of two 9 * licenses. You may choose to be licensed under the terms of the GNU 10 * General Public License (GPL) Version 2, available from the file 11 * COPYING in the main directory of this source tree, or the 12 * OpenIB.org BSD license below: 13 * 14 * Redistribution and use in source and binary forms, with or 15 * without modification, are permitted provided that the following 16 * conditions are met: 17 * 18 * - Redistributions of source code must retain the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer. 21 * 22 * - Redistributions in binary form must reproduce the above 23 * copyright notice, this list of conditions and the following 24 * disclaimer in the documentation and/or other materials 25 * provided with the distribution. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 * SOFTWARE. 35 * 36 */ 37 38 /* 39 * Abstract: 40 * Implementation of osm_drop_mgr_t. 41 * This object represents the Drop Manager object. 42 * This object is part of the opensm family of objects. 43 */ 44 45 #if HAVE_CONFIG_H 46 # include <config.h> 47 #endif /* HAVE_CONFIG_H */ 48 49 #include <stdlib.h> 50 #include <string.h> 51 #include <iba/ib_types.h> 52 #include <complib/cl_qmap.h> 53 #include <complib/cl_passivelock.h> 54 #include <complib/cl_debug.h> 55 #include <complib/cl_ptr_vector.h> 56 #include <opensm/osm_file_ids.h> 57 #define FILE_ID OSM_FILE_DROP_MGR_C 58 #include <opensm/osm_sm.h> 59 #include <opensm/osm_router.h> 60 #include <opensm/osm_switch.h> 61 #include <opensm/osm_node.h> 62 #include <opensm/osm_guid.h> 63 #include <opensm/osm_helper.h> 64 #include <opensm/osm_multicast.h> 65 #include <opensm/osm_remote_sm.h> 66 #include <opensm/osm_inform.h> 67 #include <opensm/osm_ucast_mgr.h> 68 69 static void drop_mgr_remove_router(osm_sm_t * sm, IN const ib_net64_t portguid) 70 { 71 osm_router_t *p_rtr; 72 cl_qmap_t *p_rtr_guid_tbl; 73 74 p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl; 75 p_rtr = (osm_router_t *) cl_qmap_remove(p_rtr_guid_tbl, portguid); 76 if (p_rtr != (osm_router_t *) cl_qmap_end(p_rtr_guid_tbl)) { 77 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 78 "Cleaned router for port guid 0x%016" PRIx64 "\n", 79 cl_ntoh64(portguid)); 80 osm_router_delete(&p_rtr); 81 } 82 } 83 84 static void drop_mgr_clean_physp(osm_sm_t * sm, IN osm_physp_t * p_physp) 85 { 86 osm_physp_t *p_remote_physp; 87 osm_port_t *p_remote_port; 88 89 p_remote_physp = osm_physp_get_remote(p_physp); 90 if (p_remote_physp) { 91 p_remote_port = osm_get_port_by_guid(sm->p_subn, 92 p_remote_physp->port_guid); 93 94 if (p_remote_port) { 95 /* Let's check if this is a case of link that is lost 96 (both ports weren't recognized), or a "hiccup" in the 97 subnet - in which case the remote port was 98 recognized, and its state is ACTIVE. 99 If this is just a "hiccup" - force a heavy sweep in 100 the next sweep. We don't want to lose that part of 101 the subnet. */ 102 if (p_remote_port->discovery_count && 103 osm_physp_get_port_state(p_remote_physp) == 104 IB_LINK_ACTIVE) { 105 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 106 "Forcing new heavy sweep. Remote " 107 "port 0x%016" PRIx64 " port num: %u " 108 "was recognized in ACTIVE state\n", 109 cl_ntoh64(p_remote_physp->port_guid), 110 p_remote_physp->port_num); 111 sm->p_subn->force_heavy_sweep = TRUE; 112 } 113 114 /* If the remote node is ca or router - need to remove 115 the remote port, since it is no longer reachable. 116 This can be done if we reset the discovery count 117 of the remote port. */ 118 if (!p_remote_physp->p_node->sw && 119 p_remote_physp->port_guid != sm->p_subn->sm_port_guid) { 120 p_remote_port->discovery_count = 0; 121 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 122 "Resetting discovery count of node: " 123 "0x%016" PRIx64 " port num:%u\n", 124 cl_ntoh64(osm_node_get_node_guid 125 (p_remote_physp->p_node)), 126 p_remote_physp->port_num); 127 } 128 } 129 130 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 131 "Unlinking local node 0x%016" PRIx64 ", port %u" 132 "\n\t\t\t\tand remote node 0x%016" PRIx64 133 ", port %u\n", 134 cl_ntoh64(osm_node_get_node_guid(p_physp->p_node)), 135 p_physp->port_num, 136 cl_ntoh64(osm_node_get_node_guid 137 (p_remote_physp->p_node)), 138 p_remote_physp->port_num); 139 140 if (sm->ucast_mgr.cache_valid) 141 osm_ucast_cache_add_link(&sm->ucast_mgr, p_physp, 142 p_remote_physp); 143 144 osm_physp_unlink(p_physp, p_remote_physp); 145 146 } 147 148 /* Make port as undiscovered */ 149 p_physp->p_node->physp_discovered[p_physp->port_num] = 0; 150 151 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 152 "Clearing node 0x%016" PRIx64 " physical port number %u\n", 153 cl_ntoh64(osm_node_get_node_guid(p_physp->p_node)), 154 p_physp->port_num); 155 156 osm_physp_destroy(p_physp); 157 } 158 159 static void drop_mgr_remove_port(osm_sm_t * sm, IN osm_port_t * p_port) 160 { 161 ib_net64_t port_guid; 162 osm_port_t *p_port_check; 163 cl_qmap_t *p_alias_guid_tbl; 164 cl_qmap_t *p_sm_guid_tbl; 165 osm_mcm_port_t *mcm_port; 166 cl_ptr_vector_t *p_port_lid_tbl; 167 uint16_t min_lid_ho; 168 uint16_t max_lid_ho; 169 uint16_t lid_ho; 170 osm_node_t *p_node; 171 osm_remote_sm_t *p_sm; 172 osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; 173 osm_guidinfo_work_obj_t *wobj; 174 cl_list_item_t *item, *next_item; 175 ib_gid_t port_gid; 176 ib_mad_notice_attr_t notice; 177 ib_api_status_t status; 178 179 OSM_LOG_ENTER(sm->p_log); 180 181 port_guid = osm_port_get_guid(p_port); 182 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 183 "Unreachable port 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); 184 185 p_port_check = 186 (osm_port_t *) cl_qmap_get(&sm->p_subn->port_guid_tbl, port_guid); 187 if (p_port_check != p_port) { 188 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0101: " 189 "Port 0x%016" PRIx64 " not in guid table\n", 190 cl_ntoh64(port_guid)); 191 goto Exit; 192 } 193 194 /* issue a notice - trap 65 (SM_GID_OUT_OF_SERVICE_TRAP) */ 195 /* details of the notice */ 196 notice.generic_type = 0x80 | IB_NOTICE_TYPE_SUBN_MGMT; /* is generic subn mgt type */ 197 ib_notice_set_prod_type_ho(¬ice, 4); /* A class manager generator */ 198 /* endport ceases to be reachable */ 199 notice.g_or_v.generic.trap_num = CL_HTON16(SM_GID_OUT_OF_SERVICE_TRAP); /* 65 */ 200 /* The sm_base_lid is saved in network order already. */ 201 notice.issuer_lid = sm->p_subn->sm_base_lid; 202 /* following C14-72.1.2 and table 119 p725 */ 203 /* we need to provide the GID */ 204 port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; 205 port_gid.unicast.interface_id = port_guid; 206 memcpy(&(notice.data_details.ntc_64_67.gid), 207 &(port_gid), sizeof(ib_gid_t)); 208 209 /* According to page 653 - the issuer gid in this case of trap 210 is the SM gid, since the SM is the initiator of this trap. */ 211 notice.issuer_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; 212 notice.issuer_gid.unicast.interface_id = sm->p_subn->sm_port_guid; 213 214 status = osm_report_notice(sm->p_log, sm->p_subn, ¬ice); 215 if (status != IB_SUCCESS) { 216 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0103: " 217 "Error sending trap reports (%s)\n", 218 ib_get_err_str(status)); 219 } 220 221 next_item = cl_qlist_head(&sm->p_subn->alias_guid_list); 222 while (next_item != cl_qlist_end(&sm->p_subn->alias_guid_list)) { 223 item = next_item; 224 next_item = cl_qlist_next(item); 225 wobj = cl_item_obj(item, wobj, list_item); 226 if (wobj->p_port == p_port) { 227 cl_qlist_remove_item(&sm->p_subn->alias_guid_list, 228 &wobj->list_item); 229 osm_guid_work_obj_delete(wobj); 230 } 231 } 232 233 while (!cl_is_qlist_empty(&p_port->mcm_list)) { 234 mcm_port = cl_item_obj(cl_qlist_head(&p_port->mcm_list), 235 mcm_port, list_item); 236 osm_mgrp_delete_port(sm->p_subn, sm->p_log, mcm_port->mgrp, 237 p_port); 238 } 239 240 p_alias_guid_tbl = &sm->p_subn->alias_port_guid_tbl; 241 p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_head(p_alias_guid_tbl); 242 while (p_alias_guid_check != (osm_alias_guid_t *) cl_qmap_end(p_alias_guid_tbl)) { 243 if (p_alias_guid_check->p_base_port == p_port) 244 p_alias_guid = p_alias_guid_check; 245 else 246 p_alias_guid = NULL; 247 p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid_check->map_item); 248 if (p_alias_guid) { 249 cl_qmap_remove_item(p_alias_guid_tbl, 250 &p_alias_guid->map_item); 251 osm_alias_guid_delete(&p_alias_guid); 252 } 253 } 254 255 cl_qmap_remove(&sm->p_subn->port_guid_tbl, port_guid); 256 257 p_sm_guid_tbl = &sm->p_subn->sm_guid_tbl; 258 p_sm = (osm_remote_sm_t *) cl_qmap_remove(p_sm_guid_tbl, port_guid); 259 if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl)) { 260 /* need to remove this item */ 261 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 262 "Cleaned SM for port guid 0x%016" PRIx64 "\n", 263 cl_ntoh64(port_guid)); 264 free(p_sm); 265 } 266 267 drop_mgr_remove_router(sm, port_guid); 268 269 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); 270 271 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 272 "Clearing abandoned LID range [%u,%u]\n", 273 min_lid_ho, max_lid_ho); 274 275 p_port_lid_tbl = &sm->p_subn->port_lid_tbl; 276 for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) 277 cl_ptr_vector_set(p_port_lid_tbl, lid_ho, NULL); 278 279 drop_mgr_clean_physp(sm, p_port->p_physp); 280 281 /* Delete event forwarding subscriptions */ 282 if (sm->p_subn->opt.drop_event_subscriptions) { 283 if (osm_infr_remove_subscriptions(sm->p_subn, sm->p_log, port_guid) 284 == CL_SUCCESS) 285 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 286 "Removed event subscriptions for port 0x%016" PRIx64 "\n", 287 cl_ntoh64(port_guid)); 288 } 289 290 /* initialize the p_node - may need to get node_desc later */ 291 p_node = p_port->p_node; 292 293 osm_port_delete(&p_port); 294 295 OSM_LOG(sm->p_log, OSM_LOG_INFO, 296 "Removed port with GUID:0x%016" PRIx64 297 " LID range [%u, %u] of node:%s\n", 298 cl_ntoh64(port_gid.unicast.interface_id), 299 min_lid_ho, max_lid_ho, 300 p_node ? p_node->print_desc : "UNKNOWN"); 301 302 Exit: 303 OSM_LOG_EXIT(sm->p_log); 304 } 305 306 static void drop_mgr_remove_switch(osm_sm_t * sm, IN osm_node_t * p_node) 307 { 308 osm_switch_t *p_sw; 309 cl_qmap_t *p_sw_guid_tbl; 310 ib_net64_t node_guid; 311 312 OSM_LOG_ENTER(sm->p_log); 313 314 node_guid = osm_node_get_node_guid(p_node); 315 p_sw_guid_tbl = &sm->p_subn->sw_guid_tbl; 316 317 p_sw = (osm_switch_t *) cl_qmap_remove(p_sw_guid_tbl, node_guid); 318 if (p_sw == (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl)) { 319 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0102: " 320 "Node 0x%016" PRIx64 " not in switch table\n", 321 cl_ntoh64(osm_node_get_node_guid(p_node))); 322 } else { 323 p_node->sw = NULL; 324 osm_switch_delete(&p_sw); 325 } 326 327 OSM_LOG_EXIT(sm->p_log); 328 } 329 330 static boolean_t drop_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node) 331 { 332 osm_physp_t *p_physp; 333 osm_port_t *p_port; 334 osm_node_t *p_node_check; 335 uint32_t port_num; 336 uint32_t max_ports; 337 ib_net64_t port_guid; 338 boolean_t return_val = FALSE; 339 340 OSM_LOG_ENTER(sm->p_log); 341 342 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 343 "Unreachable node 0x%016" PRIx64 "\n", 344 cl_ntoh64(osm_node_get_node_guid(p_node))); 345 346 if (sm->ucast_mgr.cache_valid) 347 osm_ucast_cache_add_node(&sm->ucast_mgr, p_node); 348 349 /* 350 Delete all the logical and physical port objects 351 associated with this node. 352 */ 353 max_ports = osm_node_get_num_physp(p_node); 354 for (port_num = 0; port_num < max_ports; port_num++) { 355 p_physp = osm_node_get_physp_ptr(p_node, port_num); 356 if (p_physp) { 357 port_guid = osm_physp_get_port_guid(p_physp); 358 359 p_port = osm_get_port_by_guid(sm->p_subn, port_guid); 360 361 if (p_port) 362 drop_mgr_remove_port(sm, p_port); 363 else 364 drop_mgr_clean_physp(sm, p_physp); 365 } 366 } 367 368 return_val = TRUE; 369 370 if (p_node->sw) 371 drop_mgr_remove_switch(sm, p_node); 372 373 p_node_check = 374 (osm_node_t *) cl_qmap_remove(&sm->p_subn->node_guid_tbl, 375 osm_node_get_node_guid(p_node)); 376 if (p_node_check != p_node) { 377 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0105: " 378 "Node 0x%016" PRIx64 " not in guid table\n", 379 cl_ntoh64(osm_node_get_node_guid(p_node))); 380 } 381 382 /* free memory allocated to node */ 383 osm_node_delete(&p_node); 384 385 OSM_LOG_EXIT(sm->p_log); 386 return return_val; 387 } 388 389 static void drop_mgr_check_switch_node(osm_sm_t * sm, IN osm_node_t * p_node) 390 { 391 ib_net64_t node_guid; 392 osm_physp_t *p_physp, *p_remote_physp; 393 osm_node_t *p_remote_node; 394 osm_port_t *p_port; 395 ib_net64_t port_guid; 396 uint8_t port_num, remote_port_num; 397 398 OSM_LOG_ENTER(sm->p_log); 399 400 node_guid = osm_node_get_node_guid(p_node); 401 402 /* Make sure we have a switch object for this node */ 403 if (!p_node->sw) { 404 /* We do not have switch info for this node */ 405 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 406 "Node 0x%016" PRIx64 " no switch in table\n", 407 cl_ntoh64(node_guid)); 408 409 drop_mgr_process_node(sm, p_node); 410 goto Exit; 411 } 412 413 /* Make sure we have a port object for port zero */ 414 p_physp = osm_node_get_physp_ptr(p_node, 0); 415 if (!p_physp) { 416 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 417 "Node 0x%016" PRIx64 " no valid physical port 0\n", 418 cl_ntoh64(node_guid)); 419 420 drop_mgr_process_node(sm, p_node); 421 goto Exit; 422 } 423 424 port_guid = osm_physp_get_port_guid(p_physp); 425 426 p_port = osm_get_port_by_guid(sm->p_subn, port_guid); 427 428 if (!p_port) { 429 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 430 "Node 0x%016" PRIx64 " has no port object\n", 431 cl_ntoh64(node_guid)); 432 433 drop_mgr_process_node(sm, p_node); 434 goto Exit; 435 } 436 437 if (!p_node->physp_discovered[0]) { 438 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 439 "Node 0x%016" PRIx64 " port has discovery count zero\n", 440 cl_ntoh64(node_guid)); 441 442 drop_mgr_process_node(sm, p_node); 443 goto Exit; 444 } 445 446 /* 447 * Unlink all ports that havn't been discovered during the last sweep. 448 * Optimization: Skip the check if discovered all the ports of the switch. 449 */ 450 if (p_port->discovery_count < p_node->physp_tbl_size) { 451 for (port_num = 1; port_num < p_node->physp_tbl_size; port_num++) { 452 if (!p_node->physp_discovered[port_num]) { 453 p_physp = osm_node_get_physp_ptr(p_node, port_num); 454 if (!p_physp) 455 continue; 456 p_remote_physp = osm_physp_get_remote(p_physp); 457 if (!p_remote_physp) 458 continue; 459 460 p_remote_node = 461 osm_physp_get_node_ptr(p_remote_physp); 462 remote_port_num = 463 osm_physp_get_port_num(p_remote_physp); 464 465 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, 466 "Unlinking local node 0x%" PRIx64 467 ", port %u" 468 "\n\t\t\t\tand remote node 0x%" PRIx64 469 ", port %u due to missing PortInfo\n", 470 cl_ntoh64(osm_node_get_node_guid 471 (p_node)), port_num, 472 cl_ntoh64(osm_node_get_node_guid 473 (p_remote_node)), 474 remote_port_num); 475 476 if (sm->ucast_mgr.cache_valid) 477 osm_ucast_cache_add_link(&sm->ucast_mgr, 478 p_physp, 479 p_remote_physp); 480 481 osm_node_unlink(p_node, (uint8_t) port_num, 482 p_remote_node, 483 (uint8_t) remote_port_num); 484 } 485 } 486 } 487 Exit: 488 OSM_LOG_EXIT(sm->p_log); 489 return; 490 } 491 492 void osm_drop_mgr_process(osm_sm_t * sm) 493 { 494 cl_qmap_t *p_node_guid_tbl, *p_port_guid_tbl; 495 osm_port_t *p_port, *p_next_port; 496 osm_node_t *p_node, *p_next_node; 497 int max_ports, port_num; 498 osm_physp_t *p_physp; 499 ib_net64_t port_guid; 500 501 CL_ASSERT(sm); 502 503 OSM_LOG_ENTER(sm->p_log); 504 505 p_node_guid_tbl = &sm->p_subn->node_guid_tbl; 506 p_port_guid_tbl = &sm->p_subn->port_guid_tbl; 507 508 CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); 509 510 p_next_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); 511 while (p_next_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl)) { 512 p_node = p_next_node; 513 p_next_node = 514 (osm_node_t *) cl_qmap_next(&p_next_node->map_item); 515 516 CL_ASSERT(cl_qmap_key(&p_node->map_item) == 517 osm_node_get_node_guid(p_node)); 518 519 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 520 "Checking node 0x%016" PRIx64 "\n", 521 cl_ntoh64(osm_node_get_node_guid(p_node))); 522 523 /* 524 Check if this node was discovered during the last sweep. 525 If not, it is unreachable in the current subnet, and 526 should therefore be removed from the subnet object. 527 */ 528 if (p_node->discovery_count == 0) 529 drop_mgr_process_node(sm, p_node); 530 else { 531 /* 532 * We want to preserve the configured pkey indexes, 533 * so if we don't receive GetResp P_KeyTable for some block, 534 * do the following: 535 * 1. Drop node if the node is sw and got timeout for port 0. 536 * 2. Drop node if node is HCA/RTR. 537 * 3. Drop only physp if got timeout for sw when the port isn't 0. 538 * We'll set error during initialization in order to 539 * cause an immediate heavy sweep and try to get the 540 * configured P_KeyTable again. 541 */ 542 if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) 543 port_num = 0; 544 else 545 port_num = 1; 546 max_ports = osm_node_get_num_physp(p_node); 547 for (; port_num < max_ports; port_num++) { 548 p_physp = osm_node_get_physp_ptr(p_node, port_num); 549 if (!p_physp || p_physp->pkeys.rcv_blocks_cnt == 0) 550 continue; 551 p_physp->pkeys.rcv_blocks_cnt = 0; 552 p_physp->need_update = 2; 553 sm->p_subn->subnet_initialization_error = TRUE; 554 port_guid = osm_physp_get_port_guid(p_physp); 555 p_port = osm_get_port_by_guid(sm->p_subn, port_guid); 556 CL_ASSERT(p_port); 557 if (p_node->physp_discovered[port_num]) { 558 p_node->physp_discovered[port_num] = 0; 559 p_port->discovery_count--; 560 } 561 } 562 } 563 } 564 565 /* 566 Go over all the nodes. If the node is a switch - make sure 567 there is also a switch record for it, and a portInfo record for 568 port zero of of the node. 569 If not - this means that there was some error in getting the data 570 of this node. Drop the node. 571 */ 572 p_next_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); 573 while (p_next_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl)) { 574 p_node = p_next_node; 575 p_next_node = 576 (osm_node_t *) cl_qmap_next(&p_next_node->map_item); 577 578 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 579 "Checking full discovery of node 0x%016" PRIx64 "\n", 580 cl_ntoh64(osm_node_get_node_guid(p_node))); 581 582 if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH) 583 continue; 584 585 /* We are handling a switch node */ 586 drop_mgr_check_switch_node(sm, p_node); 587 } 588 589 p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); 590 while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) { 591 p_port = p_next_port; 592 p_next_port = 593 (osm_port_t *) cl_qmap_next(&p_next_port->map_item); 594 595 CL_ASSERT(cl_qmap_key(&p_port->map_item) == 596 osm_port_get_guid(p_port)); 597 598 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 599 "Checking port 0x%016" PRIx64 "\n", 600 cl_ntoh64(osm_port_get_guid(p_port))); 601 602 /* 603 If the port is unreachable, remove it from the guid table. 604 */ 605 if (p_port->discovery_count == 0) 606 drop_mgr_remove_port(sm, p_port); 607 } 608 609 CL_PLOCK_RELEASE(sm->p_lock); 610 OSM_LOG_EXIT(sm->p_log); 611 } 612