xref: /freebsd/contrib/ofed/opensm/opensm/osm_dump.c (revision 4f52dfbb)
1 /*
2  * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
3  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
4  * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
5  * Copyright (c) 1996-2003 Intel Corporation. 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  *    Various OpenSM dumpers
40  */
41 
42 #if HAVE_CONFIG_H
43 #  include <config.h>
44 #endif				/* HAVE_CONFIG_H */
45 
46 #include <unistd.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <errno.h>
50 #include <iba/ib_types.h>
51 #include <complib/cl_qmap.h>
52 #include <complib/cl_debug.h>
53 #include <opensm/osm_file_ids.h>
54 #define FILE_ID OSM_FILE_DUMP_C
55 #include <opensm/osm_opensm.h>
56 #include <opensm/osm_log.h>
57 #include <opensm/osm_node.h>
58 #include <opensm/osm_switch.h>
59 #include <opensm/osm_helper.h>
60 #include <opensm/osm_msgdef.h>
61 #include <opensm/osm_opensm.h>
62 
63 static void dump_ucast_path_distribution(cl_map_item_t * item, FILE * file,
64 					 void *cxt)
65 {
66 	osm_node_t *p_node;
67 	osm_node_t *p_remote_node;
68 	uint8_t i;
69 	uint8_t num_ports;
70 	uint32_t num_paths;
71 	ib_net64_t remote_guid_ho;
72 	osm_switch_t *p_sw = (osm_switch_t *) item;
73 
74 	p_node = p_sw->p_node;
75 	num_ports = p_sw->num_ports;
76 
77 	fprintf(file, "dump_ucast_path_distribution: Switch 0x%" PRIx64 "\n"
78 		"Port : Path Count Through Port",
79 		cl_ntoh64(osm_node_get_node_guid(p_node)));
80 
81 	for (i = 0; i < num_ports; i++) {
82 		num_paths = osm_switch_path_count_get(p_sw, i);
83 		fprintf(file, "\n %03u : %u", i, num_paths);
84 		if (i == 0) {
85 			fprintf(file, " (switch management port)");
86 			continue;
87 		}
88 
89 		p_remote_node = osm_node_get_remote_node(p_node, i, NULL);
90 		if (p_remote_node == NULL)
91 			continue;
92 
93 		remote_guid_ho =
94 		    cl_ntoh64(osm_node_get_node_guid(p_remote_node));
95 
96 		switch (osm_node_get_type(p_remote_node)) {
97 		case IB_NODE_TYPE_SWITCH:
98 			fprintf(file, " (link to switch");
99 			break;
100 		case IB_NODE_TYPE_ROUTER:
101 			fprintf(file, " (link to router");
102 			break;
103 		case IB_NODE_TYPE_CA:
104 			fprintf(file, " (link to CA");
105 			break;
106 		default:
107 			fprintf(file, " (link to unknown node type");
108 			break;
109 		}
110 
111 		fprintf(file, " 0x%" PRIx64 ")", remote_guid_ho);
112 	}
113 
114 	fprintf(file, "\n");
115 }
116 
117 static void dump_ucast_routes(cl_map_item_t * item, FILE * file, void *cxt)
118 {
119 	const osm_node_t *p_node;
120 	osm_port_t *p_port;
121 	uint8_t port_num;
122 	uint8_t num_hops;
123 	uint8_t best_hops;
124 	uint8_t best_port;
125 	uint16_t max_lid_ho;
126 	uint16_t lid_ho, base_lid;
127 	boolean_t direct_route_exists = FALSE;
128 	boolean_t dor;
129 	osm_switch_t *p_sw = (osm_switch_t *) item;
130 	osm_opensm_t *p_osm = cxt;
131 
132 	p_node = p_sw->p_node;
133 
134 	max_lid_ho = p_sw->max_lid_ho;
135 
136 	fprintf(file, "dump_ucast_routes: "
137 		"Switch 0x%016" PRIx64 "\nLID    : Port : Hops : Optimal\n",
138 		cl_ntoh64(osm_node_get_node_guid(p_node)));
139 
140 	dor = (p_osm->routing_engine_used &&
141 	       p_osm->routing_engine_used->type == OSM_ROUTING_ENGINE_TYPE_DOR);
142 
143 	for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) {
144 		fprintf(file, "0x%04X : ", lid_ho);
145 
146 		p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid_ho);
147 		if (!p_port) {
148 			fprintf(file, "UNREACHABLE\n");
149 			continue;
150 		}
151 
152 		port_num = osm_switch_get_port_by_lid(p_sw, lid_ho,
153 						      OSM_NEW_LFT);
154 		if (port_num == OSM_NO_PATH) {
155 			/*
156 			   This may occur if there are 'holes' in the existing
157 			   LID assignments.  Running SM with --reassign_lids
158 			   will reassign and compress the LID range.  The
159 			   subnet should work fine either way.
160 			 */
161 			fprintf(file, "UNREACHABLE\n");
162 			continue;
163 		}
164 		/*
165 		   Switches can lie about which port routes a given
166 		   lid due to a recent reconfiguration of the subnet.
167 		   Therefore, ensure that the hop count is better than
168 		   OSM_NO_PATH.
169 		 */
170 		if (p_port->p_node->sw) {
171 			/* Target LID is switch.
172 			   Get its base lid and check hop count for this base LID only. */
173 			base_lid = osm_node_get_base_lid(p_port->p_node, 0);
174 			base_lid = cl_ntoh16(base_lid);
175 			num_hops =
176 			    osm_switch_get_hop_count(p_sw, base_lid, port_num);
177 		} else {
178 			/* Target LID is not switch (CA or router).
179 			   Check if we have route to this target from current switch. */
180 			num_hops =
181 			    osm_switch_get_hop_count(p_sw, lid_ho, port_num);
182 			if (num_hops != OSM_NO_PATH) {
183 				direct_route_exists = TRUE;
184 				base_lid = lid_ho;
185 			} else {
186 				osm_physp_t *p_physp = p_port->p_physp;
187 
188 				if (!p_physp || !p_physp->p_remote_physp ||
189 				    !p_physp->p_remote_physp->p_node->sw)
190 					num_hops = OSM_NO_PATH;
191 				else {
192 					base_lid =
193 					    osm_node_get_base_lid(p_physp->
194 								  p_remote_physp->
195 								  p_node, 0);
196 					base_lid = cl_ntoh16(base_lid);
197 					num_hops =
198 					    p_physp->p_remote_physp->p_node->
199 					    sw ==
200 					    p_sw ? 0 :
201 					    osm_switch_get_hop_count(p_sw,
202 								     base_lid,
203 								     port_num);
204 				}
205 			}
206 		}
207 
208 		if (num_hops == OSM_NO_PATH) {
209 			fprintf(file, "%03u  : HOPS UNKNOWN\n", port_num);
210 			continue;
211 		}
212 
213 		best_hops = osm_switch_get_least_hops(p_sw, base_lid);
214 		if (!p_port->p_node->sw && !direct_route_exists) {
215 			best_hops++;
216 			num_hops++;
217 		}
218 
219 		fprintf(file, "%03u  : %02u   : ", port_num, num_hops);
220 
221 		if (best_hops == num_hops)
222 			fprintf(file, "yes");
223 		else {
224 			/* No LMC Optimization */
225 			best_port = osm_switch_recommend_path(p_sw, p_port,
226 							      lid_ho, 1, TRUE,
227 							      FALSE, dor,
228 							      p_osm->subn.opt.port_shifting,
229 							      p_osm->subn.opt.scatter_ports,
230 							      OSM_NEW_LFT);
231 			fprintf(file, "No %u hop path possible via port %u!",
232 				best_hops, best_port);
233 		}
234 
235 		fprintf(file, "\n");
236 	}
237 }
238 
239 static void dump_mcast_routes(cl_map_item_t * item, FILE * file, void *cxt)
240 {
241 	osm_switch_t *p_sw = (osm_switch_t *) item;
242 	osm_mcast_tbl_t *p_tbl;
243 	int16_t mlid_ho = 0;
244 	int16_t mlid_start_ho;
245 	uint8_t position = 0;
246 	int16_t block_num = 0;
247 	boolean_t first_mlid;
248 	boolean_t first_port;
249 	const osm_node_t *p_node;
250 	uint16_t i, j;
251 	uint16_t mask_entry;
252 	char sw_hdr[256];
253 	char mlid_hdr[32];
254 
255 	p_node = p_sw->p_node;
256 
257 	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
258 
259 	sprintf(sw_hdr, "\nSwitch 0x%016" PRIx64 "\nLID    : Out Port(s)\n",
260 		cl_ntoh64(osm_node_get_node_guid(p_node)));
261 	first_mlid = TRUE;
262 	while (block_num <= p_tbl->max_block_in_use) {
263 		mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
264 		for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) {
265 			mlid_ho = mlid_start_ho + i;
266 			position = 0;
267 			first_port = TRUE;
268 			sprintf(mlid_hdr, "0x%04X :",
269 				mlid_ho + IB_LID_MCAST_START_HO);
270 			while (position <= p_tbl->max_position) {
271 				mask_entry =
272 				    cl_ntoh16((*p_tbl->
273 					       p_mask_tbl)[mlid_ho][position]);
274 				if (mask_entry == 0) {
275 					position++;
276 					continue;
277 				}
278 				for (j = 0; j < 16; j++) {
279 					if ((1 << j) & mask_entry) {
280 						if (first_mlid) {
281 							fprintf(file, "%s",
282 								sw_hdr);
283 							first_mlid = FALSE;
284 						}
285 						if (first_port) {
286 							fprintf(file, "%s",
287 								mlid_hdr);
288 							first_port = FALSE;
289 						}
290 						fprintf(file, " 0x%03X ",
291 							j + (position * 16));
292 					}
293 				}
294 				position++;
295 			}
296 			if (first_port == FALSE)
297 				fprintf(file, "\n");
298 		}
299 		block_num++;
300 	}
301 }
302 
303 static void dump_lid_matrix(cl_map_item_t * item, FILE * file, void *cxt)
304 {
305 	osm_switch_t *p_sw = (osm_switch_t *) item;
306 	osm_opensm_t *p_osm = cxt;
307 	osm_node_t *p_node = p_sw->p_node;
308 	unsigned max_lid = p_sw->max_lid_ho;
309 	unsigned max_port = p_sw->num_ports;
310 	uint16_t lid;
311 	uint8_t port;
312 
313 	fprintf(file, "Switch: guid 0x%016" PRIx64 "\n",
314 		cl_ntoh64(osm_node_get_node_guid(p_node)));
315 	for (lid = 1; lid <= max_lid; lid++) {
316 		osm_port_t *p_port;
317 		if (osm_switch_get_least_hops(p_sw, lid) == OSM_NO_PATH)
318 			continue;
319 		fprintf(file, "0x%04x:", lid);
320 		for (port = 0; port < max_port; port++)
321 			fprintf(file, " %02x",
322 				osm_switch_get_hop_count(p_sw, lid, port));
323 		p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid);
324 		if (p_port)
325 			fprintf(file, " # portguid 0x%016" PRIx64,
326 				cl_ntoh64(osm_port_get_guid(p_port)));
327 		fprintf(file, "\n");
328 	}
329 }
330 
331 static void dump_ucast_lfts(cl_map_item_t * item, FILE * file, void *cxt)
332 {
333 	osm_switch_t *p_sw = (osm_switch_t *) item;
334 	osm_opensm_t *p_osm = cxt;
335 	osm_node_t *p_node = p_sw->p_node;
336 	unsigned max_lid = p_sw->max_lid_ho;
337 	unsigned max_port = p_sw->num_ports;
338 	uint16_t lid;
339 	uint8_t port;
340 
341 	fprintf(file, "Unicast lids [0-%u] of switch Lid %u guid 0x%016"
342 		PRIx64 " (\'%s\'):\n",
343 		max_lid, cl_ntoh16(osm_node_get_base_lid(p_node, 0)),
344 		cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc);
345 	for (lid = 0; lid <= max_lid; lid++) {
346 		osm_port_t *p_port;
347 		port = osm_switch_get_port_by_lid(p_sw, lid, OSM_NEW_LFT);
348 
349 		if (port >= max_port)
350 			continue;
351 
352 		fprintf(file, "0x%04x %03u # ", lid, port);
353 
354 		p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid);
355 		if (p_port) {
356 			p_node = p_port->p_node;
357 			fprintf(file, "%s portguid 0x%016" PRIx64 ": \'%s\'",
358 				ib_get_node_type_str(osm_node_get_type(p_node)),
359 				cl_ntoh64(osm_port_get_guid(p_port)),
360 				p_node->print_desc);
361 		} else
362 			fprintf(file, "unknown node and type");
363 		fprintf(file, "\n");
364 	}
365 	fprintf(file, "%u lids dumped\n", max_lid);
366 }
367 
368 static void dump_topology_node(cl_map_item_t * item, FILE * file, void *cxt)
369 {
370 	osm_node_t *p_node = (osm_node_t *) item;
371 	uint32_t cPort;
372 	osm_node_t *p_nbnode;
373 	osm_physp_t *p_physp, *p_default_physp, *p_rphysp;
374 	uint8_t link_speed_act;
375 	const char *link_speed_act_str, *link_width_act_str;
376 
377 	if (!p_node->node_info.num_ports)
378 		return;
379 
380 	for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) {
381 		uint8_t port_state;
382 
383 		p_physp = osm_node_get_physp_ptr(p_node, cPort);
384 		if (!p_physp)
385 			continue;
386 
387 		p_rphysp = p_physp->p_remote_physp;
388 		if (!p_rphysp)
389 			continue;
390 
391 		CL_ASSERT(cPort == p_physp->port_num);
392 
393 		if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
394 			p_default_physp = osm_node_get_physp_ptr(p_node, 0);
395 		else
396 			p_default_physp = p_physp;
397 
398 		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
399 			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
400 			" VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
401 			p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ?
402 			"SW" : p_node->node_info.node_type ==
403 			IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type ==
404 			IB_NODE_TYPE_ROUTER ? "Rt" : "**",
405 			p_default_physp->port_info.base_lid ==
406 			p_default_physp->port_info.
407 			master_sm_base_lid ? "-SM" : "",
408 			p_node->node_info.num_ports,
409 			cl_ntoh64(p_node->node_info.sys_guid),
410 			cl_ntoh64(p_node->node_info.node_guid),
411 			cl_ntoh64(p_physp->port_guid),
412 			cl_ntoh32(ib_node_info_get_vendor_id
413 				  (&p_node->node_info)),
414 			cl_ntoh16(p_node->node_info.device_id),
415 			cl_ntoh32(p_node->node_info.revision),
416 			p_node->print_desc,
417 			cl_ntoh16(p_default_physp->port_info.base_lid), cPort);
418 
419 		p_nbnode = p_rphysp->p_node;
420 
421 		if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH)
422 			p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0);
423 		else
424 			p_default_physp = p_rphysp;
425 
426 		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
427 			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
428 			" VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
429 			p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ?
430 			"SW" : p_nbnode->node_info.node_type ==
431 			IB_NODE_TYPE_CA ? "CA" :
432 			p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ?
433 			"Rt" : "**",
434 			p_default_physp->port_info.base_lid ==
435 			p_default_physp->port_info.
436 			master_sm_base_lid ? "-SM" : "",
437 			p_nbnode->node_info.num_ports,
438 			cl_ntoh64(p_nbnode->node_info.sys_guid),
439 			cl_ntoh64(p_nbnode->node_info.node_guid),
440 			cl_ntoh64(p_rphysp->port_guid),
441 			cl_ntoh32(ib_node_info_get_vendor_id
442 				  (&p_nbnode->node_info)),
443 			cl_ntoh32(p_nbnode->node_info.device_id),
444 			cl_ntoh32(p_nbnode->node_info.revision),
445 			p_nbnode->print_desc,
446 			cl_ntoh16(p_default_physp->port_info.base_lid),
447 			p_rphysp->port_num);
448 
449 		port_state = ib_port_info_get_port_state(&p_physp->port_info);
450 		link_speed_act =
451 		    ib_port_info_get_link_speed_active(&p_physp->port_info);
452 		if (link_speed_act == IB_LINK_SPEED_ACTIVE_2_5)
453 			link_speed_act_str = "2.5";
454 		else if (link_speed_act == IB_LINK_SPEED_ACTIVE_5)
455 			link_speed_act_str = "5";
456 		else if (link_speed_act == IB_LINK_SPEED_ACTIVE_10)
457 			link_speed_act_str = "10";
458 		else
459 			link_speed_act_str = "??";
460 
461 		if (p_physp->ext_port_info.link_speed_active & FDR10)
462 			link_speed_act_str = "FDR10";
463 
464 		if (p_default_physp->port_info.capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) {
465 			link_speed_act =
466 			    ib_port_info_get_link_speed_ext_active(&p_physp->port_info);
467 			if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_14)
468 				link_speed_act_str = "14";
469 			else if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_25)
470 				link_speed_act_str = "25";
471 			else if (link_speed_act != IB_LINK_SPEED_EXT_ACTIVE_NONE)
472 				link_speed_act_str = "??";
473 		}
474 
475 		if (p_physp->port_info.link_width_active == 1)
476 			link_width_act_str = "1x";
477 		else if (p_physp->port_info.link_width_active == 2)
478 			link_width_act_str = "4x";
479 		else if (p_physp->port_info.link_width_active == 4)
480 			link_width_act_str = "8x";
481 		else if (p_physp->port_info.link_width_active == 8)
482 			link_width_act_str = "12x";
483 		else link_width_act_str = "??";
484 
485 		if (p_default_physp->port_info.capability_mask2 &
486 		    IB_PORT_CAP2_IS_LINK_WIDTH_2X_SUPPORTED) {
487 			if (p_physp->port_info.link_width_active == 16)
488 				link_width_act_str = "2x";
489 		}
490 
491 		fprintf(file, "PHY=%s LOG=%s SPD=%s\n",
492 			link_width_act_str,
493 			port_state == IB_LINK_ACTIVE ? "ACT" :
494 			port_state == IB_LINK_ARMED ? "ARM" :
495 			port_state == IB_LINK_INIT ? "INI" : "DWN",
496 			link_speed_act_str);
497 	}
498 }
499 
500 static void dump_sl2vl_tbl(cl_map_item_t * item, FILE * file, void *cxt)
501 {
502 	osm_port_t *p_port = (osm_port_t *) item;
503 	osm_node_t *p_node = p_port->p_node;
504 	uint32_t in_port, out_port,
505 		 num_ports = p_node->node_info.num_ports;
506 	ib_net16_t base_lid = osm_port_get_base_lid(p_port);
507 	osm_physp_t *p_physp;
508 	ib_slvl_table_t *p_tbl;
509 	int i, n;
510 	char buf[1024];
511 	const char * header_line =	"#in out : 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15";
512 	const char * separator_line = "#--------------------------------------------------------";
513 
514 	if (!num_ports)
515 		return;
516 
517 	fprintf(file, "%s 0x%016" PRIx64 ", base LID %d, "
518 		"\"%s\"\n%s\n%s\n",
519 		ib_get_node_type_str(p_node->node_info.node_type),
520 		cl_ntoh64(p_port->guid), cl_ntoh16(base_lid),
521 		p_node->print_desc, header_line, separator_line);
522 
523 	if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) {
524 		for (out_port = 0; out_port <= num_ports; out_port++){
525 			p_physp = osm_node_get_physp_ptr(p_node, out_port);
526 
527 			/* no need to print SL2VL table for port that is down */
528 			if (!p_physp || !p_physp->p_remote_physp)
529 				continue;
530 
531 			for (in_port = 0; in_port <= num_ports; in_port++) {
532 				p_tbl = osm_physp_get_slvl_tbl(p_physp, in_port);
533 				for (i = 0, n = 0; i < 16; i++)
534 					n += sprintf(buf + n, " %-2d",
535 						ib_slvl_table_get(p_tbl, i));
536 				fprintf(file, "%-3d %-3d :%s\n",
537 					in_port, out_port, buf);
538 			}
539 		}
540 	} else {
541 		p_physp = p_port->p_physp;
542 		p_tbl = osm_physp_get_slvl_tbl(p_physp, 0);
543 		for (i = 0, n = 0; i < 16; i++)
544 			n += sprintf(buf + n, " %-2d",
545 					ib_slvl_table_get(p_tbl, i));
546 		fprintf(file, "%-3d %-3d :%s\n", 0, 0, buf);
547 	}
548 
549 	fprintf(file, "%s\n\n", separator_line);
550 }
551 
552 static void print_node_report(cl_map_item_t * item, FILE * file, void *cxt)
553 {
554 	osm_node_t *p_node = (osm_node_t *) item;
555 	osm_opensm_t *osm = cxt;
556 	const osm_physp_t *p_physp, *p_remote_physp;
557 	const ib_port_info_t *p_pi;
558 	uint8_t port_num;
559 	uint32_t num_ports;
560 	uint8_t node_type;
561 
562 	node_type = osm_node_get_type(p_node);
563 
564 	num_ports = osm_node_get_num_physp(p_node);
565 	port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1;
566 	for (; port_num < num_ports; port_num++) {
567 		p_physp = osm_node_get_physp_ptr(p_node, port_num);
568 		if (!p_physp)
569 			continue;
570 
571 		fprintf(file, "%-11s : %s : %02X :",
572 			osm_get_manufacturer_str(cl_ntoh64
573 						 (osm_node_get_node_guid
574 						  (p_node))),
575 			osm_get_node_type_str_fixed_width(node_type), port_num);
576 
577 		p_pi = &p_physp->port_info;
578 
579 		/*
580 		 * Port state is not defined for base switch port 0
581 		 */
582 		if (port_num == 0 &&
583 		    ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE)
584 			fprintf(file, "     :");
585 		else
586 			fprintf(file, " %s :",
587 				osm_get_port_state_str_fixed_width
588 				(ib_port_info_get_port_state(p_pi)));
589 
590 		/*
591 		 * LID values are only meaningful in select cases.
592 		 */
593 		if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN
594 		    && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0)
595 			|| node_type != IB_NODE_TYPE_SWITCH))
596 			fprintf(file, " %04X :  %01X  :",
597 				cl_ntoh16(p_pi->base_lid),
598 				ib_port_info_get_lmc(p_pi));
599 		else
600 			fprintf(file, "      :     :");
601 
602 		if (port_num == 0 &&
603 		    ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE)
604 			fprintf(file, "      :     :      ");
605 		else
606 			fprintf(file, " %s : %s : %s ",
607 				osm_get_mtu_str
608 				(ib_port_info_get_neighbor_mtu(p_pi)),
609 				osm_get_lwa_str(p_pi->link_width_active),
610 				osm_get_lsa_str
611 				(ib_port_info_get_link_speed_active(p_pi),
612 				 ib_port_info_get_link_speed_ext_active(p_pi),
613 				 ib_port_info_get_port_state(p_pi),
614 				 p_physp->ext_port_info.link_speed_active & FDR10));
615 
616 		if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid)
617 			fprintf(file, "* %016" PRIx64 " *",
618 				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
619 		else
620 			fprintf(file, ": %016" PRIx64 " :",
621 				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
622 
623 		if (port_num
624 		    && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) {
625 			p_remote_physp = osm_physp_get_remote(p_physp);
626 			if (p_remote_physp)
627 				fprintf(file, " %016" PRIx64 " (%02X)",
628 					cl_ntoh64(osm_physp_get_port_guid
629 						  (p_remote_physp)),
630 					osm_physp_get_port_num(p_remote_physp));
631 			else
632 				fprintf(file, " UNKNOWN");
633 		}
634 
635 		fprintf(file, "\n");
636 	}
637 
638 	fprintf(file, "------------------------------------------------------"
639 		"------------------------------------------------\n");
640 }
641 
642 struct dump_context {
643 	osm_opensm_t *p_osm;
644 	FILE *file;
645 	void (*func) (cl_map_item_t *, FILE *, void *);
646 	void *cxt;
647 };
648 
649 static void dump_item(cl_map_item_t * item, void *cxt)
650 {
651 	((struct dump_context *)cxt)->func(item,
652 					   ((struct dump_context *)cxt)->file,
653 					   ((struct dump_context *)cxt)->cxt);
654 }
655 
656 static void dump_qmap(FILE * file, cl_qmap_t * map,
657 		      void (*func) (cl_map_item_t *, FILE *, void *), void *cxt)
658 {
659 	struct dump_context dump_context;
660 
661 	dump_context.file = file;
662 	dump_context.func = func;
663 	dump_context.cxt = cxt;
664 
665 	cl_qmap_apply_func(map, dump_item, &dump_context);
666 }
667 
668 void osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name,
669 			   cl_qmap_t * map,
670 			   void (*func) (cl_map_item_t *, FILE *, void *),
671 			   void *cxt)
672 {
673 	char path[1024];
674 	FILE *file;
675 
676 	snprintf(path, sizeof(path), "%s/%s",
677 		 p_osm->subn.opt.dump_files_dir, file_name);
678 
679 	file = fopen(path, "w");
680 	if (!file) {
681 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
682 			"cannot create file \'%s\': %s\n",
683 			path, strerror(errno));
684 		return;
685 	}
686 
687 	dump_qmap(file, map, func, cxt);
688 
689 	fclose(file);
690 }
691 
692 
693 static void print_report(osm_opensm_t * osm, FILE * file)
694 {
695 	fprintf(file, "\n==================================================="
696 		"====================================================\n"
697 		"Vendor      : Ty : #  : Sta : LID  : LMC : MTU  : LWA :"
698 		" LSA  : Port GUID        : Neighbor Port (Port #)\n");
699 	dump_qmap(stdout, &osm->subn.node_guid_tbl, print_node_report, osm);
700 }
701 
702 void osm_dump_mcast_routes(osm_opensm_t * osm)
703 {
704 	if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_ROUTING))
705 		/* multicast routes */
706 		osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
707 				      &osm->subn.sw_guid_tbl,
708 				      dump_mcast_routes, osm);
709 }
710 
711 void osm_dump_all(osm_opensm_t * osm)
712 {
713 	if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_ROUTING)) {
714 		/* unicast routes */
715 		osm_dump_qmap_to_file(osm, "opensm-lid-matrix.dump",
716 				      &osm->subn.sw_guid_tbl, dump_lid_matrix,
717 				      osm);
718 		osm_dump_qmap_to_file(osm, "opensm-lfts.dump",
719 				      &osm->subn.sw_guid_tbl, dump_ucast_lfts,
720 				      osm);
721 		if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_DEBUG))
722 			dump_qmap(stdout, &osm->subn.sw_guid_tbl,
723 				  dump_ucast_path_distribution, osm);
724 
725 		/* An attempt to get osm_switch_recommend_path to report the
726 		   same routes that a sweep would assign. */
727 		if (osm->subn.opt.scatter_ports)
728 			srandom(osm->subn.opt.scatter_ports);
729 
730 		osm_dump_qmap_to_file(osm, "opensm.fdbs",
731 				      &osm->subn.sw_guid_tbl,
732 				      dump_ucast_routes, osm);
733 		/* multicast routes */
734 		osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
735 				      &osm->subn.sw_guid_tbl,
736 				      dump_mcast_routes, osm);
737 		/* SL2VL tables */
738 		if (osm->subn.opt.qos ||
739 		    (osm->routing_engine_used &&
740 		     osm->routing_engine_used->update_sl2vl))
741 			osm_dump_qmap_to_file(osm, "opensm-sl2vl.dump",
742 					      &osm->subn.port_guid_tbl,
743 					      dump_sl2vl_tbl, osm);
744 	}
745 	osm_dump_qmap_to_file(osm, "opensm-subnet.lst",
746 			      &osm->subn.node_guid_tbl, dump_topology_node,
747 			      osm);
748 	if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_VERBOSE))
749 		print_report(osm, stdout);
750 }
751