1219820Sjeff#!/usr/bin/perl 2219820Sjeff# 3219820Sjeff# Copyright (c) 2006 The Regents of the University of California. 4219820Sjeff# Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved. 5219820Sjeff# 6219820Sjeff# Produced at Lawrence Livermore National Laboratory. 7219820Sjeff# Written by Ira Weiny <weiny2@llnl.gov>. 8219820Sjeff# 9219820Sjeff# This software is available to you under a choice of one of two 10219820Sjeff# licenses. You may choose to be licensed under the terms of the GNU 11219820Sjeff# General Public License (GPL) Version 2, available from the file 12219820Sjeff# COPYING in the main directory of this source tree, or the 13219820Sjeff# OpenIB.org BSD license below: 14219820Sjeff# 15219820Sjeff# Redistribution and use in source and binary forms, with or 16219820Sjeff# without modification, are permitted provided that the following 17219820Sjeff# conditions are met: 18219820Sjeff# 19219820Sjeff# - Redistributions of source code must retain the above 20219820Sjeff# copyright notice, this list of conditions and the following 21219820Sjeff# disclaimer. 22219820Sjeff# 23219820Sjeff# - Redistributions in binary form must reproduce the above 24219820Sjeff# copyright notice, this list of conditions and the following 25219820Sjeff# disclaimer in the documentation and/or other materials 26219820Sjeff# provided with the distribution. 27219820Sjeff# 28219820Sjeff# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 29219820Sjeff# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 30219820Sjeff# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31219820Sjeff# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 32219820Sjeff# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 33219820Sjeff# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 34219820Sjeff# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35219820Sjeff# SOFTWARE. 36219820Sjeff# 37219820Sjeff 38219820Sjeffuse strict; 39219820Sjeff 40219820Sjeffuse Getopt::Std; 41219820Sjeffuse IBswcountlimits; 42219820Sjeff 43219820Sjeffsub usage_and_exit 44219820Sjeff{ 45219820Sjeff my $prog = $_[0]; 46219820Sjeff print 47219820Sjeff"Usage: $prog [-Rhclp -S <guid> -D <direct route> -C <ca_name> -P <ca_port>]\n"; 48219820Sjeff print 49219820Sjeff" Report link speed and connection for each port of each switch which is active\n"; 50219820Sjeff print " -h This help message\n"; 51219820Sjeff print 52219820Sjeff" -R Recalculate ibnetdiscover information (Default is to reuse ibnetdiscover output)\n"; 53219820Sjeff print 54219820Sjeff" -D <direct route> output only the switch specified by direct route path\n"; 55219820Sjeff print " -S <guid> output only the switch specified by <guid> (hex format)\n"; 56219820Sjeff print " -d print only down links\n"; 57219820Sjeff print 58219820Sjeff " -l (line mode) print all information for each link on each line\n"; 59219820Sjeff print 60219820Sjeff" -p print additional switch settings (PktLifeTime,HoqLife,VLStallCount)\n"; 61219820Sjeff print " -c print port capabilities (enabled/supported values)\n"; 62219820Sjeff print " -C <ca_name> use selected Channel Adaptor name for queries\n"; 63219820Sjeff print " -P <ca_port> use selected channel adaptor port for queries\n"; 64219820Sjeff print " -g print port guids instead of node guids\n"; 65219820Sjeff exit 2; 66219820Sjeff} 67219820Sjeff 68219820Sjeffmy $argv0 = `basename $0`; 69219820Sjeffmy $regenerate_map = undef; 70219820Sjeffmy $single_switch = undef; 71219820Sjeffmy $direct_route = undef; 72219820Sjeffmy $line_mode = undef; 73219820Sjeffmy $print_add_switch = undef; 74219820Sjeffmy $print_extended_cap = undef; 75219820Sjeffmy $only_down_links = undef; 76219820Sjeffmy $ca_name = ""; 77219820Sjeffmy $ca_port = ""; 78219820Sjeffmy $print_port_guids = undef; 79219820Sjeffmy $switch_found = "no"; 80219820Sjeffchomp $argv0; 81219820Sjeff 82219820Sjeffif (!getopts("hcpldRS:D:C:P:g")) { usage_and_exit $argv0; } 83219820Sjeffif (defined $Getopt::Std::opt_h) { usage_and_exit $argv0; } 84219820Sjeffif (defined $Getopt::Std::opt_D) { $direct_route = $Getopt::Std::opt_D; } 85219820Sjeffif (defined $Getopt::Std::opt_R) { $regenerate_map = $Getopt::Std::opt_R; } 86219820Sjeffif (defined $Getopt::Std::opt_S) { 87219820Sjeff $single_switch = format_guid($Getopt::Std::opt_S); 88219820Sjeff} 89219820Sjeffif (defined $Getopt::Std::opt_d) { $only_down_links = $Getopt::Std::opt_d; } 90219820Sjeffif (defined $Getopt::Std::opt_l) { $line_mode = $Getopt::Std::opt_l; } 91219820Sjeffif (defined $Getopt::Std::opt_p) { $print_add_switch = $Getopt::Std::opt_p; } 92219820Sjeffif (defined $Getopt::Std::opt_c) { $print_extended_cap = $Getopt::Std::opt_c; } 93219820Sjeffif (defined $Getopt::Std::opt_C) { $ca_name = $Getopt::Std::opt_C; } 94219820Sjeffif (defined $Getopt::Std::opt_P) { $ca_port = $Getopt::Std::opt_P; } 95219820Sjeffif (defined $Getopt::Std::opt_g) { $print_port_guids = $Getopt::Std::opt_g; } 96219820Sjeff 97219820Sjeffmy $extra_smpquery_params = get_ca_name_port_param_string($ca_name, $ca_port); 98219820Sjeff 99219820Sjeffsub main 100219820Sjeff{ 101219820Sjeff get_link_ends($regenerate_map, $ca_name, $ca_port); 102219820Sjeff if (defined($direct_route)) { 103219820Sjeff # convert DR to guid, then use original single_switch option 104219820Sjeff $single_switch = convert_dr_to_guid($direct_route); 105219820Sjeff if (!defined($single_switch) || !is_switch($single_switch)) { 106219820Sjeff printf("The direct route (%s) does not map to a switch.\n", 107219820Sjeff $direct_route); 108219820Sjeff return; 109219820Sjeff } 110219820Sjeff } 111219820Sjeff foreach my $switch (sort (keys(%IBswcountlimits::link_ends))) { 112219820Sjeff if ($single_switch && $switch ne $single_switch) { 113219820Sjeff next; 114219820Sjeff } else { 115219820Sjeff $switch_found = "yes"; 116219820Sjeff } 117219820Sjeff my $switch_prompt = "no"; 118219820Sjeff my $num_ports = get_num_ports($switch, $ca_name, $ca_port); 119219820Sjeff if ($num_ports == 0) { 120219820Sjeff printf("ERROR: switch $switch has 0 ports???\n"); 121219820Sjeff } 122219820Sjeff my @output_lines = undef; 123219820Sjeff my $pkt_lifetime = ""; 124219820Sjeff my $pkt_life_prompt = ""; 125219820Sjeff my $port_timeouts = ""; 126219820Sjeff my $print_switch = "yes"; 127219820Sjeff if ($only_down_links) { $print_switch = "no"; } 128219820Sjeff if ($print_add_switch) { 129219820Sjeff my $data = `smpquery $extra_smpquery_params -G switchinfo $switch`; 130219820Sjeff if ($data eq "") { 131219820Sjeff printf("ERROR: failed to get switchinfo for $switch\n"); 132219820Sjeff } 133219820Sjeff my @lines = split("\n", $data); 134219820Sjeff foreach my $line (@lines) { 135219820Sjeff if ($line =~ /^LifeTime:\.+(.*)/) { $pkt_lifetime = $1; } 136219820Sjeff } 137219820Sjeff $pkt_life_prompt = sprintf(" (LT: %2s)", $pkt_lifetime); 138219820Sjeff } 139219820Sjeff foreach my $port (1 .. $num_ports) { 140219820Sjeff my $hr = $IBswcountlimits::link_ends{$switch}{$port}; 141219820Sjeff if ($switch_prompt eq "no" && !$line_mode) { 142219820Sjeff my $switch_name = ""; 143219820Sjeff my $tmp_port = $port; 144219820Sjeff while ($switch_name eq "" && $tmp_port <= $num_ports) { 145219820Sjeff # the first port is down find switch name with up port 146219820Sjeff my $hr = $IBswcountlimits::link_ends{$switch}{$tmp_port}; 147219820Sjeff $switch_name = $hr->{loc_desc}; 148219820Sjeff $tmp_port++; 149219820Sjeff } 150219820Sjeff if ($switch_name eq "") { 151219820Sjeff printf( 152219820Sjeff "WARNING: Switch Name not found for $switch\n"); 153219820Sjeff } 154219820Sjeff push( 155219820Sjeff @output_lines, 156219820Sjeff sprintf( 157219820Sjeff "Switch %18s %s%s:\n", 158219820Sjeff $switch, $switch_name, $pkt_life_prompt 159219820Sjeff ) 160219820Sjeff ); 161219820Sjeff $switch_prompt = "yes"; 162219820Sjeff } 163219820Sjeff my $data = 164219820Sjeff `smpquery $extra_smpquery_params -G portinfo $switch $port`; 165219820Sjeff if ($data eq "") { 166219820Sjeff printf( 167219820Sjeff "ERROR: failed to get portinfo for $switch port $port\n"); 168219820Sjeff } 169219820Sjeff my @lines = split("\n", $data); 170219820Sjeff my $speed = ""; 171219820Sjeff my $speed_sup = ""; 172219820Sjeff my $speed_enable = ""; 173219820Sjeff my $width = ""; 174219820Sjeff my $width_sup = ""; 175219820Sjeff my $width_enable = ""; 176219820Sjeff my $state = ""; 177219820Sjeff my $hoq_life = ""; 178219820Sjeff my $vl_stall = ""; 179219820Sjeff my $phy_link_state = ""; 180219820Sjeff 181219820Sjeff foreach my $line (@lines) { 182219820Sjeff if ($line =~ /^LinkSpeedActive:\.+(.*)/) { $speed = $1; } 183219820Sjeff if ($line =~ /^LinkSpeedEnabled:\.+(.*)/) { 184219820Sjeff $speed_enable = $1; 185219820Sjeff } 186219820Sjeff if ($line =~ /^LinkSpeedSupported:\.+(.*)/) { $speed_sup = $1; } 187219820Sjeff if ($line =~ /^LinkWidthActive:\.+(.*)/) { $width = $1; } 188219820Sjeff if ($line =~ /^LinkWidthEnabled:\.+(.*)/) { 189219820Sjeff $width_enable = $1; 190219820Sjeff } 191219820Sjeff if ($line =~ /^LinkWidthSupported:\.+(.*)/) { $width_sup = $1; } 192219820Sjeff if ($line =~ /^LinkState:\.+(.*)/) { $state = $1; } 193219820Sjeff if ($line =~ /^HoqLife:\.+(.*)/) { $hoq_life = $1; } 194219820Sjeff if ($line =~ /^VLStallCount:\.+(.*)/) { $vl_stall = $1; } 195219820Sjeff if ($line =~ /^PhysLinkState:\.+(.*)/) { $phy_link_state = $1; } 196219820Sjeff } 197219820Sjeff my $rem_port = $hr->{rem_port}; 198219820Sjeff my $rem_lid = $hr->{rem_lid}; 199219820Sjeff my $rem_speed_sup = ""; 200219820Sjeff my $rem_speed_enable = ""; 201219820Sjeff my $rem_width_sup = ""; 202219820Sjeff my $rem_width_enable = ""; 203219820Sjeff if ($rem_lid ne "" && $rem_port ne "") { 204219820Sjeff $data = 205219820Sjeff `smpquery $extra_smpquery_params portinfo $rem_lid $rem_port`; 206219820Sjeff if ($data eq "") { 207219820Sjeff printf( 208219820Sjeff "ERROR: failed to get portinfo for $switch port $port\n" 209219820Sjeff ); 210219820Sjeff } 211219820Sjeff my @lines = split("\n", $data); 212219820Sjeff foreach my $line (@lines) { 213219820Sjeff if ($line =~ /^LinkSpeedEnabled:\.+(.*)/) { 214219820Sjeff $rem_speed_enable = $1; 215219820Sjeff } 216219820Sjeff if ($line =~ /^LinkSpeedSupported:\.+(.*)/) { 217219820Sjeff $rem_speed_sup = $1; 218219820Sjeff } 219219820Sjeff if ($line =~ /^LinkWidthEnabled:\.+(.*)/) { 220219820Sjeff $rem_width_enable = $1; 221219820Sjeff } 222219820Sjeff if ($line =~ /^LinkWidthSupported:\.+(.*)/) { 223219820Sjeff $rem_width_sup = $1; 224219820Sjeff } 225219820Sjeff } 226219820Sjeff } 227219820Sjeff my $capabilities = ""; 228219820Sjeff if ($print_extended_cap) { 229219820Sjeff $capabilities = sprintf("(%3s %s %6s / %8s [%s/%s][%s/%s])", 230219820Sjeff $width, $speed, $state, $phy_link_state, $width_enable, 231219820Sjeff $width_sup, $speed_enable, $speed_sup); 232219820Sjeff } else { 233219820Sjeff $capabilities = sprintf("(%3s %s %6s / %8s)", 234219820Sjeff $width, $speed, $state, $phy_link_state); 235219820Sjeff } 236219820Sjeff if ($print_add_switch) { 237219820Sjeff $port_timeouts = 238219820Sjeff sprintf(" (HOQ:%s VL_Stall:%s)", $hoq_life, $vl_stall); 239219820Sjeff } 240219820Sjeff if (!$only_down_links || ($only_down_links && $state eq "Down")) { 241219820Sjeff my $width_msg = ""; 242219820Sjeff my $speed_msg = ""; 243219820Sjeff if ($rem_width_enable ne "" && $rem_width_sup ne "") { 244219820Sjeff if ( $width_enable =~ /12X/ 245219820Sjeff && $rem_width_enable =~ /12X/ 246219820Sjeff && $width !~ /12X/) 247219820Sjeff { 248219820Sjeff $width_msg = "Could be 12X"; 249219820Sjeff } else { 250219820Sjeff if ( $width_enable =~ /8X/ 251219820Sjeff && $rem_width_enable =~ /8X/ 252219820Sjeff && $width !~ /8X/) 253219820Sjeff { 254219820Sjeff $width_msg = "Could be 8X"; 255219820Sjeff } else { 256219820Sjeff if ( $width_enable =~ /4X/ 257219820Sjeff && $rem_width_enable =~ /4X/ 258219820Sjeff && $width !~ /4X/) 259219820Sjeff { 260219820Sjeff $width_msg = "Could be 4X"; 261219820Sjeff } 262219820Sjeff } 263219820Sjeff } 264219820Sjeff } 265219820Sjeff if ($rem_speed_enable ne "" && $rem_speed_sup ne "") { 266219820Sjeff if ( $speed_enable =~ /10\.0/ 267219820Sjeff && $rem_speed_enable =~ /10\.0/ 268219820Sjeff && $speed !~ /10\.0/) 269219820Sjeff { 270219820Sjeff $speed_msg = "Could be 10.0 Gbps"; 271219820Sjeff } else { 272219820Sjeff if ( $speed_enable =~ /5\.0/ 273219820Sjeff && $rem_speed_enable =~ /5\.0/ 274219820Sjeff && $speed !~ /5\.0/) 275219820Sjeff { 276219820Sjeff $speed_msg = "Could be 5.0 Gbps"; 277219820Sjeff } 278219820Sjeff } 279219820Sjeff } 280219820Sjeff 281219820Sjeff if ($line_mode) { 282219820Sjeff my $line_begin = sprintf("%18s \"%30s\"%s", 283219820Sjeff $switch, $hr->{loc_desc}, $pkt_life_prompt); 284219820Sjeff my $ext_guid = sprintf("%18s", $hr->{rem_guid}); 285219820Sjeff if ($print_port_guids && $hr->{rem_port_guid} ne "") { 286219820Sjeff $ext_guid = sprintf("0x%016s", $hr->{rem_port_guid}); 287219820Sjeff } 288219820Sjeff push( 289219820Sjeff @output_lines, 290219820Sjeff sprintf( 291219820Sjeff"%s %6s %4s[%2s] ==%s%s==> %18s %6s %4s[%2s] \"%s\" ( %s %s)\n", 292219820Sjeff $line_begin, $hr->{loc_sw_lid}, 293219820Sjeff $port, $hr->{loc_ext_port}, 294219820Sjeff $capabilities, $port_timeouts, 295219820Sjeff $ext_guid, $hr->{rem_lid}, 296219820Sjeff $hr->{rem_port}, $hr->{rem_ext_port}, 297219820Sjeff $hr->{rem_desc}, $width_msg, 298219820Sjeff $speed_msg 299219820Sjeff ) 300219820Sjeff ); 301219820Sjeff } else { 302219820Sjeff push( 303219820Sjeff @output_lines, 304219820Sjeff sprintf( 305219820Sjeff" %6s %4s[%2s] ==%s%s==> %6s %4s[%2s] \"%s\" ( %s %s)\n", 306219820Sjeff $hr->{loc_sw_lid}, $port, 307219820Sjeff $hr->{loc_ext_port}, $capabilities, 308219820Sjeff $port_timeouts, $hr->{rem_lid}, 309219820Sjeff $hr->{rem_port}, $hr->{rem_ext_port}, 310219820Sjeff $hr->{rem_desc}, $width_msg, 311219820Sjeff $speed_msg 312219820Sjeff ) 313219820Sjeff ); 314219820Sjeff } 315219820Sjeff $print_switch = "yes"; 316219820Sjeff } 317219820Sjeff } 318219820Sjeff if ($print_switch eq "yes") { 319219820Sjeff foreach my $line (@output_lines) { print $line; } 320219820Sjeff } 321219820Sjeff } 322219820Sjeff if ($single_switch && $switch_found ne "yes") { 323219820Sjeff printf("Switch \"%s\" not found.\n", $single_switch); 324219820Sjeff } 325219820Sjeff} 326219820Sjeffmain; 327219820Sjeff 328