1#!/usr/bin/perl 2# 3# Copyright (c) 2006 The Regents of the University of California. 4# Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved. 5# 6# Produced at Lawrence Livermore National Laboratory. 7# Written by Ira Weiny <weiny2@llnl.gov>. 8# 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: 14# 15# Redistribution and use in source and binary forms, with or 16# without modification, are permitted provided that the following 17# conditions are met: 18# 19# - Redistributions of source code must retain the above 20# copyright notice, this list of conditions and the following 21# disclaimer. 22# 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. 27# 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 35# SOFTWARE. 36# 37 38use strict; 39 40use Getopt::Std; 41use IBswcountlimits; 42 43sub usage_and_exit 44{ 45 my $prog = $_[0]; 46 print 47"Usage: $prog [-Rhclp -S <guid> -D <direct route> -C <ca_name> -P <ca_port>]\n"; 48 print 49" Report link speed and connection for each port of each switch which is active\n"; 50 print " -h This help message\n"; 51 print 52" -R Recalculate ibnetdiscover information (Default is to reuse ibnetdiscover output)\n"; 53 print 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"; 57 print 58 " -l (line mode) print all information for each link on each line\n"; 59 print 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"; 65 exit 2; 66} 67 68my $argv0 = `basename $0`; 69my $regenerate_map = undef; 70my $single_switch = undef; 71my $direct_route = undef; 72my $line_mode = undef; 73my $print_add_switch = undef; 74my $print_extended_cap = undef; 75my $only_down_links = undef; 76my $ca_name = ""; 77my $ca_port = ""; 78my $print_port_guids = undef; 79my $switch_found = "no"; 80chomp $argv0; 81 82if (!getopts("hcpldRS:D:C:P:g")) { usage_and_exit $argv0; } 83if (defined $Getopt::Std::opt_h) { usage_and_exit $argv0; } 84if (defined $Getopt::Std::opt_D) { $direct_route = $Getopt::Std::opt_D; } 85if (defined $Getopt::Std::opt_R) { $regenerate_map = $Getopt::Std::opt_R; } 86if (defined $Getopt::Std::opt_S) { 87 $single_switch = format_guid($Getopt::Std::opt_S); 88} 89if (defined $Getopt::Std::opt_d) { $only_down_links = $Getopt::Std::opt_d; } 90if (defined $Getopt::Std::opt_l) { $line_mode = $Getopt::Std::opt_l; } 91if (defined $Getopt::Std::opt_p) { $print_add_switch = $Getopt::Std::opt_p; } 92if (defined $Getopt::Std::opt_c) { $print_extended_cap = $Getopt::Std::opt_c; } 93if (defined $Getopt::Std::opt_C) { $ca_name = $Getopt::Std::opt_C; } 94if (defined $Getopt::Std::opt_P) { $ca_port = $Getopt::Std::opt_P; } 95if (defined $Getopt::Std::opt_g) { $print_port_guids = $Getopt::Std::opt_g; } 96 97my $extra_smpquery_params = get_ca_name_port_param_string($ca_name, $ca_port); 98 99sub main 100{ 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", 107 $direct_route); 108 return; 109 } 110 } 111 foreach my $switch (sort (keys(%IBswcountlimits::link_ends))) { 112 if ($single_switch && $switch ne $single_switch) { 113 next; 114 } else { 115 $switch_found = "yes"; 116 } 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"); 121 } 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`; 130 if ($data eq "") { 131 printf("ERROR: failed to get switchinfo for $switch\n"); 132 } 133 my @lines = split("\n", $data); 134 foreach my $line (@lines) { 135 if ($line =~ /^LifeTime:\.+(.*)/) { $pkt_lifetime = $1; } 136 } 137 $pkt_life_prompt = sprintf(" (LT: %2s)", $pkt_lifetime); 138 } 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}; 148 $tmp_port++; 149 } 150 if ($switch_name eq "") { 151 printf( 152 "WARNING: Switch Name not found for $switch\n"); 153 } 154 push( 155 @output_lines, 156 sprintf( 157 "Switch %18s %s%s:\n", 158 $switch, $switch_name, $pkt_life_prompt 159 ) 160 ); 161 $switch_prompt = "yes"; 162 } 163 my $data = 164 `smpquery $extra_smpquery_params -G portinfo $switch $port`; 165 if ($data eq "") { 166 printf( 167 "ERROR: failed to get portinfo for $switch port $port\n"); 168 } 169 my @lines = split("\n", $data); 170 my $speed = ""; 171 my $speed_sup = ""; 172 my $speed_enable = ""; 173 my $width = ""; 174 my $width_sup = ""; 175 my $width_enable = ""; 176 my $state = ""; 177 my $hoq_life = ""; 178 my $vl_stall = ""; 179 my $phy_link_state = ""; 180 181 foreach my $line (@lines) { 182 if ($line =~ /^LinkSpeedActive:\.+(.*)/) { $speed = $1; } 183 if ($line =~ /^LinkSpeedEnabled:\.+(.*)/) { 184 $speed_enable = $1; 185 } 186 if ($line =~ /^LinkSpeedSupported:\.+(.*)/) { $speed_sup = $1; } 187 if ($line =~ /^LinkWidthActive:\.+(.*)/) { $width = $1; } 188 if ($line =~ /^LinkWidthEnabled:\.+(.*)/) { 189 $width_enable = $1; 190 } 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; } 196 } 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 "") { 204 $data = 205 `smpquery $extra_smpquery_params portinfo $rem_lid $rem_port`; 206 if ($data eq "") { 207 printf( 208 "ERROR: failed to get portinfo for $switch port $port\n" 209 ); 210 } 211 my @lines = split("\n", $data); 212 foreach my $line (@lines) { 213 if ($line =~ /^LinkSpeedEnabled:\.+(.*)/) { 214 $rem_speed_enable = $1; 215 } 216 if ($line =~ /^LinkSpeedSupported:\.+(.*)/) { 217 $rem_speed_sup = $1; 218 } 219 if ($line =~ /^LinkWidthEnabled:\.+(.*)/) { 220 $rem_width_enable = $1; 221 } 222 if ($line =~ /^LinkWidthSupported:\.+(.*)/) { 223 $rem_width_sup = $1; 224 } 225 } 226 } 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); 232 } else { 233 $capabilities = sprintf("(%3s %s %6s / %8s)", 234 $width, $speed, $state, $phy_link_state); 235 } 236 if ($print_add_switch) { 237 $port_timeouts = 238 sprintf(" (HOQ:%s VL_Stall:%s)", $hoq_life, $vl_stall); 239 } 240 if (!$only_down_links || ($only_down_links && $state eq "Down")) { 241 my $width_msg = ""; 242 my $speed_msg = ""; 243 if ($rem_width_enable ne "" && $rem_width_sup ne "") { 244 if ( $width_enable =~ /12X/ 245 && $rem_width_enable =~ /12X/ 246 && $width !~ /12X/) 247 { 248 $width_msg = "Could be 12X"; 249 } else { 250 if ( $width_enable =~ /8X/ 251 && $rem_width_enable =~ /8X/ 252 && $width !~ /8X/) 253 { 254 $width_msg = "Could be 8X"; 255 } else { 256 if ( $width_enable =~ /4X/ 257 && $rem_width_enable =~ /4X/ 258 && $width !~ /4X/) 259 { 260 $width_msg = "Could be 4X"; 261 } 262 } 263 } 264 } 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/) 269 { 270 $speed_msg = "Could be 10.0 Gbps"; 271 } else { 272 if ( $speed_enable =~ /5\.0/ 273 && $rem_speed_enable =~ /5\.0/ 274 && $speed !~ /5\.0/) 275 { 276 $speed_msg = "Could be 5.0 Gbps"; 277 } 278 } 279 } 280 281 if ($line_mode) { 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}); 287 } 288 push( 289 @output_lines, 290 sprintf( 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, 298 $speed_msg 299 ) 300 ); 301 } else { 302 push( 303 @output_lines, 304 sprintf( 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, 311 $speed_msg 312 ) 313 ); 314 } 315 $print_switch = "yes"; 316 } 317 } 318 if ($print_switch eq "yes") { 319 foreach my $line (@output_lines) { print $line; } 320 } 321 } 322 if ($single_switch && $switch_found ne "yes") { 323 printf("Switch \"%s\" not found.\n", $single_switch); 324 } 325} 326main; 327 328