Blame scripts/IBswcountlimits.pm

Packit db064d
#!/usr/bin/perl
Packit db064d
#
Packit db064d
# Copyright (c) 2006 The Regents of the University of California.
Packit db064d
# Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
Packit db064d
#
Packit db064d
# Produced at Lawrence Livermore National Laboratory.
Packit db064d
# Written by Ira Weiny <weiny2@llnl.gov>.
Packit db064d
#            Erez Strauss from Voltaire for help in the get_link_ends code.
Packit db064d
#
Packit db064d
# This software is available to you under a choice of one of two
Packit db064d
# licenses.  You may choose to be licensed under the terms of the GNU
Packit db064d
# General Public License (GPL) Version 2, available from the file
Packit db064d
# COPYING in the main directory of this source tree, or the
Packit db064d
# OpenIB.org BSD license below:
Packit db064d
#
Packit db064d
#     Redistribution and use in source and binary forms, with or
Packit db064d
#     without modification, are permitted provided that the following
Packit db064d
#     conditions are met:
Packit db064d
#
Packit db064d
#      - Redistributions of source code must retain the above
Packit db064d
#        copyright notice, this list of conditions and the following
Packit db064d
#        disclaimer.
Packit db064d
#
Packit db064d
#      - Redistributions in binary form must reproduce the above
Packit db064d
#        copyright notice, this list of conditions and the following
Packit db064d
#        disclaimer in the documentation and/or other materials
Packit db064d
#        provided with the distribution.
Packit db064d
#
Packit db064d
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit db064d
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit db064d
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit db064d
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit db064d
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit db064d
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit db064d
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit db064d
# SOFTWARE.
Packit db064d
#
Packit db064d
Packit db064d
use strict;
Packit db064d
Packit db064d
%IBswcountlimits::cur_counts      = ();
Packit db064d
%IBswcountlimits::new_counts      = ();
Packit db064d
@IBswcountlimits::suppress_errors = ();
Packit db064d
$IBswcountlimits::link_ends       = undef;
Packit db064d
$IBswcountlimits::pause_time      = 10;
Packit db064d
$IBswcountlimits::cache_dir       = "/var/cache/infiniband-diags";
Packit db064d
Packit db064d
# all the PerfMgt counters
Packit db064d
@IBswcountlimits::counters = (
Packit db064d
	"SymbolErrorCounter",        "LinkErrorRecoveryCounter",
Packit db064d
	"LinkDownedCounter",          "PortRcvErrors",
Packit db064d
	"PortRcvRemotePhysicalErrors", "PortRcvSwitchRelayErrors",
Packit db064d
	"PortXmitDiscards",         "PortXmitConstraintErrors",
Packit db064d
	"PortRcvConstraintErrors", "LocalLinkIntegrityErrors",
Packit db064d
	"ExcessiveBufferOverrunErrors", "VL15Dropped",
Packit db064d
	"PortXmitData",             "PortRcvData",
Packit db064d
	"PortXmitPkts",             "PortRcvPkts"
Packit db064d
);
Packit db064d
Packit db064d
# non-critical counters
Packit db064d
%IBswcountlimits::error_counters = (
Packit db064d
	"SymbolErrorCounter",
Packit db064d
"No action is required except if counter is increasing along with LinkErrorRecoveryCounter",
Packit db064d
	"LinkErrorRecoveryCounter",
Packit db064d
"If this is increasing along with SymbolErrorCounter this may indicate a bad link, run ibswportwatch.pl on this port",
Packit db064d
	"LinkDownedCounter",
Packit db064d
	"Number of times the port has gone down (Usually for valid reasons)",
Packit db064d
	"PortRcvErrors",
Packit db064d
"This is a bad link, if the link is internal to a 288 try setting SDR, otherwise check the cable",
Packit db064d
	"PortRcvRemotePhysicalErrors",
Packit db064d
	"This indicates a problem ELSEWHERE in the fabric.",
Packit db064d
	"PortXmitDiscards",
Packit db064d
"This is a symptom of congestion and may require tweaking either HOQ or switch lifetime values",
Packit db064d
	"PortXmitConstraintErrors",
Packit db064d
	"This is a result of bad partitioning, check partition configuration.",
Packit db064d
	"PortRcvConstraintErrors",
Packit db064d
	"This is a result of bad partitioning, check partition configuration.",
Packit db064d
	"LocalLinkIntegrityErrors",
Packit db064d
	"May indicate a bad link, run ibswportwatch.pl on this port",
Packit db064d
	"ExcessiveBufferOverrunErrors",
Packit db064d
"This is a flow control state machine error and can be caused by packets with physical errors",
Packit db064d
	"VL15Dropped",
Packit db064d
	"check with ibswportwatch.pl, if increasing in SMALL increments, OK",
Packit db064d
	"PortRcvSwitchRelayErrors",
Packit db064d
	"This counter can increase due to a valid network event"
Packit db064d
);
Packit db064d
Packit db064d
sub check_counters
Packit db064d
{
Packit db064d
	my $print_action = $_[0];
Packit db064d
	my $actions      = undef;
Packit db064d
Packit db064d
	COUNTER: foreach my $cnt (keys %IBswcountlimits::error_counters) {
Packit db064d
		if ($IBswcountlimits::cur_counts{$cnt} > 0) {
Packit db064d
			foreach my $sup_cnt (@IBswcountlimits::suppress_errors) {
Packit db064d
				if ("$cnt" eq $sup_cnt) { next COUNTER; }
Packit db064d
			}
Packit db064d
			print " [$cnt == $IBswcountlimits::cur_counts{$cnt}]";
Packit db064d
			if ("$print_action" eq "yes") {
Packit db064d
				$actions = join " ",
Packit db064d
				  (
Packit db064d
					$actions,
Packit db064d
					"         $cnt: $IBswcountlimits::error_counters{$cnt}\n"
Packit db064d
				  );
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	if ($actions) {
Packit db064d
		print "\n         Actions:\n$actions";
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
# Data counters
Packit db064d
%IBswcountlimits::data_counters = (
Packit db064d
	"PortXmitData",
Packit db064d
"Total number of data octets, divided by 4, transmitted on all VLs from the port",
Packit db064d
	"PortRcvData",
Packit db064d
"Total number of data octets, divided by 4, received on all VLs to the port",
Packit db064d
	"PortXmitPkts",
Packit db064d
"Total number of packets, excluding link packets, transmitted on all VLs from the port",
Packit db064d
	"PortRcvPkts",
Packit db064d
"Total number of packets, excluding link packets, received on all VLs to the port"
Packit db064d
);
Packit db064d
Packit db064d
sub check_data_counters
Packit db064d
{
Packit db064d
	my $print_action = $_[0];
Packit db064d
	my $actions      = undef;
Packit db064d
Packit db064d
	COUNTER: foreach my $cnt (keys %IBswcountlimits::data_counters) {
Packit db064d
		print " [$cnt == $IBswcountlimits::cur_counts{$cnt}]";
Packit db064d
		if ("$print_action" eq "yes") {
Packit db064d
			$actions = join " ",
Packit db064d
			  (
Packit db064d
				$actions,
Packit db064d
				"         $cnt: $IBswcountlimits::data_counters{$cnt}\n"
Packit db064d
			  );
Packit db064d
		}
Packit db064d
	}
Packit db064d
	if ($actions) {
Packit db064d
		print "\n         Descriptions:\n$actions";
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
sub print_data_rates
Packit db064d
{
Packit db064d
	COUNTER: foreach my $cnt (keys %IBswcountlimits::data_counters) {
Packit db064d
		my $cnt_per_second = calculate_rate(
Packit db064d
			$IBswcountlimits::cur_counts{$cnt},
Packit db064d
			$IBswcountlimits::new_counts{$cnt}
Packit db064d
		);
Packit db064d
		print "   $cnt_per_second $cnt/second\n";
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# Rate dependent counters
Packit db064d
# calculate the count/sec
Packit db064d
# calculate_rate old_count new_count
Packit db064d
sub calculate_rate
Packit db064d
{
Packit db064d
	my $rate    = 0;
Packit db064d
	my $old_val = $_[0];
Packit db064d
	my $new_val = $_[1];
Packit db064d
	my $rate    = ($new_val - $old_val) / $IBswcountlimits::pause_time;
Packit db064d
	return ($rate);
Packit db064d
}
Packit db064d
%IBswcountlimits::rate_dep_thresholds = (
Packit db064d
	"SymbolErrorCounter", 10, "LinkErrorRecoveryCounter",        10,
Packit db064d
	"PortRcvErrors",    10, "LocalLinkIntegrityErrors", 10,
Packit db064d
	"PortXmitDiscards",  10
Packit db064d
);
Packit db064d
Packit db064d
sub check_counter_rates
Packit db064d
{
Packit db064d
	foreach my $rate_count (keys %IBswcountlimits::rate_dep_thresholds) {
Packit db064d
		my $rate = calculate_rate(
Packit db064d
			$IBswcountlimits::cur_counts{$rate_count},
Packit db064d
			$IBswcountlimits::new_counts{$rate_count}
Packit db064d
		);
Packit db064d
		if ($rate > $IBswcountlimits::rate_dep_thresholds{$rate_count}) {
Packit db064d
			print "Detected excessive rate for $rate_count ($rate cnts/sec)\n";
Packit db064d
		} elsif ($rate > 0) {
Packit db064d
			print "Detected rate for $rate_count ($rate cnts/sec)\n";
Packit db064d
		}
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
#
Packit db064d
sub clear_counters
Packit db064d
{
Packit db064d
	# clear the counters
Packit db064d
	foreach my $count (@IBswcountlimits::counters) {
Packit db064d
		$IBswcountlimits::cur_counts{$count} = 0;
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
#
Packit db064d
sub any_counts
Packit db064d
{
Packit db064d
	my $total = 0;
Packit db064d
	my $count = 0;
Packit db064d
	foreach $count (keys %IBswcountlimits::critical) {
Packit db064d
		$total = $total + $IBswcountlimits::cur_counts{$count};
Packit db064d
	}
Packit db064d
	COUNTER: foreach $count (keys %IBswcountlimits::error_counters) {
Packit db064d
		foreach my $sup_cnt (@IBswcountlimits::suppress_errors) {
Packit db064d
			if ("$count" eq $sup_cnt) { next COUNTER; }
Packit db064d
		}
Packit db064d
		$total = $total + $IBswcountlimits::cur_counts{$count};
Packit db064d
	}
Packit db064d
	return ($total);
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
#
Packit db064d
sub ensure_cache_dir
Packit db064d
{
Packit db064d
	if (!(-d "$IBswcountlimits::cache_dir") &&
Packit db064d
	    !mkdir($IBswcountlimits::cache_dir, 0700)) {
Packit db064d
		die "cannot create $IBswcountlimits::cache_dir: $!\n";
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# get_cache_file(ca_name, ca_port)
Packit db064d
#
Packit db064d
sub get_cache_file
Packit db064d
{
Packit db064d
	my $ca_name = $_[0];
Packit db064d
	my $ca_port = $_[1];
Packit db064d
	ensure_cache_dir;
Packit db064d
	return (
Packit db064d
		"$IBswcountlimits::cache_dir/ibnetdiscover-$ca_name-$ca_port.topology");
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# get_ca_name_port_param_string(ca_name, ca_port)
Packit db064d
#
Packit db064d
sub get_ca_name_port_param_string
Packit db064d
{
Packit db064d
	my $ca_name = $_[0];
Packit db064d
	my $ca_port = $_[1];
Packit db064d
Packit db064d
	if ("$ca_name" ne "") { $ca_name = "-C $ca_name"; }
Packit db064d
	if ("$ca_port" ne "") { $ca_port = "-P $ca_port"; }
Packit db064d
Packit db064d
	return ("$ca_name $ca_port");
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# generate_ibnetdiscover_topology(ca_name, ca_port)
Packit db064d
#
Packit db064d
sub generate_ibnetdiscover_topology
Packit db064d
{
Packit db064d
	my $ca_name      = $_[0];
Packit db064d
	my $ca_port      = $_[1];
Packit db064d
	my $cache_file   = get_cache_file($ca_name, $ca_port);
Packit db064d
	my $extra_params = get_ca_name_port_param_string($ca_name, $ca_port);
Packit db064d
Packit db064d
	if (`ibnetdiscover -g $extra_params > $cache_file`) {
Packit db064d
		die "Execution of ibnetdiscover failed: $!\n";
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# get_link_ends(regenerate_map, ca_name, ca_port)
Packit db064d
#
Packit db064d
sub get_link_ends
Packit db064d
{
Packit db064d
	my $regenerate_map = $_[0];
Packit db064d
	my $ca_name        = $_[1];
Packit db064d
	my $ca_port        = $_[2];
Packit db064d
Packit db064d
	my $cache_file = get_cache_file($ca_name, $ca_port);
Packit db064d
Packit db064d
	if ($regenerate_map || !(-f "$cache_file")) {
Packit db064d
		generate_ibnetdiscover_topology($ca_name, $ca_port);
Packit db064d
	}
Packit db064d
	open IBNET_TOPO, "<$cache_file"
Packit db064d
	  or die "Failed to open ibnet topology: $!\n";
Packit db064d
	my $in_switch  = "no";
Packit db064d
	my $desc       = "";
Packit db064d
	my $guid       = "";
Packit db064d
	my $loc_sw_lid = "";
Packit db064d
Packit db064d
	my $loc_port = "";
Packit db064d
	my $line     = "";
Packit db064d
Packit db064d
	while ($line = <IBNET_TOPO>) {
Packit db064d
		if ($line =~ /^Switch.*\"S-(.*)\"\s+#.*\"(.*)\".* lid (\d+).*/) {
Packit db064d
			$guid       = $1;
Packit db064d
			$desc       = $2;
Packit db064d
			$loc_sw_lid = $3;
Packit db064d
			$in_switch  = "yes";
Packit db064d
		}
Packit db064d
		if ($in_switch eq "yes") {
Packit db064d
			my $rec = undef;
Packit db064d
			if ($line =~
Packit db064d
/^\[(\d+)\]\s+\"[HSR]-(.+)\"\[(\d+)\](\(.+\))?\s+#.*\"(.*)\"\.* lid (\d+).*/
Packit db064d
			  )
Packit db064d
			{
Packit db064d
				$loc_port = $1;
Packit db064d
				my $rem_guid      = $2;
Packit db064d
				my $rem_port      = $3;
Packit db064d
				my $rem_port_guid = $4;
Packit db064d
				my $rem_desc      = $5;
Packit db064d
				my $rem_lid       = $6;
Packit db064d
				$rec = {
Packit db064d
					loc_guid      => "0x$guid",
Packit db064d
					loc_port      => $loc_port,
Packit db064d
					loc_ext_port  => "",
Packit db064d
					loc_desc      => $desc,
Packit db064d
					loc_sw_lid    => $loc_sw_lid,
Packit db064d
					rem_guid      => "0x$rem_guid",
Packit db064d
					rem_lid       => $rem_lid,
Packit db064d
					rem_port      => $rem_port,
Packit db064d
					rem_ext_port  => "",
Packit db064d
					rem_desc      => $rem_desc,
Packit db064d
					rem_port_guid => $rem_port_guid
Packit db064d
				};
Packit db064d
			}
Packit db064d
			if ($line =~
Packit db064d
/^\[(\d+)\]\[ext (\d+)\]\s+\"[HSR]-(.+)\"\[(\d+)\](\(.+\))?\s+#.*\"(.*)\"\.* lid (\d+).*/
Packit db064d
			  )
Packit db064d
			{
Packit db064d
				$loc_port = $1;
Packit db064d
				my $loc_ext_port  = $2;
Packit db064d
				my $rem_guid      = $3;
Packit db064d
				my $rem_port      = $4;
Packit db064d
				my $rem_port_guid = $5;
Packit db064d
				my $rem_desc      = $6;
Packit db064d
				my $rem_lid       = $7;
Packit db064d
				$rec = {
Packit db064d
					loc_guid      => "0x$guid",
Packit db064d
					loc_port      => $loc_port,
Packit db064d
					loc_ext_port  => $loc_ext_port,
Packit db064d
					loc_desc      => $desc,
Packit db064d
					loc_sw_lid    => $loc_sw_lid,
Packit db064d
					rem_guid      => "0x$rem_guid",
Packit db064d
					rem_lid       => $rem_lid,
Packit db064d
					rem_port      => $rem_port,
Packit db064d
					rem_ext_port  => "",
Packit db064d
					rem_desc      => $rem_desc,
Packit db064d
					rem_port_guid => $rem_port_guid
Packit db064d
				};
Packit db064d
			}
Packit db064d
			if ($line =~
Packit db064d
/^\[(\d+)\]\s+\"[HSR]-(.+)\"\[(\d+)\]\[ext (\d+)\](\(.+\))?\s+#.*\"(.*)\"\.* lid (\d+).*/
Packit db064d
			  )
Packit db064d
			{
Packit db064d
				$loc_port = $1;
Packit db064d
				my $rem_guid      = $2;
Packit db064d
				my $rem_port      = $3;
Packit db064d
				my $rem_ext_port  = $4;
Packit db064d
				my $rem_port_guid = $5;
Packit db064d
				my $rem_desc      = $6;
Packit db064d
				my $rem_lid       = $7;
Packit db064d
				$rec = {
Packit db064d
					loc_guid      => "0x$guid",
Packit db064d
					loc_port      => $loc_port,
Packit db064d
					loc_ext_port  => "",
Packit db064d
					loc_desc      => $desc,
Packit db064d
					loc_sw_lid    => $loc_sw_lid,
Packit db064d
					rem_guid      => "0x$rem_guid",
Packit db064d
					rem_lid       => $rem_lid,
Packit db064d
					rem_port      => $rem_port,
Packit db064d
					rem_ext_port  => $rem_ext_port,
Packit db064d
					rem_desc      => $rem_desc,
Packit db064d
					rem_port_guid => $rem_port_guid
Packit db064d
				};
Packit db064d
			}
Packit db064d
			if ($line =~
Packit db064d
/^\[(\d+)\]\[ext (\d+)\]\s+\"[HSR]-(.+)\"\[(\d+)\]\[ext (\d+)\](\(.+\))?\s+#.*\"(.*)\"\.* lid (\d+).*/
Packit db064d
			  )
Packit db064d
			{
Packit db064d
				$loc_port = $1;
Packit db064d
				my $loc_ext_port  = $2;
Packit db064d
				my $rem_guid      = $3;
Packit db064d
				my $rem_port      = $4;
Packit db064d
				my $rem_ext_port  = $5;
Packit db064d
				my $rem_port_guid = $6;
Packit db064d
				my $rem_desc      = $7;
Packit db064d
				my $rem_lid       = $8;
Packit db064d
				$rec = {
Packit db064d
					loc_guid      => "0x$guid",
Packit db064d
					loc_port      => $loc_port,
Packit db064d
					loc_ext_port  => $loc_ext_port,
Packit db064d
					loc_desc      => $desc,
Packit db064d
					loc_sw_lid    => $loc_sw_lid,
Packit db064d
					rem_guid      => "0x$rem_guid",
Packit db064d
					rem_lid       => $rem_lid,
Packit db064d
					rem_port      => $rem_port,
Packit db064d
					rem_ext_port  => $rem_ext_port,
Packit db064d
					rem_desc      => $rem_desc,
Packit db064d
					rem_port_guid => $rem_port_guid
Packit db064d
				};
Packit db064d
			}
Packit db064d
			if ($rec) {
Packit db064d
				$rec->{rem_port_guid} =~ s/\((.*)\)/$1/;
Packit db064d
				$IBswcountlimits::link_ends{"0x$guid"}{$loc_port} = $rec;
Packit db064d
			}
Packit db064d
		}
Packit db064d
Packit db064d
		if ($line =~ /^Ca.*/ || $line =~ /^Rt.*/) { $in_switch = "no"; }
Packit db064d
	}
Packit db064d
	close IBNET_TOPO;
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# get_num_ports(switch_guid, ca_name, ca_port)
Packit db064d
#
Packit db064d
sub get_num_ports
Packit db064d
{
Packit db064d
	my $guid         = $_[0];
Packit db064d
	my $ca_name      = $_[1];
Packit db064d
	my $ca_port      = $_[2];
Packit db064d
	my $num_ports    = 0;
Packit db064d
	my $extra_params = get_ca_name_port_param_string($ca_name, $ca_port);
Packit db064d
Packit db064d
	my $data         = `smpquery $extra_params -G nodeinfo $guid` ||
Packit db064d
		die "'smpquery $extra_params -G nodeinfo $guid' faild\n";
Packit db064d
	my @lines        = split("\n", $data);
Packit db064d
	my $pkt_lifetime = "";
Packit db064d
	foreach my $line (@lines) {
Packit db064d
		if ($line =~ /^NumPorts:\.+(.*)/) { $num_ports = $1; }
Packit db064d
	}
Packit db064d
	return ($num_ports);
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# format_guid(guid)
Packit db064d
# The diags store the guids as strings.  This converts the guid supplied
Packit db064d
# to the correct string format.
Packit db064d
# eg: 0x0008f10400411f56 == 0x8f10400411f56
Packit db064d
#
Packit db064d
sub format_guid
Packit db064d
{
Packit db064d
	my $guid     = $_[0];
Packit db064d
	my $guid_str = "";
Packit db064d
Packit db064d
	$guid =~ tr/[A-F]/[a-f]/;
Packit db064d
	if ($guid =~ /0x(.*)/) {
Packit db064d
		$guid_str = sprintf("0x%016s", $1);
Packit db064d
	} else {
Packit db064d
		$guid_str = sprintf("0x%016s", $guid);
Packit db064d
	}
Packit db064d
	return ($guid_str);
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# convert_dr_to_guid(direct_route)
Packit db064d
#
Packit db064d
sub convert_dr_to_guid
Packit db064d
{
Packit db064d
	my $guid = undef;
Packit db064d
Packit db064d
	my $data = `smpquery nodeinfo -D $_[0]` ||
Packit db064d
		die "'mpquery nodeinfo -D $_[0]' failed\n";
Packit db064d
	my @lines = split("\n", $data);
Packit db064d
	foreach my $line (@lines) {
Packit db064d
		if ($line =~ /^PortGuid:\.+(.*)/) { $guid = $1; }
Packit db064d
	}
Packit db064d
	return format_guid($guid);
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# get_node_type(guid_or_direct_route)
Packit db064d
#
Packit db064d
sub get_node_type
Packit db064d
{
Packit db064d
	my $type      = undef;
Packit db064d
	my $query_arg = "smpquery nodeinfo ";
Packit db064d
	if ($_[0] =~ /x/) {
Packit db064d
		# assume arg is a guid if contains an x
Packit db064d
		$query_arg .= "-G " . $_[0];
Packit db064d
	} else {
Packit db064d
		# assume arg is a direct path
Packit db064d
		$query_arg .= "-D " . $_[0];
Packit db064d
	}
Packit db064d
Packit db064d
	my $data = `$query_arg` ||
Packit db064d
		die "'$query_arg' failed\n";
Packit db064d
	my @lines = split("\n", $data);
Packit db064d
	foreach my $line (@lines) {
Packit db064d
		if ($line =~ /^NodeType:\.+(.*)/) { $type = $1; }
Packit db064d
	}
Packit db064d
	return $type;
Packit db064d
}
Packit db064d
Packit db064d
# =========================================================================
Packit db064d
# is_switch(guid_or_direct_route)
Packit db064d
#
Packit db064d
sub is_switch
Packit db064d
{
Packit db064d
	my $node_type = &get_node_type($_[0]);
Packit db064d
	return ($node_type =~ /Switch/);
Packit db064d
}