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