ibfindnodesusing.pl revision 219820
1254885Sdumbbell#!/usr/bin/perl
2254885Sdumbbell#
3254885Sdumbbell# Copyright (C) 2001-2003 The Regents of the University of California.
4254885Sdumbbell# Copyright (c) 2006 The Regents of the University of California.
5254885Sdumbbell# Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
6254885Sdumbbell#
7254885Sdumbbell# Produced at Lawrence Livermore National Laboratory.
8254885Sdumbbell# Written by Ira Weiny <weiny2@llnl.gov>
9254885Sdumbbell#            Jim Garlick <garlick@llnl.gov>
10254885Sdumbbell#            Albert Chu <chu11@llnl.gov>
11254885Sdumbbell#
12254885Sdumbbell# This software is available to you under a choice of one of two
13254885Sdumbbell# licenses.  You may choose to be licensed under the terms of the GNU
14254885Sdumbbell# General Public License (GPL) Version 2, available from the file
15254885Sdumbbell# COPYING in the main directory of this source tree, or the
16254885Sdumbbell# OpenIB.org BSD license below:
17254885Sdumbbell#
18254885Sdumbbell#     Redistribution and use in source and binary forms, with or
19254885Sdumbbell#     without modification, are permitted provided that the following
20254885Sdumbbell#     conditions are met:
21254885Sdumbbell#
22254885Sdumbbell#      - Redistributions of source code must retain the above
23254885Sdumbbell#        copyright notice, this list of conditions and the following
24254885Sdumbbell#        disclaimer.
25254885Sdumbbell#
26254885Sdumbbell#      - Redistributions in binary form must reproduce the above
27254885Sdumbbell#        copyright notice, this list of conditions and the following
28254885Sdumbbell#        disclaimer in the documentation and/or other materials
29254885Sdumbbell#        provided with the distribution.
30254885Sdumbbell#
31254885Sdumbbell# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32254885Sdumbbell# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33254885Sdumbbell# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34254885Sdumbbell# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
35254885Sdumbbell# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
36254885Sdumbbell# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
37254885Sdumbbell# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38254885Sdumbbell# SOFTWARE.
39254885Sdumbbell#
40254885Sdumbbell
41254885Sdumbbelluse strict;
42254885Sdumbbell
43254885Sdumbbelluse Getopt::Std;
44254885Sdumbbelluse IBswcountlimits;
45254885Sdumbbellmy $ca_name = "";
46254885Sdumbbellmy $ca_port = "";
47254885Sdumbbell
48254885Sdumbbell# =========================================================================
49254885Sdumbbell#
50254885Sdumbbellsub get_hosts_routed
51254885Sdumbbell{
52254885Sdumbbell	my $sw_guid      = $_[0];
53254885Sdumbbell	my $sw_port      = $_[1];
54254885Sdumbbell	my @hosts        = undef;
55254885Sdumbbell	my $extra_params = get_ca_name_port_param_string($ca_name, $ca_port);
56254885Sdumbbell
57254885Sdumbbell	if ($sw_guid eq "") { return (@hosts); }
58254885Sdumbbell
59254885Sdumbbell	my $data = `ibroute $extra_params -G $sw_guid`;
60254885Sdumbbell	my @lines = split("\n", $data);
61254885Sdumbbell	foreach my $line (@lines) {
62254885Sdumbbell		if ($line =~ /\w+\s+(\d+)\s+:\s+\(Channel Adapter.*:\s+'(.*)'\)/) {
63254885Sdumbbell			if ($1 == $sw_port) {
64254885Sdumbbell				push @hosts, $2;
65254885Sdumbbell			}
66254885Sdumbbell		}
67254885Sdumbbell	}
68254885Sdumbbell
69254885Sdumbbell	return (@hosts);
70254885Sdumbbell}
71254885Sdumbbell
72254885Sdumbbell# =========================================================================
73254885Sdumbbell#
74254885Sdumbbellsub usage_and_exit
75254885Sdumbbell{
76254885Sdumbbell	my $prog = $_[0];
77254885Sdumbbell	print
78254885Sdumbbell"Usage: $prog [-R -C <ca_name> -P <ca_port>] <switch_guid|switch_name> <port>\n";
79254885Sdumbbell	print "   find a list of nodes which are routed through switch:port\n";
80254885Sdumbbell	print "   -R Recalculate ibnetdiscover information\n";
81254885Sdumbbell	print "   -C <ca_name> use selected Channel Adaptor name for queries\n";
82254885Sdumbbell	print "   -P <ca_port> use selected channel adaptor port for queries\n";
83254885Sdumbbell	exit 2;
84254885Sdumbbell}
85254885Sdumbbell
86254885Sdumbbellmy $argv0          = `basename $0`;
87254885Sdumbbellmy $regenerate_map = undef;
88254885Sdumbbellchomp $argv0;
89254885Sdumbbellif (!getopts("hRC:P:"))          { usage_and_exit $argv0; }
90254885Sdumbbellif (defined $Getopt::Std::opt_h) { usage_and_exit $argv0; }
91254885Sdumbbellif (defined $Getopt::Std::opt_R) { $regenerate_map = $Getopt::Std::opt_R; }
92254885Sdumbbellif (defined $Getopt::Std::opt_C) { $ca_name        = $Getopt::Std::opt_C; }
93254885Sdumbbellif (defined $Getopt::Std::opt_P) { $ca_port        = $Getopt::Std::opt_P; }
94254885Sdumbbell
95254885Sdumbbellmy $target_switch = format_guid($ARGV[0]);
96254885Sdumbbellmy $target_port   = $ARGV[1];
97254885Sdumbbell
98254885Sdumbbellget_link_ends($regenerate_map, $ca_name, $ca_port);
99254885Sdumbbell
100254885Sdumbbellif ($target_switch eq "" || $target_port eq "") {
101254885Sdumbbell	usage_and_exit $argv0;
102254885Sdumbbell}
103254885Sdumbbell
104254885Sdumbbell# sortn:
105254885Sdumbbell#
106254885Sdumbbell# sort a group of alphanumeric strings by the last group of digits on
107254885Sdumbbell# those strings, if such exists (good for numerically suffixed host lists)
108254885Sdumbbell#
109254885Sdumbbellsub sortn
110254885Sdumbbell{
111254885Sdumbbell	map { $$_[0] }
112254885Sdumbbell	  sort { ($$a[1] || 0) <=> ($$b[1] || 0) } map { [$_, /(\d*)$/] } @_;
113254885Sdumbbell}
114254885Sdumbbell
115254885Sdumbbell# comp2():
116254885Sdumbbell#
117254885Sdumbbell# takes a list of names and returns a hash of arrays, indexed by name prefix,
118254885Sdumbbell# each containing a list of numerical ranges describing the initial list.
119254885Sdumbbell#
120254885Sdumbbell# e.g.: %hash = comp2(lx01,lx02,lx03,lx05,dev0,dev1,dev21)
121254885Sdumbbell#       will return:
122254885Sdumbbell#       $hash{"lx"}  = ["01-03", "05"]
123254885Sdumbbell#       $hash{"dev"} = ["0-1", "21"]
124254885Sdumbbell#
125254885Sdumbbellsub comp2
126254885Sdumbbell{
127254885Sdumbbell	my (%i) = ();
128254885Sdumbbell	my (%s) = ();
129254885Sdumbbell
130254885Sdumbbell	# turn off warnings here to avoid perl complaints about
131254885Sdumbbell	# uninitialized values for members of %i and %s
132254885Sdumbbell	local ($^W) = 0;
133254885Sdumbbell	push(
134254885Sdumbbell		@{
135254885Sdumbbell			$s{$$_[0]}[
136254885Sdumbbell			  (
137254885Sdumbbell				  $s{$$_[0]}[$i{$$_[0]}][$#{$s{$$_[0]}[$i{$$_[0]}]}] ==
138254885Sdumbbell				    ($$_[1] - 1)
139254885Sdumbbell			  ) ? $i{$$_[0]} : ++$i{$$_[0]}
140254885Sdumbbell			]
141254885Sdumbbell		  },
142254885Sdumbbell		($$_[1])
143254885Sdumbbell	) for map { [/(.*?)(\d*)$/] } sortn(@_);
144254885Sdumbbell
145254885Sdumbbell	for my $key (keys %s) {
146254885Sdumbbell		@{$s{$key}} =
147254885Sdumbbell		  map { $#$_ > 0 ? "$$_[0]-$$_[$#$_]" : @{$_} } @{$s{$key}};
148254885Sdumbbell	}
149254885Sdumbbell
150254885Sdumbbell	return %s;
151254885Sdumbbell}
152254885Sdumbbell
153254885Sdumbbellsub compress_hostlist
154254885Sdumbbell{
155254885Sdumbbell	my %rng  = comp2(@_);
156254885Sdumbbell	my @list = ();
157254885Sdumbbell
158254885Sdumbbell	local $" = ",";
159254885Sdumbbell
160254885Sdumbbell	foreach my $k (keys %rng) {
161254885Sdumbbell		@{$rng{$k}} = map { "$k$_" } @{$rng{$k}};
162254885Sdumbbell	}
163254885Sdumbbell	@list = map { @{$rng{$_}} } sort keys %rng;
164254885Sdumbbell	return "@list";
165254885Sdumbbell}
166254885Sdumbbell
167254885Sdumbbell# =========================================================================
168254885Sdumbbell#
169254885Sdumbbellsub main
170254885Sdumbbell{
171254885Sdumbbell	my $found_switch = undef;
172254885Sdumbbell	my $cache_file = get_cache_file($ca_name, $ca_port);
173254885Sdumbbell	open IBNET_TOPO, "<$cache_file" or die "Failed to open ibnet topology\n";
174254885Sdumbbell	my $in_switch   = "no";
175254885Sdumbbell	my $switch_guid = "";
176254885Sdumbbell	my $desc        = undef;
177254885Sdumbbell	my %ports       = undef;
178254885Sdumbbell	while (my $line = <IBNET_TOPO>) {
179254885Sdumbbell
180254885Sdumbbell		if ($line =~ /^Switch.*\"S-(.*)\"\s+# (.*) port.*/) {
181254885Sdumbbell			$switch_guid = $1;
182254885Sdumbbell			$desc        = $2;
183254885Sdumbbell			if ("0x$switch_guid" eq $target_switch
184254885Sdumbbell				|| $desc =~ /.*$target_switch\s+.*/)
185254885Sdumbbell			{
186254885Sdumbbell				$found_switch = "yes";
187				goto FOUND;
188			}
189		}
190		if ($line =~ /^Ca.*/ || $line =~ /^Rt.*/) { $in_switch = "no"; }
191
192		if ($line =~ /^\[(\d+)\].*/ && $in_switch eq "yes") {
193			$ports{$1} = $line;
194		}
195
196	}
197
198	FOUND:
199	close IBNET_TOPO;
200	if (!$found_switch) {
201		print "Switch \"$target_switch\" not found\n";
202		print "   Try running with the \"-R\" or \"-P\" option.\n";
203		exit 1;
204	}
205
206	$switch_guid = "0x$switch_guid";
207
208	my $hr          = $IBswcountlimits::link_ends{$switch_guid}{$target_port};
209	my $rem_sw_guid = $hr->{rem_guid};
210	my $rem_sw_port = $hr->{rem_port};
211	my $rem_sw_desc = $hr->{rem_desc};
212
213	my @hosts = undef;
214	@hosts = get_hosts_routed($switch_guid, $target_port);
215
216	my $hosts = compress_hostlist(@hosts);
217	@hosts = split ",", $hosts;
218	print
219"$switch_guid $target_port ($desc)  ==>>  $rem_sw_guid $rem_sw_port ($rem_sw_desc)\n";
220	print "@hosts\n\n";
221
222	@hosts = get_hosts_routed($rem_sw_guid, $rem_sw_port);
223
224	$hosts = compress_hostlist(@hosts);
225	@hosts = split ",", $hosts;
226	print
227"$switch_guid $target_port ($desc)  <<==  $rem_sw_guid $rem_sw_port ($rem_sw_desc)\n";
228	print "@hosts\n";
229}
230main
231
232