osm_sa_link_record.c revision 329564
1145516Sdarrenr/* 2145516Sdarrenr * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3145516Sdarrenr * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. 4255332Scy * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5145516Sdarrenr * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. 6145516Sdarrenr * 7145516Sdarrenr * This software is available to you under a choice of one of two 8145516Sdarrenr * licenses. You may choose to be licensed under the terms of the GNU 9145516Sdarrenr * General Public License (GPL) Version 2, available from the file 10145516Sdarrenr * COPYING in the main directory of this source tree, or the 11145516Sdarrenr * OpenIB.org BSD license below: 12145516Sdarrenr * 13145516Sdarrenr * Redistribution and use in source and binary forms, with or 14145516Sdarrenr * without modification, are permitted provided that the following 15145516Sdarrenr * conditions are met: 16145516Sdarrenr * 17145516Sdarrenr * - Redistributions of source code must retain the above 18145516Sdarrenr * copyright notice, this list of conditions and the following 19145516Sdarrenr * disclaimer. 20145516Sdarrenr * 21145516Sdarrenr * - Redistributions in binary form must reproduce the above 22145516Sdarrenr * copyright notice, this list of conditions and the following 23145516Sdarrenr * disclaimer in the documentation and/or other materials 24145516Sdarrenr * provided with the distribution. 25145516Sdarrenr * 26145516Sdarrenr * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27145516Sdarrenr * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28145516Sdarrenr * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29145516Sdarrenr * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30145516Sdarrenr * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31145516Sdarrenr * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32145516Sdarrenr * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33145516Sdarrenr * SOFTWARE. 34145516Sdarrenr * 35255332Scy */ 36255332Scy 37255332Scy/* 38255332Scy * Abstract: 39145516Sdarrenr * Implementation of osm_lr_rcv_t. 40145516Sdarrenr * This object represents the LinkRecord Receiver object. 41145516Sdarrenr * This object is part of the opensm family of objects. 42145516Sdarrenr */ 43145516Sdarrenr 44145516Sdarrenr#if HAVE_CONFIG_H 45145516Sdarrenr# include <config.h> 46145516Sdarrenr#endif /* HAVE_CONFIG_H */ 47145516Sdarrenr 48145516Sdarrenr#include <string.h> 49145516Sdarrenr#include <iba/ib_types.h> 50145516Sdarrenr#include <complib/cl_qmap.h> 51145516Sdarrenr#include <complib/cl_debug.h> 52145516Sdarrenr#include <opensm/osm_file_ids.h> 53145516Sdarrenr#define FILE_ID OSM_FILE_SA_LINK_RECORD_C 54145516Sdarrenr#include <vendor/osm_vendor_api.h> 55145516Sdarrenr#include <opensm/osm_node.h> 56145516Sdarrenr#include <opensm/osm_switch.h> 57145516Sdarrenr#include <opensm/osm_helper.h> 58145516Sdarrenr#include <opensm/osm_pkey.h> 59145516Sdarrenr#include <opensm/osm_sa.h> 60145516Sdarrenr 61145516Sdarrenr#define SA_LR_RESP_SIZE SA_ITEM_RESP_SIZE(link_rec) 62145516Sdarrenr 63145516Sdarrenrstatic void lr_rcv_build_physp_link(IN osm_sa_t * sa, IN ib_net16_t from_lid, 64145516Sdarrenr IN ib_net16_t to_lid, IN uint8_t from_port, 65145516Sdarrenr IN uint8_t to_port, IN cl_qlist_t * p_list) 66145516Sdarrenr{ 67145516Sdarrenr osm_sa_item_t *p_lr_item; 68145516Sdarrenr 69145516Sdarrenr p_lr_item = malloc(SA_LR_RESP_SIZE); 70145516Sdarrenr if (p_lr_item == NULL) { 71145516Sdarrenr OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1801: " 72145516Sdarrenr "Unable to acquire link record\n" 73145516Sdarrenr "\t\t\t\tFrom port %u\n" "\t\t\t\tTo port %u\n" 74145516Sdarrenr "\t\t\t\tFrom lid %u\n" "\t\t\t\tTo lid %u\n", 75145516Sdarrenr from_port, to_port, 76145516Sdarrenr cl_ntoh16(from_lid), cl_ntoh16(to_lid)); 77145516Sdarrenr return; 78145516Sdarrenr } 79145516Sdarrenr memset(p_lr_item, 0, SA_LR_RESP_SIZE); 80145516Sdarrenr 81145516Sdarrenr p_lr_item->resp.link_rec.from_port_num = from_port; 82145516Sdarrenr p_lr_item->resp.link_rec.to_port_num = to_port; 83145516Sdarrenr p_lr_item->resp.link_rec.to_lid = to_lid; 84145516Sdarrenr p_lr_item->resp.link_rec.from_lid = from_lid; 85145516Sdarrenr 86145516Sdarrenr cl_qlist_insert_tail(p_list, &p_lr_item->list_item); 87145516Sdarrenr} 88145516Sdarrenr 89145516Sdarrenrstatic ib_net16_t get_base_lid(IN const osm_physp_t * p_physp) 90145516Sdarrenr{ 91145516Sdarrenr if (p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) 92145516Sdarrenr p_physp = osm_node_get_physp_ptr(p_physp->p_node, 0); 93145516Sdarrenr return osm_physp_get_base_lid(p_physp); 94145516Sdarrenr} 95145516Sdarrenr 96145516Sdarrenrstatic void lr_rcv_get_physp_link(IN osm_sa_t * sa, 97145516Sdarrenr IN const ib_link_record_t * p_lr, 98145516Sdarrenr IN const osm_physp_t * p_src_physp, 99145516Sdarrenr IN const osm_physp_t * p_dest_physp, 100145516Sdarrenr IN const ib_net64_t comp_mask, 101255332Scy IN cl_qlist_t * p_list, 102145516Sdarrenr IN const osm_physp_t * p_req_physp) 103145516Sdarrenr{ 104145516Sdarrenr uint8_t src_port_num; 105145516Sdarrenr uint8_t dest_port_num; 106145516Sdarrenr ib_net16_t from_base_lid; 107255332Scy ib_net16_t to_base_lid; 108255332Scy ib_net16_t lmc_mask; 109255332Scy 110255332Scy OSM_LOG_ENTER(sa->p_log); 111255332Scy 112145516Sdarrenr /* 113255332Scy If only one end of the link is specified, determine 114145516Sdarrenr the other side. 115255332Scy */ 116255332Scy if (p_src_physp) { 117255332Scy if (p_dest_physp) { 118255332Scy /* 119255332Scy Ensure the two physp's are actually connected. 120255332Scy If not, bail out. 121255332Scy */ 122255332Scy if (osm_physp_get_remote(p_src_physp) != p_dest_physp) 123255332Scy goto Exit; 124255332Scy } else { 125255332Scy p_dest_physp = osm_physp_get_remote(p_src_physp); 126255332Scy if (p_dest_physp == NULL) 127255332Scy goto Exit; 128255332Scy } 129255332Scy } else { 130255332Scy if (p_dest_physp) { 131255332Scy p_src_physp = osm_physp_get_remote(p_dest_physp); 132255332Scy if (p_src_physp == NULL) 133255332Scy goto Exit; 134255332Scy } else 135255332Scy goto Exit; /* no physp's, so nothing to do */ 136255332Scy } 137255332Scy 138255332Scy /* Check that the p_src_physp, p_dest_physp and p_req_physp 139145516Sdarrenr all share a pkey (doesn't have to be the same p_key). */ 140255332Scy if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_dest_physp, 141255332Scy sa->p_subn->opt.allow_both_pkeys)) { 142255332Scy OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 143255332Scy "Source and Dest PhysPorts do not share PKey\n"); 144255332Scy goto Exit; 145255332Scy } 146145516Sdarrenr if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_req_physp, 147145516Sdarrenr sa->p_subn->opt.allow_both_pkeys)) { 148255332Scy OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 149255332Scy "Source and Requester PhysPorts do not share PKey\n"); 150255332Scy goto Exit; 151145516Sdarrenr } 152145516Sdarrenr if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_dest_physp, 153145516Sdarrenr sa->p_subn->opt.allow_both_pkeys)) { 154255332Scy OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 155255332Scy "Requester and Dest PhysPorts do not share PKey\n"); 156255332Scy goto Exit; 157255332Scy } 158255332Scy 159255332Scy src_port_num = osm_physp_get_port_num(p_src_physp); 160255332Scy dest_port_num = osm_physp_get_port_num(p_dest_physp); 161255332Scy 162255332Scy if (comp_mask & IB_LR_COMPMASK_FROM_PORT) 163255332Scy if (src_port_num != p_lr->from_port_num) 164255332Scy goto Exit; 165255332Scy 166255332Scy if (comp_mask & IB_LR_COMPMASK_TO_PORT) 167255332Scy if (dest_port_num != p_lr->to_port_num) 168255332Scy goto Exit; 169255332Scy 170255332Scy from_base_lid = get_base_lid(p_src_physp); 171255332Scy to_base_lid = get_base_lid(p_dest_physp); 172255332Scy 173255332Scy lmc_mask = ~((1 << sa->p_subn->opt.lmc) - 1); 174255332Scy lmc_mask = cl_hton16(lmc_mask); 175255332Scy 176255332Scy if (comp_mask & IB_LR_COMPMASK_FROM_LID) 177255332Scy if (from_base_lid != (p_lr->from_lid & lmc_mask)) 178145516Sdarrenr goto Exit; 179255332Scy 180145516Sdarrenr if (comp_mask & IB_LR_COMPMASK_TO_LID) 181145516Sdarrenr if (to_base_lid != (p_lr->to_lid & lmc_mask)) 182145516Sdarrenr goto Exit; 183145516Sdarrenr 184145516Sdarrenr OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Acquiring link record\n" 185145516Sdarrenr "\t\t\t\tsrc port 0x%" PRIx64 " (port %u)" 186255332Scy ", dest port 0x%" PRIx64 " (port %u)\n", 187255332Scy cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), src_port_num, 188255332Scy cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)), 189255332Scy dest_port_num); 190145516Sdarrenr 191255332Scy lr_rcv_build_physp_link(sa, from_base_lid, to_base_lid, src_port_num, 192255332Scy dest_port_num, p_list); 193255332Scy 194255332ScyExit: 195255332Scy OSM_LOG_EXIT(sa->p_log); 196255332Scy} 197255332Scy 198255332Scystatic void lr_rcv_get_port_links(IN osm_sa_t * sa, 199255332Scy IN const ib_link_record_t * p_lr, 200255332Scy IN const osm_port_t * p_src_port, 201255332Scy IN const osm_port_t * p_dest_port, 202255332Scy IN const ib_net64_t comp_mask, 203255332Scy IN cl_qlist_t * p_list, 204255332Scy IN const osm_physp_t * p_req_physp) 205255332Scy{ 206255332Scy const osm_physp_t *p_src_physp; 207255332Scy const osm_physp_t *p_dest_physp; 208255332Scy const cl_qmap_t *p_node_tbl; 209255332Scy osm_node_t *p_node; 210255332Scy uint8_t port_num; 211255332Scy uint8_t num_ports; 212255332Scy uint8_t dest_num_ports; 213255332Scy uint8_t dest_port_num; 214255332Scy 215255332Scy OSM_LOG_ENTER(sa->p_log); 216255332Scy 217255332Scy if (p_src_port) { 218255332Scy if (p_dest_port) { 219255332Scy /* 220255332Scy Build an LR for every link connected between both ports. 221255332Scy The inner function will discard physp combinations 222255332Scy that do not actually connect. Don't bother screening 223255332Scy for that here. 224255332Scy */ 225255332Scy num_ports = osm_node_get_num_physp(p_src_port->p_node); 226255332Scy dest_num_ports = 227255332Scy osm_node_get_num_physp(p_dest_port->p_node); 228255332Scy for (port_num = 1; port_num < num_ports; port_num++) { 229255332Scy p_src_physp = 230255332Scy osm_node_get_physp_ptr(p_src_port->p_node, 231145516Sdarrenr port_num); 232255332Scy for (dest_port_num = 1; 233145516Sdarrenr dest_port_num < dest_num_ports; 234255332Scy dest_port_num++) { 235255332Scy p_dest_physp = 236255332Scy osm_node_get_physp_ptr(p_dest_port-> 237255332Scy p_node, 238145516Sdarrenr dest_port_num); 239255332Scy /* both physical ports should be with data */ 240145516Sdarrenr if (p_src_physp && p_dest_physp) 241145516Sdarrenr lr_rcv_get_physp_link 242145516Sdarrenr (sa, p_lr, p_src_physp, 243145516Sdarrenr p_dest_physp, comp_mask, 244145516Sdarrenr p_list, p_req_physp); 245255332Scy } 246255332Scy } 247255332Scy } else { 248255332Scy /* 249255332Scy Build an LR for every link connected from the source port. 250255332Scy */ 251255332Scy if (comp_mask & IB_LR_COMPMASK_FROM_PORT) { 252255332Scy port_num = p_lr->from_port_num; 253255332Scy /* If the port number is out of the range of the p_src_port, then 254255332Scy this couldn't be a relevant record. */ 255255332Scy if (port_num < 256255332Scy p_src_port->p_node->physp_tbl_size) { 257255332Scy p_src_physp = 258255332Scy osm_node_get_physp_ptr(p_src_port-> 259255332Scy p_node, 260255332Scy port_num); 261255332Scy if (p_src_physp) 262255332Scy lr_rcv_get_physp_link 263255332Scy (sa, p_lr, p_src_physp, 264255332Scy NULL, comp_mask, p_list, 265255332Scy p_req_physp); 266255332Scy } 267255332Scy } else { 268255332Scy num_ports = 269255332Scy osm_node_get_num_physp(p_src_port->p_node); 270255332Scy for (port_num = 1; port_num < num_ports; 271255332Scy port_num++) { 272255332Scy p_src_physp = 273255332Scy osm_node_get_physp_ptr(p_src_port-> 274255332Scy p_node, 275255332Scy port_num); 276255332Scy if (p_src_physp) 277255332Scy lr_rcv_get_physp_link 278255332Scy (sa, p_lr, p_src_physp, 279255332Scy NULL, comp_mask, p_list, 280255332Scy p_req_physp); 281255332Scy } 282255332Scy } 283255332Scy } 284255332Scy } else { 285255332Scy if (p_dest_port) { 286255332Scy /* 287255332Scy Build an LR for every link connected to the dest port. 288255332Scy */ 289255332Scy if (comp_mask & IB_LR_COMPMASK_TO_PORT) { 290255332Scy port_num = p_lr->to_port_num; 291255332Scy /* If the port number is out of the range of the p_dest_port, then 292255332Scy this couldn't be a relevant record. */ 293255332Scy if (port_num < 294255332Scy p_dest_port->p_node->physp_tbl_size) { 295255332Scy p_dest_physp = 296255332Scy osm_node_get_physp_ptr(p_dest_port-> 297255332Scy p_node, 298255332Scy port_num); 299255332Scy if (p_dest_physp) 300255332Scy lr_rcv_get_physp_link 301255332Scy (sa, p_lr, NULL, 302255332Scy p_dest_physp, comp_mask, 303255332Scy p_list, p_req_physp); 304255332Scy } 305255332Scy } else { 306255332Scy num_ports = 307255332Scy osm_node_get_num_physp(p_dest_port->p_node); 308255332Scy for (port_num = 1; port_num < num_ports; 309255332Scy port_num++) { 310255332Scy p_dest_physp = 311145516Sdarrenr osm_node_get_physp_ptr(p_dest_port-> 312145516Sdarrenr p_node, 313255332Scy port_num); 314145516Sdarrenr if (p_dest_physp) 315145516Sdarrenr lr_rcv_get_physp_link 316145516Sdarrenr (sa, p_lr, NULL, 317145516Sdarrenr p_dest_physp, comp_mask, 318145516Sdarrenr p_list, p_req_physp); 319145516Sdarrenr } 320145516Sdarrenr } 321255332Scy } else { 322255332Scy /* 323255332Scy Process the world (recurse once back into this function). 324255332Scy */ 325145516Sdarrenr p_node_tbl = &sa->p_subn->node_guid_tbl; 326145516Sdarrenr p_node = (osm_node_t *) cl_qmap_head(p_node_tbl); 327145516Sdarrenr 328145516Sdarrenr while (p_node != (osm_node_t *) cl_qmap_end(p_node_tbl)) { 329145516Sdarrenr num_ports = osm_node_get_num_physp(p_node); 330145516Sdarrenr for (port_num = 1; port_num < num_ports; 331145516Sdarrenr port_num++) { 332145516Sdarrenr p_src_physp = 333145516Sdarrenr osm_node_get_physp_ptr(p_node, 334145516Sdarrenr port_num); 335145516Sdarrenr if (p_src_physp) 336145516Sdarrenr lr_rcv_get_physp_link 337145516Sdarrenr (sa, p_lr, p_src_physp, 338145516Sdarrenr NULL, comp_mask, p_list, 339255332Scy p_req_physp); 340145516Sdarrenr } 341145516Sdarrenr p_node = (osm_node_t *) cl_qmap_next(&p_node-> 342145516Sdarrenr map_item); 343145516Sdarrenr } 344145516Sdarrenr } 345145516Sdarrenr } 346145516Sdarrenr 347255332Scy OSM_LOG_EXIT(sa->p_log); 348255332Scy} 349255332Scy 350255332Scy/********************************************************************** 351145516Sdarrenr Returns the SA status to return to the client. 352145516Sdarrenr **********************************************************************/ 353145516Sdarrenrstatic ib_net16_t lr_rcv_get_end_points(IN osm_sa_t * sa, 354145516Sdarrenr IN const osm_madw_t * p_madw, 355145516Sdarrenr OUT const osm_port_t ** pp_src_port, 356145516Sdarrenr OUT const osm_port_t ** pp_dest_port) 357145516Sdarrenr{ 358145516Sdarrenr const ib_link_record_t *p_lr; 359145516Sdarrenr const ib_sa_mad_t *p_sa_mad; 360145516Sdarrenr ib_net64_t comp_mask; 361145516Sdarrenr ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS; 362145516Sdarrenr 363145516Sdarrenr OSM_LOG_ENTER(sa->p_log); 364145516Sdarrenr 365145516Sdarrenr /* 366145516Sdarrenr Determine what fields are valid and then get a pointer 367145516Sdarrenr to the source and destination port objects, if possible. 368145516Sdarrenr */ 369255332Scy p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 370145516Sdarrenr p_lr = (ib_link_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 371145516Sdarrenr 372145516Sdarrenr comp_mask = p_sa_mad->comp_mask; 373145516Sdarrenr *pp_src_port = NULL; 374145516Sdarrenr *pp_dest_port = NULL; 375145516Sdarrenr 376145516Sdarrenr if (comp_mask & IB_LR_COMPMASK_FROM_LID) { 377255332Scy *pp_src_port = osm_get_port_by_lid(sa->p_subn, p_lr->from_lid); 378255332Scy if (!*pp_src_port) { 379255332Scy /* 380255332Scy This 'error' is the client's fault (bad lid) so 381145516Sdarrenr don't enter it as an error in our own log. 382255332Scy Return an error response to the client. 383255332Scy */ 384145516Sdarrenr OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 385145516Sdarrenr "No source port with LID %u\n", 386145516Sdarrenr cl_ntoh16(p_lr->from_lid)); 387145516Sdarrenr 388145516Sdarrenr sa_status = IB_SA_MAD_STATUS_NO_RECORDS; 389145516Sdarrenr goto Exit; 390153876Sguido } 391153876Sguido } 392153876Sguido 393153876Sguido if (comp_mask & IB_LR_COMPMASK_TO_LID) { 394145516Sdarrenr *pp_dest_port = osm_get_port_by_lid(sa->p_subn, p_lr->to_lid); 395145516Sdarrenr if (!*pp_dest_port) { 396145516Sdarrenr /* 397145516Sdarrenr This 'error' is the client's fault (bad lid) so 398145516Sdarrenr don't enter it as an error in our own log. 399145516Sdarrenr Return an error response to the client. 400145516Sdarrenr */ 401145516Sdarrenr OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 402145516Sdarrenr "No dest port with LID %u\n", 403145516Sdarrenr cl_ntoh16(p_lr->to_lid)); 404145516Sdarrenr 405145516Sdarrenr sa_status = IB_SA_MAD_STATUS_NO_RECORDS; 406145516Sdarrenr goto Exit; 407153876Sguido } 408153876Sguido } 409153876Sguido 410153876SguidoExit: 411145516Sdarrenr OSM_LOG_EXIT(sa->p_log); 412145516Sdarrenr return sa_status; 413145516Sdarrenr} 414145516Sdarrenr 415145516Sdarrenrvoid osm_lr_rcv_process(IN void *context, IN void *data) 416145516Sdarrenr{ 417145516Sdarrenr osm_sa_t *sa = context; 418145516Sdarrenr osm_madw_t *p_madw = data; 419145516Sdarrenr const ib_link_record_t *p_lr; 420145516Sdarrenr const ib_sa_mad_t *p_sa_mad; 421145516Sdarrenr const osm_port_t *p_src_port; 422255332Scy const osm_port_t *p_dest_port; 423255332Scy cl_qlist_t lr_list; 424255332Scy ib_net16_t status; 425145516Sdarrenr osm_physp_t *p_req_physp; 426145516Sdarrenr 427145516Sdarrenr OSM_LOG_ENTER(sa->p_log); 428145516Sdarrenr 429255332Scy CL_ASSERT(p_madw); 430145516Sdarrenr 431145516Sdarrenr p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 432145516Sdarrenr p_lr = ib_sa_mad_get_payload_ptr(p_sa_mad); 433145516Sdarrenr 434145516Sdarrenr CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_LINK_RECORD); 435145516Sdarrenr 436255332Scy /* we only support SubnAdmGet and SubnAdmGetTable methods */ 437255332Scy if (p_sa_mad->method != IB_MAD_METHOD_GET && 438255332Scy p_sa_mad->method != IB_MAD_METHOD_GETTABLE) { 439255332Scy OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1804: " 440145516Sdarrenr "Unsupported Method (%s) for LinkRecord request\n", 441255332Scy ib_get_sa_method_str(p_sa_mad->method)); 442145516Sdarrenr osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 443145516Sdarrenr goto Exit; 444255332Scy } 445145516Sdarrenr 446255332Scy cl_plock_acquire(sa->p_lock); 447145516Sdarrenr 448255332Scy /* update the requester physical port */ 449145516Sdarrenr p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 450145516Sdarrenr osm_madw_get_mad_addr_ptr 451145516Sdarrenr (p_madw)); 452255332Scy if (p_req_physp == NULL) { 453145516Sdarrenr cl_plock_release(sa->p_lock); 454145516Sdarrenr OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1805: " 455145516Sdarrenr "Cannot find requester physical port\n"); 456145516Sdarrenr goto Exit; 457145516Sdarrenr } 458145516Sdarrenr 459145516Sdarrenr if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { 460145516Sdarrenr OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 461172776Sdarrenr "Requester port GUID 0x%" PRIx64 "\n", 462145516Sdarrenr cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); 463145516Sdarrenr osm_dump_link_record_v2(sa->p_log, p_lr, FILE_ID, OSM_LOG_DEBUG); 464255332Scy } 465145516Sdarrenr 466145516Sdarrenr cl_qlist_init(&lr_list); 467145516Sdarrenr 468145516Sdarrenr /* 469145516Sdarrenr Most SA functions (including this one) are read-only on the 470145516Sdarrenr subnet object, so we grab the lock non-exclusively. 471145516Sdarrenr */ 472145516Sdarrenr status = lr_rcv_get_end_points(sa, p_madw, &p_src_port, &p_dest_port); 473145516Sdarrenr 474145516Sdarrenr if (status == IB_SA_MAD_STATUS_SUCCESS) 475255332Scy lr_rcv_get_port_links(sa, p_lr, p_src_port, p_dest_port, 476145516Sdarrenr p_sa_mad->comp_mask, &lr_list, 477145516Sdarrenr p_req_physp); 478145516Sdarrenr 479145516Sdarrenr cl_plock_release(sa->p_lock); 480145516Sdarrenr 481145516Sdarrenr osm_sa_respond(sa, p_madw, sizeof(ib_link_record_t), &lr_list); 482255332Scy 483255332ScyExit: 484145516Sdarrenr OSM_LOG_EXIT(sa->p_log); 485255332Scy} 486145516Sdarrenr