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 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
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)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
osm_physp_calc_link_mtu(IN osm_log_t * p_log,IN const osm_physp_t * p_physp,IN uint8_t current_mtu)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
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)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
ptr_to_key(void const * p)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
key_to_ptr(uint64_t k)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 **********************************************************************/
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)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
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)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
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)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
osm_link_is_healthy(IN const osm_physp_t * p_physp)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
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)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
osm_alias_guid_new(IN const ib_net64_t alias_guid,IN osm_port_t * p_base_port)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
osm_alias_guid_delete(IN OUT osm_alias_guid_t ** pp_alias_guid)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
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)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