1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff/*
37219820Sjeff * Abstract:
38219820Sjeff *    Various OpenSM dumpers
39219820Sjeff */
40219820Sjeff
41219820Sjeff#if HAVE_CONFIG_H
42219820Sjeff#  include <config.h>
43219820Sjeff#endif				/* HAVE_CONFIG_H */
44219820Sjeff
45219820Sjeff#include <unistd.h>
46219820Sjeff#include <stdlib.h>
47219820Sjeff#include <string.h>
48219820Sjeff#include <errno.h>
49219820Sjeff#include <iba/ib_types.h>
50219820Sjeff#include <complib/cl_qmap.h>
51219820Sjeff#include <complib/cl_debug.h>
52219820Sjeff#include <opensm/osm_opensm.h>
53219820Sjeff#include <opensm/osm_log.h>
54219820Sjeff#include <opensm/osm_node.h>
55219820Sjeff#include <opensm/osm_switch.h>
56219820Sjeff#include <opensm/osm_helper.h>
57219820Sjeff#include <opensm/osm_msgdef.h>
58219820Sjeff#include <opensm/osm_opensm.h>
59219820Sjeff
60219820Sjeffstatic void dump_ucast_path_distribution(cl_map_item_t * p_map_item,
61219820Sjeff					 FILE *file, void *cxt)
62219820Sjeff{
63219820Sjeff	osm_node_t *p_node;
64219820Sjeff	osm_node_t *p_remote_node;
65219820Sjeff	uint8_t i;
66219820Sjeff	uint8_t num_ports;
67219820Sjeff	uint32_t num_paths;
68219820Sjeff	ib_net64_t remote_guid_ho;
69219820Sjeff	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
70219820Sjeff
71219820Sjeff	p_node = p_sw->p_node;
72219820Sjeff	num_ports = p_sw->num_ports;
73219820Sjeff
74219820Sjeff	fprintf(file, "dump_ucast_path_distribution: Switch 0x%" PRIx64 "\n"
75219820Sjeff		"Port : Path Count Through Port",
76219820Sjeff		cl_ntoh64(osm_node_get_node_guid(p_node)));
77219820Sjeff
78219820Sjeff	for (i = 0; i < num_ports; i++) {
79219820Sjeff		num_paths = osm_switch_path_count_get(p_sw, i);
80219820Sjeff		fprintf(file, "\n %03u : %u", i, num_paths);
81219820Sjeff		if (i == 0) {
82219820Sjeff			fprintf(file, " (switch management port)");
83219820Sjeff			continue;
84219820Sjeff		}
85219820Sjeff
86219820Sjeff		p_remote_node = osm_node_get_remote_node(p_node, i, NULL);
87219820Sjeff		if (p_remote_node == NULL)
88219820Sjeff			continue;
89219820Sjeff
90219820Sjeff		remote_guid_ho =
91219820Sjeff		    cl_ntoh64(osm_node_get_node_guid(p_remote_node));
92219820Sjeff
93219820Sjeff		switch (osm_node_get_type(p_remote_node)) {
94219820Sjeff		case IB_NODE_TYPE_SWITCH:
95219820Sjeff			fprintf(file, " (link to switch");
96219820Sjeff			break;
97219820Sjeff		case IB_NODE_TYPE_ROUTER:
98219820Sjeff			fprintf(file, " (link to router");
99219820Sjeff			break;
100219820Sjeff		case IB_NODE_TYPE_CA:
101219820Sjeff			fprintf(file, " (link to CA");
102219820Sjeff			break;
103219820Sjeff		default:
104219820Sjeff			fprintf(file, " (link to unknown node type");
105219820Sjeff			break;
106219820Sjeff		}
107219820Sjeff
108219820Sjeff		fprintf(file, " 0x%" PRIx64 ")", remote_guid_ho);
109219820Sjeff	}
110219820Sjeff
111219820Sjeff	fprintf(file, "\n");
112219820Sjeff}
113219820Sjeff
114219820Sjeffstatic void dump_ucast_routes(cl_map_item_t *p_map_item, FILE *file, void *cxt)
115219820Sjeff{
116219820Sjeff	const osm_node_t *p_node;
117219820Sjeff	osm_port_t *p_port;
118219820Sjeff	uint8_t port_num;
119219820Sjeff	uint8_t num_hops;
120219820Sjeff	uint8_t best_hops;
121219820Sjeff	uint8_t best_port;
122219820Sjeff	uint16_t max_lid_ho;
123219820Sjeff	uint16_t lid_ho, base_lid;
124219820Sjeff	boolean_t direct_route_exists = FALSE;
125219820Sjeff	boolean_t dor;
126219820Sjeff	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
127219820Sjeff	osm_opensm_t *p_osm = cxt;
128219820Sjeff
129219820Sjeff	p_node = p_sw->p_node;
130219820Sjeff
131219820Sjeff	max_lid_ho = p_sw->max_lid_ho;
132219820Sjeff
133219820Sjeff	fprintf(file, "__osm_ucast_mgr_dump_ucast_routes: "
134219820Sjeff		"Switch 0x%016" PRIx64 "\nLID    : Port : Hops : Optimal\n",
135219820Sjeff		cl_ntoh64(osm_node_get_node_guid(p_node)));
136219820Sjeff
137219820Sjeff	dor = (p_osm->routing_engine_used == OSM_ROUTING_ENGINE_TYPE_DOR);
138219820Sjeff
139219820Sjeff	for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) {
140219820Sjeff		fprintf(file, "0x%04X : ", lid_ho);
141219820Sjeff
142219820Sjeff		p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid_ho);
143219820Sjeff		if (!p_port) {
144219820Sjeff			fprintf(file, "UNREACHABLE\n");
145219820Sjeff			continue;
146219820Sjeff		}
147219820Sjeff
148219820Sjeff		port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
149219820Sjeff		if (port_num == OSM_NO_PATH) {
150219820Sjeff			/*
151219820Sjeff			   This may occur if there are 'holes' in the existing
152219820Sjeff			   LID assignments.  Running SM with --reassign_lids
153219820Sjeff			   will reassign and compress the LID range.  The
154219820Sjeff			   subnet should work fine either way.
155219820Sjeff			 */
156219820Sjeff			fprintf(file, "UNREACHABLE\n");
157219820Sjeff			continue;
158219820Sjeff		}
159219820Sjeff		/*
160219820Sjeff		   Switches can lie about which port routes a given
161219820Sjeff		   lid due to a recent reconfiguration of the subnet.
162219820Sjeff		   Therefore, ensure that the hop count is better than
163219820Sjeff		   OSM_NO_PATH.
164219820Sjeff		 */
165219820Sjeff		if (p_port->p_node->sw) {
166219820Sjeff			/* Target LID is switch.
167219820Sjeff			   Get its base lid and check hop count for this base LID only. */
168219820Sjeff			base_lid = osm_node_get_base_lid(p_port->p_node, 0);
169219820Sjeff			base_lid = cl_ntoh16(base_lid);
170219820Sjeff			num_hops =
171219820Sjeff			    osm_switch_get_hop_count(p_sw, base_lid, port_num);
172219820Sjeff		} else {
173219820Sjeff			/* Target LID is not switch (CA or router).
174219820Sjeff			   Check if we have route to this target from current switch. */
175219820Sjeff			num_hops =
176219820Sjeff			    osm_switch_get_hop_count(p_sw, lid_ho, port_num);
177219820Sjeff			if (num_hops != OSM_NO_PATH) {
178219820Sjeff				direct_route_exists = TRUE;
179219820Sjeff				base_lid = lid_ho;
180219820Sjeff			} else {
181219820Sjeff				osm_physp_t *p_physp = p_port->p_physp;
182219820Sjeff
183219820Sjeff				if (!p_physp || !p_physp->p_remote_physp ||
184219820Sjeff				    !p_physp->p_remote_physp->p_node->sw)
185219820Sjeff					num_hops = OSM_NO_PATH;
186219820Sjeff				else {
187219820Sjeff					base_lid =
188219820Sjeff					    osm_node_get_base_lid(p_physp->
189219820Sjeff								  p_remote_physp->
190219820Sjeff								  p_node, 0);
191219820Sjeff					base_lid = cl_ntoh16(base_lid);
192219820Sjeff					num_hops =
193219820Sjeff					    p_physp->p_remote_physp->p_node->
194219820Sjeff					    sw ==
195219820Sjeff					    p_sw ? 0 :
196219820Sjeff					    osm_switch_get_hop_count(p_sw,
197219820Sjeff								     base_lid,
198219820Sjeff								     port_num);
199219820Sjeff				}
200219820Sjeff			}
201219820Sjeff		}
202219820Sjeff
203219820Sjeff		if (num_hops == OSM_NO_PATH) {
204219820Sjeff			fprintf(file, "UNREACHABLE\n");
205219820Sjeff			continue;
206219820Sjeff		}
207219820Sjeff
208219820Sjeff		best_hops = osm_switch_get_least_hops(p_sw, base_lid);
209219820Sjeff		if (!p_port->p_node->sw && !direct_route_exists) {
210219820Sjeff			best_hops++;
211219820Sjeff			num_hops++;
212219820Sjeff		}
213219820Sjeff
214219820Sjeff		fprintf(file, "%03u  : %02u   : ", port_num, num_hops);
215219820Sjeff
216219820Sjeff		if (best_hops == num_hops)
217219820Sjeff			fprintf(file, "yes");
218219820Sjeff		else {
219219820Sjeff			/* No LMC Optimization */
220219820Sjeff			best_port = osm_switch_recommend_path(p_sw, p_port,
221219820Sjeff							      lid_ho, 1, TRUE,
222219820Sjeff							      dor);
223219820Sjeff			fprintf(file, "No %u hop path possible via port %u!",
224219820Sjeff				best_hops, best_port);
225219820Sjeff		}
226219820Sjeff
227219820Sjeff		fprintf(file, "\n");
228219820Sjeff	}
229219820Sjeff}
230219820Sjeff
231219820Sjeffstatic void dump_mcast_routes(cl_map_item_t *p_map_item, FILE *file, void *cxt)
232219820Sjeff{
233219820Sjeff	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
234219820Sjeff	osm_mcast_tbl_t *p_tbl;
235219820Sjeff	int16_t mlid_ho = 0;
236219820Sjeff	int16_t mlid_start_ho;
237219820Sjeff	uint8_t position = 0;
238219820Sjeff	int16_t block_num = 0;
239219820Sjeff	boolean_t first_mlid;
240219820Sjeff	boolean_t first_port;
241219820Sjeff	const osm_node_t *p_node;
242219820Sjeff	uint16_t i, j;
243219820Sjeff	uint16_t mask_entry;
244219820Sjeff	char sw_hdr[256];
245219820Sjeff	char mlid_hdr[32];
246219820Sjeff
247219820Sjeff	p_node = p_sw->p_node;
248219820Sjeff
249219820Sjeff	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
250219820Sjeff
251219820Sjeff	sprintf(sw_hdr, "\nSwitch 0x%016" PRIx64 "\nLID    : Out Port(s)\n",
252219820Sjeff		cl_ntoh64(osm_node_get_node_guid(p_node)));
253219820Sjeff	first_mlid = TRUE;
254219820Sjeff	while (block_num <= p_tbl->max_block_in_use) {
255219820Sjeff		mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
256219820Sjeff		for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) {
257219820Sjeff			mlid_ho = mlid_start_ho + i;
258219820Sjeff			position = 0;
259219820Sjeff			first_port = TRUE;
260219820Sjeff			sprintf(mlid_hdr, "0x%04X :",
261219820Sjeff				mlid_ho + IB_LID_MCAST_START_HO);
262219820Sjeff			while (position <= p_tbl->max_position) {
263219820Sjeff				mask_entry =
264219820Sjeff				    cl_ntoh16((*p_tbl->
265219820Sjeff					       p_mask_tbl)[mlid_ho][position]);
266219820Sjeff				if (mask_entry == 0) {
267219820Sjeff					position++;
268219820Sjeff					continue;
269219820Sjeff				}
270219820Sjeff				for (j = 0; j < 16; j++) {
271219820Sjeff					if ((1 << j) & mask_entry) {
272219820Sjeff						if (first_mlid) {
273219820Sjeff							fprintf(file, "%s",
274219820Sjeff								sw_hdr);
275219820Sjeff							first_mlid = FALSE;
276219820Sjeff						}
277219820Sjeff						if (first_port) {
278219820Sjeff							fprintf(file, "%s",
279219820Sjeff								mlid_hdr);
280219820Sjeff							first_port = FALSE;
281219820Sjeff						}
282219820Sjeff						fprintf(file, " 0x%03X ",
283219820Sjeff							j + (position * 16));
284219820Sjeff					}
285219820Sjeff				}
286219820Sjeff				position++;
287219820Sjeff			}
288219820Sjeff			if (first_port == FALSE)
289219820Sjeff				fprintf(file, "\n");
290219820Sjeff		}
291219820Sjeff		block_num++;
292219820Sjeff	}
293219820Sjeff}
294219820Sjeff
295219820Sjeffstatic void dump_lid_matrix(cl_map_item_t *p_map_item, FILE *file, void *cxt)
296219820Sjeff{
297219820Sjeff	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
298219820Sjeff	osm_opensm_t *p_osm = cxt;
299219820Sjeff	osm_node_t *p_node = p_sw->p_node;
300219820Sjeff	unsigned max_lid = p_sw->max_lid_ho;
301219820Sjeff	unsigned max_port = p_sw->num_ports;
302219820Sjeff	uint16_t lid;
303219820Sjeff	uint8_t port;
304219820Sjeff
305219820Sjeff	fprintf(file, "Switch: guid 0x%016" PRIx64 "\n",
306219820Sjeff		cl_ntoh64(osm_node_get_node_guid(p_node)));
307219820Sjeff	for (lid = 1; lid <= max_lid; lid++) {
308219820Sjeff		osm_port_t *p_port;
309219820Sjeff		if (osm_switch_get_least_hops(p_sw, lid) == OSM_NO_PATH)
310219820Sjeff			continue;
311219820Sjeff		fprintf(file, "0x%04x:", lid);
312219820Sjeff		for (port = 0; port < max_port; port++)
313219820Sjeff			fprintf(file, " %02x",
314219820Sjeff				osm_switch_get_hop_count(p_sw, lid, port));
315219820Sjeff		p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid);
316219820Sjeff		if (p_port)
317219820Sjeff			fprintf(file, " # portguid 0x016%" PRIx64,
318219820Sjeff				cl_ntoh64(osm_port_get_guid(p_port)));
319219820Sjeff		fprintf(file, "\n");
320219820Sjeff	}
321219820Sjeff}
322219820Sjeff
323219820Sjeffstatic void dump_ucast_lfts(cl_map_item_t *p_map_item, FILE *file, void *cxt)
324219820Sjeff{
325219820Sjeff	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
326219820Sjeff	osm_opensm_t *p_osm = cxt;
327219820Sjeff	osm_node_t *p_node = p_sw->p_node;
328219820Sjeff	unsigned max_lid = p_sw->max_lid_ho;
329219820Sjeff	unsigned max_port = p_sw->num_ports;
330219820Sjeff	uint16_t lid;
331219820Sjeff	uint8_t port;
332219820Sjeff
333219820Sjeff	fprintf(file, "Unicast lids [0-%u] of switch Lid %u guid 0x%016"
334219820Sjeff		PRIx64 " (\'%s\'):\n",
335219820Sjeff		max_lid, cl_ntoh16(osm_node_get_base_lid(p_node, 0)),
336219820Sjeff		cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc);
337219820Sjeff	for (lid = 0; lid <= max_lid; lid++) {
338219820Sjeff		osm_port_t *p_port;
339219820Sjeff		port = osm_switch_get_port_by_lid(p_sw, lid);
340219820Sjeff
341219820Sjeff		if (port >= max_port)
342219820Sjeff			continue;
343219820Sjeff
344219820Sjeff		fprintf(file, "0x%04x %03u # ", lid, port);
345219820Sjeff
346219820Sjeff		p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid);
347219820Sjeff		if (p_port) {
348219820Sjeff			p_node = p_port->p_node;
349219820Sjeff			fprintf(file, "%s portguid 0x%016" PRIx64 ": \'%s\'",
350219820Sjeff				ib_get_node_type_str(osm_node_get_type(p_node)),
351219820Sjeff				cl_ntoh64(osm_port_get_guid(p_port)),
352219820Sjeff				p_node->print_desc);
353219820Sjeff		} else
354219820Sjeff			fprintf(file, "unknown node and type");
355219820Sjeff		fprintf(file, "\n");
356219820Sjeff	}
357219820Sjeff	fprintf(file, "%u lids dumped\n", max_lid);
358219820Sjeff}
359219820Sjeff
360219820Sjeffstatic void dump_topology_node(cl_map_item_t *p_map_item, FILE *file, void *cxt)
361219820Sjeff{
362219820Sjeff	osm_node_t *p_node = (osm_node_t *) p_map_item;
363219820Sjeff	uint32_t cPort;
364219820Sjeff	osm_node_t *p_nbnode;
365219820Sjeff	osm_physp_t *p_physp, *p_default_physp, *p_rphysp;
366219820Sjeff	uint8_t link_speed_act;
367219820Sjeff
368219820Sjeff	if (!p_node->node_info.num_ports)
369219820Sjeff		return;
370219820Sjeff
371219820Sjeff	for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) {
372219820Sjeff		uint8_t port_state;
373219820Sjeff
374219820Sjeff		p_physp = osm_node_get_physp_ptr(p_node, cPort);
375219820Sjeff		if (!p_physp)
376219820Sjeff			continue;
377219820Sjeff
378219820Sjeff		p_rphysp = p_physp->p_remote_physp;
379219820Sjeff		if (!p_rphysp)
380219820Sjeff			continue;
381219820Sjeff
382219820Sjeff		CL_ASSERT(cPort == p_physp->port_num);
383219820Sjeff
384219820Sjeff		if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
385219820Sjeff			p_default_physp = osm_node_get_physp_ptr(p_node, 0);
386219820Sjeff		else
387219820Sjeff			p_default_physp = p_physp;
388219820Sjeff
389219820Sjeff		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
390219820Sjeff			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
391219820Sjeff			" VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
392219820Sjeff			p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ?
393219820Sjeff			"SW" : p_node->node_info.node_type ==
394219820Sjeff			IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type ==
395219820Sjeff			IB_NODE_TYPE_ROUTER ? "Rt" : "**",
396219820Sjeff			p_default_physp->port_info.base_lid ==
397219820Sjeff			p_default_physp->port_info.
398219820Sjeff			master_sm_base_lid ? "-SM" : "",
399219820Sjeff			p_node->node_info.num_ports,
400219820Sjeff			cl_ntoh64(p_node->node_info.sys_guid),
401219820Sjeff			cl_ntoh64(p_node->node_info.node_guid),
402219820Sjeff			cl_ntoh64(p_physp->port_guid),
403219820Sjeff			cl_ntoh32(ib_node_info_get_vendor_id
404219820Sjeff				  (&p_node->node_info)),
405219820Sjeff			cl_ntoh16(p_node->node_info.device_id),
406219820Sjeff			cl_ntoh32(p_node->node_info.revision),
407219820Sjeff			p_node->print_desc,
408219820Sjeff			cl_ntoh16(p_default_physp->port_info.base_lid), cPort);
409219820Sjeff
410219820Sjeff		p_nbnode = p_rphysp->p_node;
411219820Sjeff
412219820Sjeff		if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH)
413219820Sjeff			p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0);
414219820Sjeff		else
415219820Sjeff			p_default_physp = p_rphysp;
416219820Sjeff
417219820Sjeff		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
418219820Sjeff			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
419219820Sjeff			" VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
420219820Sjeff			p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ?
421219820Sjeff			"SW" : p_nbnode->node_info.node_type ==
422219820Sjeff			IB_NODE_TYPE_CA ? "CA" :
423219820Sjeff			p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ?
424219820Sjeff			"Rt" : "**",
425219820Sjeff			p_default_physp->port_info.base_lid ==
426219820Sjeff			p_default_physp->port_info.
427219820Sjeff			master_sm_base_lid ? "-SM" : "",
428219820Sjeff			p_nbnode->node_info.num_ports,
429219820Sjeff			cl_ntoh64(p_nbnode->node_info.sys_guid),
430219820Sjeff			cl_ntoh64(p_nbnode->node_info.node_guid),
431219820Sjeff			cl_ntoh64(p_rphysp->port_guid),
432219820Sjeff			cl_ntoh32(ib_node_info_get_vendor_id
433219820Sjeff				  (&p_nbnode->node_info)),
434219820Sjeff			cl_ntoh32(p_nbnode->node_info.device_id),
435219820Sjeff			cl_ntoh32(p_nbnode->node_info.revision),
436219820Sjeff			p_nbnode->print_desc,
437219820Sjeff			cl_ntoh16(p_default_physp->port_info.base_lid),
438219820Sjeff			p_rphysp->port_num);
439219820Sjeff
440219820Sjeff		port_state = ib_port_info_get_port_state(&p_physp->port_info);
441219820Sjeff		link_speed_act =
442219820Sjeff		    ib_port_info_get_link_speed_active(&p_physp->port_info);
443219820Sjeff
444219820Sjeff		fprintf(file, "PHY=%s LOG=%s SPD=%s\n",
445219820Sjeff			p_physp->port_info.link_width_active == 1 ? "1x" :
446219820Sjeff			p_physp->port_info.link_width_active == 2 ? "4x" :
447219820Sjeff			p_physp->port_info.link_width_active == 8 ? "12x" :
448219820Sjeff			"??",
449219820Sjeff			port_state == IB_LINK_ACTIVE ? "ACT" :
450219820Sjeff			port_state == IB_LINK_ARMED ? "ARM" :
451219820Sjeff			port_state == IB_LINK_INIT ? "INI" : "DWN",
452219820Sjeff			link_speed_act == 1 ? "2.5" :
453219820Sjeff			link_speed_act == 2 ? "5" :
454219820Sjeff			link_speed_act == 4 ? "10" : "??");
455219820Sjeff	}
456219820Sjeff}
457219820Sjeff
458219820Sjeffstatic void print_node_report(cl_map_item_t *p_map_item, FILE *file, void *cxt)
459219820Sjeff{
460219820Sjeff	osm_node_t *p_node = (osm_node_t *) p_map_item;
461219820Sjeff	osm_opensm_t *osm = cxt;
462219820Sjeff	const osm_physp_t *p_physp, *p_remote_physp;
463219820Sjeff	const ib_port_info_t *p_pi;
464219820Sjeff	uint8_t port_num;
465219820Sjeff	uint32_t num_ports;
466219820Sjeff	uint8_t node_type;
467219820Sjeff
468219820Sjeff	node_type = osm_node_get_type(p_node);
469219820Sjeff
470219820Sjeff	num_ports = osm_node_get_num_physp(p_node);
471219820Sjeff	port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1;
472219820Sjeff	for (; port_num < num_ports; port_num++) {
473219820Sjeff		p_physp = osm_node_get_physp_ptr(p_node, port_num);
474219820Sjeff		if (!p_physp)
475219820Sjeff			continue;
476219820Sjeff
477219820Sjeff		fprintf(file, "%-11s : %s : %02X :",
478219820Sjeff			osm_get_manufacturer_str(cl_ntoh64
479219820Sjeff						 (osm_node_get_node_guid
480219820Sjeff						  (p_node))),
481219820Sjeff			osm_get_node_type_str_fixed_width(node_type), port_num);
482219820Sjeff
483219820Sjeff		p_pi = &p_physp->port_info;
484219820Sjeff
485219820Sjeff		/*
486219820Sjeff		 * Port state is not defined for switch port 0
487219820Sjeff		 */
488219820Sjeff		if (port_num == 0)
489219820Sjeff			fprintf(file, "     :");
490219820Sjeff		else
491219820Sjeff			fprintf(file, " %s :",
492219820Sjeff				osm_get_port_state_str_fixed_width
493219820Sjeff				(ib_port_info_get_port_state(p_pi)));
494219820Sjeff
495219820Sjeff		/*
496219820Sjeff		 * LID values are only meaningful in select cases.
497219820Sjeff		 */
498219820Sjeff		if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN
499219820Sjeff		    && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0)
500219820Sjeff			|| node_type != IB_NODE_TYPE_SWITCH))
501219820Sjeff			fprintf(file, " %04X :  %01X  :",
502219820Sjeff				cl_ntoh16(p_pi->base_lid),
503219820Sjeff				ib_port_info_get_lmc(p_pi));
504219820Sjeff		else
505219820Sjeff			fprintf(file, "      :     :");
506219820Sjeff
507219820Sjeff		if (port_num != 0)
508219820Sjeff			fprintf(file, " %s : %s : %s ",
509219820Sjeff				osm_get_mtu_str
510219820Sjeff				(ib_port_info_get_neighbor_mtu(p_pi)),
511219820Sjeff				osm_get_lwa_str(p_pi->link_width_active),
512219820Sjeff				osm_get_lsa_str
513219820Sjeff				(ib_port_info_get_link_speed_active(p_pi)));
514219820Sjeff		else
515219820Sjeff			fprintf(file, "      :     :     ");
516219820Sjeff
517219820Sjeff		if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid)
518219820Sjeff			fprintf(file, "* %016" PRIx64 " *",
519219820Sjeff				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
520219820Sjeff		else
521219820Sjeff			fprintf(file, ": %016" PRIx64 " :",
522219820Sjeff				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
523219820Sjeff
524219820Sjeff		if (port_num
525219820Sjeff		    && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) {
526219820Sjeff			p_remote_physp = osm_physp_get_remote(p_physp);
527219820Sjeff			if (p_remote_physp)
528219820Sjeff				fprintf(file, " %016" PRIx64 " (%02X)",
529219820Sjeff					cl_ntoh64(osm_physp_get_port_guid
530219820Sjeff					 (p_remote_physp)),
531219820Sjeff					osm_physp_get_port_num(p_remote_physp));
532219820Sjeff			else
533219820Sjeff				fprintf(file, " UNKNOWN");
534219820Sjeff		}
535219820Sjeff
536219820Sjeff		fprintf(file, "\n");
537219820Sjeff	}
538219820Sjeff
539219820Sjeff	fprintf(file, "------------------------------------------------------"
540219820Sjeff		"------------------------------------------------\n");
541219820Sjeff}
542219820Sjeff
543219820Sjeff/**********************************************************************
544219820Sjeff **********************************************************************/
545219820Sjeffstruct dump_context {
546219820Sjeff	osm_opensm_t *p_osm;
547219820Sjeff	FILE *file;
548219820Sjeff	void (*func) (cl_map_item_t *, FILE *, void *);
549219820Sjeff	void *cxt;
550219820Sjeff};
551219820Sjeff
552219820Sjeffstatic void dump_item(cl_map_item_t *item, void *cxt)
553219820Sjeff{
554219820Sjeff	((struct dump_context *)cxt)->func(item,
555219820Sjeff					   ((struct dump_context *)cxt)->file,
556219820Sjeff					   ((struct dump_context *)cxt)->cxt);
557219820Sjeff}
558219820Sjeff
559219820Sjeffstatic void dump_qmap(FILE *file, cl_qmap_t *map,
560219820Sjeff		      void (*func)(cl_map_item_t *, FILE *, void *), void *cxt)
561219820Sjeff{
562219820Sjeff	struct dump_context dump_context;
563219820Sjeff
564219820Sjeff	dump_context.file = file;
565219820Sjeff	dump_context.func = func;
566219820Sjeff	dump_context.cxt = cxt;
567219820Sjeff
568219820Sjeff	cl_qmap_apply_func(map, dump_item, &dump_context);
569219820Sjeff}
570219820Sjeff
571219820Sjeffvoid osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name,
572219820Sjeff			   cl_qmap_t * map,
573219820Sjeff			   void (*func) (cl_map_item_t *, FILE *, void *),
574219820Sjeff			   void *cxt)
575219820Sjeff{
576219820Sjeff	char path[1024];
577219820Sjeff	FILE *file;
578219820Sjeff
579219820Sjeff	snprintf(path, sizeof(path), "%s/%s",
580219820Sjeff		 p_osm->subn.opt.dump_files_dir, file_name);
581219820Sjeff
582219820Sjeff	file = fopen(path, "w");
583219820Sjeff	if (!file) {
584219820Sjeff		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
585219820Sjeff			"cannot create file \'%s\': %s\n",
586219820Sjeff			path, strerror(errno));
587219820Sjeff		return;
588219820Sjeff	}
589219820Sjeff
590219820Sjeff	dump_qmap(file, map, func, cxt);
591219820Sjeff
592219820Sjeff	fclose(file);
593219820Sjeff}
594219820Sjeff
595219820Sjeff/**********************************************************************
596219820Sjeff **********************************************************************/
597219820Sjeff
598219820Sjeffstatic void print_report(osm_opensm_t *osm, FILE *file)
599219820Sjeff{
600219820Sjeff	fprintf(file, "\n==================================================="
601219820Sjeff		"====================================================\n"
602219820Sjeff		"Vendor      : Ty : #  : Sta : LID  : LMC : MTU  : LWA :"
603219820Sjeff		" LSA : Port GUID        : Neighbor Port (Port #)\n");
604219820Sjeff	dump_qmap(stdout, &osm->subn.node_guid_tbl, print_node_report, osm);
605219820Sjeff}
606219820Sjeff
607219820Sjeffvoid osm_dump_mcast_routes(osm_opensm_t * osm)
608219820Sjeff{
609219820Sjeff	if (osm_log_is_active(&osm->log, OSM_LOG_ROUTING))
610219820Sjeff		/* multicast routes */
611219820Sjeff		osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
612219820Sjeff				      &osm->subn.sw_guid_tbl,
613219820Sjeff				      dump_mcast_routes, osm);
614219820Sjeff}
615219820Sjeff
616219820Sjeffvoid osm_dump_all(osm_opensm_t * osm)
617219820Sjeff{
618219820Sjeff	if (osm_log_is_active(&osm->log, OSM_LOG_ROUTING)) {
619219820Sjeff		/* unicast routes */
620219820Sjeff		osm_dump_qmap_to_file(osm, "opensm-lid-matrix.dump",
621219820Sjeff				      &osm->subn.sw_guid_tbl, dump_lid_matrix,
622219820Sjeff				      osm);
623219820Sjeff		osm_dump_qmap_to_file(osm, "opensm-lfts.dump",
624219820Sjeff				      &osm->subn.sw_guid_tbl, dump_ucast_lfts,
625219820Sjeff				      osm);
626219820Sjeff		if (osm_log_is_active(&osm->log, OSM_LOG_DEBUG))
627219820Sjeff			dump_qmap(stdout, &osm->subn.sw_guid_tbl,
628219820Sjeff				  dump_ucast_path_distribution, osm);
629219820Sjeff		osm_dump_qmap_to_file(osm, "opensm.fdbs",
630219820Sjeff				      &osm->subn.sw_guid_tbl,
631219820Sjeff				      dump_ucast_routes, osm);
632219820Sjeff		/* multicast routes */
633219820Sjeff		osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
634219820Sjeff				      &osm->subn.sw_guid_tbl,
635219820Sjeff				      dump_mcast_routes, osm);
636219820Sjeff	}
637219820Sjeff	osm_dump_qmap_to_file(osm, "opensm-subnet.lst",
638219820Sjeff			      &osm->subn.node_guid_tbl, dump_topology_node,
639219820Sjeff			      osm);
640219820Sjeff	if (osm_log_is_active(&osm->log, OSM_LOG_VERBOSE))
641219820Sjeff		print_report(osm, stdout);
642219820Sjeff}
643