/**********************************************************************
* 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);
}
/****f* opensm: SM/__osm_sm_mad_ctrl_process_trap
* NAME
* __osm_sm_mad_ctrl_process_trap
*
* DESCRIPTION
* This function handles method Trap() for received MADs.
*
* SYNOPSIS
*/
static void
__osm_sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * const p_ctrl,
IN osm_madw_t * p_madw)
{
ib_smp_t *p_smp;
cl_status_t status;
cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
OSM_LOG_ENTER(p_ctrl->p_log);
p_smp = osm_madw_get_smp_ptr(p_madw);
/* Make sure OpenSM is master. If not - then we should not process the trap */
if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
"Received trap but OpenSM is not in MASTER state. "
"Dropping mad\n");
osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
goto Exit;
}
/*
Note that attr_id (like the rest of the MAD) is in
network byte order.
*/
switch (p_smp->attr_id) {
case IB_MAD_ATTR_NOTICE:
msg_id = OSM_MSG_MAD_NOTICE;
break;
default:
cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: "
"Unsupported attribute = 0x%X\n",
cl_ntoh16(p_smp->attr_id));
osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
break;
}
if (msg_id == CL_DISP_MSGID_NONE) {
/*
There is an unknown MAD attribute type for which there is
no recipient. Simply retire the MAD here.
*/
osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
goto Exit;
}
/*
Post this MAD to the dispatcher for asynchronous
processing by the appropriate controller.
*/
OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
osm_get_disp_msg_str(msg_id));
status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
__osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
if (status != CL_SUCCESS) {
OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: "
"Dispatcher post message failed (%s)\n",
CL_STATUS_MSG(status));
goto Exit;
}
Exit:
OSM_LOG_EXIT(p_ctrl->p_log);
}
/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb
* NAME
* __osm_sm_mad_ctrl_send_err_cb
*
* DESCRIPTION
* This is the callback from the transport layer for send errors
* on MADs that were expecting a response.
*
* SYNOPSIS
*/
static void
__osm_sm_mad_ctrl_send_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
{
osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context;
ib_api_status_t status;
ib_smp_t *p_smp;
OSM_LOG_ENTER(p_ctrl->p_log);
CL_ASSERT(p_madw);
OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: "
"MAD completed in error (%s)\n",
ib_get_err_str(p_madw->status));
/*
If this was a SubnSet MAD, then this error might indicate a problem
in configuring the subnet. In this case - need to mark that there was
such a problem. The subnet will not be up, and the next sweep should
be a heavy sweep as well.
*/
p_smp = osm_madw_get_smp_ptr(p_madw);
if (p_smp->method == IB_MAD_METHOD_SET &&
(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ||
p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL)) {
OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: "
"Set method failed\n");
p_ctrl->p_subn->subnet_initialization_error = TRUE;
}
/*
Since we did not get any response we suspect the DR path
used for the target port.
Find it and replace it with an alternate path.
This is true only if the destination lid is not 0xFFFF, since
then we are aiming for a specific path and not specific destination
lid.
*/
/* For now - do not add the alternate dr path to the release */
#if 0
if (p_madw->mad_addr.dest_lid != 0xFFFF) {
osm_physp_t *p_physp =
osm_get_physp_by_mad_addr(p_ctrl->p_log,
p_ctrl->p_subn,
&(p_madw->mad_addr));
if (!p_physp) {
OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: "
"Failed to find the corresponding phys port\n");
} else {
osm_physp_replace_dr_path_with_alternate_dr_path
(p_ctrl->p_log, p_ctrl->p_subn, p_physp,
p_madw->h_bind);
}
}
#endif
/*
An error occurred. No response was received to a request MAD.
Retire the original request MAD.
*/
osm_dump_dr_smp(p_ctrl->p_log, osm_madw_get_smp_ptr(p_madw),
OSM_LOG_ERROR);
__osm_sm_mad_ctrl_update_wire_stats(p_ctrl);
if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
"Posting Dispatcher message %s\n",
osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
status = cl_disp_post(p_ctrl->h_disp,
osm_madw_get_err_msg(p_madw),
p_madw,
__osm_sm_mad_ctrl_disp_done_callback,
p_ctrl);
if (status != CL_SUCCESS)
OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: "
"Dispatcher post message failed (%s)\n",
CL_STATUS_MSG(status));
} else
/*
No error message was provided, just retire the MAD.
*/
__osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
OSM_LOG_EXIT(p_ctrl->p_log);
}
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;
//.........这里部分代码省略.........
static ib_api_status_t mpr_rcv_get_path_parms(IN osm_sa_t * sa,
IN const ib_multipath_rec_t *
p_mpr,
IN const osm_alias_guid_t * p_src_alias_guid,
IN const osm_alias_guid_t * p_dest_alias_guid,
IN const uint16_t dest_lid_ho,
IN const ib_net64_t comp_mask,
OUT osm_path_parms_t * p_parms)
{
const osm_node_t *p_node;
const osm_physp_t *p_physp, *p_physp0;
const osm_physp_t *p_src_physp;
const osm_physp_t *p_dest_physp;
const osm_prtn_t *p_prtn = NULL;
const ib_port_info_t *p_pi, *p_pi0;
ib_slvl_table_t *p_slvl_tbl;
ib_api_status_t status = IB_SUCCESS;
uint8_t mtu;
uint8_t rate;
uint8_t pkt_life;
uint8_t required_mtu;
uint8_t required_rate;
ib_net16_t required_pkey;
uint8_t required_sl;
uint8_t required_pkt_life;
ib_net16_t dest_lid;
int hops = 0;
int in_port_num = 0;
uint8_t i;
osm_qos_level_t *p_qos_level = NULL;
uint16_t valid_sl_mask = 0xffff;
OSM_LOG_ENTER(sa->p_log);
dest_lid = cl_hton16(dest_lid_ho);
p_dest_physp = p_dest_alias_guid->p_base_port->p_physp;
p_physp = p_src_alias_guid->p_base_port->p_physp;
p_src_physp = p_physp;
p_pi = &p_physp->port_info;
mtu = ib_port_info_get_mtu_cap(p_pi);
rate = ib_port_info_compute_rate(p_pi,
p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS);
/*
Mellanox Tavor device performance is better using 1K MTU.
If required MTU and MTU selector are such that 1K is OK
and at least one end of the path is Tavor we override the
port MTU with 1K.
*/
if (sa->p_subn->opt.enable_quirks &&
sa_multipath_rec_apply_tavor_mtu_limit(p_mpr,
p_src_alias_guid->p_base_port,
p_dest_alias_guid->p_base_port,
comp_mask))
if (mtu > IB_MTU_LEN_1024) {
mtu = IB_MTU_LEN_1024;
OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
"Optimized Path MTU to 1K for Mellanox Tavor device\n");
}
/*
Walk the subnet object from source to destination,
tracking the most restrictive rate and mtu values along the way...
If source port node is a switch, then p_physp should
point to the port that routes the destination lid
*/
p_node = osm_physp_get_node_ptr(p_physp);
if (p_node->sw) {
/*
* Source node is a switch.
* Make sure that p_physp points to the out port of the
* switch that routes to the destination lid (dest_lid_ho)
*/
p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
if (p_physp == 0) {
OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4514: "
"Can't find routing to LID %u on switch %s "
"(GUID 0x%016"PRIx64")\n", dest_lid_ho,
p_node->print_desc,
cl_ntoh64(osm_node_get_node_guid(p_node)));
status = IB_NOT_FOUND;
goto Exit;
}
}
if (sa->p_subn->opt.qos) {
/*
* Whether this node is switch or CA, the IN port for
* the sl2vl table is 0, because this is a source node.
*/
p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0);
/* update valid SLs that still exist on this route */
for (i = 0; i < IB_MAX_NUM_VLS; i++) {
//.........这里部分代码省略.........
static void mpr_rcv_get_apm_paths(IN osm_sa_t * sa,
IN const ib_multipath_rec_t * p_mpr,
IN const osm_port_t * p_req_port,
IN osm_alias_guid_t ** _pp_alias_guids,
IN const ib_net64_t comp_mask,
IN cl_qlist_t * p_list)
{
osm_alias_guid_t *pp_alias_guids[4];
osm_sa_item_t *matrix[2][2];
int base_offs, src_lid_ho, dest_lid_ho;
int sumA, sumB, minA, minB;
OSM_LOG_ENTER(sa->p_log);
/*
* We want to:
* 1. use different lid offsets (from base) for the resultant paths
* to increase the probability of redundant paths or in case
* of Clos - to ensure it (different offset => different spine!)
* 2. keep consistent paths no matter of direction and order of ports
* 3. distibute the lid offsets to balance the load
* So, we sort the ports (within the srcs, and within the dests),
* hash the lids of S0, D0 (after the sort), and call mpr_rcv_get_apm_port_pair_paths
* with base_lid for S0, D0 and base_lid + 1 for S1, D1. This way we will get
* always the same offsets - order independent, and make sure different spines are used.
* Note that the diagonals on a Clos have the same number of hops, so it doesn't
* really matter which diagonal we use.
*/
if (_pp_alias_guids[0]->p_base_port->guid <
_pp_alias_guids[1]->p_base_port->guid) {
pp_alias_guids[0] = _pp_alias_guids[0];
pp_alias_guids[1] = _pp_alias_guids[1];
} else {
pp_alias_guids[0] = _pp_alias_guids[1];
pp_alias_guids[1] = _pp_alias_guids[0];
}
if (_pp_alias_guids[2]->p_base_port->guid <
_pp_alias_guids[3]->p_base_port->guid) {
pp_alias_guids[2] = _pp_alias_guids[2];
pp_alias_guids[3] = _pp_alias_guids[3];
} else {
pp_alias_guids[2] = _pp_alias_guids[3];
pp_alias_guids[3] = _pp_alias_guids[2];
}
src_lid_ho = osm_port_get_base_lid(pp_alias_guids[0]->p_base_port);
dest_lid_ho = osm_port_get_base_lid(pp_alias_guids[2]->p_base_port);
base_offs = src_lid_ho < dest_lid_ho ?
hash_lids(src_lid_ho, dest_lid_ho, sa->p_subn->opt.lmc) :
hash_lids(dest_lid_ho, src_lid_ho, sa->p_subn->opt.lmc);
matrix[0][0] =
mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[0],
pp_alias_guids[2], base_offs,
comp_mask, p_list);
matrix[0][1] =
mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[0],
pp_alias_guids[3], base_offs,
comp_mask, p_list);
matrix[1][0] =
mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[1],
pp_alias_guids[2], base_offs + 1,
comp_mask, p_list);
matrix[1][1] =
mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[1],
pp_alias_guids[3], base_offs + 1,
comp_mask, p_list);
OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "APM matrix:\n"
"\t{0,0} 0x%X->0x%X (%d)\t| {0,1} 0x%X->0x%X (%d)\n"
"\t{1,0} 0x%X->0x%X (%d)\t| {1,1} 0x%X->0x%X (%d)\n",
matrix[0][0]->resp.mpr_rec.path_rec.slid,
matrix[0][0]->resp.mpr_rec.path_rec.dlid,
matrix[0][0]->resp.mpr_rec.hops,
matrix[0][1]->resp.mpr_rec.path_rec.slid,
matrix[0][1]->resp.mpr_rec.path_rec.dlid,
matrix[0][1]->resp.mpr_rec.hops,
matrix[1][0]->resp.mpr_rec.path_rec.slid,
matrix[1][0]->resp.mpr_rec.path_rec.dlid,
matrix[1][0]->resp.mpr_rec.hops,
matrix[1][1]->resp.mpr_rec.path_rec.slid,
matrix[1][1]->resp.mpr_rec.path_rec.dlid,
matrix[1][1]->resp.mpr_rec.hops);
/* check diagonal A {(0,0), (1,1)} */
sumA = matrix[0][0]->resp.mpr_rec.hops + matrix[1][1]->resp.mpr_rec.hops;
minA = min(matrix[0][0]->resp.mpr_rec.hops, matrix[1][1]->resp.mpr_rec.hops);
/* check diagonal B {(0,1), (1,0)} */
sumB = matrix[0][1]->resp.mpr_rec.hops + matrix[1][0]->resp.mpr_rec.hops;
minB = min(matrix[0][1]->resp.mpr_rec.hops, matrix[1][0]->resp.mpr_rec.hops);
/* and the winner is... */
if (minA <= minB || (minA == minB && sumA < sumB)) {
/* Diag A */
OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
"Diag {0,0} & {1,1} is the best:\n"
"\t{0,0} 0x%X->0x%X (%d)\t & {1,1} 0x%X->0x%X (%d)\n",
matrix[0][0]->resp.mpr_rec.path_rec.slid,
//.........这里部分代码省略.........
static void lftr_rcv_by_comp_mask(IN cl_map_item_t * p_map_item, IN void *cxt)
{
const osm_lftr_search_ctxt_t *p_ctxt = cxt;
const osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
const ib_lft_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec;
osm_sa_t *sa = p_ctxt->sa;
ib_net64_t const comp_mask = p_ctxt->comp_mask;
const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp;
osm_port_t *p_port;
uint16_t min_lid_ho, max_lid_ho;
uint16_t min_block, max_block, block;
const osm_physp_t *p_physp;
/* In switches, the port guid is the node guid. */
p_port = osm_get_port_by_guid(sa->p_subn,
p_sw->p_node->node_info.port_guid);
if (!p_port) {
OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4405: "
"Failed to find Port by Node Guid:0x%016" PRIx64
"\n", cl_ntoh64(p_sw->p_node->node_info.node_guid));
return;
}
/* check that the requester physp and the current physp are under
the same partition. */
p_physp = p_port->p_physp;
if (!p_physp) {
OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4406: "
"Failed to find default physical Port by Node Guid:0x%016"
PRIx64 "\n",
cl_ntoh64(p_sw->p_node->node_info.node_guid));
return;
}
if (!osm_physp_share_pkey(sa->p_log, p_req_physp,
p_physp, sa->p_subn->opt.allow_both_pkeys))
return;
/* get the port 0 of the switch */
osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
/* compare the lids - if required */
if (comp_mask & IB_LFTR_COMPMASK_LID) {
OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
"Comparing lid:%u to port lid range: %u .. %u\n",
cl_ntoh16(p_rcvd_rec->lid), min_lid_ho, max_lid_ho);
/* ok we are ready for range check */
if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) ||
max_lid_ho < cl_ntoh16(p_rcvd_rec->lid))
return;
}
/* now we need to decide which blocks to output */
max_block = osm_switch_get_max_block_id_in_use(p_sw);
if (comp_mask & IB_LFTR_COMPMASK_BLOCK) {
min_block = cl_ntoh16(p_rcvd_rec->block_num);
if (min_block > max_block)
return;
max_block = min_block;
} else /* use as many blocks as "in use" */
min_block = 0;
/* so we can add these blocks one by one ... */
for (block = min_block; block <= max_block; block++)
lftr_rcv_new_lftr(sa, p_sw, p_ctxt->p_list,
osm_port_get_base_lid(p_port), block);
}
/**********************************************************************
* 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, "
//.........这里部分代码省略.........
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;
}
请发表评论