/** ========================================================================= */ void ep_port_tbl_rec_init(osm_physp_t *p_physp, struct ep_port_tbl_rec *p_rec) { const ib_port_info_t *p_pi; const osm_physp_t *p_physp0; uint8_t is_fdr10_active; uint8_t is_switch; if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH && osm_physp_get_port_num(p_physp) > 0) { /* for SW external ports, port 0 Capability Mask is used */ p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_physp->p_node, 0); p_pi = &p_physp0->port_info; } else { p_pi = &p_physp->port_info; } is_fdr10_active = ((p_physp->ext_port_info.link_speed_active & FDR10) ? 0xff : 0) & SSA_DB_PORT_IS_FDR10_ACTIVE_MASK; is_switch = ((osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) ? 0xff : 0) & SSA_DB_PORT_IS_SWITCH_MASK; p_rec->pkey_tbl_offset = 0; p_rec->pkey_tbl_size = 0; p_rec->port_lid = osm_physp_get_base_lid(p_physp); p_rec->port_num = osm_physp_get_port_num(p_physp); p_rec->neighbor_mtu = ib_port_info_get_neighbor_mtu(&p_physp->port_info); p_rec->rate = ib_port_info_compute_rate(&p_physp->port_info, p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) & SSA_DB_PORT_RATE_MASK; p_rec->vl_enforce = p_physp->port_info.vl_enforce; p_rec->rate = (uint8_t) (p_rec->rate | is_fdr10_active | is_switch); }
static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp) { osm_opensm_t *p_osm = sm->p_subn->p_osm; struct osm_routing_engine *re = p_osm->routing_engine_used; const osm_port_t *p_sm_port, *p_src_port; ib_net16_t slid; uint8_t sl; OSM_LOG_ENTER(sm->p_log); if (!(re && re->path_sl && (slid = osm_physp_get_base_lid(p_physp)))) { /* * Use default SL if routing engine does not provide a * path SL lookup callback. */ OSM_LOG_EXIT(sm->p_log); return sm->p_subn->opt.sm_sl; } /* Find osm_port of the SM itself = dest_port */ p_sm_port = osm_get_port_by_lid(sm->p_subn, sm->p_subn->sm_base_lid); /* Find osm_port of the source = p_physp */ p_src_port = osm_get_port_by_lid(sm->p_subn, slid); /* Call into routing engine to find proper SL */ sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl, p_src_port, p_sm_port); OSM_LOG_EXIT(sm->p_log); return sl; }
/** =========================================================================== */ static void extract_port(osm_physp_t *p_physp, uint16_t *p_lid_ho, uint64_t pkey_base_offset, uint16_t pkey_tbl_size, uint64_t *p_port_offset, struct ssa_db_extract *p_ssa_db) { struct ep_map_rec *p_map_rec; uint64_t rec_key; uint16_t lid_ho; if (p_lid_ho) { /* in case of switch port */ rec_key = ep_rec_gen_key(*p_lid_ho, osm_physp_get_port_num(p_physp)); lid_ho = *p_lid_ho; } else { rec_key = ep_rec_gen_key(ntohs(osm_physp_get_base_lid(p_physp)), osm_physp_get_port_num(p_physp)); lid_ho = 0; } smdb_port_init(p_physp, pkey_base_offset, pkey_tbl_size, htons(lid_ho), &p_ssa_db->p_port_tbl[*p_port_offset]); p_map_rec = ep_map_rec_init(*p_port_offset); cl_qmap_insert(&p_ssa_db->ep_port_tbl, rec_key, &p_map_rec->map_item); *p_port_offset = *p_port_offset + 1; }
static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp) { osm_opensm_t *p_osm = sm->p_subn->p_osm; struct osm_routing_engine *re = p_osm->routing_engine_used; ib_net16_t slid; ib_net16_t smlid; uint8_t sl; OSM_LOG_ENTER(sm->p_log); if (!(re && re->path_sl && (slid = osm_physp_get_base_lid(p_physp)))) { /* * Use default SL if routing engine does not provide a * path SL lookup callback. */ OSM_LOG_EXIT(sm->p_log); return sm->p_subn->opt.sm_sl; } smlid = sm->p_subn->sm_base_lid; /* Call into routing engine to find proper SL */ sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl, slid, smlid); OSM_LOG_EXIT(sm->p_log); return sl; }
/** ========================================================================= */ void ep_guid_to_lid_tbl_rec_init(osm_port_t *p_port, struct ep_guid_to_lid_tbl_rec *p_rec) { p_rec->guid = osm_physp_get_port_guid(p_port->p_physp); p_rec->lid = osm_physp_get_base_lid(p_port->p_physp); p_rec->lmc = osm_physp_get_lmc(p_port->p_physp); p_rec->is_switch = (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH); memset(&p_rec->pad, 0, sizeof(p_rec->pad)); }
/** ========================================================================= */ void ep_link_tbl_rec_init(osm_physp_t *p_physp, struct ep_link_tbl_rec *p_rec) { osm_physp_t *p_remote_physp; if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) { p_rec->from_lid = osm_node_get_base_lid(p_physp->p_node, 0); p_rec->from_port_num = osm_physp_get_port_num(p_physp); } else { p_rec->from_lid = osm_physp_get_base_lid(p_physp); p_rec->from_port_num = 0; } p_remote_physp = osm_physp_get_remote(p_physp); if (osm_node_get_type(p_remote_physp->p_node) == IB_NODE_TYPE_SWITCH) { p_rec->to_lid = osm_node_get_base_lid(p_remote_physp->p_node, 0); p_rec->to_port_num =osm_physp_get_port_num(p_remote_physp); } else { p_rec->to_lid = osm_physp_get_base_lid(p_remote_physp); p_rec->to_port_num = 0; } memset(&p_rec->pad, 0, sizeof(p_rec->pad)); }
/********************************************************************** The lock must be held before calling this function. **********************************************************************/ ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node, IN uint32_t port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; CL_ASSERT(port_num < p_node->physp_tbl_size); p_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_physp) { p_remote_physp = osm_physp_get_remote(p_physp); return osm_physp_get_base_lid(p_remote_physp); } return 0; }
/** =========================================================================== */ static void extract_host_port(osm_port_t *p_port, uint64_t *p_pkey_base_offset, uint64_t *p_pkey_offset, uint64_t *p_port_offset, uint64_t *p_link_offset, struct ssa_db_extract *p_ssa_db) { const osm_pkey_tbl_t *p_pkey_tbl; const ib_pkey_table_t *block; osm_physp_t *p_physp = p_port->p_physp; ib_net16_t pkey; uint16_t block_index, pkey_idx; p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp); for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++) { block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); if (!block) continue; for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; pkey_idx++) { pkey = block->pkey_entry[pkey_idx]; if (ib_pkey_is_invalid(pkey)) continue; p_ssa_db->p_pkey_tbl[*p_pkey_base_offset + *p_pkey_offset] = pkey; *p_pkey_offset = *p_pkey_offset + 1; } } if (*p_pkey_offset >= SSA_EXTRACT_PKEYS_MAX) { ssa_log_err(SSA_LOG_DEFAULT, "ERROR - truncating number of pkeys " "from %d to %d (maximum) for LID %u\n", *p_pkey_offset, SSA_EXTRACT_PKEYS_MAX - 1, ntohs(osm_physp_get_base_lid(p_physp))); *p_pkey_offset = SSA_EXTRACT_PKEYS_MAX - 1; } extract_port(p_physp, NULL, htonll(*p_pkey_base_offset * sizeof(pkey)), htons(*p_pkey_offset * sizeof(pkey)), p_port_offset, p_ssa_db); if (!osm_physp_get_remote(p_physp)) return; extract_link(p_physp, NULL, p_link_offset, p_ssa_db); }
/** =========================================================================== */ static void extract_link(osm_physp_t *p_physp, uint16_t *p_lid_ho, uint64_t *p_link_offset, struct ssa_db_extract *p_ssa_db) { struct ep_map_rec *p_map_rec; uint64_t rec_key; if (p_lid_ho) rec_key = ep_rec_gen_key(*p_lid_ho, osm_physp_get_port_num(p_physp)); else rec_key = ep_rec_gen_key(ntohs(osm_physp_get_base_lid(p_physp)), osm_physp_get_port_num(p_physp)); smdb_link_init(p_physp, &p_ssa_db->p_link_tbl[*p_link_offset]); p_map_rec = ep_map_rec_init(*p_link_offset); cl_qmap_insert(&p_ssa_db->ep_link_tbl, rec_key, &p_map_rec->map_item); *p_link_offset = *p_link_offset + 1; }
static boolean_t __osm_link_mgr_set_physp_pi(osm_sm_t * sm, IN osm_physp_t * const p_physp, IN uint8_t const port_state) { uint8_t payload[IB_SMP_DATA_SIZE]; ib_port_info_t *const p_pi = (ib_port_info_t *) payload; const ib_port_info_t *p_old_pi; osm_madw_context_t context; osm_node_t *p_node; ib_api_status_t status; uint8_t port_num; uint8_t mtu; uint8_t op_vls; boolean_t esp0 = FALSE; boolean_t send_set = FALSE; osm_physp_t *p_remote_physp; OSM_LOG_ENTER(sm->p_log); p_node = osm_physp_get_node_ptr(p_physp); port_num = osm_physp_get_port_num(p_physp); if (port_num == 0) { /* CAs don't have a port 0, and for switch port 0, we need to check if this is enhanced or base port 0. For base port 0 the following parameters are not valid (p822, table 145). */ if (!p_node->sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: " "Cannot find switch by guid: 0x%" PRIx64 "\n", cl_ntoh64(p_node->node_info.node_guid)); goto Exit; } if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) { /* This means the switch doesn't support enhanced port 0. Can skip it. */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Skipping port 0, GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_physp))); goto Exit; } esp0 = TRUE; } /* PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0 */ p_old_pi = &p_physp->port_info; memset(payload, 0, IB_SMP_DATA_SIZE); memcpy(payload, p_old_pi, sizeof(ib_port_info_t)); /* Should never write back a value that is bigger then 3 in the PortPhysicalState field - so can not simply copy! Actually we want to write there: port physical state - no change, link down default state = polling port state - as requested. */ p_pi->state_info2 = 0x02; ib_port_info_set_port_state(p_pi, port_state); if (ib_port_info_get_link_down_def_state(p_pi) != ib_port_info_get_link_down_def_state(p_old_pi)) send_set = TRUE; /* didn't get PortInfo before */ if (!ib_port_info_get_port_state(p_old_pi)) send_set = TRUE; /* we only change port fields if we do not change state */ if (port_state == IB_LINK_NO_CHANGE) { /* The following fields are relevant only for CA port, router, or Enh. SP0 */ if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH || port_num == 0) { p_pi->m_key = sm->p_subn->opt.m_key; if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key))) send_set = TRUE; p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix; if (memcmp(&p_pi->subnet_prefix, &p_old_pi->subnet_prefix, sizeof(p_pi->subnet_prefix))) send_set = TRUE; p_pi->base_lid = osm_physp_get_base_lid(p_physp); if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid, sizeof(p_pi->base_lid))) send_set = TRUE; /* we are initializing the ports with our local sm_base_lid */ p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid; if (memcmp(&p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, sizeof(p_pi->master_sm_base_lid))) send_set = TRUE; p_pi->m_key_lease_period = sm->p_subn->opt.m_key_lease_period; if (memcmp(&p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, sizeof(p_pi->m_key_lease_period))) send_set = TRUE; if (esp0 == FALSE) p_pi->mkey_lmc = sm->p_subn->opt.lmc; else { if (sm->p_subn->opt.lmc_esp0) p_pi->mkey_lmc = sm->p_subn->opt.lmc; else p_pi->mkey_lmc = 0; } if (memcmp(&p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc))) send_set = TRUE; ib_port_info_set_timeout(p_pi, sm->p_subn->opt. subnet_timeout); if (ib_port_info_get_timeout(p_pi) != ib_port_info_get_timeout(p_old_pi)) send_set = TRUE; } /* Several timeout mechanisms: */ p_remote_physp = osm_physp_get_remote(p_physp); if (port_num != 0 && p_remote_physp) { if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) == IB_NODE_TYPE_ROUTER) { ib_port_info_set_hoq_lifetime(p_pi, sm->p_subn-> opt. leaf_head_of_queue_lifetime); } else if (osm_node_get_type (osm_physp_get_node_ptr(p_physp)) == IB_NODE_TYPE_SWITCH) { /* Is remote end CA or router (a leaf port) ? */ if (osm_node_get_type (osm_physp_get_node_ptr(p_remote_physp)) != IB_NODE_TYPE_SWITCH) { ib_port_info_set_hoq_lifetime(p_pi, sm-> p_subn-> opt. leaf_head_of_queue_lifetime); ib_port_info_set_vl_stall_count(p_pi, sm-> p_subn-> opt. leaf_vl_stall_count); } else { ib_port_info_set_hoq_lifetime(p_pi, sm-> p_subn-> opt. head_of_queue_lifetime); ib_port_info_set_vl_stall_count(p_pi, sm-> p_subn-> opt. vl_stall_count); } } if (ib_port_info_get_hoq_lifetime(p_pi) != ib_port_info_get_hoq_lifetime(p_old_pi) || ib_port_info_get_vl_stall_count(p_pi) != ib_port_info_get_vl_stall_count(p_old_pi)) send_set = TRUE; } ib_port_info_set_phy_and_overrun_err_thd(p_pi, sm->p_subn->opt. local_phy_errors_threshold, sm->p_subn->opt. overrun_errors_threshold); if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold, sizeof(p_pi->error_threshold))) send_set = TRUE; /* Set the easy common parameters for all port types, then determine the neighbor MTU. */ p_pi->link_width_enabled = p_old_pi->link_width_supported; if (memcmp(&p_pi->link_width_enabled, &p_old_pi->link_width_enabled, sizeof(p_pi->link_width_enabled))) send_set = TRUE; if (sm->p_subn->opt.force_link_speed && (sm->p_subn->opt.force_link_speed != 15 || ib_port_info_get_link_speed_enabled(p_pi) != ib_port_info_get_link_speed_sup(p_pi))) { ib_port_info_set_link_speed_enabled(p_pi, sm->p_subn->opt. force_link_speed); if (memcmp(&p_pi->link_speed, &p_old_pi->link_speed, sizeof(p_pi->link_speed))) send_set = TRUE; } /* calc new op_vls and mtu */ op_vls = osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp); mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp); ib_port_info_set_neighbor_mtu(p_pi, mtu); if (ib_port_info_get_neighbor_mtu(p_pi) != ib_port_info_get_neighbor_mtu(p_old_pi)) send_set = TRUE; ib_port_info_set_op_vls(p_pi, op_vls); if (ib_port_info_get_op_vls(p_pi) != ib_port_info_get_op_vls(p_old_pi)) send_set = TRUE; /* provide the vl_high_limit from the qos mgr */ if (sm->p_subn->opt.qos && p_physp->vl_high_limit != p_old_pi->vl_high_limit) { send_set = TRUE; p_pi->vl_high_limit = p_physp->vl_high_limit; } } if (port_state != IB_LINK_NO_CHANGE && port_state != ib_port_info_get_port_state(p_old_pi)) { send_set = TRUE; if (port_state == IB_LINK_ACTIVE) context.pi_context.active_transition = TRUE; else context.pi_context.active_transition = FALSE; } 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 = TRUE; context.pi_context.light_sweep = FALSE; /* We need to send the PortInfoSet request with the new sm_lid in the following cases: 1. There is a change in the values (send_set == TRUE) 2. This is a switch external port (so it wasn't handled yet by osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE, which means the SM just became master, and it then needs to send at PortInfoSet to every port. */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num && sm->p_subn->first_time_master_sweep == TRUE) send_set = TRUE; if (send_set) status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, cl_hton32(port_num), CL_DISP_MSGID_NONE, &context); Exit: OSM_LOG_EXIT(sm->p_log); return send_set; }
static int link_mgr_set_physp_pi(osm_sm_t * sm, IN osm_physp_t * p_physp, IN uint8_t port_state) { uint8_t payload[IB_SMP_DATA_SIZE], payload2[IB_SMP_DATA_SIZE]; ib_port_info_t *p_pi = (ib_port_info_t *) payload; ib_mlnx_ext_port_info_t *p_epi = (ib_mlnx_ext_port_info_t *) payload2; const ib_port_info_t *p_old_pi; const ib_mlnx_ext_port_info_t *p_old_epi; osm_madw_context_t context; osm_node_t *p_node; ib_api_status_t status; uint8_t port_num, mtu, op_vls, smsl = OSM_DEFAULT_SL; boolean_t esp0 = FALSE, send_set = FALSE, send_set2 = FALSE; osm_physp_t *p_remote_physp, *physp0; int qdr_change = 0, fdr10_change = 0; int ret = 0; ib_net32_t attr_mod, cap_mask; OSM_LOG_ENTER(sm->p_log); p_node = osm_physp_get_node_ptr(p_physp); p_old_pi = &p_physp->port_info; port_num = osm_physp_get_port_num(p_physp); if (port_num == 0) { /* CAs don't have a port 0, and for switch port 0, we need to check if this is enhanced or base port 0. For base port 0 the following parameters are not valid (IBA 1.2.1 p.830 table 146). */ if (!p_node->sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: " "Cannot find switch by guid: 0x%" PRIx64 "\n", cl_ntoh64(p_node->node_info.node_guid)); goto Exit; } if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) { /* Even for base port 0 we might have to set smsl (if we are using lash routing) */ smsl = link_mgr_get_smsl(sm, p_physp); if (smsl != ib_port_info_get_master_smsl(p_old_pi)) { send_set = TRUE; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting SMSL to %d on port 0 GUID 0x%016" PRIx64 "\n", smsl, cl_ntoh64(osm_physp_get_port_guid (p_physp))); } else { /* This means the switch doesn't support enhanced port 0 and we don't need to change SMSL. Can skip it. */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Skipping port 0, GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid (p_physp))); goto Exit; } } else esp0 = TRUE; } memcpy(payload, p_old_pi, sizeof(ib_port_info_t)); /* Should never write back a value that is bigger then 3 in the PortPhysicalState field - so can not simply copy! Actually we want to write there: port physical state - no change, link down default state = polling port state - as requested. */ p_pi->state_info2 = 0x02; ib_port_info_set_port_state(p_pi, port_state); /* Check whether this is base port0 smsl handling only */ if (port_num == 0 && esp0 == FALSE) { ib_port_info_set_master_smsl(p_pi, smsl); goto Send; } /* PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0 */ if (ib_port_info_get_link_down_def_state(p_pi) != ib_port_info_get_link_down_def_state(p_old_pi)) send_set = TRUE; /* didn't get PortInfo before */ if (!ib_port_info_get_port_state(p_old_pi)) send_set = TRUE; /* we only change port fields if we do not change state */ if (port_state == IB_LINK_NO_CHANGE) { /* The following fields are relevant only for CA port, router, or Enh. SP0 */ if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH || port_num == 0) { p_pi->m_key = sm->p_subn->opt.m_key; if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key))) send_set = TRUE; p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix; if (memcmp(&p_pi->subnet_prefix, &p_old_pi->subnet_prefix, sizeof(p_pi->subnet_prefix))) send_set = TRUE; p_pi->base_lid = osm_physp_get_base_lid(p_physp); if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid, sizeof(p_pi->base_lid))) send_set = TRUE; /* we are initializing the ports with our local sm_base_lid */ p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid; if (memcmp(&p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, sizeof(p_pi->master_sm_base_lid))) send_set = TRUE; smsl = link_mgr_get_smsl(sm, p_physp); if (smsl != ib_port_info_get_master_smsl(p_old_pi)) { ib_port_info_set_master_smsl(p_pi, smsl); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting SMSL to %d on GUID 0x%016" PRIx64 ", port %d\n", smsl, cl_ntoh64(osm_physp_get_port_guid (p_physp)), port_num); send_set = TRUE; } p_pi->m_key_lease_period = sm->p_subn->opt.m_key_lease_period; if (memcmp(&p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, sizeof(p_pi->m_key_lease_period))) send_set = TRUE; /* M_KeyProtectBits are currently always zero */ p_pi->mkey_lmc = 0; if (esp0 == FALSE || sm->p_subn->opt.lmc_esp0) ib_port_info_set_lmc(p_pi, sm->p_subn->opt.lmc); if (ib_port_info_get_lmc(p_old_pi) != ib_port_info_get_lmc(p_pi) || ib_port_info_get_mpb(p_old_pi) != ib_port_info_get_mpb(p_pi)) send_set = TRUE; ib_port_info_set_timeout(p_pi, sm->p_subn->opt. subnet_timeout); if (ib_port_info_get_timeout(p_pi) != ib_port_info_get_timeout(p_old_pi)) send_set = TRUE; } /* Several timeout mechanisms: */ p_remote_physp = osm_physp_get_remote(p_physp); if (port_num != 0 && p_remote_physp) { if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) == IB_NODE_TYPE_ROUTER) { ib_port_info_set_hoq_lifetime(p_pi, sm->p_subn-> opt. leaf_head_of_queue_lifetime); } else if (osm_node_get_type (osm_physp_get_node_ptr(p_physp)) == IB_NODE_TYPE_SWITCH) { /* Is remote end CA or router (a leaf port) ? */ if (osm_node_get_type (osm_physp_get_node_ptr(p_remote_physp)) != IB_NODE_TYPE_SWITCH) { ib_port_info_set_hoq_lifetime(p_pi, sm-> p_subn-> opt. leaf_head_of_queue_lifetime); ib_port_info_set_vl_stall_count(p_pi, sm-> p_subn-> opt. leaf_vl_stall_count); } else { ib_port_info_set_hoq_lifetime(p_pi, sm-> p_subn-> opt. head_of_queue_lifetime); ib_port_info_set_vl_stall_count(p_pi, sm-> p_subn-> opt. vl_stall_count); } } if (ib_port_info_get_hoq_lifetime(p_pi) != ib_port_info_get_hoq_lifetime(p_old_pi) || ib_port_info_get_vl_stall_count(p_pi) != ib_port_info_get_vl_stall_count(p_old_pi)) send_set = TRUE; } ib_port_info_set_phy_and_overrun_err_thd(p_pi, sm->p_subn->opt. local_phy_errors_threshold, sm->p_subn->opt. overrun_errors_threshold); if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold, sizeof(p_pi->error_threshold))) send_set = TRUE; /* Set the easy common parameters for all port types, then determine the neighbor MTU. */ p_pi->link_width_enabled = p_old_pi->link_width_supported; if (memcmp(&p_pi->link_width_enabled, &p_old_pi->link_width_enabled, sizeof(p_pi->link_width_enabled))) send_set = TRUE; if (sm->p_subn->opt.force_link_speed && (sm->p_subn->opt.force_link_speed != 15 || ib_port_info_get_link_speed_enabled(p_pi) != ib_port_info_get_link_speed_sup(p_pi))) { ib_port_info_set_link_speed_enabled(p_pi, sm->p_subn->opt. force_link_speed); if (memcmp(&p_pi->link_speed, &p_old_pi->link_speed, sizeof(p_pi->link_speed))) { send_set = TRUE; /* Determine whether QDR in LSE is being changed */ if ((ib_port_info_get_link_speed_enabled(p_pi) & IB_LINK_SPEED_ACTIVE_10 && !(ib_port_info_get_link_speed_enabled(p_old_pi) & IB_LINK_SPEED_ACTIVE_10)) || ((!(ib_port_info_get_link_speed_enabled(p_pi) & IB_LINK_SPEED_ACTIVE_10) && ib_port_info_get_link_speed_enabled(p_old_pi) & IB_LINK_SPEED_ACTIVE_10))) qdr_change = 1; } } if (sm->p_subn->opt.fdr10 && p_physp->ext_port_info.link_speed_supported & FDR10) { if (sm->p_subn->opt.fdr10 == 1) { /* enable */ if (!(p_physp->ext_port_info.link_speed_enabled & FDR10)) fdr10_change = 1; } else { /* disable */ if (p_physp->ext_port_info.link_speed_enabled & FDR10) fdr10_change = 1; } if (fdr10_change) { p_old_epi = &p_physp->ext_port_info; memcpy(payload2, p_old_epi, sizeof(ib_mlnx_ext_port_info_t)); p_epi->state_change_enable = 0x01; if (sm->p_subn->opt.fdr10 == 1) p_epi->link_speed_enabled = FDR10; else p_epi->link_speed_enabled = 0; send_set2 = TRUE; } } if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) { physp0 = osm_node_get_physp_ptr(p_physp->p_node, 0); cap_mask = physp0->port_info.capability_mask; } else cap_mask = p_pi->capability_mask; if (!(cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS)) qdr_change = 0; /* Do peer ports support extended link speeds ? */ if (port_num != 0 && p_remote_physp) { osm_physp_t *rphysp0; ib_net32_t rem_cap_mask; if (osm_node_get_type(p_remote_physp->p_node) == IB_NODE_TYPE_SWITCH) { rphysp0 = osm_node_get_physp_ptr(p_remote_physp->p_node, 0); rem_cap_mask = rphysp0->port_info.capability_mask; } else rem_cap_mask = p_remote_physp->port_info.capability_mask; if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS && rem_cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) { if (sm->p_subn->opt.force_link_speed_ext && (sm->p_subn->opt.force_link_speed_ext != IB_LINK_SPEED_EXT_SET_LSES || p_pi->link_speed_ext_enabled != ib_port_info_get_link_speed_sup(p_pi))) { p_pi->link_speed_ext_enabled = sm->p_subn->opt.force_link_speed_ext; if (memcmp(&p_pi->link_speed_ext_enabled, &p_old_pi->link_speed_ext_enabled, sizeof(p_pi->link_speed_ext_enabled))) send_set = TRUE; } } } /* calc new op_vls and mtu */ op_vls = osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp); mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp); ib_port_info_set_neighbor_mtu(p_pi, mtu); if (ib_port_info_get_neighbor_mtu(p_pi) != ib_port_info_get_neighbor_mtu(p_old_pi)) send_set = TRUE; ib_port_info_set_op_vls(p_pi, op_vls); if (ib_port_info_get_op_vls(p_pi) != ib_port_info_get_op_vls(p_old_pi)) send_set = TRUE; /* provide the vl_high_limit from the qos mgr */ if (sm->p_subn->opt.qos && p_physp->vl_high_limit != p_old_pi->vl_high_limit) { send_set = TRUE; p_pi->vl_high_limit = p_physp->vl_high_limit; } } Send: if (port_state != IB_LINK_NO_CHANGE && port_state != ib_port_info_get_port_state(p_old_pi)) { send_set = TRUE; if (port_state == IB_LINK_ACTIVE) context.pi_context.active_transition = TRUE; else context.pi_context.active_transition = FALSE; } 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 = TRUE; context.pi_context.light_sweep = FALSE; /* We need to send the PortInfoSet request with the new sm_lid in the following cases: 1. There is a change in the values (send_set == TRUE) 2. This is a switch external port (so it wasn't handled yet by osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE, which means the SM just became master, and it then needs to send at PortInfoSet to every port. */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num && sm->p_subn->first_time_master_sweep == TRUE) send_set = TRUE; if (!send_set) goto Exit; attr_mod = cl_hton32(port_num); if (qdr_change) attr_mod |= cl_hton32(1 << 31); /* AM SMSupportExtendedSpeeds */ status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, attr_mod, CL_DISP_MSGID_NONE, &context); if (status) ret = -1; if (send_set2) { status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), payload2, sizeof(payload2), IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO, cl_hton32(port_num), CL_DISP_MSGID_NONE, &context); if (status) ret = -1; } Exit: OSM_LOG_EXIT(sm->p_log); return ret; }
/** =========================================================================== */ static void extract_switch_port(osm_port_t *p_port, uint64_t *p_pkey_base_offset, uint64_t *p_pkey_offset, uint64_t *p_port_offset, uint64_t *p_link_offset, struct ssa_db_extract *p_ssa_db) { osm_node_t *p_node = p_port->p_physp->p_node; const osm_pkey_tbl_t *p_pkey_tbl; const ib_pkey_table_t *block; osm_physp_t *p_physp; uint32_t i; ib_net16_t pkey; uint16_t lid_ho, block_index, pkey_idx; for (i = 0; i < p_node->physp_tbl_size; i++) { p_physp = osm_node_get_physp_ptr(p_node, i); if (!p_physp) continue; /* TODO: add filtering for down ports */ if (i == 0) { lid_ho = ntohs(osm_physp_get_base_lid(p_physp)); p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp); for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++) { block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); if (!block) continue; for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; pkey_idx++) { pkey = block->pkey_entry[pkey_idx]; if (ib_pkey_is_invalid(pkey)) continue; p_ssa_db->p_pkey_tbl[*p_pkey_base_offset + *p_pkey_offset] = pkey; *p_pkey_offset = *p_pkey_offset + 1; } } if (*p_pkey_offset >= SSA_EXTRACT_PKEYS_MAX) { ssa_log_err(SSA_LOG_DEFAULT, "ERROR - truncating number of pkeys " "from %d to %d (maximum) for LID %u\n", *p_pkey_offset, SSA_EXTRACT_PKEYS_MAX - 1, lid_ho); *p_pkey_offset = SSA_EXTRACT_PKEYS_MAX - 1; } extract_port(p_physp, &lid_ho, htonll(*p_pkey_base_offset * sizeof(pkey)), htons(*p_pkey_offset * sizeof(pkey)), p_port_offset, p_ssa_db); } else { extract_port(p_physp, &lid_ho, 0, 0, p_port_offset, p_ssa_db); } if (!osm_physp_get_remote(p_physp)) continue; extract_link(p_physp, &lid_ho, p_link_offset, p_ssa_db); } }
static ib_net16_t get_base_lid(IN const osm_physp_t * p_physp) { if (p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) p_physp = osm_node_get_physp_ptr(p_physp->p_node, 0); return osm_physp_get_base_lid(p_physp); }
void osm_ucast_cache_add_link(osm_ucast_mgr_t * p_mgr, osm_physp_t * p_physp1, osm_physp_t * p_physp2) { osm_node_t *p_node_1 = p_physp1->p_node, *p_node_2 = p_physp2->p_node; uint16_t lid_ho_1, lid_ho_2; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH && osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dropping CA-2-CA link\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if ((osm_node_get_type(p_node_1) == IB_NODE_TYPE_SWITCH && !osm_node_get_physp_ptr(p_node_1, 0)) || (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH && !osm_node_get_physp_ptr(p_node_2, 0))) { /* we're caching a link when one of the nodes has already been dropped and cached */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Port %u <-> port %u: port0 on one of the nodes " "has already been dropped and cached\n", p_physp1->port_num, p_physp2->port_num); goto Exit; } /* One of the nodes is switch. Just for code simplicity, make sure that it's the first node. */ if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) { osm_physp_t *tmp = p_physp1; p_physp1 = p_physp2; p_physp2 = tmp; p_node_1 = p_physp1->p_node; p_node_2 = p_physp2->p_node; } if (!p_node_1->sw) { /* something is wrong - we'd better not use cache */ osm_ucast_cache_invalidate(p_mgr); goto Exit; } lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0)); if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) { if (!p_node_2->sw) { /* something is wrong - we'd better not use cache */ osm_ucast_cache_invalidate(p_mgr); goto Exit; } lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0)); /* lost switch-2-switch link - cache both sides */ cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, FALSE); cache_add_sw_link(p_mgr, p_physp2, lid_ho_1, FALSE); } else { lid_ho_2 = cl_ntoh16(osm_physp_get_base_lid(p_physp2)); /* lost link to CA/RTR - cache only switch side */ cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, TRUE); } Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_add_link() */