1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff * 34219820Sjeff */ 35219820Sjeff 36219820Sjeff/* 37219820Sjeff * Abstract: 38219820Sjeff * Implementation of osm_pir_rcv_t. 39219820Sjeff * This object represents the PortInfoRecord Receiver object. 40219820Sjeff * This object is part of the opensm family of objects. 41219820Sjeff */ 42219820Sjeff 43219820Sjeff#if HAVE_CONFIG_H 44219820Sjeff# include <config.h> 45219820Sjeff#endif /* HAVE_CONFIG_H */ 46219820Sjeff 47219820Sjeff#include <string.h> 48219820Sjeff#include <iba/ib_types.h> 49219820Sjeff#include <complib/cl_qmap.h> 50219820Sjeff#include <complib/cl_passivelock.h> 51219820Sjeff#include <complib/cl_debug.h> 52219820Sjeff#include <complib/cl_qlist.h> 53219820Sjeff#include <vendor/osm_vendor_api.h> 54219820Sjeff#include <opensm/osm_port.h> 55219820Sjeff#include <opensm/osm_node.h> 56219820Sjeff#include <opensm/osm_switch.h> 57219820Sjeff#include <opensm/osm_helper.h> 58219820Sjeff#include <opensm/osm_pkey.h> 59219820Sjeff#include <opensm/osm_sa.h> 60219820Sjeff 61219820Sjefftypedef struct osm_pir_item { 62219820Sjeff cl_list_item_t list_item; 63219820Sjeff ib_portinfo_record_t rec; 64219820Sjeff} osm_pir_item_t; 65219820Sjeff 66219820Sjefftypedef struct osm_pir_search_ctxt { 67219820Sjeff const ib_portinfo_record_t *p_rcvd_rec; 68219820Sjeff ib_net64_t comp_mask; 69219820Sjeff cl_qlist_t *p_list; 70219820Sjeff osm_sa_t *sa; 71219820Sjeff const osm_physp_t *p_req_physp; 72219820Sjeff boolean_t is_enhanced_comp_mask; 73219820Sjeff} osm_pir_search_ctxt_t; 74219820Sjeff 75219820Sjeff/********************************************************************** 76219820Sjeff **********************************************************************/ 77219820Sjeffstatic ib_api_status_t 78219820Sjeff__osm_pir_rcv_new_pir(IN osm_sa_t * sa, 79219820Sjeff IN const osm_physp_t * const p_physp, 80219820Sjeff IN cl_qlist_t * const p_list, IN ib_net16_t const lid) 81219820Sjeff{ 82219820Sjeff osm_pir_item_t *p_rec_item; 83219820Sjeff ib_api_status_t status = IB_SUCCESS; 84219820Sjeff 85219820Sjeff OSM_LOG_ENTER(sa->p_log); 86219820Sjeff 87219820Sjeff p_rec_item = malloc(sizeof(*p_rec_item)); 88219820Sjeff if (p_rec_item == NULL) { 89219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2102: " 90219820Sjeff "rec_item alloc failed\n"); 91219820Sjeff status = IB_INSUFFICIENT_RESOURCES; 92219820Sjeff goto Exit; 93219820Sjeff } 94219820Sjeff 95219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 96219820Sjeff "New PortInfoRecord: port 0x%016" PRIx64 97219820Sjeff ", lid %u, port %u\n", 98219820Sjeff cl_ntoh64(osm_physp_get_port_guid(p_physp)), 99219820Sjeff cl_ntoh16(lid), osm_physp_get_port_num(p_physp)); 100219820Sjeff 101219820Sjeff memset(p_rec_item, 0, sizeof(*p_rec_item)); 102219820Sjeff 103219820Sjeff p_rec_item->rec.lid = lid; 104219820Sjeff p_rec_item->rec.port_info = p_physp->port_info; 105219820Sjeff p_rec_item->rec.port_num = osm_physp_get_port_num(p_physp); 106219820Sjeff 107219820Sjeff cl_qlist_insert_tail(p_list, &p_rec_item->list_item); 108219820Sjeff 109219820SjeffExit: 110219820Sjeff OSM_LOG_EXIT(sa->p_log); 111219820Sjeff return (status); 112219820Sjeff} 113219820Sjeff 114219820Sjeff/********************************************************************** 115219820Sjeff **********************************************************************/ 116219820Sjeffstatic void 117219820Sjeff__osm_sa_pir_create(IN osm_sa_t * sa, 118219820Sjeff IN const osm_physp_t * const p_physp, 119219820Sjeff IN osm_pir_search_ctxt_t * const p_ctxt) 120219820Sjeff{ 121219820Sjeff uint8_t lmc; 122219820Sjeff uint16_t max_lid_ho; 123219820Sjeff uint16_t base_lid_ho; 124219820Sjeff uint16_t match_lid_ho; 125219820Sjeff osm_physp_t *p_node_physp; 126219820Sjeff 127219820Sjeff OSM_LOG_ENTER(sa->p_log); 128219820Sjeff 129219820Sjeff if (p_physp->p_node->sw) { 130219820Sjeff p_node_physp = osm_node_get_physp_ptr(p_physp->p_node, 0); 131219820Sjeff base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_node_physp)); 132219820Sjeff lmc = 133219820Sjeff osm_switch_sp0_is_lmc_capable(p_physp->p_node->sw, 134219820Sjeff sa-> 135219820Sjeff p_subn) ? 136219820Sjeff osm_physp_get_lmc(p_node_physp) : 0; 137219820Sjeff } else { 138219820Sjeff lmc = osm_physp_get_lmc(p_physp); 139219820Sjeff base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_physp)); 140219820Sjeff } 141219820Sjeff max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1); 142219820Sjeff 143219820Sjeff if (p_ctxt->comp_mask & IB_PIR_COMPMASK_LID) { 144219820Sjeff match_lid_ho = cl_ntoh16(p_ctxt->p_rcvd_rec->lid); 145219820Sjeff 146219820Sjeff /* 147219820Sjeff We validate that the lid belongs to this node. 148219820Sjeff */ 149219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 150219820Sjeff "Comparing LID: %u <= %u <= %u\n", 151219820Sjeff base_lid_ho, match_lid_ho, max_lid_ho); 152219820Sjeff 153219820Sjeff if (match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho) 154219820Sjeff goto Exit; 155219820Sjeff } 156219820Sjeff 157219820Sjeff __osm_pir_rcv_new_pir(sa, p_physp, p_ctxt->p_list, 158219820Sjeff cl_hton16(base_lid_ho)); 159219820Sjeff 160219820SjeffExit: 161219820Sjeff OSM_LOG_EXIT(sa->p_log); 162219820Sjeff} 163219820Sjeff 164219820Sjeff/********************************************************************** 165219820Sjeff **********************************************************************/ 166219820Sjeffstatic void 167219820Sjeff__osm_sa_pir_check_physp(IN osm_sa_t * sa, 168219820Sjeff IN const osm_physp_t * const p_physp, 169219820Sjeff osm_pir_search_ctxt_t * const p_ctxt) 170219820Sjeff{ 171219820Sjeff const ib_portinfo_record_t *p_rcvd_rec; 172219820Sjeff ib_net64_t comp_mask; 173219820Sjeff const ib_port_info_t *p_comp_pi; 174219820Sjeff const ib_port_info_t *p_pi; 175219820Sjeff 176219820Sjeff OSM_LOG_ENTER(sa->p_log); 177219820Sjeff 178219820Sjeff p_rcvd_rec = p_ctxt->p_rcvd_rec; 179219820Sjeff comp_mask = p_ctxt->comp_mask; 180219820Sjeff p_comp_pi = &p_rcvd_rec->port_info; 181219820Sjeff p_pi = &p_physp->port_info; 182219820Sjeff 183219820Sjeff osm_dump_port_info(sa->p_log, 184219820Sjeff osm_node_get_node_guid(p_physp->p_node), 185219820Sjeff p_physp->port_guid, 186219820Sjeff p_physp->port_num, 187219820Sjeff &p_physp->port_info, OSM_LOG_DEBUG); 188219820Sjeff 189219820Sjeff /* We have to re-check the base_lid, since if the given 190219820Sjeff base_lid in p_pi is zero - we are comparing on all ports. */ 191219820Sjeff if (comp_mask & IB_PIR_COMPMASK_BASELID) { 192219820Sjeff if (p_comp_pi->base_lid != p_pi->base_lid) 193219820Sjeff goto Exit; 194219820Sjeff } 195219820Sjeff if (comp_mask & IB_PIR_COMPMASK_MKEY) { 196219820Sjeff if (p_comp_pi->m_key != p_pi->m_key) 197219820Sjeff goto Exit; 198219820Sjeff } 199219820Sjeff if (comp_mask & IB_PIR_COMPMASK_GIDPRE) { 200219820Sjeff if (p_comp_pi->subnet_prefix != p_pi->subnet_prefix) 201219820Sjeff goto Exit; 202219820Sjeff } 203219820Sjeff if (comp_mask & IB_PIR_COMPMASK_SMLID) { 204219820Sjeff if (p_comp_pi->master_sm_base_lid != p_pi->master_sm_base_lid) 205219820Sjeff goto Exit; 206219820Sjeff } 207219820Sjeff 208219820Sjeff /* IBTA 1.2 errata provides support for bitwise compare if the bit 31 209219820Sjeff of the attribute modifier of the Get/GetTable is set */ 210219820Sjeff if (comp_mask & IB_PIR_COMPMASK_CAPMASK) { 211219820Sjeff if (p_ctxt->is_enhanced_comp_mask) { 212219820Sjeff if (((p_comp_pi->capability_mask & p_pi-> 213219820Sjeff capability_mask) != p_comp_pi->capability_mask)) 214219820Sjeff goto Exit; 215219820Sjeff } else { 216219820Sjeff if (p_comp_pi->capability_mask != p_pi->capability_mask) 217219820Sjeff goto Exit; 218219820Sjeff } 219219820Sjeff } 220219820Sjeff 221219820Sjeff if (comp_mask & IB_PIR_COMPMASK_DIAGCODE) { 222219820Sjeff if (p_comp_pi->diag_code != p_pi->diag_code) 223219820Sjeff goto Exit; 224219820Sjeff } 225219820Sjeff if (comp_mask & IB_PIR_COMPMASK_MKEYLEASEPRD) { 226219820Sjeff if (p_comp_pi->m_key_lease_period != p_pi->m_key_lease_period) 227219820Sjeff goto Exit; 228219820Sjeff } 229219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LOCALPORTNUM) { 230219820Sjeff if (p_comp_pi->local_port_num != p_pi->local_port_num) 231219820Sjeff goto Exit; 232219820Sjeff } 233219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LNKWIDTHSUPPORT) { 234219820Sjeff if (p_comp_pi->link_width_supported != 235219820Sjeff p_pi->link_width_supported) 236219820Sjeff goto Exit; 237219820Sjeff } 238219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LNKWIDTHACTIVE) { 239219820Sjeff if (p_comp_pi->link_width_active != p_pi->link_width_active) 240219820Sjeff goto Exit; 241219820Sjeff } 242219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LINKWIDTHENABLED) { 243219820Sjeff if (p_comp_pi->link_width_enabled != p_pi->link_width_enabled) 244219820Sjeff goto Exit; 245219820Sjeff } 246219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LNKSPEEDSUPPORT) { 247219820Sjeff if (ib_port_info_get_link_speed_sup(p_comp_pi) != 248219820Sjeff ib_port_info_get_link_speed_sup(p_pi)) 249219820Sjeff goto Exit; 250219820Sjeff } 251219820Sjeff if (comp_mask & IB_PIR_COMPMASK_PORTSTATE) { 252219820Sjeff if (ib_port_info_get_port_state(p_comp_pi) != 253219820Sjeff ib_port_info_get_port_state(p_pi)) 254219820Sjeff goto Exit; 255219820Sjeff } 256219820Sjeff if (comp_mask & IB_PIR_COMPMASK_PORTPHYSTATE) { 257219820Sjeff if (ib_port_info_get_port_phys_state(p_comp_pi) != 258219820Sjeff ib_port_info_get_port_phys_state(p_pi)) 259219820Sjeff goto Exit; 260219820Sjeff } 261219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LINKDWNDFLTSTATE) { 262219820Sjeff if (ib_port_info_get_link_down_def_state(p_comp_pi) != 263219820Sjeff ib_port_info_get_link_down_def_state(p_pi)) 264219820Sjeff goto Exit; 265219820Sjeff } 266219820Sjeff if (comp_mask & IB_PIR_COMPMASK_MKEYPROTBITS) { 267219820Sjeff if (ib_port_info_get_mpb(p_comp_pi) != 268219820Sjeff ib_port_info_get_mpb(p_pi)) 269219820Sjeff goto Exit; 270219820Sjeff } 271219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LMC) { 272219820Sjeff if (ib_port_info_get_lmc(p_comp_pi) != 273219820Sjeff ib_port_info_get_lmc(p_pi)) 274219820Sjeff goto Exit; 275219820Sjeff } 276219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LINKSPEEDACTIVE) { 277219820Sjeff if (ib_port_info_get_link_speed_active(p_comp_pi) != 278219820Sjeff ib_port_info_get_link_speed_active(p_pi)) 279219820Sjeff goto Exit; 280219820Sjeff } 281219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LINKSPEEDENABLE) { 282219820Sjeff if (ib_port_info_get_link_speed_enabled(p_comp_pi) != 283219820Sjeff ib_port_info_get_link_speed_enabled(p_pi)) 284219820Sjeff goto Exit; 285219820Sjeff } 286219820Sjeff if (comp_mask & IB_PIR_COMPMASK_NEIGHBORMTU) { 287219820Sjeff if (ib_port_info_get_neighbor_mtu(p_comp_pi) != 288219820Sjeff ib_port_info_get_neighbor_mtu(p_pi)) 289219820Sjeff goto Exit; 290219820Sjeff } 291219820Sjeff if (comp_mask & IB_PIR_COMPMASK_MASTERSMSL) { 292219820Sjeff if (ib_port_info_get_master_smsl(p_comp_pi) != 293219820Sjeff ib_port_info_get_master_smsl(p_pi)) 294219820Sjeff goto Exit; 295219820Sjeff } 296219820Sjeff if (comp_mask & IB_PIR_COMPMASK_VLCAP) { 297219820Sjeff if (ib_port_info_get_vl_cap(p_comp_pi) != 298219820Sjeff ib_port_info_get_vl_cap(p_pi)) 299219820Sjeff goto Exit; 300219820Sjeff } 301219820Sjeff if (comp_mask & IB_PIR_COMPMASK_INITTYPE) { 302219820Sjeff if (ib_port_info_get_init_type(p_comp_pi) != 303219820Sjeff ib_port_info_get_init_type(p_pi)) 304219820Sjeff goto Exit; 305219820Sjeff } 306219820Sjeff if (comp_mask & IB_PIR_COMPMASK_VLHIGHLIMIT) { 307219820Sjeff if (p_comp_pi->vl_high_limit != p_pi->vl_high_limit) 308219820Sjeff goto Exit; 309219820Sjeff } 310219820Sjeff if (comp_mask & IB_PIR_COMPMASK_VLARBHIGHCAP) { 311219820Sjeff if (p_comp_pi->vl_arb_high_cap != p_pi->vl_arb_high_cap) 312219820Sjeff goto Exit; 313219820Sjeff } 314219820Sjeff if (comp_mask & IB_PIR_COMPMASK_VLARBLOWCAP) { 315219820Sjeff if (p_comp_pi->vl_arb_low_cap != p_pi->vl_arb_low_cap) 316219820Sjeff goto Exit; 317219820Sjeff } 318219820Sjeff if (comp_mask & IB_PIR_COMPMASK_MTUCAP) { 319219820Sjeff if (ib_port_info_get_mtu_cap(p_comp_pi) != 320219820Sjeff ib_port_info_get_mtu_cap(p_pi)) 321219820Sjeff goto Exit; 322219820Sjeff } 323219820Sjeff if (comp_mask & IB_PIR_COMPMASK_VLSTALLCNT) { 324219820Sjeff if (ib_port_info_get_vl_stall_count(p_comp_pi) != 325219820Sjeff ib_port_info_get_vl_stall_count(p_pi)) 326219820Sjeff goto Exit; 327219820Sjeff } 328219820Sjeff if (comp_mask & IB_PIR_COMPMASK_HOQLIFE) { 329219820Sjeff if ((p_comp_pi->vl_stall_life & 0x1F) != 330219820Sjeff (p_pi->vl_stall_life & 0x1F)) 331219820Sjeff goto Exit; 332219820Sjeff } 333219820Sjeff if (comp_mask & IB_PIR_COMPMASK_OPVLS) { 334219820Sjeff if ((p_comp_pi->vl_enforce & 0xF0) != (p_pi->vl_enforce & 0xF0)) 335219820Sjeff goto Exit; 336219820Sjeff } 337219820Sjeff if (comp_mask & IB_PIR_COMPMASK_PARENFIN) { 338219820Sjeff if ((p_comp_pi->vl_enforce & 0x08) != (p_pi->vl_enforce & 0x08)) 339219820Sjeff goto Exit; 340219820Sjeff } 341219820Sjeff if (comp_mask & IB_PIR_COMPMASK_PARENFOUT) { 342219820Sjeff if ((p_comp_pi->vl_enforce & 0x04) != (p_pi->vl_enforce & 0x04)) 343219820Sjeff goto Exit; 344219820Sjeff } 345219820Sjeff if (comp_mask & IB_PIR_COMPMASK_FILTERRAWIN) { 346219820Sjeff if ((p_comp_pi->vl_enforce & 0x02) != (p_pi->vl_enforce & 0x02)) 347219820Sjeff goto Exit; 348219820Sjeff } 349219820Sjeff if (comp_mask & IB_PIR_COMPMASK_FILTERRAWOUT) { 350219820Sjeff if ((p_comp_pi->vl_enforce & 0x01) != (p_pi->vl_enforce & 0x01)) 351219820Sjeff goto Exit; 352219820Sjeff } 353219820Sjeff if (comp_mask & IB_PIR_COMPMASK_MKEYVIO) { 354219820Sjeff if (p_comp_pi->m_key_violations != p_pi->m_key_violations) 355219820Sjeff goto Exit; 356219820Sjeff } 357219820Sjeff if (comp_mask & IB_PIR_COMPMASK_PKEYVIO) { 358219820Sjeff if (p_comp_pi->p_key_violations != p_pi->p_key_violations) 359219820Sjeff goto Exit; 360219820Sjeff } 361219820Sjeff if (comp_mask & IB_PIR_COMPMASK_QKEYVIO) { 362219820Sjeff if (p_comp_pi->q_key_violations != p_pi->q_key_violations) 363219820Sjeff goto Exit; 364219820Sjeff } 365219820Sjeff if (comp_mask & IB_PIR_COMPMASK_GUIDCAP) { 366219820Sjeff if (p_comp_pi->guid_cap != p_pi->guid_cap) 367219820Sjeff goto Exit; 368219820Sjeff } 369219820Sjeff if (comp_mask & IB_PIR_COMPMASK_SUBNTO) { 370219820Sjeff if (ib_port_info_get_timeout(p_comp_pi) != 371219820Sjeff ib_port_info_get_timeout(p_pi)) 372219820Sjeff goto Exit; 373219820Sjeff } 374219820Sjeff if (comp_mask & IB_PIR_COMPMASK_RESPTIME) { 375219820Sjeff if ((p_comp_pi->resp_time_value & 0x1F) != 376219820Sjeff (p_pi->resp_time_value & 0x1F)) 377219820Sjeff goto Exit; 378219820Sjeff } 379219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LOCALPHYERR) { 380219820Sjeff if (ib_port_info_get_local_phy_err_thd(p_comp_pi) != 381219820Sjeff ib_port_info_get_local_phy_err_thd(p_pi)) 382219820Sjeff goto Exit; 383219820Sjeff } 384219820Sjeff if (comp_mask & IB_PIR_COMPMASK_OVERRUNERR) { 385219820Sjeff if (ib_port_info_get_overrun_err_thd(p_comp_pi) != 386219820Sjeff ib_port_info_get_overrun_err_thd(p_pi)) 387219820Sjeff goto Exit; 388219820Sjeff } 389219820Sjeff 390219820Sjeff __osm_sa_pir_create(sa, p_physp, p_ctxt); 391219820Sjeff 392219820SjeffExit: 393219820Sjeff OSM_LOG_EXIT(sa->p_log); 394219820Sjeff} 395219820Sjeff 396219820Sjeff/********************************************************************** 397219820Sjeff **********************************************************************/ 398219820Sjeffstatic void 399219820Sjeff__osm_sa_pir_by_comp_mask(IN osm_sa_t * sa, 400219820Sjeff IN osm_node_t * const p_node, 401219820Sjeff osm_pir_search_ctxt_t * const p_ctxt) 402219820Sjeff{ 403219820Sjeff const ib_portinfo_record_t *p_rcvd_rec; 404219820Sjeff ib_net64_t comp_mask; 405219820Sjeff const osm_physp_t *p_physp; 406219820Sjeff uint8_t port_num; 407219820Sjeff uint8_t num_ports; 408219820Sjeff const osm_physp_t *p_req_physp; 409219820Sjeff 410219820Sjeff OSM_LOG_ENTER(sa->p_log); 411219820Sjeff 412219820Sjeff p_rcvd_rec = p_ctxt->p_rcvd_rec; 413219820Sjeff comp_mask = p_ctxt->comp_mask; 414219820Sjeff p_req_physp = p_ctxt->p_req_physp; 415219820Sjeff 416219820Sjeff num_ports = osm_node_get_num_physp(p_node); 417219820Sjeff 418219820Sjeff if (comp_mask & IB_PIR_COMPMASK_PORTNUM) { 419219820Sjeff if (p_rcvd_rec->port_num < num_ports) { 420219820Sjeff p_physp = 421219820Sjeff osm_node_get_physp_ptr(p_node, 422219820Sjeff p_rcvd_rec->port_num); 423219820Sjeff /* Check that the p_physp is valid, and that the 424219820Sjeff p_physp and the p_req_physp share a pkey. */ 425219820Sjeff if (p_physp && 426219820Sjeff osm_physp_share_pkey(sa->p_log, p_req_physp, 427219820Sjeff p_physp)) 428219820Sjeff __osm_sa_pir_check_physp(sa, p_physp, 429219820Sjeff p_ctxt); 430219820Sjeff } 431219820Sjeff } else { 432219820Sjeff for (port_num = 0; port_num < num_ports; port_num++) { 433219820Sjeff p_physp = 434219820Sjeff osm_node_get_physp_ptr(p_node, port_num); 435219820Sjeff if (!p_physp) 436219820Sjeff continue; 437219820Sjeff 438219820Sjeff /* if the requester and the p_physp don't share a pkey - 439219820Sjeff continue */ 440219820Sjeff if (!osm_physp_share_pkey 441219820Sjeff (sa->p_log, p_req_physp, p_physp)) 442219820Sjeff continue; 443219820Sjeff 444219820Sjeff __osm_sa_pir_check_physp(sa, p_physp, p_ctxt); 445219820Sjeff } 446219820Sjeff } 447219820Sjeff 448219820Sjeff OSM_LOG_EXIT(sa->p_log); 449219820Sjeff} 450219820Sjeff 451219820Sjeff/********************************************************************** 452219820Sjeff **********************************************************************/ 453219820Sjeffstatic void 454219820Sjeff__osm_sa_pir_by_comp_mask_cb(IN cl_map_item_t * const p_map_item, 455219820Sjeff IN void *context) 456219820Sjeff{ 457219820Sjeff osm_node_t *const p_node = (osm_node_t *) p_map_item; 458219820Sjeff osm_pir_search_ctxt_t *const p_ctxt = (osm_pir_search_ctxt_t *) context; 459219820Sjeff 460219820Sjeff __osm_sa_pir_by_comp_mask(p_ctxt->sa, p_node, p_ctxt); 461219820Sjeff} 462219820Sjeff 463219820Sjeff/********************************************************************** 464219820Sjeff **********************************************************************/ 465219820Sjeffvoid osm_pir_rcv_process(IN void *ctx, IN void *data) 466219820Sjeff{ 467219820Sjeff osm_sa_t *sa = ctx; 468219820Sjeff osm_madw_t *p_madw = data; 469219820Sjeff const ib_sa_mad_t *p_rcvd_mad; 470219820Sjeff const ib_portinfo_record_t *p_rcvd_rec; 471219820Sjeff const cl_ptr_vector_t *p_tbl; 472219820Sjeff const osm_port_t *p_port = NULL; 473219820Sjeff const ib_port_info_t *p_pi; 474219820Sjeff cl_qlist_t rec_list; 475219820Sjeff osm_pir_search_ctxt_t context; 476219820Sjeff ib_api_status_t status = IB_SUCCESS; 477219820Sjeff ib_net64_t comp_mask; 478219820Sjeff osm_physp_t *p_req_physp; 479219820Sjeff 480219820Sjeff CL_ASSERT(sa); 481219820Sjeff 482219820Sjeff OSM_LOG_ENTER(sa->p_log); 483219820Sjeff 484219820Sjeff CL_ASSERT(p_madw); 485219820Sjeff 486219820Sjeff p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); 487219820Sjeff p_rcvd_rec = 488219820Sjeff (ib_portinfo_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); 489219820Sjeff comp_mask = p_rcvd_mad->comp_mask; 490219820Sjeff 491219820Sjeff CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD); 492219820Sjeff 493219820Sjeff /* we only support SubnAdmGet and SubnAdmGetTable methods */ 494219820Sjeff if (p_rcvd_mad->method != IB_MAD_METHOD_GET && 495219820Sjeff p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { 496219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2105: " 497219820Sjeff "Unsupported Method (%s)\n", 498219820Sjeff ib_get_sa_method_str(p_rcvd_mad->method)); 499219820Sjeff osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 500219820Sjeff goto Exit; 501219820Sjeff } 502219820Sjeff 503219820Sjeff /* update the requester physical port. */ 504219820Sjeff p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 505219820Sjeff osm_madw_get_mad_addr_ptr 506219820Sjeff (p_madw)); 507219820Sjeff if (p_req_physp == NULL) { 508219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2104: " 509219820Sjeff "Cannot find requester physical port\n"); 510219820Sjeff goto Exit; 511219820Sjeff } 512219820Sjeff 513219820Sjeff if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 514219820Sjeff osm_dump_portinfo_record(sa->p_log, p_rcvd_rec, OSM_LOG_DEBUG); 515219820Sjeff 516219820Sjeff p_tbl = &sa->p_subn->port_lid_tbl; 517219820Sjeff p_pi = &p_rcvd_rec->port_info; 518219820Sjeff 519219820Sjeff cl_qlist_init(&rec_list); 520219820Sjeff 521219820Sjeff context.p_rcvd_rec = p_rcvd_rec; 522219820Sjeff context.p_list = &rec_list; 523219820Sjeff context.comp_mask = p_rcvd_mad->comp_mask; 524219820Sjeff context.sa = sa; 525219820Sjeff context.p_req_physp = p_req_physp; 526219820Sjeff context.is_enhanced_comp_mask = 527219820Sjeff cl_ntoh32(p_rcvd_mad->attr_mod) & (1 << 31); 528219820Sjeff 529219820Sjeff cl_plock_acquire(sa->p_lock); 530219820Sjeff 531219820Sjeff CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000); 532219820Sjeff 533219820Sjeff /* 534219820Sjeff If the user specified a LID, it obviously narrows our 535219820Sjeff work load, since we don't have to search every port 536219820Sjeff */ 537219820Sjeff if (comp_mask & IB_PIR_COMPMASK_LID) { 538219820Sjeff status = 539219820Sjeff osm_get_port_by_base_lid(sa->p_subn, p_rcvd_rec->lid, 540219820Sjeff &p_port); 541219820Sjeff if ((status != IB_SUCCESS) || (p_port == NULL)) { 542219820Sjeff status = IB_NOT_FOUND; 543219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2109: " 544219820Sjeff "No port found with LID %u\n", 545219820Sjeff cl_ntoh16(p_rcvd_rec->lid)); 546219820Sjeff } 547219820Sjeff } else if (comp_mask & IB_PIR_COMPMASK_BASELID) { 548219820Sjeff if ((uint16_t) cl_ptr_vector_get_size(p_tbl) > 549219820Sjeff cl_ntoh16(p_pi->base_lid)) 550219820Sjeff p_port = cl_ptr_vector_get(p_tbl, 551219820Sjeff cl_ntoh16(p_pi->base_lid)); 552219820Sjeff else { 553219820Sjeff status = IB_NOT_FOUND; 554219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2103: " 555219820Sjeff "Given LID (%u) is out of range:%u\n", 556219820Sjeff cl_ntoh16(p_pi->base_lid), 557219820Sjeff cl_ptr_vector_get_size(p_tbl)); 558219820Sjeff } 559219820Sjeff } 560219820Sjeff 561219820Sjeff if (status == IB_SUCCESS) { 562219820Sjeff if (p_port) 563219820Sjeff __osm_sa_pir_by_comp_mask(sa, p_port->p_node, 564219820Sjeff &context); 565219820Sjeff else 566219820Sjeff cl_qmap_apply_func(&sa->p_subn->node_guid_tbl, 567219820Sjeff __osm_sa_pir_by_comp_mask_cb, 568219820Sjeff &context); 569219820Sjeff } 570219820Sjeff 571219820Sjeff cl_plock_release(sa->p_lock); 572219820Sjeff 573219820Sjeff /* 574219820Sjeff p922 - The M_Key returned shall be zero, except in the case of a 575219820Sjeff trusted request. 576219820Sjeff Note: In the mad controller we check that the SM_Key received on 577219820Sjeff the mad is valid. Meaning - is either zero or equal to the local 578219820Sjeff sm_key. 579219820Sjeff */ 580219820Sjeff if (!p_rcvd_mad->sm_key) { 581219820Sjeff osm_pir_item_t *item; 582219820Sjeff for (item = (osm_pir_item_t *) cl_qlist_head(&rec_list); 583219820Sjeff item != (osm_pir_item_t *) cl_qlist_end(&rec_list); 584219820Sjeff item = (osm_pir_item_t *)cl_qlist_next(&item->list_item)) 585219820Sjeff item->rec.port_info.m_key = 0; 586219820Sjeff } 587219820Sjeff 588219820Sjeff osm_sa_respond(sa, p_madw, sizeof(ib_portinfo_record_t), &rec_list); 589219820Sjeff 590219820SjeffExit: 591219820Sjeff OSM_LOG_EXIT(sa->p_log); 592219820Sjeff} 593