/********************************************************************** Add each switch's own and neighbor LIDs to its LID matrix **********************************************************************/ static void __osm_ucast_mgr_process_hop_0_1(IN cl_map_item_t * const p_map_item, IN void *context) { osm_switch_t *const p_sw = (osm_switch_t *) p_map_item; osm_node_t *p_remote_node; uint16_t lid, remote_lid; uint8_t i, remote_port; lid = osm_node_get_base_lid(p_sw->p_node, 0); lid = cl_ntoh16(lid); osm_switch_set_hops(p_sw, lid, 0, 0); for (i = 1; i < p_sw->num_ports; i++) { p_remote_node = osm_node_get_remote_node(p_sw->p_node, i, &remote_port); if (p_remote_node && p_remote_node->sw && (p_remote_node != p_sw->p_node)) { remote_lid = osm_node_get_base_lid(p_remote_node, 0); remote_lid = cl_ntoh16(remote_lid); osm_switch_set_hops(p_sw, remote_lid, i, 1); osm_switch_set_hops(p_remote_node->sw, lid, remote_port, 1); } } }
static void dump_ucast_path_distribution(cl_map_item_t * item, FILE * file, void *cxt) { osm_node_t *p_node; osm_node_t *p_remote_node; uint8_t i; uint8_t num_ports; uint32_t num_paths; ib_net64_t remote_guid_ho; osm_switch_t *p_sw = (osm_switch_t *) item; p_node = p_sw->p_node; num_ports = p_sw->num_ports; fprintf(file, "dump_ucast_path_distribution: Switch 0x%" PRIx64 "\n" "Port : Path Count Through Port", cl_ntoh64(osm_node_get_node_guid(p_node))); for (i = 0; i < num_ports; i++) { num_paths = osm_switch_path_count_get(p_sw, i); fprintf(file, "\n %03u : %u", i, num_paths); if (i == 0) { fprintf(file, " (switch management port)"); continue; } p_remote_node = osm_node_get_remote_node(p_node, i, NULL); if (p_remote_node == NULL) continue; remote_guid_ho = cl_ntoh64(osm_node_get_node_guid(p_remote_node)); switch (osm_node_get_type(p_remote_node)) { case IB_NODE_TYPE_SWITCH: fprintf(file, " (link to switch"); break; case IB_NODE_TYPE_ROUTER: fprintf(file, " (link to router"); break; case IB_NODE_TYPE_CA: fprintf(file, " (link to CA"); break; default: fprintf(file, " (link to unknown node type"); break; } fprintf(file, " 0x%" PRIx64 ")", remote_guid_ho); } fprintf(file, "\n"); }
static void __osm_ucast_mgr_process_neighbors(IN cl_map_item_t * const p_map_item, IN void *context) { osm_switch_t *const p_sw = (osm_switch_t *) p_map_item; osm_ucast_mgr_t *const p_mgr = (osm_ucast_mgr_t *) context; osm_node_t *p_node; osm_node_t *p_remote_node; uint32_t port_num; uint8_t remote_port_num; uint32_t num_ports; osm_physp_t *p_physp; OSM_LOG_ENTER(p_mgr->p_log); p_node = p_sw->p_node; CL_ASSERT(p_node); CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing switch with GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); num_ports = osm_node_get_num_physp(p_node); /* Start with port 1 to skip the switch's management port. */ for (port_num = 1; port_num < num_ports; port_num++) { p_remote_node = osm_node_get_remote_node(p_node, (uint8_t) port_num, &remote_port_num); if (p_remote_node && p_remote_node->sw && (p_remote_node != p_node)) { /* make sure the link is healthy. If it is not - don't propagate through it. */ p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !osm_link_is_healthy(p_physp)) continue; __osm_ucast_mgr_process_neighbor(p_mgr, p_sw, p_remote_node->sw, (uint8_t) port_num, remote_port_num); } } OSM_LOG_EXIT(p_mgr->p_log); }
/********************************************************************** * This function does the bfs of min hop table calculation by guid index * as a starting point. **********************************************************************/ static int updn_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn, IN osm_switch_t * p_sw) { uint8_t pn, pn_rem; cl_qlist_t list; uint16_t lid; struct updn_node *u; updn_switch_dir_t next_dir, current_dir; OSM_LOG_ENTER(p_log); lid = osm_node_get_base_lid(p_sw->p_node, 0); lid = cl_ntoh16(lid); osm_switch_set_hops(p_sw, lid, 0, 0); OSM_LOG(p_log, OSM_LOG_DEBUG, "Starting from switch - port GUID 0x%" PRIx64 " lid %u\n", cl_ntoh64(p_sw->p_node->node_info.port_guid), lid); u = p_sw->priv; u->dir = UP; /* Update list with the new element */ cl_qlist_init(&list); cl_qlist_insert_tail(&list, &u->list); /* BFS the list till no next element */ while (!cl_is_qlist_empty(&list)) { u = (struct updn_node *)cl_qlist_remove_head(&list); u->visited = 0; /* cleanup */ current_dir = u->dir; /* Go over all ports of the switch and find unvisited remote nodes */ for (pn = 1; pn < u->sw->num_ports; pn++) { osm_node_t *p_remote_node; struct updn_node *rem_u; uint8_t current_min_hop, remote_min_hop, set_hop_return_value; osm_switch_t *p_remote_sw; p_remote_node = osm_node_get_remote_node(u->sw->p_node, pn, &pn_rem); /* If no remote node OR remote node is not a SWITCH continue to next pn */ if (!p_remote_node || !p_remote_node->sw) continue; /* Fetch remote guid only after validation of remote node */ p_remote_sw = p_remote_node->sw; rem_u = p_remote_sw->priv; /* Decide which direction to mark it (UP/DOWN) */ next_dir = updn_get_dir(u->rank, rem_u->rank, u->id, rem_u->id); /* Check if this is a legal step : the only illegal step is going from DOWN to UP */ if ((current_dir == DOWN) && (next_dir == UP)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)), cl_ntoh64(osm_node_get_node_guid(p_remote_node))); /* Illegal step */ continue; } /* Set MinHop value for the current lid */ current_min_hop = osm_switch_get_least_hops(u->sw, lid); /* Check hop count if better insert into list && update the remote node Min Hop Table */ remote_min_hop = osm_switch_get_hop_count(p_remote_sw, lid, pn_rem); if (current_min_hop + 1 < remote_min_hop) { set_hop_return_value = osm_switch_set_hops(p_remote_sw, lid, pn_rem, current_min_hop + 1); if (set_hop_return_value) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AA01: " "Invalid value returned from set min hop is: %d\n", set_hop_return_value); } /* Check if remote port has already been visited */ if (!rem_u->visited) { /* Insert updn_switch item into the list */ rem_u->dir = next_dir; rem_u->visited = 1; cl_qlist_insert_tail(&list, &rem_u->list); } } } } OSM_LOG_EXIT(p_log); return 0; }