1 /* 2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2015 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_physp_t. 39 * This object represents an Infiniband Port. 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 <stdlib.h> 48 #include <string.h> 49 #include <complib/cl_debug.h> 50 #include <iba/ib_types.h> 51 #include <opensm/osm_file_ids.h> 52 #define FILE_ID OSM_FILE_PORT_C 53 #include <opensm/osm_port.h> 54 #include <opensm/osm_node.h> 55 #include <opensm/osm_madw.h> 56 #include <opensm/osm_switch.h> 57 #include <opensm/osm_db_pack.h> 58 #include <opensm/osm_sm.h> 59 60 void osm_physp_construct(IN osm_physp_t * p_physp) 61 { 62 memset(p_physp, 0, sizeof(*p_physp)); 63 osm_dr_path_construct(&p_physp->dr_path); 64 cl_ptr_vector_construct(&p_physp->slvl_by_port); 65 osm_pkey_tbl_construct(&p_physp->pkeys); 66 } 67 68 void osm_physp_destroy(IN osm_physp_t * p_physp) 69 { 70 size_t num_slvl, i; 71 72 /* the physp might be uninitialized */ 73 if (p_physp->port_guid) { 74 if (p_physp->p_guids) 75 free(p_physp->p_guids); 76 77 /* free the SL2VL Tables */ 78 num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port); 79 for (i = 0; i < num_slvl; i++) 80 free(cl_ptr_vector_get(&p_physp->slvl_by_port, i)); 81 cl_ptr_vector_destroy(&p_physp->slvl_by_port); 82 83 /* free the P_Key Tables */ 84 osm_pkey_tbl_destroy(&p_physp->pkeys); 85 86 memset(p_physp, 0, sizeof(*p_physp)); 87 osm_dr_path_construct(&p_physp->dr_path); /* clear dr_path */ 88 } 89 } 90 91 void osm_physp_init(IN osm_physp_t * p_physp, IN ib_net64_t port_guid, 92 IN uint8_t port_num, IN const struct osm_node *p_node, 93 IN osm_bind_handle_t h_bind, IN uint8_t hop_count, 94 IN const uint8_t * p_initial_path) 95 { 96 uint16_t num_slvl, i; 97 ib_slvl_table_t *p_slvl; 98 99 CL_ASSERT(p_node); 100 101 osm_physp_construct(p_physp); 102 p_physp->port_guid = port_guid; 103 p_physp->port_num = port_num; 104 p_physp->healthy = TRUE; 105 p_physp->need_update = 2; 106 p_physp->p_node = (struct osm_node *)p_node; 107 108 osm_dr_path_init(&p_physp->dr_path, hop_count, p_initial_path); 109 110 /* allocate enough SL2VL tables */ 111 if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) 112 /* we need node num ports + 1 SL2VL tables */ 113 num_slvl = osm_node_get_num_physp(p_node) + 1; 114 else 115 /* An end node - we need only one SL2VL */ 116 num_slvl = 1; 117 118 cl_ptr_vector_init(&p_physp->slvl_by_port, num_slvl, 1); 119 for (i = 0; i < num_slvl; i++) { 120 p_slvl = (ib_slvl_table_t *) malloc(sizeof(ib_slvl_table_t)); 121 if (!p_slvl) 122 break; 123 memset(p_slvl, 0, sizeof(ib_slvl_table_t)); 124 cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl); 125 } 126 127 /* initialize the pkey table */ 128 osm_pkey_tbl_init(&p_physp->pkeys); 129 } 130 131 void osm_port_delete(IN OUT osm_port_t ** pp_port) 132 { 133 free(*pp_port); 134 *pp_port = NULL; 135 } 136 137 osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni, 138 IN osm_node_t * p_parent_node) 139 { 140 osm_port_t *p_port; 141 ib_net64_t port_guid; 142 osm_physp_t *p_physp; 143 uint8_t port_num; 144 145 p_port = malloc(sizeof(*p_port)); 146 if (!p_port) 147 return NULL; 148 149 memset(p_port, 0, sizeof(*p_port)); 150 cl_qlist_init(&p_port->mcm_list); 151 p_port->p_node = (struct osm_node *)p_parent_node; 152 port_guid = p_ni->port_guid; 153 p_port->guid = port_guid; 154 port_num = p_ni->node_type == IB_NODE_TYPE_SWITCH ? 155 0 : ib_node_info_get_local_port_num(p_ni); 156 157 /* 158 Get the pointers to the physical node objects "owned" by this 159 logical port GUID. 160 For switches, port '0' is owned; for HCA's and routers, 161 only the singular part that has this GUID is owned. 162 */ 163 p_physp = osm_node_get_physp_ptr(p_parent_node, port_num); 164 if (!p_physp) { 165 osm_port_delete(&p_port); 166 return NULL; 167 } 168 169 CL_ASSERT(port_guid == osm_physp_get_port_guid(p_physp)); 170 p_port->p_physp = p_physp; 171 172 return p_port; 173 } 174 175 void osm_port_get_lid_range_ho(IN const osm_port_t * p_port, 176 IN uint16_t * p_min_lid, IN uint16_t * p_max_lid) 177 { 178 uint8_t lmc; 179 180 *p_min_lid = cl_ntoh16(osm_port_get_base_lid(p_port)); 181 lmc = osm_port_get_lmc(p_port); 182 *p_max_lid = (uint16_t) (*p_min_lid + (1 << lmc) - 1); 183 } 184 185 uint8_t osm_physp_calc_link_mtu(IN osm_log_t * p_log, 186 IN const osm_physp_t * p_physp, 187 IN uint8_t current_mtu) 188 { 189 const osm_physp_t *p_remote_physp; 190 uint8_t mtu; 191 uint8_t remote_mtu; 192 193 OSM_LOG_ENTER(p_log); 194 195 p_remote_physp = osm_physp_get_remote(p_physp); 196 if (p_remote_physp) { 197 /* use the available MTU */ 198 mtu = ib_port_info_get_mtu_cap(&p_physp->port_info); 199 200 remote_mtu = 201 ib_port_info_get_mtu_cap(&p_remote_physp->port_info); 202 203 OSM_LOG(p_log, OSM_LOG_DEBUG, 204 "Remote port 0x%016" PRIx64 " port = %u : " 205 "MTU = %u. This Port MTU: %u\n", 206 cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)), 207 osm_physp_get_port_num(p_remote_physp), 208 remote_mtu, mtu); 209 210 if (mtu != remote_mtu) { 211 if (mtu > remote_mtu) 212 mtu = remote_mtu; 213 if (mtu != current_mtu) 214 OSM_LOG(p_log, OSM_LOG_VERBOSE, 215 "MTU mismatch between ports." 216 "\n\t\t\t\tPort 0x%016" PRIx64 ", port %u" 217 " and port 0x%016" PRIx64 ", port %u." 218 "\n\t\t\t\tUsing lower MTU of %u\n", 219 cl_ntoh64(osm_physp_get_port_guid(p_physp)), 220 osm_physp_get_port_num(p_physp), 221 cl_ntoh64(osm_physp_get_port_guid 222 (p_remote_physp)), 223 osm_physp_get_port_num(p_remote_physp), mtu); 224 } 225 } else 226 mtu = ib_port_info_get_neighbor_mtu(&p_physp->port_info); 227 228 if (mtu == 0) { 229 OSM_LOG(p_log, OSM_LOG_DEBUG, "ERR 4101: " 230 "Invalid MTU = 0. Forcing correction to 256\n"); 231 mtu = 1; 232 } 233 234 OSM_LOG_EXIT(p_log); 235 return mtu; 236 } 237 238 uint8_t osm_physp_calc_link_op_vls(IN osm_log_t * p_log, 239 IN const osm_subn_t * p_subn, 240 IN const osm_physp_t * p_physp, 241 IN uint8_t current_op_vls) 242 { 243 const osm_physp_t *p_remote_physp; 244 uint8_t op_vls; 245 uint8_t remote_op_vls; 246 247 OSM_LOG_ENTER(p_log); 248 249 p_remote_physp = osm_physp_get_remote(p_physp); 250 if (p_remote_physp) { 251 /* use the available VLCap */ 252 op_vls = ib_port_info_get_vl_cap(&p_physp->port_info); 253 254 remote_op_vls = 255 ib_port_info_get_vl_cap(&p_remote_physp->port_info); 256 257 OSM_LOG(p_log, OSM_LOG_DEBUG, 258 "Remote port 0x%016" PRIx64 " port = 0x%X : " 259 "VL_CAP = %u. This port VL_CAP = %u\n", 260 cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)), 261 osm_physp_get_port_num(p_remote_physp), 262 remote_op_vls, op_vls); 263 264 if (op_vls != remote_op_vls) { 265 if (op_vls > remote_op_vls) 266 op_vls = remote_op_vls; 267 if (op_vls != current_op_vls) 268 OSM_LOG(p_log, OSM_LOG_VERBOSE, 269 "OP_VLS mismatch between ports." 270 "\n\t\t\t\tPort 0x%016" PRIx64 ", port 0x%X" 271 " and port 0x%016" PRIx64 ", port 0x%X." 272 "\n\t\t\t\tUsing lower OP_VLS of %u\n", 273 cl_ntoh64(osm_physp_get_port_guid(p_physp)), 274 osm_physp_get_port_num(p_physp), 275 cl_ntoh64(osm_physp_get_port_guid 276 (p_remote_physp)), 277 osm_physp_get_port_num(p_remote_physp), op_vls); 278 } 279 } else 280 op_vls = ib_port_info_get_op_vls(&p_physp->port_info); 281 282 if (op_vls == 0) { 283 /* for non compliant implementations */ 284 OSM_LOG(p_log, OSM_LOG_VERBOSE, 285 "Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n"); 286 op_vls = 1; 287 } 288 289 /* support user limitation of max_op_vls */ 290 if (op_vls > p_subn->opt.max_op_vls) 291 op_vls = p_subn->opt.max_op_vls; 292 293 OSM_LOG_EXIT(p_log); 294 return op_vls; 295 } 296 297 static inline uint64_t ptr_to_key(void const *p) 298 { 299 uint64_t k = 0; 300 301 memcpy(&k, p, sizeof(void *)); 302 return k; 303 } 304 305 static inline void *key_to_ptr(uint64_t k) 306 { 307 void *p = 0; 308 309 memcpy(&p, &k, sizeof(void *)); 310 return p; 311 } 312 313 /********************************************************************** 314 Traverse the fabric from the SM node following the DR path given and 315 add every phys port traversed to the map. Avoid tracking the first and 316 last phys ports (going into the first switch and into the target port). 317 **********************************************************************/ 318 static cl_status_t physp_get_dr_physp_set(IN osm_log_t * p_log, 319 IN osm_subn_t const *p_subn, 320 IN osm_dr_path_t const *p_path, 321 OUT cl_map_t * p_physp_map) 322 { 323 osm_port_t *p_port; 324 osm_physp_t *p_physp; 325 osm_node_t *p_node; 326 uint8_t hop; 327 cl_status_t status = CL_SUCCESS; 328 329 OSM_LOG_ENTER(p_log); 330 331 /* find the OSM node */ 332 p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid); 333 if (!p_port) { 334 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4103: " 335 "Failed to find the SM own port by guid\n"); 336 status = CL_ERROR; 337 goto Exit; 338 } 339 340 /* get the node of the SM */ 341 p_node = p_port->p_node; 342 343 /* 344 traverse the path adding the nodes to the table 345 start after the first dummy hop and stop just before the 346 last one 347 */ 348 for (hop = 1; hop < p_path->hop_count - 1; hop++) { 349 /* go out using the phys port of the path */ 350 p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]); 351 352 /* make sure we got a valid port and it has a remote port */ 353 if (!p_physp) { 354 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4104: " 355 "DR Traversal stopped on invalid port at hop:%u\n", 356 hop); 357 status = CL_ERROR; 358 goto Exit; 359 } 360 361 /* we track the ports we go out along the path */ 362 if (hop > 1) 363 cl_map_insert(p_physp_map, ptr_to_key(p_physp), NULL); 364 365 OSM_LOG(p_log, OSM_LOG_DEBUG, 366 "Traversed through node: 0x%016" PRIx64 367 " port:%u\n", 368 cl_ntoh64(p_node->node_info.node_guid), 369 p_path->path[hop]); 370 371 if (!(p_physp = osm_physp_get_remote(p_physp))) { 372 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4106: " 373 "DR Traversal stopped on missing remote physp at hop:%u\n", 374 hop); 375 status = CL_ERROR; 376 goto Exit; 377 } 378 379 p_node = osm_physp_get_node_ptr(p_physp); 380 } 381 382 Exit: 383 OSM_LOG_EXIT(p_log); 384 return status; 385 } 386 387 static void physp_update_new_dr_path(IN osm_physp_t const *p_dest_physp, 388 IN cl_map_t * p_visited_map, 389 IN osm_bind_handle_t * h_bind) 390 { 391 cl_list_t tmpPortsList; 392 osm_physp_t *p_physp, *p_src_physp = NULL; 393 uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; 394 uint8_t i = 0; 395 osm_dr_path_t *p_dr_path; 396 397 cl_list_construct(&tmpPortsList); 398 cl_list_init(&tmpPortsList, 10); 399 400 cl_list_insert_head(&tmpPortsList, p_dest_physp); 401 /* get the output port where we need to come from */ 402 p_physp = (osm_physp_t *) cl_map_get(p_visited_map, 403 ptr_to_key(p_dest_physp)); 404 while (p_physp != NULL) { 405 cl_list_insert_head(&tmpPortsList, p_physp); 406 /* get the input port through where we reached the output port */ 407 p_src_physp = p_physp; 408 p_physp = (osm_physp_t *) cl_map_get(p_visited_map, 409 ptr_to_key(p_physp)); 410 /* if we reached a null p_physp - this means we are at the begining 411 of the path. Break. */ 412 if (p_physp == NULL) 413 break; 414 /* get the output port */ 415 p_physp = (osm_physp_t *) cl_map_get(p_visited_map, 416 ptr_to_key(p_physp)); 417 } 418 419 memset(path_array, 0, sizeof(path_array)); 420 p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList); 421 while (p_physp != NULL) { 422 i++; 423 path_array[i] = p_physp->port_num; 424 p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList); 425 } 426 if (p_src_physp) { 427 p_dr_path = osm_physp_get_dr_path_ptr(p_src_physp); 428 osm_dr_path_init(p_dr_path, i, path_array); 429 } 430 431 cl_list_destroy(&tmpPortsList); 432 } 433 434 void osm_physp_replace_dr_path_with_alternate_dr_path(IN osm_log_t * p_log, 435 IN osm_subn_t const 436 *p_subn, IN osm_physp_t const 437 *p_dest_physp, 438 IN osm_bind_handle_t * 439 h_bind) 440 { 441 cl_map_t physp_map; 442 cl_map_t visited_map; 443 osm_dr_path_t *p_dr_path; 444 cl_list_t *p_currPortsList; 445 cl_list_t *p_nextPortsList; 446 osm_port_t *p_port; 447 osm_physp_t *p_physp, *p_remote_physp; 448 ib_net64_t port_guid; 449 boolean_t next_list_is_full = TRUE, reached_dest = FALSE; 450 uint8_t num_ports, port_num; 451 452 p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t)); 453 if (!p_nextPortsList) 454 return; 455 456 /* 457 initialize the map of all port participating in current dr path 458 not including first and last switches 459 */ 460 cl_map_construct(&physp_map); 461 cl_map_init(&physp_map, 4); 462 cl_map_construct(&visited_map); 463 cl_map_init(&visited_map, 4); 464 p_dr_path = osm_physp_get_dr_path_ptr(p_dest_physp); 465 physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map); 466 467 /* 468 BFS from OSM port until we find the target physp but avoid 469 going through mapped ports 470 */ 471 cl_list_construct(p_nextPortsList); 472 cl_list_init(p_nextPortsList, 10); 473 474 port_guid = p_subn->sm_port_guid; 475 476 CL_ASSERT(port_guid); 477 478 p_port = osm_get_port_by_guid(p_subn, port_guid); 479 if (!p_port) { 480 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4105: No SM port object\n"); 481 goto Exit; 482 } 483 484 /* 485 HACK: We are assuming SM is running on HCA, so when getting the default 486 port we'll get the port connected to the rest of the subnet. If SM is 487 running on SWITCH - we should try to get a dr path from all switch ports. 488 */ 489 p_physp = p_port->p_physp; 490 491 CL_ASSERT(p_physp); 492 493 cl_list_insert_tail(p_nextPortsList, p_physp); 494 495 while (next_list_is_full == TRUE) { 496 next_list_is_full = FALSE; 497 p_currPortsList = p_nextPortsList; 498 p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t)); 499 if (!p_nextPortsList) { 500 p_nextPortsList = p_currPortsList; 501 goto Exit; 502 } 503 cl_list_construct(p_nextPortsList); 504 cl_list_init(p_nextPortsList, 10); 505 p_physp = (osm_physp_t *) cl_list_remove_head(p_currPortsList); 506 while (p_physp != NULL) { 507 /* If we are in a switch - need to go out through all 508 the other physical ports of the switch */ 509 num_ports = osm_node_get_num_physp(p_physp->p_node); 510 511 for (port_num = 1; port_num < num_ports; port_num++) { 512 if (osm_node_get_type(p_physp->p_node) == 513 IB_NODE_TYPE_SWITCH) 514 p_remote_physp = 515 osm_node_get_physp_ptr(p_physp-> 516 p_node, 517 port_num); 518 else 519 /* this is HCA or router - the remote port is just the port connected 520 on the other side */ 521 p_remote_physp = 522 p_physp->p_remote_physp; 523 524 /* 525 make sure that all of the following occurred: 526 1. The port isn't NULL 527 2. This is not the port we came from 528 3. The port is not in the physp_map 529 4. This port haven't been visited before 530 */ 531 if (p_remote_physp && 532 p_remote_physp != p_physp && 533 cl_map_get(&physp_map, 534 ptr_to_key(p_remote_physp)) 535 == NULL 536 && cl_map_get(&visited_map, 537 ptr_to_key 538 (p_remote_physp)) == NULL) { 539 /* Insert the port into the visited_map, and save its source port */ 540 cl_map_insert(&visited_map, 541 ptr_to_key 542 (p_remote_physp), 543 p_physp); 544 545 /* Is this the p_dest_physp? */ 546 if (p_remote_physp == p_dest_physp) { 547 /* update the new dr path */ 548 physp_update_new_dr_path 549 (p_dest_physp, &visited_map, 550 h_bind); 551 reached_dest = TRUE; 552 break; 553 } 554 555 /* add the p_remote_physp to the nextPortsList */ 556 cl_list_insert_tail(p_nextPortsList, 557 p_remote_physp); 558 next_list_is_full = TRUE; 559 } 560 } 561 562 p_physp = (osm_physp_t *) 563 cl_list_remove_head(p_currPortsList); 564 if (reached_dest == TRUE) { 565 /* free the rest of the currPortsList */ 566 while (p_physp != NULL) 567 p_physp = (osm_physp_t *) 568 cl_list_remove_head 569 (p_currPortsList); 570 /* free the nextPortsList, if items were added to it */ 571 p_physp = (osm_physp_t *) 572 cl_list_remove_head(p_nextPortsList); 573 while (p_physp != NULL) 574 p_physp = (osm_physp_t *) 575 cl_list_remove_head 576 (p_nextPortsList); 577 next_list_is_full = FALSE; 578 } 579 } 580 cl_list_destroy(p_currPortsList); 581 free(p_currPortsList); 582 } 583 584 /* cleanup */ 585 Exit: 586 cl_list_destroy(p_nextPortsList); 587 free(p_nextPortsList); 588 cl_map_destroy(&physp_map); 589 cl_map_destroy(&visited_map); 590 } 591 592 boolean_t osm_link_is_healthy(IN const osm_physp_t * p_physp) 593 { 594 osm_physp_t *p_remote_physp; 595 596 CL_ASSERT(p_physp); 597 p_remote_physp = p_physp->p_remote_physp; 598 if (p_remote_physp != NULL) 599 return ((p_physp->healthy) & (p_remote_physp->healthy)); 600 /* the other side is not known - consider the link as healthy */ 601 return TRUE; 602 } 603 604 void osm_physp_set_pkey_tbl(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, 605 IN osm_physp_t * p_physp, 606 IN ib_pkey_table_t * p_pkey_tbl, 607 IN uint16_t block_num, 608 IN boolean_t is_set) 609 { 610 uint16_t max_blocks; 611 612 CL_ASSERT(p_pkey_tbl); 613 /* 614 (14.2.5.7) - the block number valid values are 0-2047, and are 615 further limited by the size of the P_Key table specified by 616 the PartitionCap on the node. 617 */ 618 if (!p_physp->p_node->sw || p_physp->port_num == 0) 619 /* 620 The maximum blocks is defined in the node info: partition cap 621 for CA, router, and switch management ports. 622 */ 623 max_blocks = 624 (cl_ntoh16(p_physp->p_node->node_info.partition_cap) + 625 IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) 626 / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; 627 else 628 /* 629 This is a switch, and not a management port. The maximum 630 blocks is defined in the switch info: partition enforcement 631 cap. 632 */ 633 max_blocks = 634 (cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) + 635 IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 636 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; 637 638 if (block_num >= max_blocks) { 639 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4108: " 640 "Got illegal update for block number:%u max:%u " 641 "for GUID: %" PRIx64 " port number:%u\n", 642 block_num, max_blocks, 643 cl_ntoh64(p_physp->p_node->node_info.node_guid), 644 p_physp->port_num); 645 return; 646 } 647 648 /* decrement block received counter */ 649 if(!is_set) 650 p_physp->pkeys.rcv_blocks_cnt--; 651 osm_pkey_tbl_set(&p_physp->pkeys, block_num, p_pkey_tbl, 652 p_subn->opt.allow_both_pkeys); 653 } 654 655 osm_alias_guid_t *osm_alias_guid_new(IN const ib_net64_t alias_guid, 656 IN osm_port_t *p_base_port) 657 { 658 osm_alias_guid_t *p_alias_guid; 659 660 p_alias_guid = calloc(1, sizeof(*p_alias_guid)); 661 if (p_alias_guid) { 662 p_alias_guid->alias_guid = alias_guid; 663 p_alias_guid->p_base_port = p_base_port; 664 } 665 return p_alias_guid; 666 } 667 668 void osm_alias_guid_delete(IN OUT osm_alias_guid_t ** pp_alias_guid) 669 { 670 free(*pp_alias_guid); 671 *pp_alias_guid = NULL; 672 } 673 674 void osm_physp_set_port_info(IN osm_physp_t * p_physp, 675 IN const ib_port_info_t * p_pi, 676 IN const struct osm_sm * p_sm) 677 { 678 CL_ASSERT(p_pi); 679 CL_ASSERT(osm_physp_is_valid(p_physp)); 680 681 if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) { 682 /* If PortState is down, only copy PortState */ 683 /* and PortPhysicalState per C14-24-2.1 */ 684 ib_port_info_set_port_state(&p_physp->port_info, IB_LINK_DOWN); 685 ib_port_info_set_port_phys_state 686 (ib_port_info_get_port_phys_state(p_pi), 687 &p_physp->port_info); 688 } else { 689 p_physp->port_info = *p_pi; 690 691 /* The MKey in p_pi can only be considered valid if it's 692 * for a HCA/router or switch port 0, and it's either 693 * non-zero or the MKeyProtect bits are also zero. 694 */ 695 if ((osm_node_get_type(p_physp->p_node) != 696 IB_NODE_TYPE_SWITCH || p_physp->port_num == 0) && 697 (p_pi->m_key != 0 || ib_port_info_get_mpb(p_pi) == 0)) 698 osm_db_guid2mkey_set(p_sm->p_subn->p_g2m, 699 cl_ntoh64(p_physp->port_guid), 700 cl_ntoh64(p_pi->m_key)); 701 } 702 } 703