]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/infiniband-diags/scripts/check_lft_balance.pl
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / infiniband-diags / scripts / check_lft_balance.pl
1 #!/usr/bin/perl
2 #
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.
6 #
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>
11 #
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:
17 #
18 #     Redistribution and use in source and binary forms, with or
19 #     without modification, are permitted provided that the following
20 #     conditions are met:
21 #
22 #      - Redistributions of source code must retain the above
23 #        copyright notice, this list of conditions and the following
24 #        disclaimer.
25 #
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.
30 #
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
38 # SOFTWARE.
39 #
40
41 use strict;
42
43 use Getopt::Std;
44 use IBswcountlimits;
45
46 my $regenerate_cache = 0;
47 my $verbose          = 0;
48
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 = ();
54 my $host                                  = undef;
55 my @host_ports                            = ();
56
57 my @lft_lines = ();
58 my $lft_line;
59
60 my $lids_per_port;
61 my $lids_per_port_calculated;
62
63 my $iblinkinfo_regenerate = 0;
64
65 my $cache_file;
66
67 sub usage
68 {
69         my $prog = `basename $0`;
70
71         chomp($prog);
72         print "Usage: $prog [-R -v]\n";
73         print "  -R recalculate all cached information\n";
74         print "  -v verbose output\n";
75         exit 2;
76 }
77
78 sub is_port_up
79 {
80         my $iblinkinfo_output = $_[0];
81         my $port              = $_[1];
82         my $decport;
83         my @lines;
84         my $line;
85
86         $port =~ /0+(.+)/;
87         $decport = $1;
88
89         # Add a space if necessary
90         if ($decport >= 1 && $decport <= 9) {
91                 $decport = " $decport";
92         }
93
94         @lines = split("\n", $iblinkinfo_output);
95         foreach $line (@lines) {
96                 if ($line =~ /$decport\[..\]  ==/) {
97                         if ($line =~ /Down/) {
98                                 return 0;
99                         }
100                 }
101         }
102         return 1;
103 }
104
105 sub is_directly_connected
106 {
107         my $iblinkinfo_output = $_[0];
108         my $port              = $_[1];
109         my $decport;
110         my $str;
111         my $rv = 0;
112         my $host_tmp;
113         my @lines;
114         my $line;
115
116         if (($switch_port_count{$port} != $lids_per_port)
117                 || !(@switch_maybe_directly_connected_hosts))
118         {
119                 return $rv;
120         }
121
122         $port =~ /0+(.+)/;
123         $decport = $1;
124
125         # Add a space if necessary
126         if ($decport >= 1 && $decport <= 9) {
127                 $decport = " $decport";
128         }
129
130         @lines = split("\n", $iblinkinfo_output);
131         foreach $line (@lines) {
132                 if ($line =~ /$decport\[..\]  ==/) {
133                         $str = $line;
134                 }
135         }
136
137         if ($str =~ "Active") {
138                 $str =~
139 /[\d]+[\s]+[\d]+\[.+\]  \=\=.+\=\=>[\s]+[\d]+[\s]+[\d]+\[.+\] \"(.+)\".+/;
140                 for $host_tmp (@switch_maybe_directly_connected_hosts) {
141                         if ($1 == $host_tmp) {
142                                 $rv = 1;
143                                 last;
144                         }
145                 }
146         }
147
148         return $rv;
149 }
150
151 sub output_switch_port_usage
152 {
153         my $min_usage = 999999;
154         my $max_usage = 0;
155         my @ports     = (
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"
159         );
160         my @output_ports = ();
161         my $port;
162         my $iblinkinfo_output;
163         my $ret;
164
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++;
169         }
170         else {
171             $iblinkinfo_output = `iblinkinfo.pl -S $switch_guid`;
172         }
173
174         for $port (@ports) {
175                 if (!defined($switch_port_count{$port})) {
176                         $switch_port_count{$port} = 0;
177                 }
178
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);
182                         if ($ret == 0) {
183                                 next;
184                         }
185                 }
186
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) {
190                         next;
191                 }
192
193                 # Save off ports that should be output later
194                 push(@output_ports, $port);
195
196                 if ($switch_port_count{$port} < $min_usage) {
197                         $min_usage = $switch_port_count{$port};
198                 }
199                 if ($switch_port_count{$port} > $max_usage) {
200                         $max_usage = $switch_port_count{$port};
201                 }
202         }
203
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";
208                 } else {
209                         print
210                           "Switch Port Usage: $switch_name, $switch_guid, $switch_lid\n";
211                 }
212                 for $port (@output_ports) {
213                         print "Port $port: $switch_port_count{$port}\n";
214                 }
215         }
216 }
217
218 sub process_host_ports
219 {
220         my $test_port;
221         my $tmp;
222         my $flag = 0;
223
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) {
229                                 $flag = 1;
230                                 last;
231                         }
232                 }
233                 # If all host ports are identical, maybe its directly
234                 # connected to a host.
235                 if ($flag == 0) {
236                         push(@switch_maybe_directly_connected_hosts, $host);
237                 }
238         }
239 }
240
241 if (!getopts("hRv")) {
242         usage();
243 }
244
245 if (defined($main::opt_h)) {
246         usage();
247 }
248
249 if (defined($main::opt_R)) {
250         $regenerate_cache = 1;
251 }
252
253 if (defined($main::opt_v)) {
254         $verbose = 1;
255 }
256
257 $cache_file = "$IBswcountlimits::cache_dir/dump_lfts.out";
258 if ($regenerate_cache || !(-f $cache_file)) {
259         `dump_lfts.sh > $cache_file`;
260         if ($? != 0) {
261                 die "Execution of dump_lfts.sh failed with errors\n";
262         }
263 }
264
265 if (!open(FH, "< $cache_file")) {
266         print STDERR ("Couldn't open cache file: $cache_file: $!\n");
267 }
268
269 @lft_lines = <FH>;
270
271 foreach $lft_line (@lft_lines) {
272         chomp($lft_line);
273         if ($lft_line =~ /Unicast/) {
274                 $lft_line =~ /Unicast lids .+ of switch Lid (.+) guid (.+) \((.+)\)/;
275                 if (@host_ports) {
276                         process_host_ports();
277                 }
278                 if (defined($switch_name)) {
279                         output_switch_port_usage();
280                 }
281                 $switch_lid                            = $1;
282                 $switch_guid                           = $2;
283                 $switch_name                           = $3;
284                 @switch_maybe_directly_connected_hosts = ();
285                 %switch_port_count                     = ();
286                 @host_ports                            = ();
287                 $lids_per_port                         = 0;
288                 $lids_per_port_calculated              = 0;
289         } elsif ($lft_line =~ /Channel/ || $lft_line =~ /Router/) {
290                 $lft_line =~ /.+ (.+) : \(.+ portguid .+: '(.+)'\)/;
291                 $host = $2;
292                 $switch_port_count{$1}++;
293                 if (@host_ports) {
294                         process_host_ports();
295                 }
296                 @host_ports = ($1);
297
298                 if ($lids_per_port == 0) {
299                         $lids_per_port++;
300                 } else {
301                         $lids_per_port_calculated++;
302                 }
303         } elsif ($lft_line =~ /path/) {
304                 $lft_line =~ /.+ (.+) : \(path #. out of .: portguid .+\)/;
305                 $switch_port_count{$1}++;
306                 if ($lids_per_port_calculated == 0) {
307                         $lids_per_port++;
308                 }
309                 push(@host_ports, $1);
310         } else {
311                 if ($lids_per_port) {
312                         $lids_per_port_calculated++;
313                 }
314                 next;
315         }
316 }
317
318 if (@host_ports) {
319         process_host_ports();
320 }
321 output_switch_port_usage();