3 # Copyright (C) 2001-2003 The Regents of the University of California.
4 # Copyright (c) 2006 The Regents of the University of California.
5 # Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
7 # Produced at Lawrence Livermore National Laboratory.
8 # Written by Ira Weiny <weiny2@llnl.gov>
9 # Jim Garlick <garlick@llnl.gov>
10 # Albert Chu <chu11@llnl.gov>
12 # This software is available to you under a choice of one of two
13 # licenses. You may choose to be licensed under the terms of the GNU
14 # General Public License (GPL) Version 2, available from the file
15 # COPYING in the main directory of this source tree, or the
16 # OpenIB.org BSD license below:
18 # Redistribution and use in source and binary forms, with or
19 # without modification, are permitted provided that the following
22 # - Redistributions of source code must retain the above
23 # copyright notice, this list of conditions and the following
26 # - Redistributions in binary form must reproduce the above
27 # copyright notice, this list of conditions and the following
28 # disclaimer in the documentation and/or other materials
29 # provided with the distribution.
31 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
35 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
36 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
37 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
46 my $regenerate_cache = 0;
49 my $switch_lid = undef;
50 my $switch_guid = undef;
51 my $switch_name = undef;
52 my %switch_port_count = ();
53 my @switch_maybe_directly_connected_hosts = ();
61 my $lids_per_port_calculated;
63 my $iblinkinfo_regenerate = 0;
69 my $prog = `basename $0`;
72 print "Usage: $prog [-R -v]\n";
73 print " -R recalculate all cached information\n";
74 print " -v verbose output\n";
80 my $iblinkinfo_output = $_[0];
89 # Add a space if necessary
90 if ($decport >= 1 && $decport <= 9) {
91 $decport = " $decport";
94 @lines = split("\n", $iblinkinfo_output);
95 foreach $line (@lines) {
96 if ($line =~ /$decport\[..\] ==/) {
97 if ($line =~ /Down/) {
105 sub is_directly_connected
107 my $iblinkinfo_output = $_[0];
116 if (($switch_port_count{$port} != $lids_per_port)
117 || !(@switch_maybe_directly_connected_hosts))
125 # Add a space if necessary
126 if ($decport >= 1 && $decport <= 9) {
127 $decport = " $decport";
130 @lines = split("\n", $iblinkinfo_output);
131 foreach $line (@lines) {
132 if ($line =~ /$decport\[..\] ==/) {
137 if ($str =~ "Active") {
139 /[\d]+[\s]+[\d]+\[.+\] \=\=.+\=\=>[\s]+[\d]+[\s]+[\d]+\[.+\] \"(.+)\".+/;
140 for $host_tmp (@switch_maybe_directly_connected_hosts) {
141 if ($1 == $host_tmp) {
151 sub output_switch_port_usage
153 my $min_usage = 999999;
156 "001", "002", "003", "004", "005", "006", "007", "008",
157 "009", "010", "011", "012", "013", "014", "015", "016",
158 "017", "018", "019", "020", "021", "022", "023", "024"
160 my @output_ports = ();
162 my $iblinkinfo_output;
165 # Run command once to reduce number of calls to iblinkinfo.pl
166 if ($regenerate_cache && !$iblinkinfo_regenerate) {
167 $iblinkinfo_output = `iblinkinfo.pl -R -S $switch_guid`;
168 $iblinkinfo_regenerate++;
171 $iblinkinfo_output = `iblinkinfo.pl -S $switch_guid`;
175 if (!defined($switch_port_count{$port})) {
176 $switch_port_count{$port} = 0;
179 if ($switch_port_count{$port} == 0) {
180 # If port is down, don't use it in this calculation
181 $ret = is_port_up($iblinkinfo_output, $port);
187 # If port is directly connected to a node, don't use
188 # it in this calculation.
189 if (is_directly_connected($iblinkinfo_output, $port) == 1) {
193 # Save off ports that should be output later
194 push(@output_ports, $port);
196 if ($switch_port_count{$port} < $min_usage) {
197 $min_usage = $switch_port_count{$port};
199 if ($switch_port_count{$port} > $max_usage) {
200 $max_usage = $switch_port_count{$port};
204 if ($verbose || ($max_usage > ($min_usage + 1))) {
205 if ($max_usage > ($min_usage + 1)) {
206 print "Unbalanced Switch Port Usage: ";
207 print "$switch_name, $switch_guid, $switch_lid\n";
210 "Switch Port Usage: $switch_name, $switch_guid, $switch_lid\n";
212 for $port (@output_ports) {
213 print "Port $port: $switch_port_count{$port}\n";
218 sub process_host_ports
224 if (@host_ports == $lids_per_port) {
225 # Are all the host ports identical?
226 $test_port = $host_ports[0];
227 for $tmp (@host_ports) {
228 if ($tmp != $test_port) {
233 # If all host ports are identical, maybe its directly
234 # connected to a host.
236 push(@switch_maybe_directly_connected_hosts, $host);
241 if (!getopts("hRv")) {
245 if (defined($main::opt_h)) {
249 if (defined($main::opt_R)) {
250 $regenerate_cache = 1;
253 if (defined($main::opt_v)) {
257 $cache_file = "$IBswcountlimits::cache_dir/dump_lfts.out";
258 if ($regenerate_cache || !(-f $cache_file)) {
259 `dump_lfts.sh > $cache_file`;
261 die "Execution of dump_lfts.sh failed with errors\n";
265 if (!open(FH, "< $cache_file")) {
266 print STDERR ("Couldn't open cache file: $cache_file: $!\n");
271 foreach $lft_line (@lft_lines) {
273 if ($lft_line =~ /Unicast/) {
274 $lft_line =~ /Unicast lids .+ of switch Lid (.+) guid (.+) \((.+)\)/;
276 process_host_ports();
278 if (defined($switch_name)) {
279 output_switch_port_usage();
284 @switch_maybe_directly_connected_hosts = ();
285 %switch_port_count = ();
288 $lids_per_port_calculated = 0;
289 } elsif ($lft_line =~ /Channel/ || $lft_line =~ /Router/) {
290 $lft_line =~ /.+ (.+) : \(.+ portguid .+: '(.+)'\)/;
292 $switch_port_count{$1}++;
294 process_host_ports();
298 if ($lids_per_port == 0) {
301 $lids_per_port_calculated++;
303 } elsif ($lft_line =~ /path/) {
304 $lft_line =~ /.+ (.+) : \(path #. out of .: portguid .+\)/;
305 $switch_port_count{$1}++;
306 if ($lids_per_port_calculated == 0) {
309 push(@host_ports, $1);
311 if ($lids_per_port) {
312 $lids_per_port_calculated++;
319 process_host_ports();
321 output_switch_port_usage();