boolean_t osm_port_share_pkey(IN osm_log_t * p_log, IN const osm_port_t * p_port_1, IN const osm_port_t * p_port_2, IN boolean_t allow_both_pkeys) { osm_physp_t *p_physp1, *p_physp2; boolean_t ret; OSM_LOG_ENTER(p_log); if (!p_port_1 || !p_port_2) { ret = FALSE; goto Exit; } p_physp1 = p_port_1->p_physp; p_physp2 = p_port_2->p_physp; if (!p_physp1 || !p_physp2) { ret = FALSE; goto Exit; } ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2, allow_both_pkeys); Exit: OSM_LOG_EXIT(p_log); return ret; }
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); }
/********************************************************************** o13-14.1.1: Except for Set(InformInfo) requests with Inform- Info:LIDRangeBegin=0xFFFF, managers that support event forwarding shall, upon receiving a Set(InformInfo), verify that the requester originating the Set(InformInfo) and a Trap() source identified by Inform- can access each other - can use path record to verify that. **********************************************************************/ static boolean_t __validate_ports_access_rights(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec) { boolean_t valid = TRUE; osm_physp_t *p_requester_physp; osm_port_t *p_port; osm_physp_t *p_physp; ib_net64_t portguid; ib_net16_t lid_range_begin; ib_net16_t lid_range_end; ib_net16_t lid; const cl_ptr_vector_t *p_tbl; ib_gid_t zero_gid; OSM_LOG_ENTER(sa->p_log); /* get the requester physp from the request address */ p_requester_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, &p_infr_rec->report_addr); memset(&zero_gid, 0, sizeof(zero_gid)); if (memcmp(&(p_infr_rec->inform_record.inform_info.gid), &zero_gid, sizeof(ib_gid_t))) { /* a gid is defined */ portguid = p_infr_rec->inform_record.inform_info.gid.unicast. interface_id; p_port = osm_get_port_by_guid(sa->p_subn, portguid); if (p_port == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4301: " "Invalid port guid: 0x%016" PRIx64 "\n", cl_ntoh64(portguid)); valid = FALSE; goto Exit; } /* get the destination InformInfo physical port */ p_physp = p_port->p_physp; /* make sure that the requester and destination port can access each other according to the current partitioning. */ if (!osm_physp_share_pkey (sa->p_log, p_physp, p_requester_physp)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "port and requester don't share pkey\n"); valid = FALSE; goto Exit; } } else { /* gid is zero - check if LID range is defined */ lid_range_begin = cl_ntoh16(p_infr_rec->inform_record.inform_info. lid_range_begin); /* if lid is 0xFFFF - meaning all endports managed by the manager */ if (lid_range_begin == 0xFFFF) goto Exit; lid_range_end = cl_ntoh16(p_infr_rec->inform_record.inform_info. lid_range_end); /* lid_range_end is set to zero if no range desired. In this case - just make it equal to the lid_range_begin. */ if (lid_range_end == 0) lid_range_end = lid_range_begin; /* go over all defined lids within the range and make sure that the requester port can access them according to current partitioning. */ for (lid = lid_range_begin; lid <= lid_range_end; lid++) { p_tbl = &sa->p_subn->port_lid_tbl; if (cl_ptr_vector_get_size(p_tbl) > lid) p_port = cl_ptr_vector_get(p_tbl, lid); else { /* lid requested is out of range */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4302: " "Given LID (%u) is out of range:%u\n", lid, cl_ptr_vector_get_size(p_tbl)); valid = FALSE; goto Exit; } if (p_port == NULL) continue; p_physp = p_port->p_physp; /* make sure that the requester and destination port can access each other according to the current partitioning. */ if (!osm_physp_share_pkey (sa->p_log, p_physp, p_requester_physp)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "port and requester don't share pkey\n"); valid = FALSE; goto Exit; } } } Exit: OSM_LOG_EXIT(sa->p_log); return valid; }
static void __osm_sa_inform_info_rec_by_comp_mask(IN osm_sa_t * sa, IN const osm_infr_t * const p_infr, osm_iir_search_ctxt_t * const p_ctxt) { const ib_inform_info_record_t *p_rcvd_rec = NULL; ib_net64_t comp_mask; ib_net64_t portguid; osm_port_t *p_subscriber_port; osm_physp_t *p_subscriber_physp; const osm_physp_t *p_req_physp; osm_iir_item_t *p_rec_item; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; p_req_physp = p_ctxt->p_req_physp; if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID && memcmp(&p_infr->inform_record.subscriber_gid, &p_ctxt->subscriber_gid, sizeof(p_infr->inform_record.subscriber_gid))) goto Exit; if (comp_mask & IB_IIR_COMPMASK_ENUM && p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum) goto Exit; /* Implement any other needed search cases */ /* Ensure pkey is shared before returning any records */ portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id; p_subscriber_port = osm_get_port_by_guid(sa->p_subn, portguid); if (p_subscriber_port == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430D: " "Invalid subscriber port guid: 0x%016" PRIx64 "\n", cl_ntoh64(portguid)); goto Exit; } /* get the subscriber InformInfo physical port */ p_subscriber_physp = p_subscriber_port->p_physp; /* make sure that the requester and subscriber port can access each other according to the current partitioning. */ if (!osm_physp_share_pkey (sa->p_log, p_req_physp, p_subscriber_physp)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "requester and subscriber ports don't share pkey\n"); goto Exit; } p_rec_item = malloc(sizeof(*p_rec_item)); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430E: " "rec_item alloc failed\n"); goto Exit; } memcpy((void *)&p_rec_item->rec, (void *)&p_infr->inform_record, sizeof(ib_inform_info_record_t)); cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); }
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); }
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); }
void osm_smir_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *sad_mad; const ib_sminfo_record_t *p_rcvd_rec; const osm_port_t *p_port = NULL; const ib_sm_info_t *p_smi; cl_qlist_t rec_list; osm_smir_search_ctxt_t context; ib_api_status_t status = IB_SUCCESS; ib_net64_t comp_mask; ib_net64_t port_guid; osm_physp_t *p_req_physp; osm_port_t *local_port; osm_remote_sm_t *p_rem_sm; cl_qmap_t *p_sm_guid_tbl; uint8_t pri_state; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); sad_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_sminfo_record_t *) ib_sa_mad_get_payload_ptr(sad_mad); comp_mask = sad_mad->comp_mask; CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (sad_mad->method != IB_MAD_METHOD_GET && sad_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2804: " "Unsupported Method (%s)\n", ib_get_sa_method_str(sad_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2803: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_sm_info_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } p_smi = &p_rcvd_rec->sm_info; cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = sad_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; cl_plock_acquire(sa->p_lock); /* If the user specified a LID, it obviously narrows our work load, since we don't have to search every port */ if (comp_mask & IB_SMIR_COMPMASK_LID) { p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (!p_port) { status = IB_NOT_FOUND; OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2806: " "No port found with LID %u\n", cl_ntoh16(p_rcvd_rec->lid)); } } if (status == IB_SUCCESS) { /* Handle our own SM first */ local_port = osm_get_port_by_guid(sa->p_subn, sa->p_subn->sm_port_guid); if (!local_port) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2809: " "No port found with GUID 0x%016" PRIx64 "\n", cl_ntoh64(sa->p_subn->sm_port_guid)); goto Exit; } if (!p_port || local_port == p_port) { if (FALSE == osm_physp_share_pkey(sa->p_log, p_req_physp, local_port->p_physp, sa->p_subn->opt.allow_both_pkeys)) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2805: " "Cannot get SMInfo record due to pkey violation\n"); goto Exit; } /* Check that other search components specified match */ if ((comp_mask & IB_SMIR_COMPMASK_GUID) && sa->p_subn->sm_port_guid != p_smi->guid) goto Remotes; if ((comp_mask & IB_SMIR_COMPMASK_PRIORITY) && sa->p_subn->opt.sm_priority != ib_sminfo_get_priority(p_smi)) goto Remotes; if ((comp_mask & IB_SMIR_COMPMASK_SMSTATE) && sa->p_subn->sm_state != ib_sminfo_get_state(p_smi)) goto Remotes; /* Now, add local SMInfo to list */ pri_state = sa->p_subn->sm_state & 0x0F; pri_state |= (sa->p_subn->opt.sm_priority & 0x0F) << 4; smir_rcv_new_smir(sa, local_port, context.p_list, sa->p_subn->sm_port_guid, cl_ntoh32(sa->p_subn->p_osm->stats. qp0_mads_sent), pri_state, p_req_physp); } Remotes: if (p_port && p_port != local_port) { /* Find remote SM corresponding to p_port */ port_guid = osm_port_get_guid(p_port); p_sm_guid_tbl = &sa->p_subn->sm_guid_tbl; p_rem_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_guid_tbl, port_guid); if (p_rem_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl)) sa_smir_by_comp_mask(sa, p_rem_sm, &context); else OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 280A: " "No remote SM for GUID 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); } else { /* Go over all other known (remote) SMs */ cl_qmap_apply_func(&sa->p_subn->sm_guid_tbl, sa_smir_by_comp_mask_cb, &context); } } cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_sminfo_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); }
static void lr_rcv_get_physp_link(IN osm_sa_t * sa, IN const ib_link_record_t * p_lr, IN const osm_physp_t * p_src_physp, IN const osm_physp_t * p_dest_physp, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list, IN const osm_physp_t * p_req_physp) { uint8_t src_port_num; uint8_t dest_port_num; ib_net16_t from_base_lid; ib_net16_t to_base_lid; ib_net16_t lmc_mask; OSM_LOG_ENTER(sa->p_log); /* If only one end of the link is specified, determine the other side. */ if (p_src_physp) { if (p_dest_physp) { /* Ensure the two physp's are actually connected. If not, bail out. */ if (osm_physp_get_remote(p_src_physp) != p_dest_physp) goto Exit; } else { p_dest_physp = osm_physp_get_remote(p_src_physp); if (p_dest_physp == NULL) goto Exit; } } else { if (p_dest_physp) { p_src_physp = osm_physp_get_remote(p_dest_physp); if (p_src_physp == NULL) goto Exit; } else goto Exit; /* no physp's, so nothing to do */ } /* Check that the p_src_physp, p_dest_physp and p_req_physp all share a pkey (doesn't have to be the same p_key). */ if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Source and Dest PhysPorts do not share PKey\n"); goto Exit; } if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_req_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Source and Requester PhysPorts do not share PKey\n"); goto Exit; } if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester and Dest PhysPorts do not share PKey\n"); goto Exit; } src_port_num = osm_physp_get_port_num(p_src_physp); dest_port_num = osm_physp_get_port_num(p_dest_physp); if (comp_mask & IB_LR_COMPMASK_FROM_PORT) if (src_port_num != p_lr->from_port_num) goto Exit; if (comp_mask & IB_LR_COMPMASK_TO_PORT) if (dest_port_num != p_lr->to_port_num) goto Exit; from_base_lid = get_base_lid(p_src_physp); to_base_lid = get_base_lid(p_dest_physp); lmc_mask = ~((1 << sa->p_subn->opt.lmc) - 1); lmc_mask = cl_hton16(lmc_mask); if (comp_mask & IB_LR_COMPMASK_FROM_LID) if (from_base_lid != (p_lr->from_lid & lmc_mask)) goto Exit; if (comp_mask & IB_LR_COMPMASK_TO_LID) if (to_base_lid != (p_lr->to_lid & lmc_mask)) goto Exit; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Acquiring link record\n" "\t\t\t\tsrc port 0x%" PRIx64 " (port %u)" ", dest port 0x%" PRIx64 " (port %u)\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), src_port_num, cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)), dest_port_num); lr_rcv_build_physp_link(sa, from_base_lid, to_base_lid, src_port_num, dest_port_num, p_list); Exit: OSM_LOG_EXIT(sa->p_log); }
static void __osm_mftr_rcv_by_comp_mask(IN cl_map_item_t * const p_map_item, IN void *context) { const osm_mftr_search_ctxt_t *const p_ctxt = (osm_mftr_search_ctxt_t *) context; osm_switch_t *const p_sw = (osm_switch_t *) p_map_item; const ib_mft_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 position_block_num_ho; uint16_t min_block, max_block, block; const osm_physp_t *p_physp; uint8_t min_position, max_position, position; /* 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 4A05: " "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 4A06: " "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)) 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_MFTR_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; } if (!osm_switch_supports_mcast(p_sw)) return; /* Are there any blocks in use ? */ if (osm_switch_get_mft_max_block_in_use(p_sw) == -1) return; position_block_num_ho = cl_ntoh16(p_rcvd_rec->position_block_num); /* now we need to decide which blocks to output */ if (comp_mask & IB_MFTR_COMPMASK_BLOCK) { max_block = min_block = position_block_num_ho & IB_MCAST_BLOCK_ID_MASK_HO; if (max_block > osm_switch_get_mft_max_block_in_use(p_sw)) return; } else { /* use as many blocks as needed */ min_block = 0; max_block = osm_switch_get_mft_max_block_in_use(p_sw); } /* need to decide which positions to output */ if (comp_mask & IB_MFTR_COMPMASK_POSITION) { min_position = max_position = (position_block_num_ho & 0xF000) >> 12; if (max_position > osm_switch_get_mft_max_position(p_sw)) return; } else {