/********************************************************************* Received a Set(InformInfo) MAD **********************************************************************/ static void osm_infr_rcv_process_set_method(IN osm_sa_t * sa, IN osm_madw_t * const p_madw) { ib_sa_mad_t *p_sa_mad; ib_inform_info_t *p_recvd_inform_info; osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */ osm_infr_t *p_infr; ib_net32_t qpn; uint8_t resp_time_val; ib_api_status_t res; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_inform_info = (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); #if 0 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) osm_dump_inform_info(sa->p_log, p_recvd_inform_info, OSM_LOG_DEBUG); #endif /* Grab the lock */ cl_plock_excl_acquire(sa->p_lock); /* define the inform record */ inform_info_rec.inform_record.inform_info = *p_recvd_inform_info; /* following C13-32.1.2 Tbl 120: we only copy the source address vector */ inform_info_rec.report_addr = p_madw->mad_addr; /* we will need to know the mad srvc to send back through */ inform_info_rec.h_bind = p_madw->h_bind; inform_info_rec.sa = sa; /* update the subscriber GID according to mad address */ res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr, &inform_info_rec.inform_record. subscriber_gid); if (res != IB_SUCCESS) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 " "Subscribe Request from unknown LID: %u\n", cl_ntoh16(p_madw->mad_addr.dest_lid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* HACK: enum is always 0 (currently) */ inform_info_rec.inform_record.subscriber_enum = 0; /* Subscribe values above 1 are undefined */ if (p_recvd_inform_info->subscribe > 1) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 " "Invalid subscribe: %d\n", p_recvd_inform_info->subscribe); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * MODIFICATIONS DONE ON INCOMING REQUEST: * * QPN: * Internally we keep the QPN field of the InformInfo updated * so we can simply compare it in the record - when finding such. */ if (p_recvd_inform_info->subscribe) { ib_inform_info_set_qpn(&inform_info_rec.inform_record. inform_info, inform_info_rec.report_addr.addr_type. gsi.remote_qp); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Subscribe Request with QPN: 0x%06X\n", cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi. remote_qp)); } else { ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v. generic.qpn_resp_time_val, &qpn, &resp_time_val); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "UnSubscribe Request with QPN: 0x%06X\n", cl_ntoh32(qpn)); } /* If record exists with matching InformInfo */ p_infr = osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec); /* check to see if the request was for subscribe */ if (p_recvd_inform_info->subscribe) { /* validate the request for a new or update InformInfo */ if (__validate_infr(sa, &inform_info_rec) != TRUE) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: " "Failed to validate a new inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* ok - we can try and create a new entry */ if (p_infr == NULL) { /* Create the instance of the osm_infr_t object */ p_infr = osm_infr_new(&inform_info_rec); if (p_infr == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: " "Failed to create a new inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } /* Add this new osm_infr_t object to subnet object */ osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr); } else /* Update the old instance of the osm_infr_t object */ p_infr->inform_record = inform_info_rec.inform_record; /* We got an UnSubscribe request */ } else if (p_infr == NULL) { cl_plock_release(sa->p_lock); /* No Such Item - So Error */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: " "Failed to UnSubscribe to non existing inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } else /* Delete this object from the subnet list of informs */ osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr); cl_plock_release(sa->p_lock); /* send the success response */ __osm_infr_rcv_respond(sa, p_madw); Exit: OSM_LOG_EXIT(sa->p_log); }
/* * Register/Unregister to receive the given InformInfo * * Uses the qp context to send the inform info mad. * Wait for GetResp(InformInfoResp) * */ ib_api_status_t osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt, IN osmt_qp_ctx_t * p_qp_ctx, IN ib_inform_info_t * p_inform_info, IN uint8_t reg_flag) { ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf); ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); /* SA Payload */ VAPI_ret_t vapi_ret; VAPI_wc_desc_t wc_desc; VAPI_ud_av_hndl_t avh; static VAPI_wr_id_t wrid = 16198; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); /* init the MAD */ ib_mad_init_new((ib_mad_t *) p_sa_mad, IB_MCLASS_SUBN_ADM, (uint8_t) 2, IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0); wrid++; p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO; /* copy the reference inform info */ memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t)); if (reg_flag) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n", p_ii->lid_range_begin, p_ii->lid_range_end, p_ii->g_or_v.generic.trap_num); } else { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n", p_ii->lid_range_begin, p_ii->lid_range_end); } /* set the subscribe bit */ if (reg_flag) { p_ii->subscribe = 1; } else { p_ii->subscribe = 0; /* * we need to set the QPN on the mad if we unsubscribe: * o13-2.1.1 - QPN Field need to be set when unsubscribing. */ ib_inform_info_set_qpn(p_ii, cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id. qp_num)); } osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG); /* --------------------- PREP ------------------------- */ if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1, /* but we need only one mad at a time */ GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: " "Error posting recv bufs\n"); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n"); vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: " "Error Preparing AVH (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n"); if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) { osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf), OSM_LOG_DEBUG); #if 0 for (i = 56; i < 253; i++) { if (i % 8 == 0) { printf("\n %d : ", i); } printf("0x%02X ", p_qp_ctx->p_send_buf[i]); } #endif printf("\n"); } /* --------------------- SEND ------------------------- */ vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1, /* SA is QP1 */ 0, /* SL is 0 */ OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY, avh); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: " "Error sending mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, p_qp_ctx->qp_bind_hndl.sq_cq_hndl, &wc_desc, 20, 10000, NULL); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: " "Error getting send completion (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } if (wc_desc.status != VAPI_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: " "Error on send completion (%s) (%d)\n", VAPI_strerror_sym(wc_desc.status), wc_desc.status); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n"); /* --------------------- RECV ------------------------- */ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, p_qp_ctx->qp_bind_hndl.rq_cq_hndl, &wc_desc, 20, 10000, &avh); if (vapi_ret != VAPI_SUCCESS) { if (vapi_ret == VAPI_CQ_EMPTY) { status = IB_TIMEOUT; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: " "Error receiving mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; } goto Exit; } /* check to see if successful - by examination of the subscribe bit */ p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN); if (p_sa_mad->status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str((ib_mad_t *) p_sa_mad)); status = IB_REMOTE_ERROR; goto Exit; } if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n", p_sa_mad->method); status = IB_REMOTE_ERROR; goto Exit; } if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n", cl_ntoh16(p_sa_mad->attr_id)); status = IB_REMOTE_ERROR; goto Exit; } p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); if (!p_ii->subscribe) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: " "Subscribe/Unsubscribe Failed\n"); status = IB_REMOTE_ERROR; } Exit: OSM_LOG_EXIT(&p_osmt->log); return status; }