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