static ib_api_status_t osm_switch_init(IN osm_switch_t * const p_sw, IN osm_node_t * const p_node, IN const osm_madw_t * const p_madw) { ib_api_status_t status = IB_SUCCESS; ib_switch_info_t *p_si; ib_smp_t *p_smp; uint8_t num_ports; uint32_t port_num; p_smp = osm_madw_get_smp_ptr(p_madw); p_si = (ib_switch_info_t *) ib_smp_get_payload_ptr(p_smp); num_ports = osm_node_get_num_physp(p_node); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO); p_sw->p_node = p_node; p_sw->switch_info = *p_si; p_sw->num_ports = num_ports; p_sw->need_update = 2; /* Initiate the linear forwarding table */ if (!p_si->lin_cap) { /* This switch does not support linear forwarding tables */ status = IB_UNSUPPORTED; goto Exit; } p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1); if (!p_sw->lft) { status = IB_INSUFFICIENT_MEMORY; goto Exit; } /* Initialize the table to OSM_NO_PATH, which is "invalid port" */ memset(p_sw->lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1); p_sw->p_prof = malloc(sizeof(*p_sw->p_prof) * num_ports); if (p_sw->p_prof == NULL) { status = IB_INSUFFICIENT_MEMORY; goto Exit; } memset(p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports); status = osm_mcast_tbl_init(&p_sw->mcast_tbl, osm_node_get_num_physp(p_node), cl_ntoh16(p_si->mcast_cap)); if (status != IB_SUCCESS) goto Exit; for (port_num = 0; port_num < num_ports; port_num++) osm_port_prof_construct(&p_sw->p_prof[port_num]); Exit: return (status); }
osm_switch_t *osm_switch_new(IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { osm_switch_t *p_sw; ib_switch_info_t *p_si; ib_smp_t *p_smp; uint8_t num_ports; uint32_t port_num; CL_ASSERT(p_madw); CL_ASSERT(p_node); p_smp = osm_madw_get_smp_ptr(p_madw); p_si = ib_smp_get_payload_ptr(p_smp); num_ports = osm_node_get_num_physp(p_node); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO); if (!p_si->lin_cap) /* The switch doesn't support LFT */ return NULL; p_sw = malloc(sizeof(*p_sw)); if (!p_sw) return NULL; memset(p_sw, 0, sizeof(*p_sw)); p_sw->p_node = p_node; p_sw->switch_info = *p_si; p_sw->num_ports = num_ports; p_sw->need_update = 2; p_sw->p_prof = malloc(sizeof(*p_sw->p_prof) * num_ports); if (!p_sw->p_prof) goto err; memset(p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports); osm_mcast_tbl_init(&p_sw->mcast_tbl, osm_node_get_num_physp(p_node), cl_ntoh16(p_si->mcast_cap)); for (port_num = 0; port_num < num_ports; port_num++) osm_port_prof_construct(&p_sw->p_prof[port_num]); return p_sw; err: osm_switch_delete(&p_sw); return NULL; }
static ib_api_status_t sl2vl_update(osm_sm_t * sm, osm_port_t * p_port, osm_physp_t * p, uint8_t port_num, unsigned force_update, const struct qos_config *qcfg) { ib_api_status_t status; uint8_t i, num_ports; osm_physp_t *p_physp; if (osm_node_get_type(osm_physp_get_node_ptr(p)) == IB_NODE_TYPE_SWITCH) { if (ib_port_info_get_vl_cap(&p->port_info) == 1) { /* Check port 0's capability mask */ p_physp = p_port->p_physp; if (! (p_physp->port_info. capability_mask & IB_PORT_CAP_HAS_SL_MAP)) return IB_SUCCESS; } num_ports = osm_node_get_num_physp(osm_physp_get_node_ptr(p)); } else { if (!(p->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) return IB_SUCCESS; num_ports = 1; } for (i = 0; i < num_ports; i++) { status = sl2vl_update_table(sm, p, i, port_num, force_update, &qcfg->sl2vl); if (status != IB_SUCCESS) return status; } return IB_SUCCESS; }
static osm_signal_t __osm_link_mgr_process_node(osm_sm_t * sm, IN osm_node_t * const p_node, IN const uint8_t link_state) { uint32_t i; uint32_t num_physp; osm_physp_t *p_physp; uint8_t current_state; osm_signal_t signal = OSM_SIGNAL_DONE; OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Node 0x%" PRIx64 " going to %s\n", cl_ntoh64(osm_node_get_node_guid(p_node)), ib_get_port_state_str(link_state)); /* Set the PortInfo for every Physical Port associated with this Port. Start iterating with port 1, since the linkstate is not applicable to the management port on switches. */ num_physp = osm_node_get_num_physp(p_node); for (i = 0; i < num_physp; i++) { /* Don't bother doing anything if this Physical Port is not valid. or if the state of the port is already better then the specified state. */ p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i); if (!p_physp) continue; current_state = osm_physp_get_port_state(p_physp); if (current_state == IB_LINK_DOWN) continue; /* Normally we only send state update if state is lower then required state. However, we need to send update if no state change required. */ if (link_state != IB_LINK_NO_CHANGE && link_state <= current_state) OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Physical port %u already %s. Skipping\n", p_physp->port_num, ib_get_port_state_str(current_state)); else if (__osm_link_mgr_set_physp_pi(sm, p_physp, link_state)) signal = OSM_SIGNAL_DONE_PENDING; } OSM_LOG_EXIT(sm->p_log); return (signal); }
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); }
/********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void pi_rcv_process_switch_port0(IN osm_sm_t * sm, IN osm_node_t * p_node, IN osm_physp_t * p_physp, IN ib_port_info_t * p_pi) { ib_api_status_t status; osm_madw_context_t context; uint8_t port, num_ports; OSM_LOG_ENTER(sm->p_log); if (p_physp->need_update) sm->p_subn->ignore_existing_lfts = TRUE; pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp); /* Update the PortInfo attribute */ osm_physp_set_port_info(p_physp, p_pi, sm); /* Determine if base switch port 0 */ if (p_node->sw && !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) /* PortState is not used on BSP0 but just in case it is DOWN */ p_physp->port_info = *p_pi; /* Now, query PortInfo for the switch external ports */ num_ports = osm_node_get_num_physp(p_node); context.pi_context.node_guid = osm_node_get_node_guid(p_node); context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); context.pi_context.set_method = FALSE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; for (port = 1; port < num_ports; port++) { status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp), IB_MAD_ATTR_PORT_INFO, cl_hton32(port), FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F16: " "Failure initiating PortInfo request (%s)\n", ib_get_err_str(status)); } pi_rcv_process_endport(sm, p_physp, p_pi); OSM_LOG_EXIT(sm->p_log); }
static void osm_lash_process_switch(lash_t * p_lash, osm_switch_t * p_sw) { osm_log_t *p_log = &p_lash->p_osm->log; int i, port_count; osm_physp_t *p_current_physp, *p_remote_physp; unsigned switch_a_lash_id, switch_b_lash_id; OSM_LOG_ENTER(p_log); switch_a_lash_id = get_lash_id(p_sw); port_count = osm_node_get_num_physp(p_sw->p_node); /* starting at port 1, ignoring management port on switch */ for (i = 1; i < port_count; i++) { p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i); if (p_current_physp) { p_remote_physp = p_current_physp->p_remote_physp; if (p_remote_physp && p_remote_physp->p_node->sw) { int physical_port_a_num = osm_physp_get_port_num(p_current_physp); int physical_port_b_num = osm_physp_get_port_num(p_remote_physp); switch_b_lash_id = get_lash_id(p_remote_physp->p_node->sw); connect_switches(p_lash, switch_a_lash_id, switch_b_lash_id, physical_port_a_num); OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH SUCCESS connected G 0x%016" PRIx64 " , lash_id(%u), P(%u) " " to G 0x%016" PRIx64 " , lash_id(%u) , P(%u)\n", cl_ntoh64(osm_physp_get_port_guid (p_current_physp)), switch_a_lash_id, physical_port_a_num, cl_ntoh64(osm_physp_get_port_guid (p_remote_physp)), switch_b_lash_id, physical_port_b_num); } } } OSM_LOG_EXIT(p_log); }
static void state_mgr_update_node_desc(IN cl_map_item_t * obj, IN void *context) { osm_madw_context_t mad_context; osm_node_t *p_node = (osm_node_t *) obj; osm_sm_t *sm = context; osm_physp_t *p_physp = NULL; unsigned i, num_ports; ib_api_status_t status; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_node); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Updating NodeDesc for 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); /* get a physp to request from. */ num_ports = osm_node_get_num_physp(p_node); for (i = 0; i < num_ports; i++) if ((p_physp = osm_node_get_physp_ptr(p_node, i))) break; if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331C: " "Failed to find any valid physical port object.\n"); goto exit; } mad_context.nd_context.node_guid = osm_node_get_node_guid(p_node); status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp), IB_MAD_ATTR_NODE_DESC, 0, CL_DISP_MSGID_NONE, &mad_context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331B: Failure initiating NodeDescription request " "(%s)\n", ib_get_err_str(status)); exit: 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(sm->p_log, osm_physp_get_dr_path_ptr (p_physp), 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; }
static void __osm_sa_slvl_by_comp_mask(IN osm_sa_t * sa, IN const osm_port_t * const p_port, osm_slvl_search_ctxt_t * const p_ctxt) { const ib_slvl_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; const osm_physp_t *p_out_physp, *p_in_physp; uint8_t in_port_num, out_port_num; uint8_t num_ports; uint8_t in_port_start, in_port_end; uint8_t out_port_start, out_port_end; const osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; num_ports = osm_node_get_num_physp(p_port->p_node); in_port_start = 0; in_port_end = num_ports - 1; out_port_start = 0; out_port_end = num_ports - 1; p_req_physp = p_ctxt->p_req_physp; if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Using Physical Default Port Number: 0x%X (for End Node)\n", p_port->p_physp->port_num); p_out_physp = p_port->p_physp; /* check that the p_out_physp and the p_req_physp share a pkey */ if (osm_physp_share_pkey (sa->p_log, p_req_physp, p_out_physp)) __osm_sa_slvl_create(sa, p_out_physp, p_ctxt, 0); } else { if (comp_mask & IB_SLVL_COMPMASK_OUT_PORT) out_port_start = out_port_end = p_rcvd_rec->out_port_num; if (comp_mask & IB_SLVL_COMPMASK_IN_PORT) in_port_start = in_port_end = p_rcvd_rec->in_port_num; for (out_port_num = out_port_start; out_port_num <= out_port_end; out_port_num++) { p_out_physp = osm_node_get_physp_ptr(p_port->p_node, out_port_num); if (!p_out_physp) continue; for (in_port_num = in_port_start; in_port_num <= in_port_end; in_port_num++) { #if 0 if (out_port_num && out_port_num == in_port_num) continue; #endif p_in_physp = osm_node_get_physp_ptr(p_port->p_node, in_port_num); if (!p_in_physp) continue; /* if the requester and the p_out_physp don't share a pkey - continue */ if (!osm_physp_share_pkey (sa->p_log, p_req_physp, p_out_physp)) continue; __osm_sa_slvl_create(sa, p_out_physp, p_ctxt, in_port_num); } } } OSM_LOG_EXIT(sa->p_log); }
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; }
static int link_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node, IN const uint8_t link_state) { osm_physp_t *p_physp, *p_physp_remote; uint32_t i, num_physp; int ret = 0; uint8_t current_state; OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Node 0x%" PRIx64 " going to %s\n", cl_ntoh64(osm_node_get_node_guid(p_node)), ib_get_port_state_str(link_state)); /* Set the PortInfo for every Physical Port associated with this Port. Start iterating with port 1, since the linkstate is not applicable to the management port on switches. */ num_physp = osm_node_get_num_physp(p_node); for (i = 0; i < num_physp; i++) { /* Don't bother doing anything if this Physical Port is not valid. or if the state of the port is already better then the specified state. */ p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i); if (!p_physp) continue; current_state = osm_physp_get_port_state(p_physp); if (current_state == IB_LINK_DOWN) continue; /* Set PortState to DOWN in case Remote Physical Port is unreachable. We have to check this for all ports, except port zero. */ p_physp_remote = osm_physp_get_remote(p_physp); if ((i != 0) && (!p_physp_remote || !osm_physp_is_valid(p_physp_remote))) { if (current_state != IB_LINK_INIT) link_mgr_set_physp_pi(sm, p_physp, IB_LINK_DOWN); continue; } /* Normally we only send state update if state is lower then required state. However, we need to send update if no state change required. */ if (link_state != IB_LINK_NO_CHANGE && link_state <= current_state) OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Physical port %u already %s. Skipping\n", p_physp->port_num, ib_get_port_state_str(current_state)); else if (link_mgr_set_physp_pi(sm, p_physp, link_state)) ret = -1; } OSM_LOG_EXIT(sm->p_log); return ret; }
static int qos_extports_setup(osm_sm_t * sm, osm_node_t *node, const struct qos_config *qcfg, cl_qlist_t *port_mad_list) { osm_physp_t *p0, *p; unsigned force_update; unsigned num_ports = osm_node_get_num_physp(node); struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; int ret = 0; unsigned in, out; uint8_t op_vl, common_op_vl = 0, max_num = 0; uint8_t op_vl_arr[15]; /* * Do nothing unless the most recent routing attempt was successful. */ if (!re) return ret; for (out = 1; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; force_update = p->need_update || sm->p_subn->need_update; p->vl_high_limit = qcfg->vl_high_limit; if (vlarb_update(sm, p, p->port_num, force_update, qcfg, port_mad_list)) ret = -1; } p0 = osm_node_get_physp_ptr(node, 0); if (!(p0->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) return ret; if (ib_switch_info_get_opt_sl2vlmapping(&node->sw->switch_info) && sm->p_subn->opt.use_optimized_slvl && !re->update_sl2vl) { /* we should find the op_vl that is used by majority of ports */ memset(&op_vl_arr[0], 0, sizeof(op_vl_arr)); p0 = osm_node_get_physp_ptr(node, 1); for (out = 1; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; op_vl = ib_port_info_get_op_vls(&p->port_info); op_vl_arr[op_vl]++; if (op_vl_arr[op_vl] > max_num){ max_num = op_vl_arr[op_vl]; common_op_vl = op_vl; /* remember the port with most common op_vl */ p0 = p; } } force_update = node->sw->need_update || sm->p_subn->need_update; if (sl2vl_update_table(sm, p0, p0->port_num, 0x30000, force_update, &qcfg->sl2vl, port_mad_list)) ret = -1; /* * Overwrite default ALL configuration if port's * op_vl is different. */ for (out = 1; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; force_update = p->need_update || force_update; if (ib_port_info_get_op_vls(&p->port_info) != common_op_vl && sl2vl_update_table(sm, p, p->port_num, 0x20000 | out, force_update, &qcfg->sl2vl, port_mad_list)) ret = -1; } return ret; } /* non optimized sl2vl configuration */ out = ib_switch_info_is_enhanced_port0(&node->sw->switch_info) ? 0 : 1; for (; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; force_update = p->need_update || sm->p_subn->need_update; /* go over all in ports */ for (in = 0; in < num_ports; in++) { const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl; ib_slvl_table_t routing_sl2vl; if (re->update_sl2vl) { routing_sl2vl = *port_sl2vl; re->update_sl2vl(re->context, p, in, out, &routing_sl2vl); port_sl2vl = &routing_sl2vl; } if (sl2vl_update_table(sm, p, in, in << 8 | out, force_update, port_sl2vl, port_mad_list)) ret = -1; } } return ret; }
static void __osm_sa_pkey_by_comp_mask(IN osm_sa_t * sa, IN const osm_port_t * const p_port, osm_pkey_search_ctxt_t * const p_ctxt) { const ib_pkey_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; osm_physp_t *p_physp; uint8_t port_num; uint8_t num_ports; const osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; port_num = p_rcvd_rec->port_num; p_req_physp = p_ctxt->p_req_physp; /* if this is a switch port we can search all ports otherwise we must be looking on port 0 */ if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) { /* we put it in the comp mask and port num */ port_num = p_port->p_physp->port_num; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Using Physical Default Port Number: 0x%X (for End Node)\n", port_num); comp_mask |= IB_PKEY_COMPMASK_PORT; } if (comp_mask & IB_PKEY_COMPMASK_PORT) { if (port_num < osm_node_get_num_physp(p_port->p_node)) { p_physp = osm_node_get_physp_ptr(p_port->p_node, port_num); /* Check that the p_physp is valid, and that is shares a pkey with the p_req_physp. */ if (p_physp && (osm_physp_share_pkey (sa->p_log, p_req_physp, p_physp))) __osm_sa_pkey_check_physp(sa, p_physp, p_ctxt); } else { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4603: " "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n", port_num, osm_node_get_num_physp(p_port->p_node)); goto Exit; } } else { num_ports = osm_node_get_num_physp(p_port->p_node); for (port_num = 0; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_port->p_node, port_num); if (!p_physp) continue; /* if the requester and the p_physp don't share a pkey - continue */ if (!osm_physp_share_pkey (sa->p_log, p_req_physp, p_physp)) continue; __osm_sa_pkey_check_physp(sa, p_physp, p_ctxt); } } Exit: OSM_LOG_EXIT(sa->p_log); }
osm_signal_t 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; uint32_t num_physp; osm_physp_t *p_physp; osm_node_t *p_node; ib_api_status_t status; unsigned force_update; uint8_t i; if (!p_osm->subn.opt.qos) return OSM_SIGNAL_DONE; 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_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)) { p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); p_node = p_port->p_node; if (p_node->sw) { num_physp = osm_node_get_num_physp(p_node); for (i = 1; i < num_physp; i++) { p_physp = osm_node_get_physp_ptr(p_node, i); if (!p_physp) continue; force_update = p_physp->need_update || p_osm->subn.need_update; status = qos_physp_setup(&p_osm->log, &p_osm->sm, p_port, p_physp, i, force_update, &swe_config); } /* skip base port 0 */ if (!ib_switch_info_is_enhanced_port0 (&p_node->sw->switch_info)) continue; cfg = &sw0_config; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) cfg = &rtr_config; else cfg = &ca_config; p_physp = p_port->p_physp; if (!p_physp) continue; force_update = p_physp->need_update || p_osm->subn.need_update; status = qos_physp_setup(&p_osm->log, &p_osm->sm, p_port, p_physp, 0, force_update, cfg); } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return OSM_SIGNAL_DONE; }
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() */
static void print_node_report(cl_map_item_t * item, FILE * file, void *cxt) { osm_node_t *p_node = (osm_node_t *) item; osm_opensm_t *osm = cxt; const osm_physp_t *p_physp, *p_remote_physp; const ib_port_info_t *p_pi; uint8_t port_num; uint32_t num_ports; uint8_t node_type; node_type = osm_node_get_type(p_node); num_ports = osm_node_get_num_physp(p_node); port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1; for (; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) continue; fprintf(file, "%-11s : %s : %02X :", osm_get_manufacturer_str(cl_ntoh64 (osm_node_get_node_guid (p_node))), osm_get_node_type_str_fixed_width(node_type), port_num); p_pi = &p_physp->port_info; /* * Port state is not defined for base switch port 0 */ if (port_num == 0 && ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) fprintf(file, " :"); else fprintf(file, " %s :", osm_get_port_state_str_fixed_width (ib_port_info_get_port_state(p_pi))); /* * LID values are only meaningful in select cases. */ if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0) || node_type != IB_NODE_TYPE_SWITCH)) fprintf(file, " %04X : %01X :", cl_ntoh16(p_pi->base_lid), ib_port_info_get_lmc(p_pi)); else fprintf(file, " : :"); if (port_num == 0 && ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) fprintf(file, " : : "); else fprintf(file, " %s : %s : %s ", osm_get_mtu_str (ib_port_info_get_neighbor_mtu(p_pi)), osm_get_lwa_str(p_pi->link_width_active), osm_get_lsa_str (ib_port_info_get_link_speed_active(p_pi), ib_port_info_get_link_speed_ext_active(p_pi), ib_port_info_get_port_state(p_pi), p_physp->ext_port_info.link_speed_active & FDR10)); if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid) fprintf(file, "* %016" PRIx64 " *", cl_ntoh64(osm_physp_get_port_guid(p_physp))); else fprintf(file, ": %016" PRIx64 " :", cl_ntoh64(osm_physp_get_port_guid(p_physp))); if (port_num && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) { p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) fprintf(file, " %016" PRIx64 " (%02X)", cl_ntoh64(osm_physp_get_port_guid (p_remote_physp)), osm_physp_get_port_num(p_remote_physp)); else fprintf(file, " UNKNOWN"); } fprintf(file, "\n"); } fprintf(file, "------------------------------------------------------" "------------------------------------------------\n"); }
static void dump_topology_node(cl_map_item_t * item, FILE * file, void *cxt) { osm_node_t *p_node = (osm_node_t *) item; uint32_t cPort; osm_node_t *p_nbnode; osm_physp_t *p_physp, *p_default_physp, *p_rphysp; uint8_t link_speed_act; const char *link_speed_act_str; if (!p_node->node_info.num_ports) return; for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) { uint8_t port_state; p_physp = osm_node_get_physp_ptr(p_node, cPort); if (!p_physp) continue; p_rphysp = p_physp->p_remote_physp; if (!p_rphysp) continue; CL_ASSERT(cPort == p_physp->port_num); if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) p_default_physp = osm_node_get_physp_ptr(p_node, 0); else p_default_physp = p_physp; fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64 " NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64 " VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ", p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ? "SW" : p_node->node_info.node_type == IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type == IB_NODE_TYPE_ROUTER ? "Rt" : "**", p_default_physp->port_info.base_lid == p_default_physp->port_info. master_sm_base_lid ? "-SM" : "", p_node->node_info.num_ports, cl_ntoh64(p_node->node_info.sys_guid), cl_ntoh64(p_node->node_info.node_guid), cl_ntoh64(p_physp->port_guid), cl_ntoh32(ib_node_info_get_vendor_id (&p_node->node_info)), cl_ntoh16(p_node->node_info.device_id), cl_ntoh32(p_node->node_info.revision), p_node->print_desc, cl_ntoh16(p_default_physp->port_info.base_lid), cPort); p_nbnode = p_rphysp->p_node; if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH) p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0); else p_default_physp = p_rphysp; fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64 " NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64 " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ", p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ? "SW" : p_nbnode->node_info.node_type == IB_NODE_TYPE_CA ? "CA" : p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ? "Rt" : "**", p_default_physp->port_info.base_lid == p_default_physp->port_info. master_sm_base_lid ? "-SM" : "", p_nbnode->node_info.num_ports, cl_ntoh64(p_nbnode->node_info.sys_guid), cl_ntoh64(p_nbnode->node_info.node_guid), cl_ntoh64(p_rphysp->port_guid), cl_ntoh32(ib_node_info_get_vendor_id (&p_nbnode->node_info)), cl_ntoh32(p_nbnode->node_info.device_id), cl_ntoh32(p_nbnode->node_info.revision), p_nbnode->print_desc, cl_ntoh16(p_default_physp->port_info.base_lid), p_rphysp->port_num); port_state = ib_port_info_get_port_state(&p_physp->port_info); link_speed_act = ib_port_info_get_link_speed_active(&p_physp->port_info); if (link_speed_act == IB_LINK_SPEED_ACTIVE_2_5) link_speed_act_str = "2.5"; else if (link_speed_act == IB_LINK_SPEED_ACTIVE_5) link_speed_act_str = "5"; else if (link_speed_act == IB_LINK_SPEED_ACTIVE_10) link_speed_act_str = "10"; else link_speed_act_str = "??"; if (p_physp->ext_port_info.link_speed_active & FDR10) link_speed_act_str = "FDR10"; if (p_default_physp->port_info.capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) { link_speed_act = ib_port_info_get_link_speed_ext_active(&p_physp->port_info); if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_14) link_speed_act_str = "14"; else if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_25) link_speed_act_str = "25"; else if (link_speed_act != IB_LINK_SPEED_EXT_ACTIVE_NONE) link_speed_act_str = "??"; } fprintf(file, "PHY=%s LOG=%s SPD=%s\n", p_physp->port_info.link_width_active == 1 ? "1x" : p_physp->port_info.link_width_active == 2 ? "4x" : p_physp->port_info.link_width_active == 4 ? "8x" : p_physp->port_info.link_width_active == 8 ? "12x" : "??", port_state == IB_LINK_ACTIVE ? "ACT" : port_state == IB_LINK_ARMED ? "ARM" : port_state == IB_LINK_INIT ? "INI" : "DWN", link_speed_act_str); } }
/********************************************************************** Sweeps the node 1 hop away. This sets off a "chain reaction" that causes discovery of the subnet. Used when there is suspicion that something on the subnet has changed. **********************************************************************/ static ib_api_status_t state_mgr_sweep_hop_1(IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; osm_bind_handle_t h_bind; osm_madw_context_t context; osm_node_t *p_node; osm_port_t *p_port; osm_physp_t *p_physp; osm_dr_path_t *p_dr_path; osm_dr_path_t hop_1_path; ib_net64_t port_guid; uint8_t port_num; uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; uint8_t num_ports; osm_physp_t *p_ext_physp; OSM_LOG_ENTER(sm->p_log); /* * First, get our own port and node objects. */ port_guid = sm->p_subn->sm_port_guid; CL_ASSERT(port_guid); /* Set the in_sweep_hop_0 flag in subn to be FALSE. * This will indicate the sweeping to continue beyond the * the current node. * This is relevant for the case of SM on switch, since in the * switch info we need to signal that the sweeping should * continue through the switch. */ sm->p_subn->in_sweep_hop_0 = FALSE; p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3310: " "No SM port object\n"); status = IB_ERROR; goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); port_num = ib_node_info_get_local_port_num(&p_node->node_info); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Probing hop 1 on local port %u\n", port_num); p_physp = osm_node_get_physp_ptr(p_node, port_num); CL_ASSERT(p_physp); p_dr_path = osm_physp_get_dr_path_ptr(p_physp); h_bind = osm_dr_path_get_bind_handle(p_dr_path); CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE); memset(path_array, 0, sizeof(path_array)); /* the hop_1 operations depend on the type of our node. * Currently - legal nodes that can host SM are SW and CA */ switch (osm_node_get_type(p_node)) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = port_num; path_array[1] = port_num; osm_dr_path_init(&hop_1_path, h_bind, 1, path_array); status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3311: " "Request for NodeInfo failed (%s)\n", ib_get_err_str(status)); break; case IB_NODE_TYPE_SWITCH: /* Need to go over all the ports of the switch, and send a * node_info from them. This doesn't include the port 0 of the * switch, which hosts the SM. * Note: We'll send another switchInfo on port 0, since if no * ports are connected, we still want to get some response, and * have the subnet come up. */ num_ports = osm_node_get_num_physp(p_node); for (port_num = 1; port_num < num_ports; port_num++) { /* go through the port only if the port is not DOWN */ p_ext_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_ext_physp && ib_port_info_get_port_state (&(p_ext_physp->port_info)) > IB_LINK_DOWN) { memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = port_num; path_array[1] = port_num; osm_dr_path_init(&hop_1_path, h_bind, 1, path_array); status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3312: " "Request for NodeInfo failed (%s)\n", ib_get_err_str(status)); } } break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3313: Unknown node type %d (%s)\n", osm_node_get_type(p_node), p_node->print_desc); } Exit: OSM_LOG_EXIT(sm->p_log); return status; }
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); }
void osm_ucast_cache_add_node(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node) { uint16_t lid_ho; uint8_t max_ports; uint8_t port_num; osm_physp_t *p_physp; cache_switch_t *p_cache_sw; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) { lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0)); if (!lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Skip caching. Switch dropped before " "it gets a valid lid.\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Caching dropped switch lid %u\n", lid_ho); if (!p_node->sw) { /* something is wrong - forget about cache */ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD03: no switch info for node lid %u - " "clearing cache\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* unlink (add to cache) all the ports of this switch */ max_ports = osm_node_get_num_physp(p_node); 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) continue; osm_ucast_cache_add_link(p_mgr, p_physp, p_physp->p_remote_physp); } /* * All the ports have been dropped (cached). * If one of the ports was connected to CA/RTR, * then the cached switch would be marked as leaf. * If it isn't, then the dropped switch isn't a leaf, * and cache can't handle it. */ p_cache_sw = cache_get_sw(p_mgr, lid_ho); /* p_cache_sw could be NULL if it has no remote phys ports */ if (!p_cache_sw || !cache_sw_is_leaf(p_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dropped non-leaf switch (lid %u)\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } p_cache_sw->dropped = TRUE; if (!p_node->sw->num_hops || !p_node->sw->hops) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "No LID matrices for switch lid %u\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* lid matrices */ p_cache_sw->num_hops = p_node->sw->num_hops; p_node->sw->num_hops = 0; p_cache_sw->hops = p_node->sw->hops; p_node->sw->hops = NULL; /* linear forwarding table */ if (p_node->sw->new_lft) { /* LFT buffer exists - we use it, because it is more updated than the switch's LFT */ p_cache_sw->lft = p_node->sw->new_lft; p_node->sw->new_lft = NULL; } else { /* no LFT buffer, so we use the switch's LFT */ p_cache_sw->lft = p_node->sw->lft; p_node->sw->lft = NULL; p_node->sw->lft_size = 0; } p_cache_sw->max_lid_ho = p_node->sw->max_lid_ho; } else { /* dropping CA/RTR: add to cache all the ports of this node */ max_ports = osm_node_get_num_physp(p_node); 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) continue; CL_ASSERT(osm_node_get_type (p_physp->p_remote_physp->p_node) == IB_NODE_TYPE_SWITCH); osm_ucast_cache_add_link(p_mgr, p_physp->p_remote_physp, p_physp); } } Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_add_node() */