1/* 2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 */ 35 36/* 37 * Abstract: 38 * Implementation of osm_sr_rcv_t. 39 * This object represents the ServiceRecord Receiver object. 40 * This object is part of the opensm family of objects. 41 */ 42 43#if HAVE_CONFIG_H 44# include <config.h> 45#endif /* HAVE_CONFIG_H */ 46 47#include <string.h> 48#include <iba/ib_types.h> 49#include <complib/cl_qmap.h> 50#include <complib/cl_passivelock.h> 51#include <complib/cl_debug.h> 52#include <complib/cl_qlist.h> 53#include <vendor/osm_vendor_api.h> 54#include <opensm/osm_port.h> 55#include <opensm/osm_node.h> 56#include <opensm/osm_switch.h> 57#include <opensm/osm_helper.h> 58#include <opensm/osm_sa.h> 59#include <opensm/osm_service.h> 60#include <opensm/osm_pkey.h> 61 62typedef struct osm_sr_item { 63 cl_list_item_t list_item; 64 ib_service_record_t service_rec; 65} osm_sr_item_t; 66 67typedef struct osm_sr_match_item { 68 cl_qlist_t sr_list; 69 ib_service_record_t *p_service_rec; 70 ib_net64_t comp_mask; 71 osm_sa_t *sa; 72} osm_sr_match_item_t; 73 74typedef struct osm_sr_search_ctxt { 75 osm_sr_match_item_t *p_sr_item; 76 const osm_physp_t *p_req_physp; 77} osm_sr_search_ctxt_t; 78 79/********************************************************************** 80 **********************************************************************/ 81static boolean_t 82__match_service_pkey_with_ports_pkey(IN osm_sa_t * sa, 83 IN const osm_madw_t * const p_madw, 84 ib_service_record_t * const p_service_rec, 85 ib_net64_t const comp_mask) 86{ 87 boolean_t valid = TRUE; 88 osm_physp_t *p_req_physp; 89 ib_net64_t service_guid; 90 osm_port_t *service_port; 91 92 /* update the requester physical port. */ 93 p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, 94 sa->p_subn, 95 osm_madw_get_mad_addr_ptr 96 (p_madw)); 97 if (p_req_physp == NULL) { 98 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2404: " 99 "Cannot find requester physical port\n"); 100 valid = FALSE; 101 goto Exit; 102 } 103 104 if ((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY) { 105 /* We have a ServiceP_Key - check matching on requester port, and 106 ServiceGid port (if such exists) */ 107 /* Make sure it matches the p_req_physp */ 108 if (!osm_physp_has_pkey 109 (sa->p_log, p_service_rec->service_pkey, p_req_physp)) { 110 valid = FALSE; 111 goto Exit; 112 } 113 114 /* Make sure it matches the port of the ServiceGid */ 115 if ((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID) { 116 service_guid = 117 p_service_rec->service_gid.unicast.interface_id; 118 service_port = 119 osm_get_port_by_guid(sa->p_subn, service_guid); 120 if (!service_port) { 121 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2405: " 122 "No port object for port 0x%016" PRIx64 123 "\n", cl_ntoh64(service_guid)); 124 valid = FALSE; 125 goto Exit; 126 } 127 /* check on the table of the default physical port of the service port */ 128 if (!osm_physp_has_pkey(sa->p_log, 129 p_service_rec->service_pkey, 130 service_port->p_physp)) { 131 valid = FALSE; 132 goto Exit; 133 } 134 } 135 } 136 137Exit: 138 return valid; 139} 140 141/********************************************************************** 142 **********************************************************************/ 143static boolean_t 144__match_name_to_key_association(IN osm_sa_t * sa, 145 ib_service_record_t * p_service_rec, 146 ib_net64_t comp_mask) 147{ 148 UNUSED_PARAM(p_service_rec); 149 UNUSED_PARAM(sa); 150 151 if ((comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) == 152 (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) { 153 /* For now, we are not maintaining the ServiceAssociation record 154 * so just return TRUE 155 */ 156 return TRUE; 157 } 158 159 return TRUE; 160} 161 162/********************************************************************** 163 **********************************************************************/ 164static boolean_t 165__validate_sr(IN osm_sa_t * sa, IN const osm_madw_t * const p_madw) 166{ 167 boolean_t valid = TRUE; 168 ib_sa_mad_t *p_sa_mad; 169 ib_service_record_t *p_recvd_service_rec; 170 171 OSM_LOG_ENTER(sa->p_log); 172 173 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 174 p_recvd_service_rec = 175 (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 176 177 valid = __match_service_pkey_with_ports_pkey(sa, 178 p_madw, 179 p_recvd_service_rec, 180 p_sa_mad->comp_mask); 181 182 if (!valid) { 183 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 184 "No Match for Service Pkey\n"); 185 valid = FALSE; 186 goto Exit; 187 } 188 189 valid = __match_name_to_key_association(sa, 190 p_recvd_service_rec, 191 p_sa_mad->comp_mask); 192 193 if (!valid) { 194 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 195 "Service Record Name to key matching failed\n"); 196 valid = FALSE; 197 goto Exit; 198 } 199 200Exit: 201 OSM_LOG_EXIT(sa->p_log); 202 return valid; 203} 204 205/********************************************************************** 206 **********************************************************************/ 207static void 208__osm_sr_rcv_respond(IN osm_sa_t * sa, 209 IN osm_madw_t * const p_madw, 210 IN cl_qlist_t * const p_list) 211{ 212 /* p923 - The ServiceKey shall be set to 0, except in the case of 213 a trusted request. 214 Note: In the mad controller we check that the SM_Key received on 215 the mad is valid. Meaning - is either zero or equal to the local 216 sm_key. 217 */ 218 if (!osm_madw_get_sa_mad_ptr(p_madw)->sm_key) { 219 osm_sr_item_t *item; 220 for (item = (osm_sr_item_t *) cl_qlist_head(p_list); 221 item != (osm_sr_item_t *) cl_qlist_end(p_list); 222 item = (osm_sr_item_t *)cl_qlist_next(&item->list_item)) 223 memset(item->service_rec.service_key, 0, 224 sizeof(item->service_rec.service_key)); 225 } 226 227 osm_sa_respond(sa, p_madw, sizeof(ib_service_record_t), p_list); 228} 229 230/********************************************************************** 231 **********************************************************************/ 232static void 233__get_matching_sr(IN cl_list_item_t * const p_list_item, IN void *context) 234{ 235 osm_sr_search_ctxt_t *const p_ctxt = (osm_sr_search_ctxt_t *) context; 236 osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item; 237 osm_sr_item_t *p_sr_pool_item; 238 osm_sr_match_item_t *p_sr_item = p_ctxt->p_sr_item; 239 ib_net64_t comp_mask = p_sr_item->comp_mask; 240 const osm_physp_t *p_req_physp = p_ctxt->p_req_physp; 241 242 if ((comp_mask & IB_SR_COMPMASK_SID) == IB_SR_COMPMASK_SID) { 243 if (p_sr_item->p_service_rec->service_id != 244 p_svcr->service_record.service_id) 245 return; 246 } 247 if ((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID) { 248 if (memcmp(&p_sr_item->p_service_rec->service_gid, 249 &p_svcr->service_record.service_gid, 250 sizeof(p_svcr->service_record.service_gid)) != 0) 251 return; 252 } 253 if ((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY) { 254 if (p_sr_item->p_service_rec->service_pkey != 255 p_svcr->service_record.service_pkey) 256 return; 257 } 258 259 if ((comp_mask & IB_SR_COMPMASK_SKEY) == IB_SR_COMPMASK_SKEY) { 260 if (memcmp(p_sr_item->p_service_rec->service_key, 261 p_svcr->service_record.service_key, 262 16 * sizeof(uint8_t))) 263 return; 264 } 265 if ((comp_mask & IB_SR_COMPMASK_SNAME) == IB_SR_COMPMASK_SNAME) { 266 if (memcmp(p_sr_item->p_service_rec->service_name, 267 p_svcr->service_record.service_name, 268 sizeof(p_svcr->service_record.service_name)) != 0) 269 return; 270 } 271 if ((comp_mask & IB_SR_COMPMASK_SDATA8_0) == IB_SR_COMPMASK_SDATA8_0) { 272 if (p_sr_item->p_service_rec->service_data8[0] != 273 p_svcr->service_record.service_data8[0]) 274 return; 275 } 276 277 if ((comp_mask & IB_SR_COMPMASK_SDATA8_1) == IB_SR_COMPMASK_SDATA8_1) { 278 if (p_sr_item->p_service_rec->service_data8[1] != 279 p_svcr->service_record.service_data8[1]) 280 return; 281 } 282 if ((comp_mask & IB_SR_COMPMASK_SDATA8_2) == IB_SR_COMPMASK_SDATA8_2) { 283 if (p_sr_item->p_service_rec->service_data8[2] != 284 p_svcr->service_record.service_data8[2]) 285 return; 286 } 287 if ((comp_mask & IB_SR_COMPMASK_SDATA8_3) == IB_SR_COMPMASK_SDATA8_3) { 288 if (p_sr_item->p_service_rec->service_data8[3] != 289 p_svcr->service_record.service_data8[3]) 290 return; 291 } 292 if ((comp_mask & IB_SR_COMPMASK_SDATA8_4) == IB_SR_COMPMASK_SDATA8_4) { 293 if (p_sr_item->p_service_rec->service_data8[4] != 294 p_svcr->service_record.service_data8[4]) 295 return; 296 } 297 if ((comp_mask & IB_SR_COMPMASK_SDATA8_5) == IB_SR_COMPMASK_SDATA8_5) { 298 if (p_sr_item->p_service_rec->service_data8[5] != 299 p_svcr->service_record.service_data8[5]) 300 return; 301 } 302 if ((comp_mask & IB_SR_COMPMASK_SDATA8_6) == IB_SR_COMPMASK_SDATA8_6) { 303 if (p_sr_item->p_service_rec->service_data8[6] != 304 p_svcr->service_record.service_data8[6]) 305 return; 306 } 307 308 if ((comp_mask & IB_SR_COMPMASK_SDATA8_7) == IB_SR_COMPMASK_SDATA8_7) { 309 if (p_sr_item->p_service_rec->service_data8[7] != 310 p_svcr->service_record.service_data8[7]) 311 return; 312 } 313 314 if ((comp_mask & IB_SR_COMPMASK_SDATA8_8) == IB_SR_COMPMASK_SDATA8_8) { 315 if (p_sr_item->p_service_rec->service_data8[8] != 316 p_svcr->service_record.service_data8[8]) 317 return; 318 } 319 320 if ((comp_mask & IB_SR_COMPMASK_SDATA8_9) == IB_SR_COMPMASK_SDATA8_9) { 321 if (p_sr_item->p_service_rec->service_data8[9] != 322 p_svcr->service_record.service_data8[9]) 323 return; 324 } 325 326 if ((comp_mask & IB_SR_COMPMASK_SDATA8_10) == IB_SR_COMPMASK_SDATA8_10) { 327 if (p_sr_item->p_service_rec->service_data8[10] != 328 p_svcr->service_record.service_data8[10]) 329 return; 330 } 331 332 if ((comp_mask & IB_SR_COMPMASK_SDATA8_11) == IB_SR_COMPMASK_SDATA8_11) { 333 if (p_sr_item->p_service_rec->service_data8[11] != 334 p_svcr->service_record.service_data8[11]) 335 return; 336 } 337 338 if ((comp_mask & IB_SR_COMPMASK_SDATA8_12) == IB_SR_COMPMASK_SDATA8_12) { 339 if (p_sr_item->p_service_rec->service_data8[12] != 340 p_svcr->service_record.service_data8[12]) 341 return; 342 } 343 if ((comp_mask & IB_SR_COMPMASK_SDATA8_13) == IB_SR_COMPMASK_SDATA8_13) { 344 if (p_sr_item->p_service_rec->service_data8[13] != 345 p_svcr->service_record.service_data8[13]) 346 return; 347 } 348 if ((comp_mask & IB_SR_COMPMASK_SDATA8_14) == IB_SR_COMPMASK_SDATA8_14) { 349 if (p_sr_item->p_service_rec->service_data8[14] != 350 p_svcr->service_record.service_data8[14]) 351 return; 352 } 353 if ((comp_mask & IB_SR_COMPMASK_SDATA8_15) == IB_SR_COMPMASK_SDATA8_15) { 354 if (p_sr_item->p_service_rec->service_data8[15] != 355 p_svcr->service_record.service_data8[15]) 356 return; 357 } 358 if ((comp_mask & IB_SR_COMPMASK_SDATA16_0) == IB_SR_COMPMASK_SDATA16_0) { 359 if (p_sr_item->p_service_rec->service_data16[0] != 360 p_svcr->service_record.service_data16[0]) 361 return; 362 } 363 if ((comp_mask & IB_SR_COMPMASK_SDATA16_1) == IB_SR_COMPMASK_SDATA16_1) { 364 if (p_sr_item->p_service_rec->service_data16[1] != 365 p_svcr->service_record.service_data16[1]) 366 return; 367 } 368 if ((comp_mask & IB_SR_COMPMASK_SDATA16_2) == IB_SR_COMPMASK_SDATA16_2) { 369 if (p_sr_item->p_service_rec->service_data16[2] != 370 p_svcr->service_record.service_data16[2]) 371 return; 372 } 373 if ((comp_mask & IB_SR_COMPMASK_SDATA16_3) == IB_SR_COMPMASK_SDATA16_3) { 374 if (p_sr_item->p_service_rec->service_data16[3] != 375 p_svcr->service_record.service_data16[3]) 376 return; 377 } 378 if ((comp_mask & IB_SR_COMPMASK_SDATA16_4) == IB_SR_COMPMASK_SDATA16_4) { 379 if (p_sr_item->p_service_rec->service_data16[4] != 380 p_svcr->service_record.service_data16[4]) 381 return; 382 } 383 if ((comp_mask & IB_SR_COMPMASK_SDATA16_5) == IB_SR_COMPMASK_SDATA16_5) { 384 if (p_sr_item->p_service_rec->service_data16[5] != 385 p_svcr->service_record.service_data16[5]) 386 return; 387 } 388 if ((comp_mask & IB_SR_COMPMASK_SDATA16_6) == IB_SR_COMPMASK_SDATA16_6) { 389 if (p_sr_item->p_service_rec->service_data16[6] != 390 p_svcr->service_record.service_data16[6]) 391 return; 392 } 393 if ((comp_mask & IB_SR_COMPMASK_SDATA16_7) == IB_SR_COMPMASK_SDATA16_7) { 394 if (p_sr_item->p_service_rec->service_data16[7] != 395 p_svcr->service_record.service_data16[7]) 396 return; 397 } 398 if ((comp_mask & IB_SR_COMPMASK_SDATA32_0) == IB_SR_COMPMASK_SDATA32_0) { 399 if (p_sr_item->p_service_rec->service_data32[0] != 400 p_svcr->service_record.service_data32[0]) 401 return; 402 } 403 if ((comp_mask & IB_SR_COMPMASK_SDATA32_1) == IB_SR_COMPMASK_SDATA32_1) { 404 if (p_sr_item->p_service_rec->service_data32[1] != 405 p_svcr->service_record.service_data32[1]) 406 return; 407 } 408 if ((comp_mask & IB_SR_COMPMASK_SDATA32_2) == IB_SR_COMPMASK_SDATA32_2) { 409 if (p_sr_item->p_service_rec->service_data32[2] != 410 p_svcr->service_record.service_data32[2]) 411 return; 412 } 413 if ((comp_mask & IB_SR_COMPMASK_SDATA32_3) == IB_SR_COMPMASK_SDATA32_3) { 414 if (p_sr_item->p_service_rec->service_data32[3] != 415 p_svcr->service_record.service_data32[3]) 416 return; 417 } 418 419 if ((comp_mask & IB_SR_COMPMASK_SDATA64_0) == IB_SR_COMPMASK_SDATA64_0) { 420 if (p_sr_item->p_service_rec->service_data64[0] != 421 p_svcr->service_record.service_data64[0]) 422 return; 423 } 424 if ((comp_mask & IB_SR_COMPMASK_SDATA64_1) == IB_SR_COMPMASK_SDATA64_1) { 425 if (p_sr_item->p_service_rec->service_data64[1] != 426 p_svcr->service_record.service_data64[1]) 427 return; 428 } 429 430 /* Check that the requester port has the pkey which is the service_pkey. 431 If not - then it cannot receive this ServiceRecord. */ 432 /* The check is relevant only if the service_pkey is valid */ 433 if (!ib_pkey_is_invalid(p_svcr->service_record.service_pkey)) { 434 if (!osm_physp_has_pkey(p_sr_item->sa->p_log, 435 p_svcr->service_record.service_pkey, 436 p_req_physp)) { 437 OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_VERBOSE, 438 "requester port doesn't have the service_pkey: 0x%X\n", 439 cl_ntoh16(p_svcr->service_record.service_pkey)); 440 return; 441 } 442 } 443 444 p_sr_pool_item = malloc(sizeof(*p_sr_pool_item)); 445 if (p_sr_pool_item == NULL) { 446 OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_ERROR, "ERR 2408: " 447 "Unable to acquire Service Record from pool\n"); 448 goto Exit; 449 } 450 451 p_sr_pool_item->service_rec = p_svcr->service_record; 452 453 cl_qlist_insert_tail(&p_sr_item->sr_list, &p_sr_pool_item->list_item); 454 455Exit: 456 return; 457} 458 459/********************************************************************** 460 **********************************************************************/ 461static void 462osm_sr_rcv_process_get_method(IN osm_sa_t * sa, 463 IN osm_madw_t * const p_madw) 464{ 465 ib_sa_mad_t *p_sa_mad; 466 ib_service_record_t *p_recvd_service_rec; 467 osm_sr_match_item_t sr_match_item; 468 osm_sr_search_ctxt_t context; 469 osm_physp_t *p_req_physp; 470 471 OSM_LOG_ENTER(sa->p_log); 472 473 CL_ASSERT(p_madw); 474 475 /* update the requester physical port. */ 476 p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, 477 sa->p_subn, 478 osm_madw_get_mad_addr_ptr 479 (p_madw)); 480 if (p_req_physp == NULL) { 481 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2409: " 482 "Cannot find requester physical port\n"); 483 goto Exit; 484 } 485 486 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 487 p_recvd_service_rec = 488 (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 489 490 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 491 osm_dump_service_record(sa->p_log, p_recvd_service_rec, 492 OSM_LOG_DEBUG); 493 494 cl_qlist_init(&sr_match_item.sr_list); 495 sr_match_item.p_service_rec = p_recvd_service_rec; 496 sr_match_item.comp_mask = p_sa_mad->comp_mask; 497 sr_match_item.sa = sa; 498 499 context.p_sr_item = &sr_match_item; 500 context.p_req_physp = p_req_physp; 501 502 /* Grab the lock */ 503 cl_plock_excl_acquire(sa->p_lock); 504 505 cl_qlist_apply_func(&sa->p_subn->sa_sr_list, 506 __get_matching_sr, &context); 507 508 cl_plock_release(sa->p_lock); 509 510 if (p_sa_mad->method == IB_MAD_METHOD_GET && 511 cl_qlist_count(&sr_match_item.sr_list) == 0) { 512 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 513 "No records matched the Service Record query\n"); 514 515 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); 516 goto Exit; 517 } 518 519 __osm_sr_rcv_respond(sa, p_madw, &sr_match_item.sr_list); 520 521Exit: 522 OSM_LOG_EXIT(sa->p_log); 523 return; 524} 525 526/********************************************************************** 527 **********************************************************************/ 528static void 529osm_sr_rcv_process_set_method(IN osm_sa_t * sa, 530 IN osm_madw_t * const p_madw) 531{ 532 ib_sa_mad_t *p_sa_mad; 533 ib_service_record_t *p_recvd_service_rec; 534 ib_net64_t comp_mask; 535 osm_svcr_t *p_svcr; 536 osm_sr_item_t *p_sr_item; 537 cl_qlist_t sr_list; 538 539 OSM_LOG_ENTER(sa->p_log); 540 541 CL_ASSERT(p_madw); 542 543 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 544 p_recvd_service_rec = 545 (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 546 547 comp_mask = p_sa_mad->comp_mask; 548 549 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 550 osm_dump_service_record(sa->p_log, p_recvd_service_rec, 551 OSM_LOG_DEBUG); 552 553 if ((comp_mask & (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID)) != 554 (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID)) { 555 OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 556 "Component Mask RID check failed for METHOD_SET\n"); 557 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 558 goto Exit; 559 } 560 561 /* if we were not provided with a service lease make it 562 infinite */ 563 if ((comp_mask & IB_SR_COMPMASK_SLEASE) != IB_SR_COMPMASK_SLEASE) { 564 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 565 "ServiceLease Component Mask not set - using infinite lease\n"); 566 p_recvd_service_rec->service_lease = 0xFFFFFFFF; 567 } 568 569 /* Grab the lock */ 570 cl_plock_excl_acquire(sa->p_lock); 571 572 /* If Record exists with matching RID */ 573 p_svcr = osm_svcr_get_by_rid(sa->p_subn, 574 sa->p_log, p_recvd_service_rec); 575 576 if (p_svcr == NULL) { 577 /* Create the instance of the osm_svcr_t object */ 578 p_svcr = osm_svcr_new(p_recvd_service_rec); 579 if (p_svcr == NULL) { 580 cl_plock_release(sa->p_lock); 581 582 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2411: " 583 "osm_svcr_get_by_rid failed\n"); 584 585 osm_sa_send_error(sa, p_madw, 586 IB_SA_MAD_STATUS_NO_RESOURCES); 587 goto Exit; 588 } 589 590 /* Add this new osm_svcr_t object to subnet object */ 591 osm_svcr_insert_to_db(sa->p_subn, sa->p_log, p_svcr); 592 593 } else { 594 /* Update the old instance of the osm_svcr_t object */ 595 osm_svcr_init(p_svcr, p_recvd_service_rec); 596 } 597 598 cl_plock_release(sa->p_lock); 599 600 if (p_recvd_service_rec->service_lease != 0xFFFFFFFF) { 601#if 0 602 cl_timer_trim(&sa->sr_timer, 603 p_recvd_service_rec->service_lease * 1000); 604#endif 605 /* This was a bug since no check was made to see if too long */ 606 /* just make sure the timer works - get a call back within a second */ 607 cl_timer_trim(&sa->sr_timer, 1000); 608 p_svcr->modified_time = cl_get_time_stamp_sec(); 609 } 610 611 p_sr_item = malloc(sizeof(*p_sr_item)); 612 if (p_sr_item == NULL) { 613 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2412: " 614 "Unable to acquire Service record\n"); 615 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); 616 goto Exit; 617 } 618 619 if ((comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY) { 620 /* Set the Default Service P_Key in the response */ 621 p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY; 622 } 623 624 p_sr_item->service_rec = *p_recvd_service_rec; 625 cl_qlist_init(&sr_list); 626 627 cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item); 628 629 __osm_sr_rcv_respond(sa, p_madw, &sr_list); 630 631Exit: 632 OSM_LOG_EXIT(sa->p_log); 633} 634 635/********************************************************************** 636 **********************************************************************/ 637static void 638osm_sr_rcv_process_delete_method(IN osm_sa_t * sa, 639 IN osm_madw_t * const p_madw) 640{ 641 ib_sa_mad_t *p_sa_mad; 642 ib_service_record_t *p_recvd_service_rec; 643 ib_net64_t comp_mask; 644 osm_svcr_t *p_svcr; 645 osm_sr_item_t *p_sr_item; 646 cl_qlist_t sr_list; 647 648 OSM_LOG_ENTER(sa->p_log); 649 650 CL_ASSERT(p_madw); 651 652 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 653 p_recvd_service_rec = 654 (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 655 656 comp_mask = p_sa_mad->comp_mask; 657 658 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 659 osm_dump_service_record(sa->p_log, p_recvd_service_rec, 660 OSM_LOG_DEBUG); 661 662 /* Grab the lock */ 663 cl_plock_excl_acquire(sa->p_lock); 664 665 /* If Record exists with matching RID */ 666 p_svcr = osm_svcr_get_by_rid(sa->p_subn, 667 sa->p_log, p_recvd_service_rec); 668 669 if (p_svcr == NULL) { 670 cl_plock_release(sa->p_lock); 671 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 672 "No records matched the RID\n"); 673 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); 674 goto Exit; 675 } else { 676 osm_svcr_remove_from_db(sa->p_subn, sa->p_log, p_svcr); 677 } 678 679 cl_plock_release(sa->p_lock); 680 681 p_sr_item = malloc(sizeof(*p_sr_item)); 682 if (p_sr_item == NULL) { 683 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2413: " 684 "Unable to acquire Service record\n"); 685 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); 686 goto Exit; 687 } 688 689 /* provide back the copy of the record */ 690 p_sr_item->service_rec = p_svcr->service_record; 691 cl_qlist_init(&sr_list); 692 693 cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item); 694 695 if (p_svcr) 696 osm_svcr_delete(p_svcr); 697 698 __osm_sr_rcv_respond(sa, p_madw, &sr_list); 699 700Exit: 701 OSM_LOG_EXIT(sa->p_log); 702 return; 703} 704 705/********************************************************************** 706 **********************************************************************/ 707void osm_sr_rcv_process(IN void *context, IN void *data) 708{ 709 osm_sa_t *sa = context; 710 osm_madw_t *p_madw = data; 711 ib_sa_mad_t *p_sa_mad; 712 boolean_t valid; 713 714 OSM_LOG_ENTER(sa->p_log); 715 716 CL_ASSERT(p_madw); 717 718 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 719 720 CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD); 721 722 switch (p_sa_mad->method) { 723 case IB_MAD_METHOD_SET: 724 valid = __validate_sr(sa, p_madw); 725 if (!valid) { 726 OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 727 "Component Mask check failed for set request\n"); 728 osm_sa_send_error(sa, p_madw, 729 IB_SA_MAD_STATUS_REQ_INVALID); 730 goto Exit; 731 } 732 osm_sr_rcv_process_set_method(sa, p_madw); 733 break; 734 case IB_MAD_METHOD_DELETE: 735 valid = __validate_sr(sa, p_madw); 736 if (!valid) { 737 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 738 "Component Mask check failed for delete request\n"); 739 osm_sa_send_error(sa, p_madw, 740 IB_SA_MAD_STATUS_REQ_INVALID); 741 goto Exit; 742 } 743 osm_sr_rcv_process_delete_method(sa, p_madw); 744 break; 745 case IB_MAD_METHOD_GET: 746 case IB_MAD_METHOD_GETTABLE: 747 osm_sr_rcv_process_get_method(sa, p_madw); 748 break; 749 default: 750 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 751 "Unsupported Method (%s)\n", 752 ib_get_sa_method_str(p_sa_mad->method)); 753 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 754 break; 755 } 756 757Exit: 758 OSM_LOG_EXIT(sa->p_log); 759} 760 761/********************************************************************** 762 **********************************************************************/ 763void osm_sr_rcv_lease_cb(IN void *context) 764{ 765 osm_sa_t *sa = context; 766 cl_list_item_t *p_list_item; 767 cl_list_item_t *p_next_list_item; 768 osm_svcr_t *p_svcr; 769 uint32_t curr_time; 770 uint32_t elapsed_time; 771 uint32_t trim_time = 20; /* maxiaml timer refresh is 20 seconds */ 772 773 OSM_LOG_ENTER(sa->p_log); 774 775 cl_plock_excl_acquire(sa->p_lock); 776 777 p_list_item = cl_qlist_head(&sa->p_subn->sa_sr_list); 778 779 while (p_list_item != cl_qlist_end(&sa->p_subn->sa_sr_list)) { 780 p_svcr = (osm_svcr_t *) p_list_item; 781 782 if (p_svcr->service_record.service_lease == 0xFFFFFFFF) { 783 p_list_item = cl_qlist_next(p_list_item); 784 continue; 785 } 786 787 /* current time in seconds */ 788 curr_time = cl_get_time_stamp_sec(); 789 /* elapsed time from last modify */ 790 elapsed_time = curr_time - p_svcr->modified_time; 791 /* but it can not be less then 1 */ 792 if (elapsed_time < 1) 793 elapsed_time = 1; 794 795 if (elapsed_time < p_svcr->lease_period) { 796 /* 797 Just update the service lease period 798 note: for simplicity we work with a uint32_t field 799 external to the network order lease_period of the MAD 800 */ 801 p_svcr->lease_period -= elapsed_time; 802 803 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 804 "Remaining time for Service Name:%s is:0x%X\n", 805 p_svcr->service_record.service_name, 806 p_svcr->lease_period); 807 808 p_svcr->modified_time = curr_time; 809 810 /* Update the trim timer */ 811 if (trim_time > p_svcr->lease_period) { 812 trim_time = p_svcr->lease_period; 813 if (trim_time < 1) 814 trim_time = 1; 815 } 816 817 p_list_item = cl_qlist_next(p_list_item); 818 continue; 819 820 } else { 821 p_next_list_item = cl_qlist_next(p_list_item); 822 823 /* Remove the service Record */ 824 osm_svcr_remove_from_db(sa->p_subn, 825 sa->p_log, p_svcr); 826 827 osm_svcr_delete(p_svcr); 828 829 p_list_item = p_next_list_item; 830 continue; 831 } 832 } 833 834 /* Release the Lock */ 835 cl_plock_release(sa->p_lock); 836 837 if (trim_time != 0xFFFFFFFF) { 838 cl_timer_trim(&sa->sr_timer, trim_time * 1000); /* Convert to milli seconds */ 839 } 840 841 OSM_LOG_EXIT(sa->p_log); 842} 843