3 # Copyright (c) 2006 The Regents of the University of California.
4 # Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
6 # Produced at Lawrence Livermore National Laboratory.
7 # Written by Ira Weiny <weiny2@llnl.gov>.
9 # This software is available to you under a choice of one of two
10 # licenses. You may choose to be licensed under the terms of the GNU
11 # General Public License (GPL) Version 2, available from the file
12 # COPYING in the main directory of this source tree, or the
13 # OpenIB.org BSD license below:
15 # Redistribution and use in source and binary forms, with or
16 # without modification, are permitted provided that the following
19 # - Redistributions of source code must retain the above
20 # copyright notice, this list of conditions and the following
23 # - Redistributions in binary form must reproduce the above
24 # copyright notice, this list of conditions and the following
25 # disclaimer in the documentation and/or other materials
26 # provided with the distribution.
28 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
47 "Usage: $prog [-Rhclp -S <guid> -D <direct route> -C <ca_name> -P <ca_port>]\n";
49 " Report link speed and connection for each port of each switch which is active\n";
50 print " -h This help message\n";
52 " -R Recalculate ibnetdiscover information (Default is to reuse ibnetdiscover output)\n";
54 " -D <direct route> output only the switch specified by direct route path\n";
55 print " -S <guid> output only the switch specified by <guid> (hex format)\n";
56 print " -d print only down links\n";
58 " -l (line mode) print all information for each link on each line\n";
60 " -p print additional switch settings (PktLifeTime,HoqLife,VLStallCount)\n";
61 print " -c print port capabilities (enabled/supported values)\n";
62 print " -C <ca_name> use selected Channel Adaptor name for queries\n";
63 print " -P <ca_port> use selected channel adaptor port for queries\n";
64 print " -g print port guids instead of node guids\n";
68 my $argv0 = `basename $0`;
69 my $regenerate_map = undef;
70 my $single_switch = undef;
71 my $direct_route = undef;
72 my $line_mode = undef;
73 my $print_add_switch = undef;
74 my $print_extended_cap = undef;
75 my $only_down_links = undef;
78 my $print_port_guids = undef;
79 my $switch_found = "no";
82 if (!getopts("hcpldRS:D:C:P:g")) { usage_and_exit $argv0; }
83 if (defined $Getopt::Std::opt_h) { usage_and_exit $argv0; }
84 if (defined $Getopt::Std::opt_D) { $direct_route = $Getopt::Std::opt_D; }
85 if (defined $Getopt::Std::opt_R) { $regenerate_map = $Getopt::Std::opt_R; }
86 if (defined $Getopt::Std::opt_S) {
87 $single_switch = format_guid($Getopt::Std::opt_S);
89 if (defined $Getopt::Std::opt_d) { $only_down_links = $Getopt::Std::opt_d; }
90 if (defined $Getopt::Std::opt_l) { $line_mode = $Getopt::Std::opt_l; }
91 if (defined $Getopt::Std::opt_p) { $print_add_switch = $Getopt::Std::opt_p; }
92 if (defined $Getopt::Std::opt_c) { $print_extended_cap = $Getopt::Std::opt_c; }
93 if (defined $Getopt::Std::opt_C) { $ca_name = $Getopt::Std::opt_C; }
94 if (defined $Getopt::Std::opt_P) { $ca_port = $Getopt::Std::opt_P; }
95 if (defined $Getopt::Std::opt_g) { $print_port_guids = $Getopt::Std::opt_g; }
97 my $extra_smpquery_params = get_ca_name_port_param_string($ca_name, $ca_port);
101 get_link_ends($regenerate_map, $ca_name, $ca_port);
102 if (defined($direct_route)) {
103 # convert DR to guid, then use original single_switch option
104 $single_switch = convert_dr_to_guid($direct_route);
105 if (!defined($single_switch) || !is_switch($single_switch)) {
106 printf("The direct route (%s) does not map to a switch.\n",
111 foreach my $switch (sort (keys(%IBswcountlimits::link_ends))) {
112 if ($single_switch && $switch ne $single_switch) {
115 $switch_found = "yes";
117 my $switch_prompt = "no";
118 my $num_ports = get_num_ports($switch, $ca_name, $ca_port);
119 if ($num_ports == 0) {
120 printf("ERROR: switch $switch has 0 ports???\n");
122 my @output_lines = undef;
123 my $pkt_lifetime = "";
124 my $pkt_life_prompt = "";
125 my $port_timeouts = "";
126 my $print_switch = "yes";
127 if ($only_down_links) { $print_switch = "no"; }
128 if ($print_add_switch) {
129 my $data = `smpquery $extra_smpquery_params -G switchinfo $switch`;
131 printf("ERROR: failed to get switchinfo for $switch\n");
133 my @lines = split("\n", $data);
134 foreach my $line (@lines) {
135 if ($line =~ /^LifeTime:\.+(.*)/) { $pkt_lifetime = $1; }
137 $pkt_life_prompt = sprintf(" (LT: %2s)", $pkt_lifetime);
139 foreach my $port (1 .. $num_ports) {
140 my $hr = $IBswcountlimits::link_ends{$switch}{$port};
141 if ($switch_prompt eq "no" && !$line_mode) {
142 my $switch_name = "";
143 my $tmp_port = $port;
144 while ($switch_name eq "" && $tmp_port <= $num_ports) {
145 # the first port is down find switch name with up port
146 my $hr = $IBswcountlimits::link_ends{$switch}{$tmp_port};
147 $switch_name = $hr->{loc_desc};
150 if ($switch_name eq "") {
152 "WARNING: Switch Name not found for $switch\n");
157 "Switch %18s %s%s:\n",
158 $switch, $switch_name, $pkt_life_prompt
161 $switch_prompt = "yes";
164 `smpquery $extra_smpquery_params -G portinfo $switch $port`;
167 "ERROR: failed to get portinfo for $switch port $port\n");
169 my @lines = split("\n", $data);
172 my $speed_enable = "";
175 my $width_enable = "";
179 my $phy_link_state = "";
181 foreach my $line (@lines) {
182 if ($line =~ /^LinkSpeedActive:\.+(.*)/) { $speed = $1; }
183 if ($line =~ /^LinkSpeedEnabled:\.+(.*)/) {
186 if ($line =~ /^LinkSpeedSupported:\.+(.*)/) { $speed_sup = $1; }
187 if ($line =~ /^LinkWidthActive:\.+(.*)/) { $width = $1; }
188 if ($line =~ /^LinkWidthEnabled:\.+(.*)/) {
191 if ($line =~ /^LinkWidthSupported:\.+(.*)/) { $width_sup = $1; }
192 if ($line =~ /^LinkState:\.+(.*)/) { $state = $1; }
193 if ($line =~ /^HoqLife:\.+(.*)/) { $hoq_life = $1; }
194 if ($line =~ /^VLStallCount:\.+(.*)/) { $vl_stall = $1; }
195 if ($line =~ /^PhysLinkState:\.+(.*)/) { $phy_link_state = $1; }
197 my $rem_port = $hr->{rem_port};
198 my $rem_lid = $hr->{rem_lid};
199 my $rem_speed_sup = "";
200 my $rem_speed_enable = "";
201 my $rem_width_sup = "";
202 my $rem_width_enable = "";
203 if ($rem_lid ne "" && $rem_port ne "") {
205 `smpquery $extra_smpquery_params portinfo $rem_lid $rem_port`;
208 "ERROR: failed to get portinfo for $switch port $port\n"
211 my @lines = split("\n", $data);
212 foreach my $line (@lines) {
213 if ($line =~ /^LinkSpeedEnabled:\.+(.*)/) {
214 $rem_speed_enable = $1;
216 if ($line =~ /^LinkSpeedSupported:\.+(.*)/) {
219 if ($line =~ /^LinkWidthEnabled:\.+(.*)/) {
220 $rem_width_enable = $1;
222 if ($line =~ /^LinkWidthSupported:\.+(.*)/) {
227 my $capabilities = "";
228 if ($print_extended_cap) {
229 $capabilities = sprintf("(%3s %s %6s / %8s [%s/%s][%s/%s])",
230 $width, $speed, $state, $phy_link_state, $width_enable,
231 $width_sup, $speed_enable, $speed_sup);
233 $capabilities = sprintf("(%3s %s %6s / %8s)",
234 $width, $speed, $state, $phy_link_state);
236 if ($print_add_switch) {
238 sprintf(" (HOQ:%s VL_Stall:%s)", $hoq_life, $vl_stall);
240 if (!$only_down_links || ($only_down_links && $state eq "Down")) {
243 if ($rem_width_enable ne "" && $rem_width_sup ne "") {
244 if ( $width_enable =~ /12X/
245 && $rem_width_enable =~ /12X/
248 $width_msg = "Could be 12X";
250 if ( $width_enable =~ /8X/
251 && $rem_width_enable =~ /8X/
254 $width_msg = "Could be 8X";
256 if ( $width_enable =~ /4X/
257 && $rem_width_enable =~ /4X/
260 $width_msg = "Could be 4X";
265 if ($rem_speed_enable ne "" && $rem_speed_sup ne "") {
266 if ( $speed_enable =~ /10\.0/
267 && $rem_speed_enable =~ /10\.0/
268 && $speed !~ /10\.0/)
270 $speed_msg = "Could be 10.0 Gbps";
272 if ( $speed_enable =~ /5\.0/
273 && $rem_speed_enable =~ /5\.0/
276 $speed_msg = "Could be 5.0 Gbps";
282 my $line_begin = sprintf("%18s \"%30s\"%s",
283 $switch, $hr->{loc_desc}, $pkt_life_prompt);
284 my $ext_guid = sprintf("%18s", $hr->{rem_guid});
285 if ($print_port_guids && $hr->{rem_port_guid} ne "") {
286 $ext_guid = sprintf("0x%016s", $hr->{rem_port_guid});
291 "%s %6s %4s[%2s] ==%s%s==> %18s %6s %4s[%2s] \"%s\" ( %s %s)\n",
292 $line_begin, $hr->{loc_sw_lid},
293 $port, $hr->{loc_ext_port},
294 $capabilities, $port_timeouts,
295 $ext_guid, $hr->{rem_lid},
296 $hr->{rem_port}, $hr->{rem_ext_port},
297 $hr->{rem_desc}, $width_msg,
305 " %6s %4s[%2s] ==%s%s==> %6s %4s[%2s] \"%s\" ( %s %s)\n",
306 $hr->{loc_sw_lid}, $port,
307 $hr->{loc_ext_port}, $capabilities,
308 $port_timeouts, $hr->{rem_lid},
309 $hr->{rem_port}, $hr->{rem_ext_port},
310 $hr->{rem_desc}, $width_msg,
315 $print_switch = "yes";
318 if ($print_switch eq "yes") {
319 foreach my $line (@output_lines) { print $line; }
322 if ($single_switch && $switch_found ne "yes") {
323 printf("Switch \"%s\" not found.\n", $single_switch);