1321936Shselasky/* 2321936Shselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3321936Shselasky * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. 4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5321936Shselasky * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. 6321936Shselasky * 7321936Shselasky * This software is available to you under a choice of one of two 8321936Shselasky * licenses. You may choose to be licensed under the terms of the GNU 9321936Shselasky * General Public License (GPL) Version 2, available from the file 10321936Shselasky * COPYING in the main directory of this source tree, or the 11321936Shselasky * OpenIB.org BSD license below: 12321936Shselasky * 13321936Shselasky * Redistribution and use in source and binary forms, with or 14321936Shselasky * without modification, are permitted provided that the following 15321936Shselasky * conditions are met: 16321936Shselasky * 17321936Shselasky * - Redistributions of source code must retain the above 18321936Shselasky * copyright notice, this list of conditions and the following 19321936Shselasky * disclaimer. 20321936Shselasky * 21321936Shselasky * - Redistributions in binary form must reproduce the above 22321936Shselasky * copyright notice, this list of conditions and the following 23321936Shselasky * disclaimer in the documentation and/or other materials 24321936Shselasky * provided with the distribution. 25321936Shselasky * 26321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33321936Shselasky * SOFTWARE. 34321936Shselasky * 35321936Shselasky */ 36321936Shselasky 37321936Shselasky/* 38321936Shselasky * Abstract: 39321936Shselasky * Implementation of osm_sr_rcv_t. 40321936Shselasky * This object represents the ServiceRecord Receiver object. 41321936Shselasky * This object is part of the opensm family of objects. 42321936Shselasky */ 43321936Shselasky 44321936Shselasky#if HAVE_CONFIG_H 45321936Shselasky# include <config.h> 46321936Shselasky#endif /* HAVE_CONFIG_H */ 47321936Shselasky 48321936Shselasky#include <string.h> 49321936Shselasky#include <iba/ib_types.h> 50321936Shselasky#include <complib/cl_qmap.h> 51321936Shselasky#include <complib/cl_passivelock.h> 52321936Shselasky#include <complib/cl_debug.h> 53321936Shselasky#include <complib/cl_qlist.h> 54321936Shselasky#include <opensm/osm_file_ids.h> 55321936Shselasky#define FILE_ID OSM_FILE_SA_SERVICE_RECORD_C 56321936Shselasky#include <vendor/osm_vendor_api.h> 57321936Shselasky#include <opensm/osm_port.h> 58321936Shselasky#include <opensm/osm_node.h> 59321936Shselasky#include <opensm/osm_switch.h> 60321936Shselasky#include <opensm/osm_helper.h> 61321936Shselasky#include <opensm/osm_sa.h> 62321936Shselasky#include <opensm/osm_service.h> 63321936Shselasky#include <opensm/osm_pkey.h> 64321936Shselasky 65321936Shselasky#define SA_SR_RESP_SIZE SA_ITEM_RESP_SIZE(service_rec) 66321936Shselasky 67321936Shselaskytypedef struct osm_sr_match_item { 68321936Shselasky cl_qlist_t sr_list; 69321936Shselasky ib_service_record_t *p_service_rec; 70321936Shselasky ib_net64_t comp_mask; 71321936Shselasky osm_sa_t *sa; 72321936Shselasky} osm_sr_match_item_t; 73321936Shselasky 74321936Shselaskytypedef struct osm_sr_search_ctxt { 75321936Shselasky osm_sr_match_item_t *p_sr_item; 76321936Shselasky const osm_physp_t *p_req_physp; 77321936Shselasky} osm_sr_search_ctxt_t; 78321936Shselasky 79321936Shselaskystatic boolean_t 80321936Shselaskymatch_service_pkey_with_ports_pkey(IN osm_sa_t * sa, 81321936Shselasky IN const osm_madw_t * p_madw, 82321936Shselasky ib_service_record_t * p_service_rec, 83321936Shselasky ib_net64_t const comp_mask) 84321936Shselasky{ 85321936Shselasky boolean_t valid = TRUE; 86321936Shselasky osm_physp_t *p_req_physp; 87321936Shselasky ib_net64_t service_guid; 88321936Shselasky osm_port_t *service_port; 89321936Shselasky 90321936Shselasky /* update the requester physical port */ 91321936Shselasky p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 92321936Shselasky osm_madw_get_mad_addr_ptr 93321936Shselasky (p_madw)); 94321936Shselasky if (p_req_physp == NULL) { 95321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2404: " 96321936Shselasky "Cannot find requester physical port\n"); 97321936Shselasky valid = FALSE; 98321936Shselasky goto Exit; 99321936Shselasky } 100321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 101321936Shselasky "Requester port GUID 0x%" PRIx64 "\n", 102321936Shselasky cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); 103321936Shselasky 104321936Shselasky if ((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY) { 105321936Shselasky /* We have a ServiceP_Key - check matching on requester port, 106321936Shselasky and ServiceGid port (if such exists) */ 107321936Shselasky /* Make sure it matches the p_req_physp */ 108321936Shselasky if (!osm_physp_has_pkey 109321936Shselasky (sa->p_log, p_service_rec->service_pkey, p_req_physp)) { 110321936Shselasky valid = FALSE; 111321936Shselasky goto Exit; 112321936Shselasky } 113321936Shselasky 114321936Shselasky /* If unicast, make sure it matches the port of the ServiceGid */ 115321936Shselasky if (comp_mask & IB_SR_COMPMASK_SGID && 116321936Shselasky !ib_gid_is_multicast(&p_service_rec->service_gid)) { 117321936Shselasky service_guid = 118321936Shselasky p_service_rec->service_gid.unicast.interface_id; 119321936Shselasky service_port = 120321936Shselasky osm_get_port_by_alias_guid(sa->p_subn, service_guid); 121321936Shselasky if (!service_port) { 122321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2405: " 123321936Shselasky "No port object for port 0x%016" PRIx64 124321936Shselasky "\n", cl_ntoh64(service_guid)); 125321936Shselasky valid = FALSE; 126321936Shselasky goto Exit; 127321936Shselasky } 128321936Shselasky /* check on the table of the default physical port of the service port */ 129321936Shselasky if (!osm_physp_has_pkey(sa->p_log, 130321936Shselasky p_service_rec->service_pkey, 131321936Shselasky service_port->p_physp)) { 132321936Shselasky valid = FALSE; 133321936Shselasky goto Exit; 134321936Shselasky } 135321936Shselasky } 136321936Shselasky } 137321936Shselasky 138321936ShselaskyExit: 139321936Shselasky return valid; 140321936Shselasky} 141321936Shselasky 142321936Shselaskystatic boolean_t 143321936Shselaskymatch_name_to_key_association(IN osm_sa_t * sa, 144321936Shselasky ib_service_record_t * p_service_rec, 145321936Shselasky ib_net64_t comp_mask) 146321936Shselasky{ 147321936Shselasky UNUSED_PARAM(p_service_rec); 148321936Shselasky UNUSED_PARAM(sa); 149321936Shselasky 150321936Shselasky if ((comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) == 151321936Shselasky (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) { 152321936Shselasky /* For now, we are not maintaining the ServiceAssociation record 153321936Shselasky * so just return TRUE 154321936Shselasky */ 155321936Shselasky return TRUE; 156321936Shselasky } 157321936Shselasky 158321936Shselasky return TRUE; 159321936Shselasky} 160321936Shselasky 161321936Shselaskystatic boolean_t validate_sr(IN osm_sa_t * sa, IN const osm_madw_t * p_madw) 162321936Shselasky{ 163321936Shselasky boolean_t valid = TRUE; 164321936Shselasky ib_sa_mad_t *p_sa_mad; 165321936Shselasky ib_service_record_t *p_recvd_service_rec; 166321936Shselasky 167321936Shselasky OSM_LOG_ENTER(sa->p_log); 168321936Shselasky 169321936Shselasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 170321936Shselasky p_recvd_service_rec = 171321936Shselasky (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 172321936Shselasky 173321936Shselasky valid = match_service_pkey_with_ports_pkey(sa, p_madw, 174321936Shselasky p_recvd_service_rec, 175321936Shselasky p_sa_mad->comp_mask); 176321936Shselasky if (!valid) { 177321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 178321936Shselasky "No Match for Service Pkey\n"); 179321936Shselasky valid = FALSE; 180321936Shselasky goto Exit; 181321936Shselasky } 182321936Shselasky 183321936Shselasky valid = match_name_to_key_association(sa, p_recvd_service_rec, 184321936Shselasky p_sa_mad->comp_mask); 185321936Shselasky if (!valid) { 186321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 187321936Shselasky "Service Record Name to key matching failed\n"); 188321936Shselasky valid = FALSE; 189321936Shselasky goto Exit; 190321936Shselasky } 191321936Shselasky 192321936ShselaskyExit: 193321936Shselasky OSM_LOG_EXIT(sa->p_log); 194321936Shselasky return valid; 195321936Shselasky} 196321936Shselasky 197321936Shselaskystatic void sr_rcv_respond(IN osm_sa_t * sa, IN osm_madw_t * p_madw, 198321936Shselasky IN cl_qlist_t * p_list) 199321936Shselasky{ 200321936Shselasky /* p923 - The ServiceKey shall be set to 0, except in the case of 201321936Shselasky a trusted request. 202321936Shselasky Note: In the mad controller we check that the SM_Key received on 203321936Shselasky the mad is valid. Meaning - is either zero or equal to the local 204321936Shselasky sm_key. 205321936Shselasky */ 206321936Shselasky if (!osm_madw_get_sa_mad_ptr(p_madw)->sm_key) { 207321936Shselasky osm_sa_item_t *item; 208321936Shselasky for (item = (osm_sa_item_t *) cl_qlist_head(p_list); 209321936Shselasky item != (osm_sa_item_t *) cl_qlist_end(p_list); 210321936Shselasky item = (osm_sa_item_t *) cl_qlist_next(&item->list_item)) 211321936Shselasky memset(item->resp.service_rec.service_key, 0, 212321936Shselasky sizeof(item->resp.service_rec.service_key)); 213321936Shselasky } 214321936Shselasky 215321936Shselasky osm_sa_respond(sa, p_madw, sizeof(ib_service_record_t), p_list); 216321936Shselasky} 217321936Shselasky 218321936Shselaskystatic void get_matching_sr(IN cl_list_item_t * p_list_item, IN void *context) 219321936Shselasky{ 220321936Shselasky osm_sr_search_ctxt_t *p_ctxt = context; 221321936Shselasky osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item; 222321936Shselasky osm_sa_item_t *p_sr_pool_item; 223321936Shselasky osm_sr_match_item_t *p_sr_item = p_ctxt->p_sr_item; 224321936Shselasky ib_net64_t comp_mask = p_sr_item->comp_mask; 225321936Shselasky const osm_physp_t *p_req_physp = p_ctxt->p_req_physp; 226321936Shselasky 227321936Shselasky if (comp_mask & IB_SR_COMPMASK_SID) { 228321936Shselasky if (p_sr_item->p_service_rec->service_id != 229321936Shselasky p_svcr->service_record.service_id) 230321936Shselasky return; 231321936Shselasky } 232321936Shselasky if (comp_mask & IB_SR_COMPMASK_SGID) { 233321936Shselasky if (memcmp(&p_sr_item->p_service_rec->service_gid, 234321936Shselasky &p_svcr->service_record.service_gid, 235321936Shselasky sizeof(p_svcr->service_record.service_gid)) != 0) 236321936Shselasky return; 237321936Shselasky } 238321936Shselasky if (comp_mask & IB_SR_COMPMASK_SPKEY) { 239321936Shselasky if (p_sr_item->p_service_rec->service_pkey != 240321936Shselasky p_svcr->service_record.service_pkey) 241321936Shselasky return; 242321936Shselasky } 243321936Shselasky 244321936Shselasky if (comp_mask & IB_SR_COMPMASK_SKEY) { 245321936Shselasky if (memcmp(p_sr_item->p_service_rec->service_key, 246321936Shselasky p_svcr->service_record.service_key, 247321936Shselasky 16 * sizeof(uint8_t))) 248321936Shselasky return; 249321936Shselasky } 250321936Shselasky if (comp_mask & IB_SR_COMPMASK_SNAME) { 251321936Shselasky if (memcmp(p_sr_item->p_service_rec->service_name, 252321936Shselasky p_svcr->service_record.service_name, 253321936Shselasky sizeof(p_svcr->service_record.service_name)) != 0) 254321936Shselasky return; 255321936Shselasky } 256321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_0) { 257321936Shselasky if (p_sr_item->p_service_rec->service_data8[0] != 258321936Shselasky p_svcr->service_record.service_data8[0]) 259321936Shselasky return; 260321936Shselasky } 261321936Shselasky 262321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_1) { 263321936Shselasky if (p_sr_item->p_service_rec->service_data8[1] != 264321936Shselasky p_svcr->service_record.service_data8[1]) 265321936Shselasky return; 266321936Shselasky } 267321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_2) { 268321936Shselasky if (p_sr_item->p_service_rec->service_data8[2] != 269321936Shselasky p_svcr->service_record.service_data8[2]) 270321936Shselasky return; 271321936Shselasky } 272321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_3) { 273321936Shselasky if (p_sr_item->p_service_rec->service_data8[3] != 274321936Shselasky p_svcr->service_record.service_data8[3]) 275321936Shselasky return; 276321936Shselasky } 277321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_4) { 278321936Shselasky if (p_sr_item->p_service_rec->service_data8[4] != 279321936Shselasky p_svcr->service_record.service_data8[4]) 280321936Shselasky return; 281321936Shselasky } 282321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_5) { 283321936Shselasky if (p_sr_item->p_service_rec->service_data8[5] != 284321936Shselasky p_svcr->service_record.service_data8[5]) 285321936Shselasky return; 286321936Shselasky } 287321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_6) { 288321936Shselasky if (p_sr_item->p_service_rec->service_data8[6] != 289321936Shselasky p_svcr->service_record.service_data8[6]) 290321936Shselasky return; 291321936Shselasky } 292321936Shselasky 293321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_7) { 294321936Shselasky if (p_sr_item->p_service_rec->service_data8[7] != 295321936Shselasky p_svcr->service_record.service_data8[7]) 296321936Shselasky return; 297321936Shselasky } 298321936Shselasky 299321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_8) { 300321936Shselasky if (p_sr_item->p_service_rec->service_data8[8] != 301321936Shselasky p_svcr->service_record.service_data8[8]) 302321936Shselasky return; 303321936Shselasky } 304321936Shselasky 305321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_9) { 306321936Shselasky if (p_sr_item->p_service_rec->service_data8[9] != 307321936Shselasky p_svcr->service_record.service_data8[9]) 308321936Shselasky return; 309321936Shselasky } 310321936Shselasky 311321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_10) { 312321936Shselasky if (p_sr_item->p_service_rec->service_data8[10] != 313321936Shselasky p_svcr->service_record.service_data8[10]) 314321936Shselasky return; 315321936Shselasky } 316321936Shselasky 317321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_11) { 318321936Shselasky if (p_sr_item->p_service_rec->service_data8[11] != 319321936Shselasky p_svcr->service_record.service_data8[11]) 320321936Shselasky return; 321321936Shselasky } 322321936Shselasky 323321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_12) { 324321936Shselasky if (p_sr_item->p_service_rec->service_data8[12] != 325321936Shselasky p_svcr->service_record.service_data8[12]) 326321936Shselasky return; 327321936Shselasky } 328321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_13) { 329321936Shselasky if (p_sr_item->p_service_rec->service_data8[13] != 330321936Shselasky p_svcr->service_record.service_data8[13]) 331321936Shselasky return; 332321936Shselasky } 333321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_14) { 334321936Shselasky if (p_sr_item->p_service_rec->service_data8[14] != 335321936Shselasky p_svcr->service_record.service_data8[14]) 336321936Shselasky return; 337321936Shselasky } 338321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA8_15) { 339321936Shselasky if (p_sr_item->p_service_rec->service_data8[15] != 340321936Shselasky p_svcr->service_record.service_data8[15]) 341321936Shselasky return; 342321936Shselasky } 343321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_0) { 344321936Shselasky if (p_sr_item->p_service_rec->service_data16[0] != 345321936Shselasky p_svcr->service_record.service_data16[0]) 346321936Shselasky return; 347321936Shselasky } 348321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_1) { 349321936Shselasky if (p_sr_item->p_service_rec->service_data16[1] != 350321936Shselasky p_svcr->service_record.service_data16[1]) 351321936Shselasky return; 352321936Shselasky } 353321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_2) { 354321936Shselasky if (p_sr_item->p_service_rec->service_data16[2] != 355321936Shselasky p_svcr->service_record.service_data16[2]) 356321936Shselasky return; 357321936Shselasky } 358321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_3) { 359321936Shselasky if (p_sr_item->p_service_rec->service_data16[3] != 360321936Shselasky p_svcr->service_record.service_data16[3]) 361321936Shselasky return; 362321936Shselasky } 363321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_4) { 364321936Shselasky if (p_sr_item->p_service_rec->service_data16[4] != 365321936Shselasky p_svcr->service_record.service_data16[4]) 366321936Shselasky return; 367321936Shselasky } 368321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_5) { 369321936Shselasky if (p_sr_item->p_service_rec->service_data16[5] != 370321936Shselasky p_svcr->service_record.service_data16[5]) 371321936Shselasky return; 372321936Shselasky } 373321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_6) { 374321936Shselasky if (p_sr_item->p_service_rec->service_data16[6] != 375321936Shselasky p_svcr->service_record.service_data16[6]) 376321936Shselasky return; 377321936Shselasky } 378321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA16_7) { 379321936Shselasky if (p_sr_item->p_service_rec->service_data16[7] != 380321936Shselasky p_svcr->service_record.service_data16[7]) 381321936Shselasky return; 382321936Shselasky } 383321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA32_0) { 384321936Shselasky if (p_sr_item->p_service_rec->service_data32[0] != 385321936Shselasky p_svcr->service_record.service_data32[0]) 386321936Shselasky return; 387321936Shselasky } 388321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA32_1) { 389321936Shselasky if (p_sr_item->p_service_rec->service_data32[1] != 390321936Shselasky p_svcr->service_record.service_data32[1]) 391321936Shselasky return; 392321936Shselasky } 393321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA32_2) { 394321936Shselasky if (p_sr_item->p_service_rec->service_data32[2] != 395321936Shselasky p_svcr->service_record.service_data32[2]) 396321936Shselasky return; 397321936Shselasky } 398321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA32_3) { 399321936Shselasky if (p_sr_item->p_service_rec->service_data32[3] != 400321936Shselasky p_svcr->service_record.service_data32[3]) 401321936Shselasky return; 402321936Shselasky } 403321936Shselasky 404321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA64_0) { 405321936Shselasky if (p_sr_item->p_service_rec->service_data64[0] != 406321936Shselasky p_svcr->service_record.service_data64[0]) 407321936Shselasky return; 408321936Shselasky } 409321936Shselasky if (comp_mask & IB_SR_COMPMASK_SDATA64_1) { 410321936Shselasky if (p_sr_item->p_service_rec->service_data64[1] != 411321936Shselasky p_svcr->service_record.service_data64[1]) 412321936Shselasky return; 413321936Shselasky } 414321936Shselasky 415321936Shselasky /* Check that the requester port has the pkey which is the service_pkey. 416321936Shselasky If not - then it cannot receive this ServiceRecord. */ 417321936Shselasky /* The check is relevant only if the service_pkey is valid */ 418321936Shselasky if (!ib_pkey_is_invalid(p_svcr->service_record.service_pkey)) { 419321936Shselasky if (!osm_physp_has_pkey(p_sr_item->sa->p_log, 420321936Shselasky p_svcr->service_record.service_pkey, 421321936Shselasky p_req_physp)) { 422321936Shselasky OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_VERBOSE, 423321936Shselasky "requester port doesn't have the service_pkey: 0x%X\n", 424321936Shselasky cl_ntoh16(p_svcr->service_record.service_pkey)); 425321936Shselasky return; 426321936Shselasky } 427321936Shselasky } 428321936Shselasky 429321936Shselasky p_sr_pool_item = malloc(SA_SR_RESP_SIZE); 430321936Shselasky if (p_sr_pool_item == NULL) { 431321936Shselasky OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_ERROR, "ERR 2408: " 432321936Shselasky "Unable to acquire Service Record from pool\n"); 433321936Shselasky goto Exit; 434321936Shselasky } 435321936Shselasky 436321936Shselasky p_sr_pool_item->resp.service_rec = p_svcr->service_record; 437321936Shselasky 438321936Shselasky cl_qlist_insert_tail(&p_sr_item->sr_list, &p_sr_pool_item->list_item); 439321936Shselasky 440321936ShselaskyExit: 441321936Shselasky return; 442321936Shselasky} 443321936Shselasky 444321936Shselaskystatic void sr_rcv_process_get_method(osm_sa_t * sa, IN osm_madw_t * p_madw) 445321936Shselasky{ 446321936Shselasky ib_sa_mad_t *p_sa_mad; 447321936Shselasky ib_service_record_t *p_recvd_service_rec; 448321936Shselasky osm_sr_match_item_t sr_match_item; 449321936Shselasky osm_sr_search_ctxt_t context; 450321936Shselasky osm_physp_t *p_req_physp; 451321936Shselasky 452321936Shselasky OSM_LOG_ENTER(sa->p_log); 453321936Shselasky 454321936Shselasky CL_ASSERT(p_madw); 455321936Shselasky 456321936Shselasky /* Grab the lock */ 457321936Shselasky cl_plock_acquire(sa->p_lock); 458321936Shselasky 459321936Shselasky /* update the requester physical port */ 460321936Shselasky p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 461321936Shselasky osm_madw_get_mad_addr_ptr 462321936Shselasky (p_madw)); 463321936Shselasky if (p_req_physp == NULL) { 464321936Shselasky cl_plock_release(sa->p_lock); 465321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2409: " 466321936Shselasky "Cannot find requester physical port\n"); 467321936Shselasky goto Exit; 468321936Shselasky } 469321936Shselasky 470321936Shselasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 471321936Shselasky p_recvd_service_rec = 472321936Shselasky (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 473321936Shselasky 474321936Shselasky if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { 475321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 476321936Shselasky "Requester port GUID 0x%" PRIx64 "\n", 477321936Shselasky cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); 478321936Shselasky osm_dump_service_record_v2(sa->p_log, p_recvd_service_rec, 479321936Shselasky FILE_ID, OSM_LOG_DEBUG); 480321936Shselasky } 481321936Shselasky 482321936Shselasky cl_qlist_init(&sr_match_item.sr_list); 483321936Shselasky sr_match_item.p_service_rec = p_recvd_service_rec; 484321936Shselasky sr_match_item.comp_mask = p_sa_mad->comp_mask; 485321936Shselasky sr_match_item.sa = sa; 486321936Shselasky 487321936Shselasky context.p_sr_item = &sr_match_item; 488321936Shselasky context.p_req_physp = p_req_physp; 489321936Shselasky 490321936Shselasky cl_qlist_apply_func(&sa->p_subn->sa_sr_list, get_matching_sr, &context); 491321936Shselasky 492321936Shselasky cl_plock_release(sa->p_lock); 493321936Shselasky 494321936Shselasky if (p_sa_mad->method == IB_MAD_METHOD_GET && 495321936Shselasky cl_qlist_count(&sr_match_item.sr_list) == 0) { 496321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 497321936Shselasky "No records matched the Service Record query\n"); 498321936Shselasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); 499321936Shselasky goto Exit; 500321936Shselasky } 501321936Shselasky 502321936Shselasky sr_rcv_respond(sa, p_madw, &sr_match_item.sr_list); 503321936Shselasky 504321936ShselaskyExit: 505321936Shselasky OSM_LOG_EXIT(sa->p_log); 506321936Shselasky return; 507321936Shselasky} 508321936Shselasky 509321936Shselaskystatic void sr_rcv_process_set_method(osm_sa_t * sa, IN osm_madw_t * p_madw) 510321936Shselasky{ 511321936Shselasky ib_sa_mad_t *p_sa_mad; 512321936Shselasky ib_service_record_t *p_recvd_service_rec; 513321936Shselasky ib_net64_t comp_mask; 514321936Shselasky osm_svcr_t *p_svcr; 515321936Shselasky osm_sa_item_t *p_sr_item; 516321936Shselasky cl_qlist_t sr_list; 517321936Shselasky 518321936Shselasky OSM_LOG_ENTER(sa->p_log); 519321936Shselasky 520321936Shselasky CL_ASSERT(p_madw); 521321936Shselasky 522321936Shselasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 523321936Shselasky p_recvd_service_rec = 524321936Shselasky (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 525321936Shselasky 526321936Shselasky comp_mask = p_sa_mad->comp_mask; 527321936Shselasky 528321936Shselasky if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) 529321936Shselasky osm_dump_service_record_v2(sa->p_log, p_recvd_service_rec, 530321936Shselasky FILE_ID, OSM_LOG_DEBUG); 531321936Shselasky 532321936Shselasky if ((comp_mask & (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID)) != 533321936Shselasky (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID)) { 534321936Shselasky cl_plock_release(sa->p_lock); 535321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 536321936Shselasky "Component Mask RID check failed for METHOD_SET\n"); 537321936Shselasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 538321936Shselasky goto Exit; 539321936Shselasky } 540321936Shselasky 541321936Shselasky /* if we were not provided with a service lease make it infinite */ 542321936Shselasky if (!(comp_mask & IB_SR_COMPMASK_SLEASE)) { 543321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 544321936Shselasky "ServiceLease Component Mask not set - using infinite lease\n"); 545321936Shselasky p_recvd_service_rec->service_lease = 0xFFFFFFFF; 546321936Shselasky } 547321936Shselasky 548321936Shselasky /* If Record exists with matching RID */ 549321936Shselasky p_svcr = osm_svcr_get_by_rid(sa->p_subn, sa->p_log, 550321936Shselasky p_recvd_service_rec); 551321936Shselasky 552321936Shselasky if (p_svcr == NULL) { 553321936Shselasky /* Create the instance of the osm_svcr_t object */ 554321936Shselasky p_svcr = osm_svcr_new(p_recvd_service_rec); 555321936Shselasky if (p_svcr == NULL) { 556321936Shselasky cl_plock_release(sa->p_lock); 557321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2411: " 558321936Shselasky "Failed to create new service record\n"); 559321936Shselasky 560321936Shselasky osm_sa_send_error(sa, p_madw, 561321936Shselasky IB_SA_MAD_STATUS_NO_RESOURCES); 562321936Shselasky goto Exit; 563321936Shselasky } 564321936Shselasky 565321936Shselasky /* Add this new osm_svcr_t object to subnet object */ 566321936Shselasky osm_svcr_insert_to_db(sa->p_subn, sa->p_log, p_svcr); 567321936Shselasky 568321936Shselasky } else /* Update the old instance of the osm_svcr_t object */ 569321936Shselasky osm_svcr_init(p_svcr, p_recvd_service_rec); 570321936Shselasky 571321936Shselasky cl_plock_release(sa->p_lock); 572321936Shselasky 573321936Shselasky if (p_recvd_service_rec->service_lease != 0xFFFFFFFF) { 574321936Shselasky#if 0 575321936Shselasky cl_timer_trim(&sa->sr_timer, 576321936Shselasky p_recvd_service_rec->service_lease * 1000); 577321936Shselasky#endif 578321936Shselasky /* This was a bug since no check was made to see if too long */ 579321936Shselasky /* just make sure the timer works - get a call back within a second */ 580321936Shselasky cl_timer_trim(&sa->sr_timer, 1000); 581321936Shselasky p_svcr->modified_time = cl_get_time_stamp_sec(); 582321936Shselasky } 583321936Shselasky 584321936Shselasky p_sr_item = malloc(SA_SR_RESP_SIZE); 585321936Shselasky if (p_sr_item == NULL) { 586321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2412: " 587321936Shselasky "Unable to acquire Service record\n"); 588321936Shselasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); 589321936Shselasky goto Exit; 590321936Shselasky } 591321936Shselasky 592321936Shselasky if ((comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY) 593321936Shselasky /* Set the Default Service P_Key in the response */ 594321936Shselasky p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY; 595321936Shselasky 596321936Shselasky p_sr_item->resp.service_rec = *p_recvd_service_rec; 597321936Shselasky cl_qlist_init(&sr_list); 598321936Shselasky 599321936Shselasky cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item); 600321936Shselasky 601321936Shselasky sr_rcv_respond(sa, p_madw, &sr_list); 602321936Shselasky 603321936ShselaskyExit: 604321936Shselasky OSM_LOG_EXIT(sa->p_log); 605321936Shselasky} 606321936Shselasky 607321936Shselaskystatic void sr_rcv_process_delete_method(osm_sa_t * sa, IN osm_madw_t * p_madw) 608321936Shselasky{ 609321936Shselasky ib_sa_mad_t *p_sa_mad; 610321936Shselasky ib_service_record_t *p_recvd_service_rec; 611321936Shselasky osm_svcr_t *p_svcr; 612321936Shselasky osm_sa_item_t *p_sr_item; 613321936Shselasky cl_qlist_t sr_list; 614321936Shselasky 615321936Shselasky OSM_LOG_ENTER(sa->p_log); 616321936Shselasky 617321936Shselasky CL_ASSERT(p_madw); 618321936Shselasky 619321936Shselasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 620321936Shselasky p_recvd_service_rec = 621321936Shselasky (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 622321936Shselasky 623321936Shselasky if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) 624321936Shselasky osm_dump_service_record_v2(sa->p_log, p_recvd_service_rec, 625321936Shselasky FILE_ID, OSM_LOG_DEBUG); 626321936Shselasky 627321936Shselasky /* If Record exists with matching RID */ 628321936Shselasky p_svcr = osm_svcr_get_by_rid(sa->p_subn, sa->p_log, 629321936Shselasky p_recvd_service_rec); 630321936Shselasky 631321936Shselasky if (p_svcr == NULL) { 632321936Shselasky cl_plock_release(sa->p_lock); 633321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 634321936Shselasky "No records matched the RID\n"); 635321936Shselasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); 636321936Shselasky goto Exit; 637321936Shselasky } 638321936Shselasky 639321936Shselasky osm_svcr_remove_from_db(sa->p_subn, sa->p_log, p_svcr); 640321936Shselasky cl_plock_release(sa->p_lock); 641321936Shselasky 642321936Shselasky p_sr_item = malloc(SA_SR_RESP_SIZE); 643321936Shselasky if (p_sr_item == NULL) { 644321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2413: " 645321936Shselasky "Unable to acquire Service record\n"); 646321936Shselasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); 647321936Shselasky osm_svcr_delete(p_svcr); 648321936Shselasky goto Exit; 649321936Shselasky } 650321936Shselasky 651321936Shselasky /* provide back the copy of the record */ 652321936Shselasky p_sr_item->resp.service_rec = p_svcr->service_record; 653321936Shselasky cl_qlist_init(&sr_list); 654321936Shselasky 655321936Shselasky cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item); 656321936Shselasky 657321936Shselasky osm_svcr_delete(p_svcr); 658321936Shselasky 659321936Shselasky sr_rcv_respond(sa, p_madw, &sr_list); 660321936Shselasky 661321936ShselaskyExit: 662321936Shselasky OSM_LOG_EXIT(sa->p_log); 663321936Shselasky return; 664321936Shselasky} 665321936Shselasky 666321936Shselaskyvoid osm_sr_rcv_process(IN void *context, IN void *data) 667321936Shselasky{ 668321936Shselasky osm_sa_t *sa = context; 669321936Shselasky osm_madw_t *p_madw = data; 670321936Shselasky ib_sa_mad_t *p_sa_mad; 671321936Shselasky boolean_t valid; 672321936Shselasky 673321936Shselasky OSM_LOG_ENTER(sa->p_log); 674321936Shselasky 675321936Shselasky CL_ASSERT(p_madw); 676321936Shselasky 677321936Shselasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 678321936Shselasky 679321936Shselasky CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD); 680321936Shselasky 681321936Shselasky switch (p_sa_mad->method) { 682321936Shselasky case IB_MAD_METHOD_SET: 683321936Shselasky cl_plock_excl_acquire(sa->p_lock); 684321936Shselasky valid = validate_sr(sa, p_madw); 685321936Shselasky if (!valid) { 686321936Shselasky cl_plock_release(sa->p_lock); 687321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 688321936Shselasky "Component Mask check failed for set request\n"); 689321936Shselasky osm_sa_send_error(sa, p_madw, 690321936Shselasky IB_SA_MAD_STATUS_REQ_INVALID); 691321936Shselasky goto Exit; 692321936Shselasky } 693321936Shselasky sr_rcv_process_set_method(sa, p_madw); 694321936Shselasky break; 695321936Shselasky case IB_MAD_METHOD_DELETE: 696321936Shselasky cl_plock_excl_acquire(sa->p_lock); 697321936Shselasky valid = validate_sr(sa, p_madw); 698321936Shselasky if (!valid) { 699321936Shselasky cl_plock_release(sa->p_lock); 700321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 701321936Shselasky "Component Mask check failed for delete request\n"); 702321936Shselasky osm_sa_send_error(sa, p_madw, 703321936Shselasky IB_SA_MAD_STATUS_REQ_INVALID); 704321936Shselasky goto Exit; 705321936Shselasky } 706321936Shselasky sr_rcv_process_delete_method(sa, p_madw); 707321936Shselasky break; 708321936Shselasky case IB_MAD_METHOD_GET: 709321936Shselasky case IB_MAD_METHOD_GETTABLE: 710321936Shselasky sr_rcv_process_get_method(sa, p_madw); 711321936Shselasky break; 712321936Shselasky default: 713321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 714321936Shselasky "Unsupported Method (%s) for ServiceRecord request\n", 715321936Shselasky ib_get_sa_method_str(p_sa_mad->method)); 716321936Shselasky osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 717321936Shselasky break; 718321936Shselasky } 719321936Shselasky 720321936ShselaskyExit: 721321936Shselasky OSM_LOG_EXIT(sa->p_log); 722321936Shselasky} 723321936Shselasky 724321936Shselaskyvoid osm_sr_rcv_lease_cb(IN void *context) 725321936Shselasky{ 726321936Shselasky osm_sa_t *sa = context; 727321936Shselasky cl_list_item_t *p_list_item; 728321936Shselasky cl_list_item_t *p_next_list_item; 729321936Shselasky osm_svcr_t *p_svcr; 730321936Shselasky uint32_t curr_time; 731321936Shselasky uint32_t elapsed_time; 732321936Shselasky uint32_t trim_time = 20; /* maxiaml timer refresh is 20 seconds */ 733321936Shselasky 734321936Shselasky OSM_LOG_ENTER(sa->p_log); 735321936Shselasky 736321936Shselasky cl_plock_excl_acquire(sa->p_lock); 737321936Shselasky 738321936Shselasky p_list_item = cl_qlist_head(&sa->p_subn->sa_sr_list); 739321936Shselasky 740321936Shselasky while (p_list_item != cl_qlist_end(&sa->p_subn->sa_sr_list)) { 741321936Shselasky p_svcr = (osm_svcr_t *) p_list_item; 742321936Shselasky 743321936Shselasky if (p_svcr->service_record.service_lease == 0xFFFFFFFF) { 744321936Shselasky p_list_item = cl_qlist_next(p_list_item); 745321936Shselasky continue; 746321936Shselasky } 747321936Shselasky 748321936Shselasky /* current time in seconds */ 749321936Shselasky curr_time = cl_get_time_stamp_sec(); 750321936Shselasky /* elapsed time from last modify */ 751321936Shselasky elapsed_time = curr_time - p_svcr->modified_time; 752321936Shselasky /* but it can not be less then 1 */ 753321936Shselasky if (elapsed_time < 1) 754321936Shselasky elapsed_time = 1; 755321936Shselasky 756321936Shselasky if (elapsed_time < p_svcr->lease_period) { 757321936Shselasky /* 758321936Shselasky Just update the service lease period 759321936Shselasky note: for simplicity we work with a uint32_t field 760321936Shselasky external to the network order lease_period of the MAD 761321936Shselasky */ 762321936Shselasky p_svcr->lease_period -= elapsed_time; 763321936Shselasky 764321936Shselasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 765321936Shselasky "Remaining time for Service Name:%s is:0x%X\n", 766321936Shselasky p_svcr->service_record.service_name, 767321936Shselasky p_svcr->lease_period); 768321936Shselasky 769321936Shselasky p_svcr->modified_time = curr_time; 770321936Shselasky 771321936Shselasky /* Update the trim timer */ 772321936Shselasky if (trim_time > p_svcr->lease_period) { 773321936Shselasky trim_time = p_svcr->lease_period; 774321936Shselasky if (trim_time < 1) 775321936Shselasky trim_time = 1; 776321936Shselasky } 777321936Shselasky 778321936Shselasky p_list_item = cl_qlist_next(p_list_item); 779321936Shselasky continue; 780321936Shselasky 781321936Shselasky } else { 782321936Shselasky p_next_list_item = cl_qlist_next(p_list_item); 783321936Shselasky 784321936Shselasky /* Remove the service Record */ 785321936Shselasky osm_svcr_remove_from_db(sa->p_subn, sa->p_log, p_svcr); 786321936Shselasky 787321936Shselasky osm_svcr_delete(p_svcr); 788321936Shselasky 789321936Shselasky p_list_item = p_next_list_item; 790321936Shselasky continue; 791321936Shselasky } 792321936Shselasky } 793321936Shselasky 794321936Shselasky /* Release the Lock */ 795321936Shselasky cl_plock_release(sa->p_lock); 796321936Shselasky 797321936Shselasky if (trim_time != 0xFFFFFFFF) { 798321936Shselasky cl_timer_trim(&sa->sr_timer, trim_time * 1000); /* Convert to milli seconds */ 799321936Shselasky } 800321936Shselasky 801321936Shselasky OSM_LOG_EXIT(sa->p_log); 802321936Shselasky} 803