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_nr_rcv_t. 39219820Sjeff * This object represents the NodeInfo 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_debug.h> 50219820Sjeff#include <complib/cl_qlist.h> 51219820Sjeff#include <vendor/osm_vendor_api.h> 52219820Sjeff#include <opensm/osm_node.h> 53219820Sjeff#include <opensm/osm_helper.h> 54219820Sjeff#include <opensm/osm_pkey.h> 55219820Sjeff#include <opensm/osm_sa.h> 56219820Sjeff 57219820Sjefftypedef struct osm_nr_item { 58219820Sjeff cl_list_item_t list_item; 59219820Sjeff ib_node_record_t rec; 60219820Sjeff} osm_nr_item_t; 61219820Sjeff 62219820Sjefftypedef struct osm_nr_search_ctxt { 63219820Sjeff const ib_node_record_t *p_rcvd_rec; 64219820Sjeff ib_net64_t comp_mask; 65219820Sjeff cl_qlist_t *p_list; 66219820Sjeff osm_sa_t *sa; 67219820Sjeff const osm_physp_t *p_req_physp; 68219820Sjeff} osm_nr_search_ctxt_t; 69219820Sjeff 70219820Sjeff/********************************************************************** 71219820Sjeff **********************************************************************/ 72219820Sjeffstatic ib_api_status_t 73219820Sjeff__osm_nr_rcv_new_nr(IN osm_sa_t * sa, 74219820Sjeff IN const osm_node_t * const p_node, 75219820Sjeff IN cl_qlist_t * const p_list, 76219820Sjeff IN ib_net64_t const port_guid, IN ib_net16_t const lid) 77219820Sjeff{ 78219820Sjeff osm_nr_item_t *p_rec_item; 79219820Sjeff ib_api_status_t status = IB_SUCCESS; 80219820Sjeff 81219820Sjeff OSM_LOG_ENTER(sa->p_log); 82219820Sjeff 83219820Sjeff p_rec_item = malloc(sizeof(*p_rec_item)); 84219820Sjeff if (p_rec_item == NULL) { 85219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D02: " 86219820Sjeff "rec_item alloc failed\n"); 87219820Sjeff status = IB_INSUFFICIENT_RESOURCES; 88219820Sjeff goto Exit; 89219820Sjeff } 90219820Sjeff 91219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 92219820Sjeff "New NodeRecord: node 0x%016" PRIx64 93219820Sjeff "\n\t\t\t\tport 0x%016" PRIx64 ", lid %u\n", 94219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 95219820Sjeff cl_ntoh64(port_guid), cl_ntoh16(lid)); 96219820Sjeff 97219820Sjeff memset(p_rec_item, 0, sizeof(*p_rec_item)); 98219820Sjeff 99219820Sjeff p_rec_item->rec.lid = lid; 100219820Sjeff 101219820Sjeff p_rec_item->rec.node_info = p_node->node_info; 102219820Sjeff p_rec_item->rec.node_info.port_guid = port_guid; 103219820Sjeff memcpy(&(p_rec_item->rec.node_desc), &(p_node->node_desc), 104219820Sjeff IB_NODE_DESCRIPTION_SIZE); 105219820Sjeff cl_qlist_insert_tail(p_list, &p_rec_item->list_item); 106219820Sjeff 107219820SjeffExit: 108219820Sjeff OSM_LOG_EXIT(sa->p_log); 109219820Sjeff return (status); 110219820Sjeff} 111219820Sjeff 112219820Sjeff/********************************************************************** 113219820Sjeff **********************************************************************/ 114219820Sjeffstatic void 115219820Sjeff__osm_nr_rcv_create_nr(IN osm_sa_t * sa, 116219820Sjeff IN osm_node_t * const p_node, 117219820Sjeff IN cl_qlist_t * const p_list, 118219820Sjeff IN ib_net64_t const match_port_guid, 119219820Sjeff IN ib_net16_t const match_lid, 120219820Sjeff IN const osm_physp_t * const p_req_physp) 121219820Sjeff{ 122219820Sjeff const osm_physp_t *p_physp; 123219820Sjeff uint8_t port_num; 124219820Sjeff uint8_t num_ports; 125219820Sjeff uint16_t match_lid_ho; 126219820Sjeff ib_net16_t base_lid; 127219820Sjeff ib_net16_t base_lid_ho; 128219820Sjeff ib_net16_t max_lid_ho; 129219820Sjeff uint8_t lmc; 130219820Sjeff ib_net64_t port_guid; 131219820Sjeff 132219820Sjeff OSM_LOG_ENTER(sa->p_log); 133219820Sjeff 134219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 135219820Sjeff "Looking for NodeRecord with LID: %u GUID:0x%016" 136219820Sjeff PRIx64 "\n", cl_ntoh16(match_lid), 137219820Sjeff cl_ntoh64(match_port_guid)); 138219820Sjeff 139219820Sjeff /* 140219820Sjeff For switches, do not return the NodeInfo record 141219820Sjeff for each port on the switch, just for port 0. 142219820Sjeff */ 143219820Sjeff if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) 144219820Sjeff num_ports = 1; 145219820Sjeff else 146219820Sjeff num_ports = osm_node_get_num_physp(p_node); 147219820Sjeff 148219820Sjeff for (port_num = 0; port_num < num_ports; port_num++) { 149219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 150219820Sjeff if (!p_physp) 151219820Sjeff continue; 152219820Sjeff 153219820Sjeff /* Check to see if the found p_physp and the requester physp 154219820Sjeff share a pkey. If not - continue */ 155219820Sjeff if (!osm_physp_share_pkey(sa->p_log, p_physp, p_req_physp)) 156219820Sjeff continue; 157219820Sjeff 158219820Sjeff port_guid = osm_physp_get_port_guid(p_physp); 159219820Sjeff 160219820Sjeff if (match_port_guid && (port_guid != match_port_guid)) 161219820Sjeff continue; 162219820Sjeff 163219820Sjeff base_lid = osm_physp_get_base_lid(p_physp); 164219820Sjeff base_lid_ho = cl_ntoh16(base_lid); 165219820Sjeff lmc = osm_physp_get_lmc(p_physp); 166219820Sjeff max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1); 167219820Sjeff match_lid_ho = cl_ntoh16(match_lid); 168219820Sjeff 169219820Sjeff if (match_lid_ho) { 170219820Sjeff /* 171219820Sjeff We validate that the lid belongs to this node. 172219820Sjeff */ 173219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 174219820Sjeff "Comparing LID: %u <= %u <= %u\n", 175219820Sjeff base_lid_ho, match_lid_ho, max_lid_ho); 176219820Sjeff 177219820Sjeff if (match_lid_ho < base_lid_ho 178219820Sjeff || match_lid_ho > max_lid_ho) 179219820Sjeff continue; 180219820Sjeff } 181219820Sjeff 182219820Sjeff __osm_nr_rcv_new_nr(sa, p_node, p_list, port_guid, base_lid); 183219820Sjeff 184219820Sjeff } 185219820Sjeff 186219820Sjeff OSM_LOG_EXIT(sa->p_log); 187219820Sjeff} 188219820Sjeff 189219820Sjeff/********************************************************************** 190219820Sjeff **********************************************************************/ 191219820Sjeffstatic void 192219820Sjeff__osm_nr_rcv_by_comp_mask(IN cl_map_item_t * const p_map_item, IN void *context) 193219820Sjeff{ 194219820Sjeff const osm_nr_search_ctxt_t *const p_ctxt = 195219820Sjeff (osm_nr_search_ctxt_t *) context; 196219820Sjeff osm_node_t *const p_node = (osm_node_t *) p_map_item; 197219820Sjeff const ib_node_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; 198219820Sjeff const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; 199219820Sjeff osm_sa_t *sa = p_ctxt->sa; 200219820Sjeff ib_net64_t const comp_mask = p_ctxt->comp_mask; 201219820Sjeff ib_net64_t match_port_guid = 0; 202219820Sjeff ib_net16_t match_lid = 0; 203219820Sjeff 204219820Sjeff OSM_LOG_ENTER(p_ctxt->sa->p_log); 205219820Sjeff 206219820Sjeff osm_dump_node_info(p_ctxt->sa->p_log, 207219820Sjeff &p_node->node_info, OSM_LOG_VERBOSE); 208219820Sjeff 209219820Sjeff if (comp_mask & IB_NR_COMPMASK_LID) 210219820Sjeff match_lid = p_rcvd_rec->lid; 211219820Sjeff 212219820Sjeff if (comp_mask & IB_NR_COMPMASK_NODEGUID) { 213219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 214219820Sjeff "Looking for node 0x%016" PRIx64 215219820Sjeff ", found 0x%016" PRIx64 "\n", 216219820Sjeff cl_ntoh64(p_rcvd_rec->node_info.node_guid), 217219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node))); 218219820Sjeff 219219820Sjeff if ((p_node->node_info.node_guid != 220219820Sjeff p_rcvd_rec->node_info.node_guid)) 221219820Sjeff goto Exit; 222219820Sjeff } 223219820Sjeff if (comp_mask & IB_NR_COMPMASK_PORTGUID) { 224219820Sjeff match_port_guid = p_rcvd_rec->node_info.port_guid; 225219820Sjeff } 226219820Sjeff if (comp_mask & IB_NR_COMPMASK_SYSIMAGEGUID) { 227219820Sjeff if ((p_node->node_info.sys_guid != 228219820Sjeff p_rcvd_rec->node_info.sys_guid)) 229219820Sjeff goto Exit; 230219820Sjeff } 231219820Sjeff if (comp_mask & IB_NR_COMPMASK_BASEVERSION) { 232219820Sjeff if ((p_node->node_info.base_version != 233219820Sjeff p_rcvd_rec->node_info.base_version)) 234219820Sjeff goto Exit; 235219820Sjeff } 236219820Sjeff if (comp_mask & IB_NR_COMPMASK_CLASSVERSION) { 237219820Sjeff if ((p_node->node_info.class_version != 238219820Sjeff p_rcvd_rec->node_info.class_version)) 239219820Sjeff goto Exit; 240219820Sjeff } 241219820Sjeff if (comp_mask & IB_NR_COMPMASK_NODETYPE) { 242219820Sjeff if ((p_node->node_info.node_type != 243219820Sjeff p_rcvd_rec->node_info.node_type)) 244219820Sjeff goto Exit; 245219820Sjeff } 246219820Sjeff if (comp_mask & IB_NR_COMPMASK_NUMPORTS) { 247219820Sjeff if ((p_node->node_info.num_ports != 248219820Sjeff p_rcvd_rec->node_info.num_ports)) 249219820Sjeff goto Exit; 250219820Sjeff } 251219820Sjeff if (comp_mask & IB_NR_COMPMASK_PARTCAP) { 252219820Sjeff if ((p_node->node_info.partition_cap != 253219820Sjeff p_rcvd_rec->node_info.partition_cap)) 254219820Sjeff goto Exit; 255219820Sjeff } 256219820Sjeff if (comp_mask & IB_NR_COMPMASK_DEVID) { 257219820Sjeff if ((p_node->node_info.device_id != 258219820Sjeff p_rcvd_rec->node_info.device_id)) 259219820Sjeff goto Exit; 260219820Sjeff } 261219820Sjeff if (comp_mask & IB_NR_COMPMASK_REV) { 262219820Sjeff if ((p_node->node_info.revision != 263219820Sjeff p_rcvd_rec->node_info.revision)) 264219820Sjeff goto Exit; 265219820Sjeff } 266219820Sjeff if (comp_mask & IB_NR_COMPMASK_PORTNUM) { 267219820Sjeff if (ib_node_info_get_local_port_num(&p_node->node_info) != 268219820Sjeff ib_node_info_get_local_port_num(&p_rcvd_rec->node_info)) 269219820Sjeff goto Exit; 270219820Sjeff } 271219820Sjeff if (comp_mask & IB_NR_COMPMASK_VENDID) { 272219820Sjeff if (ib_node_info_get_vendor_id(&p_node->node_info) != 273219820Sjeff ib_node_info_get_vendor_id(&p_rcvd_rec->node_info)) 274219820Sjeff goto Exit; 275219820Sjeff } 276219820Sjeff if (comp_mask & IB_NR_COMPMASK_NODEDESC) { 277219820Sjeff if (strncmp((char *)&p_node->node_desc, 278219820Sjeff (char *)&p_rcvd_rec->node_desc, 279219820Sjeff sizeof(ib_node_desc_t))) 280219820Sjeff goto Exit; 281219820Sjeff } 282219820Sjeff 283219820Sjeff __osm_nr_rcv_create_nr(sa, p_node, p_ctxt->p_list, 284219820Sjeff match_port_guid, match_lid, p_req_physp); 285219820Sjeff 286219820SjeffExit: 287219820Sjeff OSM_LOG_EXIT(p_ctxt->sa->p_log); 288219820Sjeff} 289219820Sjeff 290219820Sjeff/********************************************************************** 291219820Sjeff **********************************************************************/ 292219820Sjeffvoid osm_nr_rcv_process(IN void *ctx, IN void *data) 293219820Sjeff{ 294219820Sjeff osm_sa_t *sa = ctx; 295219820Sjeff osm_madw_t *p_madw = data; 296219820Sjeff const ib_sa_mad_t *p_rcvd_mad; 297219820Sjeff const ib_node_record_t *p_rcvd_rec; 298219820Sjeff cl_qlist_t rec_list; 299219820Sjeff osm_nr_search_ctxt_t context; 300219820Sjeff osm_physp_t *p_req_physp; 301219820Sjeff 302219820Sjeff CL_ASSERT(sa); 303219820Sjeff 304219820Sjeff OSM_LOG_ENTER(sa->p_log); 305219820Sjeff 306219820Sjeff CL_ASSERT(p_madw); 307219820Sjeff 308219820Sjeff p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); 309219820Sjeff p_rcvd_rec = (ib_node_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); 310219820Sjeff 311219820Sjeff CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_NODE_RECORD); 312219820Sjeff 313219820Sjeff /* we only support SubnAdmGet and SubnAdmGetTable methods */ 314219820Sjeff if (p_rcvd_mad->method != IB_MAD_METHOD_GET && 315219820Sjeff p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { 316219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D05: " 317219820Sjeff "Unsupported Method (%s)\n", 318219820Sjeff ib_get_sa_method_str(p_rcvd_mad->method)); 319219820Sjeff osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 320219820Sjeff goto Exit; 321219820Sjeff } 322219820Sjeff 323219820Sjeff /* update the requester physical port. */ 324219820Sjeff p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 325219820Sjeff osm_madw_get_mad_addr_ptr 326219820Sjeff (p_madw)); 327219820Sjeff if (p_req_physp == NULL) { 328219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D04: " 329219820Sjeff "Cannot find requester physical port\n"); 330219820Sjeff goto Exit; 331219820Sjeff } 332219820Sjeff 333219820Sjeff if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 334219820Sjeff osm_dump_node_record(sa->p_log, p_rcvd_rec, OSM_LOG_DEBUG); 335219820Sjeff 336219820Sjeff cl_qlist_init(&rec_list); 337219820Sjeff 338219820Sjeff context.p_rcvd_rec = p_rcvd_rec; 339219820Sjeff context.p_list = &rec_list; 340219820Sjeff context.comp_mask = p_rcvd_mad->comp_mask; 341219820Sjeff context.sa = sa; 342219820Sjeff context.p_req_physp = p_req_physp; 343219820Sjeff 344219820Sjeff cl_plock_acquire(sa->p_lock); 345219820Sjeff 346219820Sjeff cl_qmap_apply_func(&sa->p_subn->node_guid_tbl, 347219820Sjeff __osm_nr_rcv_by_comp_mask, &context); 348219820Sjeff 349219820Sjeff cl_plock_release(sa->p_lock); 350219820Sjeff 351219820Sjeff osm_sa_respond(sa, p_madw, sizeof(ib_node_record_t), &rec_list); 352219820Sjeff 353219820SjeffExit: 354219820Sjeff OSM_LOG_EXIT(sa->p_log); 355219820Sjeff} 356