/****f* opensm: SM/__osm_sm_mad_ctrl_process_set * NAME * __osm_sm_mad_ctrl_process_set * * DESCRIPTION * This function handles method Set() for received MADs. * * SYNOPSIS */ static void __osm_sm_mad_ctrl_process_set(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); /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_SM_INFO: msg_id = OSM_MSG_MAD_SM_INFO; break; default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: " "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 3108: " "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); }
/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp * NAME * __osm_sm_mad_ctrl_process_get_resp * * DESCRIPTION * This function handles method GetResp() for received MADs. * This is the most common path for QP0 MADs. * * SYNOPSIS */ static void __osm_sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * const p_ctrl, IN osm_madw_t * p_madw, IN void *transaction_context) { ib_smp_t *p_smp; cl_status_t status; osm_madw_t *p_old_madw; cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); CL_ASSERT(transaction_context); p_smp = osm_madw_get_smp_ptr(p_madw); if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: " "'D' bit not set in returned SMP\n"); osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); } p_old_madw = (osm_madw_t *) transaction_context; __osm_sm_mad_ctrl_update_wire_stats(p_ctrl); /* Copy the MAD Wrapper context from the requesting MAD to the new MAD. This mechanism allows the recipient controller to recover its own context regarding this MAD transaction. Once we've copied the context, we can return the original MAD to the pool. */ osm_madw_copy_context(p_madw, p_old_madw); osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw); /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_NODE_DESC: msg_id = OSM_MSG_MAD_NODE_DESC; break; case IB_MAD_ATTR_NODE_INFO: msg_id = OSM_MSG_MAD_NODE_INFO; break; case IB_MAD_ATTR_SWITCH_INFO: msg_id = OSM_MSG_MAD_SWITCH_INFO; break; case IB_MAD_ATTR_PORT_INFO: msg_id = OSM_MSG_MAD_PORT_INFO; break; case IB_MAD_ATTR_LIN_FWD_TBL: msg_id = OSM_MSG_MAD_LFT; break; case IB_MAD_ATTR_MCAST_FWD_TBL: msg_id = OSM_MSG_MAD_MFT; break; case IB_MAD_ATTR_SM_INFO: msg_id = OSM_MSG_MAD_SM_INFO; break; case IB_MAD_ATTR_SLVL_TABLE: msg_id = OSM_MSG_MAD_SLVL; break; case IB_MAD_ATTR_VL_ARBITRATION: msg_id = OSM_MSG_MAD_VL_ARB; break; case IB_MAD_ATTR_P_KEY_TABLE: msg_id = OSM_MSG_MAD_PKEY; break; case IB_MAD_ATTR_GUID_INFO: case IB_MAD_ATTR_CLASS_PORT_INFO: case IB_MAD_ATTR_NOTICE: case IB_MAD_ATTR_INFORM_INFO: default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: " "Unsupported attribute = 0x%X\n", cl_ntoh16(p_smp->attr_id)); osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); goto Exit; } if (msg_id == CL_DISP_MSGID_NONE) 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 3104: " "Dispatcher post message failed (%s) for attribute = 0x%X\n", CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id)); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); }
static void vl15_poller(IN void *p_ptr) { ib_api_status_t status; osm_madw_t *p_madw; osm_vl15_t *p_vl = p_ptr; cl_qlist_t *p_fifo; int32_t max_smps = p_vl->max_wire_smps; int32_t max_smps2 = p_vl->max_wire_smps2; OSM_LOG_ENTER(p_vl->p_log); if (p_vl->thread_state == OSM_THREAD_STATE_NONE) p_vl->thread_state = OSM_THREAD_STATE_RUN; while (p_vl->thread_state == OSM_THREAD_STATE_RUN) { /* Start servicing the FIFOs by pulling off MAD wrappers and passing them to the transport interface. There are lots of corner cases here so tread carefully. The unicast FIFO has priority, since somebody is waiting for a timely response. */ cl_spinlock_acquire(&p_vl->lock); if (cl_qlist_count(&p_vl->ufifo) != 0) p_fifo = &p_vl->ufifo; else p_fifo = &p_vl->rfifo; p_madw = (osm_madw_t *) cl_qlist_remove_head(p_fifo); cl_spinlock_release(&p_vl->lock); if (p_madw != (osm_madw_t *) cl_qlist_end(p_fifo)) { OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Servicing p_madw = %p\n", p_madw); if (osm_log_is_active(p_vl->p_log, OSM_LOG_FRAMES)) osm_dump_dr_smp(p_vl->p_log, osm_madw_get_smp_ptr(p_madw), OSM_LOG_FRAMES); vl15_send_mad(p_vl, p_madw); } else /* The VL15 FIFO is empty, so we have nothing left to do. */ status = cl_event_wait_on(&p_vl->signal, EVENT_NO_TIMEOUT, TRUE); while (p_vl->p_stats->qp0_mads_outstanding_on_wire >= max_smps && p_vl->thread_state == OSM_THREAD_STATE_RUN) { status = cl_event_wait_on(&p_vl->signal, p_vl->max_smps_timeout, TRUE); if (status == CL_TIMEOUT) { if (max_smps < max_smps2) max_smps++; break; } else if (status != CL_SUCCESS) { OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E02: " "Event wait failed (%s)\n", CL_STATUS_MSG(status)); break; } max_smps = p_vl->max_wire_smps; } } /* since we abort immediately when the state != OSM_THREAD_STATE_RUN we might have some mads on the queues. After the thread exits the vl15 destroy routine should put these mads back... */ OSM_LOG_EXIT(p_vl->p_log); }