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.
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:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
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.
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
38 * Various OpenSM dumpers
43 #endif /* HAVE_CONFIG_H */
49 #include <iba/ib_types.h>
50 #include <complib/cl_qmap.h>
51 #include <complib/cl_debug.h>
52 #include <opensm/osm_opensm.h>
53 #include <opensm/osm_log.h>
54 #include <opensm/osm_node.h>
55 #include <opensm/osm_switch.h>
56 #include <opensm/osm_helper.h>
57 #include <opensm/osm_msgdef.h>
58 #include <opensm/osm_opensm.h>
60 static void dump_ucast_path_distribution(cl_map_item_t * p_map_item,
61 FILE *file, void *cxt)
64 osm_node_t *p_remote_node;
68 ib_net64_t remote_guid_ho;
69 osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
71 p_node = p_sw->p_node;
72 num_ports = p_sw->num_ports;
74 fprintf(file, "dump_ucast_path_distribution: Switch 0x%" PRIx64 "\n"
75 "Port : Path Count Through Port",
76 cl_ntoh64(osm_node_get_node_guid(p_node)));
78 for (i = 0; i < num_ports; i++) {
79 num_paths = osm_switch_path_count_get(p_sw, i);
80 fprintf(file, "\n %03u : %u", i, num_paths);
82 fprintf(file, " (switch management port)");
86 p_remote_node = osm_node_get_remote_node(p_node, i, NULL);
87 if (p_remote_node == NULL)
91 cl_ntoh64(osm_node_get_node_guid(p_remote_node));
93 switch (osm_node_get_type(p_remote_node)) {
94 case IB_NODE_TYPE_SWITCH:
95 fprintf(file, " (link to switch");
97 case IB_NODE_TYPE_ROUTER:
98 fprintf(file, " (link to router");
100 case IB_NODE_TYPE_CA:
101 fprintf(file, " (link to CA");
104 fprintf(file, " (link to unknown node type");
108 fprintf(file, " 0x%" PRIx64 ")", remote_guid_ho);
114 static void dump_ucast_routes(cl_map_item_t *p_map_item, FILE *file, void *cxt)
116 const osm_node_t *p_node;
123 uint16_t lid_ho, base_lid;
124 boolean_t direct_route_exists = FALSE;
126 osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
127 osm_opensm_t *p_osm = cxt;
129 p_node = p_sw->p_node;
131 max_lid_ho = p_sw->max_lid_ho;
133 fprintf(file, "__osm_ucast_mgr_dump_ucast_routes: "
134 "Switch 0x%016" PRIx64 "\nLID : Port : Hops : Optimal\n",
135 cl_ntoh64(osm_node_get_node_guid(p_node)));
137 dor = (p_osm->routing_engine_used == OSM_ROUTING_ENGINE_TYPE_DOR);
139 for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) {
140 fprintf(file, "0x%04X : ", lid_ho);
142 p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid_ho);
144 fprintf(file, "UNREACHABLE\n");
148 port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
149 if (port_num == OSM_NO_PATH) {
151 This may occur if there are 'holes' in the existing
152 LID assignments. Running SM with --reassign_lids
153 will reassign and compress the LID range. The
154 subnet should work fine either way.
156 fprintf(file, "UNREACHABLE\n");
160 Switches can lie about which port routes a given
161 lid due to a recent reconfiguration of the subnet.
162 Therefore, ensure that the hop count is better than
165 if (p_port->p_node->sw) {
166 /* Target LID is switch.
167 Get its base lid and check hop count for this base LID only. */
168 base_lid = osm_node_get_base_lid(p_port->p_node, 0);
169 base_lid = cl_ntoh16(base_lid);
171 osm_switch_get_hop_count(p_sw, base_lid, port_num);
173 /* Target LID is not switch (CA or router).
174 Check if we have route to this target from current switch. */
176 osm_switch_get_hop_count(p_sw, lid_ho, port_num);
177 if (num_hops != OSM_NO_PATH) {
178 direct_route_exists = TRUE;
181 osm_physp_t *p_physp = p_port->p_physp;
183 if (!p_physp || !p_physp->p_remote_physp ||
184 !p_physp->p_remote_physp->p_node->sw)
185 num_hops = OSM_NO_PATH;
188 osm_node_get_base_lid(p_physp->
191 base_lid = cl_ntoh16(base_lid);
193 p_physp->p_remote_physp->p_node->
196 osm_switch_get_hop_count(p_sw,
203 if (num_hops == OSM_NO_PATH) {
204 fprintf(file, "UNREACHABLE\n");
208 best_hops = osm_switch_get_least_hops(p_sw, base_lid);
209 if (!p_port->p_node->sw && !direct_route_exists) {
214 fprintf(file, "%03u : %02u : ", port_num, num_hops);
216 if (best_hops == num_hops)
217 fprintf(file, "yes");
219 /* No LMC Optimization */
220 best_port = osm_switch_recommend_path(p_sw, p_port,
223 fprintf(file, "No %u hop path possible via port %u!",
224 best_hops, best_port);
231 static void dump_mcast_routes(cl_map_item_t *p_map_item, FILE *file, void *cxt)
233 osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
234 osm_mcast_tbl_t *p_tbl;
236 int16_t mlid_start_ho;
237 uint8_t position = 0;
238 int16_t block_num = 0;
239 boolean_t first_mlid;
240 boolean_t first_port;
241 const osm_node_t *p_node;
247 p_node = p_sw->p_node;
249 p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
251 sprintf(sw_hdr, "\nSwitch 0x%016" PRIx64 "\nLID : Out Port(s)\n",
252 cl_ntoh64(osm_node_get_node_guid(p_node)));
254 while (block_num <= p_tbl->max_block_in_use) {
255 mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
256 for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) {
257 mlid_ho = mlid_start_ho + i;
260 sprintf(mlid_hdr, "0x%04X :",
261 mlid_ho + IB_LID_MCAST_START_HO);
262 while (position <= p_tbl->max_position) {
265 p_mask_tbl)[mlid_ho][position]);
266 if (mask_entry == 0) {
270 for (j = 0; j < 16; j++) {
271 if ((1 << j) & mask_entry) {
282 fprintf(file, " 0x%03X ",
283 j + (position * 16));
288 if (first_port == FALSE)
295 static void dump_lid_matrix(cl_map_item_t *p_map_item, FILE *file, void *cxt)
297 osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
298 osm_opensm_t *p_osm = cxt;
299 osm_node_t *p_node = p_sw->p_node;
300 unsigned max_lid = p_sw->max_lid_ho;
301 unsigned max_port = p_sw->num_ports;
305 fprintf(file, "Switch: guid 0x%016" PRIx64 "\n",
306 cl_ntoh64(osm_node_get_node_guid(p_node)));
307 for (lid = 1; lid <= max_lid; lid++) {
309 if (osm_switch_get_least_hops(p_sw, lid) == OSM_NO_PATH)
311 fprintf(file, "0x%04x:", lid);
312 for (port = 0; port < max_port; port++)
313 fprintf(file, " %02x",
314 osm_switch_get_hop_count(p_sw, lid, port));
315 p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid);
317 fprintf(file, " # portguid 0x016%" PRIx64,
318 cl_ntoh64(osm_port_get_guid(p_port)));
323 static void dump_ucast_lfts(cl_map_item_t *p_map_item, FILE *file, void *cxt)
325 osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
326 osm_opensm_t *p_osm = cxt;
327 osm_node_t *p_node = p_sw->p_node;
328 unsigned max_lid = p_sw->max_lid_ho;
329 unsigned max_port = p_sw->num_ports;
333 fprintf(file, "Unicast lids [0-%u] of switch Lid %u guid 0x%016"
334 PRIx64 " (\'%s\'):\n",
335 max_lid, cl_ntoh16(osm_node_get_base_lid(p_node, 0)),
336 cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc);
337 for (lid = 0; lid <= max_lid; lid++) {
339 port = osm_switch_get_port_by_lid(p_sw, lid);
341 if (port >= max_port)
344 fprintf(file, "0x%04x %03u # ", lid, port);
346 p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid);
348 p_node = p_port->p_node;
349 fprintf(file, "%s portguid 0x%016" PRIx64 ": \'%s\'",
350 ib_get_node_type_str(osm_node_get_type(p_node)),
351 cl_ntoh64(osm_port_get_guid(p_port)),
354 fprintf(file, "unknown node and type");
357 fprintf(file, "%u lids dumped\n", max_lid);
360 static void dump_topology_node(cl_map_item_t *p_map_item, FILE *file, void *cxt)
362 osm_node_t *p_node = (osm_node_t *) p_map_item;
364 osm_node_t *p_nbnode;
365 osm_physp_t *p_physp, *p_default_physp, *p_rphysp;
366 uint8_t link_speed_act;
368 if (!p_node->node_info.num_ports)
371 for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) {
374 p_physp = osm_node_get_physp_ptr(p_node, cPort);
378 p_rphysp = p_physp->p_remote_physp;
382 CL_ASSERT(cPort == p_physp->port_num);
384 if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
385 p_default_physp = osm_node_get_physp_ptr(p_node, 0);
387 p_default_physp = p_physp;
389 fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
390 " NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
391 " VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
392 p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ?
393 "SW" : p_node->node_info.node_type ==
394 IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type ==
395 IB_NODE_TYPE_ROUTER ? "Rt" : "**",
396 p_default_physp->port_info.base_lid ==
397 p_default_physp->port_info.
398 master_sm_base_lid ? "-SM" : "",
399 p_node->node_info.num_ports,
400 cl_ntoh64(p_node->node_info.sys_guid),
401 cl_ntoh64(p_node->node_info.node_guid),
402 cl_ntoh64(p_physp->port_guid),
403 cl_ntoh32(ib_node_info_get_vendor_id
404 (&p_node->node_info)),
405 cl_ntoh16(p_node->node_info.device_id),
406 cl_ntoh32(p_node->node_info.revision),
408 cl_ntoh16(p_default_physp->port_info.base_lid), cPort);
410 p_nbnode = p_rphysp->p_node;
412 if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH)
413 p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0);
415 p_default_physp = p_rphysp;
417 fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
418 " NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
419 " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
420 p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ?
421 "SW" : p_nbnode->node_info.node_type ==
422 IB_NODE_TYPE_CA ? "CA" :
423 p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ?
425 p_default_physp->port_info.base_lid ==
426 p_default_physp->port_info.
427 master_sm_base_lid ? "-SM" : "",
428 p_nbnode->node_info.num_ports,
429 cl_ntoh64(p_nbnode->node_info.sys_guid),
430 cl_ntoh64(p_nbnode->node_info.node_guid),
431 cl_ntoh64(p_rphysp->port_guid),
432 cl_ntoh32(ib_node_info_get_vendor_id
433 (&p_nbnode->node_info)),
434 cl_ntoh32(p_nbnode->node_info.device_id),
435 cl_ntoh32(p_nbnode->node_info.revision),
436 p_nbnode->print_desc,
437 cl_ntoh16(p_default_physp->port_info.base_lid),
440 port_state = ib_port_info_get_port_state(&p_physp->port_info);
442 ib_port_info_get_link_speed_active(&p_physp->port_info);
444 fprintf(file, "PHY=%s LOG=%s SPD=%s\n",
445 p_physp->port_info.link_width_active == 1 ? "1x" :
446 p_physp->port_info.link_width_active == 2 ? "4x" :
447 p_physp->port_info.link_width_active == 8 ? "12x" :
449 port_state == IB_LINK_ACTIVE ? "ACT" :
450 port_state == IB_LINK_ARMED ? "ARM" :
451 port_state == IB_LINK_INIT ? "INI" : "DWN",
452 link_speed_act == 1 ? "2.5" :
453 link_speed_act == 2 ? "5" :
454 link_speed_act == 4 ? "10" : "??");
458 static void print_node_report(cl_map_item_t *p_map_item, FILE *file, void *cxt)
460 osm_node_t *p_node = (osm_node_t *) p_map_item;
461 osm_opensm_t *osm = cxt;
462 const osm_physp_t *p_physp, *p_remote_physp;
463 const ib_port_info_t *p_pi;
468 node_type = osm_node_get_type(p_node);
470 num_ports = osm_node_get_num_physp(p_node);
471 port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1;
472 for (; port_num < num_ports; port_num++) {
473 p_physp = osm_node_get_physp_ptr(p_node, port_num);
477 fprintf(file, "%-11s : %s : %02X :",
478 osm_get_manufacturer_str(cl_ntoh64
479 (osm_node_get_node_guid
481 osm_get_node_type_str_fixed_width(node_type), port_num);
483 p_pi = &p_physp->port_info;
486 * Port state is not defined for switch port 0
491 fprintf(file, " %s :",
492 osm_get_port_state_str_fixed_width
493 (ib_port_info_get_port_state(p_pi)));
496 * LID values are only meaningful in select cases.
498 if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN
499 && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0)
500 || node_type != IB_NODE_TYPE_SWITCH))
501 fprintf(file, " %04X : %01X :",
502 cl_ntoh16(p_pi->base_lid),
503 ib_port_info_get_lmc(p_pi));
505 fprintf(file, " : :");
508 fprintf(file, " %s : %s : %s ",
510 (ib_port_info_get_neighbor_mtu(p_pi)),
511 osm_get_lwa_str(p_pi->link_width_active),
513 (ib_port_info_get_link_speed_active(p_pi)));
515 fprintf(file, " : : ");
517 if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid)
518 fprintf(file, "* %016" PRIx64 " *",
519 cl_ntoh64(osm_physp_get_port_guid(p_physp)));
521 fprintf(file, ": %016" PRIx64 " :",
522 cl_ntoh64(osm_physp_get_port_guid(p_physp)));
525 && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) {
526 p_remote_physp = osm_physp_get_remote(p_physp);
528 fprintf(file, " %016" PRIx64 " (%02X)",
529 cl_ntoh64(osm_physp_get_port_guid
531 osm_physp_get_port_num(p_remote_physp));
533 fprintf(file, " UNKNOWN");
539 fprintf(file, "------------------------------------------------------"
540 "------------------------------------------------\n");
543 /**********************************************************************
544 **********************************************************************/
545 struct dump_context {
548 void (*func) (cl_map_item_t *, FILE *, void *);
552 static void dump_item(cl_map_item_t *item, void *cxt)
554 ((struct dump_context *)cxt)->func(item,
555 ((struct dump_context *)cxt)->file,
556 ((struct dump_context *)cxt)->cxt);
559 static void dump_qmap(FILE *file, cl_qmap_t *map,
560 void (*func)(cl_map_item_t *, FILE *, void *), void *cxt)
562 struct dump_context dump_context;
564 dump_context.file = file;
565 dump_context.func = func;
566 dump_context.cxt = cxt;
568 cl_qmap_apply_func(map, dump_item, &dump_context);
571 void osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name,
573 void (*func) (cl_map_item_t *, FILE *, void *),
579 snprintf(path, sizeof(path), "%s/%s",
580 p_osm->subn.opt.dump_files_dir, file_name);
582 file = fopen(path, "w");
584 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
585 "cannot create file \'%s\': %s\n",
586 path, strerror(errno));
590 dump_qmap(file, map, func, cxt);
595 /**********************************************************************
596 **********************************************************************/
598 static void print_report(osm_opensm_t *osm, FILE *file)
600 fprintf(file, "\n==================================================="
601 "====================================================\n"
602 "Vendor : Ty : # : Sta : LID : LMC : MTU : LWA :"
603 " LSA : Port GUID : Neighbor Port (Port #)\n");
604 dump_qmap(stdout, &osm->subn.node_guid_tbl, print_node_report, osm);
607 void osm_dump_mcast_routes(osm_opensm_t * osm)
609 if (osm_log_is_active(&osm->log, OSM_LOG_ROUTING))
610 /* multicast routes */
611 osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
612 &osm->subn.sw_guid_tbl,
613 dump_mcast_routes, osm);
616 void osm_dump_all(osm_opensm_t * osm)
618 if (osm_log_is_active(&osm->log, OSM_LOG_ROUTING)) {
620 osm_dump_qmap_to_file(osm, "opensm-lid-matrix.dump",
621 &osm->subn.sw_guid_tbl, dump_lid_matrix,
623 osm_dump_qmap_to_file(osm, "opensm-lfts.dump",
624 &osm->subn.sw_guid_tbl, dump_ucast_lfts,
626 if (osm_log_is_active(&osm->log, OSM_LOG_DEBUG))
627 dump_qmap(stdout, &osm->subn.sw_guid_tbl,
628 dump_ucast_path_distribution, osm);
629 osm_dump_qmap_to_file(osm, "opensm.fdbs",
630 &osm->subn.sw_guid_tbl,
631 dump_ucast_routes, osm);
632 /* multicast routes */
633 osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
634 &osm->subn.sw_guid_tbl,
635 dump_mcast_routes, osm);
637 osm_dump_qmap_to_file(osm, "opensm-subnet.lst",
638 &osm->subn.node_guid_tbl, dump_topology_node,
640 if (osm_log_is_active(&osm->log, OSM_LOG_VERBOSE))
641 print_report(osm, stdout);