static void lr_rcv_get_port_links(IN osm_sa_t * sa, IN const ib_link_record_t * p_lr, IN const osm_port_t * p_src_port, IN const osm_port_t * p_dest_port, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list, IN const osm_physp_t * p_req_physp) { const osm_physp_t *p_src_physp; const osm_physp_t *p_dest_physp; const cl_qmap_t *p_node_tbl; osm_node_t *p_node; uint8_t port_num; uint8_t num_ports; uint8_t dest_num_ports; uint8_t dest_port_num; OSM_LOG_ENTER(sa->p_log); if (p_src_port) { if (p_dest_port) { /* Build an LR for every link connected between both ports. The inner function will discard physp combinations that do not actually connect. Don't bother screening for that here. */ num_ports = osm_node_get_num_physp(p_src_port->p_node); dest_num_ports = osm_node_get_num_physp(p_dest_port->p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_src_physp = osm_node_get_physp_ptr(p_src_port->p_node, port_num); for (dest_port_num = 1; dest_port_num < dest_num_ports; dest_port_num++) { p_dest_physp = osm_node_get_physp_ptr(p_dest_port-> p_node, dest_port_num); /* both physical ports should be with data */ if (p_src_physp && p_dest_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, p_dest_physp, comp_mask, p_list, p_req_physp); } } } else { /* Build an LR for every link connected from the source port. */ if (comp_mask & IB_LR_COMPMASK_FROM_PORT) { port_num = p_lr->from_port_num; /* If the port number is out of the range of the p_src_port, then this couldn't be a relevant record. */ if (port_num < p_src_port->p_node->physp_tbl_size) { p_src_physp = osm_node_get_physp_ptr(p_src_port-> p_node, port_num); if (p_src_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, NULL, comp_mask, p_list, p_req_physp); } } else { num_ports = osm_node_get_num_physp(p_src_port->p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_src_physp = osm_node_get_physp_ptr(p_src_port-> p_node, port_num); if (p_src_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, NULL, comp_mask, p_list, p_req_physp); } } } } else { if (p_dest_port) { /* Build an LR for every link connected to the dest port. */ if (comp_mask & IB_LR_COMPMASK_TO_PORT) { port_num = p_lr->to_port_num; /* If the port number is out of the range of the p_dest_port, then this couldn't be a relevant record. */ if (port_num < p_dest_port->p_node->physp_tbl_size) { p_dest_physp = osm_node_get_physp_ptr(p_dest_port-> p_node, port_num); if (p_dest_physp) lr_rcv_get_physp_link (sa, p_lr, NULL, p_dest_physp, comp_mask, p_list, p_req_physp); } } else { num_ports = osm_node_get_num_physp(p_dest_port->p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_dest_physp = osm_node_get_physp_ptr(p_dest_port-> p_node, port_num); if (p_dest_physp) lr_rcv_get_physp_link (sa, p_lr, NULL, p_dest_physp, comp_mask, p_list, p_req_physp); } } } else { /* Process the world (recurse once back into this function). */ p_node_tbl = &sa->p_subn->node_guid_tbl; p_node = (osm_node_t *) cl_qmap_head(p_node_tbl); while (p_node != (osm_node_t *) cl_qmap_end(p_node_tbl)) { num_ports = osm_node_get_num_physp(p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_src_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_src_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, NULL, comp_mask, p_list, p_req_physp); } p_node = (osm_node_t *) cl_qmap_next(&p_node-> map_item); } } } OSM_LOG_EXIT(sa->p_log); }
/* UPDN callback function */ static int updn_lid_matrices(void *ctx) { updn_t *p_updn = ctx; cl_map_item_t *item; osm_switch_t *p_sw; int ret = 0; OSM_LOG_ENTER(&p_updn->p_osm->log); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; p_sw->priv = create_updn_node(p_sw); if (!p_sw->priv) { OSM_LOG(&(p_updn->p_osm->log), OSM_LOG_ERROR, "ERR AA0C: " "cannot create updn node\n"); OSM_LOG_EXIT(&p_updn->p_osm->log); return -1; } } /* First setup root nodes */ p_updn->num_roots = 0; if (p_updn->p_osm->subn.opt.root_guid_file) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG, "UPDN - Fetching root nodes from file \'%s\'\n", p_updn->p_osm->subn.opt.root_guid_file); ret = parse_node_map(p_updn->p_osm->subn.opt.root_guid_file, rank_root_node, p_updn); if (ret) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA02: " "cannot parse root guids file \'%s\'\n", p_updn->p_osm->subn.opt.root_guid_file); osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr); updn_find_root_nodes_by_min_hop(p_updn); } else if (p_updn->p_osm->subn.opt.connect_roots && p_updn->num_roots > 1) osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr); } else { osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr); updn_find_root_nodes_by_min_hop(p_updn); } if (p_updn->p_osm->subn.opt.ids_guid_file) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG, "UPDN - update node ids from file \'%s\'\n", p_updn->p_osm->subn.opt.ids_guid_file); ret = parse_node_map(p_updn->p_osm->subn.opt.ids_guid_file, update_id, p_updn->p_osm); if (ret) OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA03: " "cannot parse node ids file \'%s\'\n", p_updn->p_osm->subn.opt.ids_guid_file); } /* Only if there are assigned root nodes do the algorithm, otherwise perform do nothing */ if (p_updn->num_roots) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG, "activating UPDN algorithm\n"); ret = updn_build_lid_matrices(p_updn); } else { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_INFO, "disabling UPDN algorithm, no root nodes were found\n"); ret = -1; } if (OSM_LOG_IS_ACTIVE_V2(&p_updn->p_osm->log, OSM_LOG_ROUTING)) osm_dump_qmap_to_file(p_updn->p_osm, "opensm-updn-roots.dump", &p_updn->p_osm->subn.sw_guid_tbl, dump_roots, NULL); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *) item; delete_updn_node(p_sw->priv); } OSM_LOG_EXIT(&p_updn->p_osm->log); return ret; }
static void ucast_cache_validate(osm_ucast_mgr_t * p_mgr) { cache_switch_t *p_cache_sw; cache_switch_t *p_remote_cache_sw; unsigned port_num; unsigned max_ports; uint8_t remote_node_type; uint16_t lid_ho; uint16_t remote_lid_ho; osm_switch_t *p_sw; osm_switch_t *p_remote_sw; osm_node_t *p_node; osm_physp_t *p_physp; osm_physp_t *p_remote_physp; osm_port_t *p_remote_port; cl_qmap_t *p_sw_tbl; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; /* If there are no switches in the subnet, we are done */ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; if (cl_qmap_count(p_sw_tbl) == 0) { osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* * Scan all the physical switch ports in the subnet. * If the port need_update flag is on, check whether * it's just some node/port reset or a cached topology * change. Otherwise the cache is invalid. */ for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl); p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) { p_node = p_sw->p_node; lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0)); p_cache_sw = cache_get_sw(p_mgr, lid_ho); max_ports = osm_node_get_num_physp(p_node); /* skip port 0 */ for (port_num = 1; port_num < max_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !p_physp->p_remote_physp || !osm_physp_link_exists(p_physp, p_physp->p_remote_physp)) /* no valid link */ continue; /* * While scanning all the physical ports in the subnet, * mark corresponding leaf switches in the cache. */ if (p_cache_sw && !p_cache_sw->dropped && !cache_sw_is_leaf(p_cache_sw) && p_physp->p_remote_physp->p_node && osm_node_get_type(p_physp->p_remote_physp-> p_node) != IB_NODE_TYPE_SWITCH) cache_sw_set_leaf(p_cache_sw); if (!p_physp->need_update) continue; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Checking switch lid %u, port %u\n", lid_ho, port_num); p_remote_physp = osm_physp_get_remote(p_physp); remote_node_type = osm_node_get_type(p_remote_physp->p_node); if (remote_node_type == IB_NODE_TYPE_SWITCH) remote_lid_ho = cl_ntoh16(osm_node_get_base_lid (p_remote_physp->p_node, 0)); else remote_lid_ho = cl_ntoh16(osm_node_get_base_lid (p_remote_physp->p_node, osm_physp_get_port_num (p_remote_physp))); if (!p_cache_sw || port_num >= p_cache_sw->num_ports || !p_cache_sw->ports[port_num].remote_lid_ho) { /* * There is some uncached change on the port. * In general, the reasons might be as follows: * - switch reset * - port reset (or port down/up) * - quick connection location change * - new link (or new switch) * * First two reasons allow cache usage, while * the last two reasons should invalidate cache. * * In case of quick connection location change, * cache would have been invalidated by * osm_ucast_cache_check_new_link() function. * * In case of new link between two known nodes, * cache also would have been invalidated by * osm_ucast_cache_check_new_link() function. * * Another reason is cached link between two * known switches went back. In this case the * osm_ucast_cache_check_new_link() function would * clear both sides of the link from the cache * during the discovery process, so effectively * this would be equivalent to port reset. * * So three possible reasons remain: * - switch reset * - port reset (or port down/up) * - link of a new switch * * To validate cache, we need to check only the * third reason - link of a new node/switch: * - If this is the local switch that is new, * then it should have (p_sw->need_update == 2). * - If the remote node is switch and it's new, * then it also should have * (p_sw->need_update == 2). * - If the remote node is CA/RTR and it's new, * then its port should have is_new flag on. */ if (p_sw->need_update == 2) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New switch found (lid %u)\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (remote_node_type == IB_NODE_TYPE_SWITCH) { p_remote_sw = p_remote_physp->p_node->sw; if (p_remote_sw->need_update == 2) { /* this could also be case of switch coming back with an additional link that it didn't have before */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New switch/link found (lid %u)\n", remote_lid_ho); osm_ucast_cache_invalidate (p_mgr); goto Exit; } } else { /* * Remote node is CA/RTR. * Get p_port of the remote node and * check its p_port->is_new flag. */ p_remote_port = osm_get_port_by_guid(p_mgr->p_subn, osm_physp_get_port_guid (p_remote_physp)); if (p_remote_port->is_new) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New CA/RTR found (lid %u)\n", remote_lid_ho); osm_ucast_cache_invalidate (p_mgr); goto Exit; } } } else { /* * The change on the port is cached. * In general, the reasons might be as follows: * - link between two known nodes went back * - one or more nodes went back, causing all * the links to reappear * * If it was link that went back, then this case * would have been taken care of during the * discovery by osm_ucast_cache_check_new_link(), * so it's some node that went back. */ if ((p_cache_sw->ports[port_num].is_leaf && remote_node_type == IB_NODE_TYPE_SWITCH) || (!p_cache_sw->ports[port_num].is_leaf && remote_node_type != IB_NODE_TYPE_SWITCH)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Remote node type change on switch lid %u, port %u\n", lid_ho, port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (p_cache_sw->ports[port_num].remote_lid_ho != remote_lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Remote lid change on switch lid %u, port %u" "(was %u, now %u)\n", lid_ho, port_num, p_cache_sw->ports[port_num]. remote_lid_ho, remote_lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* * We don't care who is the node that has * reappeared in the subnet (local or remote). * What's important that the cached link matches * the real fabrics link. * Just clean it from cache. */ p_cache_sw->ports[port_num].remote_lid_ho = 0; p_cache_sw->ports[port_num].is_leaf = FALSE; if (p_cache_sw->dropped) { cache_restore_ucast_info(p_mgr, p_cache_sw, p_sw); p_cache_sw->dropped = FALSE; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Restored link from cache: lid %u, port %u to lid %u\n", lid_ho, port_num, remote_lid_ho); } } } /* Remove all the cached switches that have all their ports restored */ cache_cleanup_switches(p_mgr); /* * Done scanning all the physical switch ports in the subnet. * Now we need to check the other side: * Scan all the cached switches and their ports: * - If the cached switch is missing in the subnet * (dropped flag is on), check that it's a leaf switch. * If it's not a leaf, the cache is invalid, because * cache can tolerate only leaf switch removal. * - If the cached switch exists in fabric, check all * its cached ports. These cached ports represent * missing link in the fabric. * The missing links that can be tolerated are: * + link to missing CA/RTR * + link to missing leaf switch */ for (p_cache_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl); p_cache_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl); p_cache_sw = (cache_switch_t *) cl_qmap_next(&p_cache_sw->map_item)) { if (p_cache_sw->dropped) { if (!cache_sw_is_leaf(p_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Missing non-leaf switch (lid %u)\n", cache_sw_get_base_lid_ho(p_cache_sw)); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Missing leaf switch (lid %u) - " "continuing validation\n", cache_sw_get_base_lid_ho(p_cache_sw)); continue; } for (port_num = 1; port_num < p_cache_sw->num_ports; port_num++) { if (!p_cache_sw->ports[port_num].remote_lid_ho) continue; if (p_cache_sw->ports[port_num].is_leaf) { CL_ASSERT(cache_sw_is_leaf(p_cache_sw)); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing link to CA/RTR - " "continuing validation\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); continue; } p_remote_cache_sw = cache_get_sw(p_mgr, p_cache_sw-> ports[port_num]. remote_lid_ho); if (!p_remote_cache_sw || !p_remote_cache_sw->dropped) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing link to existing switch\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (!cache_sw_is_leaf(p_remote_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing link to non-leaf switch\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* * At this point we know that the missing link is to * a leaf switch. However, one case deserves a special * treatment. If there was a link between two leaf * switches, then missing leaf switch might break * routing. It is possible that there are routes * that use leaf switches to get from switch to switch * and not just to get to the CAs behind the leaf switch. */ if (cache_sw_is_leaf(p_cache_sw) && cache_sw_is_leaf(p_remote_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing leaf-2-leaf link\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing remote leaf switch - " "continuing validation\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); } } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Unicast cache is valid\n"); ucast_cache_dump(p_mgr); Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_validate() */
/* rank is a SWITCH for BFS purpose */ static int updn_subn_rank(IN updn_t * p_updn) { osm_switch_t *p_sw; osm_physp_t *p_physp, *p_remote_physp; cl_qlist_t list; cl_map_item_t *item; struct updn_node *u, *remote_u; uint8_t num_ports, port_num; osm_log_t *p_log = &p_updn->p_osm->log; unsigned max_rank = 0; OSM_LOG_ENTER(p_log); cl_qlist_init(&list); /* add all roots to the list */ for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; u = p_sw->priv; if (!u->rank) cl_qlist_insert_tail(&list, &u->list); } /* BFS the list till it's empty */ while (!cl_is_qlist_empty(&list)) { u = (struct updn_node *)cl_qlist_remove_head(&list); /* Go over all remote nodes and rank them (if not already visited) */ p_sw = u->sw; num_ports = p_sw->num_ports; OSM_LOG(p_log, OSM_LOG_DEBUG, "Handling switch GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); for (port_num = 1; port_num < num_ports; port_num++) { ib_net64_t port_guid; /* Current port fetched in order to get remote side */ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); if (!p_physp) continue; p_remote_physp = p_physp->p_remote_physp; /* make sure that all the following occur on p_remote_physp: 1. The port isn't NULL 2. It is a switch */ if (p_remote_physp && p_remote_physp->p_node->sw) { remote_u = p_remote_physp->p_node->sw->priv; port_guid = p_remote_physp->port_guid; if (remote_u->rank > u->rank + 1) { remote_u->rank = u->rank + 1; max_rank = remote_u->rank; cl_qlist_insert_tail(&list, &remote_u->list); OSM_LOG(p_log, OSM_LOG_DEBUG, "Rank of port GUID 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid), remote_u->rank); } } } } /* Print Summary of ranking */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "Subnet ranking completed. Max Node Rank = %d\n", max_rank); OSM_LOG_EXIT(p_log); return 0; }
/* Find Root nodes automatically by Min Hop Table info */ static void updn_find_root_nodes_by_min_hop(OUT updn_t * p_updn) { osm_opensm_t *p_osm = p_updn->p_osm; osm_switch_t *p_sw; osm_port_t *p_port; osm_physp_t *p_physp; cl_map_item_t *item; double thd1, thd2; unsigned i, cas_num = 0; unsigned *cas_per_sw; uint16_t lid_ho; OSM_LOG_ENTER(&p_osm->log); OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Current number of ports in the subnet is %d\n", cl_qmap_count(&p_osm->subn.port_guid_tbl)); lid_ho = (uint16_t) cl_ptr_vector_get_size(&p_updn->p_osm->subn.port_lid_tbl) + 1; cas_per_sw = malloc(lid_ho * sizeof(*cas_per_sw)); if (!cas_per_sw) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR AA14: " "cannot alloc mem for CAs per switch counter array\n"); goto _exit; } memset(cas_per_sw, 0, lid_ho * sizeof(*cas_per_sw)); /* Find the Maximum number of CAs (and routers) for histogram normalization */ OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Finding the number of CAs and storing them in cl_map\n"); for (item = cl_qmap_head(&p_updn->p_osm->subn.port_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.port_guid_tbl); item = cl_qmap_next(item)) { p_port = (osm_port_t *)item; if (!p_port->p_node->sw) { p_physp = p_port->p_physp->p_remote_physp; if (!p_physp || !p_physp->p_node->sw) continue; lid_ho = osm_node_get_base_lid(p_physp->p_node, 0); lid_ho = cl_ntoh16(lid_ho); cas_per_sw[lid_ho]++; cas_num++; } } thd1 = cas_num * 0.9; thd2 = cas_num * 0.05; OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Found %u CAs and RTRs, %u SWs in the subnet. " "Thresholds are thd1 = %f && thd2 = %f\n", cas_num, cl_qmap_count(&p_osm->subn.sw_guid_tbl), thd1, thd2); OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Passing through all switches to collect Min Hop info\n"); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { unsigned hop_hist[IB_SUBNET_PATH_HOPS_MAX]; uint16_t max_lid_ho; uint8_t hop_val; uint16_t numHopBarsOverThd1 = 0; uint16_t numHopBarsOverThd2 = 0; p_sw = (osm_switch_t *) item; memset(hop_hist, 0, sizeof(hop_hist)); max_lid_ho = p_sw->max_lid_ho; for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) if (cas_per_sw[lid_ho]) { hop_val = osm_switch_get_least_hops(p_sw, lid_ho); if (hop_val >= IB_SUBNET_PATH_HOPS_MAX) continue; hop_hist[hop_val] += cas_per_sw[lid_ho]; } /* Now recognize the spines by requiring one bar to be above 90% of the number of CAs and RTRs */ for (i = 0; i < IB_SUBNET_PATH_HOPS_MAX; i++) { if (hop_hist[i] > thd1) numHopBarsOverThd1++; if (hop_hist[i] > thd2) numHopBarsOverThd2++; } /* If thd conditions are valid - rank the root node */ if (numHopBarsOverThd1 == 1 && numHopBarsOverThd2 == 1) { OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Ranking GUID 0x%" PRIx64 " as root node\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); ((struct updn_node *)p_sw->priv)->rank = 0; p_updn->num_roots++; } } free(cas_per_sw); _exit: OSM_LOG_EXIT(&p_osm->log); return; }
static void populate_fwd_tbls(lash_t * p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; osm_subn_t *p_subn = &p_lash->p_osm->subn; osm_switch_t *p_sw, *p_next_sw, *p_dst_sw; osm_port_t *port; uint16_t max_lid_ho, lid; OSM_LOG_ENTER(p_log); p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); /* Go through each switch individually */ while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { uint64_t current_guid; switch_t *sw; p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); max_lid_ho = p_sw->max_lid_ho; current_guid = p_sw->p_node->node_info.port_guid; sw = p_sw->priv; memset(p_sw->new_lft, OSM_NO_PATH, p_sw->lft_size); for (lid = 1; lid <= max_lid_ho; lid++) { port = osm_get_port_by_lid_ho(p_subn, lid); if (!port) continue; p_dst_sw = get_osm_switch_from_port(port); if (p_dst_sw == p_sw) { uint8_t egress_port = port->p_node->sw ? 0 : port->p_physp->p_remote_physp->port_num; p_sw->new_lft[lid] = egress_port; OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH fwd MY SRC SRC GUID 0x%016" PRIx64 " src lash id (%d), src lid no (%u) src lash port (%d) " "DST GUID 0x%016" PRIx64 " src lash id (%d), src lash port (%d)\n", cl_ntoh64(current_guid), -1, lid, egress_port, cl_ntoh64(current_guid), -1, egress_port); } else if (p_dst_sw) { unsigned dst_lash_switch_id = get_lash_id(p_dst_sw); uint8_t lash_egress_port = (uint8_t) sw-> routing_table[dst_lash_switch_id].out_link; uint8_t physical_egress_port = get_next_port(sw, lash_egress_port); p_sw->new_lft[lid] = physical_egress_port; OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH fwd SRC GUID 0x%016" PRIx64 " src lash id (%d), " "src lid no (%u) src lash port (%d) " "DST GUID 0x%016" PRIx64 " src lash id (%d), src lash port (%d)\n", cl_ntoh64(current_guid), sw->id, lid, lash_egress_port, cl_ntoh64(p_dst_sw->p_node->node_info. port_guid), dst_lash_switch_id, physical_egress_port); } } /* for */ } OSM_LOG_EXIT(p_log); }
int osm_qos_setup(osm_opensm_t * p_osm) { struct qos_config ca_config, sw0_config, swe_config, rtr_config; struct qos_config *cfg; cl_qmap_t *p_tbl; cl_map_item_t *p_next; osm_port_t *p_port; osm_node_t *p_node; int ret = 0; int vlarb_only; qos_mad_list_t *p_list, *p_list_next; qos_mad_item_t *p_port_mad; cl_qlist_t qos_mad_list; if (!p_osm->subn.opt.qos) return 0; OSM_LOG_ENTER(&p_osm->log); qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, &p_osm->subn.opt.qos_options); qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, &p_osm->subn.opt.qos_options); qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, &p_osm->subn.opt.qos_options); qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, &p_osm->subn.opt.qos_options); cl_qlist_init(&qos_mad_list); cl_plock_excl_acquire(&p_osm->lock); /* read QoS policy config file */ osm_qos_parse_policy_file(&p_osm->subn); p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { vlarb_only = 0; p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); p_list = (qos_mad_list_t *) malloc(sizeof(*p_list)); if (!p_list) return -1; memset(p_list, 0, sizeof(*p_list)); cl_qlist_init(&p_list->port_mad_list); p_node = p_port->p_node; if (p_node->sw) { if (qos_extports_setup(&p_osm->sm, p_node, &swe_config, &p_list->port_mad_list)) ret = -1; /* skip base port 0 */ if (!ib_switch_info_is_enhanced_port0 (&p_node->sw->switch_info)) goto Continue; if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) && p_osm->sm.p_subn->opt.use_optimized_slvl && !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl, sizeof(swe_config.sl2vl))) vlarb_only = 1; cfg = &sw0_config; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) cfg = &rtr_config; else cfg = &ca_config; if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg, vlarb_only, &p_list->port_mad_list)) ret = -1; Continue: /* if MAD list is not empty, add it to the global MAD list */ if (cl_qlist_count(&p_list->port_mad_list)) { cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item); } else { free(p_list); } } while (cl_qlist_count(&qos_mad_list)) { p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list); while (p_list_next != (qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) { p_list = p_list_next; p_list_next = (qos_mad_list_t *) cl_qlist_next(&p_list->list_item); /* next MAD to send*/ p_port_mad = (qos_mad_item_t *) cl_qlist_remove_head(&p_list->port_mad_list); osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw); osm_qos_mad_delete(&p_port_mad); /* remove the QoS MAD from global MAD list */ if (cl_qlist_count(&p_list->port_mad_list) == 0) { cl_qlist_remove_item(&qos_mad_list, &p_list->list_item); free(p_list); } } } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return ret; }
static int discover_network_properties(lash_t * p_lash) { int i, id = 0; uint8_t vl_min; osm_subn_t *p_subn = &p_lash->p_osm->subn; osm_switch_t *p_next_sw, *p_sw; osm_log_t *p_log = &p_lash->p_osm->log; p_lash->num_switches = cl_qmap_count(&p_subn->sw_guid_tbl); p_lash->switches = calloc(p_lash->num_switches, sizeof(switch_t *)); if (!p_lash->switches) return -1; vl_min = 5; /* set to a high value */ p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { uint16_t port_count; p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); p_lash->switches[id] = switch_create(p_lash, id, p_sw); if (!p_lash->switches[id]) return -1; id++; port_count = osm_node_get_num_physp(p_sw->p_node); /* Note, ignoring port 0. management port */ for (i = 1; i < port_count; i++) { osm_physp_t *p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i); if (p_current_physp && p_current_physp->p_remote_physp) { ib_port_info_t *p_port_info = &p_current_physp->port_info; uint8_t port_vl_min = ib_port_info_get_op_vls(p_port_info); if (port_vl_min && port_vl_min < vl_min) vl_min = port_vl_min; } } /* for */ } /* while */ vl_min = 1 << (vl_min - 1); if (vl_min > 15) vl_min = 15; if (p_lash->p_osm->subn.opt.lash_start_vl >= vl_min) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D03: " "Start VL(%d) too high for min operational vl(%d)\n", p_lash->p_osm->subn.opt.lash_start_vl, vl_min); return -1; } p_lash->vl_min = vl_min - p_lash->p_osm->subn.opt.lash_start_vl; OSM_LOG(p_log, OSM_LOG_INFO, "min operational vl(%d) start vl(%d) max_switches(%d)\n", p_lash->vl_min, p_lash->p_osm->subn.opt.lash_start_vl, p_lash->num_switches); return 0; }
/* If possible compress a point into a simpler format * This looks for lists which consist of a single entry or * lists which include all the components of a higher level type */ void PointFabricCompress(Point *point) { switch (point->Type) { case POINT_TYPE_NONE: break; case POINT_TYPE_PORT: break; case POINT_TYPE_PORT_LIST: { PortData *portp; LIST_ITERATOR head = ListHead(&point->u.portList); ASSERT(head); ASSERT(ListCount(&point->u.portList) >= 1); portp = (PortData*)ListObj(head); if (ListCount(&point->u.portList) == 1) { /* degenerate case, simplify as a single port */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_PORT, portp); } else if (ListCount(&point->u.portList) == cl_qmap_count(&portp->nodep->Ports)) { /* maybe we can consolidate to a single node */ LIST_ITERATOR i; DLIST *pList = &point->u.portList; for (i=ListHead(pList); portp && i != NULL; i = ListNext(pList, i)) { if (portp->nodep != ((PortData*)ListObj(i))->nodep) portp = NULL; /* not in same node, flag for below */ } if (portp) { /* degenerate case, simplify as a single node */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_NODE, portp->nodep); } #if 0 } else { // the likelihood of this is low for port oriented searches // and it would present just the system image guide in the summary // and may be less obvious to the user than a list of ports /* maybe we can consolidate to a single system */ LIST_ITERATOR i; DLIST *pList = &point->u.portList; for (i=ListHead(pList); portp && i != NULL; i = ListNext(pList, i)) { if (portp->nodep->systemp != ((PortData*)ListObj(i))->nodep->systemp) portp = NULL; /* not in same system, flag for below */ } if (portp) { /* all ports are in same system. is it a complete list? */ /* count ports in the system */ uint32 count = 0; cl_map_item_t *p; for (p=cl_qmap_head(&portp->nodep->systemp->Nodes); p != cl_qmap_end(&portp->nodep->systemp->Nodes); p = cl_qmap_next(p)) { NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); count += cl_qmap_count(&nodep->Ports); } if (ListCount(&point->u.portList) != count) portp = NULL; /* incomplete list, flag for below */ } if (portp) { /* degenerate case, simplify as a single system */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_SYSTEM, portp->nodep->systemp); } #endif } break; } case POINT_TYPE_NODE: break; case POINT_TYPE_NODE_LIST: { NodeData *nodep; LIST_ITERATOR head = ListHead(&point->u.nodeList); ASSERT(head); ASSERT(ListCount(&point->u.nodeList) >= 1); nodep = (NodeData*)ListObj(head); if (ListCount(&point->u.nodeList) == 1) { /* degenerate case, simplify as a single node */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_NODE, nodep); } else if (ListCount(&point->u.nodeList) == cl_qmap_count(&nodep->systemp->Nodes)) { /* maybe we can consolidate to a single system */ LIST_ITERATOR i; DLIST *pList = &point->u.nodeList; for (i=ListHead(pList); nodep && i != NULL; i = ListNext(pList, i)) { if (nodep->systemp != ((NodeData*)ListObj(i))->systemp) nodep = NULL; /* not in same system, flag for below */ } if (nodep) { /* degenerate case, simplify as a single system */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_SYSTEM, nodep->systemp); } } break; } #if !defined(VXWORKS) || defined(BUILD_DMC) case POINT_TYPE_IOC: break; case POINT_TYPE_IOC_LIST: { IocData *iocp; LIST_ITERATOR head = ListHead(&point->u.iocList); ASSERT(head); ASSERT(ListCount(&point->u.iocList) >= 1); iocp = (IocData*)ListObj(head); if (ListCount(&point->u.iocList) == 1) { /* degenerate case, simplify as a single IOC */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_IOC, iocp); } else if (ListCount(&point->u.iocList) == QListCount(&iocp->ioup->Iocs)) { /* maybe we can consolidate to a single node */ LIST_ITERATOR i; DLIST *pList = &point->u.iocList; for (i=ListHead(pList); iocp && i != NULL; i = ListNext(pList, i)) { if (iocp->ioup != ((IocData*)ListObj(i))->ioup) iocp = NULL; /* not in same iou, flag for below */ } if (iocp) { /* degenerate case, simplify as a single node */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_NODE, iocp->ioup->nodep); } #if 0 } else { // the likelihood of this is low for ioc oriented searches // and it would present just the system image guide in the summary // and may be less obvious to the user than a list of iocs /* maybe we can consolidate to a single system */ LIST_ITERATOR i; DLIST *pList = &point->u.iocList; for (i=ListHead(pList); iocp && i != NULL; i = ListNext(pList, i)) { if (iocp->ioup->nodep->systemp != ((IocData*)ListObj(i))->ioup->nodep->systemp) iocp = NULL; /* not in same system, flag for below */ } if (iocp) { /* all IOCs are in same system. is it a complete list? */ /* count IOCs in the system */ uint32 count = 0; cl_map_item_t *p; for (p=cl_qmap_head(&iocp->ioup->nodep->systemp->Nodes); p != cl_qmap_end(&iocp->ioup->nodep->systemp->Nodes); p = cl_qmap_next(p)) { NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); if (nodep->ioup) count += QListCount(&nodep->ioup->Iocs); } if (ListCount(&point->u.iocList) != count) iocp = NULL; /* incomplete list, flag for below */ } if (iocp) { /* degenerate case, simplify as a single system */ PointFabricDestroy(point); PointInitSimple(point, POINT_TYPE_SYSTEM, iocp->ioup->nodep->systemp); } #endif } break; } #endif case POINT_TYPE_SYSTEM: break; } }
/********************************************************************** * Make sure that the lid_port_tbl of the subnet has only the ports * that are recognized, and in the correct lid place. There could be * errors if we wanted to assign a certain port with lid X, but that * request didn't reach the port. In this case port_lid_tbl will have * the port under lid X, though the port isn't updated with this lid. * We will run a new heavy sweep (since there were errors in the * initialization), but here we'll clean the database from incorrect * information. **********************************************************************/ static void state_mgr_check_tbl_consistency(IN osm_sm_t * sm) { cl_qmap_t *p_port_guid_tbl; osm_port_t *p_port; osm_port_t *p_next_port; cl_ptr_vector_t *p_port_lid_tbl; size_t max_lid, ref_size, curr_size, lid; osm_port_t *p_port_ref, *p_port_stored; cl_ptr_vector_t ref_port_lid_tbl; uint16_t min_lid_ho; uint16_t max_lid_ho; uint16_t lid_ho; OSM_LOG_ENTER(sm->p_log); cl_ptr_vector_construct(&ref_port_lid_tbl); cl_ptr_vector_init(&ref_port_lid_tbl, cl_ptr_vector_get_size(&sm->p_subn->port_lid_tbl), OSM_SUBNET_VECTOR_GROW_SIZE); p_port_guid_tbl = &sm->p_subn->port_guid_tbl; /* Let's go over all the ports according to port_guid_tbl, * and add the port to a reference port_lid_tbl. */ p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) { p_port = p_next_port; p_next_port = (osm_port_t *) cl_qmap_next(&p_next_port->map_item); osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) cl_ptr_vector_set(&ref_port_lid_tbl, lid_ho, p_port); } p_port_lid_tbl = &sm->p_subn->port_lid_tbl; ref_size = cl_ptr_vector_get_size(&ref_port_lid_tbl); curr_size = cl_ptr_vector_get_size(p_port_lid_tbl); /* They should be the same, but compare it anyway */ max_lid = (ref_size > curr_size) ? ref_size : curr_size; for (lid = 1; lid < max_lid; lid++) { p_port_ref = NULL; p_port_stored = NULL; cl_ptr_vector_at(p_port_lid_tbl, lid, (void *)&p_port_stored); cl_ptr_vector_at(&ref_port_lid_tbl, lid, (void *)&p_port_ref); if (p_port_stored == p_port_ref) /* This is the "good" case - both entries are the * same for this lid. Nothing to do. */ continue; if (p_port_ref == NULL) /* There is an object in the subnet database for this * lid, but no such object exists in the reference * port_list_tbl. This can occur if we wanted to assign * a certain port with some lid (different than the one * pre-assigned to it), and the port didn't get the * PortInfo Set request. Due to this, the port is * updated with its original lid in our database, but * with the new lid we wanted to give it in our * port_lid_tbl. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3322: " "lid %zu is wrongly assigned to port 0x%016" PRIx64 " (\'%s\' port %u) in port_lid_tbl\n", lid, cl_ntoh64(osm_port_get_guid(p_port_stored)), p_port_stored->p_node->print_desc, p_port_stored->p_physp->port_num); else if (p_port_stored == NULL) /* There is an object in the new database, but no * object in our subnet database. This is the matching * case of the prior check - the port still has its * original lid. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3323: " "port 0x%016" PRIx64 " (\'%s\' port %u)" " exists in new port_lid_tbl under lid %zu," " but missing in subnet port_lid_tbl db\n", cl_ntoh64(osm_port_get_guid(p_port_ref)), p_port_ref->p_node->print_desc, p_port_ref->p_physp->port_num, lid); else /* if we reached here then p_port_stored != p_port_ref. * We were trying to set a lid to p_port_stored, but * it didn't reach it, and p_port_ref also didn't get * the lid update. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3324: " "lid %zu has port 0x%016" PRIx64 " (\'%s\' port %u) in new port_lid_tbl db, " "and port 0x%016" PRIx64 " (\'%s\' port %u)" " in subnet port_lid_tbl db\n", lid, cl_ntoh64(osm_port_get_guid(p_port_ref)), p_port_ref->p_node->print_desc, p_port_ref->p_physp->port_num, cl_ntoh64(osm_port_get_guid(p_port_stored)), p_port_ref->p_node->print_desc, p_port_ref->p_physp->port_num); /* In any of these cases we want to set NULL in the * port_lid_tbl, since this entry is invalid. Also, make sure * we'll do another heavy sweep. */ cl_ptr_vector_set(p_port_lid_tbl, lid, NULL); sm->p_subn->subnet_initialization_error = TRUE; } cl_ptr_vector_destroy(&ref_port_lid_tbl); OSM_LOG_EXIT(sm->p_log); }
/********************************************************************** * Send Trap 64 on all new ports. **********************************************************************/ static void state_mgr_report_new_ports(IN osm_sm_t * sm) { ib_gid_t port_gid; ib_mad_notice_attr_t notice; ib_api_status_t status; ib_net64_t port_guid; cl_map_item_t *p_next; osm_port_t *p_port; uint16_t min_lid_ho; uint16_t max_lid_ho; OSM_LOG_ENTER(sm->p_log); CL_PLOCK_ACQUIRE(sm->p_lock); p_next = cl_qmap_head(&sm->p_subn->port_guid_tbl); while (p_next != cl_qmap_end(&sm->p_subn->port_guid_tbl)) { p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); if (!p_port->is_new) continue; port_guid = osm_port_get_guid(p_port); /* issue a notice - trap 64 */ /* details of the notice */ notice.generic_type = 0x83; /* is generic subn mgt type */ ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */ /* endport becomes reachable */ notice.g_or_v.generic.trap_num = CL_HTON16(64); /* The sm_base_lid is saved in network order already. */ notice.issuer_lid = sm->p_subn->sm_base_lid; /* following C14-72.1.1 and table 119 p739 */ /* we need to provide the GID */ port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; port_gid.unicast.interface_id = port_guid; memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid), sizeof(ib_gid_t)); /* According to page 653 - the issuer gid in this case of trap * is the SM gid, since the SM is the initiator of this trap. */ notice.issuer_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; notice.issuer_gid.unicast.interface_id = sm->p_subn->sm_port_guid; status = osm_report_notice(sm->p_log, sm->p_subn, ¬ice); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3318: " "Error sending trap reports on GUID:0x%016" PRIx64 " (%s)\n", port_gid.unicast.interface_id, ib_get_err_str(status)); osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); OSM_LOG(sm->p_log, OSM_LOG_INFO, "Discovered new port with GUID:0x%016" PRIx64 " LID range [%u,%u] of node: %s\n", cl_ntoh64(port_gid.unicast.interface_id), min_lid_ho, max_lid_ho, p_port->p_node ? p_port->p_node-> print_desc : "UNKNOWN"); p_port->is_new = 0; } CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); }
/********************************************************************** Initiates a lightweight sweep of the subnet. Used during normal sweeps after the subnet is up. **********************************************************************/ static ib_api_status_t state_mgr_light_sweep_start(IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; osm_bind_handle_t h_bind; cl_qmap_t *p_sw_tbl; cl_map_item_t *p_next; osm_node_t *p_node; osm_physp_t *p_physp; uint8_t port_num; OSM_LOG_ENTER(sm->p_log); p_sw_tbl = &sm->p_subn->sw_guid_tbl; /* * First, get the bind handle. */ h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl); if (h_bind == OSM_BIND_INVALID_HANDLE) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "No bound ports. Deferring sweep...\n"); status = IB_INVALID_STATE; goto _exit; } OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING LIGHT SWEEP"); CL_PLOCK_ACQUIRE(sm->p_lock); cl_qmap_apply_func(p_sw_tbl, state_mgr_get_sw_info, sm); CL_PLOCK_RELEASE(sm->p_lock); CL_PLOCK_ACQUIRE(sm->p_lock); cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, state_mgr_get_node_desc, sm); CL_PLOCK_RELEASE(sm->p_lock); /* now scan the list of physical ports that were not down but have no remote port */ CL_PLOCK_ACQUIRE(sm->p_lock); p_next = cl_qmap_head(&sm->p_subn->node_guid_tbl); while (p_next != cl_qmap_end(&sm->p_subn->node_guid_tbl)) { p_node = (osm_node_t *) p_next; p_next = cl_qmap_next(p_next); for (port_num = 1; port_num < osm_node_get_num_physp(p_node); port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_physp && (osm_physp_get_port_state(p_physp) != IB_LINK_DOWN) && !osm_physp_get_remote(p_physp)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3315: " "Unknown remote side for node 0x%016" PRIx64 " (%s) port %u. Adding to light sweep sampling list\n", cl_ntoh64(osm_node_get_node_guid (p_node)), p_node->print_desc, port_num); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr (p_physp), FILE_ID, OSM_LOG_ERROR); state_mgr_get_remote_port_info(sm, p_physp); } } } cl_qmap_apply_func(&sm->p_subn->sm_guid_tbl, query_sm_info, sm); CL_PLOCK_RELEASE(sm->p_lock); _exit: OSM_LOG_EXIT(sm->p_log); return status; }